Expand PMF_FN_* macros.
[netbsd-mini2440.git] / sys / dev / microcode / siop / esiop.ss
blob54e09e4b3b26f58d7ba0fcc87a84869427c981df
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
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.
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
25 ; SUCH DAMAGE.
28 ARCH 825
30 ; offsets in siop_common_xfer
31 ABSOLUTE t_id = 40;
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;
36 ABSOLUTE t_cmd = 80;
37 ABSOLUTE t_status = 88;
38 ABSOLUTE t_data = 96;
40 ; offsets in the per-target lun table
41 ABSOLUTE target_id = 0x0;
42 ABSOLUTE target_luntbl = 0x8;
43 ABSOLUTE target_luntbl_tag = 0xc;
45 ;; interrupt codes
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
61 ; scratchC0: flags
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
74 ; flags in a cmd slot
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
89 ENTRY cmdr0;
90 ENTRY cmdr1;
91 ENTRY cmdr2;
92 ENTRY cmdr3;
93 ENTRY doner0;
94 ENTRY doner1;
95 ENTRY doner2;
96 ENTRY doner3;
97 ENTRY reselect;
98 ENTRY led_on1;
99 ENTRY led_on2;
100 ENTRY led_off;
101 ENTRY status;
102 ENTRY msgin;
103 ENTRY msgin_ack;
104 ENTRY get_extmsgdata;
105 ENTRY send_msgout;
106 ENTRY script_sched;
107 ENTRY load_targtable;
109 EXTERN tlq_offset;
110 EXTERN saved_offset_offset;
111 EXTERN abs_msgin2;
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
117 PROC  esiop_script:
119 no_cmd:
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
125 reselect:
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"
131 led_off:
132         NOP;
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"
136 led_on2:
137         NOP;
138         MOVE SSID & 0x0f to SFBR;
139         MOVE SFBR to SCRATCHC1;
140         MOVE SCRATCHC0 | f_c_target to SCRATCHC0; save target
141         CLEAR CARRY;
142         MOVE SCRATCHC1 SHL SFBR;
143         MOVE SFBR SHL DSA0; target * 4 in dsa
144         MOVE 0x0 to DSA1;
145         MOVE 0x0 to DSA2;
146         MOVE 0x0 to DSA3;
147 ; load DSA for the target table
148 load_targtable:
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);
155 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
159         CLEAR ACK and CARRY;
160         MOVE SCRATCHC2 SHL SFBR;
161         MOVE SFBR 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;
171         CLEAR ACK;
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;
179         CLEAR CARRY;
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
194 msgin_ack:
195         CLEAR ACK;
196 waitphase:
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;
203         INT int_err;
205 handle_cmpl:
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;
211 handle_cmpl_noxfer:
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
215         MOVE SFBR to DSA0;
216         MOVE SCRATCHF1 to SFBR;
217         MOVE SFBR to DSA1;
218         MOVE SCRATCHF2 to SFBR;
219         MOVE SFBR to DSA2;
220         MOVE SCRATCHF3 to SFBR;
221         MOVE SFBR to DSA3;
222 wait_free:
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;
234 doner0:
235         MOVE 0xff to SCRATCHF0; driver will change 0xff to base of ring
236 doner1:
237         MOVE 0xff to SCRATCHF1;
238 doner2:
239         MOVE 0xff to SCRATCHF2;
240 doner3:
241         MOVE 0xff to SCRATCHF3;
242         MOVE 0  to SCRATCHE2;
243 is_done:
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
249 reselect_fail:
250         ; clear SIGP in ISTAT
251         MOVE CTEST2 & 0x40 TO SFBR;
252 script_sched:
253 ; Load ring DSA
254         MOVE SCRATCHD0 to SFBR;
255         MOVE SFBR to DSA0;
256         MOVE SCRATCHD1 to SFBR;
257         MOVE SFBR to DSA1;
258         MOVE SCRATCHD2 to SFBR;
259         MOVE SFBR to DSA2;
260         MOVE SCRATCHD3 to SFBR;
261         MOVE SFBR to DSA3;
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;
275 ignore_cmd:
276         MOVE SCRATCHD0 to SFBR; restore scheduler DSA
277         MOVE SFBR to DSA0;
278         MOVE SCRATCHD1 to SFBR;
279         MOVE SFBR to DSA1;
280         MOVE SCRATCHD2 to SFBR;
281         MOVE SFBR to DSA2;
282         MOVE SCRATCHD3 to SFBR;
283         MOVE SFBR to DSA3;
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
292 cmdr0:
293         MOVE 0xff to SCRATCHD0; correct value will be patched by driver
294 cmdr1:
295         MOVE 0xff to SCRATCHD1;
296 cmdr2:
297         MOVE 0xff to SCRATCHD2;
298 cmdr3:
299         MOVE 0xff to SCRATCHD3;
300         MOVE 0x00 to SCRATCHE0;
301 handle_cmd:
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"
318 led_on1:
319         NOP;
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
324         SET ATN;
325         CLEAR ACK;
326 msgout:
327         MOVE FROM t_msg_out, WHEN MSG_OUT;
328         CLEAR ATN;
329         JUMP REL(waitphase);
332 handle_sdp:
333         CLEAR ACK;
334         MOVE SCRATCHC0 | f_c_sdp TO SCRATCHC0;
335         ; should get a disconnect message now
336 msgin:
337         CLEAR ATN
338         MOVE FROM t_msg_in, WHEN MSG_IN;
339 handle_msgin:
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);
354 cmdout:
355         MOVE FROM t_cmd, WHEN CMD;
356         JUMP REL(waitphase);
357 status:
358         MOVE FROM t_status, WHEN STATUS;
359         MOVE SFBR TO SCRATCHE1;
360         JUMP REL(waitphase);
361 datain:
362         CALL REL(savedsa);
363         MOVE SCRATCHC0 | f_c_data TO SCRATCHC0;
364         datain_loop:
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;
374         JUMP REL(waitphase);
376 dataout:
377         CALL REL(savedsa);
378         MOVE SCRATCHC0 | f_c_data TO SCRATCHC0;
379 dataout_loop:
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;
389         JUMP REL(waitphase);
391 savedsa:
392         MOVE DSA0 to SFBR;
393         MOVE SFBR to SCRATCHB0;
394         MOVE DSA1 to SFBR;
395         MOVE SFBR to SCRATCHB1;
396         MOVE DSA2 to SFBR;
397         MOVE SFBR to SCRATCHB2;
398         MOVE DSA3 to SFBR;
399         MOVE SFBR to SCRATCHB3;
400         RETURN;
402 restoredsa:
403         MOVE SCRATCHB0 TO SFBR;
404         MOVE SFBR TO DSA0;
405         MOVE SCRATCHB1 TO SFBR;
406         MOVE SFBR TO DSA1;
407         MOVE SCRATCHB2 TO SFBR;
408         MOVE SFBR TO DSA2;
409         MOVE SCRATCHB3 TO SFBR;
410         MOVE SFBR TO DSA3;
411         RETURN;
413 disconnect:
414         MOVE SCNTL2 & 0x7f TO SCNTL2;
415         CLEAR ATN;
416         CLEAR ACK;
417         WAIT DISCONNECT;
418         RETURN;
420 handle_extin:
421         CLEAR ACK;
422         MOVE FROM t_ext_msg_in, WHEN MSG_IN;
423         INT int_extmsgin; /* let host fill in t_ext_msg_data */
424 get_extmsgdata:
425         CLEAR ACK;
426         MOVE FROM t_ext_msg_data, WHEN MSG_IN;
427         INT int_extmsgdata;
429 PROC esiop_led_on:
430         MOVE GPREG & 0xfe TO GPREG;
432 PROC esiop_led_off:
433         MOVE GPREG | 0x01 TO GPREG;