mirror of
https://github.com/elliotnunn/mac-rom.git
synced 2025-01-01 11:29:27 +00:00
4325cdcc78
Resource forks are included only for .rsrc files. These are DeRezzed into their data fork. 'ckid' resources, from the Projector VCS, are not included. The Tools directory, containing mostly junk, is also excluded.
2141 lines
61 KiB
Plaintext
2141 lines
61 KiB
Plaintext
;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
;
|
|
; File: HALc96.a
|
|
;
|
|
; Contains: Hardware Abstraction Layer for the 53c96 machines (Quadra + Cyclone)
|
|
;
|
|
; Written by: Paul Wolf
|
|
;
|
|
; Copyright: © 1992-1993 by Apple Computer, Inc., all rights reserved.
|
|
;
|
|
;
|
|
; NOTES on HALc96
|
|
;
|
|
; This HAL is written assuming at least a 68020! If we ever have a 68000 machine with
|
|
; a 53c96 then we have to change a few things.
|
|
;
|
|
;
|
|
; Change History (most recent first):
|
|
;
|
|
; <SM33> 11/22/93 pdw Rolling in from <MCxx>.
|
|
; <MC7> 11/8/93 pdw Added some support for unexpected disconnect. Fixed a bug in
|
|
; the handling of the selected-as-target Curio bug.
|
|
; <MC6> 11/5/93 pdw Series of attempts and re-attempts to fix various VM/FileShare
|
|
; problems.
|
|
; <MC5> 10/28/93 pdw Trivial stuff.
|
|
; <SM32> 11/16/93 SAM Include HardwarePrivateEqu.a
|
|
; <SMG2> 9/29/93 chp Substitute a 68020 addressing mode when referencing G_JmpTbl.
|
|
; The HAL variables have expanded enough that the old 8-bit base
|
|
; displacement indexed addressing mode is not sufficient.
|
|
; <SM30> 10/29/93 pdw Fixing build - RecordCmd is being expanded in the ROM but not in
|
|
; the Init in SOME places.
|
|
; <SM29> 10/29/93 DCB Removing a bogus clear of the gotInt flag at the start of
|
|
; doInitiate and SCSISelect which caused a sync wait hang.
|
|
; <SM28> 10/14/93 pdw <MC> roll-in.
|
|
; <MC4> 10/12/93 pdw Fixed error reported on initiate w/too few message out bytes.
|
|
; <MC3> 10/12/93 pdw Added support for Synchronous data transfers, rewrote State
|
|
; Machine, message handling etc.
|
|
; <SM27> 9/26/93 DCB SCSI Reset was not clearing the FIFO. This led to some weird
|
|
; crashes if the reset interrupted something that had left data
|
|
; there. In particular SCSI CDBs were being send instead of
|
|
; identify messages. Yikes.
|
|
; <MC2> 9/26/93 pdw Changes to G_State usage from bit flags to enumeration and other
|
|
; stuff.
|
|
; <SM26> 9/12/93 pdw Comment changes. Changed post-ResetBus delay to 250mS instead
|
|
; of 500mS.
|
|
; <SM25> 9/9/93 pdw Lots of little changes. Name changes, temporary cache_bug
|
|
; stuff.
|
|
; <SM24> 8/13/93 pdw A lot of eieios, RecordRCMDs, reworked PutXferPhase/Disconnect
|
|
; stuff, rewrote SCSIComplete.
|
|
; <SM23> 7/19/93 pdw Fixed build.
|
|
; <SM22> 7/19/93 pdw Added an ENDIF to fix that build warning.
|
|
; <SM21> 7/17/93 pdw Lots of little things.
|
|
; <SM20> 6/29/93 pdw Massive checkins: Change asynchronicity mechanism to CallMachine
|
|
; stack switching mechanism. Adding support for Cold Fusion.
|
|
; Rearranging HW/SW Init code. Some code optimizations. Resolving
|
|
; with my Ludwig sources.
|
|
; <SM19> 5/25/93 DCB Rollin from Ludwig. (The next item below)
|
|
; <LW15> 5/21/93 PW Hopefully adding ability to handle being selected while we are
|
|
; trying to select.
|
|
; <SM18> 5/5/93 PW Converted names to meanies-friendly names. Updated with latest
|
|
; from Ludwig stuff.
|
|
; <LW14> 4/30/93 DCB Make DoHalInfo a separate function so it can be stuffed into a
|
|
; vector.
|
|
; <LW12> 4/14/93 DCB Added SetParity HALAction but left it disabled for now.
|
|
; <LW11> 3/26/93 PW Removed useless RejectMsg stuff.
|
|
; <SM17> 3/29/93 PW Removed rCF3 manipulations for PDM. Now I just set it up once in
|
|
; HWInit for threshold 8 or not.
|
|
; <SM16> 3/21/93 PW Removing useless RejectMsg stuff.
|
|
; <LW10> 3/8/93 PW Fixed another instance of c96-FIFO-stuck bug in DoCommand by
|
|
; checking not only for zero bytes but for 1 byte in FIFO after
|
|
; interrupt.
|
|
; <LW9> 2/17/93 PW Removed DoBitBucket and put it in HALc96Data.a instead.
|
|
; <SM15> 3/20/93 PW Removed some bogus PDM stuff that causes problems on non-PDMs.
|
|
; <SM14> 3/20/93 PW Removed DoBitBucket and put it in HALc96Data.a instead.
|
|
; <LW8> 2/3/93 PW Removed initCF1 munging before and after DoReset to fix reset
|
|
; blowing up bug.
|
|
; <SM13> 1/31/93 PW Update from the latest of Ludwig. Also changes required for PDM
|
|
; (will update Ludwig with these as needed myself).
|
|
; <LW7> 1/29/93 PW Passing HALg into SetupIOPB function.
|
|
; <LW6> 1/27/93 PW Playing around with some interrupt stuff. Changed HALaction
|
|
; events to include SR (for int level).
|
|
; <LW5> 1/27/93 PW Changed the name of InitDataPointer to InitDataStuff (since it's
|
|
; more general now). Changed intEnable and intDisable calling
|
|
; around - now I disable going into MyDT and enable coming out and
|
|
; I disable going into HALAction and enable coming out.
|
|
; <LW4> 1/8/93 PW Removed bogusing the phase and selectorID values in HALActionPB
|
|
; in ReadHALAction. This fixes the problem where RestorePointers
|
|
; action trashes phase so following SwitchPhase breaks. Also added
|
|
; fixes to Initiate to handle Reselect better - moved call to
|
|
; InitDataPointer to after select complete and flushed FIFO after
|
|
; checking for a second interrupt on a r_select. Also flushed FIFO
|
|
; after a select is complete (for targets which dont get all of
|
|
; the command bytes (i.e. IBM 160 with a $90 command).
|
|
; <LW3> 12/18/92 PW Really fix the hanging in vSyncWait after SCSICmd bug by
|
|
; clearing the G_State96 bits after Ck4SCSIInt sees the interrupt.
|
|
; <LW2> 12/15/92 DCB Fixed SCSICmd bug with DSP running or with caches disabled by
|
|
; not calling Wt4S if ck4int reveals an interrupt.
|
|
; <SM12> 12/9/92 PW Changed SCStats record name to SCResults. Rearranged DoCommand
|
|
; routine to fix some MORE bugs handling SCSISelAtn/SCSIMsgOut.
|
|
; <SM11> 12/9/92 PW Fixed SCSIMsgOut bug by changing DMA xfer count from 3 bytes to
|
|
; 2.
|
|
; <SM10> 12/5/92 PW Changed some names and fixed the DoReset routine so that it
|
|
; works when Reset interrupt reporting is on.
|
|
; <SM9> 11/12/92 PW Changed beq.s and bra.s to beq.w and bra.w to work when
|
|
; RECORD_rCMD is turned on.
|
|
; <SM8> 10/30/92 DCB Added Setup and Teardown routines to support Direct DMA into a
|
|
; user buffer
|
|
; <SM7> 10/8/92 PW Added GrossError checks. Some trivial name changes. Added test
|
|
; for out of bounds xferType. (cb) Fixed .w vs .l direction
|
|
; parameter bug in calling of StartDMA.
|
|
; <SM6> 9/11/92 DCB Rolled in Paul's fix for message out during initiate
|
|
; <SM5> 8/31/92 PW Changed register and command definitions to reflect changes to
|
|
; SCSIEqu53c96. Also added SelWAtnStop stuff to send 2 and 4 or
|
|
; more byte messages out in DoInitiate.
|
|
; <SM4> 8/30/92 PW Added DoAssertATN and fixed SendMsg bugs (it couldn't handle
|
|
; multiple-byte msg non-SelWAtn case).
|
|
; <SM3> 8/20/92 DCB Added Select w/o Atn and fixed SCSI Reset
|
|
; <SM2> 7/28/92 PW Resolved differences in sources.
|
|
; <SM1> 7/27/92 PW Initial check-in.
|
|
;
|
|
;____________________________________________________________________________________
|
|
|
|
|
|
MACHINE MC68020 ; '020-level
|
|
BLANKS ON ; assembler accepts spaces & tabs in operand field
|
|
PRINT OFF ; do not send subsequent lines to the listing file
|
|
; don't print includes
|
|
|
|
|
|
INCLUDE 'SysEqu.a'
|
|
wholeErrors equ 1
|
|
INCLUDE 'SysErr.a'
|
|
INCLUDE 'HardwarePrivateEqu.a'
|
|
INCLUDE 'Debug.a' ; for NAME macro
|
|
|
|
INCLUDE 'SCSI.a'
|
|
INCLUDE 'SCSIStandard.a'
|
|
INCLUDE 'SCSIEqu53c96.a'
|
|
INCLUDE 'ACAM.a'
|
|
INCLUDE 'SIMCoreEqu.a'
|
|
|
|
INCLUDE 'HALc96equ.a'
|
|
|
|
PRINT ON ; do send subsequent lines to the listing files
|
|
|
|
CASE OBJECT
|
|
|
|
IMPORT Xfer1Byte96, Wt4SCSIInt
|
|
IMPORT Ck4SCSIInt
|
|
IMPORT GetSelectInfo, GetReconnectInfo
|
|
|
|
IMPORT InitDataStuff
|
|
IMPORT GetHalInfo
|
|
|
|
IMPORT RecordEvent, Ck4DREQ
|
|
|
|
IMPORT AsmInit53c9xHW
|
|
IMPORT Disconnected, UnexpectedDisc
|
|
|
|
;====================================================================================
|
|
|
|
;************************************************************************************
|
|
;
|
|
; HALaction - main entry point for HAL (called by SIMCore)
|
|
;
|
|
; This routine gets handed 1 parameter on the stack - a pointer to a HALactionPB.
|
|
; It establishes the following register convention and then calls the requested action.
|
|
;
|
|
; A0 - current SCSI_IO parameter block ptr
|
|
; A3 - ptr to 53c96 base address
|
|
; A4 - ptr to the HALactionPB (passed in as parameter on stack)
|
|
; A5 - HALg (ptr to the HALglobals)
|
|
;
|
|
; These register conventions are used throughout the HAL. Any routine that uses
|
|
; any of these registers must save/restore them.There are no conventions for
|
|
; Dx registers.
|
|
;
|
|
; The action is specified in the HALactionPB.action parameter. We use the handy
|
|
; jump table to find and call the appropriate routine.
|
|
;
|
|
; When we return from the requested HALaction, the phase is checked to see if some
|
|
; additional work is needed before returning to the SIM. If Bus Free, then we need
|
|
; to do some housework associated with Disconnecting. If MsgIn phase, the we will go
|
|
; ahead and get the message for the SIM but we won't accept it unless we know what to
|
|
; do with it.
|
|
;
|
|
;====================================================================================
|
|
|
|
HALaction PROC EXPORT
|
|
;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
|
|
regsToSave REG D3-D7/A2-A5
|
|
numRegsToSave EQU 9
|
|
|
|
WITH HALactions
|
|
WITH HALc96GlobalRecord
|
|
WITH SCSIPhase
|
|
|
|
movem.l regsToSave, -(sp)
|
|
|
|
move.l numRegsToSave*4+4(sp), A4 ; get the one parameter from stack (HALactionPB)
|
|
move.l HALactionPB.HALstaticPtr(A4), A5 ; and get the staticPtr
|
|
|
|
; Initialize the values in the HALactionPB
|
|
|
|
clr.w HALactionPB.result(A4) ; assume noErr, Action will change if needed
|
|
|
|
; Get stuff out of PB into our world
|
|
|
|
move.l baseRegAddr(A5), A3 ; load A3 with base addr of 53c96
|
|
|
|
move.w HALactionPB.action(A4), D0 ; get Action from HALactionPB
|
|
|
|
cmp.w #kNumHALaction, D0 ; is scsiSelector higher than last one?
|
|
bhs.s @Unknown ; yes - unknown
|
|
|
|
move.l (G_JmpTbl, A5, D0.w*4), A1 ; get action routine from jump table
|
|
|
|
IF RECORD_ON THEN
|
|
pea 'HAL-'
|
|
move.b HALactionPB.action+1(A4), D3
|
|
lsl.l #8, D3
|
|
move.b HALactionPB.msgOutLen(A4), D3
|
|
lsl.l #8, D3
|
|
move.b HALactionPB.msg(A4), D3
|
|
lsl.l #8, D3
|
|
move.b currentPhase(A5), D3
|
|
move.l D3, -(sp)
|
|
bsr RecordEvent
|
|
addq.l #8, sp
|
|
ENDIF
|
|
|
|
;ÉÉÉÉÉÉÉÉÉÉÉ Call the selected routine ÉÉÉÉÉÉÉÉÉÉÉÉÉÉ
|
|
|
|
move.l HALactionPB.ioPtr(A4), A0 ; load A0 with ptr to SCSI_IO pb
|
|
jsr (A1) ; and go to requested action routine
|
|
|
|
;ÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉ
|
|
|
|
move.b currentPhase(A5), D0
|
|
@ck4msgIn
|
|
cmp.b #kMessageInPhase, D0
|
|
bne.s @ck4busFree
|
|
jsr ([jvAutoMsgIn, A5])
|
|
move.b currentPhase(A5), D0
|
|
@ck4busFree
|
|
cmp.b #kBusFreePhase, D0
|
|
bne.s @normalPhase
|
|
bsr Disconnected
|
|
@normalPhase
|
|
move.b D0, HALactionPB.phase(A4)
|
|
|
|
IF RECORD_ON THEN
|
|
pea '-HAL'
|
|
move.b HALactionPB.action+1(A4), D3
|
|
lsl.l #8, D3
|
|
move.b HALactionPB.result+1(A4), D3
|
|
lsl.l #8, D3
|
|
move.b HALactionPB.msg(A4), D3
|
|
lsl.l #8, D3
|
|
move.b HALactionPB.phase(A4), D3
|
|
move.l D3, -(sp)
|
|
bsr RecordEvent
|
|
addq.l #8, sp
|
|
ENDIF
|
|
|
|
movem.l (sp)+, regsToSave
|
|
rts
|
|
|
|
|
|
@Unknown
|
|
IfDebugStr 'HAL action selector too high'
|
|
moveq #dsIOCoreErr, D0
|
|
_SysError
|
|
|
|
bra.s *
|
|
|
|
RTSNAME 'HALaction'
|
|
|
|
|
|
;==========================================================================
|
|
|
|
HALc96 PROC EXPORT
|
|
;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
|
|
EXPORT DoInitiate, Wt4SelectComplete, HandleBusInt
|
|
EXPORT DoAcceptMsg
|
|
EXPORT DoMsgOut
|
|
EXPORT DoStatus
|
|
EXPORT DoComplete
|
|
EXPORT DoSelect
|
|
EXPORT DoCommand
|
|
EXPORT SetParity
|
|
EXPORT CyclePhase
|
|
EXPORT AutoMsgIn
|
|
|
|
EXPORT HALResetBus, HALAssertATN, HALTeardownIO
|
|
EXPORT HALSyncConfig
|
|
EXPORT DoAssertATN
|
|
EXPORT SetupIONoDMA, TeardownIONoDMA
|
|
EXPORT DoReset
|
|
|
|
WITH HALc96GlobalRecord
|
|
WITH SCSI_IO, HALactions, SCSIPhase
|
|
|
|
|
|
;==========================================================================
|
|
;
|
|
Unimplemented
|
|
IfDebugStr 'Unknown HAL action selector'
|
|
moveq #dsIOCoreErr, D0
|
|
_SysError
|
|
|
|
;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
rts
|
|
|
|
NAME 'Unimplemented'
|
|
|
|
|
|
;################################################################################
|
|
;********** HALActions *********
|
|
;################################################################################
|
|
|
|
IF 0 THEN
|
|
;========================================================================
|
|
Initiate a connection
|
|
Arbitrate, Select and send [Identify message and] CDB to target
|
|
|
|
Description:
|
|
Once DMA is setup to do CDB and c96 is setup to do Arb+Select+Identify+CDB,
|
|
it can end up several ways:
|
|
¥ Arbitration failed
|
|
SCSI Int - ??
|
|
no DMA int
|
|
¥ Select failed
|
|
SCSI Int - ??
|
|
no DMA int
|
|
¥ Select w/Atn but didn't go into MessageOut phase
|
|
SCSI Int - ??
|
|
no DMA int
|
|
¥ didn't go into Command phase
|
|
SCSI Int - ??
|
|
no DMA int
|
|
¥ only sent part of CDB before target went out of Command phase
|
|
SCSI Int - ??
|
|
no DMA int
|
|
¥ sent CDB but didn't get out of Command phase
|
|
SCSI Int - Function Complete + ??
|
|
DMA int - xfer complete
|
|
c96 will bitblast 00 out until !Command phase. Can/can't?? tell it happened.
|
|
¥ all OK - send MsgOut and Command out and went into a different phase
|
|
SCSI Int - Function Complete + Bus Service, rSEQ=??
|
|
DMA int - xfer complete
|
|
|
|
Flow:
|
|
Setup c96 to do a Select w/Atn with Identify msg in FIFO and CDB in DMA
|
|
Setup DMA for CDB
|
|
Return to caller and wait for interrupt from c96 and DMA
|
|
Int c96:
|
|
get status, fifo seq and interrupt regs
|
|
all cool?
|
|
yes: DMA already int?
|
|
no: rts - wait for DMA_complete int
|
|
yes: call InitiateComplete(success)
|
|
no: find out what went wrong
|
|
terminate DMA
|
|
call InitiateComplete(failed)
|
|
Int DMA:
|
|
SCSI already int?
|
|
no: rts - wait for SCSI int
|
|
yes: check
|
|
;
|
|
ENDIF
|
|
|
|
|
|
;==========================================================================
|
|
; Initiate
|
|
; - Arbitrate, Select, Send Message(s) (optional), Send CDB (command bytes, optional)
|
|
;
|
|
; In the 5396, arbitration, selection and command-send operations are integrated operations.
|
|
; We need the target id and the actual command descriptor block in order to exploit the
|
|
; capabilities of the chip. Unfortunately, the old SCSI manager was structured for separate
|
|
; such operations. This proc is an attempt to remain compatible to that type of operation.
|
|
; Our goal is to select a target and report the success or failure of that operation.
|
|
; This is accomplished by:
|
|
; 1) Loading transfer count, TC, with one in order to activate the select process
|
|
; 2) Using DMA mode in order to allow us to send the actual CDB during DoSCSICmd proc.
|
|
;
|
|
; Upon exit, we should be in transfer phase waiting for the client to perform either a
|
|
; command send or msg-out--if select w/ ATN. The c96 would be ready and waiting for the
|
|
; CDB or message byte because we told it to expect at least 1 byte of data.
|
|
;
|
|
; Select w/ ATN asserts the ATTENTION line during selection process. This allows the
|
|
; client to perform a 1 byte msg-out via SCSIMsgOut. The ATN line is deasserted
|
|
; prior to sending the msg byte.
|
|
;
|
|
; A4 - ptr to HALaction pb
|
|
; A3 - SCSI read base address
|
|
; A5 - ptr to SCSI Mgr globals
|
|
;
|
|
;--------------------------------------------------------------------------
|
|
DoInitiate
|
|
IF RECORD_ON THEN
|
|
move.l D0, -(sp)
|
|
pea 'Init'
|
|
moveq #'0', D0
|
|
add.b scsiDevice.targetID(A0), D0 ; ID
|
|
move.l D0, -(sp)
|
|
bsr RecordEvent
|
|
addq.l #8, sp
|
|
move.l (sp)+, D0
|
|
ENDIF
|
|
|
|
|
|
move.b rSTA(A3), D1 ; interrupt?
|
|
bmi.w @getBusInt ; if we got an int from the bus, go check it out
|
|
;
|
|
; Set up chip for select process (init dest ID)
|
|
;
|
|
move.b scsiDevice.targetID(A0), rDID(A3) ; tell chip which target ID to select
|
|
|
|
;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
;
|
|
; Check scsiDisableSelectWAtn flag and number of msg_out bytes needed to determine what kind
|
|
; of Select operation we need to do.
|
|
;
|
|
move.w SCSI_IO.scsiIOFlags(A0), D0 ; Get the flags field
|
|
and.w #scsiDisableSelectWAtn,D0 ; Are we doing select with attention?
|
|
bne @useNoAtnSel ; nope, don't send an identify message
|
|
|
|
;
|
|
; How many message bytes are there? This will determine what Select command
|
|
; we will issue to the c96.
|
|
;
|
|
moveq.l #0, D0
|
|
move.b HALactionPB.msgOutLen(A4), D0
|
|
IF DEBUGGING THEN
|
|
bne.s @99 ; if no msg bytes to send, we're toast!!!
|
|
DebugStr 'DoInitiate:SelectWAtn but no msg'
|
|
ENDIF
|
|
@99 cmp.b #1, D0 ; 1 message byte?
|
|
bne.s @ck3byteSel ; no->ck for 3 bytes
|
|
|
|
|
|
|
|
;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
;
|
|
; If there is 1 message out byte, we can stuff it and the CDB into the
|
|
; FIFO then send a SelWAtn command.
|
|
;
|
|
|
|
@use1byteSel
|
|
move.b HALactionPB.msg(A4), rFIFO(A3) ; move message into FIFO
|
|
|
|
tst.b HALactionPB.sendCDB(A4) ; are we sposed to send CDB too?
|
|
beq.s @skipCDB1 ; no->skip it
|
|
bsr MoveCDBintoFIFO ; yes: stuff it and check for bus int
|
|
bmi.w @getBusInt ; if we got an int, go check it out
|
|
@skipCDB1
|
|
RecCmd $42, 'A',$08
|
|
eieio
|
|
move.b #cSelWAtn, rCMD(A3) ; issue Select w/ Atn cmd (non-DMA)
|
|
eieio
|
|
bra.w @SelStarted
|
|
|
|
|
|
|
|
;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
;
|
|
; If there are 3 message bytes to send, use a SelWAtn3 command.
|
|
;
|
|
@ck3byteSel
|
|
cmp.b #3, D0 ; 3 message bytes?
|
|
bne.s @doSelAndStop
|
|
|
|
@use3byteSel
|
|
lea.l HALactionPB.msg(A4), A1
|
|
move.b (A1)+, rFIFO(A3) ; move message into FIFO
|
|
move.b (A1)+, rFIFO(A3) ; move message into FIFO
|
|
move.b (A1)+, rFIFO(A3) ; move message into FIFO
|
|
move.b rSTA(A3), D1 ; interrupt?
|
|
bmi.w @getBusInt ; if we got an int, go find out what it is
|
|
|
|
tst.b HALactionPB.sendCDB(A4) ; are we sposed to send CDB too?
|
|
beq.s @skipCDB3 ; no->skip it
|
|
bsr MoveCDBintoFIFO ; yes: stuff it and check for bus int
|
|
bmi.w @getBusInt ; if we got an int, go check it out
|
|
@skipCDB3
|
|
RecCmd $46, 'A',$0a
|
|
eieio ; flush all writes out before issuing cmd
|
|
move.b #cSelWAtn3, rCMD(a3) ; issue Select w/ Atn3 cmd (non-DMA)
|
|
eieio
|
|
|
|
bra.w @SelStarted
|
|
|
|
|
|
;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
;
|
|
; If there are other than 1 or 3 message out bytes, we have to do a SelAndStop command
|
|
; followed by cIOXfer of the remainder of the message then cIOXfer of the command bytes.
|
|
;
|
|
@doSelAndStop
|
|
lea.l HALactionPB.msg(A4), A1
|
|
move.b (A1)+, rFIFO(A3) ; move 1st message byte into FIFO
|
|
eieio
|
|
|
|
RecCmd $41, 'A',$00
|
|
move.b #cSelWATNStop, rCMD(a3) ; do Select w/Atn and stop (after 1 msg-out)
|
|
eieio
|
|
jsrv jvWt4SelectComplete, A2
|
|
bne.w @exit ; if we didn't select, exit
|
|
|
|
;
|
|
; Check phase and/or check FIFO: if we didn't send the 1 message byte out, set a flag
|
|
; indicating that. If we did but we aren't still in msg_out phz, set a different flag.
|
|
; If we did and we are still in msg_out phase - jolly good - stuff the rest of the msg
|
|
; into the FIFO.
|
|
;
|
|
moveq.l #mFIFOCount, D1 ; use mask to get FIFO flag field
|
|
and.b int_rFIFOflags(A5), D1 ; is the byte still in the FIFO?
|
|
beq.s @sendRestOfMsg ; no -> send rest of message
|
|
|
|
bra.w @selIncompleteMsg ;
|
|
|
|
@sendRestOfMsg
|
|
cmpi.b #kMessageOutPhase, currentPhase(A5) ; are we in MsgOut phase?
|
|
beq.s @inMsgOutPhase ; yes->send rest of bytes
|
|
|
|
move.b #1, HALactionPB.msgOutLen(A4) ; no: we only sent 1 msg byte
|
|
bra.w @selIncMsgNoCalc
|
|
|
|
@inMsgOutPhase
|
|
moveq.l #0, D0
|
|
move.b HALactionPB.msgOutLen(A4), D0
|
|
subq.w #2, D0 ; 1 for missing dbra, 1 for 1st msg byte
|
|
@lp
|
|
move.b (A1)+, rFIFO(A3) ; move message into FIFO
|
|
dbra D0, @lp
|
|
eieio
|
|
|
|
;
|
|
; Do the IOxfer and check the results (FIFO count and phase). Note if we didn't get all
|
|
; of our message bytes out (and clear them out with FlushFIFO).
|
|
;
|
|
RecCmd $10, 'A',$04
|
|
move.b #cIOXfer, rCMD(a3) ; load Transfer cmd byte in CMD regr
|
|
eieio
|
|
|
|
bsr Wt4SCSIInt ; Wait for intrp w/o timeout
|
|
|
|
moveq.l #mFIFOCount, D1 ; use mask to get FIFO flag field
|
|
and.b int_rFIFOflags(A5), D1 ; are there bytes still in the FIFO?
|
|
beq.s @ck4CmdPhase ; no -> see if we're in cmd Phase
|
|
; we didn't send all of our message out
|
|
bra @selIncompleteMsg
|
|
|
|
@ck4CmdPhase
|
|
tst.b HALactionPB.sendCDB(A4) ; are we sposed to send CDB too?
|
|
beq.w @selComplete ; no->we're done
|
|
|
|
cmpi.b #kCommandPhase, currentPhase(A5) ; are we in Command phase?
|
|
bne.w @selNoCommand ; no->we missed Command phase
|
|
|
|
@inCommandPhase
|
|
bsr MoveCDBintoFIFO ; yes: stuff it and check for bus int
|
|
|
|
RecCmd $10, 'A',$06
|
|
move.b #cIOXfer, rCMD(a3) ; load Transfer cmd byte in CMD regr
|
|
eieio
|
|
bsr Wt4SCSIInt ; Wait for intrp w/o timeout
|
|
bne UnexpectedDisc ; bus free? -> exit
|
|
|
|
moveq.l #mFIFOCount, D1 ; use mask to get FIFO flag field
|
|
and.b int_rFIFOflags(A5), D1 ; are there bytes still in the FIFO?
|
|
beq.w @selComplete ; no -> select is complete
|
|
bra.s @selIncompleteCommand ; yes-> sent too few Command bytes
|
|
|
|
|
|
;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
;
|
|
; If we aren't supposed to Select w/Atn, then we don't have any message bytes
|
|
; to send
|
|
;
|
|
@useNoAtnSel
|
|
bsr MoveCDBintoFIFO
|
|
bmi @getBusInt ; if we got an int, go check it out
|
|
|
|
RecCmd $41, 'A',$0c
|
|
move.b #cSelWOATN, rCMD(a3) ; issue Select w/o Atn cmd (non-DMA)
|
|
eieio
|
|
|
|
|
|
;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
|
|
@SelStarted
|
|
jsrv jvWt4SelectComplete, A2 ; wt 4 something to happen
|
|
bne.w @selectDidnt ; reselect/bus free -> didn't select
|
|
|
|
moveq.l #mFIFOCount, D1 ; use mask to get FIFO flag field
|
|
and.b int_rFIFOflags(A5), D1 ; are there bytes still in the FIFO?
|
|
beq.w @selComplete
|
|
|
|
tst.b HALactionPB.sendCDB(A4)
|
|
beq.s @selIncompleteMsg
|
|
|
|
sub.b scsiCDBLength(A0), D1 ; how does fifo count compare to cdb len?
|
|
beq.s @selNoCommand ; same? -> no command
|
|
bcs.s @selIncompleteCommand ; cdb>fifo count? -> incomplete cmd
|
|
|
|
@selIncompleteMsg
|
|
sub.w D1, HALactionPB.msgOutLen(A4) ; calc xferred bytes
|
|
@selIncMsgNoCalc
|
|
IF ERR_RECORD_ON THEN
|
|
move.l D0, -(sp)
|
|
pea 'Err!'
|
|
move.l #'msg0', D0
|
|
add.b HALactionPB.msgOutLen(A4), D0
|
|
move.l D0, -(sp)
|
|
bsr RecordEvent
|
|
addq.l #8, sp
|
|
move.l (sp)+, D0
|
|
ENDIF
|
|
move.w #HALresult.kHALpartialMsgOut, HALactionPB.result(A4)
|
|
bra.s @exitWFlush
|
|
@selIncompleteCommand
|
|
IF ERR_RECORD_ON THEN
|
|
pea 'Err!'
|
|
pea 'cmdx'
|
|
bsr RecordEvent
|
|
addq.l #8, sp
|
|
ENDIF
|
|
move.w #HALresult.kHALpartialCommand, HALactionPB.result(A4)
|
|
bra.s @exitWFlush
|
|
@selNoCommand
|
|
IF ERR_RECORD_ON THEN
|
|
pea 'Err!'
|
|
pea 'cmd0'
|
|
bsr RecordEvent
|
|
addq.l #8, sp
|
|
ENDIF
|
|
move.w #HALresult.kHALnoCommand, HALactionPB.result(A4)
|
|
@exitWFlush
|
|
RecCmd $01, 'A',$0e
|
|
move.b #cFlushFIFO, rCMD(A3) ; yes - get rid of them
|
|
eieio
|
|
@selectDidnt
|
|
@selComplete
|
|
@exit
|
|
rts
|
|
|
|
@getBusInt
|
|
jsrv jvHandleBusInt, A2
|
|
rts
|
|
|
|
|
|
;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
|
|
|
|
NAME 'DoInitiate'
|
|
|
|
|
|
|
|
;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
|
|
Wt4SelectComplete
|
|
|
|
bsr InitDataStuff ; set up saved and current data pointers
|
|
;
|
|
; OK - first we need to setup any buffers for DMA
|
|
;
|
|
; The reason we are setting up the buffers here instead of somewhere else is that a select will typically
|
|
; take a fair amount of time. Instead of giving that time back to the client we will use it to do a lock
|
|
; memory. This optimizes for transaction performance rather than asynchronicity. <SM8>
|
|
;
|
|
move.l A0, -(sp) ; pb that gets setup
|
|
jsrv jvSetupIO, A2
|
|
move.l (sp)+, A0 ; get rid of parm and restore A0
|
|
|
|
|
|
;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
HandleBusInt
|
|
|
|
; Check for an int - either Disconnected (fld select) or Bus Service/Func. Cmplt (good select)
|
|
|
|
bsr Wt4SCSIInt
|
|
;
|
|
; We got an interrupt, it means that the select command is complete. Either the target did
|
|
; not respond (i.e. didn't exist) or it was selected and either finished the message out
|
|
; and command phases then saw a REQ or it went to an unexpected phase. (OR A RESELECT !)
|
|
;
|
|
cmp.b #mFuncComplete+mBusService, int_rINT(A5) ; was interrupt a FuncComplete/BusService ?
|
|
bne.s @ck4reselect ; no -> check disconnect, reselect etc.
|
|
|
|
@exitDidSelect
|
|
moveq.l #0, D0 ; yes: successful select
|
|
rts
|
|
|
|
|
|
;ÑÑÑ Was it a Reconnect (during select)?
|
|
@ck4reselect
|
|
btst #bReselected, int_rINT(A5) ; was it a Reselect?
|
|
beq.s @1
|
|
bsr Ck4SCSIInt ; check for another int (in case of illegal cmd)
|
|
|
|
move.b #cFlushFIFO, rCMD(A3) ; wipe misc. msg and CDB that we stuffed
|
|
eieio
|
|
jsrv jvGetReconnectInfo, A2
|
|
@exitDidntSelect
|
|
moveq.l #1, D0 ; didn't select result code
|
|
rts
|
|
|
|
;ÑÑÑ Was it a bus-initiated Select (during our select)?
|
|
@1 btst #bSelected, int_rINT(A5) ; selected int?
|
|
beq.s @2
|
|
jsrv jvGetReconnectInfo, A2
|
|
bra.s @exitDidntSelect
|
|
|
|
;ÑÑÑ Was it a failed select? (i.e. a disconnect interrupt)
|
|
@2 btst #bDisconnected, int_rINT(A5) ; (i.e. timed-out then bus free)
|
|
beq.s @unknownInt
|
|
|
|
move.w #HALresult.kHALselectFld, HALactionPB.result(A4) ; select timeout
|
|
bra.s @exitDidntSelect
|
|
|
|
;ÑÑÑ It was an unknown interrupt
|
|
@unknownInt
|
|
DebugStr 'Unknown interrupt on Initiate'
|
|
bra.s @exitDidSelect
|
|
|
|
RTSNAME 'Wt4SelectComplete'
|
|
|
|
|
|
;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
|
|
MoveCDBintoFIFO
|
|
move.l SCSI_IO.scsiFlags(A0), D0
|
|
and.l #scsiCDBIsPointer, D0
|
|
beq.s @CDBisReal
|
|
move.l scsiCDB(A0), A1 ; get CDB from io pb
|
|
bra.s @moveBytes
|
|
@CDBisReal
|
|
lea.l scsiCDB(A0), A1 ; get CDB from io pb
|
|
@moveBytes
|
|
moveq.l #0, D0 ; clear upper part of D0 for dbra
|
|
move.b scsiCDBLength(A0), D0 ; get len of CDB from io pb
|
|
IF RECORD_ON THEN
|
|
move.l 0(A1),-(sp) ; CDB bytes 0-3
|
|
move.l 4(A1),-(sp) ; CDB bytes 4-7
|
|
bsr RecordEvent
|
|
addq.l #8, sp
|
|
ENDIF
|
|
|
|
bra.s @cdbLpBtm
|
|
@cdbLoop
|
|
move.b (A1)+, rFIFO(a3)
|
|
@cdbLpBtm
|
|
move.b rSTA(A3), D1 ; interrupt?
|
|
dbmi D0, @cdbLoop ; if so, fall thru, else, dec and bra
|
|
|
|
eieio
|
|
rts ; <SM5> pdw from prev
|
|
|
|
NAME 'MoveCDBintoFIFO'
|
|
|
|
|
|
;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
;
|
|
; FUNCTION SCSISelect(TargID:INTEGER): INTEGER;
|
|
; (8) (10)
|
|
;
|
|
; Select the target on the bus. Returns 0 for success, or error.
|
|
; Selection can be done with or without the ATN line.
|
|
;
|
|
|
|
DoSelect
|
|
|
|
; Set up chip for select process (init dest ID)
|
|
|
|
move.b scsiDevice.targetID(A0), rDID(A3) ; tell chip which target ID to select
|
|
; delayed eieio
|
|
IF DEBUGGING THEN
|
|
tst.b HBAhasPseudoDMA(A5) ; if we have pseudoDMA ...
|
|
bne.s @DREQable ;
|
|
tst.b HBAhasDMA(A5) ; or real DMA ...
|
|
bne.s @DREQable ; ... use this routine
|
|
|
|
IfDebugStr 'bad hwDesc - no DMA or pDMA'
|
|
moveq #dsIOCoreErr, D0
|
|
_SysError
|
|
|
|
@DREQable
|
|
ENDIF
|
|
|
|
cmp.w #scsiSelAtn, scsiSelector(A0) ; Select w/Atn?
|
|
beq.s @withAtn ; yes->set up for msg byte expected
|
|
|
|
; If Select w/o Atn then set up for 2 DMA bytes (last bytes of command block) and start process
|
|
|
|
@withoutATN
|
|
eieio
|
|
move.b #NeedCmdSent, G_State96(A5) ; flag=expect to see a COMMAND phase next
|
|
clr.b rXCM(a3) ; tell chip that we will be sending 2
|
|
move.b #2, rXCL(a3) ; DMA bytes (in command phase)
|
|
move.b #kCommandPhase, currentPhase(A5) ; fake out command phase
|
|
|
|
RecCmd $c1, 'A',$10
|
|
move.b #cDMASelWOAtn, rCMD(a3) ; issue Select w/o Atn cmd
|
|
eieio
|
|
bra.s @0
|
|
|
|
; If Select w/Atn then set up for 2 DMA bytes (msg_out byte + last byte of command block)
|
|
|
|
@withATN
|
|
eieio
|
|
move.b #NeedMsgOut, G_State96(A5) ; flag=expect to see a MESSAGE_OUT phase next
|
|
clr.b rXCM(a3) ; tell chip that we will be sending 1
|
|
move.b #2, rXCL(a3) ; DMA bytes (1 in msg_out, 2 in command)
|
|
move.b #kMessageOutPhase, currentPhase(A5) ; fake out MessageOut phas
|
|
|
|
RecCmd $c2, 'A',$12
|
|
move.b #cDMASelWAtn, rCMD(a3) ; issue Select w/ Atn cmd
|
|
eieio
|
|
@0
|
|
|
|
|
|
; Set up >512mS timeout for select operation to get somewhere (probably more like 4 seconds)
|
|
|
|
moveq.l #0, d1 ; clear upper word
|
|
move.w TimeSCSIDB, d1 ; get # of DBRAs
|
|
lsl.l #8, d1 ; multiply by 256
|
|
move.l d1, d2 ; 4-16 sec wait for overall watchdog
|
|
swap d2
|
|
|
|
|
|
; We have told the chip to start it, now we wait for an indication that it has completed a
|
|
; selection. Several things can happen:
|
|
; - the target at the requested ID may not exist or may not respond to the select. In
|
|
; this case we will receive a Disconnect interrupt from the chip.
|
|
; - the target may select OK but go into something other than Command Phase (if Sel w/o Atn)
|
|
; or Message_Out Phase (if Sel w/Atn). Here we will see a Function Complete/Bus Service
|
|
; interrupt.
|
|
; - the target may select OK and go into the expected Phase - the SUCCESS case. When this
|
|
; happens, the chip will assert DREQ because it wants the Command (or Msg_Out) byte.
|
|
; - the bus may be hung and the chip is unable to arbitrate. We detect this by timing
|
|
; out on the whole process.
|
|
;
|
|
; So basically, this is a 3-way wait for:
|
|
; 1) DREQ asserted
|
|
; 2) interrupt
|
|
; 3) loop timed out
|
|
|
|
;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
@waitLoop
|
|
; Check for a REQ from the target (within valid phase)
|
|
bsr Ck4DREQ ; DREQ?
|
|
bne.s @gotDREQ ; yes-> we have a REQ for MsgOut or Cmd byte
|
|
|
|
; Check for an int - Disconnected, good select, reselected or selected
|
|
tst.b gotInt(A5) ; check for an int
|
|
bne.s @doneWithSel ;
|
|
tst.b rSTA(A3) ; interrupt?
|
|
dbmi D1, @waitLoop ;
|
|
dbmi D2, @waitLoop ; loop until count exhausted or intrp detected
|
|
; count is up or intrp detected so we're outta' here
|
|
bpl.s @timedOut ; if not interrupt
|
|
|
|
;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
|
|
; If we got an interrupt, it means that the select command is complete. Either the target did
|
|
; not respond (i.e. didn't exist) or it was selected but went to an unexpected phase.
|
|
|
|
@doneWithSel ; got an interrupt
|
|
clr.b G_State96(A5) ; not waiting for anything
|
|
|
|
jsrv jvHandleBusInt, A2
|
|
rts
|
|
|
|
;ÑÑÑ
|
|
@gotDREQ
|
|
bsr InitDataStuff ; set up saved and current data pointers
|
|
rts
|
|
|
|
NAME 'Select'
|
|
|
|
|
|
;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
|
|
@timedOut
|
|
IF ERR_RECORD_ON THEN
|
|
pea 'STmO'
|
|
move.w busID(A5), -(sp)
|
|
move.w int_rINT(A5), -(sp)
|
|
bsr RecordEvent
|
|
addq.l #8, sp
|
|
ENDIF
|
|
move.w #scArbNBErr, HALactionPB.result(A4) ; arbitration timeout (1/2 second or so)
|
|
|
|
;
|
|
; Check for CURIO Target mode bug (where it goes into DMA mode halfway through
|
|
; receiving the command bytes.
|
|
;
|
|
cmp.b #$0a, rSTA(A3) ; cmd_xfer_cmplt + cmd phz
|
|
bne.s @exit ; not same value -> not the bug
|
|
cmp.b #$30, rFIFOflags(A3) ; no bytes in FIFO
|
|
bne.s @exit
|
|
cmp.b #$c1, rSQS(A3) ; sequence step == C1
|
|
bne.s @exit
|
|
cmp.b #$c1, rCMD(A3) ; last command was our DMA select
|
|
bne.s @exit
|
|
|
|
IfDebugStr 'AMD shines again!'
|
|
|
|
IF ERR_RECORD_ON THEN
|
|
pea 'Err!'
|
|
pea 'AMD!'
|
|
bsr RecordEvent
|
|
addq.l #8, sp
|
|
ENDIF
|
|
bsr AsmInit53c9xHW ; reset this chip and start over!
|
|
move.b #kBusFreePhase, currentPhase(A5)
|
|
move.w #HALresult.kHALselectedAsTargetFld, HALactionPB.result(A4) ; select timeout
|
|
@exit
|
|
rts
|
|
|
|
NAME 'DoSelect_excptns'
|
|
|
|
|
|
|
|
;==========================================================================
|
|
;
|
|
; Send Command.
|
|
;
|
|
; A0, A3, A5 - usual HAL conventions
|
|
;
|
|
; Sends the CDB bytes that are specified in the IOpb (A0). There are two ways of
|
|
; doing this, depending on whether we are working on an old API or new API transaction.
|
|
; In both cases, we stuff all of the CDB except 2 bytes and then, depending on whether
|
|
; it's old or new, we do different things for the last two bytes - see details below.
|
|
;
|
|
;
|
|
|
|
DoCommand
|
|
;---- Load the FIFO with ALMOST all of the bytes
|
|
|
|
@sendBytes
|
|
move.l SCSI_IO.scsiFlags(A0), D0
|
|
and.l #scsiCDBIsPointer, D0
|
|
beq.s @CDBisReal
|
|
move.l scsiCDB(A0), A1 ; get CDB from io pb
|
|
bra.s @1
|
|
@CDBisReal
|
|
lea.l scsiCDB(A0), A1 ; get CDB from io pb
|
|
@1
|
|
moveq.l #0, D2 ; clear upper part of D2 for dbra
|
|
move.b scsiCDBLength(A0), D2 ; get len of CDB from io pb
|
|
subq.l #2, D2 ; adjust for DMA of last bytes
|
|
bge.s @btmLoadFIFO ; bra to dbra for zero case (2 byte CDB)
|
|
bra @oneByteCDB
|
|
@loadFIFO ; loading the FIFO w/o pseudo-DMA will simulate
|
|
move.b (A1)+, rFIFO(A3) ; preloading of the FIFO...we then pDMA the
|
|
@btmLoadFIFO ;
|
|
dbra D2, @loadFIFO
|
|
eieio
|
|
|
|
;---- send the last 2 bytes
|
|
|
|
@oldAPIorNewAPI
|
|
tst.b G_State96(A5) ; are we doing a Select operation?
|
|
beq @newAPIcmd ; no -> new API: rFIFO last 2, IOXfer
|
|
; yes: old API: rDMA(), no cmd
|
|
|
|
;ÑÑÑÑÑ Old API Last 2 bytes ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
;
|
|
;---- Handle the Select operation that's in progress
|
|
|
|
; If the NeedCmdSent condition is true, that means that we are in the middle of an old-API
|
|
; transaction which means that we are sitting right in the middle of a c96 SelW(O)Atn
|
|
; process which means that all we have to do is stuff the last two bytes into the FIFO
|
|
; with pseudo-DMA or real DMA. No command needs to be issued to the c96 since it is
|
|
; working on the Select command.
|
|
;
|
|
@lastCmdBytes
|
|
tst.b HBAhasPseudoDMA(A5)
|
|
beq.s @ck4hasDMA
|
|
move.w (A1)+, rDMA(A3) ; Use Pseudo DMA to load last bytes
|
|
bra.s @sentAll
|
|
eieio
|
|
|
|
@ck4hasDMA
|
|
tst.b HBAhasDMA(A5)
|
|
bne.s @hasDMA
|
|
|
|
IfDebugStr 'Bad hwDesc - no DMA or pDMA'
|
|
moveq #dsIOCoreErr, D0
|
|
_SysError
|
|
|
|
@hasDMA
|
|
move.w (a1)+, ([logicalCopyBuffer,A5]) ; put last bytes into our DMA buffer
|
|
|
|
move.w #false, -(sp) ; false = out
|
|
move.l #2, -(sp)
|
|
move.l physicalCopyBuffer(A5), -(sp)
|
|
jsr ([jvStartDMA,A5])
|
|
lea 10(sp), sp
|
|
jsr ([jvWt4DMAComplete,A5])
|
|
@sentAll
|
|
move.b #FCIntPend,G_State96(A5) ; now we can expect a FunctionCmplt interrupt
|
|
|
|
;---- Wait for either FIFO empty (c96 sent the bytes) or an interrupt (target bailed early)
|
|
|
|
@wt4EmptyOrInt
|
|
moveq.l #mFIFOCount, D1 ; use mask to get FIFO flag field
|
|
and.b rFIFOflags(A3), D1 ; how many bytes left in FIFO?
|
|
beq.s @wt4int ; if none, return out to caller, we'll wait
|
|
; for int at start of next call (in XPT)
|
|
bsr Ck4SCSIInt ; if not empty, did we get an interrupt?
|
|
beq.s @wt4EmptyOrInt
|
|
|
|
; Did we send all the bytes?
|
|
moveq.l #mFIFOCount, D1 ; use mask to get FIFO flag field
|
|
and.b rFIFOflags(A3), D1 ; how many bytes left in FIFO?
|
|
beq.s @gotSelInt ; ->if none then we're cool
|
|
|
|
RecCmd $01, 'A',$83
|
|
move.b #cFlushFIFO, rCMD(a3) ; if bytes in FIFO, wipe them out
|
|
|
|
cmp.b #1, D1 ; check for c96 FIFO-gets-stuck bug
|
|
beq.s @gotSelInt ; ->if 1 then we're cool too (probably)
|
|
bra.s @phaseErr ; if >1 byte left, then target bailed early
|
|
|
|
@wt4int ; <L2> pdw
|
|
;---- Wait till we get an interrupt (indicating a REQ beyond Command Phz)
|
|
bsr.w Wt4SCSIInt
|
|
|
|
@gotSelInt
|
|
;
|
|
; We have to flush the FIFO because of another bug in the c96 where it leaves a byte
|
|
; in the FIFO (or at least the count is nonzero) after a cSelWOAtn operation (that
|
|
; was sent during a SCSISelect call). This caused a later SCSIComplete
|
|
; to read in a bogus Status byte before reading in the real Status byte (which was
|
|
; thought to be the Message byte). The null Status byte is usually OK on hard disks and
|
|
; such but when polling for a CD-ROM, we are supposed to be getting 02 (check condition)
|
|
; and when the CD-ROM driver sees a null, it posts a bogus DiskInsert event.
|
|
;
|
|
@flushAndExit
|
|
RecCmd $01, 'A',$86
|
|
move.b #cFlushFIFO, rCMD(A3) ; Flush FIFO - REMEMBER THE CD-ROM BUG!!!
|
|
eieio
|
|
@noErrRet
|
|
clr.b G_State96(A5) ; not waiting for anything
|
|
cmp.b #kBusFreePhase, currentPhase(A5)
|
|
beq UnexpectedDisc ; bus free? -> exit
|
|
rts
|
|
|
|
|
|
;ÑÑÑÑÑ New API Last 2 bytes ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
;
|
|
; If we didn't have the NeedCmdSent condition, that means that we aren't doing an old-API
|
|
; transaction which means that we aren't sitting in the middle of a c96 cSelectWOAtn
|
|
; process. This means that we need to stuff the last two bytes into the FIFO using the
|
|
; regular byte-wide rFIFO register (not DMA) and issue a cIOXfer command to the c96 to
|
|
; actually send the whole FIFO full of CDB bytes.
|
|
;
|
|
@newAPIcmd
|
|
move.b (a1)+, rFIFO(A3) ; load last 2 bytes
|
|
move.b (a1)+, rFIFO(A3)
|
|
eieio
|
|
RecCmd $10, 'A',$13
|
|
move.b #cIOXfer, rCMD(A3) ; issue IOXfer command
|
|
eieio
|
|
bra.s @wt4int
|
|
|
|
RTSNAME 'DoCommand'
|
|
|
|
|
|
;ÑÑÑÑÑ Exceptions ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
|
|
@oneByteCDB
|
|
move.b (a1), d0
|
|
lsl.w #8, D0
|
|
move.b (a1), d0 ;_debugger CAN't DO THIS ON A CYCLONE!!!!%%%
|
|
move.w D0, rDMA(a3) ; Use Pseudo DMA to load only byte
|
|
; do a word to satisfy c96's DMA counter
|
|
eieio
|
|
bra.s @sentAll
|
|
|
|
@phaseErr
|
|
IF ERR_RECORD_ON THEN
|
|
pea 'Err!'
|
|
pea 'CPz2'
|
|
bsr RecordEvent
|
|
addq.l #8, sp
|
|
ENDIF
|
|
@2
|
|
moveq.l #scPhaseErr, d0 ; no error
|
|
move.w D0, HALactionPB.result(A4) ; with whatever err
|
|
bra.s @flushAndExit
|
|
|
|
RTSNAME 'DoCommand_excptns'
|
|
|
|
|
|
;==========================================================================
|
|
;
|
|
; FUNCTION SCSIComplete(VAR Stat, Message: INTEGER; wait:LongInt): INTEGER;
|
|
; (16) (12) (8) (20)
|
|
;
|
|
; Complete the SCSI command by:
|
|
; 1) Sending command complete sequence byte to get status & msg bytes from target
|
|
; 2) Sending message accepted command to complete the cycle
|
|
;
|
|
; Return Codes:
|
|
; noErr, scCommErr, scPhaseErr, scComplPhaseErr
|
|
|
|
DoStatus
|
|
DoComplete
|
|
@chkPhase
|
|
cmpi.b #kStatusPhase, currentPhase(A5) ; are we in status phase?
|
|
beq.s @inStatusPhase ;
|
|
|
|
cmp.b #kBusFreePhase, currentPhase(A5)
|
|
beq @scsiComplPhaseErr ;
|
|
|
|
@notInStatusPhase ; only called for Complete phase errors
|
|
bsr CyclePhase
|
|
bra.s @chkPhase
|
|
|
|
@inStatusPhase
|
|
RecCmd $11, 'A',$14
|
|
move.b #cCmdComplete, rCMD(a3) ; load cmd complete code
|
|
eieio
|
|
bsr Ck4SCSIInt ; Check for intrp
|
|
bne.s @gotStatus ; got it -> good
|
|
bsr Ck4SCSIInt ; Check for intrp
|
|
bne.s @gotStatus ; got it -> good
|
|
bsr Wt4SCSIInt ; no, try again and wait for it
|
|
@gotStatus
|
|
move.b rFIFO(a3), D2 ; read status byte from FIFO
|
|
move.b D2, scsiSCSIstatus(A0) ; return status byte
|
|
|
|
moveq.l #mFIFOCount, d1 ; use mask to get FIFO flag field
|
|
and.b rFIFOflags(a3), d1 ; bytes left in FIFO?
|
|
bne.s @gotMsg ; ->if so, it's the message byte
|
|
cmp.b #kBusFreePhase, currentPhase(A5) ;
|
|
beq.s @scsiComplPhaseErr
|
|
@gotMsg
|
|
move.b rFIFO(A3), D2 ; read msg byte from FIFO
|
|
move.b D2, scsiSCSImessage(A0) ; and return message byte in PB also
|
|
move.b #1, HALactionPB.msgInLen(A4) ; say we returned 1 byte
|
|
|
|
RecCmd $12, 'A',$16
|
|
move.b #cMsgAccept, rCMD(a3) ; load msg accepted code which de-asserts *ACK
|
|
eieio
|
|
bsr Wt4SCSIInt ; Wait for intrp w/o timeout
|
|
@check4BusFree
|
|
cmp.b #kBusFreePhase, currentPhase(A5)
|
|
beq.s @disconnected ; if disconnected -> we're done
|
|
@badAcpt
|
|
bsr Ck4SCSIInt ; Check for intrp (bouncy REQ)
|
|
bne.s @check4BusFree ; got it -> go back to check for busfree
|
|
@scsiComplPhaseErr
|
|
move.w #SCResults.scsiSequenceFailed, D0 ; bad
|
|
@exitComplete
|
|
move.w D0, HALactionPB.result(A4) ; with whatever err
|
|
@disconnected ;
|
|
rts
|
|
|
|
NAME 'DoSCSIComplete'
|
|
|
|
|
|
;==========================================================================
|
|
;
|
|
; CyclePhase -- we may have to discard data or write filler bytes to get to
|
|
; the desired phase, status phase.
|
|
;
|
|
; This routine is broken into two main sections; standard I/O and Pseudo-DMA. The DMA
|
|
; sequence is used in case we are in the middle of a failed DMA transfer which left the
|
|
; transfer count nonzero. We only have to handle Pseudo-DMA in data phase. All other
|
|
; phases (and normal I/O mode data phase) are handled 1 byte at a time by individual
|
|
; phase handling code with, after each byte, returns to check the next phase to see
|
|
; where to go next.
|
|
;
|
|
; Phase Action
|
|
; ÑÑÑÑÑ ÑÑÑÑÑÑ
|
|
; Command: We send as many EE bytes as needed to get out of phase. If the select sequence
|
|
; flag 'NeedCmdSent' is set, it turns out that the chip will do the fill by itself
|
|
; once we send 1 rDMA byte (thereby completing the transfer) using
|
|
; rDMA. We also set the flag 'FCIntPend' bit if 'NeedCmdSent' was set.
|
|
;
|
|
; Msg_Out: We send as many 08(NOP) bytes as needed to get out of phase. If the select
|
|
; sequence flag 'NeedMsgOut' flag is set we set the flag 'NeedCmdSent' and continue.
|
|
;
|
|
; Data_In: We bitbucket as many bytes as needed to clear phase.
|
|
;
|
|
; Data_Out: We send as many EE bytes as needed to get out of phase.
|
|
;
|
|
;
|
|
; Note: We need to check if the SCSIMgr is busy in order to differentiate between
|
|
; IDLE bus phase and DATA OUT phase. They both have phase value = 0.
|
|
;
|
|
; Uses: d0
|
|
|
|
CyclePhase ; (accessed thru jvCyclePhase)
|
|
@checkNextPhase ;
|
|
move.b currentPhase(A5), d0 ; get phase value
|
|
|
|
cmp.b #kDataInPhase, d0 ;
|
|
beq.s @dumpDataIn ;
|
|
|
|
cmp.b #kDataOutPhase, d0 ;
|
|
beq.s @shoveDataOut ;
|
|
|
|
cmp.b #kCommandPhase, d0 ;
|
|
beq.w @shoveCommand ;
|
|
|
|
cmp.b #kMessageOutPhase, d0 ;
|
|
beq.w @shoveMsgOut ;
|
|
|
|
cmp.b #kMessageInPhase, d0 ;
|
|
beq.w @bitbucketMsgIn ;
|
|
|
|
cmp.b #kStatusPhase, d0 ;
|
|
bne.s @xferErr
|
|
@okExit
|
|
move.w #scComplPhaseErr, d0 ; tell SCSIComplete we had to read/write junk
|
|
rts ; err code is saved
|
|
|
|
@xferErr ;
|
|
clr.l d0 ; no recovery
|
|
rts
|
|
|
|
NAME 'CyclePhaseTOP'
|
|
|
|
;
|
|
; Data Phases - note that we no longer support the (pseudo) DMA bitbucketing here because
|
|
; the buserr handler should completely clean itself up before exiting out of the data
|
|
; routine/call.
|
|
;
|
|
; Data_In ------
|
|
;
|
|
@dumpDataIn
|
|
bsr Xfer1Byte96 ; xfer 1 byte and wait for intrp w/o timeout
|
|
move.b rFIFO(A3), D0 ; just empty the FIFO
|
|
bra.s @checkNextPhase
|
|
|
|
;
|
|
; Data_Out ------
|
|
;
|
|
@shoveDataOut
|
|
; DebugStr 'Old API bitbucketing'
|
|
move.b #$EE, rFIFO(a3) ; load filler byte into FIFO
|
|
eieio
|
|
bsr Xfer1Byte96 ; xfer 1 byte and wait for intrp w/o timeout
|
|
bra.s @checkNextPhase
|
|
|
|
|
|
;
|
|
; Command ------
|
|
;
|
|
@shoveCommand
|
|
tst.b G_State96(A5) ; did we expect this?
|
|
beq.s @cmdNonDMA ; no - bra, do xfer using FIFO
|
|
|
|
tst.b HBAhasPseudoDMA(A5)
|
|
beq.s @ck4hasDMA
|
|
move.w #$EEEE, rDMA(a3) ; use pseudo DMA (since chip is waiting for it)
|
|
eieio
|
|
bra.s @sentCmd
|
|
|
|
@ck4hasDMA
|
|
tst.b HBAhasDMA(A5)
|
|
bne.s @hasDMA
|
|
|
|
IfDebugStr 'Bad hwDesc - no DMA or pDMA'
|
|
moveq #dsIOCoreErr, D0
|
|
_SysError
|
|
|
|
@hasDMA
|
|
move.w #$EEEE, ([logicalCopyBuffer,A5]) ; put last bytes into our DMA buffer
|
|
|
|
move.w #false, -(sp) ; false = out
|
|
move.l #2, -(sp) ; send 2 bytes
|
|
move.l physicalCopyBuffer(A5), -(sp) ; starting at this physical address
|
|
jsr ([jvStartDMA,A5])
|
|
lea 10(sp), sp
|
|
jsr ([jvWt4DMAComplete,A5])
|
|
|
|
@sentCmd
|
|
bsr.w Wt4SCSIInt
|
|
;
|
|
; We have to flush the FIFO because of a bug in the c96. See the DoCommand routine for
|
|
; further information
|
|
;
|
|
@flushAndExit
|
|
RecCmd $01, 'A',$17
|
|
move.b #cFlushFIFO, rCMD(A3) ; Flush FIFO - REMEMBER THE CD-ROM BUG!!!
|
|
eieio
|
|
clr.b G_State96(A5)
|
|
bra.w @checkNextPhase
|
|
|
|
@cmdNonDMA
|
|
move.b #$EE, rFIFO(A3) ; load filler byte into FIFO
|
|
move.b #$EE, rFIFO(A3) ; load filler byte into FIFO
|
|
move.b #$EE, rFIFO(A3) ; load filler byte into FIFO
|
|
move.b #$EE, rFIFO(A3) ; load filler byte into FIFO
|
|
eieio
|
|
bsr Xfer1Byte96 ; send cmd and wait for intrp w/o timeout
|
|
bra.s @flushAndExit
|
|
|
|
|
|
;
|
|
; Message_Out ------
|
|
;
|
|
@shoveMsgOut
|
|
tst.b G_State96(A5) ; are we in cSelW(O)Atn process?
|
|
bne.s @ck4hasDMA ; yes-> go to cmd phase routine
|
|
move.b #$08, rFIFO(A3) ; load filler byte into FIFO (NOP message)
|
|
eieio
|
|
@needXferCmd
|
|
bsr Xfer1Byte96 ; xfer 1 byte and wait for intrp w/o timeout
|
|
bra.w @checkNextPhase
|
|
|
|
|
|
;
|
|
; Message-In ------
|
|
;
|
|
@bitbucketMsgIn
|
|
bsr Xfer1Byte96 ; xfer 1 byte and wait for intrp w/o timeout
|
|
move.b rFIFO(A3), D0 ; just empty the FIFO
|
|
|
|
RecCmd $12, 'A',$18
|
|
move.b #cMsgAccept, rCMD(a3) ; load msg accepted code which de-asserts ACK
|
|
eieio
|
|
|
|
bsr Wt4SCSIInt ; Wait for intrp w/o timeout
|
|
|
|
bra.w @checkNextPhase
|
|
|
|
|
|
RTSNAME 'CyclePhaseBOTTOM'
|
|
|
|
|
|
;==========================================================================
|
|
;
|
|
; AutoMsgIn
|
|
;
|
|
; Get message in bytes. If a HAL-recognized message, do what we need to do then
|
|
; return to caller (HALaction). If not, put entire message into buffer - either
|
|
; 2 bytes if msg=$2x, or extended message if 1st msg=01 (2+length bytes), or 1
|
|
; byte.
|
|
;
|
|
; Note: This routine, not being a HALaction proper, is not allowed to return an
|
|
; error in HALaction.result!
|
|
;
|
|
AutoMsgIn
|
|
@0
|
|
RecCmd $10, 'A',$24
|
|
move.b #cIOXfer, rCMD(A3)
|
|
eieio
|
|
bsr Wt4SCSIInt
|
|
bne UnexpectedDisc ; bus free? -> exit
|
|
|
|
moveq.l #0, D0
|
|
move.b rFIFO(A3), D0 ; retrieve first message from FIFO
|
|
|
|
IF RECORD_ON THEN
|
|
pea 'AMsg'
|
|
move.l D0, -(sp)
|
|
bsr RecordEvent
|
|
addq.l #8, sp
|
|
ENDIF
|
|
|
|
;
|
|
; Check for a one byte message that we recognize.
|
|
;
|
|
@ck4SaveDP
|
|
cmp.b #kSaveDataPointerMsg, D0
|
|
bne.s @ck4RestoreDP
|
|
|
|
RecCmd $12, 'A',$28
|
|
move.b #cMsgAccept, rCMD(A3) ; de-assert ACK
|
|
eieio
|
|
|
|
jsrv jvSaveDataPointer, A1 ;
|
|
bra.s @wt4acceptComp
|
|
|
|
@ck4RestoreDP
|
|
cmp.b #kRestorePointersMsg, D0
|
|
bne.s @ck4ExtendedMsg
|
|
|
|
RecCmd $12, 'A',$2c
|
|
move.b #cMsgAccept, rCMD(A3) ; de-assert ACK
|
|
eieio
|
|
|
|
jsrv jvRestorePointers, A1 ;
|
|
@wt4acceptComp
|
|
bsr Wt4SCSIInt
|
|
|
|
cmp.b #kMessageInPhase, currentPhase(A5) ; still in msg phase?
|
|
beq.w @0 ; yes-> go back and get next msg
|
|
bra @outOfPhase ; no: return to SIM w/new phase
|
|
|
|
;
|
|
; Check for extended message
|
|
;
|
|
@ck4ExtendedMsg
|
|
lea HALactionPB.msg(A4), A0
|
|
move.b D0, (A0)+ ; put the message in bfr
|
|
move.b #1, HALactionPB.msgInLen(A4) ;
|
|
|
|
cmp.b #kExtendedMsg, D0 ; extended msg?
|
|
bne @ck2byteMsg ; no->check 4 2-byte message
|
|
|
|
;
|
|
; Extended Msg: Accept 1st message, get 2nd message byte (length) then, for each
|
|
; byte in length, accept previous byte then get the next. This leaves ACK for
|
|
; last byte.
|
|
;
|
|
@get2ndMsg
|
|
bsr DoAcceptMsg
|
|
|
|
cmp.b #kMessageInPhase, currentPhase(A5)
|
|
bne @outOfPhase
|
|
|
|
RecCmd $10, 'A',$30
|
|
move.b #cIOXfer, rCMD(A3)
|
|
eieio
|
|
bsr Wt4SCSIInt
|
|
bne UnexpectedDisc ; bus free? -> exit
|
|
|
|
moveq.l #0, D0
|
|
move.b rFIFO(A3), D0 ; retrieve 2nd message from FIFO
|
|
move.b D0, (A0)+
|
|
bne.s @lpEnd ; non-zero-> byte is # of bytes left
|
|
move.w #$100, D0 ; zero-> 256 bytes left
|
|
bra.s @lpEnd ; loop: ack prev byte, get next
|
|
@lpTop
|
|
bsr DoAcceptMsg ; drop ACK, where does phase go?
|
|
|
|
cmp.b #kMessageInPhase, currentPhase(A5) ; still messageIn?
|
|
bne.s @outOfPhase ; no->out of here
|
|
|
|
RecCmd $10, 'A',$38
|
|
move.b #cIOXfer, rCMD(A3) ; get the byte (assert ACK)
|
|
eieio
|
|
bsr Wt4SCSIInt
|
|
bne UnexpectedDisc ; bus free? -> exit
|
|
|
|
move.b rFIFO(A3), (A0)+ ; retrieve next message from FIFO
|
|
addq.b #1, HALactionPB.msgInLen(A4) ;
|
|
@lpEnd
|
|
dbra D0, @lpTop
|
|
|
|
IF RECORD_ON THEN
|
|
pea 'XMsg'
|
|
move.l HALactionPB.msg(A4), -(sp)
|
|
bsr RecordEvent
|
|
addq.l #8, sp
|
|
ENDIF
|
|
@inPhase
|
|
move.b #kMessageInPhaseNACK, currentPhase(A5)
|
|
@outOfPhase
|
|
rts
|
|
|
|
;
|
|
; Check for a 2-byte message - this includes all messages of the form $2x. We don't
|
|
; interpret any 2-byte messages in the HAL so just get them and return.
|
|
;
|
|
@ck2byteMsg
|
|
and.b #$F0, D0
|
|
cmp.b #$20, D0 ; msg = $2x?
|
|
bne.s @inPhase ; no-> we're done
|
|
|
|
;
|
|
; If 2-byte msg, accept 1st byte then get second byte and return to caller
|
|
;
|
|
bsr.s DoAcceptMsg
|
|
|
|
cmp.b #kMessageInPhase, currentPhase(A5)
|
|
bne.s @outOfPhase
|
|
|
|
RecCmd $10, 'A',$40
|
|
move.b #cIOXfer, rCMD(A3)
|
|
eieio
|
|
bsr Wt4SCSIInt
|
|
bne UnexpectedDisc ; bus free? -> exit
|
|
|
|
moveq.l #0, D0
|
|
move.b rFIFO(A3), (A0)+ ; retrieve next message from FIFO
|
|
move.b #2, HALactionPB.msgInLen(A4) ; inc count
|
|
bra.s @inPhase
|
|
|
|
RTSNAME 'AutoMsgIn'
|
|
|
|
|
|
;==========================================================================
|
|
;
|
|
; AcceptMsg - accept a message
|
|
;
|
|
DoAcceptMsg
|
|
RecCmd $12, 'A',$44
|
|
move.b #cMsgAccept, rCMD(A3) ; de-assert ACK
|
|
eieio
|
|
|
|
bsr Wt4SCSIInt
|
|
rts ; don't touch result
|
|
|
|
NAME 'DoAcceptMsg'
|
|
|
|
|
|
;==========================================================================
|
|
;
|
|
; DoMsgOut - Send a message byte to the target
|
|
;
|
|
; Send the HALactionPB.msgLen message bytes in HALactionPB.msg[]. Don't change
|
|
; result (noErr) if all bytes sent, else, return err and indicate how many bytes
|
|
; WEREN'T sent in HALactionPB.msgOutLen. We will only be called if we are IN msg
|
|
; out phase already.
|
|
;
|
|
|
|
DoMsgOut
|
|
lea HALactionPB.msg(A4), A1 ; where the message is
|
|
|
|
tst.b G_State96(A5) ; Is this part of an old API Select w/ATN?
|
|
bne.s @oldAPI ; yes->
|
|
|
|
;
|
|
; If we didn't send a SelWAtn, then we need to stuff the FIFO full of the message bytes
|
|
; that we need to send then issue a xferInfo command which will drop ATN during the
|
|
; last byte. Hole: what about more than 16 message out bytes? HA!
|
|
;
|
|
@needXfer
|
|
moveq.l #0, D0
|
|
move.b HALactionPB.msgOutLen(A4), D0
|
|
bne.s @loopBtm
|
|
bra.s @goodExit
|
|
@loopTop
|
|
move.b (A1)+, rFIFO(A3) ; move msg byte into FIFO
|
|
@loopBtm
|
|
dbra D0, @loopTop ;
|
|
eieio
|
|
; now we sent all of the message bytes
|
|
|
|
RecCmd $10, 'A',$48
|
|
move.b #cIOXfer, rCMD(A3) ; load IO transfer cmd & begin xfers
|
|
eieio
|
|
bsr.w Wt4SCSIInt ; Wait for intrp w/o timeout
|
|
|
|
moveq.l #mFIFOCount, D0
|
|
and.b int_rFIFOflags(A5), D0 ; how many bytes left?
|
|
bne.s @phaseChange
|
|
@goodExit
|
|
rts
|
|
|
|
|
|
;
|
|
; If we sent a SelWAtn, we only need to stick the message byte (only 1) into the FIFO.
|
|
; The c96 and the target continue from there.
|
|
;
|
|
@oldAPI
|
|
move.b #NeedCmdSent, G_State96(A5) ; we will expect to see command phz
|
|
move.b #kCommandPhase, currentPhase(A5) ; pretend like we're there already
|
|
|
|
move.b (A1), rFIFO(A3) ; xfer msg byte
|
|
eieio
|
|
bra.s @goodExit ; don't wait for int - CDB needed first
|
|
|
|
|
|
@phaseChange
|
|
sub.b D0, HALactionPB.msgOutLen(A4) ; calc how many bytes were xferred
|
|
move.w #HALresult.kHALpartialMsgOut, HALactionPB.result(A4)
|
|
rts
|
|
|
|
NAME 'DoMsgOut'
|
|
|
|
|
|
|
|
;==========================================================================
|
|
;
|
|
; SetParity - Set the parity bit in the c96 configuration register2
|
|
; so that parity errors will be reported. Note that we
|
|
; turn this off at each disconnect to prevent problems on
|
|
; reconnects from devices that don't support parity.
|
|
;
|
|
;
|
|
SetParity
|
|
IF PARITY_ENABLED THEN
|
|
move.l HALactionPB.ioPtr(A4), A0 ; ptr to SCSI_IO pb
|
|
move.w SCSI_IO.scsiIOFlags(A0), D0 ; Get the flags field
|
|
and.w #scsiNoParityCheck,D0 ; Are we doing parity?
|
|
bne.s @noParity ; nope-> don't send an identify message
|
|
or.b #mCF1_EnableParity,rCF1(a3) ; set the parity bit
|
|
@noParity
|
|
ENDIF
|
|
rts
|
|
|
|
NAME 'SetParity'
|
|
|
|
|
|
|
|
;################################################################################
|
|
;********** Non-HALActions *********
|
|
;################################################################################
|
|
|
|
;==========================================================================
|
|
;
|
|
; HALSyncConfig - Configure registers for Synchronous Data Transfer
|
|
; 4 8 12
|
|
; void HALSyncConfig( offset, periodFactor, HALc96Globals * HALg );
|
|
;
|
|
HALSyncConfig
|
|
move.l A3, -(sp)
|
|
move.l A5, -(sp)
|
|
|
|
move.l 20(sp), A5 ; get HALg
|
|
move.l baseRegAddr(A5), A3 ; load A3 with base addr of 53c96
|
|
|
|
IF RECORD_ON THEN
|
|
pea 'SCfg'
|
|
move.w 22(sp), -(sp)
|
|
move.w 22(sp), -(sp)
|
|
bsr RecordEvent
|
|
addq.l #8, sp
|
|
ENDIF
|
|
|
|
move.l 16(sp), D0 ; get periodFactor
|
|
move.b (periodTable, D0.w), D1
|
|
bmi.s @illegalValue
|
|
and.b #$1f, D1
|
|
move.b D1, rSyncPeriod(A3)
|
|
|
|
cmp.b #50, D0 ; are we in Fast range?
|
|
bcc.s @notFast
|
|
or.b #mCF3_FastSCSI, rCF3(A3) ; set fast bit
|
|
bra.s @1
|
|
@notFast
|
|
and.b #~mCF3_FastSCSI, rCF3(A3) ; clr fast bit
|
|
@1
|
|
move.l 12(sp), D1 ; get offset
|
|
move.b D1, rSyncOffset(A3)
|
|
|
|
@illegalValue
|
|
move.l (sp)+, A5
|
|
move.l (sp)+, A3
|
|
rts
|
|
|
|
NAME 'HALSyncConfig'
|
|
|
|
|
|
;ÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉ
|
|
; set period 25
|
|
; loop
|
|
; if {period}<100
|
|
; echo -n "@0{period} "
|
|
; else
|
|
; echo -n "@{period} "
|
|
; end
|
|
; echo -n "dc.b "
|
|
; evaluate -h {period}*1000 div 625 div 10
|
|
; evaluate period+=1
|
|
; break if {period}==256
|
|
; end
|
|
;
|
|
;ÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉ
|
|
periodTable
|
|
@0 dc.b $80, $80, $80, $80, $80, $80, $80, $80
|
|
@8 dc.b $80, $80, $80, $80, $80, $80, $80, $80
|
|
@16 dc.b $80, $80, $80, $80, $80, $80, $80, $80
|
|
@24 dc.b $80
|
|
|
|
@025 dc.b $04
|
|
@026 dc.b $04
|
|
@027 dc.b $04
|
|
@028 dc.b $04
|
|
@029 dc.b $04
|
|
@030 dc.b $04
|
|
@031 dc.b $04
|
|
@032 dc.b $05
|
|
@033 dc.b $05
|
|
@034 dc.b $05
|
|
@035 dc.b $05
|
|
@036 dc.b $05
|
|
@037 dc.b $05
|
|
@038 dc.b $06
|
|
@039 dc.b $06
|
|
@040 dc.b $06
|
|
@041 dc.b $06
|
|
@042 dc.b $06
|
|
@043 dc.b $06
|
|
@044 dc.b $07
|
|
@045 dc.b $07
|
|
@046 dc.b $07 ; -
|
|
@047 dc.b $07 ; -
|
|
@048 dc.b $07 ; -
|
|
@049 dc.b $07 ; Fast SCSI bit set
|
|
|
|
@050 dc.b $08 ; Fast SCSI bit clr
|
|
@051 dc.b $08 ; -
|
|
@052 dc.b $08 ; -
|
|
@053 dc.b $08 ; -
|
|
@054 dc.b $08
|
|
@055 dc.b $08
|
|
@056 dc.b $08
|
|
@057 dc.b $09
|
|
@058 dc.b $09
|
|
@059 dc.b $09
|
|
@060 dc.b $09
|
|
@061 dc.b $09
|
|
@062 dc.b $09
|
|
@063 dc.b $0a
|
|
@064 dc.b $0a
|
|
@065 dc.b $0a
|
|
@066 dc.b $0a
|
|
@067 dc.b $0a
|
|
@068 dc.b $0a
|
|
@069 dc.b $0b
|
|
@070 dc.b $0b
|
|
@071 dc.b $0b
|
|
@072 dc.b $0b
|
|
@073 dc.b $0b
|
|
@074 dc.b $0b
|
|
@075 dc.b $0c
|
|
@076 dc.b $0c
|
|
@077 dc.b $0c
|
|
@078 dc.b $0c
|
|
@079 dc.b $0c
|
|
@080 dc.b $0c
|
|
@081 dc.b $0c
|
|
@082 dc.b $0d
|
|
@083 dc.b $0d
|
|
@084 dc.b $0d
|
|
@085 dc.b $0d
|
|
@086 dc.b $0d
|
|
@087 dc.b $0d
|
|
@088 dc.b $0e
|
|
@089 dc.b $0e
|
|
@090 dc.b $0e
|
|
@091 dc.b $0e
|
|
@092 dc.b $0e
|
|
@093 dc.b $0e
|
|
@094 dc.b $0f
|
|
@095 dc.b $0f
|
|
@096 dc.b $0f
|
|
@097 dc.b $0f
|
|
@098 dc.b $0f
|
|
@099 dc.b $0f
|
|
@100 dc.b $10
|
|
@101 dc.b $10
|
|
@102 dc.b $10
|
|
@103 dc.b $10
|
|
@104 dc.b $10
|
|
@105 dc.b $10
|
|
@106 dc.b $10
|
|
@107 dc.b $11
|
|
@108 dc.b $11
|
|
@109 dc.b $11
|
|
@110 dc.b $11
|
|
@111 dc.b $11
|
|
@112 dc.b $11
|
|
@113 dc.b $12
|
|
@114 dc.b $12
|
|
@115 dc.b $12
|
|
@116 dc.b $12
|
|
@117 dc.b $12
|
|
@118 dc.b $12
|
|
@119 dc.b $13
|
|
@120 dc.b $13
|
|
@121 dc.b $13
|
|
@122 dc.b $13
|
|
@123 dc.b $13
|
|
@124 dc.b $13
|
|
@125 dc.b $14
|
|
@126 dc.b $14
|
|
@127 dc.b $14
|
|
@128 dc.b $14
|
|
@129 dc.b $14
|
|
@130 dc.b $14
|
|
@131 dc.b $14
|
|
@132 dc.b $15
|
|
@133 dc.b $15
|
|
@134 dc.b $15
|
|
@135 dc.b $15
|
|
@136 dc.b $15
|
|
@137 dc.b $15
|
|
@138 dc.b $16
|
|
@139 dc.b $16
|
|
@140 dc.b $16
|
|
@141 dc.b $16
|
|
@142 dc.b $16
|
|
@143 dc.b $16
|
|
@144 dc.b $17
|
|
@145 dc.b $17
|
|
@146 dc.b $17
|
|
@147 dc.b $17
|
|
@148 dc.b $17
|
|
@149 dc.b $17
|
|
@150 dc.b $18
|
|
@151 dc.b $18
|
|
@152 dc.b $18
|
|
@153 dc.b $18
|
|
@154 dc.b $18
|
|
@155 dc.b $18
|
|
@156 dc.b $18
|
|
@157 dc.b $19
|
|
@158 dc.b $19
|
|
@159 dc.b $19
|
|
@160 dc.b $19
|
|
@161 dc.b $19
|
|
@162 dc.b $19
|
|
@163 dc.b $1a
|
|
@164 dc.b $1a
|
|
@165 dc.b $1a
|
|
@166 dc.b $1a
|
|
@167 dc.b $1a
|
|
@168 dc.b $1a
|
|
@169 dc.b $1b
|
|
@170 dc.b $1b
|
|
@171 dc.b $1b
|
|
@172 dc.b $1b
|
|
@173 dc.b $1b
|
|
@174 dc.b $1b
|
|
@175 dc.b $1c
|
|
@176 dc.b $1c
|
|
@177 dc.b $1c
|
|
@178 dc.b $1c
|
|
@179 dc.b $1c
|
|
@180 dc.b $1c
|
|
@181 dc.b $1c
|
|
@182 dc.b $1d
|
|
@183 dc.b $1d
|
|
@184 dc.b $1d
|
|
@185 dc.b $1d
|
|
@186 dc.b $1d
|
|
@187 dc.b $1d
|
|
@188 dc.b $1e
|
|
@189 dc.b $1e
|
|
@190 dc.b $1e
|
|
@191 dc.b $1e
|
|
@192 dc.b $1e
|
|
@193 dc.b $1e
|
|
@194 dc.b $1f
|
|
@195 dc.b $1f
|
|
@196 dc.b $1f
|
|
@197 dc.b $1f
|
|
@198 dc.b $1f
|
|
@199 dc.b $1f
|
|
@200 dc.b $00
|
|
@201 dc.b $00
|
|
@202 dc.b $00
|
|
@203 dc.b $00
|
|
@204 dc.b $00
|
|
@205 dc.b $00
|
|
@206 dc.b $00
|
|
@207 dc.b $01
|
|
@208 dc.b $01
|
|
@209 dc.b $01
|
|
@210 dc.b $01
|
|
@211 dc.b $01
|
|
@212 dc.b $01
|
|
@213 dc.b $02
|
|
@214 dc.b $02
|
|
@215 dc.b $02
|
|
@216 dc.b $02
|
|
@217 dc.b $02
|
|
@218 dc.b $02
|
|
@219 dc.b $03
|
|
@220 dc.b $03
|
|
@221 dc.b $03
|
|
@222 dc.b $03
|
|
@223 dc.b $03
|
|
@224 dc.b $03
|
|
|
|
@225 dc.b $84
|
|
@226 dc.b $84
|
|
@227 dc.b $84
|
|
@228 dc.b $84
|
|
@229 dc.b $84
|
|
@230 dc.b $84
|
|
@231 dc.b $84
|
|
@232 dc.b $85
|
|
@233 dc.b $85
|
|
@234 dc.b $85
|
|
@235 dc.b $85
|
|
@236 dc.b $85
|
|
@237 dc.b $85
|
|
@238 dc.b $86
|
|
@239 dc.b $86
|
|
@240 dc.b $86
|
|
@241 dc.b $86
|
|
@242 dc.b $86
|
|
@243 dc.b $86
|
|
@244 dc.b $87
|
|
@245 dc.b $87
|
|
@246 dc.b $87
|
|
@247 dc.b $87
|
|
@248 dc.b $87
|
|
@249 dc.b $87
|
|
@250 dc.b $88
|
|
@251 dc.b $88
|
|
@252 dc.b $88
|
|
@253 dc.b $88
|
|
@254 dc.b $88
|
|
@255 dc.b $88
|
|
|
|
;==========================================================================
|
|
;
|
|
; HALResetBus - Reset the scsi bus
|
|
;
|
|
; void HALResetBus( HALc96Globals * HALg );
|
|
;
|
|
HALResetBus
|
|
move.l A3, -(sp)
|
|
move.l A5, -(sp)
|
|
|
|
move.l 12(sp), A5 ; get HALg
|
|
move.l baseRegAddr(A5), A3 ; load A3 with base addr of 53c96
|
|
|
|
; move.w sr, -(sp) ; Block interrupts
|
|
; or.w #$0700, sr
|
|
|
|
IF RECORD_ON THEN
|
|
pea 'RstB'
|
|
move.l A1, -(sp)
|
|
bsr RecordEvent
|
|
addq.l #8, sp
|
|
ENDIF
|
|
|
|
jsrv jvResetBus, A1
|
|
|
|
; move.w (sp)+, sr ; restore interrupt level
|
|
|
|
move.l (sp)+, A5
|
|
move.l (sp)+, A3
|
|
rts
|
|
|
|
NAME 'HALResetBus'
|
|
|
|
;ÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉ
|
|
;
|
|
; DoReset - Reset the scsi bus
|
|
;
|
|
DoReset
|
|
; move.b #initCF1+mResetIntrpDisable, rCF1(A3) ; load init config value which affects:
|
|
; busID, SCSI reset reporting & parity checking
|
|
eieio
|
|
|
|
RecCmd $03, 'A',$4c
|
|
move.b #cResetSCSIBus, rCMD(A3) ; load reset scsi bus cmd - no int generated
|
|
; except that ResetO goes to ResetI which
|
|
; DOES generate an interrupt
|
|
eieio
|
|
;
|
|
; Just for the fun of it, we're going to wait 128mS, then reset that CF1 register
|
|
; then wait another 128mS and see if we got an interrupt - Just for the heck of it.
|
|
;
|
|
moveq.l #0, D0 ; clear upper word
|
|
move.w TimeDBRA, D0 ; get # of DBRAs per mS
|
|
lsl.l #7, D0 ; multiply by 128
|
|
move.l D0, D1 ; ...a 128mS wait
|
|
swap D1
|
|
@1 dbra D0, @1 ; D0 low word of counter
|
|
dbra D1, @1 ; D1 high word
|
|
|
|
; move.b #initCF1, rCF1(A3) ; reload init config value
|
|
eieio
|
|
|
|
moveq.l #0, D0 ; clear upper word
|
|
move.w TimeDBRA, D0 ; get # of DBRAs per mS
|
|
lsl.l #7, D0 ; multiply by 128
|
|
move.l D0, D1 ; ...a 128mS wait
|
|
swap D1
|
|
@2 dbra D0, @2 ; D0 low word of counter
|
|
dbra D1, @2 ; D1 high word
|
|
|
|
|
|
bsr Ck4SCSIInt ; did we get an interrupt?
|
|
; Did we? Who cares? I don't.
|
|
|
|
RecCmd $01, 'A',$50
|
|
move.b #cFlushFIFO, rCMD(a3) ; reset doesn't flush the @#$%^&! fifo!
|
|
eieio
|
|
|
|
move.b #kBusFreePhase, currentPhase(A5) ; in Bus Free Phase now
|
|
|
|
rts
|
|
|
|
NAME 'DoReset'
|
|
|
|
|
|
;==========================================================================
|
|
;
|
|
; HALAssertATN - Assert the ATN signal on the scsi bus <SM4> pdw
|
|
; 4
|
|
; void HALAssertATN( HALc96Globals * HALg );
|
|
;
|
|
HALAssertATN
|
|
move.l A3, -(sp)
|
|
move.l A5, -(sp)
|
|
|
|
move.l 12(sp), A5 ; get HALg
|
|
move.l baseRegAddr(A5), A3 ; load A3 with base addr of 53c96
|
|
|
|
move.l jvAssertATN(A5), A1
|
|
IF RECORD_ON THEN
|
|
pea 'AAtn'
|
|
move.l A1, -(sp)
|
|
bsr RecordEvent
|
|
addq.l #8, sp
|
|
ENDIF
|
|
|
|
jsr (A1)
|
|
|
|
move.l (sp)+, A5
|
|
move.l (sp)+, A3
|
|
rts
|
|
|
|
NAME 'HALAssertATN'
|
|
|
|
;ÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉ
|
|
;
|
|
DoAssertATN
|
|
RecCmd $1a, 'A',$54
|
|
move.b #cSetAtn, rCMD(A3)
|
|
eieio
|
|
|
|
rts
|
|
|
|
NAME 'DoAssertATN'
|
|
|
|
;==========================================================================
|
|
;
|
|
; HALTeardownIO -
|
|
; 8 4
|
|
; void HALTeardownIO( SCSI_IO * ioPtr, HALc96Globals * HALg );
|
|
;
|
|
HALTeardownIO
|
|
move.l 8(sp), A0 ; get HALg
|
|
move.l jvTeardownIO(A0), A0
|
|
IF RECORD_ON THEN
|
|
pea 'tdIO'
|
|
move.l A0, -(sp)
|
|
bsr RecordEvent
|
|
addq.l #8, sp
|
|
ENDIF
|
|
jmp (A0) ; calling through to a C routine so
|
|
; we leave parms as is on the stack
|
|
|
|
RTSNAME 'HALAssertATN'
|
|
|
|
;ÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉÉ
|
|
;
|
|
SetupIONoDMA
|
|
TeardownIONoDMA
|
|
|
|
rts
|
|
|
|
NAME 'Set/TearIONoDMA'
|
|
|
|
|
|
;################################################################################
|
|
;********** Utilities *********
|
|
;################################################################################
|
|
|
|
;==========================================================================
|
|
;
|
|
MoveSmallBlock
|
|
; D0 = number of bytes
|
|
; A1 = source
|
|
; A2 = dest
|
|
move.l @table(D0.w*4), D0
|
|
jmp @table(D0.w)
|
|
|
|
@table
|
|
dc.l @0-@table
|
|
dc.l @1-@table
|
|
dc.l @2-@table
|
|
dc.l @3-@table
|
|
dc.l @4-@table
|
|
dc.l @5-@table
|
|
dc.l @6-@table
|
|
dc.l @7-@table
|
|
dc.l @8-@table
|
|
dc.l @9-@table
|
|
dc.l @10-@table
|
|
dc.l @11-@table
|
|
dc.l @12-@table
|
|
dc.l @13-@table
|
|
dc.l @14-@table
|
|
dc.l @15-@table
|
|
dc.l @16-@table
|
|
|
|
@13
|
|
move.l (A1)+, (A2)+
|
|
@9
|
|
move.l (A1)+, (A2)+
|
|
@5
|
|
move.l (A1)+, (A2)+
|
|
@1
|
|
move.b (A1)+, (A2)+
|
|
@0
|
|
rts
|
|
|
|
@14
|
|
move.l (A1)+, (A2)+
|
|
@10
|
|
move.l (A1)+, (A2)+
|
|
@6
|
|
move.l (A1)+, (A2)+
|
|
@2
|
|
move.w (A1)+, (A2)+
|
|
rts
|
|
|
|
|
|
@15
|
|
move.l (A1)+, (A2)+
|
|
@11
|
|
move.l (A1)+, (A2)+
|
|
@7
|
|
move.l (A1)+, (A2)+
|
|
@3
|
|
move.w (A1)+, (A2)+
|
|
move.b (A1)+, (A2)+
|
|
rts
|
|
|
|
@16
|
|
move.l (A1)+, (A2)+
|
|
@12
|
|
move.l (A1)+, (A2)+
|
|
@8
|
|
move.l (A1)+, (A2)+
|
|
@4
|
|
move.l (A1)+, (A2)+
|
|
rts
|
|
|
|
NAME 'MoveSmallBlock'
|
|
|
|
ENDWITH
|
|
|
|
ENDPROC
|
|
END
|