esiop.ss revision 1.7
1;	$NetBSD: esiop.ss,v 1.7 2002/04/23 20:41:16 bouyer Exp $
2
3;
4; Copyright (c) 2002 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. Neither the name of the University nor the names of its contributors
18;    may be used to endorse or promote products derived from this software
19;    without specific prior written permission.
20;
21; THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24; ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25; FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27; OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28; HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29; LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30; OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31; SUCH DAMAGE.
32;
33
34ARCH 825
35
36; offsets in siop_common_xfer
37ABSOLUTE t_id = 40;
38ABSOLUTE t_msg_in = 48;
39ABSOLUTE t_ext_msg_in = 56;
40ABSOLUTE t_ext_msg_data = 64;
41ABSOLUTE t_msg_out = 72;
42ABSOLUTE t_cmd = 80;
43ABSOLUTE t_status = 88;
44ABSOLUTE t_data = 96;
45
46; offsets in the per-target lun table
47ABSOLUTE target_id = 0x0;
48ABSOLUTE target_luntbl = 0x8;
49
50;; interrupt codes
51; interrupts that needs a valid target/lun/tag
52ABSOLUTE int_done	= 0xff00;
53ABSOLUTE int_msgin	= 0xff01;
54ABSOLUTE int_extmsgin	= 0xff02;
55ABSOLUTE int_extmsgdata	= 0xff03;
56ABSOLUTE int_disc	= 0xff04;
57; interrupts that don't have a valid I/T/Q
58ABSOLUTE int_resfail	= 0xff80;     
59ABSOLUTE int_err	= 0xffff;     
60
61; We use the various scratch[a-j] registers to keep internal status:
62
63; scratchA1: offset in data DSA (for save data pointer)
64; scratchB: save/restore DSA in data loop
65; scratchC: current target/lun/tag
66; scratchC0: flags
67ABSOLUTE f_c_target	= 0x01 ; target valid
68ABSOLUTE f_c_lun	= 0x02 ; lun valud
69ABSOLUTE f_c_tag	= 0x04 ; tag valid
70ABSOLUTE f_c_data	= 0x08 ; data I/O in progress
71ABSOLUTE f_c_data_mask	= 0xf7 ; ~f_c_data
72ABSOLUTE f_c_sdp	= 0x10 ; got save data pointer message
73; scratchC[1-3]: target/lun/tag
74
75; scratchD: current DSA in start cmd ring
76; scratchE0: index in start cmd ring
77ABSOLUTE ncmd_slots	= 64 ; number of slots in CMD ring
78; flags in a cmd slot
79ABSOLUTE f_cmd_free	= 0x01 ; this slot is free
80ABSOLUTE f_cmd_ignore	= 0x02 ; this slot is not free but don't start it
81; offsets in a cmd slot
82ABSOLUTE o_cmd_dsa	= 0; also holds f_cmd_*
83ABSOLUTE o_cmd_id	= 4;
84
85; SCRATCHE1: last status
86
87ENTRY reselect;
88ENTRY cmdr0;
89ENTRY cmdr1;
90ENTRY cmdr2;
91ENTRY cmdr3;
92ENTRY led_on1;
93ENTRY led_on2;
94ENTRY led_off;
95ENTRY status;
96ENTRY msgin;
97ENTRY msgin_ack;
98ENTRY get_extmsgdata;
99ENTRY send_msgout;
100ENTRY script_sched;
101ENTRY load_targtable;
102
103EXTERN tlq_offset;
104EXTERN abs_msgin2;
105
106PROC  esiop_script:
107
108no_cmd:
109	MOVE ISTAT & 0x10 TO SFBR;  pending done command ?
110	INTFLY 0, IF NOT 0x00; 
111reselect:
112	MOVE 0x00 TO SCRATCHA1;
113	MOVE 0x00 TO SCRATCHC0;
114	MOVE 0xff TO SCRATCHE1;
115; a NOP by default; patched with MOVE GPREG | 0x01 to GPREG on compile-time
116; option "SIOP_SYMLED"
117led_off:
118	NOP;
119	WAIT RESELECT REL(reselect_fail);
120; a NOP by default; patched with MOVE GPREG & 0xfe to GPREG on compile-time
121; option "SIOP_SYMLED"
122led_on2:
123        NOP;
124	MOVE SSID & 0x0f to SFBR;
125	MOVE SFBR to SCRATCHC1;
126	MOVE SCRATCHC0 | f_c_target to SCRATCHC0; save target
127	CLEAR CARRY;
128	MOVE SCRATCHC1 SHL SFBR;
129	MOVE SFBR SHL DSA0; target * 4 in dsa
130	MOVE 0x0 to DSA1;
131	MOVE 0x0 to DSA2;
132	MOVE 0x0 to DSA3;
133; load DSA for the target table
134load_targtable:
135	MOVE DSA0 + 0x00 to DSA0; host will patch 0x0 with base of table
136	MOVE DSA1 + 0x00 to DSA1 with carry;
137	MOVE DSA2 + 0x00 to DSA2 with carry;
138	MOVE DSA3 + 0x00 to DSA3 with carry; now dsa -> basetable + target * 4
139	LOAD DSA0, 4, FROM 0; now load DSA for this target
140	SELECT FROM target_id, REL(nextisn);
141nextisn:
142	MOVE 1, abs_msgin2, WHEN MSG_IN;
143	MOVE SFBR & 0x07 to SCRATCHC2;
144	MOVE SCRATCHC0 | f_c_lun to SCRATCHC0; save LUN
145	CLEAR ACK and CARRY;
146	MOVE SCRATCHC2 SHL SFBR; 
147	MOVE SFBR SHL SFBR; lun * 4
148	MOVE DSA0 + SFBR TO DSA0;
149	MOVE DSA1 + 0x0 TO DSA1 with carry;
150	MOVE DSA2 + 0x0 TO DSA2 with carry;
151	MOVE DSA3 + 0x0 TO DSA3 with carry;
152	LOAD DSA0, 4, from target_luntbl; load DSA for this LUN
153	JUMP REL(waitphase), WHEN NOT MSG_IN;
154	MOVE 1, abs_msgin2, WHEN MSG_IN;
155	CLEAR ACK;
156	INT int_msgin, IF NOT 0x20; not a simple tag message, let host handle it
157	MOVE 1, abs_msgin2, WHEN MSG_IN; get tag
158	CLEAR ACK;
159	MOVE SFBR to SCRATCHA2;
160	MOVE SFBR to SCRATCHC3;
161	MOVE SCRATCHC0 | f_c_tag to SCRATCHC0; save TAG
162	MOVE 0x0 to SCRATCHA3;
163	CLEAR CARRY;
164	MOVE SCRATCHA2 SHL SCRATCHA2;
165	MOVE SCRATCHA3 SHL SCRATCHA3;
166	MOVE SCRATCHA2 SHL SCRATCHA2;
167	MOVE SCRATCHA3 SHL SCRATCHA3; TAG * 4 to SCRATCHA(2,3)
168	MOVE SCRATCHA2 TO SFBR;
169	MOVE DSA0 + SFBR TO DSA0;
170	MOVE DSA1 + 0x00 TO DSA1 with CARRY;
171	MOVE DSA2 + 0x00 TO DSA2 with CARRY;
172	MOVE DSA3 + 0x00 TO DSA3 with CARRY;
173	MOVE SCRATCHA3 TO SFBR;
174	MOVE DSA1 + SFBR TO DSA1;
175	MOVE DSA2 + 0x00 TO DSA2 with CARRY;
176	MOVE DSA3 + 0x00 TO DSA3 with CARRY; SCRACHA(2,3) + DSA to DSA
177	LOAD DSA0, 4, from 0; load DSA for this tag
178	JUMP REL(waitphase);
179
180reselect_fail:
181	; check that host asserted SIGP, this'll clear SIGP in ISTAT
182	MOVE CTEST2 & 0x40 TO SFBR;
183	INT int_resfail,  IF 0x00;
184script_sched:
185; Load ring DSA
186	MOVE SCRATCHD0 to SFBR;
187	MOVE SFBR to DSA0;
188	MOVE SCRATCHD1 to SFBR;
189	MOVE SFBR to DSA1;
190	MOVE SCRATCHD2 to SFBR;
191	MOVE SFBR to DSA2;
192	MOVE SCRATCHD3 to SFBR;
193	MOVE SFBR to DSA3;
194	LOAD SCRATCHA0,4, from o_cmd_dsa; /* get flags */
195	MOVE SCRATCHA0 & f_cmd_free to SFBR;
196	JUMP REL(no_cmd), IF NOT 0x0;
197	MOVE SCRATCHA0 & f_cmd_ignore to SFBR;
198	JUMP REL(ignore_cmd), IF NOT 0x0;
199; this slot is busy, attempt to exec command
200	SELECT ATN FROM o_cmd_id, REL(reselect);
201; select either succeeded or timed out.
202; if timed out the STO interrupt will be posted at the first SCSI bus access
203; waiting for a valid phase, so we have to do it now. If not a MSG_OUT phase,
204; this is an error anyway (we selected with ATN)
205	INT int_err, WHEN NOT MSG_OUT;
206ignore_cmd:
207	MOVE SCRATCHE0 + 1 to SCRATCHE0;
208	MOVE SCRATCHD0 + 8 to SCRATCHD0; sizeof (esiop_cmd_slot)
209	MOVE SCRATCHD1 + 0 to SCRATCHD1 WITH CARRY;
210	MOVE SCRATCHD2 + 0 to SCRATCHD2 WITH CARRY;
211	MOVE SCRATCHD3 + 0 to SCRATCHD3 WITH CARRY;
212	MOVE SCRATCHE0 TO SFBR;
213	JUMP REL(handle_cmd), IF  NOT ncmd_slots;
214; reset pointers to beggining of area
215cmdr0:
216	MOVE 0xff to SCRATCHD0; correct value will be patched by driver
217cmdr1:
218	MOVE 0xff to SCRATCHD1;
219cmdr2:
220	MOVE 0xff to SCRATCHD2;
221cmdr3:
222	MOVE 0xff to SCRATCHD3;
223	MOVE 0x00 to SCRATCHE0;
224handle_cmd:
225	MOVE SCRATCHA0 | f_cmd_free to SCRATCHA0;
226	STORE noflush SCRATCHA0, 4, FROM o_cmd_dsa;
227	MOVE SCRATCHA0 & f_cmd_ignore to SFBR;
228	JUMP REL(script_sched), IF NOT 0x00; /* next command if ignore */
229
230; a NOP by default; patched with MOVE GPREG & 0xfe to GPREG on compile-time
231; option "SIOP_SYMLED"
232led_on1:
233	NOP;
234	LOAD DSA0, 4, FROM o_cmd_dsa; /* load new DSA */
235	MOVE DSA0 & 0xfe to DSA0; /* clear f_cmd_free */
236	MOVE 0x00 TO SCRATCHA1;
237	MOVE 0xff TO SCRATCHE1;
238	LOAD SCRATCHC0, 4, FROM tlq_offset;
239;we can now send our identify message
240send_msgout: ; entry point for msgout after a msgin or status phase
241	SET ATN;
242	CLEAR ACK;
243msgout: 
244        MOVE FROM t_msg_out, WHEN MSG_OUT;
245	CLEAR ATN;  
246	JUMP REL(waitphase);
247
248msgin_ack:
249	CLEAR ACK;
250waitphase:
251	JUMP REL(msgout), WHEN MSG_OUT;
252	JUMP REL(msgin), WHEN MSG_IN;
253	JUMP REL(dataout), WHEN DATA_OUT;
254	JUMP REL(datain), WHEN DATA_IN;
255	JUMP REL(cmdout), WHEN CMD;
256	JUMP REL(status), WHEN STATUS;
257	INT int_err;
258
259
260handle_sdp:
261	CLEAR ACK;
262	MOVE SCRATCHC0 | f_c_sdp TO SCRATCHC0;
263	; should get a disconnect message now
264msgin:
265	CLEAR ATN
266	MOVE FROM t_msg_in, WHEN MSG_IN;
267handle_msgin:
268	JUMP REL(handle_cmpl), IF 0x00	; command complete message
269	JUMP REL(handle_sdp), IF 0x02	; save data pointer message
270	JUMP REL(handle_extin), IF 0x01	; extended message
271	INT int_msgin, IF NOT 0x04;
272	CALL REL(disconnect)		; disconnect message
273; if we didn't get sdp, or if offset is 0, no need to interrupt
274	MOVE SCRATCHC0 & f_c_sdp TO SFBR;
275	JUMP REL(script_sched), if 0x00;
276	MOVE SCRATCHA1 TO SFBR;
277	JUMP REL(script_sched), if 0x00;
278; Ok, we need to save data pointers
279	INT int_disc;
280
281cmdout:
282        MOVE FROM t_cmd, WHEN CMD; 
283	JUMP REL(waitphase);
284status: 
285        MOVE FROM t_status, WHEN STATUS;
286	MOVE SFBR TO SCRATCHE1;
287	JUMP REL(waitphase);
288datain:
289        CALL REL(savedsa);
290	MOVE SCRATCHC0 | f_c_data TO SCRATCHC0;
291	datain_loop:
292	MOVE FROM t_data, WHEN DATA_IN;
293	MOVE SCRATCHA1 + 1 TO SCRATCHA1 ; adjust offset
294	MOVE DSA0 + 8 to DSA0;
295	MOVE DSA1 + 0 to DSA1 WITH CARRY;
296	MOVE DSA2 + 0 to DSA2 WITH CARRY;
297	MOVE DSA3 + 0 to DSA3 WITH CARRY;
298	JUMP REL(datain_loop), WHEN DATA_IN;
299	CALL REL(restoredsa);
300	MOVE SCRATCHC0 & f_c_data_mask TO SCRATCHC0;
301	JUMP REL(waitphase);
302
303dataout:
304        CALL REL(savedsa);
305	MOVE SCRATCHC0 | f_c_data TO SCRATCHC0;
306dataout_loop:
307	MOVE FROM t_data, WHEN DATA_OUT;
308	MOVE SCRATCHA1 + 1 TO SCRATCHA1 ; adjust offset
309	MOVE DSA0 + 8 to DSA0;
310	MOVE DSA1 + 0 to DSA1 WITH CARRY;
311	MOVE DSA2 + 0 to DSA2 WITH CARRY;
312	MOVE DSA3 + 0 to DSA3 WITH CARRY;
313	JUMP REL(dataout_loop), WHEN DATA_OUT;
314	CALL REL(restoredsa);
315	MOVE SCRATCHC0 & f_c_data_mask TO SCRATCHC0;
316	JUMP REL(waitphase);
317
318savedsa:
319        MOVE DSA0 to SFBR;
320	MOVE SFBR to SCRATCHB0;       
321	MOVE DSA1 to SFBR;
322	MOVE SFBR to SCRATCHB1;       
323	MOVE DSA2 to SFBR;
324	MOVE SFBR to SCRATCHB2;
325	MOVE DSA3 to SFBR;
326	MOVE SFBR to SCRATCHB3;
327	RETURN;
328
329restoredsa:
330	MOVE SCRATCHB0 TO SFBR;
331	MOVE SFBR TO DSA0;
332	MOVE SCRATCHB1 TO SFBR;
333	MOVE SFBR TO DSA1;
334	MOVE SCRATCHB2 TO SFBR;
335	MOVE SFBR TO DSA2;
336	MOVE SCRATCHB3 TO SFBR;       
337	MOVE SFBR TO DSA3;
338	RETURN;
339
340disconnect:
341        MOVE SCNTL2 & 0x7f TO SCNTL2;
342	CLEAR ATN;
343	CLEAR ACK;
344	WAIT DISCONNECT;
345	RETURN;
346
347handle_cmpl:
348	CALL REL(disconnect);
349	MOVE SCRATCHE1 to SFBR;
350	INT int_done, IF NOT 0x00; if status is not "done", let host handle it
351	MOVE ISTAT | 0x10 TO ISTAT; else signal that cmd is done in ISTAT
352	JUMP REL(script_sched); and attempt next command
353
354handle_extin:
355	CLEAR ACK;
356	MOVE FROM t_ext_msg_in, WHEN MSG_IN;
357	INT int_extmsgin; /* let host fill in t_ext_msg_data */
358get_extmsgdata:
359	CLEAR ACK;
360	MOVE FROM t_ext_msg_data, WHEN MSG_IN;
361	INT int_extmsgdata; 
362
363PROC esiop_led_on:
364	MOVE GPREG & 0xfe TO GPREG;
365
366PROC esiop_led_off:
367	MOVE GPREG | 0x01 TO GPREG;
368