siop.ss revision 1.12 1 ; $NetBSD: siop.ss,v 1.12 2000/10/23 14:53:53 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 sym_xfer
34 ABSOLUTE t_id = 24;
35 ABSOLUTE t_msg_in = 32;
36 ABSOLUTE t_ext_msg_in = 40;
37 ABSOLUTE t_ext_msg_data = 48;
38 ABSOLUTE t_msg_out = 56;
39 ABSOLUTE t_cmd = 64;
40 ABSOLUTE t_status = 72;
41 ABSOLUTE t_data = 80;
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 ; interrupts that don't have a valid DSA
51 ABSOLUTE int_reseltarg = 0xff80;
52 ABSOLUTE int_resellun = 0xff81;
53 ABSOLUTE int_reseltag = 0xff82;
54 ABSOLUTE int_resfail = 0xff83;
55 ABSOLUTE int_err = 0xffff;
56
57 ; flags for scratcha0
58 ABSOLUTE flag_sdp = 0x01 ; got save data pointer
59 ABSOLUTE flag_data = 0x02 ; we're in data phase
60 ABSOLUTE flag_data_mask = 0xfd ; ~flag_data
61
62 ; main script symbols
63
64 ENTRY waitphase;
65 ENTRY send_msgout;
66 ENTRY msgout;
67 ENTRY msgin;
68 ENTRY handle_msgin;
69 ENTRY msgin_ack;
70 ENTRY dataout;
71 ENTRY datain;
72 ENTRY cmdout;
73 ENTRY status;
74 ENTRY disconnect;
75 ENTRY reselect;
76 ENTRY reselected;
77 ENTRY selected;
78 ENTRY script_sched;
79 ENTRY script_sched_slot0;
80 ENTRY get_extmsgdata;
81 ENTRY resel_targ0;
82 ENTRY msgin_space;
83 ENTRY lunsw_return;
84 EXTERN abs_script_sched_slot0;
85 EXTERN abs_targ0;
86 EXTERN abs_msgin;
87
88 ; lun switch symbols
89 ENTRY lun_switch_entry;
90 ENTRY resel_lun0;
91 ENTRY restore_scntl3;
92 EXTERN abs_lunsw_return;
93
94 ; tag switch symbols
95 ENTRY tag_switch_entry;
96 ENTRY resel_tag0;
97 EXTERN abs_tag0;
98
99 ; command reselect script symbols
100 ENTRY rdsa0;
101 ENTRY rdsa1;
102 ENTRY rdsa2;
103 ENTRY rdsa3;
104 ENTRY ldsa_reload_dsa;
105 ENTRY ldsa_select;
106 ENTRY ldsa_data;
107
108 EXTERN ldsa_abs_reselected;
109 EXTERN ldsa_abs_reselect;
110 EXTERN ldsa_abs_selected;
111 EXTERN ldsa_abs_data;
112 EXTERN ldsa_abs_slot;
113
114 ; main script
115
116 PROC siop_script:
117
118 reselected:
119 ; starting a new session, init 'local variables'
120 MOVE 0 to SCRATCHA0 ; flags
121 MOVE 0 to SCRATCHA1 ; DSA offset (for S/G save data pointer)
122 MOVE SCRATCHA3 to SFBR ; pending message ?
123 JUMP REL(handle_msgin), IF not 0x20;
124 waitphase:
125 JUMP REL(msgout), WHEN MSG_OUT;
126 JUMP REL(msgin), WHEN MSG_IN;
127 JUMP REL(dataout), WHEN DATA_OUT;
128 JUMP REL(datain), WHEN DATA_IN;
129 JUMP REL(cmdout), WHEN CMD;
130 JUMP REL(status), WHEN STATUS;
131 INT int_err;
132
133 reselect_fail:
134 ; check that host asserted SIGP, this'll clear SIGP in ISTAT
135 MOVE CTEST2 & 0x40 TO SFBR;
136 INT int_resfail, IF 0x00;
137 script_sched:
138 ; Clear DSA and init status
139 MOVE 0xff to DSA0;
140 MOVE 0xff to DSA1;
141 MOVE 0xff to DSA2;
142 MOVE 0xff to DSA3;
143 MOVE 0 to SCRATCHA0 ; flags
144 MOVE 0 to SCRATCHA1 ; DSA offset (for S/G save data pointer)
145 ; the script scheduler: siop_start() we set the absolute jump addr, and then
146 ; changes the FALSE to TRUE. The select script will change it back to false
147 ; once the target is selected.
148 ; The RAM could hold 370 slot entry, we limit it to 40. Should be more than
149 ; enouth.
150 script_sched_slot0:
151 JUMP abs_script_sched_slot0, IF FALSE;
152 JUMP abs_script_sched_slot0, IF FALSE;
153 JUMP abs_script_sched_slot0, IF FALSE;
154 JUMP abs_script_sched_slot0, IF FALSE;
155 JUMP abs_script_sched_slot0, IF FALSE;
156 JUMP abs_script_sched_slot0, IF FALSE;
157 JUMP abs_script_sched_slot0, IF FALSE;
158 JUMP abs_script_sched_slot0, IF FALSE;
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 ; Nothing to do, wait for reselect
192 reselect:
193 ; Clear DSA and init status
194 MOVE 0xff to DSA0;
195 MOVE 0xff to DSA1;
196 MOVE 0xff to DSA2;
197 MOVE 0xff to DSA3;
198 MOVE 0x00 to SCRATCHA2; no tag
199 MOVE 0x20 to SCRATCHA3; simple tag msg, ignored by reselected:
200 WAIT RESELECT REL(reselect_fail)
201 MOVE SSID & 0x8f to SFBR
202 MOVE SFBR to SCRATCHA0 ; save reselect ID
203 ; find the rigth param for this target
204 resel_targ0:
205 JUMP abs_targ0, IF 0xff;
206 JUMP abs_targ0, IF 0xff;
207 JUMP abs_targ0, IF 0xff;
208 JUMP abs_targ0, IF 0xff;
209 JUMP abs_targ0, IF 0xff;
210 JUMP abs_targ0, IF 0xff;
211 JUMP abs_targ0, IF 0xff;
212 JUMP abs_targ0, IF 0xff;
213 JUMP abs_targ0, IF 0xff;
214 JUMP abs_targ0, IF 0xff;
215 JUMP abs_targ0, IF 0xff;
216 JUMP abs_targ0, IF 0xff;
217 JUMP abs_targ0, IF 0xff;
218 JUMP abs_targ0, IF 0xff;
219 JUMP abs_targ0, IF 0xff;
220 INT int_reseltarg;
221 lunsw_return:
222 MOVE 1, abs_msgin, WHEN MSG_IN;
223 MOVE SFBR & 0x07 to SCRATCHA1; save LUN
224 CLEAR ACK;
225 RETURN, WHEN NOT MSG_IN; If no more message, jump to lun sw
226 MOVE 1, abs_msgin, WHEN MSG_IN;
227 CLEAR ACK;
228 MOVE SFBR to SCRATCHA3; save message
229 RETURN, IF NOT 0x20; jump to lun sw if not simple tag msg
230 MOVE 1, abs_msgin, WHEN MSG_IN; get tag
231 CLEAR ACK;
232 MOVE SFBR to SCRATCHA2; save tag
233 RETURN; jump to lun sw
234
235 handle_sdp:
236 CLEAR ACK;
237 MOVE SCRATCHA0 | flag_sdp TO SCRATCHA0;
238 ; should get a disconnect message now
239 msgin:
240 CLEAR ATN
241 MOVE FROM t_msg_in, WHEN MSG_IN;
242 handle_msgin:
243 JUMP REL(handle_cmpl), IF 0x00 ; command complete message
244 JUMP REL(handle_sdp), IF 0x02 ; save data pointer message
245 JUMP REL(handle_extin), IF 0x01 ; extended message
246 INT int_msgin, IF not 0x04;
247 CALL REL(disconnect) ; disconnect message;
248 ; if we didn't get sdp, or if offset is 0, no need to interrupt
249 MOVE SCRATCHA0 & flag_sdp TO SFBR;
250 JUMP REL(script_sched), if 0x00;
251 MOVE SCRATCHA1 TO SFBR;
252 JUMP REL(script_sched), if 0x00;
253 ; Ok, we need to save data pointers
254 INT int_disc;
255 msgin_ack:
256 selected:
257 CLEAR ACK;
258 JUMP REL(waitphase);
259
260 ; entry point for msgout after a msgin or status phase
261 send_msgout:
262 SET ATN;
263 CLEAR ACK;
264 msgout:
265 MOVE FROM t_msg_out, WHEN MSG_OUT;
266 CLEAR ATN;
267 JUMP REL(waitphase);
268 cmdout:
269 MOVE FROM t_cmd, WHEN CMD;
270 JUMP REL(waitphase);
271 status:
272 MOVE FROM t_status, WHEN STATUS;
273 JUMP REL(waitphase);
274 datain:
275 CALL REL(savedsa);
276 MOVE SCRATCHA0 | flag_data TO SCRATCHA0;
277 datain_loop:
278 MOVE FROM t_data, WHEN DATA_IN;
279 MOVE SCRATCHA1 + 1 TO SCRATCHA1 ; adjust offset
280 MOVE DSA0 + 8 to DSA0;
281 MOVE DSA1 + 0 to DSA1 WITH CARRY;
282 MOVE DSA2 + 0 to DSA2 WITH CARRY;
283 MOVE DSA3 + 0 to DSA3 WITH CARRY;
284 JUMP REL(datain_loop), WHEN DATA_IN;
285 CALL REL(restoredsa);
286 MOVE SCRATCHA0 & flag_data_mask TO SCRATCHA0;
287 JUMP REL(waitphase);
288
289 dataout:
290 CALL REL(savedsa);
291 MOVE SCRATCHA0 | flag_data TO SCRATCHA0;
292 dataout_loop:
293 MOVE FROM t_data, WHEN DATA_OUT;
294 MOVE SCRATCHA1 + 1 TO SCRATCHA1 ; adjust offset
295 MOVE DSA0 + 8 to DSA0;
296 MOVE DSA1 + 0 to DSA1 WITH CARRY;
297 MOVE DSA2 + 0 to DSA2 WITH CARRY;
298 MOVE DSA3 + 0 to DSA3 WITH CARRY;
299 JUMP REL(dataout_loop), WHEN DATA_OUT;
300 CALL REL(restoredsa);
301 MOVE SCRATCHA0 & flag_data_mask TO SCRATCHA0;
302 JUMP REL(waitphase);
303
304 savedsa:
305 MOVE DSA0 to SFBR;
306 MOVE SFBR to SCRATCHB0;
307 MOVE DSA1 to SFBR;
308 MOVE SFBR to SCRATCHB1;
309 MOVE DSA2 to SFBR;
310 MOVE SFBR to SCRATCHB2;
311 MOVE DSA3 to SFBR;
312 MOVE SFBR to SCRATCHB3;
313 RETURN;
314
315 restoredsa:
316 MOVE SCRATCHB0 TO SFBR;
317 MOVE SFBR TO DSA0;
318 MOVE SCRATCHB1 TO SFBR;
319 MOVE SFBR TO DSA1;
320 MOVE SCRATCHB2 TO SFBR;
321 MOVE SFBR TO DSA2;
322 MOVE SCRATCHB3 TO SFBR;
323 MOVE SFBR TO DSA3;
324 RETURN;
325
326 disconnect:
327 MOVE SCNTL2 & 0x7f TO SCNTL2;
328 CLEAR ATN;
329 CLEAR ACK;
330 WAIT DISCONNECT;
331 RETURN;
332
333 handle_cmpl:
334 CALL REL(disconnect);
335 INT int_done;
336
337 handle_extin:
338 CLEAR ACK;
339 MOVE FROM t_ext_msg_in, WHEN MSG_IN;
340 INT int_extmsgin; /* let host fill in t_ext_msg_data */
341 get_extmsgdata:
342 CLEAR ACK;
343 MOVE FROM t_ext_msg_data, WHEN MSG_IN;
344 INT int_extmsgdata;
345 msgin_space:
346 NOP; space to store msgin when reselect
347
348
349 ;; per-target switch script for LUNs
350 ; hack: we first do a call to the target-specific code, so that a return
351 ; in the main switch will jump to the lun switch.
352 PROC lun_switch:
353 restore_scntl3:
354 MOVE 0xff TO SCNTL3;
355 MOVE 0xff TO SXFER;
356 JUMP abs_lunsw_return;
357 lun_switch_entry:
358 CALL REL(restore_scntl3);
359 MOVE SCRATCHA1 TO SFBR;
360 resel_lun0:
361 INT int_resellun;
362
363 ;; Per-device switch script for tag
364 PROC tag_switch:
365 tag_switch_entry:
366 MOVE SCRATCHA2 TO SFBR; restore tag
367 resel_tag0:
368 JUMP abs_tag0, IF 0x00;
369 JUMP abs_tag0, IF 0x01;
370 JUMP abs_tag0, IF 0x02;
371 JUMP abs_tag0, IF 0x03;
372 JUMP abs_tag0, IF 0x04;
373 JUMP abs_tag0, IF 0x05;
374 JUMP abs_tag0, IF 0x06;
375 JUMP abs_tag0, IF 0x07;
376 JUMP abs_tag0, IF 0x08;
377 JUMP abs_tag0, IF 0x09;
378 JUMP abs_tag0, IF 0x0a;
379 JUMP abs_tag0, IF 0x0b;
380 JUMP abs_tag0, IF 0x0c;
381 JUMP abs_tag0, IF 0x0d;
382 JUMP abs_tag0, IF 0x0e;
383 JUMP abs_tag0, IF 0x0f;
384 INT int_reseltag;
385
386 ;; per-command script: select, and called after a reselect to load DSA
387
388 PROC load_dsa:
389 ; Can't use MOVE MEMORY to load DSA, doesn't work I/O mapped
390 rdsa0:
391 MOVE 0xf0 to DSA0;
392 rdsa1:
393 MOVE 0xf1 to DSA1;
394 rdsa2:
395 MOVE 0xf2 to DSA2;
396 rdsa3:
397 MOVE 0xf3 to DSA3;
398 RETURN;
399 ldsa_reload_dsa:
400 CALL REL(rdsa0);
401 JUMP ldsa_abs_reselected;
402 ldsa_select:
403 CALL REL(rdsa0);
404 SELECT ATN FROM t_id, ldsa_abs_reselect;
405 MOVE MEMORY 4, ldsa_abs_data, ldsa_abs_slot;
406 JUMP ldsa_abs_selected;
407 ldsa_data:
408 NOP; contains data used by the MOVE MEMORY
409