7ae5c097e5
Install the core of the scheduler in main script (so it's in RAM when there is one), and avoid jump in the common case. The command part of the scheduler now lives in host memory, with tables. Add template for a tag switch.
409 lines
11 KiB
Scheme
409 lines
11 KiB
Scheme
; $NetBSD: siop.ss,v 1.12 2000/10/23 14:53:53 bouyer Exp $
|
|
|
|
;
|
|
; Copyright (c) 2000 Manuel Bouyer.
|
|
;
|
|
; Redistribution and use in source and binary forms, with or without
|
|
; modification, are permitted provided that the following conditions
|
|
; are met:
|
|
; 1. Redistributions of source code must retain the above copyright
|
|
; notice, this list of conditions and the following disclaimer.
|
|
; 2. Redistributions in binary form must reproduce the above copyright
|
|
; notice, this list of conditions and the following disclaimer in the
|
|
; documentation and/or other materials provided with the distribution.
|
|
; 3. All advertising materials mentioning features or use of this software
|
|
; must display the following acknowledgement:
|
|
; This product includes software developed by Manuel Bouyer
|
|
; 4. The name of the author may not be used to endorse or promote products
|
|
; derived from this software without specific prior written permission.
|
|
;
|
|
; THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
; IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
; OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
; IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
; INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
; NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
; THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
ARCH 720
|
|
|
|
; offsets in sym_xfer
|
|
ABSOLUTE t_id = 24;
|
|
ABSOLUTE t_msg_in = 32;
|
|
ABSOLUTE t_ext_msg_in = 40;
|
|
ABSOLUTE t_ext_msg_data = 48;
|
|
ABSOLUTE t_msg_out = 56;
|
|
ABSOLUTE t_cmd = 64;
|
|
ABSOLUTE t_status = 72;
|
|
ABSOLUTE t_data = 80;
|
|
|
|
;; interrupt codes
|
|
; interrupts that need a valid DSA
|
|
ABSOLUTE int_done = 0xff00;
|
|
ABSOLUTE int_msgin = 0xff01;
|
|
ABSOLUTE int_extmsgin = 0xff02;
|
|
ABSOLUTE int_extmsgdata = 0xff03;
|
|
ABSOLUTE int_disc = 0xff04;
|
|
; interrupts that don't have a valid DSA
|
|
ABSOLUTE int_reseltarg = 0xff80;
|
|
ABSOLUTE int_resellun = 0xff81;
|
|
ABSOLUTE int_reseltag = 0xff82;
|
|
ABSOLUTE int_resfail = 0xff83;
|
|
ABSOLUTE int_err = 0xffff;
|
|
|
|
; flags for scratcha0
|
|
ABSOLUTE flag_sdp = 0x01 ; got save data pointer
|
|
ABSOLUTE flag_data = 0x02 ; we're in data phase
|
|
ABSOLUTE flag_data_mask = 0xfd ; ~flag_data
|
|
|
|
; main script symbols
|
|
|
|
ENTRY waitphase;
|
|
ENTRY send_msgout;
|
|
ENTRY msgout;
|
|
ENTRY msgin;
|
|
ENTRY handle_msgin;
|
|
ENTRY msgin_ack;
|
|
ENTRY dataout;
|
|
ENTRY datain;
|
|
ENTRY cmdout;
|
|
ENTRY status;
|
|
ENTRY disconnect;
|
|
ENTRY reselect;
|
|
ENTRY reselected;
|
|
ENTRY selected;
|
|
ENTRY script_sched;
|
|
ENTRY script_sched_slot0;
|
|
ENTRY get_extmsgdata;
|
|
ENTRY resel_targ0;
|
|
ENTRY msgin_space;
|
|
ENTRY lunsw_return;
|
|
EXTERN abs_script_sched_slot0;
|
|
EXTERN abs_targ0;
|
|
EXTERN abs_msgin;
|
|
|
|
; lun switch symbols
|
|
ENTRY lun_switch_entry;
|
|
ENTRY resel_lun0;
|
|
ENTRY restore_scntl3;
|
|
EXTERN abs_lunsw_return;
|
|
|
|
; tag switch symbols
|
|
ENTRY tag_switch_entry;
|
|
ENTRY resel_tag0;
|
|
EXTERN abs_tag0;
|
|
|
|
; command reselect script symbols
|
|
ENTRY rdsa0;
|
|
ENTRY rdsa1;
|
|
ENTRY rdsa2;
|
|
ENTRY rdsa3;
|
|
ENTRY ldsa_reload_dsa;
|
|
ENTRY ldsa_select;
|
|
ENTRY ldsa_data;
|
|
|
|
EXTERN ldsa_abs_reselected;
|
|
EXTERN ldsa_abs_reselect;
|
|
EXTERN ldsa_abs_selected;
|
|
EXTERN ldsa_abs_data;
|
|
EXTERN ldsa_abs_slot;
|
|
|
|
; main script
|
|
|
|
PROC siop_script:
|
|
|
|
reselected:
|
|
; starting a new session, init 'local variables'
|
|
MOVE 0 to SCRATCHA0 ; flags
|
|
MOVE 0 to SCRATCHA1 ; DSA offset (for S/G save data pointer)
|
|
MOVE SCRATCHA3 to SFBR ; pending message ?
|
|
JUMP REL(handle_msgin), IF not 0x20;
|
|
waitphase:
|
|
JUMP REL(msgout), WHEN MSG_OUT;
|
|
JUMP REL(msgin), WHEN MSG_IN;
|
|
JUMP REL(dataout), WHEN DATA_OUT;
|
|
JUMP REL(datain), WHEN DATA_IN;
|
|
JUMP REL(cmdout), WHEN CMD;
|
|
JUMP REL(status), WHEN STATUS;
|
|
INT int_err;
|
|
|
|
reselect_fail:
|
|
; check that host asserted SIGP, this'll clear SIGP in ISTAT
|
|
MOVE CTEST2 & 0x40 TO SFBR;
|
|
INT int_resfail, IF 0x00;
|
|
script_sched:
|
|
; Clear DSA and init status
|
|
MOVE 0xff to DSA0;
|
|
MOVE 0xff to DSA1;
|
|
MOVE 0xff to DSA2;
|
|
MOVE 0xff to DSA3;
|
|
MOVE 0 to SCRATCHA0 ; flags
|
|
MOVE 0 to SCRATCHA1 ; DSA offset (for S/G save data pointer)
|
|
; the script scheduler: siop_start() we set the absolute jump addr, and then
|
|
; changes the FALSE to TRUE. The select script will change it back to false
|
|
; once the target is selected.
|
|
; The RAM could hold 370 slot entry, we limit it to 40. Should be more than
|
|
; enouth.
|
|
script_sched_slot0:
|
|
JUMP abs_script_sched_slot0, IF FALSE;
|
|
JUMP abs_script_sched_slot0, IF FALSE;
|
|
JUMP abs_script_sched_slot0, IF FALSE;
|
|
JUMP abs_script_sched_slot0, IF FALSE;
|
|
JUMP abs_script_sched_slot0, IF FALSE;
|
|
JUMP abs_script_sched_slot0, IF FALSE;
|
|
JUMP abs_script_sched_slot0, IF FALSE;
|
|
JUMP abs_script_sched_slot0, IF FALSE;
|
|
JUMP abs_script_sched_slot0, IF FALSE;
|
|
JUMP abs_script_sched_slot0, IF FALSE;
|
|
JUMP abs_script_sched_slot0, IF FALSE;
|
|
JUMP abs_script_sched_slot0, IF FALSE;
|
|
JUMP abs_script_sched_slot0, IF FALSE;
|
|
JUMP abs_script_sched_slot0, IF FALSE;
|
|
JUMP abs_script_sched_slot0, IF FALSE;
|
|
JUMP abs_script_sched_slot0, IF FALSE;
|
|
JUMP abs_script_sched_slot0, IF FALSE;
|
|
JUMP abs_script_sched_slot0, IF FALSE;
|
|
JUMP abs_script_sched_slot0, IF FALSE;
|
|
JUMP abs_script_sched_slot0, IF FALSE;
|
|
JUMP abs_script_sched_slot0, IF FALSE;
|
|
JUMP abs_script_sched_slot0, IF FALSE;
|
|
JUMP abs_script_sched_slot0, IF FALSE;
|
|
JUMP abs_script_sched_slot0, IF FALSE;
|
|
JUMP abs_script_sched_slot0, IF FALSE;
|
|
JUMP abs_script_sched_slot0, IF FALSE;
|
|
JUMP abs_script_sched_slot0, IF FALSE;
|
|
JUMP abs_script_sched_slot0, IF FALSE;
|
|
JUMP abs_script_sched_slot0, IF FALSE;
|
|
JUMP abs_script_sched_slot0, IF FALSE;
|
|
JUMP abs_script_sched_slot0, IF FALSE;
|
|
JUMP abs_script_sched_slot0, IF FALSE;
|
|
JUMP abs_script_sched_slot0, IF FALSE;
|
|
JUMP abs_script_sched_slot0, IF FALSE;
|
|
JUMP abs_script_sched_slot0, IF FALSE;
|
|
JUMP abs_script_sched_slot0, IF FALSE;
|
|
JUMP abs_script_sched_slot0, IF FALSE;
|
|
JUMP abs_script_sched_slot0, IF FALSE;
|
|
JUMP abs_script_sched_slot0, IF FALSE;
|
|
JUMP abs_script_sched_slot0, IF FALSE;
|
|
; Nothing to do, wait for reselect
|
|
reselect:
|
|
; Clear DSA and init status
|
|
MOVE 0xff to DSA0;
|
|
MOVE 0xff to DSA1;
|
|
MOVE 0xff to DSA2;
|
|
MOVE 0xff to DSA3;
|
|
MOVE 0x00 to SCRATCHA2; no tag
|
|
MOVE 0x20 to SCRATCHA3; simple tag msg, ignored by reselected:
|
|
WAIT RESELECT REL(reselect_fail)
|
|
MOVE SSID & 0x8f to SFBR
|
|
MOVE SFBR to SCRATCHA0 ; save reselect ID
|
|
; find the rigth param for this target
|
|
resel_targ0:
|
|
JUMP abs_targ0, IF 0xff;
|
|
JUMP abs_targ0, IF 0xff;
|
|
JUMP abs_targ0, IF 0xff;
|
|
JUMP abs_targ0, IF 0xff;
|
|
JUMP abs_targ0, IF 0xff;
|
|
JUMP abs_targ0, IF 0xff;
|
|
JUMP abs_targ0, IF 0xff;
|
|
JUMP abs_targ0, IF 0xff;
|
|
JUMP abs_targ0, IF 0xff;
|
|
JUMP abs_targ0, IF 0xff;
|
|
JUMP abs_targ0, IF 0xff;
|
|
JUMP abs_targ0, IF 0xff;
|
|
JUMP abs_targ0, IF 0xff;
|
|
JUMP abs_targ0, IF 0xff;
|
|
JUMP abs_targ0, IF 0xff;
|
|
INT int_reseltarg;
|
|
lunsw_return:
|
|
MOVE 1, abs_msgin, WHEN MSG_IN;
|
|
MOVE SFBR & 0x07 to SCRATCHA1; save LUN
|
|
CLEAR ACK;
|
|
RETURN, WHEN NOT MSG_IN; If no more message, jump to lun sw
|
|
MOVE 1, abs_msgin, WHEN MSG_IN;
|
|
CLEAR ACK;
|
|
MOVE SFBR to SCRATCHA3; save message
|
|
RETURN, IF NOT 0x20; jump to lun sw if not simple tag msg
|
|
MOVE 1, abs_msgin, WHEN MSG_IN; get tag
|
|
CLEAR ACK;
|
|
MOVE SFBR to SCRATCHA2; save tag
|
|
RETURN; jump to lun sw
|
|
|
|
handle_sdp:
|
|
CLEAR ACK;
|
|
MOVE SCRATCHA0 | flag_sdp TO SCRATCHA0;
|
|
; should get a disconnect message now
|
|
msgin:
|
|
CLEAR ATN
|
|
MOVE FROM t_msg_in, WHEN MSG_IN;
|
|
handle_msgin:
|
|
JUMP REL(handle_cmpl), IF 0x00 ; command complete message
|
|
JUMP REL(handle_sdp), IF 0x02 ; save data pointer message
|
|
JUMP REL(handle_extin), IF 0x01 ; extended message
|
|
INT int_msgin, IF not 0x04;
|
|
CALL REL(disconnect) ; disconnect message;
|
|
; if we didn't get sdp, or if offset is 0, no need to interrupt
|
|
MOVE SCRATCHA0 & flag_sdp TO SFBR;
|
|
JUMP REL(script_sched), if 0x00;
|
|
MOVE SCRATCHA1 TO SFBR;
|
|
JUMP REL(script_sched), if 0x00;
|
|
; Ok, we need to save data pointers
|
|
INT int_disc;
|
|
msgin_ack:
|
|
selected:
|
|
CLEAR ACK;
|
|
JUMP REL(waitphase);
|
|
|
|
; entry point for msgout after a msgin or status phase
|
|
send_msgout:
|
|
SET ATN;
|
|
CLEAR ACK;
|
|
msgout:
|
|
MOVE FROM t_msg_out, WHEN MSG_OUT;
|
|
CLEAR ATN;
|
|
JUMP REL(waitphase);
|
|
cmdout:
|
|
MOVE FROM t_cmd, WHEN CMD;
|
|
JUMP REL(waitphase);
|
|
status:
|
|
MOVE FROM t_status, WHEN STATUS;
|
|
JUMP REL(waitphase);
|
|
datain:
|
|
CALL REL(savedsa);
|
|
MOVE SCRATCHA0 | flag_data TO SCRATCHA0;
|
|
datain_loop:
|
|
MOVE FROM t_data, WHEN DATA_IN;
|
|
MOVE SCRATCHA1 + 1 TO SCRATCHA1 ; adjust offset
|
|
MOVE DSA0 + 8 to DSA0;
|
|
MOVE DSA1 + 0 to DSA1 WITH CARRY;
|
|
MOVE DSA2 + 0 to DSA2 WITH CARRY;
|
|
MOVE DSA3 + 0 to DSA3 WITH CARRY;
|
|
JUMP REL(datain_loop), WHEN DATA_IN;
|
|
CALL REL(restoredsa);
|
|
MOVE SCRATCHA0 & flag_data_mask TO SCRATCHA0;
|
|
JUMP REL(waitphase);
|
|
|
|
dataout:
|
|
CALL REL(savedsa);
|
|
MOVE SCRATCHA0 | flag_data TO SCRATCHA0;
|
|
dataout_loop:
|
|
MOVE FROM t_data, WHEN DATA_OUT;
|
|
MOVE SCRATCHA1 + 1 TO SCRATCHA1 ; adjust offset
|
|
MOVE DSA0 + 8 to DSA0;
|
|
MOVE DSA1 + 0 to DSA1 WITH CARRY;
|
|
MOVE DSA2 + 0 to DSA2 WITH CARRY;
|
|
MOVE DSA3 + 0 to DSA3 WITH CARRY;
|
|
JUMP REL(dataout_loop), WHEN DATA_OUT;
|
|
CALL REL(restoredsa);
|
|
MOVE SCRATCHA0 & flag_data_mask TO SCRATCHA0;
|
|
JUMP REL(waitphase);
|
|
|
|
savedsa:
|
|
MOVE DSA0 to SFBR;
|
|
MOVE SFBR to SCRATCHB0;
|
|
MOVE DSA1 to SFBR;
|
|
MOVE SFBR to SCRATCHB1;
|
|
MOVE DSA2 to SFBR;
|
|
MOVE SFBR to SCRATCHB2;
|
|
MOVE DSA3 to SFBR;
|
|
MOVE SFBR to SCRATCHB3;
|
|
RETURN;
|
|
|
|
restoredsa:
|
|
MOVE SCRATCHB0 TO SFBR;
|
|
MOVE SFBR TO DSA0;
|
|
MOVE SCRATCHB1 TO SFBR;
|
|
MOVE SFBR TO DSA1;
|
|
MOVE SCRATCHB2 TO SFBR;
|
|
MOVE SFBR TO DSA2;
|
|
MOVE SCRATCHB3 TO SFBR;
|
|
MOVE SFBR TO DSA3;
|
|
RETURN;
|
|
|
|
disconnect:
|
|
MOVE SCNTL2 & 0x7f TO SCNTL2;
|
|
CLEAR ATN;
|
|
CLEAR ACK;
|
|
WAIT DISCONNECT;
|
|
RETURN;
|
|
|
|
handle_cmpl:
|
|
CALL REL(disconnect);
|
|
INT int_done;
|
|
|
|
handle_extin:
|
|
CLEAR ACK;
|
|
MOVE FROM t_ext_msg_in, WHEN MSG_IN;
|
|
INT int_extmsgin; /* let host fill in t_ext_msg_data */
|
|
get_extmsgdata:
|
|
CLEAR ACK;
|
|
MOVE FROM t_ext_msg_data, WHEN MSG_IN;
|
|
INT int_extmsgdata;
|
|
msgin_space:
|
|
NOP; space to store msgin when reselect
|
|
|
|
|
|
;; per-target switch script for LUNs
|
|
; hack: we first do a call to the target-specific code, so that a return
|
|
; in the main switch will jump to the lun switch.
|
|
PROC lun_switch:
|
|
restore_scntl3:
|
|
MOVE 0xff TO SCNTL3;
|
|
MOVE 0xff TO SXFER;
|
|
JUMP abs_lunsw_return;
|
|
lun_switch_entry:
|
|
CALL REL(restore_scntl3);
|
|
MOVE SCRATCHA1 TO SFBR;
|
|
resel_lun0:
|
|
INT int_resellun;
|
|
|
|
;; Per-device switch script for tag
|
|
PROC tag_switch:
|
|
tag_switch_entry:
|
|
MOVE SCRATCHA2 TO SFBR; restore tag
|
|
resel_tag0:
|
|
JUMP abs_tag0, IF 0x00;
|
|
JUMP abs_tag0, IF 0x01;
|
|
JUMP abs_tag0, IF 0x02;
|
|
JUMP abs_tag0, IF 0x03;
|
|
JUMP abs_tag0, IF 0x04;
|
|
JUMP abs_tag0, IF 0x05;
|
|
JUMP abs_tag0, IF 0x06;
|
|
JUMP abs_tag0, IF 0x07;
|
|
JUMP abs_tag0, IF 0x08;
|
|
JUMP abs_tag0, IF 0x09;
|
|
JUMP abs_tag0, IF 0x0a;
|
|
JUMP abs_tag0, IF 0x0b;
|
|
JUMP abs_tag0, IF 0x0c;
|
|
JUMP abs_tag0, IF 0x0d;
|
|
JUMP abs_tag0, IF 0x0e;
|
|
JUMP abs_tag0, IF 0x0f;
|
|
INT int_reseltag;
|
|
|
|
;; per-command script: select, and called after a reselect to load DSA
|
|
|
|
PROC load_dsa:
|
|
; Can't use MOVE MEMORY to load DSA, doesn't work I/O mapped
|
|
rdsa0:
|
|
MOVE 0xf0 to DSA0;
|
|
rdsa1:
|
|
MOVE 0xf1 to DSA1;
|
|
rdsa2:
|
|
MOVE 0xf2 to DSA2;
|
|
rdsa3:
|
|
MOVE 0xf3 to DSA3;
|
|
RETURN;
|
|
ldsa_reload_dsa:
|
|
CALL REL(rdsa0);
|
|
JUMP ldsa_abs_reselected;
|
|
ldsa_select:
|
|
CALL REL(rdsa0);
|
|
SELECT ATN FROM t_id, ldsa_abs_reselect;
|
|
MOVE MEMORY 4, ldsa_abs_data, ldsa_abs_slot;
|
|
JUMP ldsa_abs_selected;
|
|
ldsa_data:
|
|
NOP; contains data used by the MOVE MEMORY
|