diff options
Diffstat (limited to 'sys/dev/microcode/siop/siop.ss')
| -rw-r--r-- | sys/dev/microcode/siop/siop.ss | 153 |
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 |
