mirror of
https://github.com/elliotnunn/supermario.git
synced 2024-11-29 05:49:19 +00:00
632 lines
24 KiB
Plaintext
632 lines
24 KiB
Plaintext
|
;
|
||
|
; 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
|
||
|
|
||
|
|