esiop.ss revision 1.1
11.1Sbouyer;	$NetBSD: esiop.ss,v 1.1 2002/04/21 22:52:06 bouyer Exp $
21.1Sbouyer
31.1Sbouyer;
41.1Sbouyer; Copyright (c) 2002 Manuel Bouyer.
51.1Sbouyer;
61.1Sbouyer; Redistribution and use in source and binary forms, with or without
71.1Sbouyer; modification, are permitted provided that the following conditions
81.1Sbouyer; are met:
91.1Sbouyer; 1. Redistributions of source code must retain the above copyright
101.1Sbouyer;    notice, this list of conditions and the following disclaimer.
111.1Sbouyer; 2. Redistributions in binary form must reproduce the above copyright
121.1Sbouyer;    notice, this list of conditions and the following disclaimer in the
131.1Sbouyer;    documentation and/or other materials provided with the distribution.
141.1Sbouyer; 3. All advertising materials mentioning features or use of this software
151.1Sbouyer;    must display the following acknowledgement:
161.1Sbouyer;	This product includes software developed by the University of
171.1Sbouyer;	California, Berkeley and its contributors.
181.1Sbouyer; 4. Neither the name of the University nor the names of its contributors
191.1Sbouyer;    may be used to endorse or promote products derived from this software
201.1Sbouyer;    without specific prior written permission.
211.1Sbouyer;
221.1Sbouyer; THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
231.1Sbouyer; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
241.1Sbouyer; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
251.1Sbouyer; ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
261.1Sbouyer; FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
271.1Sbouyer; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
281.1Sbouyer; OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
291.1Sbouyer; HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
301.1Sbouyer; LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
311.1Sbouyer; OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
321.1Sbouyer; SUCH DAMAGE.
331.1Sbouyer;
341.1Sbouyer
351.1SbouyerARCH 825
361.1Sbouyer
371.1Sbouyer; offsets in sym_xfer
381.1SbouyerABSOLUTE t_id = 24;
391.1SbouyerABSOLUTE t_msg_in = 32;
401.1SbouyerABSOLUTE t_ext_msg_in = 40;
411.1SbouyerABSOLUTE t_ext_msg_data = 48;
421.1SbouyerABSOLUTE t_msg_out = 56;
431.1SbouyerABSOLUTE t_cmd = 64;
441.1SbouyerABSOLUTE t_status = 72;
451.1SbouyerABSOLUTE t_data = 80;
461.1Sbouyer
471.1Sbouyer; offsets in the per-target lun table
481.1SbouyerABSOLUTE target_id = 0x0;
491.1SbouyerABSOLUTE target_luntbl = 0x8;
501.1Sbouyer
511.1Sbouyer;; interrupt codes
521.1Sbouyer; interrupts that needs a valid target/lun/tag
531.1SbouyerABSOLUTE int_done	= 0xff00;
541.1SbouyerABSOLUTE int_msgin	= 0xff01;
551.1SbouyerABSOLUTE int_extmsgin	= 0xff02;
561.1SbouyerABSOLUTE int_extmsgdata	= 0xff03;
571.1SbouyerABSOLUTE int_disc	= 0xff04;
581.1Sbouyer; interrupts that don't have a valid I/T/Q
591.1SbouyerABSOLUTE int_resfail	= 0xff80;     
601.1SbouyerABSOLUTE int_err	= 0xffff;     
611.1Sbouyer
621.1Sbouyer; We use the various scratch[a-j] registers to keep internal status:
631.1Sbouyer
641.1Sbouyer; scratchA1: offset in data DSA (for save data pointer)
651.1Sbouyer; scratchB: save/restore DSA in data loop
661.1Sbouyer; scratchC: current target/lun/tag
671.1Sbouyer; scratchC0: flags
681.1SbouyerABSOLUTE f_c_target	= 0x01 ; target valid
691.1SbouyerABSOLUTE f_c_lun	= 0x02 ; lun valud
701.1SbouyerABSOLUTE f_c_tag	= 0x04 ; tag valid
711.1SbouyerABSOLUTE f_c_data	= 0x08 ; data I/O in progress
721.1SbouyerABSOLUTE f_c_data_mask	= 0xf7 ; ~f_c_data
731.1SbouyerABSOLUTE f_c_sdp	= 0x10 ; got save data pointer message
741.1Sbouyer; scratchC[1-3]: target/lun/tag
751.1Sbouyer
761.1Sbouyer; scratchD: current DSA in start cmd ring
771.1Sbouyer; scratchE0: index in start cmd ring
781.1SbouyerABSOLUTE ncmd_slots	= 64 ; number of slots in CMD ring
791.1Sbouyer; flags in a cmd slot
801.1SbouyerABSOLUTE f_cmd_free	= 0x01 ; this slot is free
811.1Sbouyer; offsets in a cmd slot
821.1SbouyerABSOLUTE o_cmd_dsa	= 0; also holds f_cmd_free
831.1SbouyerABSOLUTE o_cmd_id	= 4;
841.1Sbouyer
851.1Sbouyer; SCRATCHE1: last status
861.1Sbouyer
871.1SbouyerENTRY reselect;
881.1SbouyerENTRY ring_reset;
891.1SbouyerENTRY cmdr0;
901.1SbouyerENTRY cmdr1;
911.1SbouyerENTRY cmdr2;
921.1SbouyerENTRY cmdr3;
931.1SbouyerENTRY led_on1;
941.1SbouyerENTRY led_on2;
951.1SbouyerENTRY led_off;
961.1SbouyerENTRY status;
971.1SbouyerENTRY msgin;
981.1SbouyerENTRY msgin_ack;
991.1SbouyerENTRY get_extmsgdata;
1001.1SbouyerENTRY send_msgout;
1011.1SbouyerENTRY script_sched;
1021.1SbouyerENTRY load_targtable;
1031.1Sbouyer
1041.1SbouyerEXTERN tlq_offset;
1051.1SbouyerEXTERN abs_msgin2;
1061.1Sbouyer
1071.1SbouyerPROC  esiop_script:
1081.1Sbouyer
1091.1Sbouyerno_cmd:
1101.1Sbouyer	MOVE ISTAT & 0x10 TO SFBR;  pending done command ?
1111.1Sbouyer	INTFLY 0, IF NOT 0x00; 
1121.1Sbouyerreselect:
1131.1Sbouyer	MOVE 0x00 TO SCRATCHA1;
1141.1Sbouyer	MOVE 0x00 TO SCRATCHC0;
1151.1Sbouyer	MOVE 0xff TO SCRATCHE1;
1161.1Sbouyer; a NOP by default; patched with MOVE GPREG | 0x01 to GPREG on compile-time
1171.1Sbouyer; option "SIOP_SYMLED"
1181.1Sbouyerled_off:
1191.1Sbouyer	NOP;
1201.1Sbouyer	WAIT RESELECT REL(reselect_fail);
1211.1Sbouyer; a NOP by default; patched with MOVE GPREG & 0xfe to GPREG on compile-time
1221.1Sbouyer; option "SIOP_SYMLED"
1231.1Sbouyerled_on2:
1241.1Sbouyer        NOP;
1251.1Sbouyer	MOVE SSID & 0x0f to SFBR;
1261.1Sbouyer	MOVE SFBR to SCRATCHC1;
1271.1Sbouyer	MOVE SCRATCHC0 | f_c_target to SCRATCHC0; save target
1281.1Sbouyer	CLEAR CARRY;
1291.1Sbouyer	MOVE SCRATCHC1 SHL SFBR;
1301.1Sbouyer	MOVE SFBR SHL DSA0; target * 4
1311.1Sbouyer	MOVE 0x0 to DSA1;
1321.1Sbouyer	MOVE 0x0 to DSA2;
1331.1Sbouyer	MOVE 0x0 to DSA3;
1341.1Sbouyer; load DSA for the target table
1351.1Sbouyerload_targtable:
1361.1Sbouyer	MOVE DSA0 + 0x00 to DSA0;
1371.1Sbouyer	MOVE DSA1 + 0x00 to DSA1 with carry;
1381.1Sbouyer	MOVE DSA2 + 0x00 to DSA2 with carry;
1391.1Sbouyer	MOVE DSA3 + 0x00 to DSA3 with carry;
1401.1Sbouyer	LOAD DSA0, 4, FROM 0; now load DSA for this target
1411.1Sbouyer	SELECT FROM target_id, REL(nextisn);
1421.1Sbouyernextisn:
1431.1Sbouyer	MOVE 1, abs_msgin2, WHEN MSG_IN;
1441.1Sbouyer	MOVE SFBR & 0x07 to SCRATCHC2;
1451.1Sbouyer	MOVE SCRATCHC0 | f_c_lun to SCRATCHC0; save LUN
1461.1Sbouyer	CLEAR ACK and CARRY;
1471.1Sbouyer	MOVE SCRATCHC2 SHL SFBR; 
1481.1Sbouyer	MOVE SFBR SHL SFBR; target * 4
1491.1Sbouyer	MOVE DSA0 + SFBR TO DSA0;
1501.1Sbouyer	MOVE DSA1 + 0x0 TO DSA1 with carry;
1511.1Sbouyer	MOVE DSA2 + 0x0 TO DSA2 with carry;
1521.1Sbouyer	MOVE DSA3 + 0x0 TO DSA3 with carry;
1531.1Sbouyer	LOAD DSA0, 4, from target_luntbl; load DSA for ths LUN
1541.1Sbouyer	JUMP REL(waitphase);
1551.1Sbouyer
1561.1Sbouyerreselect_fail:
1571.1Sbouyer	; check that host asserted SIGP, this'll clear SIGP in ISTAT
1581.1Sbouyer	MOVE CTEST2 & 0x40 TO SFBR;
1591.1Sbouyer	INT int_resfail,  IF 0x00;
1601.1Sbouyerscript_sched:
1611.1Sbouyer; Load ring DSA
1621.1Sbouyer	MOVE SCRATCHD0 to SFBR;
1631.1Sbouyer	MOVE SFBR to DSA0;
1641.1Sbouyer	MOVE SCRATCHD1 to SFBR;
1651.1Sbouyer	MOVE SFBR to DSA1;
1661.1Sbouyer	MOVE SCRATCHD2 to SFBR;
1671.1Sbouyer	MOVE SFBR to DSA2;
1681.1Sbouyer	MOVE SCRATCHD3 to SFBR;
1691.1Sbouyer	MOVE SFBR to DSA3;
1701.1Sbouyer	LOAD SCRATCHA0,4, from o_cmd_dsa; /* get flags */
1711.1Sbouyer	MOVE SCRATCHA0 & f_cmd_free to SFBR;
1721.1Sbouyer	JUMP REL(no_cmd), IF NOT 0x0;
1731.1Sbouyer; this slot is busy, attempt to exec command
1741.1Sbouyer	SELECT ATN FROM o_cmd_id, REL(reselect);
1751.1Sbouyer; select either succeeded or timed out. In either case update ring pointer.
1761.1Sbouyer; if timed out the STO interrupt will be posted at the first SCSI bus access
1771.1Sbouyer; waiting for a valid phase.
1781.1Sbouyer	MOVE SCRATCHE0 + 1 to SFBR;
1791.1Sbouyer	MOVE SFBR to SCRATCHE0;
1801.1Sbouyer	JUMP REL(ring_reset), IF ncmd_slots;
1811.1Sbouyer	MOVE SCRATCHD0 + 8 to SCRATCHD0; sizeof (esiop_cmd_slot)
1821.1Sbouyer	MOVE SCRATCHD1 + 0 to SCRATCHD1 WITH CARRY;
1831.1Sbouyer	MOVE SCRATCHD2 + 0 to SCRATCHD2 WITH CARRY;
1841.1Sbouyer	MOVE SCRATCHD3 + 0 to SCRATCHD3 WITH CARRY;
1851.1Sbouyer	JUMP REL(handle_cmd);
1861.1Sbouyerring_reset:
1871.1Sbouyercmdr0:
1881.1Sbouyer	MOVE 0xff to SCRATCHD0; correct value will be patched by driver
1891.1Sbouyercmdr1:
1901.1Sbouyer	MOVE 0xff to SCRATCHD1;
1911.1Sbouyercmdr2:
1921.1Sbouyer	MOVE 0xff to SCRATCHD2;
1931.1Sbouyercmdr3:
1941.1Sbouyer	MOVE 0xff to SCRATCHD3;
1951.1Sbouyer	MOVE 0x00 to SCRATCHE0;
1961.1Sbouyerhandle_cmd:
1971.1Sbouyer; a NOP by default; patched with MOVE GPREG & 0xfe to GPREG on compile-time
1981.1Sbouyer; option "SIOP_SYMLED"
1991.1Sbouyerled_on1:
2001.1Sbouyer	NOP;
2011.1Sbouyer	MOVE SCRATCHA0 | f_cmd_free to SCRATCHA0;
2021.1Sbouyer	STORE noflush SCRATCHA0, 4, FROM o_cmd_dsa;
2031.1Sbouyer	LOAD DSA0, 4, FROM o_cmd_dsa; /* load new DSA */
2041.1Sbouyer	MOVE DSA0 & 0xfc to DSA0; /* clear flags */
2051.1Sbouyer	MOVE 0x00 TO SCRATCHA1;
2061.1Sbouyer	MOVE 0xff TO SCRATCHE1;
2071.1Sbouyer	LOAD SCRATCHC0, 4, FROM tlq_offset;
2081.1Sbouyermsgin_ack:
2091.1Sbouyer	CLEAR ACK;
2101.1Sbouyerwaitphase:
2111.1Sbouyer	JUMP REL(msgout), WHEN MSG_OUT;
2121.1Sbouyer	JUMP REL(msgin), WHEN MSG_IN;
2131.1Sbouyer	JUMP REL(dataout), WHEN DATA_OUT;
2141.1Sbouyer	JUMP REL(datain), WHEN DATA_IN;
2151.1Sbouyer	JUMP REL(cmdout), WHEN CMD;
2161.1Sbouyer	JUMP REL(status), WHEN STATUS;
2171.1Sbouyer	INT int_err;
2181.1Sbouyer
2191.1Sbouyer; entry point for msgout after a msgin or status phase
2201.1Sbouyersend_msgout: 
2211.1Sbouyer	SET ATN;
2221.1Sbouyer	CLEAR ACK;
2231.1Sbouyermsgout: 
2241.1Sbouyer        MOVE FROM t_msg_out, WHEN MSG_OUT;
2251.1Sbouyer	CLEAR ATN;  
2261.1Sbouyer	JUMP REL(waitphase);
2271.1Sbouyer
2281.1Sbouyerhandle_sdp:
2291.1Sbouyer	CLEAR ACK;
2301.1Sbouyer	MOVE SCRATCHC0 | f_c_sdp TO SCRATCHC0;
2311.1Sbouyer	; should get a disconnect message now
2321.1Sbouyermsgin:
2331.1Sbouyer	CLEAR ATN
2341.1Sbouyer	MOVE FROM t_msg_in, WHEN MSG_IN;
2351.1Sbouyerhandle_msgin:
2361.1Sbouyer	JUMP REL(handle_cmpl), IF 0x00	; command complete message
2371.1Sbouyer	JUMP REL(handle_sdp), IF 0x02	; save data pointer message
2381.1Sbouyer	JUMP REL(handle_extin), IF 0x01	; extended message
2391.1Sbouyer	INT int_msgin, IF NOT 0x04;
2401.1Sbouyer	CALL REL(disconnect)		; disconnect message
2411.1Sbouyer; if we didn't get sdp, or if offset is 0, no need to interrupt
2421.1Sbouyer	MOVE SCRATCHC0 & f_c_sdp TO SFBR;
2431.1Sbouyer	JUMP REL(script_sched), if 0x00;
2441.1Sbouyer	MOVE SCRATCHA1 TO SFBR;
2451.1Sbouyer	JUMP REL(script_sched), if 0x00;
2461.1Sbouyer; Ok, we need to save data pointers
2471.1Sbouyer	INT int_disc;
2481.1Sbouyer
2491.1Sbouyercmdout:
2501.1Sbouyer        MOVE FROM t_cmd, WHEN CMD; 
2511.1Sbouyer	JUMP REL(waitphase);
2521.1Sbouyerstatus: 
2531.1Sbouyer        MOVE FROM t_status, WHEN STATUS;
2541.1Sbouyer	MOVE SFBR TO SCRATCHE1;
2551.1Sbouyer	JUMP REL(waitphase);
2561.1Sbouyerdatain:
2571.1Sbouyer        CALL REL(savedsa);
2581.1Sbouyer	MOVE SCRATCHC0 | f_c_data TO SCRATCHC0;
2591.1Sbouyer	datain_loop:
2601.1Sbouyer	MOVE FROM t_data, WHEN DATA_IN;
2611.1Sbouyer	MOVE SCRATCHA1 + 1 TO SCRATCHA1 ; adjust offset
2621.1Sbouyer	MOVE DSA0 + 8 to DSA0;
2631.1Sbouyer	MOVE DSA1 + 0 to DSA1 WITH CARRY;
2641.1Sbouyer	MOVE DSA2 + 0 to DSA2 WITH CARRY;
2651.1Sbouyer	MOVE DSA3 + 0 to DSA3 WITH CARRY;
2661.1Sbouyer	JUMP REL(datain_loop), WHEN DATA_IN;
2671.1Sbouyer	CALL REL(restoredsa);
2681.1Sbouyer	MOVE SCRATCHC0 & f_c_data_mask TO SCRATCHC0;
2691.1Sbouyer	JUMP REL(waitphase);
2701.1Sbouyer
2711.1Sbouyerdataout:
2721.1Sbouyer        CALL REL(savedsa);
2731.1Sbouyer	MOVE SCRATCHC0 | f_c_data TO SCRATCHC0;
2741.1Sbouyerdataout_loop:
2751.1Sbouyer	MOVE FROM t_data, WHEN DATA_OUT;
2761.1Sbouyer	MOVE SCRATCHA1 + 1 TO SCRATCHA1 ; adjust offset
2771.1Sbouyer	MOVE DSA0 + 8 to DSA0;
2781.1Sbouyer	MOVE DSA1 + 0 to DSA1 WITH CARRY;
2791.1Sbouyer	MOVE DSA2 + 0 to DSA2 WITH CARRY;
2801.1Sbouyer	MOVE DSA3 + 0 to DSA3 WITH CARRY;
2811.1Sbouyer	JUMP REL(dataout_loop), WHEN DATA_OUT;
2821.1Sbouyer	CALL REL(restoredsa);
2831.1Sbouyer	MOVE SCRATCHC0 & f_c_data_mask TO SCRATCHC0;
2841.1Sbouyer	JUMP REL(waitphase);
2851.1Sbouyer
2861.1Sbouyersavedsa:
2871.1Sbouyer        MOVE DSA0 to SFBR;
2881.1Sbouyer	MOVE SFBR to SCRATCHB0;       
2891.1Sbouyer	MOVE DSA1 to SFBR;
2901.1Sbouyer	MOVE SFBR to SCRATCHB1;       
2911.1Sbouyer	MOVE DSA2 to SFBR;
2921.1Sbouyer	MOVE SFBR to SCRATCHB2;
2931.1Sbouyer	MOVE DSA3 to SFBR;
2941.1Sbouyer	MOVE SFBR to SCRATCHB3;
2951.1Sbouyer	RETURN;
2961.1Sbouyer
2971.1Sbouyerrestoredsa:
2981.1Sbouyer	MOVE SCRATCHB0 TO SFBR;
2991.1Sbouyer	MOVE SFBR TO DSA0;
3001.1Sbouyer	MOVE SCRATCHB1 TO SFBR;
3011.1Sbouyer	MOVE SFBR TO DSA1;
3021.1Sbouyer	MOVE SCRATCHB2 TO SFBR;
3031.1Sbouyer	MOVE SFBR TO DSA2;
3041.1Sbouyer	MOVE SCRATCHB3 TO SFBR;       
3051.1Sbouyer	MOVE SFBR TO DSA3;
3061.1Sbouyer	RETURN;
3071.1Sbouyer
3081.1Sbouyerdisconnect:
3091.1Sbouyer        MOVE SCNTL2 & 0x7f TO SCNTL2;
3101.1Sbouyer	CLEAR ATN;
3111.1Sbouyer	CLEAR ACK;
3121.1Sbouyer	WAIT DISCONNECT;
3131.1Sbouyer	RETURN;
3141.1Sbouyer
3151.1Sbouyerhandle_cmpl:
3161.1Sbouyer	CALL REL(disconnect);
3171.1Sbouyer	MOVE SCRATCHE1 to SFBR;
3181.1Sbouyer	INT int_done, IF NOT 0x00; if status is not "done", let host handle it
3191.1Sbouyer	MOVE ISTAT | 0x10 TO ISTAT; else signal that cmd is done in ISTAT
3201.1Sbouyer	JUMP REL(script_sched); and attempt next command
3211.1Sbouyer
3221.1Sbouyerhandle_extin:
3231.1Sbouyer	CLEAR ACK;
3241.1Sbouyer	MOVE FROM t_ext_msg_in, WHEN MSG_IN;
3251.1Sbouyer	INT int_extmsgin; /* let host fill in t_ext_msg_data */
3261.1Sbouyerget_extmsgdata:
3271.1Sbouyer	CLEAR ACK;
3281.1Sbouyer	MOVE FROM t_ext_msg_data, WHEN MSG_IN;
3291.1Sbouyer	INT int_extmsgdata; 
330