1 ; $NetBSD: esiop.ss,v 1.20 2005/11/18 23:10:32 bouyer Exp $
4 ; Copyright (c) 2002 Manuel Bouyer.
6 ; Redistribution and use in source and binary forms, with or without
7 ; modification, are permitted provided that the following conditions
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.
15 ; THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
16 ; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 ; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 ; ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
19 ; FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 ; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 ; OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 ; HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 ; LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 ; OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 ; offsets in siop_common_xfer
32 ABSOLUTE t_msg_in = 48;
33 ABSOLUTE t_ext_msg_in = 56;
34 ABSOLUTE t_ext_msg_data = 64;
35 ABSOLUTE t_msg_out = 72;
37 ABSOLUTE t_status = 88;
40 ; offsets in the per-target lun table
41 ABSOLUTE target_id = 0x0;
42 ABSOLUTE target_luntbl = 0x8;
43 ABSOLUTE target_luntbl_tag = 0xc;
46 ; interrupts that needs a valid target/lun/tag
47 ABSOLUTE int_done = 0xff00;
48 ABSOLUTE int_msgin = 0xff01;
49 ABSOLUTE int_extmsgin = 0xff02;
50 ABSOLUTE int_extmsgdata = 0xff03;
51 ABSOLUTE int_disc = 0xff04;
52 ; interrupts that don't have a valid I/T/Q
53 ABSOLUTE int_resfail = 0xff80;
54 ABSOLUTE int_err = 0xffff;
56 ; We use the various scratch[a-j] registers to keep internal status:
58 ; scratchA1: offset in data DSA (for save data pointer)
59 ; scratchB: save/restore DSA in data loop
60 ; scratchC: current target/lun/tag
62 ABSOLUTE f_c_target = 0x01 ; target valid
63 ABSOLUTE f_c_lun = 0x02 ; lun valid
64 ABSOLUTE f_c_tag = 0x04 ; tag valid
65 ABSOLUTE f_c_data = 0x08 ; data I/O in progress
66 ABSOLUTE f_c_data_mask = 0xf7 ; ~f_c_data
67 ABSOLUTE f_c_sdp = 0x10 ; got save data pointer message
68 ; scratchC[1-3]: target/lun/tag
70 ; scratchD: current DSA in start cmd ring
71 ; scratchE0: index in start cmd ring
72 ABSOLUTE ncmd_slots = 256 ; number of slots in CMD ring
73 ABSOLUTE ncmd_slots_last = 0 ; == ncmd_slots in a 8bit counter
75 ABSOLUTE f_cmd_free = 0x01 ; this slot is free
76 ABSOLUTE f_cmd_ignore = 0x02 ; this slot is not free but don't start it
77 ; offsets in a cmd slot
78 ABSOLUTE o_cmd_dsa = 0; also holds f_cmd_*
79 ; size of a cmd slot (for DSA increments)
80 ABSOLUTE cmd_slot_size = 4;
82 ; SCRATCHE1: last status
84 ; SCRATCHE2: current command done slot
85 ABSOLUTE ndone_slots = 256 ; number of slots in CMD ring
86 ABSOLUTE ndone_slots_last = 0 ; == ndonemd_slots in a 8bit counter
87 ; SCRATCHF: pointer in command done ring
104 ENTRY get_extmsgdata;
107 ENTRY load_targtable;
110 EXTERN saved_offset_offset;
113 EXTERN abs_sem; a 32bits word used a semaphore between script and driver
114 ABSOLUTE sem_done = 0x01; there are pending done commands
115 ABSOLUTE sem_start = 0x02; a CMD slot was freed
120 LOAD SCRATCHB0, 4, abs_sem; pending done command ?
121 MOVE SCRATCHB0 & sem_done TO SFBR;
122 INTFLY 0, IF NOT 0x00;
123 MOVE SCRATCHB0 | sem_start TO SCRATCHB0; we are there because the
124 STORE NOFLUSH SCRATCHB0, 4, abs_sem; cmd ring is empty
126 MOVE 0x00 TO SCRATCHA1;
127 MOVE 0x00 TO SCRATCHC0;
128 MOVE 0xff TO SCRATCHE1;
129 ; a NOP by default; patched with MOVE GPREG | 0x01 to GPREG on compile-time
130 ; option "SIOP_SYMLED"
133 WAIT RESELECT REL(reselect_fail);
134 ; a NOP by default; patched with MOVE GPREG & 0xfe to GPREG on compile-time
135 ; option "SIOP_SYMLED"
138 MOVE SSID & 0x0f to SFBR;
139 MOVE SFBR to SCRATCHC1;
140 MOVE SCRATCHC0 | f_c_target to SCRATCHC0; save target
142 MOVE SCRATCHC1 SHL SFBR;
143 MOVE SFBR SHL DSA0; target * 4 in dsa
147 ; load DSA for the target table
149 MOVE DSA0 + 0x00 to DSA0; host will patch 0x0 with base of table
150 MOVE DSA1 + 0x00 to DSA1 with carry;
151 MOVE DSA2 + 0x00 to DSA2 with carry;
152 MOVE DSA3 + 0x00 to DSA3 with carry; now dsa -> basetable + target * 4
153 LOAD DSA0, 4, FROM 0; now load DSA for this target
154 SELECT FROM target_id, REL(nextisn);
156 MOVE 1, abs_msgin2, WHEN MSG_IN;
157 MOVE SFBR & 0x07 to SCRATCHC2;
158 MOVE SCRATCHC0 | f_c_lun to SCRATCHC0; save LUN
160 MOVE SCRATCHC2 SHL SFBR;
162 MOVE SFBR SHL SFBR; lun * 8
163 MOVE DSA0 + SFBR TO DSA0;
164 MOVE DSA1 + 0x0 TO DSA1 with carry;
165 MOVE DSA2 + 0x0 TO DSA2 with carry;
166 MOVE DSA3 + 0x0 TO DSA3 with carry;
167 LOAD SCRATCHB0, 4, from target_luntbl_tag; in case it's a tagged cmd
168 LOAD DSA0, 4, from target_luntbl; load DSA for this LUN
169 JUMP REL(waitphase), WHEN NOT MSG_IN;
170 MOVE 1, abs_msgin2, WHEN MSG_IN;
172 JUMP REL(handle_msgin), IF NOT 0x20; not a simple tag message
173 MOVE 1, abs_msgin2, WHEN MSG_IN; get tag
174 MOVE SFBR to SCRATCHA2;
175 MOVE SFBR to SCRATCHC3;
176 MOVE SCRATCHC0 | f_c_tag to SCRATCHC0; save TAG
177 CALL REL(restoredsa); switch to tag table DSA
178 MOVE 0x0 to SCRATCHA3;
180 MOVE SCRATCHA2 SHL SCRATCHA2;
181 MOVE SCRATCHA3 SHL SCRATCHA3;
182 MOVE SCRATCHA2 SHL SCRATCHA2;
183 MOVE SCRATCHA3 SHL SCRATCHA3; TAG * 4 to SCRATCHA(2,3)
184 MOVE SCRATCHA2 TO SFBR;
185 MOVE DSA0 + SFBR TO DSA0;
186 MOVE DSA1 + 0x00 TO DSA1 with CARRY;
187 MOVE DSA2 + 0x00 TO DSA2 with CARRY;
188 MOVE DSA3 + 0x00 TO DSA3 with CARRY;
189 MOVE SCRATCHA3 TO SFBR;
190 MOVE DSA1 + SFBR TO DSA1;
191 MOVE DSA2 + 0x00 TO DSA2 with CARRY;
192 MOVE DSA3 + 0x00 TO DSA3 with CARRY; SCRACHA(2,3) + DSA to DSA
193 LOAD DSA0, 4, from 0; load DSA for this tag
197 JUMP REL(msgout), WHEN MSG_OUT;
198 JUMP REL(msgin), WHEN MSG_IN;
199 JUMP REL(dataout), WHEN DATA_OUT;
200 JUMP REL(datain), WHEN DATA_IN;
201 JUMP REL(cmdout), WHEN CMD;
202 JUMP REL(status), WHEN STATUS;
206 CALL REL(disconnect);
207 ; update offset if we did some data transfer
208 MOVE SCRATCHA1 TO SFBR;
209 JUMP REL(handle_cmpl_noxfer), if 0x00;
210 STORE NOFLUSH SCRATCHA0, 4, FROM saved_offset_offset;
212 MOVE SCRATCHE1 to SFBR;
213 INT int_done, IF NOT 0x00; if status is not "done", let host handle it
214 MOVE SCRATCHF0 to SFBR; load pointer in done ring
216 MOVE SCRATCHF1 to SFBR;
218 MOVE SCRATCHF2 to SFBR;
220 MOVE SCRATCHF3 to SFBR;
223 LOAD SCRATCHA0, 1, from 0;
224 MOVE SCRATCHA0 to SFBR;
225 JUMP REL(wait_free), if not 0; wait for slot to be free
226 STORE NOFLUSH SCRATCHC0, 4, from 0; save current target/lun/flag
227 MOVE SCRATCHF0 + 4 to SCRATCHF0; advance to next slot
228 MOVE SCRATCHF1 + 0 to SCRATCHF1 with carry;
229 MOVE SCRATCHF2 + 0 to SCRATCHF2 with carry;
230 MOVE SCRATCHF3 + 0 to SCRATCHF3 with carry;
231 MOVE SCRATCHE2 + 1 to SCRATCHE2;
232 MOVE SCRATCHE2 to SFBR;
233 JUMP REL(is_done), if not ndone_slots_last;
235 MOVE 0xff to SCRATCHF0; driver will change 0xff to base of ring
237 MOVE 0xff to SCRATCHF1;
239 MOVE 0xff to SCRATCHF2;
241 MOVE 0xff to SCRATCHF3;
244 LOAD SCRATCHB0, 4, abs_sem; signal that a command is done
245 MOVE SCRATCHB0 | sem_done TO SCRATCHB0;
246 STORE NOFLUSH SCRATCHB0, 4, abs_sem;
247 ; and attempt next command
250 ; clear SIGP in ISTAT
251 MOVE CTEST2 & 0x40 TO SFBR;
254 MOVE SCRATCHD0 to SFBR;
256 MOVE SCRATCHD1 to SFBR;
258 MOVE SCRATCHD2 to SFBR;
260 MOVE SCRATCHD3 to SFBR;
262 LOAD DSA0,4, from o_cmd_dsa; get DSA and flags for this slot
263 MOVE DSA0 & f_cmd_free to SFBR; check flags
264 JUMP REL(no_cmd), IF NOT 0x0;
265 MOVE DSA0 & f_cmd_ignore to SFBR;
266 JUMP REL(ignore_cmd), IF NOT 0x0;
267 LOAD SCRATCHC0, 4, FROM tlq_offset;
268 ; this slot is busy, attempt to exec command
269 SELECT ATN FROM t_id, REL(reselect);
270 ; select either succeeded or timed out.
271 ; if timed out the STO interrupt will be posted at the first SCSI bus access
272 ; waiting for a valid phase, so we have to do it now. If not a MSG_OUT phase,
273 ; this is an error anyway (we selected with ATN)
274 INT int_err, WHEN NOT MSG_OUT;
276 MOVE SCRATCHD0 to SFBR; restore scheduler DSA
278 MOVE SCRATCHD1 to SFBR;
280 MOVE SCRATCHD2 to SFBR;
282 MOVE SCRATCHD3 to SFBR;
284 MOVE SCRATCHE0 + 1 to SCRATCHE0;
285 MOVE SCRATCHD0 + cmd_slot_size to SCRATCHD0;
286 MOVE SCRATCHD1 + 0 to SCRATCHD1 WITH CARRY;
287 MOVE SCRATCHD2 + 0 to SCRATCHD2 WITH CARRY;
288 MOVE SCRATCHD3 + 0 to SCRATCHD3 WITH CARRY;
289 MOVE SCRATCHE0 TO SFBR;
290 JUMP REL(handle_cmd), IF NOT ncmd_slots_last;
291 ; reset pointers to beggining of area
293 MOVE 0xff to SCRATCHD0; correct value will be patched by driver
295 MOVE 0xff to SCRATCHD1;
297 MOVE 0xff to SCRATCHD2;
299 MOVE 0xff to SCRATCHD3;
300 MOVE 0x00 to SCRATCHE0;
302 ; to avoid race condition we have to load the DSA value before setting the
303 ; free flag, so we have to use a temp register.
304 ; use SCRATCHB0 so that we can CALL restoredsa later
305 LOAD SCRATCHB0, 4, FROM o_cmd_dsa; load DSA for this command in temp reg
306 MOVE SCRATCHB0 | f_cmd_free to SCRATCHB0; mark slot as free
307 STORE noflush SCRATCHB0, 4, FROM o_cmd_dsa;
308 MOVE SCRATCHB0 & f_cmd_ignore to SFBR;
309 JUMP REL(script_sched), IF NOT 0x00; next command if ignore
310 MOVE SCRATCHB0 & 0xfc to SCRATCHB0; clear f_cmd_*
311 CALL REL(restoredsa); and move SCRATCHB to DSA
312 LOAD SCRATCHB0, 4, abs_sem;
313 MOVE SCRATCHB0 | sem_start TO SCRATCHB0;
314 STORE NOFLUSH SCRATCHB0, 4, abs_sem;
316 ; a NOP by default; patched with MOVE GPREG & 0xfe to GPREG on compile-time
317 ; option "SIOP_SYMLED"
320 MOVE 0x00 TO SCRATCHA1;
321 MOVE 0xff TO SCRATCHE1;
322 ;we can now send our identify message
323 send_msgout: ; entry point for msgout after a msgin or status phase
327 MOVE FROM t_msg_out, WHEN MSG_OUT;
334 MOVE SCRATCHC0 | f_c_sdp TO SCRATCHC0;
335 ; should get a disconnect message now
338 MOVE FROM t_msg_in, WHEN MSG_IN;
340 JUMP REL(handle_cmpl), IF 0x00 ; command complete message
341 JUMP REL(handle_sdp), IF 0x02 ; save data pointer message
342 JUMP REL(handle_extin), IF 0x01 ; extended message
343 INT int_msgin, IF NOT 0x04;
344 CALL REL(disconnect) ; disconnect message
345 ; if we didn't get sdp, no need to interrupt
346 MOVE SCRATCHC0 & f_c_sdp TO SFBR;
347 INT int_disc, IF not 0x00;
348 ; update offset if we did some data transfer
349 MOVE SCRATCHA1 TO SFBR;
350 JUMP REL(script_sched), if 0x00;
351 STORE NOFLUSH SCRATCHA0, 4, FROM saved_offset_offset;
352 JUMP REL(script_sched);
355 MOVE FROM t_cmd, WHEN CMD;
358 MOVE FROM t_status, WHEN STATUS;
359 MOVE SFBR TO SCRATCHE1;
363 MOVE SCRATCHC0 | f_c_data TO SCRATCHC0;
365 MOVE FROM t_data, WHEN DATA_IN;
366 MOVE SCRATCHA1 + 1 TO SCRATCHA1 ; adjust offset
367 MOVE DSA0 + 8 to DSA0;
368 MOVE DSA1 + 0 to DSA1 WITH CARRY;
369 MOVE DSA2 + 0 to DSA2 WITH CARRY;
370 MOVE DSA3 + 0 to DSA3 WITH CARRY;
371 JUMP REL(datain_loop), WHEN DATA_IN;
372 CALL REL(restoredsa);
373 MOVE SCRATCHC0 & f_c_data_mask TO SCRATCHC0;
378 MOVE SCRATCHC0 | f_c_data TO SCRATCHC0;
380 MOVE FROM t_data, WHEN DATA_OUT;
381 MOVE SCRATCHA1 + 1 TO SCRATCHA1 ; adjust offset
382 MOVE DSA0 + 8 to DSA0;
383 MOVE DSA1 + 0 to DSA1 WITH CARRY;
384 MOVE DSA2 + 0 to DSA2 WITH CARRY;
385 MOVE DSA3 + 0 to DSA3 WITH CARRY;
386 JUMP REL(dataout_loop), WHEN DATA_OUT;
387 CALL REL(restoredsa);
388 MOVE SCRATCHC0 & f_c_data_mask TO SCRATCHC0;
393 MOVE SFBR to SCRATCHB0;
395 MOVE SFBR to SCRATCHB1;
397 MOVE SFBR to SCRATCHB2;
399 MOVE SFBR to SCRATCHB3;
403 MOVE SCRATCHB0 TO SFBR;
405 MOVE SCRATCHB1 TO SFBR;
407 MOVE SCRATCHB2 TO SFBR;
409 MOVE SCRATCHB3 TO SFBR;
414 MOVE SCNTL2 & 0x7f TO SCNTL2;
422 MOVE FROM t_ext_msg_in, WHEN MSG_IN;
423 INT int_extmsgin; /* let host fill in t_ext_msg_data */
426 MOVE FROM t_ext_msg_data, WHEN MSG_IN;
430 MOVE GPREG & 0xfe TO GPREG;
433 MOVE GPREG | 0x01 TO GPREG;