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