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