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