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

939 lines
38 KiB
Plaintext
Raw Normal View History

2019-06-29 15:17:50 +00:00
;
; File: SonyRWT.a
;
; Contains: Sony 3.5" Floppy Disk Driver Read/Write Track Logic
;
; Written by: Larry Kenyon 05-May-83
;
; Copyright: © 1983-1993 by Apple Computer, Inc. All rights reserved.
;
; Change History (most recent first):
;
; <SM9> 12/13/93 PN Roll in KAOs and Horror changes to support Malcom and AJ
; machines
; <SM8> 1/10/93 RC Added Nop for Smurf
; <SM7> 12/14/92 RC Restore Pre-PDM D2 with Horror Roll-in
; <SM5> 12/7/92 rab Roll in Horror changes. Comments follow…
; <H4> 2/13/92 CMP Patched AdrDtaErr to check if retries are disabled before
; attempting them.
; <H2> 10/18/91 CMP Overpatch for SWIM2 support. Also, changed the way the drives are
; disabled since those signals are no longer gated by MotorOn.
; <SM1> 12/02/92 HY Put back hasPwrControls conditional (for LC930, non-universal)
; and fix a branch out of range.
; <5> 7/14/92 CSS Fixed the comment below so an exact version of this
; file could be copied into SuperMario.
; <4> 4/27/92 JSM Get rid of conditionals: supportsPWM, supportsDCD, and
; hasHarpoVIA are always false, forROM, supportsMFM, forDiskDup,
; isUniversal, hasPowerMgr, and hasPwrControls are always true
; (although hasPowerMgr currently isnt for the ROM, it will be
; and was always ORed with hasPwrControls here anyway). This file
; now has no conditionals.
; <3> 1/21/91 SWC Cleaned up header comments.
; <2> 5/11/90 MSH Converted all onHcMac or hasPowerMgr conditionals to universal
; versions. Test is based on the existence of the power manager
; bit in the config word.
; <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 Fixed bugs in GotSect, was using (a1,d6), but d6 may be invalid,
; use (a1,d1) instead, since GetDrv1 has been called. Let new
; interface drives (800K/SuperDrive) attempt 1 to 1 writes, since
; it will always work in MFM, and should usually work in GCR.
; 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.
; <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.8> 8/19/88 SWC Save the format byte returned by RdAddr if for disk duplicator.
; <1.7> 8/16/88 GGD Restored VIA Buf B Direction bit in EmptyPD for HcMac
; <1.7> 8/9/88 GGD Restored VIA Buf B Direction bit in EmptyPD 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/23/88 GGD No changes, entire sony driver 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
; <C437> 3/28/88 SWC GotSect: made 1-sector-wait on writes for GCR disks only (MFM
; does 1-1).
; <C437> 2/22/88 SWC OnTrack1: restored drive vars offset to D6 after RdData trashes
; it.
; <1.0> 2/12/88 BBM Adding file for the first time into EASE…
; 2/4/88 SWC DiskPrime: moved the SetChipMode and DiskSelect calls to before
; the branch to the DCD code (this was duplicated but now removed
; from SonyDCD).
; <C907> 10/13/87 MSH Port to HcMac (Laguna).
; 10/8/87 SWC Decrement the sector number for MFM disks when calculating cache
; offsets since MFM disks start with sector 1.
; 9/30/87 SWC Don't call SetChipMode if an IWM is installed and SetIWMMode
; wouldn't have been called anyway.
; <C437> 12/4/86 SWC Check disk format on entry if the disk is unclamped. Patched
; GetTrack to jump to mGetTrack (SonyMFM.a) if we're running in
; MFM mode (different sector layout). Set sector time to 7.5ms for
; MFM disks in OnTrack since the track format has fixed sector
; spacing.
; <C115> 8/22/86 TJ Made 400K Sony drive support conditional under 'supportsPWM';
; not supported on nuMac.
; <C97> 8/5/86 TJ Disabled some cache code so that writes update the disk, and
; hence the tags. (Tags were not in sync w/ sector data.)
; <C1> 5/5/86 RDC Changed old onMidmac conditional to onNuMac
; 11/3/85 LAK Fixed bug in last fix (track cacheing was always turned off).
; 10/31/85 LAK Turn off cache if RDData hook has been replaced (attempt to get
; other copy-protection schemes to work).
; 10/29/85 LAK Turn off cache on read errors (attempt to get Jazz copy
; protection to work reasonably).
; 10/25/85 LAK Skip thermal drift adjust for new drive (still check it). Use
; NewIntf rather than Sides to determine whether drive has new
; interface. Increment DriveErrs for address and data errors. On
; RWT waits, set up timer first before calling EmptyPD for more
; accurate waits (use TimeSetUp and TimeGo).
; 10/24/85 LAK Added support for track caching. Open up all ints after r/w of a
; sector to see if this fixes keyboard.
; 10/22/85 LAK Use CurSector to store sector number we are reading/writing
; instead of using TagData low-memory var which is overwritten on
; reads. For writes, don't allow retries before reseek for bad
; addrmark errors (should reduce the likelihood off-track
; trashing).
; 9/2/85 LAK Give an early warning for two-sided diskettes in old drives (new
; file system doesn't catch it as quickly).
; 8/14/85 LAK Don't overwrite TagData+10 with Time on writes.
; 7/29/85 RDC Added changes for MidMac: - changed interrupt level settings to
; use equates - removed DCD code - skip track speed checking
; 1/15/85 JTC Converted to MDS
; 11/10/84 LAK Cut enable to drive if no DIP at prime: try to prevent drive
; tick.
; 11/2/84 LAK Sped up logical block mapping.
; 10/26/84 LAK Patched Got1Sect to make 2-1 write possible; interrupts are
; always enabled now after every sector and 1-1 writes are always
; prevented.
; 8/20/83 LAK Added support of SpdAdjErr, SeekErr, SectNFErr (D0 did not
; necessarily have an error code in these cases).
; 8/20/83 LAK Added test of DskWr11 boolean before giving up on 1-1 writing.
; 8/15/83 LAK Verify mode bit is bit 6 now; added Andy's optimizations.
; 8/11/83 LAK Removed statistics; added support for 2-sided drives.
; 8/6/83 LAK Added support for read/verify mode. Increments RndSeed when
; wrong sector passes by . . .
; 7/24/83 LAK Fixed bug in EmptyPD (serial driver trashes A1 . . .) by
; reverting to ROM 3.1 code.
; 7/21/83 LAK If TagBufStrt drive variable is non-zero, tag data is now
; stripped from the data stream and read/written to/from the
; separate buffer.
; 7/10/83 LAK Fixed bug in thermal-drift compensation code.
; 6/23/83 LAK Updated to compensate for speed thermal drift! Subroutined the
; 'drive exist' and 'disk-in-place' checks to share with the disk
; VBL task.
; 5/27/83 LAK Changed for new 5-speed class format
; 5/11/83 LAK MakeSpdTbl no longer trashes A1 on error path (in DoRecal).
; 5/5/83 LAK Adapted from twiggy driver for 3-1/2 inch drive . . .
;
title 'File: SonyRWT.a'
;_______________________________________________________________________
;
; This is the mainline of the disk driver. It processes
; the request parameter block a track at a time.
;
; Arguments: A0 (input) -- pointer to request parameter block
; A1 (input) -- pointer to disk DCE
;_______________________________________________________________________
; Here is the prime routine, which gets reads and writes going.
BLANKS ON
STRING ASIS
DiskPrime MOVE.L JDiskPrime,-(SP)
RTS
jtDiskPrime ORI #VIAIntMask,SR ; exclude VBL interrupts <29Jul85>
MOVE.W IOTrap(A0),D3 ; save I/O command
BTST #6,IOPosMode+1(A0) ; check for read verify mode
SNE DskVerify ; note for later
BSR.S CkDrvNum ; check for valid drive number and setup
BNE DiskErr ; exit if bad drive error
MOVE.W D3,Command(A1) ; note I/O command
; ok, we should already know what's connected out there . . .
; if nothing, then just exit. . . otherwise, select the drive
; and continue . . .
MOVEQ #NoDriveErr,D0 ; assume no drive installed <03Mar85>
TST.B Installed(A1,D1) ; 1=installed, $FF=not <03Mar85>
BMI DiskErr ; exit if nothing connected <03Mar85><C437/14sep87>
IF hasPwrControls THEN ; <SM1>
TestFor hwCbPwrMgr
BEQ.S @pmgrdone
BSR TurnIWMon ; Turn IWM on with pmgr call <C907>
@pmgrdone
ENDIF ; <SM1>
TST.B isSWIM(A1) ;Is a SWIM installed? <C437/30sep87>
BPL.S @00 ;-> no, skip <C437/30sep87>
BSR SetChipMode ;Make sure the chip is set up OK <C437/14sep87>
@00 ; <C437/30sep87>
BSR DiskSelect ; select the appropriate interface
; check disk-in-place at the drive . . . (may have been manually ejected)
MOVEQ #DIPAdr,D0 ;
BSR AdrAndSense ; sets up A0,A1,A2,D1
BPL.S @1 ; br if disk in place
CLR.B DiskInPlace(A1,D1) ; no diskette here
MOVE.B #$86,wZeroes(A0) ;Cut drive enable (SWIM2 style) <2><CMP><SM2>
if NonSerializedIO then
nop ; force write to complete <SM5>
endif
TST.B MtrOff(A0) ; cut enable to drive to prevent ticking
MOVEQ #OffLinErr,D0 ; report it as no DIP . . .
BRA DiskErr ; <SM1>
@1 CMP.B #2,DiskInPlace(A1,D1) ; is it already clamped?
BEQ.S CkWrProt ; br if so
CLR.B mfmDisk(A1,D1) ;Make sure we're in GCR mode on <C437/17jun87>
; powerup for proper disk chucking <C437/17jun87>
TST.B isSWIM(A1) ;Is a SWIM installed? <C437/30sep87>
BPL.S @10 ;-> no, skip <C437/30sep87>
BSR SetChipMode ;switch the SWIM chip to IWM mode <C437/17jun87>
@10 ; <C437/30sep87>
BSR FastPower ; power-on drive (no wait cause we'll
BSR Recal ; call MakeSpdTbl) and recal
BMI.S DskImmOff ; exit on errors
BSR MakeSpdTbl ; figure speeds out via tach
BNE.S DskImmOff ; exit on errors
MOVEQ #WrProtAdr,D0 ; once we recal it should be safe
BSR AdrAndSense ; to check write protect . . .
SPL WriteProt(A1,D1) ; write-protect sense (FF=writeprot)
CLR.B TwoSideFmt(A1,D1) ; assume one-sided disk format at first
MOVE.B #2,DiskInPlace(A1,D1) ; note that we have recal'ed
BRA ChkDiskType ;Find out how the disk's formatted <C437/04dec86>
; check for write-protected diskette and a write
CkWrProt BSR CheckRead ; is it a read?
BEQ.S RWPower ; br if so
MOVE.W TagData+8,FirstFSeq(A1) ; save the first file sequence number
TST.B WriteProt(A1,D1) ; FF=writeprotected
BPL.S RWPower ; branch if not
MOVEQ #WPrErr,D0 ; diskette write-protected!
DskRWOff MOVE.W PwrOffTime(A1),D2 ; read/write power-down time
BRA.S POffExit ; speed determine errors
DskImmOff MOVEQ #0,D2 ; immediate power-down for recal and
; The following exit is shared by the Format/Verify control routines
POffExit MOVE.W D0,-(SP) ; save error code
MOVE.W D2,D0 ; power-down time
BSR PowerDown ; initiate powerdown
MOVE.W (SP)+,D0 ; restore error code
; here we handle the disk priming errors
DiskErr ANDI #$F8FF,SR ; open up interrupts
BRA DiskDone ; tell the OS about it
; make sure the drive is powered and start going for the data . . .
RWPower MOVE.W Track(A1,D1),D6 ; set speed for last track read . . .
BSR RWPowerUp ; turn on drive and delay until powered
eject ; <A351/05nov86>
;_______________________________________________________________________
;
; Routine: GetTrack
; Arguments: (input): disk is powered and selected
; (output): SideTrack - set to next track to process
; FirstSect - first sector on that track we need
; SectMap - bit map of sectors on that track we need
; FBlksDone - number of blocks done prior to this track
; DiskBuffer - points to point in buffer 4 this track
; RecalCnt - initialized to number of recals per trk
; Called By: this is really DiskPrime, part II
; Function: This code is executed before reading or writing the data
; on a single track.
;_______________________________________________________________________
GetTrack MOVE.L DiskUnitPtr(A1),A2 ; Device Ctl Entry ptr
MOVE.L DCtlQHead(A2),A0 ; current request ptr
MOVE.L DCtlPosition(A2),D0 ; current byte position
MOVEQ #9,D7 ;
LSR.L D7,D0 ; convert to block number (div by 512)
; at this point:
; A0 = user request parameter blk ptr
; A1 = disk locals ptr
; A2 = disk driver DCE ptr
; D1 = drive locals offset
; D0 = absolute diskette block number
; D7 = 9 (2^9=512)
;
; now figure out the next track number we need, the first sector number we want
; on this track and the bitmap of sectors we want from this track/side . . .
TST.B mfmDisk(A1,D1) ;Is this an MFM disk? <C437/04dec86>
BMI mGetTrack ;-> yes, sector layout is different <C437/04dec86>
MOVEQ #0,D4 ; 0 = 1-sided format = side 0
TST.B TwoSideFmt(A1,D1) ;
BEQ.S @1 ;
MOVEQ #1,D4 ; 1 = 2-sided format = side 1
@1 MOVEQ #100,D2 ;
LSL #3,D2 ; D2 = 800
LSL D4,D2 ; block #, end of disk
CMP.L D2,D0 ; block number past end of disk block?
BLT.S NxtClass ; br if not
DskParmErr MOVEQ #ParamErr,D0 ; disk position parameter too high
ToDRWOff BRA.S DskRWOff ; exit, activating power-down task
NxtClass MOVEQ #7,D3 ; 8 blks/track in last speed class
LSL #4,D3 ; 128 blks/side in last speed class
LSL D4,D3 ; blks in last speed class
MOVEQ #16,D5
LSL D4,D5 ; next speed class has 16-32 more blks
@1 ADD D5,D3 ; next lower speed class has more blks
SUB.L D3,D2 ; first blk #, this spd class
CMP.L D2,D0 ;
BLT.S @1 ; br if blk in a lower speed class
NxtTrack LSR #4,D3 ; blks/cylinder
MOVEQ #-1,D5 ; will hold trk offset, this speed class
@1 ADD D3,D2 ; first blk # next track
ADDQ #1,D5 ;
CMP D2,D0 ;
BGE.S @1 ; loop until past track
LSR D4,D3 ; blks per track, this speed class
MOVEQ #12,D6 ;
SUB D3,D6 ;
LSL #4,D6 ; first track this speed class
ADD D6,D5 ; the track we're on!
MOVE.L D4,D6 ; side
SUB D3,D2 ; first blk#, this track
CMP.L D2,D0 ;
BGE.S @2 ; br if on this track
SUB D3,D2 ; must be side 0 of 2-sided cylinder
MOVEQ #0,D6 ;
@2
gtResume ;This is where mGetTrack returns <C437/04dec86>
TST.B D6 ; side 1 or side 0?
BEQ.S @3 ; br if side 0
BSET #11,D5 ; set for side 1
TST.B Sides(A1,D1) ; do we have a 2-sided drive?
BNE.S @3 ; br if so
MOVEQ #twosideErr,D0 ; can't read it on a 1-sided drive
BRA.S ToDRWOff ; exit, activating power-down task
@3 MOVE.W D5,SideTrack(A1) ; side/track we want to be on
SUB D2, D0 ; first sector this track
SUB D0, D3 ; sectors left this track
MOVE.W D0,FirstSect(A1) ;
MOVE.L IOByteCount(A0),D5 ; get # of bytes requested
MOVE.L IONumDone(A0),D2 ; get # of bytes already done
SUB.L D2,D5 ; minus the ones we processed already
LSR.L D7,D5 ; round down to nearest sector
BEQ.S DskParmErr ; uneven parameter error . . .
; D5 = number of sectors (blocks) we have to go
; D3 = number of sectors still left on this track
CMP.W D5,D3 ; want all remaining sectors this trk?
SLT D6 ; D6=$00 if it's the last track to do <24Oct85>
BLE.S @4 ; branch if so
MOVE.W D5,D3 ; number of sectors to get this track
; at this point:
; A0 = ptr to user request parameter blk
; (A1,D1) = ptr to drive locals
; A2 = ptr to disk driver DCE
; D0 = first 'track sector' to get this track
; D2 = IONumDone
; D3 = number of sectors to get this track
; D6 = $00 if this is the last track we have to do <24Oct85>
; D7 = 9
; FirstSect = first sequential sector number we want this track
@4 MOVEQ #0,D5 ; sector bit map
MOVE.W D0,D4 ; save 1st sector number and sector <24Oct85>
MOVE.W D3,-(SP) ; count for cache check <24Oct85>
@5 BSET D0,D5 ; one bit is always set for FirstSect
ADDQ.W #1,D0 ; incr to next sector number
SUBQ.W #1,D3 ; decr number of sectors needed
BNE.S @5
MOVE.W (SP)+,D3 ; restore sector count <24Oct85>
MOVE.L D5,SectMap(A1) ; keep sector bitmap around
MOVE.L IOBuffer(A0),A3 ; get pointer to user buffer <24Oct85>
ADD.L D2,A3 ; add IONumDone <24Oct85>
MOVE.L A3,DiskBuffer(A1) ; start buf addr, 1st sector this trk <24Oct85>
LSR.L D7,D2 ; figure file blocks done so far
MOVE.W D2,FBlksDone(A1) ; and save (for file tag writes)
MOVE.B RecalInit(A1),RecalCnt(A1) ; one recal per track
; OK, it's time to check whether our track cache (if any) has the blocks we need
;
; A0 = ptr to user request parameter blk
; (A1,D1) = ptr to drive locals
; A2 = ptr to disk driver DCE
; A3 = start buf addr for 1st sector this track
; D3 = sector count this track
; D4 = first 'track sector' to get this track
; D5 = bitmap of needed track sectors
; D6 = $00 if this is the last track we have to do <24Oct85>
; D7 = 9
; FirstSect = first sequential sector number we want this track
CheckCache
; cache cache
; valid read installed action
;
; dc dc no reset TCRdEnable (TCRdEnable,TCInstalled both zero)
; no no yes reset TCRdEnable (preserve cache for a different track)
; no yes yes if sync call and no sectors needed on another track,
; set TCRdEnable and init cache for this drive/track/side.
; yes no yes reset TCRdEnable invalidate cache for written sectors
; yes yes yes get appropriate sectors from cache; if sync call,
; and no sectors needed on another track, set TCRdEnable.
; If verify, skip cache always.
CLR.B TCRdEnable(A1) ; assume we won't be caching this RWT <24Oct85>
BSR CheckRead ; is this a read call?
BEQ.S readCache ; br if so
BSR CacheValid ; do we have a valid cache?
BNE.S toReSeek ; continue with RWT if not
MOVE.L D5,D0 ; get bitmap of sectors we are writing
NOT.L D0 ; form bitmap of those we aren't writing
AND.L D0,TCSectMap(A1) ; invalidate those sectors we write
; BSR TCRdEnbChk ; reads into cache if sync call, last trk <C115/05aug86>
toReSeek BRA ReSeek ; continue with RWT (MIGHT WANT TO ENABLE CACHE READS?)
readCache TST.B DskVerify ; read-verify? <25Oct85>
BNE.S toReSeek ; skip caching if so <25Oct85>'
BSR CacheValid ; do we have a valid cache?
BNE rdCacheNV ; br if not
MOVE.L D5,D2 ; get bitmap of sectors we are reading
AND.L TCSectMap(A1),D2 ; see if we have any currently cached
BEQ rc_Cont ; br if not . . . <C437/08oct87>
MOVEQ #2,D7 ; number of bytes/sector
ASL.L #8,D7 ; (cheap way to make 512)
MOVE.W D4,D0 ; first sector needed this track
TST.B mfmDisk(A1,D1) ;Is this an MFM disk? <C437/08oct87>
BPL.S @00 ; <C437/08oct87>
SUBQ.W #1,D0 ;Yes, the buggers start with sector 1 <C437/08oct87>
@00 ; not sector zero!!! <C437/08oct87>
MULU #524,D0 ; offset into cache buffer
MOVE.L TCBuffer(A1),A4 ; get track cache buffer ptr
ADD D0,A4 ; track cache buffer for first sector
rc_Loop BTST D4,D2 ; do we have and need this sector?
BEQ.S @3 ; br if not
BCLR D4,D5 ; mark it got in sector map
MOVEM.L A0-A1,-(SP) ; preserve regs over blockmove
TST.L TagBufPtr(A1) ; do we have a separate tag buffer?
BEQ.S @1 ; br if not (transfer to low-mem)
MOVE.W D4,D0 ; current sector
SUB.W FirstSect(A1),D0 ; relative sector number this track
ADD.W FBlksDone(A1),D0 ; blocks done so far
MULU #12,D0 ; offset into caller's tag buffer
MOVE.L TagBufPtr(A1),A1 ; separate tag buffer
ADD.L D0,A1 ; ptr into it
BRA.S @2 ; transfer the tags
@1 LEA TagData+2,A1 ; copy them to low-memory
@2 MOVE.L A4,A0 ; track cache
MOVE.L (A0)+,(A1)+ ; transfer tags
MOVE.L (A0)+,(A1)+
MOVE.L (A0)+,(A1)+
MOVE.L A3,A1 ; user buffer address
MOVE.L D7,D0 ; 512-byte blockmove
_BlockMove ; transfer data
MOVEM.L (SP)+,A0-A1
ADDQ.W #1,TCNumUsed(A1) ; increment cache usage count <25Oct85>
ADD.L D7,DCtlPosition(A2) ; bump position (not accurate until done)
ADD.L D7,IONumDone(A0) ; bump number done
@3 ADD.L D7,A3 ; bump user buffer address
ADD.L D7,A4 ; bump track cache buffer address
ADD #12,A4 ; (track cache includes tags)
ADDQ.W #1,D4 ; incr to next sector number
SUBQ.W #1,D3 ; decr number of sectors needed
BNE.S rc_Loop ; go again if not done
MOVE.L D5,SectMap(A1) ; update sector bitmap
BNE.S rc_Cont ; br if not finished with this track
MOVE.L IONumDone(A0),D0 ; bytes done so far
CMP.L IOByteCount(A0),D0 ; more to do?
BLT GetTrack ; loop if more to do
MOVEQ #0,D0 ; success!
BRA DskRWOff ; sayonara
rc_Cont BSR.S TCRdEnbChk ; enable reads into cache if sync call, last track
BRA.S ReSeek ; continue with RWT
rdCacheNV BSR.S TCRdEnbChk ; enable reads into cache if sync call, last track
BNE.S ReSeek ; continue with RWT if not
MOVE.W Drive(A1),TCDrive(A1) ; initialize cache
MOVE.W SideTrack(A1),TCSideTrack(A1) ; current side and track
CLR.L TCSectMap(A1) ; no sectors so far
BRA.S ReSeek ; and on to RWT
; TCRdEnbChk checks whether this is a synchronous call and we're on the last track
TCRdEnbChk ; <22Oct85>
TST.B TCInstalled(A1) ; installed and enabled?
BEQ.S @2 ; exit if not
BTST #AsyncTrpBit,Command(A1) ; async bit on?
BNE.S @1 ; br if so
TST.B D6 ; more sectors needed on another track?
@1 SEQ TCRdEnable(A1) ; activate reads into cache if sync, last track
RTS ; BEQ for sync, last track, enabled
@2 MOVEQ #1,D6 ; force NE
BRA.S @1
; CacheValid checks to see if the cache is valid for current drive/side/track
CacheValid ; <22Oct85>
TST.B TCInstalled(A1) ; installed and enabled?
BEQ.S @1 ; exit if not
MOVE.W TCDrive(A1),D0 ; get cache drive
BEQ.S @1 ; br if not valid
CMP.W Drive(A1),D0 ; same drive?
BNE.S @1 ; br if not
MOVE.W SideTrack(A1),D0 ; get track side/track
SUB.W TCSideTrack(A1),D0 ; current side and track match?
BEQ.S @2 ; br if cache is set up
@1 MOVEQ #-1,D0 ; not valid
@2 RTS ; BEQ for valid
eject ; <A351/05nov86>
;_______________________________________________________________________
;
; Routine: ReSeek
; Arguments: (input): disk is powered and selected
; SideTrack - set to next track to process
; FirstSect - first sector on that track we need
; SectMap - bit map of sectors on that track we need
; FBlksDone - number of blocks done prior to this track
; DiskBuffer - points to point in buffer 4 this track
; RecalCnt - initialized to number of recals per trk
; (output): nothing
; Called By: this is DiskPrime, part III
; Function: Seek to the desired track; check the speed at the track if
; it's time, and adjust it if necessary.
;_______________________________________________________________________
ReSeek MOVE.L JReSeek,-(SP)
RTS
jtReSeek MOVE.B BadSpdInit(A1),BadSpdCnt(A1)
; seek (asynchronously) to get to the right track (seek handles the case where
; we are already at the right track . . .)
ReSeek1 MOVE.W SideTrack(A1),D6 ; seek . . .
BSR Seek
BMI.S toDoRecal ; (to DoRecal) recal on errors <25Oct85>
MOVE.B ReadErrInit(A1),ReadErrCnt(A1)
BRA.S OnTrack ; skip track speed check for NuMac <C1/5May86>
toDoRecal BRA DoRecal ; recal eventually . . . <25Oct85>
eject ; <A351/05nov86>
;_______________________________________________________________________
;
; Routine: OnTrack
; Arguments: (input): disk is powered and selected
; SideTrack - set to next track to process
; FirstSect - first sector on that track we need
; SectMap - bit map of sectors on that track we need
; FBlksDone - number of blocks done prior to this track
; DiskBuffer - points to point in buffer 4 this track
; RecalCnt - initialized to number of recals per trk
; (A1,D1) - points at drive variables
; (output): DCtlPosition - updated by bytes processed
; IONumDone - updated by bytes processed
; SectMap - cleared
; Called By: this is DiskPrime, part IV
; Function: Read each address mark as it passes under the head; if that
; sector is needed, read or write it as desired and pass any
; poll data on to the serial driver.
;
; Note: as a sector passes over the r/w head, the current file block and
; tag buffer pointers are figured so:
;
; current file block = FirstFSeq + FBlksDone + (sector-FirstSect)
; tag buffer pointer = [FBlksDone + (sector-FirstSect)] * 12
;_______________________________________________________________________
OnTrack MOVE.B WrgSectInit(A1),WrgSectCnt(A1) ; addr mark misses we tolerate
; At this point, we should be on the right track. Read the next
; address mark to see where we are. RdAddr sets interrupt level 3.
OnTrack1 MOVE.W D1,D6 ; preserve drive offset <24Oct85>
BSR RdAddrSetup ; set up for and call RdAddr
BMI AdrDtaErr ; process stack data, go to AdrDtaErr <24Oct85>
CMP.W SideTrack(A1),D1 ; are we on the right track and side?
BNE WrgSideTrk ; <24Oct85>
MOVE.B D3,gcrFmtByte(A1) ; save format byte for the duplicator <1.8>
MOVE.W D2,CurSector(A1) ; save the sector number <22Oct85>
MOVE.W D2,TagData ; set up TagData+1 for writes
MOVE.L SectMap(A1),D0 ; sector bitmap of needed sectors
BTST D2,D0 ; do we need this sector?
BNE OTSetUp ; br if so . . . normal r/w path <24Oct85>
TST.B TCRdEnable(A1) ; are we reading into a cache? <22Oct85>
BEQ WrgSectAdr ; go to WrgSectAdr if not <24Oct85>
MOVE.L TCSectMap(A1),D0 ; see if we have it in the cache yet <24Oct85>
BTST D2,D0 ; <24Oct85>
@toWrgSectAdr ; <H6>
BNE WrgSectAdr ; go to WrgSectAdr if so <24Oct85>
LEA jtRdData,A0 ; no, use the normal rdData routine <H2><SM2>
CMP.B #-2,isSWIM(A1) ; Check for presence of SWIM2 <H2><SM2>
BNE.S @NotSWIM2 ; <H2><SM2>
LEA jtISMRdData,A0 ; yes, use the SWIM2 rdData routine <H2><SM2>
@NotSWIM2 ; <H2><SM2>
CMP.L JRdData,A0 ; has been replaced or prefixed --- <03Nov85>
SNE TCRdEnable(A1) ; i.e., this is a copy-protection <31Oct85>
BNE WrgSectAdr ; check . . . skip cache if so <31Oct85>
MOVE.W D2,D1 ; sector number <24Oct85>
TST.B mfmDisk(A1,D6) ;Is this an MFM disk? <C437/08oct87>
BPL.S @00 ; <C437/08oct87>
SUBQ.W #1,D2 ;Yes, the buggers start with sector 1 <C437/08oct87>
; not sector zero!!! <C437/08oct87>
BMI.S @toWrgSectAdr ; don't cache sector zero!! <H6>
@00 ; <C437/08oct87>
MULU #524,D2 ; tag/data offset into track cache buf <24Oct85>
MOVE.L TCBuffer(A1),A0 ; buffer start <24Oct85>
ADD.L D2,A0 ; add in offset to tag/data <24Oct85>
ADD #12,A0 ; skip over tags to data <24Oct85>
BSR RdData ; read the data mark <24Oct85>
BSR GetDrv1 ;get A1,D1 back <C437/22feb88>
MOVE.W D1,D6 ; and save the drive vars offset in D6 <C437/22feb88>
TST.W D0 ;reset the CCR with RdData's result <C437/11mar88>
SPL TCRdEnable(A1) ; turn off cache this trk on errors <29Oct85>
BMI.S @1 ; ignore errors (may be copy-prot sect) <24Oct85>
ADDQ.W #1,TCNumCached(A1) ; increment cache activity count <25Oct85>
MOVE.W CurSector(A1),D2 ; get sector number we read <24Oct85>
MOVE.L TCBuffer(A1),A0 ; buffer start <24Oct85>
MOVE.W D2,D1 ; sector number <24Oct85>
TST.B mfmDisk(A1,D6) ;Is this an MFM disk? <C437/08oct87>
BPL.S @01 ; <C437/08oct87>
SUBQ.W #1,D1 ;Yes, the buggers start with sector 1 <C437/08oct87>
@01 ; not sector zero!!! <C437/08oct87>
MULU #524,D1 ; tag offset into track cache buffer <24Oct85>
ADD.L D1,A0 ; add in offset to tag/data this sect <24Oct85>
LEA TagData+2,A2 ; <24Oct85>
MOVE.L (A2)+,(A0)+ ; transfer tag data from low memory <24Oct85>
MOVE.L (A2)+,(A0)+ ; <24Oct85>
MOVE.L (A2)+,(A0)+ ; <24Oct85>
MOVE.L TCSectMap(A1),D4 ; get the cache sector map <24Oct85>
BSET D2,D4 ; flag it as valid <24Oct85>
MOVE.L D4,TCSectMap(A1) ; update the map <24Oct85>
@1 BSET #7,IntFlag ; do we need to open up ints for <24Oct85>
BNE.S @2 ; AppleTalk? br if not . . . <24Oct85>
MOVE.W SectTime(A1),D0 ; set up timer for 1 sector time <25Oct85>
TST.B mfmDisk(A1,D6) ;Are we in MFM mode? <C437/04dec86>
BPL.S @11 ;-> no <C437/04dec86>
MOVEQ #MFMSectTime,D0 ;MFM sectors have a fixed gap size <C437/04dec86>
@11 ; <C437/04dec86>
BSR WakeSetUp ; return immediately <25Oct85>
BSR EmptyPD ; process stack data <25Oct85>
BSR WakeGo ; do the wait (and enable ints) <25Oct85>
BRA.S @3
@2 BSR EmptyPD ; process stack data <24Oct85>
ANDI #$F8FF,SR ; open for SCC/VIA ints <24Oct85>
@3 BRA OnTrack ; now try for the real data <24Oct85>
OTSetUp CMP.B #$1F,D3 ; set format type
SGT TwoSideFmt(A1,D6) ; and save it to distinguish 2-sided disks
SUB.W FirstSect(A1),D2 ; relative sector number this track
MOVE.W D2,D1
ASL.L #8,D1
ADD.L D1,D1 ; sector # times 512
ADD.L DiskBuffer(A1),D1 ; add in buffer start
MOVE.L D1,A0 ; data buffer pointer
MOVE.W FBlksDone(A1),D1 ; blocks done so far
ADD.W D2,D1 ; relative block number
MOVE.W D1,D0 ; save for write case
ADD.W D1,D1 ; double
ADD.W D0,D1 ; x3
ASL.W #2,D1 ; x12 gives us offset into buffer
MOVE.W D1,TagBufOS(A1) ; save in case of read
BSR CheckRead ; is it a read?
BEQ.S OTRead ; br if so
; it was a write request so call write data mark
OTWrite MOVE.L TagBufPtr(A1),D3 ; tag buffer start
BEQ.S @1 ; br if no separate buffer
MOVE.L D3,A1 ; tag buffer start
ADD.W D1,A1 ; point to appropriate tag
LEA TagData+2,A2
MOVE.L (A1)+,(A2)+
MOVE.L (A1)+,(A2)+
MOVE.L (A1)+,(A2)+ ; fill it in
BRA.S @2 ; and do the write
@1 ADD.W FirstFSeq(A1),D0 ; figure relative file block number
MOVE.W D0,TagData+8 ; so we can write it out in tag field
@2 BSR WrData ; WrData timestamps it
BMI AdrDtaErr ; go to AdrDtaErr on errors
BRA.S GotSect ;
; it was a read request so call read data mark
OTRead BSR RdData ; read the data mark
BMI AdrDtaErr ; go to AdrDtaErr on errors
MOVE.L SonyVars,A1
MOVE.L TagBufPtr(A1),D0 ; do we have a separate tag buffer?
BEQ.S GotSect ; br if not
MOVE.L D0,A0 ; point to tag buffer start
ADD.W TagBufOS(A1),A0 ; and then to appropriate entry
LEA TagData+2,A2
MOVE.L (A2)+,(A0)+
MOVE.L (A2)+,(A0)+
MOVE.L (A2)+,(A0)+ ; transfer tag data from low memory
; We got the sector so flag it as gotten, update our counts and
; then try for the next one
GotSect BSR GetDrv1 ; get A1, D1 <25Oct85>
MOVE.L SectMap(A1),D4 ; get the map
MOVE.W CurSector(A1),D2 ; get r/w sector number <22Oct85>
BCLR D2,D4 ; flag it as gotten
MOVE.L D4,SectMap(A1) ; update the map
MOVE.L DiskUnitPtr(A1),A2 ; get pointer to DCE
MOVE.L DCtlQHead(A2),A0 ; get pointer to user request block
MOVEQ #2,D3 ; number of bytes/sector
ASL.L #8,D3 ; (cheap way to make 512)
ADD.L D3,DCtlPosition(A2) ; bump position (not accurate until done)
ADD.L D3,IONumDone(A0) ; bump number done <24Oct85>
MOVE.L IOByteCount(A0),D3 ; original request <24Oct85>
SUB.L IONumDone(A0),D3 ; D3 = 0 if we're done (save for later) <24Oct85>
; done r/w NewIntf Atalk action <2.1>
;
; dc dc dc yes 10 ms sector wait
; yes read dc no continue (to next track)
; no read dc no continue (may get 1-1)
; yes write dc no 700 us wait for erase head off
; no write yes no continue (may get 1-1)
; no write no no 10 ms sector wait (1-1 not possible)
BSET #7,IntFlag ; do we need to open up ints for <24Oct85>
BEQ.S @1 ; AppleTalk? br if so . . . <24Oct85>
BSR.S CheckRead ; is it a read? <24Oct85>
BEQ.S @2 ; br if so <24Oct85>
TST.L D4 ; last sector on this track/side? <24Oct85>
BNE.S @0 ;-> no <C437/28mar88><2.1>
BSR.S EmptyPD ; process stack data <25Oct85><C437/10feb88>
MOVEQ #7,D0 ; wait 700 usec after last sector write <24Oct85>
BSR WakeUp ; wake up when it's over <24Oct85>
BRA.S @3 ; <25Oct85>
@0 TST.B NewIntf(A1,D1) ; is this a new interface drive <C437/28mar88><2.1>
BMI.S @2 ;-> yes, no waiting (we might do 1-1) <C437/28mar88><2.1>
@1 MOVE.W SectTime(A1),D0 ; set up timer for 1 sector time <25Oct85>
TST.B mfmDisk(A1,D1) ;Are we in MFM mode? <C437/04dec86><2.1>
BPL.S @11 ;-> no <C437/04dec86>
MOVEQ #MFMSectTime,D0 ;MFM sectors have a fixed spacing <C437/04dec86>
@11 ; <C437/04dec86>
BSR WakeSetUp ; return immediately <25Oct85>
BSR.S EmptyPD ; process stack data <25Oct85><C437/10feb88>
BSR WakeGo ; do the wait (and enable ints) <25Oct85>
BRA.S @3 ; then continue <25Oct85>
@2 BSR.S EmptyPD ; process stack data <25Oct85><C437/10feb88>
ANDI #$F8FF,SR ; open for SCC/VIA ints <25Oct85>
@3 MOVE.L D4,D0 ; sector map (set D0=0 for exit case) <25Oct85>
BNE OnTrack ; br if there's more on this track
; we're all done with this track. See if there is anything else to do
TST.L D3 ; bytes to go <24Oct85>
BGT GetTrack ; loop if more to do <24Oct85>
TST.B TwoSideFmt(A1,D1) ; 2-sided format? <02Sep85>
BEQ.S ToDskRWOff ; br if not <02Sep85>
TST.B Sides(A1,D1) ; we better have a 2-sided drive? <02Sep85>
BNE.S ToDskRWOff ; br if so <02Sep85>
MOVEQ #twoSideErr,D0 ; give an early warning! <02Sep85>
ToDskRWOff BRA DskRWOff ; jump to IODone to tell the OS we're finished.
CheckRead CMP.B #ARdCmd,Command+1(A1) ; is it a read?
RTS
eject ; <A351/05nov86>
;______________________________________________________________________________;
;
; routine to call polldata process procedure if there is one,
; or reset the stack if there isn't . . .
;______________________________________________________________________________;
EmptyPD MOVE.L (SP)+,A4 ; save return address
PEA @2 ; this routine's return address
MOVE.L PollProc,-(SP) ; is there a proc to process poll data?
BEQ.S @1 ; br if not
MOVE.L SonyVars,A1
MOVEM.L D0/D2-D3/A0/A4,SaveRegs(A1) ; save some regs
RTS ; go to it!
@2 BSR GetDrv1
MOVEM.L SaveRegs(A1),D0/D2-D3/A0/A4
JMP (A4)
@1 MOVE.L PollStack,SP ; otherwise, throw away any data
BSR GetDrv1
JMP (A4)
;______________________________________________________________________________;
;
; Here is the exception handling code . . . these routines are branched to from
; OnTrack with interrupts disabled and data possibly on the stack.
;______________________________________________________________________________;
AdrDtaErr BSR.S EmptyPD ; process stack data <24Oct85><C437/10feb88>
ANDI #$F8FF,SR ; restore interrupts
ADDQ.W #1,DiskErrs(A1) ; increment global soft-error count <H11><SM2>
TST.B DisableRetries(A1) ; are we supposed to do retries? <H11><SM2>
BEQ.S @Done ; -> yes <H11><SM2>
CLR.B ReCalCnt(A1) ; perform no recals <H11><SM2>
CLR.B ReadErrCnt(A1) ; or read retries <H11><SM2>
@Done ; <H11><SM2>
ADDQ.W #1,DriveErrs(A1,D1) ; increment drive soft-error count <25Oct85>
TST.B ReCalCnt(A1) ; down to last recal? <22Oct85>
BEQ.S @1 ; br if so (retry rather than fail) <22Oct85>
BSR.S CheckRead ; write? <22Oct85><C437/10feb88>
BNE.S DoRecal ; br if so (may be slightly off-track) <22Oct85>
@1 SUBQ.B #1,ReadErrCnt(A1) ; bad addr, data mk - decrement error cnt
BPL OnTrack ; try for another
BRA.S DoRecal ; <24Oct85>
; we don't need this one so figure out how long it will take for one we do need
; to pass under the head and give the time back to the user
; (for now, just wait for most of this sector to pass)
WrgSectAdr MOVE.L SonyVars,A1 ; get A1 <25Oct85>
MOVE.W SectTime(A1),D0 ; set up timer for 1 sector time <25Oct85>
TST.B mfmDisk(A1,D6) ;Are we in MFM mode? <C437/04dec86>
BPL.S @1 ;-> no <C437/04dec86>
MOVEQ #MFMSectTime,D0 ;MFM sectors have a fixed gap size <C437/04dec86>
@1 ; <C437/04dec86>
BSR WakeSetUp ; return immediately <25Oct85>
BSR.S EmptyPD ; process stack data <25Oct85><C437/10feb88>
BSR WakeGo ; do the wait (and enable ints) <25Oct85>
ADDQ.L #1,RndSeed ; bump our random seed
MOVEQ #SectNFErr,D0 ; in case we run out of recals <24Oct85>
SUBQ.B #1,WrgSectCnt(A1) ; enough already?
BMI.S DoRecal ; if so, recal
BRA OnTrack1 ; then continue search
WrgSideTrk BSR.S EmptyPD ; process stack data <24Oct85><C437/10feb88>
MOVEQ #SeekErr,D0 ; in case we run out of recals <24Oct85>
; fall through to DoRecal <24Oct85>
;______________________________________________________________________________;
;
; if we can't get an address mark (with retries) we must try to recalibrate
; DoRecal recals to track 0 and then refigure speed codes.
;______________________________________________________________________________;
DoRecal ANDI #$F8FF,SR ; restore interrupts
SUBQ.B #1,ReCalCnt(A1) ; did we recal yet?
BLE.S @1 ; if so, give up
BSR Recal ; recal to track 0
BMI.S @1 ; exit on errors
BSR MakeSpdTbl ; and redetermine speeds
BPL ReSeek
@1 BRA.S ToDskRWOff ; we ran out of retries so give up and
; return an error