siop.ss revision 1.20 1 ; $NetBSD: siop.ss,v 1.20 2005/11/18 23:10:32 bouyer Exp $
2
3 ;
4 ; Copyright (c) 2000 Manuel Bouyer.
5 ;
6 ; Redistribution and use in source and binary forms, with or without
7 ; modification, are permitted provided that the following conditions
8 ; are met:
9 ; 1. Redistributions of source code must retain the above copyright
10 ; notice, this list of conditions and the following disclaimer.
11 ; 2. Redistributions in binary form must reproduce the above copyright
12 ; notice, this list of conditions and the following disclaimer in the
13 ; documentation and/or other materials provided with the distribution.
14 ; 3. All advertising materials mentioning features or use of this software
15 ; must display the following acknowledgement:
16 ; This product includes software developed by Manuel Bouyer.
17 ; 4. The name of the author may not be used to endorse or promote products
18 ; derived from this software without specific prior written permission.
19 ;
20 ; THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21 ; IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22 ; OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 ; IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24 ; INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 ; NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 ; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 ; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 ; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 ; THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31 ARCH 720
32
33 ; offsets in siop_common_xfer
34 ABSOLUTE t_id = 40;
35 ABSOLUTE t_msg_in = 48;
36 ABSOLUTE t_ext_msg_in = 56;
37 ABSOLUTE t_ext_msg_data = 64;
38 ABSOLUTE t_msg_out = 72;
39 ABSOLUTE t_cmd = 80;
40 ABSOLUTE t_status = 88;
41 ABSOLUTE t_data = 96;
42
43 ;; interrupt codes
44 ; interrupts that need a valid DSA
45 ABSOLUTE int_done = 0xff00;
46 ABSOLUTE int_msgin = 0xff01;
47 ABSOLUTE int_extmsgin = 0xff02;
48 ABSOLUTE int_extmsgdata = 0xff03;
49 ABSOLUTE int_disc = 0xff04;
50 ABSOLUTE int_saveoffset = 0xff05;
51 ; interrupts that don't have a valid DSA
52 ABSOLUTE int_reseltarg = 0xff80;
53 ABSOLUTE int_resellun = 0xff81;
54 ABSOLUTE int_reseltag = 0xff82;
55 ABSOLUTE int_resfail = 0xff83;
56 ABSOLUTE int_err = 0xffff;
57
58 ; flags for scratcha0
59 ABSOLUTE flag_sdp = 0x01 ; got save data pointer
60 ABSOLUTE flag_data = 0x02 ; we're in data phase
61 ABSOLUTE flag_data_mask = 0xfd ; ~flag_data
62
63 ; main script symbols
64
65 ENTRY waitphase;
66 ENTRY send_msgout;
67 ENTRY msgout;
68 ENTRY msgin;
69 ENTRY handle_msgin;
70 ENTRY msgin_ack;
71 ENTRY dataout;
72 ENTRY datain;
73 ENTRY cmdout;
74 ENTRY status;
75 ENTRY disconnect;
76 ENTRY reselect;
77 ENTRY reselected;
78 ENTRY selected;
79 ENTRY script_sched;
80 ENTRY script_sched_slot0;
81 ENTRY get_extmsgdata;
82 ENTRY resel_targ0;
83 ENTRY msgin_space;
84 ENTRY lunsw_return;
85 ENTRY led_on1;
86 ENTRY led_on2;
87 ENTRY led_off;
88 EXTERN abs_script_sched_slot0;
89 EXTERN abs_targ0;
90 EXTERN abs_msgin;
91
92 ; lun switch symbols
93 ENTRY lun_switch_entry;
94 ENTRY resel_lun0;
95 ENTRY restore_scntl3;
96 EXTERN abs_lunsw_return;
97
98 ; tag switch symbols
99 ENTRY tag_switch_entry;
100 ENTRY resel_tag0;
101 EXTERN abs_tag0;
102
103 ; command reselect script symbols
104 ENTRY rdsa0;
105 ENTRY rdsa1;
106 ENTRY rdsa2;
107 ENTRY rdsa3;
108 ENTRY ldsa_reload_dsa;
109 ENTRY ldsa_select;
110 ENTRY ldsa_data;
111
112 EXTERN ldsa_abs_reselected;
113 EXTERN ldsa_abs_reselect;
114 EXTERN ldsa_abs_selected;
115 EXTERN ldsa_abs_data;
116 EXTERN ldsa_abs_slot;
117
118 ; main script
119
120 PROC siop_script:
121
122 reselected:
123 ; starting a new session, init 'local variables'
124 MOVE 0 to SCRATCHA0 ; flags
125 MOVE 0 to SCRATCHA1 ; DSA offset (for S/G save data pointer)
126 MOVE SCRATCHA3 to SFBR ; pending message ?
127 JUMP REL(handle_msgin), IF not 0x20;
128 waitphase:
129 JUMP REL(msgout), WHEN MSG_OUT;
130 JUMP REL(msgin), WHEN MSG_IN;
131 JUMP REL(dataout), WHEN DATA_OUT;
132 JUMP REL(datain), WHEN DATA_IN;
133 JUMP REL(cmdout), WHEN CMD;
134 JUMP REL(status), WHEN STATUS;
135 INT int_err;
136
137 reselect_fail:
138 ; check that host asserted SIGP, this'll clear SIGP in ISTAT
139 MOVE CTEST2 & 0x40 TO SFBR;
140 INT int_resfail, IF 0x00;
141 ; a NOP by default; patched with MOVE GPREG & 0xfe to GPREG on compile-time
142 ; option "SIOP_SYMLED"
143 led_on1:
144 NOP;
145 script_sched:
146 ; Clear DSA and init status
147 MOVE 0xff to DSA0;
148 MOVE 0xff to DSA1;
149 MOVE 0xff to DSA2;
150 MOVE 0xff to DSA3;
151 MOVE 0 to SCRATCHA0 ; flags
152 MOVE 0 to SCRATCHA1 ; DSA offset (for S/G save data pointer)
153 ; the script scheduler: siop_start() we set the absolute jump addr, and then
154 ; changes the FALSE to TRUE. The select script will change it back to false
155 ; once the target is selected.
156 ; The RAM could hold 370 slot entry, we limit it to 40. Should be more than
157 ; enough.
158 script_sched_slot0:
159 JUMP abs_script_sched_slot0, IF FALSE;
160 JUMP abs_script_sched_slot0, IF FALSE;
161 JUMP abs_script_sched_slot0, IF FALSE;
162 JUMP abs_script_sched_slot0, IF FALSE;
163 JUMP abs_script_sched_slot0, IF FALSE;
164 JUMP abs_script_sched_slot0, IF FALSE;
165 JUMP abs_script_sched_slot0, IF FALSE;
166 JUMP abs_script_sched_slot0, IF FALSE;
167 JUMP abs_script_sched_slot0, IF FALSE;
168 JUMP abs_script_sched_slot0, IF FALSE;
169 JUMP abs_script_sched_slot0, IF FALSE;
170 JUMP abs_script_sched_slot0, IF FALSE;
171 JUMP abs_script_sched_slot0, IF FALSE;
172 JUMP abs_script_sched_slot0, IF FALSE;
173 JUMP abs_script_sched_slot0, IF FALSE;
174 JUMP abs_script_sched_slot0, IF FALSE;
175 JUMP abs_script_sched_slot0, IF FALSE;
176 JUMP abs_script_sched_slot0, IF FALSE;
177 JUMP abs_script_sched_slot0, IF FALSE;
178 JUMP abs_script_sched_slot0, IF FALSE;
179 JUMP abs_script_sched_slot0, IF FALSE;
180 JUMP abs_script_sched_slot0, IF FALSE;
181 JUMP abs_script_sched_slot0, IF FALSE;
182 JUMP abs_script_sched_slot0, IF FALSE;
183 JUMP abs_script_sched_slot0, IF FALSE;
184 JUMP abs_script_sched_slot0, IF FALSE;
185 JUMP abs_script_sched_slot0, IF FALSE;
186 JUMP abs_script_sched_slot0, IF FALSE;
187 JUMP abs_script_sched_slot0, IF FALSE;
188 JUMP abs_script_sched_slot0, IF FALSE;
189 JUMP abs_script_sched_slot0, IF FALSE;
190 JUMP abs_script_sched_slot0, IF FALSE;
191 JUMP abs_script_sched_slot0, IF FALSE;
192 JUMP abs_script_sched_slot0, IF FALSE;
193 JUMP abs_script_sched_slot0, IF FALSE;
194 JUMP abs_script_sched_slot0, IF FALSE;
195 JUMP abs_script_sched_slot0, IF FALSE;
196 JUMP abs_script_sched_slot0, IF FALSE;
197 JUMP abs_script_sched_slot0, IF FALSE;
198 JUMP abs_script_sched_slot0, IF FALSE;
199 ; Nothing to do, wait for reselect
200 reselect:
201 ; Clear DSA and init status
202 MOVE 0xff to DSA0;
203 MOVE 0xff to DSA1;
204 MOVE 0xff to DSA2;
205 MOVE 0xff to DSA3;
206 MOVE 0x00 to SCRATCHA2; no tag
207 MOVE 0x20 to SCRATCHA3; simple tag msg, ignored by reselected:
208 ; a NOP by default; patched with MOVE GPREG | 0x01 to GPREG on compile-time
209 ; option "SIOP_SYMLED"
210 led_off:
211 NOP;
212 WAIT RESELECT REL(reselect_fail)
213 ; a NOP by default; patched with MOVE GPREG & 0xfe to GPREG on compile-time
214 ; option "SIOP_SYMLED"
215 led_on2:
216 NOP;
217 MOVE SSID & 0x8f to SFBR
218 MOVE SFBR to SCRATCHA0 ; save reselect ID
219 ; find the right param for this target
220 resel_targ0:
221 JUMP abs_targ0, IF 0xff;
222 JUMP abs_targ0, IF 0xff;
223 JUMP abs_targ0, IF 0xff;
224 JUMP abs_targ0, IF 0xff;
225 JUMP abs_targ0, IF 0xff;
226 JUMP abs_targ0, IF 0xff;
227 JUMP abs_targ0, IF 0xff;
228 JUMP abs_targ0, IF 0xff;
229 JUMP abs_targ0, IF 0xff;
230 JUMP abs_targ0, IF 0xff;
231 JUMP abs_targ0, IF 0xff;
232 JUMP abs_targ0, IF 0xff;
233 JUMP abs_targ0, IF 0xff;
234 JUMP abs_targ0, IF 0xff;
235 JUMP abs_targ0, IF 0xff;
236 INT int_reseltarg;
237 lunsw_return:
238 MOVE 1, abs_msgin, WHEN MSG_IN;
239 MOVE SFBR & 0x07 to SCRATCHA1; save LUN
240 CLEAR ACK;
241 RETURN, WHEN NOT MSG_IN; If no more message, jump to lun sw
242 MOVE 1, abs_msgin, WHEN MSG_IN;
243 CLEAR ACK;
244 MOVE SFBR to SCRATCHA3; save message
245 RETURN, IF NOT 0x20; jump to lun sw if not simple tag msg
246 MOVE 1, abs_msgin, WHEN MSG_IN; get tag
247 CLEAR ACK;
248 MOVE SFBR to SCRATCHA2; save tag
249 RETURN; jump to lun sw
250
251 handle_sdp:
252 CLEAR ACK;
253 MOVE SCRATCHA0 | flag_sdp TO SCRATCHA0;
254 ; should get a disconnect message now
255 msgin:
256 CLEAR ATN
257 MOVE FROM t_msg_in, WHEN MSG_IN;
258 handle_msgin:
259 JUMP REL(handle_cmpl), IF 0x00 ; command complete message
260 JUMP REL(handle_sdp), IF 0x02 ; save data pointer message
261 JUMP REL(handle_extin), IF 0x01 ; extended message
262 INT int_msgin, IF not 0x04;
263 CALL REL(disconnect) ; disconnect message;
264 ; if we didn't get sdp, no need to interrupt
265 MOVE SCRATCHA0 & flag_sdp TO SFBR;
266 INT int_disc, IF not 0x00;
267 ; update offset if we did some data transfer
268 MOVE SCRATCHA1 TO SFBR;
269 JUMP REL(script_sched), if 0x00;
270 INT int_saveoffset;
271
272 msgin_ack:
273 selected:
274 CLEAR ACK;
275 JUMP REL(waitphase);
276
277 ; entry point for msgout after a msgin or status phase
278 send_msgout:
279 SET ATN;
280 CLEAR ACK;
281 msgout:
282 MOVE FROM t_msg_out, WHEN MSG_OUT;
283 CLEAR ATN;
284 JUMP REL(waitphase);
285 cmdout:
286 MOVE FROM t_cmd, WHEN CMD;
287 JUMP REL(waitphase);
288 status:
289 MOVE FROM t_status, WHEN STATUS;
290 JUMP REL(waitphase);
291 datain:
292 CALL REL(savedsa);
293 MOVE SCRATCHA0 | flag_data TO SCRATCHA0;
294 datain_loop:
295 MOVE FROM t_data, WHEN DATA_IN;
296 MOVE SCRATCHA1 + 1 TO SCRATCHA1 ; adjust offset
297 MOVE DSA0 + 8 to DSA0;
298 MOVE DSA1 + 0 to DSA1 WITH CARRY;
299 MOVE DSA2 + 0 to DSA2 WITH CARRY;
300 MOVE DSA3 + 0 to DSA3 WITH CARRY;
301 JUMP REL(datain_loop), WHEN DATA_IN;
302 CALL REL(restoredsa);
303 MOVE SCRATCHA0 & flag_data_mask TO SCRATCHA0;
304 JUMP REL(waitphase);
305
306 dataout:
307 CALL REL(savedsa);
308 MOVE SCRATCHA0 | flag_data TO SCRATCHA0;
309 dataout_loop:
310 MOVE FROM t_data, WHEN DATA_OUT;
311 MOVE SCRATCHA1 + 1 TO SCRATCHA1 ; adjust offset
312 MOVE DSA0 + 8 to DSA0;
313 MOVE DSA1 + 0 to DSA1 WITH CARRY;
314 MOVE DSA2 + 0 to DSA2 WITH CARRY;
315 MOVE DSA3 + 0 to DSA3 WITH CARRY;
316 JUMP REL(dataout_loop), WHEN DATA_OUT;
317 CALL REL(restoredsa);
318 MOVE SCRATCHA0 & flag_data_mask TO SCRATCHA0;
319 JUMP REL(waitphase);
320
321 savedsa:
322 MOVE DSA0 to SFBR;
323 MOVE SFBR to SCRATCHB0;
324 MOVE DSA1 to SFBR;
325 MOVE SFBR to SCRATCHB1;
326 MOVE DSA2 to SFBR;
327 MOVE SFBR to SCRATCHB2;
328 MOVE DSA3 to SFBR;
329 MOVE SFBR to SCRATCHB3;
330 RETURN;
331
332 restoredsa:
333 MOVE SCRATCHB0 TO SFBR;
334 MOVE SFBR TO DSA0;
335 MOVE SCRATCHB1 TO SFBR;
336 MOVE SFBR TO DSA1;
337 MOVE SCRATCHB2 TO SFBR;
338 MOVE SFBR TO DSA2;
339 MOVE SCRATCHB3 TO SFBR;
340 MOVE SFBR TO DSA3;
341 RETURN;
342
343 disconnect:
344 MOVE SCNTL2 & 0x7f TO SCNTL2;
345 CLEAR ATN;
346 CLEAR ACK;
347 WAIT DISCONNECT;
348 RETURN;
349
350 handle_cmpl:
351 CALL REL(disconnect);
352 INT int_done;
353
354 handle_extin:
355 CLEAR ACK;
356 MOVE FROM t_ext_msg_in, WHEN MSG_IN;
357 INT int_extmsgin; /* let host fill in t_ext_msg_data */
358 get_extmsgdata:
359 CLEAR ACK;
360 MOVE FROM t_ext_msg_data, WHEN MSG_IN;
361 INT int_extmsgdata;
362 msgin_space:
363 NOP; space to store msgin when reselect
364
365
366 ;; per-target switch script for LUNs
367 ; hack: we first do a call to the target-specific code, so that a return
368 ; in the main switch will jump to the lun switch.
369 PROC lun_switch:
370 restore_scntl3:
371 MOVE 0xff TO SCNTL3;
372 MOVE 0xff TO SXFER;
373 JUMP abs_lunsw_return;
374 lun_switch_entry:
375 CALL REL(restore_scntl3);
376 MOVE SCRATCHA1 TO SFBR;
377 resel_lun0:
378 INT int_resellun;
379
380 ;; Per-device switch script for tag
381 PROC tag_switch:
382 tag_switch_entry:
383 MOVE SCRATCHA2 TO SFBR; restore tag
384 resel_tag0:
385 JUMP abs_tag0, IF 0x00;
386 JUMP abs_tag0, IF 0x01;
387 JUMP abs_tag0, IF 0x02;
388 JUMP abs_tag0, IF 0x03;
389 JUMP abs_tag0, IF 0x04;
390 JUMP abs_tag0, IF 0x05;
391 JUMP abs_tag0, IF 0x06;
392 JUMP abs_tag0, IF 0x07;
393 JUMP abs_tag0, IF 0x08;
394 JUMP abs_tag0, IF 0x09;
395 JUMP abs_tag0, IF 0x0a;
396 JUMP abs_tag0, IF 0x0b;
397 JUMP abs_tag0, IF 0x0c;
398 JUMP abs_tag0, IF 0x0d;
399 JUMP abs_tag0, IF 0x0e;
400 JUMP abs_tag0, IF 0x0f;
401 INT int_reseltag;
402
403 ;; per-command script: select, and called after a reselect to load DSA
404
405 PROC load_dsa:
406 ; Can't use MOVE MEMORY to load DSA, doesn't work I/O mapped
407 rdsa0:
408 MOVE 0xf0 to DSA0;
409 rdsa1:
410 MOVE 0xf1 to DSA1;
411 rdsa2:
412 MOVE 0xf2 to DSA2;
413 rdsa3:
414 MOVE 0xf3 to DSA3;
415 RETURN;
416 ldsa_reload_dsa:
417 CALL REL(rdsa0);
418 JUMP ldsa_abs_reselected;
419 ldsa_select:
420 CALL REL(rdsa0);
421 SELECT ATN FROM t_id, ldsa_abs_reselect;
422 MOVE MEMORY 4, ldsa_abs_data, ldsa_abs_slot;
423 JUMP ldsa_abs_selected;
424 ldsa_data:
425 NOP; contains data used by the MOVE MEMORY
426
427 PROC siop_led_on:
428 MOVE GPREG & 0xfe TO GPREG;
429
430 PROC siop_led_off:
431 MOVE GPREG | 0x01 TO GPREG;
432