mac-rom/Drivers/Sony/SonyRWT.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

939 lines
38 KiB
Plaintext

;
; 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 isnÕt 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