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