supermario/base/SuperMarioProj.1994-02-09/Drivers/Sony/SonyRead.a

632 lines
24 KiB
Plaintext
Raw Normal View History

2019-06-29 15:17:50 +00:00
;
; File: SonyRead.a
;
; Contains: This file contains disk driver routines used to read
; sector information from twiggy diskettes.
;
; Written by: Larry Kenyon
;
; Copyright: © 1982-1992 by Apple Computer, Inc. All rights reserved.
;
; Change History (most recent first):
;
; <SM6> 12/14/92 RC Restore Pre-PDM D2 with Horror rollin
; <SM4> 12/7/92 rab Roll in Horror changes. Comments follow…
; <H5> 6/19/92 CMP Patched SetUpPoll to set A6 to point to a bogus set of
; "registers" so that no SCC polling is done if there is no
; PollProc installed. This is because on DB Lite with LocalTalk
; connected to the internal serial port, we get so much poll data
; that we corrupt the heap.
; <H4> 11/14/91 SWC Converted the SCC polling code to a macro (in SonyHdr.a) so it's
; easier to overpatch. Also cleaned up comments.
; <6> 7/14/92 CSS Fixed the comment below so an exact version of this
; file could be copied into SuperMario.
; <5> 4/27/92 JSM Get rid of conditionals: hasHarpoVIA is always false,
; supportsMFM and forROM are always true. This file now has no
; conditionals.
; <4> 1/21/91 SWC Cleaned up header comments.
; <3> 9/21/90 BG Removed <2>. 040s are behaving more reliably now.
; <2> 6/18/90 CCH Added NOPs for flaky 68040's.
; <2.4> 5/23/89 GGD No changes to this file, entire Sony Driver is checked out and
; in as a group.
; <2.3> 4/29/89 GGD No changes to this file, entire Sony Driver is checked out and
; in as a group.
; <2.2> 4/10/89 gmr No changes to this file, entire Sony Driver is checked out and
; in as a group.
; <2.1> 2/21/89 GGD Added extra VIA accesses in read code to allow time for a new
; bit to shift in, and clear the data latch, so that a previous
; data byte doesn't get interpreted as a new byte on fast
; processors (25mhz). Changed bit number of SCC/VIA direction bit
; save in chipState.
; <2.0> 12/15/88 GGD Changed some machine based conditionals to feature based.
; Modified nibble timeout code in RdAddr to be processor speed
; independent.
; <1.1> 11/11/88 CCH Fixed Header.
; <1.0> 11/9/88 CCH Adding to EASE.
; <1.9> 9/29/88 GGD No changes to this file, entire Sony Driver is checked out and
; in as a group.
; <1.8> 9/19/88 GGD No changes to this file, entire Sony Driver is checked out and
; in as a group.
; <1.7> 8/16/88 GGD Changed usages of absolute VIA/SCC hardware addresses in
; SetUpPoll, to use low mem hw base addresses instead. Changed
; vBufA to vBufD for HcMac. Saved and changed VIA Buf B Direction
; bit in SetUpPoll for HcMac.
; <1.7> 8/9/88 Saved and changed VIA Buf B Direction bit in SetUpPoll for HcMac.
; <1.7> 8/5/88 GGD Changed usages of absolute VIA/SCC hardware addresses in
; SetUpPoll, to use low mem hw base addresses instead. Changed
; vBufA to vBufD for HcMac.
; <1.6> 7/15/88 GGD No changes to this file, entire Sony Driver is checked out and
; in as a group.
; <1.5> 6/15/88 GGD No changes to this file, entire Sony Driver is checked out and
; in as a group.
; <1.4> 5/25/88 GGD No changes to this file, entire Sony Driver is checked out and
; in as a group.
; <1.3> 5/24/88 GGD No changes to this file, entire Sony Driver is checked out and
; in as a group.
; <1.2> 5/3/88 GGD No changes, entire sony driver checked out and in as a group.
; <1.1> 4/18/88 GGD Merged in MFM support <C437> by Steve Christensen Renamed
; RdVerify to RVerify to eleminate the name conflict with the
; RdVerify equate in SysEqu.a (removes an ASM warning)
; <1.0> 2/12/88 BBM Adding file for the first time into EASE…
; <C965> 11/13/87 MSH Time-out loop in RdAddr was too short because we are so fast.
; <C907> 10/8/87 MSH Port to HcMac (Laguna).
; <C437> 11/21/86 SWC Patched RdAddr and RdData to jump to their MFM counterparts if
; we're running in MFM mode.
; <A351> 11/5/86 TJ Text cleanup
; <A302> 10/30/86 TJ Removed IWM absolute addresses.
; <C55> 6/25/86 RDC Increased no-nibble timeout for NuMac
; 11/2/85 LAK Use NewIntf instead of Sides when adjusting MustFndCnt.
; 7/29/85 RDC Changed interrupt level settings to use equates
; 7/24/85 LAK Convert back to WorkShop.
; 1/15/85 JTC convert to MDS.
; 10/26/84 LAK Patched RdAddr to compensate for missed nibbles after write
; (during erase) and increased no-nibble timeout.
; 8/18/83 LAK Addresses of AdrMks and DtaMks tables are passed thru vectors.
; 8/11/83 LAK Sets head select according to SideTrack.
; 8/4/83 LAK Added verify-only read (does it if lowmem var DskVerify is
; non-zero).
; 4/17/83 LAK Rewrote both RdAddr and RdData to incorporate SCC channel A
; polling scheme.
; 12/17/82 LAK Changed nibble "must-find" count to 1500 from 3000.
; 11/18/82 LAK Added head select setup and a search for some nibbles to avoid
; long delays on blank tracks
;
title 'File: SonyRead.a'
eject
;_______________________________________________________________________
;
; Routine: RdAddr,SetUpPoll,RdAddrSetup
; Arguments: A5.L (input) -- ptr to 6522 A-reg (has head sel, wait/req)
; A6.L (input) -- ptr to SCC A-channel data register
; A2.L (input) -- pointer to AdrMks table
; D0.W (output) --
; 0-1499 = no error, 1500 - nybbles before address mark
; -66 = no transitions found
; -67 = no address mark found (no header read)
; -68 = bad data nybble (header read aborted)
; -69 = bad checksum (header read but is inconsistent)
; -70 = bad bit slip marks (header read but may be bad)
; D1.W (output) -- <side><track> (low-order 12 bits)
; D2.W (output) -- <sector>
; D3.W (output) -- <volume>
; A3.L (output) -- ptr to <DNib-$96> (denibblizing table)
; A4.L (output) -- DiskQ6L pointer
; D4,D5,A0,A2 are trashed
; D6-D7 and A1,A5-A6 are preserved
; Function: This routine reads the next address mark that spins by. On exit,
; the attributes of the mark are passed back as:
;
; D1 = <side> <track>
; D2 = <sector>
; D3 = <volume>
;
; The disk should be up to speed with the correct head
; selected, and interrupts should be disabled.
;
; 'Nibble must find' count may have to be tuned.
;_______________________________________________________________________
BLANKS ON
STRING ASIS
AdrMks DC.B $D5,$AA,$96,$DE,$AA,$FF
; code-saving proc called by RdAddrSetUp and FigTrkSpeed
SetUpPoll MOVE.L JSetUpPoll,-(SP)
RTS
BogusSCC DCB.B 6,0 ; this is the bogus SCC register set <SM4>
jtSetUpPoll ; <SM4>
TST.L PollProc ; check to see if there is a pollproc <SM4>
BEQ.S @1 ; -> no, point A6 to a bogus place <SM4>
MOVEA.L SCCRd,A6 ; get SCC read base address <SM4>
BRA.S @2 ; <SM4>
@1 LEA BogusSCC,A6 ; fake SCC base address into A6 <SM4>
@2 ; <SM4>
ADDQ.L #AData,A6 ; SCC A-reg data <1.7>
MOVEA.L VIA,A5 ; get VIA base address <1.7>
ADDA.W #VBufD,A5 ; 6522 disk-reg has head sel, wait/req <1.7>
ORI #HiIntMask,SR ; no ints from now on! <29Jul85>
MOVE.L SP,PollStack ; init PollStack at current stack level
ADD.L D0,PollStack ; compensate for 1 or 2 levels
RTS
RdAddrSetup MOVEQ #8,D0 ; init PollStack 8 bytes down
BSR.S SetUpPoll
MOVEQ #RdDtaAdr,D0 ; assume side 0
BTST #3,SideTrack(A1) ; side 1?
BEQ.S @1 ; br if not
MOVEQ #RdDta1Adr,D0 ; set for side 1
@1 BSR AdrDisk
RdAddr
BSR GetDrv1 ;Get the drive offset <C437/21nov86>
TST.B mfmDisk(A1,D1) ;Are we in MFM mode? <C437/21nov86>
BMI mRdAddr ;-> yes, do the MFM version <C437/21nov86>
LEA AdrMks,A2 ; point to our mark table
MOVE.L JRdAddr,-(SP)
RTS
jtRdAddr
; When reading immediatly after a write, the drive may suppress read data for
; up to 620µsec, so we will wait at least that long for the first byte to be valid.
; We look for 3 bytes @16µsec per byte brings the total wait to 668µsec.
; There is an access to the VIA in the loop, which must synchronize with the 783khz
; clock (1.2765µsec per access), so we compute the timeout for the fastest processor
; which would be 668/1.2765 = 523 iterations, and add in another 10% for good measure
; to get 575. It doesn't hurt for it to be too big on slower processors, it would just
; take longer to get noNybErr which should never occur unless there is a hardware error.
MOVEQ #3,D3 ; try for 3 bytes
MOVE.W #575,D2 ; setup loop timeout count <2.0>
MOVEQ #0,D5 ; D5 is used for offsets, so clear it
movea.l IWM,A4 ; <A302/30oct86><2.0>
adda.w #Q6L,A4 ; A4 points to shiftreg for speed <A302/30oct86><2.0>
MOVE.L (SP)+,DskRtnAdr ; return address
@1 _PollSCC ; poll the SCC modem port <H4><SM4>
@2 MOVE.B (A4),D5 ; read a nibble
DBRA D2,@3 ; if no timeout yet, see if it was valid
MOVEQ #NoNybErr,D0 ; set CCR
BRA RdAddrXit
@3 BPL.S @1 ; try again if no nibble
SUBQ.W #1,D3 ; leave D3=0
BNE.S @1 ; if we can find 3, should be ok
MOVE.W #MustFindCt,D0 ; D0 holds nibble must find count
TST.B NewIntf(A1,D1) ; new interface drive? <02Nov85>
BEQ.S @4
MOVE.W #MustFindCt-32,D0
@4 LEA (DNib-$96),A3 ; A3 points to denibblizing table
RdAddr1 MOVE.L A2,A0 ; point to our mark table
MOVEQ #3,D1 ;
@1 MOVE.B (A4),D5 ;
BPL.S @1 ;
_PollSCC ; poll the SCC modem port <H4><SM4>
@2 DBRA D0,@3 ;
MOVEQ #NoAdrMkErr,D0 ; after 1500 tries report error
BRA.W RdAddrXit
@3 CMP.B (A0)+,D5 ;
BNE.S RdAddr1 ;
SUBQ.W #1,D1 ;
BNE.S @1 ; leave D1=0 (returns <side><track>)
; We found an address mark header so retrieve the information from the mark.
_PollSCC ; poll the SCC modem port <H4><SM4>
RdAddrMk MOVE.B (A4),D5 ; read track number byte
BPL.S RdAddrMk ;
MOVE.B 0(A3,D5.W),D1 ; denibblize it
MOVE.B D1,D4 ; init the checksum
ROR.W #6,D1 ; make room for 6 bits of side . . .
_PollSCC ; poll the SCC modem port <H4><SM4>
@2 MOVE.B (A4),D5 ; read sector number byte
BPL.S @2 ;
MOVEQ #0,D2 ; zero extend the sector number <2.0>
MOVE.B 0(A3,D5.W),D2 ; denibblize it
EOR.B D2,D4 ; calculate the checksum
_PollSCC ; poll the SCC modem port <H4><SM4>
@3 MOVE.B (A4),D5 ; read side number byte
BPL.S @3 ;
MOVE.B 0(A3,D5.W),D1 ; denibblize it
EOR.B D1,D4 ; calculate the checksum
ROL.W #6,D1 ; D1,bits 0-11 = <side><track>
_PollSCC ; poll the SCC modem port <H4><SM4>
@4 MOVE.B (A4),D5 ; read volume number byte
BPL.S @4 ;
MOVE.B 0(A3,D5.W),D3 ; denibblize it
EOR.B D3,D4 ; calculate the checksum
_PollSCC ; poll the SCC modem port <H4><SM4>
@5 MOVE.B (A4),D5 ; read checksum nibble
BPL.S @5 ;
MOVE.B 0(A3,D5.W),D5 ; denibblize it
EOR.B D5,D4
BNE.S BadCkSum ; report bad checksum
MOVEQ #1,D4 ; 2 bit slip marks
RdAddrEnd
_PollSCC ; poll the SCC modem port <H4><SM4>
@1 MOVE.B (A4),D5 ; get first trail nibble <2.1>
BPL.S @1 ; <2.1>
CMP.B (A0)+,D5 ; trail mark ok?
BNE.S NoSlip ; br if not
DBRA D4,RdAddrEnd
RdAddrXit BRA DskRtn ; return with D0 positive, BPL for ok
BadCkSum MOVEQ #BadCkSmErr,D0
BRA.S RdAddrXit
NoSlip MOVEQ #BadBtSlpErr,D0
BRA.S RdAddrXit
eject ; <A351/05nov86>
;_______________________________________________________________________
;
; Routine: RdData
; Arguments: A0.L (input) -- ptr to 512-byte data buffer
; A3.L (input) -- ptr to <DNib-$96> (denibblizing table)
; A4.L (input) -- DiskQ6L pointer
; A5.L (input) -- ptr to 6522 A-reg (has head sel, wait/req)
; A6.L (input) -- ptr to SCC channel A data register
;
; D0.W (output) --
; 0 = no error
; -71 = no data mark found
; -72 = bad checksum
; -73 = bad bit slip marks
; A3-A6 are preserved
; all other registers are trashed
; Function: This routine reads the next data mark that spins by. The 524
; bytes of data are split as follows: the first 12 bytes are put
; into TagData, the remaining 512 bytes into the buffer at (A0).
; This routine denibblizes and computes the checksum on the fly,
; so it may be used for one-to-one reading.
;
; The disk should be up to speed with the correct head
; selected, and interrupts should be disabled. This routine
; should be called immediately after RdAddr for disk reads.
;
; To do:
;
; Currently (on the SCC version Macintosh), there is no time to check each
; nibble when denibblizing data nibbles for $FF mappings; this should be added
; when this routine is put in ROM or run on a faster processor.
;
; An optimization could be added for missed address marks: if the calling
; routine is after a particular sector number and already knows which track
; it is on, this routine could be modified to check for that sector in the
; byte just before the encoded data, and return immediately on no match . . .
;_______________________________________________________________________
DtaMks DC.B $D5,$AA,$AD,$DE,$AA,$FF
RdData
BSR GetDrv1 ;Get the drive offset <C437/21nov86>
TST.B mfmDisk(A1,D1) ;Are we in MFM mode? <C437/21nov86>
BMI mRdData ;-> yes, do the MFM version <C437/21nov86>
LEA DtaMks,A1
MOVE.L JRdData,-(SP)
RTS
jtRdData MOVE.L (SP)+,DskRtnAdr ; save return address here
MOVEQ #48,D2 ; D2 holds nibble must find count
MOVEQ #0,D3 ; clear D3 for use as an index
MOVEQ #-64,D0 ; $C0 used to mask off bits 0-5
MOVE.L #$1FE000A,D4 ; byte read counts for 2 buffers
MOVEQ #0,D5 ; init CkSumA
MOVEQ #0,D6 ; init CkSumB
MOVEQ #0,D7 ; init CkSumC
; try to find a valid header until we've timed out
RdData1 MOVE.L A1,A2 ; address of address marks
MOVEQ #3,D1
@1 MOVE.B (A4),D3
BPL.S @1
_PollSCC ; poll the SCC modem port <H4><SM4>
@2 DBRA D2,@3
MOVEQ #NoDtaMkErr,D0 ; after 48 tries report error
BRA.S RdAddrXit
@3 CMP.B (A2)+,D3
BNE.S RdData1
SUBQ.W #1,D1
BNE.S @1 ; leave D1=0
; We found a data mark header so retrieve the information from the mark.
@4 MOVE.B (A4),D3 ; read the encoded sector number
BPL.S @4 ;
LEA TagData+1,A1 ; A1 points to buffer for extra bytes
MOVE.B 0(A3,D3.W),(A1)+ ;
;_______________________________________________________________________
;
; We found the header so the actual info is about to spin by. There are 699
; nibbles followed by 3 checksum nibbles. We use a four nibble loop for the
; data nibbles . . . the first 12 bytes go into a separate buffer, then 512
; bytes are placed in the user's buffer.
;
; D7 = CkSumC A7 = stack (where poll data is pushed)
; D6 = CkSumB A6 = ptr to SCC chan A data reg
; D5 = CkSumA A5 = ptr to 6522 A-reg
; D4 = loop counters A4 = ptr to Q6L (IWM)
; D3 = buffer A3 = ptr to denibblizing table
; D2 = buffer A2 = ptr to trail mark table
; D1 = buffer for odd bits A1 = ptr to data buffer
; D0 = $C0 mask A0 = ptr to user buffer
;_______________________________________________________________________
RdData2 _PollSCC ; poll the SCC modem port <H4><SM4>
@0 MOVE.B (A4),D3 ; read a nibble
BPL.S RdData2 ;
MOVE.B 0(A3,D3.W),D1 ; D1 = [00][00][A7][A6][B7][B6][C7][C6]
ROL.B #2,D1 ; D1 = [A7][A6][B7][B6][C7][C6][00][00]
MOVE.B D1,D2 ;
AND.B D0,D2 ; D2 = [A7][A6][00][00][00][00][00][00]
@1 MOVE.B (A4),D3 ; read a nibble
BPL.S @1 ;
OR.B 0(A3,D3.W),D2 ; D2 = ByteA' (no time for bad nibs)
MOVE.B D7,D3 ;
ADD.B D7,D3 ; ex <- CkSumC[7]
ROL.B #1,D7 ; CkSumC' <- ROL (CkSumC)
EOR.B D7,D2 ; ByteA <- ByteA' XOR CkSumC'
MOVE.B D2,(A1)+ ; store first byte
ADDX.B D2,D5 ; CkSumA',ex <- CkSumA + ByteA + ex
ROL.B #2,D1 ; D1 = [B7][B6][C7][C6][00][00][A7][A6]
MOVE.B D1,D2 ;
AND.B D0,D2 ; D2 = [B7][B6][00][00][00][00][00][00]
@2 MOVE.B (A4),D3 ; read a nibble
BPL.S @2 ;
OR.B 0(A3,D3.W),D2 ; D2 = ByteB' (no time for bad nibs)
EOR.B D5,D2 ; D2 = ByteB
MOVE.B D2,(A1)+ ; store second byte
ADDX.B D2,D6 ; CkSumB',ex <- CkSumB + ByteB + ex
ROL.B #2,D1 ; D1 = [C7][C6][0][0][A7][A6][B7][B6]
AND.B D0,D1 ; D1 = [C7][C6][0][0][0][0][0][0]
_PollSCC ; poll the SCC modem port <H4><SM4>
@3 MOVE.B (A4),D3 ; read a nibble
BPL.S @3 ;
OR.B 0(A3,D3.W),D1 ; D1 = ByteC' (no time for bad nibs)
EOR.B D6,D1 ; D1 = ByteC
MOVE.B D1,(A1)+ ; store third byte
ADDX.B D1,D7 ; CkSumC'' <- CkSumC' + ByteC + ex
SUBQ.W #3,D4 ; decrement counter by 3 bytes
BPL.S RdData2 ; loop (careful->subq changes ex bit)
SWAP D4 ; first time thru switch counters, buffers
TST.B DskVerify ; doing a read verify?
BEQ.S RdData3A ; br if not
BRA.S RdVer1 ; br if so (only verify, don't read)
RdData3 _PollSCC ; poll the SCC modem port <H4><SM4>
RdData3A MOVE.B (A4),D3 ; read a nibble
BPL.S RdData3 ;
MOVE.B 0(A3,D3.W),D1 ; D1 = [00][00][A7][A6][B7][B6][C7][C6]
ROL.B #2,D1 ; D1 = [A7][A6][B7][B6][C7][C6][00][00]
MOVE.B D1,D2 ;
AND.B D0,D2 ; D2 = [A7][A6][00][00][00][00][00][00]
@1 MOVE.B (A4),D3 ; read a nibble
BPL.S @1 ;
OR.B 0(A3,D3.W),D2 ; D2 = ByteA' (no time for bad nibs)
MOVE.B D7,D3 ;
ADD.B D7,D3 ; ex <- CkSumC[7]
ROL.B #1,D7 ; CkSumC' <- ROL (CkSumC)
EOR.B D7,D2 ; ByteA <- ByteA' XOR CkSumC'
MOVE.B D2,(A0)+ ; store first byte
ADDX.B D2,D5 ; CkSumA',ex <- CkSumA + ByteA + ex
ROL.B #2,D1 ; D1 = [B7][B6][C7][C6][00][00][A7][A6]
MOVE.B D1,D2 ;
AND.B D0,D2 ; D2 = [B7][B6][00][00][00][00][00][00]
@2 MOVE.B (A4),D3 ; read a nibble
BPL.S @2 ;
OR.B 0(A3,D3.W),D2 ; D2 = ByteB' (no time for bad nibs)
EOR.B D5,D2 ; D2 = ByteB
MOVE.B D2,(A0)+ ; store second byte
ADDX.B D2,D6 ; CkSumB',ex <- CkSumB + ByteB + ex
TST.W D4 ; check counter
BEQ.W RdCkSum ; we are done when counter is 0
ROL.B #2,D1 ; D1 = [C7][C6][0][0][A7][A6][B7][B6]
AND.B D0,D1 ; D1 = [C7][C6][0][0][0][0][0][0]
_PollSCC ; poll the SCC modem port <H4><SM4>
@3 MOVE.B (A4),D3 ; read a nibble
BPL.S @3 ;
OR.B 0(A3,D3.W),D1 ; D1 = ByteC' (no time for bad nibs)
EOR.B D6,D1 ; D1 = ByteC
MOVE.B D1,(A0)+ ; store third byte
ADDX.B D1,D7 ; CkSumC'' <- CkSumC' + ByteC + ex
SUBQ.W #3,D4 ; decrement counter by 3 bytes
BRA.S RdData3 ; loop (careful->subq changes ex bit)
RVerify _PollSCC ; poll the SCC modem port <H4><SM4>
RdVer1 MOVE.B (A4),D3 ; read a nibble
BPL.S RVerify ; <1.1/12feb88>
MOVE.B 0(A3,D3.W),D1 ; D1 = [00][00][A7][A6][B7][B6][C7][C6]
ROL.B #2,D1 ; D1 = [A7][A6][B7][B6][C7][C6][00][00]
MOVE.B D1,D2 ;
AND.B D0,D2 ; D2 = [A7][A6][00][00][00][00][00][00]
@1 MOVE.B (A4),D3 ; read a nibble
BPL.S @1 ;
OR.B 0(A3,D3.W),D2 ; D2 = ByteA' (no time for bad nibs)
MOVE.B D7,D3 ;
ADD.B D7,D3 ; ex <- CkSumC[7]
ROL.B #1,D7 ; CkSumC' <- ROL (CkSumC)
EOR.B D7,D2 ; ByteA <- ByteA' XOR CkSumC'
CMP.B (A0)+,D2 ; check first byte
BNE.S @4 ; (to RdVerErr) exit on errors
ADDX.B D2,D5 ; CkSumA',ex <- CkSumA + ByteA + ex
ROL.B #2,D1 ; D1 = [B7][B6][C7][C6][00][00][A7][A6]
MOVE.B D1,D2 ;
AND.B D0,D2 ; D2 = [B7][B6][00][00][00][00][00][00]
@2 MOVE.B (A4),D3 ; read a nibble
BPL.S @2 ;
OR.B 0(A3,D3.W),D2 ; D2 = ByteB' (no time for bad nibs)
EOR.B D5,D2 ; D2 = ByteB
CMP.B (A0)+,D2 ; compare second byte
BNE.W RdVerErr ; exit on errors
ADDX.B D2,D6 ; CkSumB',ex <- CkSumB + ByteB + ex
TST.W D4 ;
BEQ.S RdCkSum ; we are done when counter is 0
ROL.B #2,D1 ; D1 = [C7][C6][0][0][A7][A6][B7][B6]
AND.B D0,D1 ; D1 = [C7][C6][0][0][0][0][0][0]
_PollSCC ; poll the SCC modem port <H4><SM4>
@3 MOVE.B (A4),D3 ; read a nibble
BPL.S @3 ;
OR.B 0(A3,D3.W),D1 ; D1 = ByteC' (no time for bad nibs)
EOR.B D6,D1 ; D1 = ByteC
CMP.B (A0)+,D1 ; compare third byte
@4 BNE.S RdVerErr ; exit on errors
ADDX.B D1,D7 ; CkSumC'' <- CkSumC' + ByteC + ex
SUBQ.W #3,D4 ; decrement counter by 3 bytes
BRA.S RVerify ; loop (careful->subq changes ex bit) <1.1/12feb88>
; now read the four checksum nibbles and compare . . .
RdCkSum _PollSCC ; poll the SCC modem port <H4><SM4>
@0 MOVE.B (A4),D3 ; read a nibble
BPL.S @0 ;
MOVE.B 0(A3,D3.W),D1 ; D1 = [00][00][A7][A6][B7][B6][C7][C6]
BMI.S DCkSumBad ; branch if bad nibble
ROL.B #2,D1 ; D1 = [A7][A6][B7][B6][C7][C6][00][00]
MOVE.B D1,D2 ;
AND.B D0,D2 ; D2 = [A7][A6][00][00][00][00][00][00]
@1 MOVE.B (A4),D3 ; read a nibble
BPL.S @1 ;
MOVE.B 0(A3,D3.W),D3 ; D3 = [0][0][A5][A4][A3][A2][A1][A0]
BMI.S DCkSumBad ; br if bad nibble
OR.B D3,D2 ; D2 = CkSumA
CMP.B D2,D5 ; check against calculated value
BNE.S DCkSumBad ; br if bad
ROL.B #2,D1 ; D1 = [B7][B6][C7][C6][00][00][A7][A6]
MOVE.B D1,D2 ;
AND.B D0,D2 ; D2 = [B7][B6][00][00][00][00][00][00]
@2 MOVE.B (A4),D3 ; read a nibble
BPL.S @2 ;
MOVE.B 0(A3,D3.W),D3 ; D3 = [0][0][B5][B4][B3][B2][B1][B0]
BMI.S DCkSumBad ; branch if bad nibble
OR.B D3,D2 ; D2 = CkSumB
CMP.B D2,D6 ; check against calculated value
BNE.S DCkSumBad ; br if bad
ROL.B #2,D1 ; D1 = [C7][C6][00][00][A7][A6][B7][B6]
AND.B D0,D1 ; D1 = [C7][C6][00][00][00][00][00][00]
_PollSCC ; poll the SCC modem port <H4><SM4>
@3 MOVE.B (A4),D3 ; read a nibble
BPL.S @3 ;
MOVE.B 0(A3,D3.W),D3 ; D3 = [00][00][C5][C4][C3][C2][C1][C0]
BMI.S DCkSumBad ; branch if bad nibble
OR.B D3,D1 ; D1 = CkSumC
CMP.B D1,D7 ; check against calculated value
BEQ.S RdSlip ;
DCkSumBad MOVEQ #BadDCkSum,D0 ; bad checksum
BRA.S RdDataXit
RdVerErr MOVEQ #DataVerErr,D0
BRA.S RdDataXit
; finally we must read the bit slip marks before giving our stamp of approval
RdSlip MOVEQ #1,D4 ; 2 bit slip marks
@1 MOVE.B (A4),D3 ; get next trail nibble
BPL.S @1 ;
_PollSCC ; poll the SCC modem port <H4><SM4>
@2 CMP.B (A2)+,D3 ; trail mark ok?
BNE.S NoDSlip ; br if not
DBRA D4,@1
MOVEQ #0,D0 ; report success!!!
RdDataXit BRA DskRtn ; return with D0 positive, BPL for ok
NoDSlip MOVEQ #BadDBtSlp,D0 ; bad slip nibbles is error code 3 . . .
BRA.S RdDataXit
; Denibblizing Table (nibbles $96 thru $FF converted to $00 thru $3F)
; $FF means illegal nibble: if we checked for illegal nibbles (currently we
; don't have time for it), this table could be extended down to $80 . . .
DNib
DC.B $00,$01,$FF,$FF,$02,$03 ; $96,$97, , ,$9A,$9B
DC.B $FF,$04,$05,$06,$FF,$FF ; ,$9D,$9E,$9F, ,
DC.B $FF,$FF,$FF,$FF,$07,$08 ; , , , ,$A6,$A7
DC.B $FF,$FF,$FF,$09,$0A,$0B ; , , ,$AB,$AC,$AD
DC.B $0C,$0D,$FF,$FF,$0E,$0F ; $AE,$AF, , ,$B2,$B3
DC.B $10,$11,$12,$13,$FF,$14 ; $B4,$B5,$B6,$B7, ,$B9
DC.B $15,$16,$17,$18,$19,$1A ; $BA,$BB,$BC,$BD,$BE,$BF
DC.B $FF,$FF,$FF,$FF,$FF,$FF ; , , , , ,
DC.B $FF,$FF,$FF,$FF,$FF,$1B ; , , , , ,$CB
DC.B $FF,$1C,$1D,$1E,$FF,$FF ; ,$CD,$CE,$CF,
DC.B $FF,$1F,$FF,$FF,$20,$21 ; ,$D3, , ,$D6,$D7
DC.B $FF,$22,$23,$24,$25,$26 ; ,$D9,$DA,$DB,$DC,$DD
DC.B $27,$28,$FF,$FF,$FF,$FF ; $DE,$DF,
DC.B $FF,$29,$2A,$2B,$FF,$2C ; ,$E5,$E6,$E7, ,$E9
DC.B $2D,$2E,$2F,$30,$31,$32 ; $EA,$EB,$EC,$ED,$EE,$EF
DC.B $FF,$FF,$33,$34,$35,$36 ; , ,$F2,$F3,$F4,$F5
DC.B $37,$38,$FF,$39,$3A,$3B ; $F6,$F7, ,$F9,$FA,$FB
DC.B $3C,$3D,$3E,$3F ; $FC,$FD,$FE,$FF