summaryrefslogtreecommitdiff
path: root/sys/dev/microcode/siop/siop.ss
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/microcode/siop/siop.ss')
-rw-r--r--sys/dev/microcode/siop/siop.ss153
1 files changed, 153 insertions, 0 deletions
diff --git a/sys/dev/microcode/siop/siop.ss b/sys/dev/microcode/siop/siop.ss
new file mode 100644
index 00000000000..e7e6b61220f
--- /dev/null
+++ b/sys/dev/microcode/siop/siop.ss
@@ -0,0 +1,153 @@
+ARCH 720
+
+; offsets of sym_xfer
+ABSOLUTE t_id = 4;
+ABSOLUTE t_msg_in = 12;
+ABSOLUTE t_msg_out = 20;
+ABSOLUTE t_cmd = 28;
+ABSOLUTE t_status = 36;
+ABSOLUTE t_data = 44;
+
+;; interrupt codes
+ABSOLUTE int_done = 0xff00;
+ABSOLUTE int_msgin = 0xff01;
+ABSOLUTE int_resel = 0xff02;
+ABSOLUTE int_resfail = 0xff03;
+ABSOLUTE int_disc = 0xff04;
+ABSOLUTE int_err = 0xffff;
+
+; flags for scratcha0
+ABSOLUTE flag_sdp = 0x01 ; got save data pointer
+
+ENTRY waitphase;
+ENTRY select;
+ENTRY msgout;
+ENTRY msgin;
+ENTRY dataout;
+ENTRY datain;
+ENTRY cmdout;
+ENTRY status;
+ENTRY disconnect;
+ENTRY reselect;
+ENTRY reselected;
+ENTRY handle_reselect;
+
+PROC siop_script:
+
+select:
+ SELECT ATN FROM t_id, REL(reselect);
+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)
+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;
+err:
+ INT int_err;
+
+reselect:
+ WAIT RESELECT REL(reselect_fail)
+ MOVE SSID & 0x8f to SFBR
+ MOVE SFBR to SCRATCHA0 ; save reselect ID
+ INT int_err, WHEN NOT MSG_IN;
+ MOVE FROM t_msg_in, WHEN MSG_IN;
+ CLEAR ACK;
+ INT int_resel;
+
+reselect_fail:
+ INT int_resfail;
+
+msgin:
+ CLEAR ATN
+ MOVE FROM t_msg_in, WHEN MSG_IN;
+ JUMP REL(handle_dis), IF 0x04 ; disconnect message
+ JUMP REL(handle_cmpl), IF 0x00 ; command complete message
+ JUMP REL(handle_sdp), IF 0x02 ; save data pointer message
+ INT int_msgin;
+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);
+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);
+ JUMP REL(waitphase);
+
+dataout:
+ CALL REL(savedsa);
+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);
+ 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_dis:
+ CALL REL(disconnect);
+; if we didn't get sdp, or if offset is 0, no need to interrupt
+ MOVE SCRATCHA0 & flag_sdp TO SFBR;
+ JUMP REL(reselect), if 0x00;
+ MOVE SCRATCHA1 TO SFBR;
+ JUMP REL(reselect), if 0x00;
+; Ok, we need to save data pointers
+ INT int_disc;
+
+handle_cmpl:
+ CALL REL(disconnect);
+ INT int_done;
+handle_sdp:
+ CLEAR ACK;
+ MOVE SCRATCHA0 | flag_sdp TO SCRATCHA0;
+ JUMP REL(msgin) ; should get a disconnect message now