mac-rom/Drivers/Sony/SonyRawTrack.a
Elliot Nunn 4325cdcc78 Bring in CubeE sources
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.
2017-12-26 09:52:23 +08:00

493 lines
18 KiB
Plaintext

;
; File: SonyRawTrack.a
;
; Contains: Support for the Raw Track Dump control call
;
; Written by: Steve Christensen 09-Nov-90
;
; Copyright: © 1990-1992 by Apple Computer, Inc. All rights reserved.
;
; This file is used in these builds: Mac32
;
; Change History (most recent first):
;
; <SM2> 2/18/93 rab Added a TestFor hwCbPwrMgr around the bsr to TurnIWMon so that
; CPUs without a PwrMgr won't get an unimplemented trap error.
; <1> 12/7/92 rab first checked in
; <H9> 9/22/92 DHN Fixed problem in ReadMFM with SWIM2 ASIC where rHandShake bit 8
; (data avail) goes high before its other bits are valid. We read
; rHandShake again to get the valid bits. There are other related
; fixes.
; <H8> 7/21/92 NJV Removed hasSonora1 conditionalized code (no longer needed)
; <H7> 6/4/92 CMP Fixed RawTrackDump to work properly for GCR disks with SWIM2.
; <H6> 3/6/92 CMP Increased mByteTOCnt to 60 to accomodate 33Mhz. CPUs.
; <H5> 12/20/91 JC Temporary Fix for problem in Sonora1
; <4> 11/14/91 SWC Moved SWIM2 check in RawRead to SonyPatches.a. Converted the SCC
; polling code to a macro to make it easier to overpatch.
; <3> 10/24/91 CMP Updated comment header for Horror ROM
; <2> 10/18/91 CMP Added support for SWIM2.
; ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
; Pre-HORROR ROM comments begin here.
; ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
; <3> 7/3/91 HJR Changed hasPowerMgr conditional to hasPwrControls.
; <2> 4/22/91 ag SWC/Fixed the parameter checking to be consistent with the IOP
; version. It was returning paramErr if the user specified index
; search mode for a GCR disk (no index pulse). It now forces the
; search mode to immediate instead.
; <1> 2/18/91 HJR first checked in
; 11/9/90 SWC New today.
;__________________________________________________________________________________________________
BLANKS ON
STRING ASIS
; call parameters (relative to csParam)
clockBuffer EQU 0
dataBuffer EQU 4
byteCount EQU 8
numDone EQU 12
searchMode EQU 16
theTrack EQU 18
side EQU 20
sector EQU 21
; searchMode values
searchNow EQU 0
searchAddr EQU 1
searchData EQU 2
searchIndex EQU 3
; misc stuff
indexAddr EQU tachAdr ; drive address to read the index pulse from
rtdParams EQU sectMap ; pointer to params in parameter block
; (steal sectMap since we don't use it at all)
;__________________________________________________________________________________________________
;
; Routine: CtlRawTrackDump
;
; Inputs: A0 -- pointer to caller's parameter block
; A1 -- pointer to SonyVars
; D0 -- error code if the drive number is invalid or the drive is not installed, else zero
; D1 -- drive locals offset
;
; Outputs: D0 -- result code
;
; Trashes: D1-D7,A0-A6
;
; Function: The call reads all or part of a track and returns the raw, unmassaged data it
; finds there so that applications can access a floppy disk at a very low level
; without having to directly access the hardware. The following parameters are
; passed starting at csParam:
;
; 0: clockBuffer pointer to packed bit array (MFM disks only), or nil
; 4: dataBuffer pointer to raw track data, or nil
; 8: byteCount number of bytes requested
; (dataBuffer must be able to hold this many bytes)
; 12: numDone number of bytes actually read (² byteCount)
; 16: searchMode when to start collecting bytes:
; 0 = as soon as spindle motor is up to speed
; 1 = after reading an address field
; 2 = after reading a data field
; 3 = at the index mark (MFM disks only)
; 18: track which track to read (0-79)
; 20: side which side to read (0-1)
; 21: sector which sector to synchronize on (0-255)
;
; If clockBitsBuffer is non-nil, it must point to a buffer that's at least 1/8th
; the size of dataBuffer. It consists of a packed array of bits signifying whether
; or not the corresponding byte in dataBuffer is a mark or data byte. If a bit
; is equal to "1", the byte is an MFM mark byte; if it's a "0", the byte is an
; MFM data byte. Bits for ASCENDING data bytes are arranged in DESCENDING order
; within a byte, i.e., bit 7 represents byte 0, bit 6 represents byte 1, etc.
;
; NOTE: If both clockBitsBuffer and dataBuffer are nil, the call will do nothing.
; This provides a way for applications to determine if the call exists
; without first having to allocate large buffers.
;__________________________________________________________________________________________________
CtlRawTrackDump
TST.W D0
BNE DiskDone ; -> bad drive number or no drive
LEA -512(SP),SP ; (get space for a buffer)
MOVE.L SP,DiskBuffer(A1)
; check all parameters and bail if any are out of range...
LEA csParam(A0),A0 ; point to the start of the passed parameters
MOVE.L A0,rtdParams(A1) ; and save the address for later
CLR.L numDone(A0) ; numDone=0
MOVE.L (A0)+,D0 ; are clockBuffer and dataBuffer both nil?
OR.L (A0)+,D0
BEQ.S @toRTDone ; -> yes, just exit
ADDQ.W #searchMode-dataBuffer-4,A0 ; (skip over byteCount)
MOVEQ #paramErr,D0 ; assume something's out of range
MOVE.W (A0)+,D7 ; get the search mode
CMPI.W #searchIndex,D7 ; valid search mode? <2>
BHI.S @toRTDone ; -> nope, bail <2>
BNE.S @CommonMode ; -> common MFM/GCR search mode <2>
TST.B mfmDisk(A1,D1) ; is this an MFM disk? <2>
BMI.S @CommonMode ; -> yes, all modes are OK <2>
CLR.W -2(A0) ; for GCR, force "index search" to "immediate search" <2>
@CommonMode MOVE.W (A0)+,D2 ; get the track number <2>
CMPI.W #80,D2 ; is it in range?
BHS.S @toRTDone ; -> nope
ROL.W #8,D2 ; D2.W=[track][0]
MOVE.B (A0)+,D2 ; get the sector number
CMPI.B #2,D2 ; is it in range?
@toRTDone BHS @RTDone ; -> nope
ASL.B #3,D2 ; shift it into bit 3
ROL.W #8,D2 ; D2.W=[0][0][0][0][side][track (11 bits)]
MOVE.W D2,sideTrack(A1) ; save the side and track numbers
MOVEQ #0,D2
MOVE.B (A0)+,D2
MOVE.W D2,curSector(A1) ; save the sector number
; setup the hardware as appropriate...
IF hasPwrControls THEN ; <3> HJR
TestFor hwCbPwrMgr ; do we have a PowerMgr? <SM2>
BEQ.S @pmgrdone ; if not, skip this call <SM2>
BSR TurnIWMon ; turn the IWM on with a power manager call
@pmgrdone ; <SM2>
ENDIF
TST.B isSWIM(A1) ; is a SWIM installed?
BPL.S @NoSWIM ; -> no, skip
BSR SetChipMode ; set up the mode for MFM or GCR
BNE @RTDone ; -> couldn't initialize the chip
@NoSWIM
BSR DiskSelect ; re-select the interface
BSR FVPowerUp ; and start up the drive (synchronously)
BSR SpdSeek ; seek to track and adjust speed if needed
BNE.S @RTDone ; -> couldn't seek so just exit with an error
; OK, we're on the selected track, so figure out where to start reading...
MOVEQ #4,D0 ; setup the poll stack just in case
BSR SetupPoll ; it's the immediate or index search mode
MOVEA.L rtdParams(A1),A0 ; point to our parameters
MOVE.W searchMode(A0),D7 ; so we can get the search mode (trashed by SpdSeek)
CMPI.W #searchIndex,D7 ; do we need to synch up on the index mark?
BNE.S @NotIndex ; -> nope
BSR.S SyncOnIndex ; go wait for the index pulse before beginning
BEQ.S @ReadNow ; -> we found it so start reading
BRA.S @RTCleanup ; -> couldn't find the index pulse
@NotIndex TST.W D7 ; do we just want to start reading?
BEQ.S @ReadNow ; -> yes, go for it!
; sync up on the desired sector by first looking for its address field...
MOVE.W #255,D6 ; since we can handle sector numbers 0-255...
@SyncLoop BSR RdAddrSetup ; read the next address mark
BMI.S @NextMark ; -> error, ignore this one
CMP.W sideTrack(A1),D1 ; is this the one we want?
BNE.S @NextMark ; -> no, keep looking
CMP.W curSector(A1),D2 ; is this the sector we want?
BEQ.S @FoundAddr ; -> yes, all done
@NextMark BSR toEmptyPD ; get rid of poll data (saves D0 in DskErr)
DBRA D6,@SyncLoop ; -> keep looking
MOVEQ #sectNFErr,D0 ; return "sector not found"
BRA.S @RTDone
@FoundAddr SUBQ.W #searchAddr,D7 ; start reading after address field?
BEQ.S @ReadNow ; -> yes!
; if we get here, we need to first read this sector's data field...
MOVEA.L diskBuffer(A1),A0 ; point to our stack buffer for someplace to put the data
CLR.B DskVerify ; don't verify the data
BSR RdData ; go read the data field
BMI.S @RTDone ; -> an error occurred, so bail
; we're now in the correct position on the disk to begin collecting raw data, so setup and go...
@ReadNow BSR.S RawRead ; go read the bytes
BNE.S @RTCleanup ; -> something bad happened
MOVEA.L SonyVars,A1 ; point to the driver's variables
MOVEA.L rtdParams(A1),A1 ; and from there point to our parameters
MOVE.L byteCount(A1),numDone(A1) ; we were successful, so update how much we read
@RTCleanup BSR toEmptyPD ; get rid of poll data (saves D0 in DskErr)
ANDI.W #$F8FF,SR ; turn interrupts back on
@RTDone LEA 512(SP),SP ; clean up the stack
BRA DskRWOff ; share SonyRWT exit routine
;__________________________________________________________________________________________________
;
; Routine: SyncOnIndex
;
; Inputs: D1 -- offset to drive-specific variables
; A1 -- pointer to driver's variables
;
; Outputs: D0 -- result code
;
; Trashes: D0-D2,A0,A2 (all other registers are preserved)
;
; Function: waits for the start of the index pulse (or times out if it doesn't see it)
;__________________________________________________________________________________________________
SyncOnIndex MOVE.L (SP)+,DskRtnAdr ; save the return address
MOVEQ #indexAddr,D0 ; select the index sense drive address
BSR AdrDisk
MOVEQ #100+10,D2 ; assume HD disk -> 600rpm = 100ms (+10%)
TST.B twoMegFmt(A1,D1) ; is it?
BMI.S @SetTimeout
ADD.W D2,D2 ; no, it's 720K -> 300rpm = 200ms (+10%)
@SetTimeout MULU TimeDBRA,D2 ; figure out how many iterations are in that time
MOVEA.L IWM,A4 ; point to the handshake register for speed
LEA rHandshake(A4),A4
MOVEQ #NoErr,D0 ; assume we'll sync up OK
@WtIndexLo _PollSCC ; poll the SCC modem port <H4>
@NoSCCLo
BTST #3,(A4) ; is the index pulse low yet?
BEQ.S @WtIndexHi ; -> yes, wait for it to go high
SUBQ.L #1,D2
BGT.S @WtIndexLo
BRA.S @NoIndex
@WtIndexHi _PollSCC ; poll the SCC modem port <H4>
@NoSCCHi
BTST #3,(A4) ; is the index pulse high yet?
BNE.S @IndexDone ; -> yes, we're sync'd up
SUBQ.L #1,D2
BGT.S @WtIndexHi
@NoIndex MOVEQ #noIndexErr,D0 ; timed out waiting for index
@IndexDone BRA DskRtn ; set CCR and return
;__________________________________________________________________________________________________
;
; Routine: RawRead
;
; Inputs: A5 -- pointer to 6522 A-reg (has head sel, wait/req)
; A6 -- pointer to SCC channel A data register
;
; Outputs: D0 -- result code
;
; Trashes: D1-D3,A0-A4 (all other registers are preserved)
;
; Function: reads data bytes into data buffer and clock bytes into clockBuffer
;__________________________________________________________________________________________________
RawRead BSR GetDrv1 ; setup A1,D1
MOVEQ #RdDtaAdr,D0 ; assume we want side 0
BTST #3,SideTrack(A1) ; is it?
BEQ.S @SelectSide ; -> yes
MOVEQ #RdDta1Adr,D0 ; use the side 1 address
@SelectSide BSR AdrDisk ; select the head
MOVEA.L rtdParams(A1),A4 ; point to our parameters:
MOVEA.L (A4)+,A2 ; clockBuffer
MOVEA.L (A4)+,A0 ; dataBuffer
MOVE.L (A4)+,D0 ; byteCount
TST.B mfmDisk(A1,D1) ; is this an MFM disk? <SM1>
BMI.W ReadMFM ; -> yes, go read it <SM1>
CMP.B #-2,isSWIM(A1) ; do we have a SWIM2? <SM1>
BEQ.W ISMReadGCR ; -> yes, read gcr the ISM way <SM1>
BRA.S ReadGCR ; no, read GCR the old fashioned way <SM1>
;__________________________________________________________________________________________________
;
; Routine: ReadMFM
;
; Inputs: D0 -- number of bytes to read
; D1 -- offset to drive-specific variables
; A0 -- pointer to dataBuffer
; A1 -- pointer to driver's variables
; A2 -- pointer to clockBuffer
; A5 -- pointer to 6522 A-reg (has head sel, wait/req)
; A6 -- pointer to SCC channel A data register
;
; Outputs: D0 -- result code
;
; Trashes: D1-D3,A0,A2-A4 (all other registers are preserved)
;
; Function: reads raw data starting with the next mark byte after a sync field
;__________________________________________________________________________________________________
ReadMFM MOVE.L (SP)+,DskRtnAdr ; save the return address
MOVEA.L IWM,A4
LEA rHandshake(A4),A3 ; point to the handshake and mark registers for speed
LEA rMark(A4),A4
TST.B rError-rMark(A4) ; clear the error register
MOVE.B #$18,wZeroes-rMark(A4) ; clear the write and action bits
MOVE.B #$01,wOnes-rMark(A4) ; toggle the clFIFO bit to clear out
MOVE.B #$01,wZeroes-rMark(A4) ; any data in the FIFO
TST.B rError-rMark(A4) ; clear the error register again for grins
MOVE.B #$08,wOnes-rMark(A4) ; turn on the action bit: GO!
MOVEQ #-1,D2 ; initial timeout counter (needs to be tuned)
BRA.S @StartRead
@Wait4Byte _PollSCC ; poll the SCC modem port <H4>
@NoSCCData TST.B (A3) ; wait for a byte <H9>
DBMI D2,@Wait4Byte
BPL.S RawReadTOErr ;-> timeout <SM1>
MOVE.B (A3),D3 ;Get the handshake register with valid bits <SM1>
MOVEQ #mByteTOCnt,D2 ; reset the timeout counter for the next byte <SM1>
MOVE.B (A4),(A0)+ ; read the current byte into dataBuffer
LSR.B #1,D3 ; bit 0 is the mark bit
ADDX.B D1,D1 ; shift it into bit 0 to acculumate it
BCC.S @NextByte
MOVE.B D1,(A2)+ ; we've grabbed 8 bits, so stuff them into clockBuffer
@StartRead MOVEQ #1,D1 ; initialize the "bits" register (8 shifts will set C=1)
@NextByte SUBQ.L #1,D0 ; decrement the byte count
BGE.S @Wait4Byte ; -> more left to do
CMPI.B #1,D1 ; is the last clockBits byte partially filled?
BEQ.S @ReadOK
@AlignBits ADD.B D1,D1 ; no, shift the bits so they start at bit 7 down
BCC.S @AlignBits
MOVE.B D1,(A2)+
@ReadOK MOVEQ #NoErr,D0
RawReadExit MOVE.B #$18,wZeroes-rMark(A4) ; clear the write and action bits to turn everything off
BRA DskRtn ; set CCR and return
RawReadTOErr
MOVEQ #dataTOErr,D0 ; timed out waiting for a byte
BRA.S RawReadExit
;__________________________________________________________________________________________________
;
; Routine: ReadGCR
;
; Inputs: D0 -- number of bytes to read
; D1 -- offset to drive-specific variables
; A0 -- pointer to dataBuffer
; A1 -- pointer to driver's variables
; A2 -- pointer to clockBuffer (not used)
; A5 -- pointer to 6522 A-reg (has head sel, wait/req)
; A6 -- pointer to SCC channel A data register
;
; Outputs: D0 -- result code
;
; Trashes: D1-D2,A0,A4 (all other registers are preserved)
;
; Function: reads raw data as soon as possible
;__________________________________________________________________________________________________
ReadGCR MOVE.L (SP)+,DskRtnAdr ; save the return address
MOVEA.L IWM,A4 ; point to the data register for speed
LEA q6L(A4),A4
MOVEQ #-1,D2 ; initial timeout counter (needs to be tuned)
BRA.S @StartRead
@Wait4Byte _PollSCC ; poll the SCC modem port <H4>
@NoSCCData MOVE.B (A4),D1 ; wait for a byte
DBMI D2,@Wait4Byte
BPL.S @ReadTOErr ; -> timed out
MOVE.B D1,(A0)+ ; put the current byte into dataBuffer
MOVEQ #mByteTOCnt,D2 ; reset the timeout counter for the next byte
@StartRead SUBQ.L #1,D0 ; decrement the byte count
BGE.S @Wait4Byte ; -> more left to do
MOVEQ #NoErr,D0
@ReadExit BRA DskRtn ; set CCR and return
@ReadTOErr MOVEQ #dataTOErr,D0 ; timed out waiting for a byte
BRA.S @ReadExit
;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ <SM1> begin
;
; Routine: ISMReadGCR
;
; Inputs: D0 -- number of bytes to read
; D1 -- offset to drive-specific variables
; A0 -- pointer to dataBuffer
; A1 -- pointer to driver's variables
; A2 -- pointer to clockBuffer
; A5 -- pointer to 6522 A-reg (has head sel, wait/req)
; A6 -- pointer to SCC channel A data register
;
; Outputs: D0 -- result code
;
; Trashes: D1-D3,A0,A2-A4 (all other registers are preserved)
;
; Function: reads raw data starting with the next mark byte after a sync field
;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
ISMReadGCR MOVE.L (SP)+,DskRtnAdr ; save the return address
MOVEA.L IWM,A4
LEA rHandshake(A4),A3 ; point to the handshake and mark registers for speed
LEA rMark(A4),A4
TST.B rError-rMark(A4) ; clear the error register
MOVE.B #$18,wZeroes-rMark(A4) ; clear the write and action bits
MOVE.B #$01,wOnes-rMark(A4) ; toggle the clFIFO bit to clear out
MOVE.B #$01,wZeroes-rMark(A4) ; any data in the FIFO
TST.B rError-rMark(A4) ; clear the error register again for grins
MOVE.B #$08,wOnes-rMark(A4) ; turn on the action bit: GO!
MOVEQ #-1,D2 ; initial timeout counter (needs to be tuned)
BRA.S @StartRead
@Wait4Byte _PollSCC ; poll the SCC modem port <H4>
TST.B (A3) ; wait for a byte
DBMI D2,@Wait4Byte
BPL.S @ReadTOErr ; -> timed out
MOVEQ #mByteTOCnt,D2 ; reset the timeout counter for the next byte
MOVE.B (A4),(A0)+ ; read the current byte into dataBuffer
@StartRead SUBQ.L #1,D0 ; decrement the byte count
BGE.S @Wait4Byte ; -> more left to do
MOVEQ #NoErr,D0
@ReadExit MOVE.B #$18,wZeroes-rMark(A4) ; clear the write and action bits to turn everything off
BRA DskRtn ; set CCR and return
@ReadTOErr MOVEQ #dataTOErr,D0 ; timed out waiting for a byte
BRA.S @ReadExit ; <SM1> end