mirror of
https://github.com/elliotnunn/supermario.git
synced 2024-11-29 05:49:19 +00:00
1012 lines
41 KiB
Plaintext
1012 lines
41 KiB
Plaintext
;
|
||
; File: SonyUtil.a
|
||
;
|
||
; Contains: This file contains various utility routines used by the
|
||
; disk driver. It includes the powerup/powerdown logic, wakeup timing,
|
||
; seek, eject, recal, and speed determination.
|
||
;
|
||
; Written by: Larry Kenyon
|
||
;
|
||
; Copyright: © 1982-1990, 1992-1993 by Apple Computer, Inc., all rights reserved.
|
||
;
|
||
; Change History (most recent first):
|
||
;
|
||
; <SM10> 12/13/93 PN Roll in KAOs and Horror changes to support Malcom and AJ
|
||
; machines
|
||
; <SM9> 12/14/92 RC Restore to Before PDM D2 Build with Horror Roll-in
|
||
; <SM6> 12/7/92 rab Roll in Horror changes. Comments follow…
|
||
; <H6> 7/8/92 CMP Do BSR to CkEjectPatch instead of BRA. This was causing the
|
||
; rest of CkEjSw to not get executed, which in turn caused the VBL
|
||
; task to always post eject events for 800k drives.
|
||
; <H5> 3/18/92 SWC Reversed branch polarity in chip existance check in DiskVBLTask.
|
||
; <H4> 11/14/91 SWC Removed the patch to SetIWMMode since it won't be called except
|
||
; on an IWM, or SWIM in IWM mode. Changed the CkDCDExist patch to
|
||
; use more of the existing code. Check if a disk controller is
|
||
; installed in DiskVBLTask. Don't check the eject switch on
|
||
; SuperDrives. Converted SCC polling code to a macro to make it
|
||
; easier to overpatch.
|
||
; <H2> 10/18/91 CMP Overpatched SetIWMMode and CkDCDExist for SWIM2 support.
|
||
; Also, changed drive disable to not depend on MotorOn gating the
|
||
; enable lines.
|
||
; <SM5> 12/02/92 HY Added hasPwrControls conditionals.
|
||
; <SM4> 10/18/92 CCH Added nop's for systems with non-serial writes to IO space.
|
||
; <12> 7/14/92 CSS Fixed the comment below so an exact version of this
|
||
; file could be copied into SuperMario.
|
||
; <11> 4/27/92 JSM Get rid of conditionals: supportsPWM, supportsDCD, and
|
||
; has3rdFloppy are always false, forROM, supportsMFM, 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.
|
||
; <10> 1/17/91 GMR Added additional 15 µs delay to Wait100 after step goes high
|
||
; (per Sonys request) so the time between steps is not less than
|
||
; 72 µs.
|
||
; <9> 9/25/90 GMR Changed Recal to use fast (with handshake) step pulses for the
|
||
; new Buddy Lite SuperDrive.
|
||
; <8> 9/21/90 BG Removed <7>. 040s are behaving more reliably now.
|
||
; <7> 6/18/90 CCH Added NOPs for flaky 68040's.
|
||
; <6> 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.
|
||
; <5> 4/26/90 GMR Backed out previous change (there was a recursive problem with
|
||
; it).
|
||
; <4> 2/2/90 GMR Modified ReCal to support low cost 800K drives (and low cost
|
||
; Superdrives) by using Seek to do the stepping (without 6/12msec
|
||
; delays), unless it's a 400K drive.
|
||
; <3> 1/16/90 MSH Roll in Portable changes from Fiction.
|
||
; <2> 1/15/90 MSH Prepare comment header for conversion.
|
||
; <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 VIA accesses during Pulse to waste some time to ensure
|
||
; adequate pulse width of LSTRB. Added VIA accesses in DiskSel to
|
||
; kill some time.
|
||
; <2.0> 12/15/88 GGD Added short delay loop in Seek loop to fix problem with seek
|
||
; errors on fast processors (like Cobra2). 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 WC Made drive translation table stuff conditional for everyone
|
||
; but onMac.
|
||
; <1.7> 8/16/88 GGD Changed ref to DBase in FigTrkSpeed to use low mem loc IWM
|
||
; instead.
|
||
; <1.6> 7/15/88 GGD For HcMac, don't turn off drive power while ejecting.
|
||
; <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 Change WakeUp
|
||
; to use the TimeMgr when forRAM too. Change LoadPWMBuf to use
|
||
; PWMBuf1 when forRAM too. Added conditional code based upon
|
||
; onMacPPpatch=1 to add code to WakeUp and DiskSelect to only jump
|
||
; to the patch if it starts with a NOP, because those two routines
|
||
; are patched in the system disk 5.0 patches, and executing those
|
||
; patches with the new SuperDrive roms would cause the system to
|
||
; crash. Fixed Seek to check mfmMode instead of mfmDisk before
|
||
; calling SetParams (causes problems with 800K format on 1440K
|
||
; media)
|
||
; 3/28/88 GGD Fixed Seek to check mfmMode instead of mfmDisk before calling
|
||
; SetParams (causes problems with 800K format on 1440K media)
|
||
; 2/26/88 SWC PowerUp: wait an additional 600ms on writes (and formats) if the
|
||
; motor had to be turned on to guarantee motor speed within ±1.5%.
|
||
; <1.0> 2/12/88 BBM Adding file for the first time into EASE…
|
||
; <C437> 1/28/88 SWC Changed PowerUp so that if a MFM<->GCR drive mode switch is
|
||
; being made, it will force a wait even if the drive is powered
|
||
; up.
|
||
; <C437> 12/15/87 SWC Swapped usage of D2 & D5 in Seek because WakeUp was trashing D2
|
||
; when seeking on 400K disks.
|
||
; <C437> 12/8/87 SWC Added a call to SetParams in Seek if an MFM disk is installed.
|
||
; <C907> 10/8/87 MSH Port to HcMac (Laguna).
|
||
; <A855> 5/27/87 CSL Fixed the performance problem of the upper internal drive.
|
||
; <C511> 12/12/86 TJ Ints off in WakeUp to prevent convoluted path from PrimeTime
|
||
; back into WakeUp/WakeSetUp.
|
||
; <A351> 11/5/86 TJ Cleaned up the text, added ejects. Separated SetIWMMode from
|
||
; Recal; Fixed bug in SetIWMMode that destroyed D1 (but was never
|
||
; executed??)
|
||
; <A302> 10/30/86 TJ For old 400K drive support, rearm T2 to interrupt immediately,
|
||
; to avoid loss of TimeMgr interrupts. (FigTrkSpd keeps ints off
|
||
; for so long any T2 int has long since gone by ...)
|
||
; <A216> 10/17/86 TJ Upped Sony VBL task interrupt level from 1 (VBL) to 3 so that
|
||
; AppleTalk cant get in; fileserver activity can initiate disk
|
||
; access, which get messed up because the VBL task is fiddling
|
||
; down there ... this really needs to get handled in some
|
||
; reasonable way, like Active(SonyVars) used as a non-reentrancy
|
||
; flag or something ... but then AppleTalk would have to "back
|
||
; out" ... etc.
|
||
; <C123> 9/3/86 TJ Added Eject Button polling in VBL task.
|
||
; <C97> 7/24/86 TJ Repaired WakeUp & WakeGo to set up for the interrupt before
|
||
; enabling it, eliminating the "I'll be ready before the interrupt
|
||
; happens" (but was not) case, ie. AppleTalk interrupt taking
|
||
; longer than the WakeUp delay time. Added logical to physical
|
||
; drive translation in GetDrive(), plus added GetRDrive, that does
|
||
; not translate.
|
||
; <C1> 4/25/86 RDC Added changes for new 68020 Reno project (NuMac) - Changed
|
||
; setting of IWM mode
|
||
; <C437> 3/19/86 SWC Patched Recal to call SetChipMode instead of SetIWMMode if a
|
||
; SWIM is installed so that the appropriate registers will be
|
||
; initialized. Seek: moved the "set direction" out of and cleaned
|
||
; up the step loop. Patched PowerUp to switch a SuperDrive into
|
||
; either constant or variable speed mode for MFM or GCR,
|
||
; respectively. Made MFM mode patches to AdrDisk, Sense, Pulse,
|
||
; DiskSelect, and a few other places so that the SWIM HW is
|
||
; accessed correctly.
|
||
; 10/25/85 LAK PowerDown sets up TimeOutDrive. DiskSelect calls PowerDown if
|
||
; TimeOut nonzero and TimeOutDrive is not Drive. Vectored
|
||
; DiskSelect for ROM. Use NewIntf rather than Sides to determine
|
||
; whether drive has new interface. Split WakeUp into WakeSetUp and
|
||
; WakeGo for RWT fix.
|
||
; 10/24/85 LAK WakeUp now uses new timer routines. Added routine InvalTrkCache.
|
||
; 7/29/85 RDC Added changes for MidMac: - changed interrupt level settings to
|
||
; use equates - removed DCD code - changed VIA timer and timing
|
||
; loops to use equates - adjusted tach frequency tables - replaced
|
||
; make speed table routine w/ 800 ms delay
|
||
;
|
||
;_______________________________________________________________________
|
||
;
|
||
; Routines: GetDrive, GetDrv1, AdrAndSense, AdrAndStrb, AdrDisk, Pulse, Sense,
|
||
; SetSpeed, SetASpeed, Eject, Seek, Seek1, WakeUp, Recal, SetIWMMode,
|
||
; PowerDown, PowerUp, DiskSelect, MakeSpdTbl, FigTrkSpeed,
|
||
; DiskVBLTask.
|
||
;
|
||
; Register Conventions:
|
||
; A3,A4: used for return addresses, highest level (MakeSpdTbl)
|
||
; also use D3-D4 to keep values, may trash all other regs
|
||
; A5,A6: used for return addresses, lowest level (Seek, Recal)
|
||
; also use D5,D6,D7 to keep values, must preserve A3-A4/D3-D4.
|
||
; DskRtnAdr: used by RdAddr,RdData,WrData,WakeUp to store return address.
|
||
; Utility routines must preserve registers D3-D7/A3-A6 (though many
|
||
; preserve all regs except D0).
|
||
;_______________________________________________________________________
|
||
|
||
eject ; <A351/05nov86>
|
||
;_______________________________________________________________________
|
||
;
|
||
; Routine: GetDrive,GetDrv1,GetRDrive
|
||
; Arguments: A1 (output) -- pointer to driver variables
|
||
; D1 (output) -- word offset of current drive's specific vars
|
||
; A0 (output) -- IWM base ptr
|
||
; A2 (output) -- VIA base ptr
|
||
; Called By: (GetDrive): AdrDisk,WakeUp,WakeRcvr,DiskSelect,
|
||
; Check4Disk
|
||
; (GetDrv1): SetSpeed(2x),SetASpeed,Seek1(2x),PowerUp,
|
||
; PowerDown,MakeSpdTbl,EmptyPD,CkDrvNum
|
||
; (GetRDrive): DiskOpen
|
||
; Function: Get much-used values into D1,A0,A1, and A2.
|
||
;
|
||
;Note: This is called with Drive(A1) set to maxDrvNum + 1 in DiskOpen;
|
||
; this is for determining the presences of the passThru function
|
||
; on DCDs. To avoid problems GetDrvx bounds the drive number to
|
||
; maxDrvNum.
|
||
;_______________________________________________________________________
|
||
|
||
|
||
BLANKS ON
|
||
STRING ASIS
|
||
|
||
DrvVarOS DC.W Drive1 ; offsets into SonyVars <C97/28jul86>
|
||
DC.W Drive2 ; one for each drive <C97/28jul86>
|
||
|
||
;
|
||
;Return the stuff, but do not translate the drive number.
|
||
;
|
||
GetRDrive move.l IWM,A0 ;set up hardware pointers <C97/28jul86>
|
||
move.l VIA,A2 ; <C97/28jul86>
|
||
bsr.s GetDrv2 ; <C97/28jul86>
|
||
move.w DrvVarOS-2(D1),D1 ;untranslated drive vars <C97/28jul86>
|
||
rts ; <C97/28jul86>
|
||
;
|
||
; Return the stuff, but logically translate the drive number.
|
||
;
|
||
GetDrive MOVE.L IWM,A0 ;set up pointers to hardware
|
||
MOVE.L VIA,A2
|
||
|
||
GetDrv1
|
||
bsr.s GetDrv2 ;get basic setup stuff, <C97/28jul86>
|
||
|
||
move.w DrvVarOS-2(D1),D1 ;driver vars offset <C97/28jul86>
|
||
rts ; <C97/28jul86>
|
||
|
||
GetDrv2 move.l SonyVars,A1 ; <C97/28jul86>
|
||
move.w Drive(A1),D1 ;logical drive number, <C97/28jul86>
|
||
cmp.w #maxDrvNum,D1 ;if > max drive # <C115/13aug86>
|
||
BLS.S GetDrv3 ;bound to max (passThru test) <C437/28sep87>
|
||
MOVEQ #maxDrvNum,D1 ; <C437/28sep87>
|
||
GetDrv3 add.w D1,D1 ;make word ptr <C97/28jul86>
|
||
rts ; <C97/28jul86>
|
||
eject ; <A351/05nov86>
|
||
|
||
;_______________________________________________________________________
|
||
;
|
||
; Routine: AdrAndSense, AdrAndStrb, AdrDisk, Pulse, Sense
|
||
; Arguments: A1 (output) -- pointer to driver variables (input for GetOther)
|
||
; D1 (output) -- word offset of current drive's specific vars
|
||
; A0 (output) -- IWM base ptr
|
||
; A2 (output) -- VIA base ptr
|
||
; Called By:(AdrDisk): RdAddrSetup,AdrAndSense,AdrAndStrb,FigTrkSpeed,Eject
|
||
; (AdrAndStrb): Seek,Recal,PowerDown,Check4Disk
|
||
; (AdrAndSense): Seek,Recal(2x),PowerUp,Check4Disk(3x),CkInstll(2x),
|
||
; CkDIP(2x),CkWrProt
|
||
; (Pulse): AdrAndStrb,Seek,Recal,PowerUp
|
||
; (Sense): AdrAndSense
|
||
; Function: Utility routines used in addressing and configuring disk.
|
||
;_______________________________________________________________________
|
||
|
||
; D0 is 'address' (ca1-ca0-sel-ca2)
|
||
|
||
AdrDisk BSR.S GetDrive ; setup A0,A1,A2,D1
|
||
|
||
TST.B mfmMode(A1) ;Are we in MFM mode? <C437/25feb87>
|
||
BMI mAdrDisk ;-> yes, set phases SWIM style <C437/25feb87>
|
||
|
||
TST.B Ph0H(A0) ; when changing SEL from 1 to 0,
|
||
TST.B Ph1H(A0) ; CA0=CA1=1 must be true
|
||
|
||
LSR.B #1,D0 ; CA2 state
|
||
BCC.S @0
|
||
TST.B Ph2H(A0) ; set high
|
||
BRA.S @1
|
||
@0 TST.B Ph2L(A0) ; set low
|
||
|
||
@1 LSR.B #1,D0 ; SEL state
|
||
BCC.S @2
|
||
BSET #VHeadSel,VBufD(A2) ; set high
|
||
if NonSerializedIO then
|
||
nop ; force write to complete <SM4>
|
||
endif
|
||
BRA.S @3
|
||
@2 BCLR #VHeadSel,VBufD(A2) ; set low
|
||
if NonSerializedIO then
|
||
nop ; force write to complete
|
||
endif
|
||
|
||
@3 LSR.B #1,D0 ; CA0 state
|
||
BCS.S @4
|
||
;TST.B Ph0L(A0)
|
||
TST.B (A0)
|
||
|
||
@4 LSR.B #1,D0 ; CA1 state
|
||
BCS.S @5
|
||
TST.B Ph1L(A0)
|
||
|
||
@5 RTS
|
||
|
||
AdrAndSense BSR.S AdrDisk
|
||
Sense
|
||
TST.B mfmMode(A1) ;Are we in MFM mode? <C437/25feb87>
|
||
BMI mSense ;-> yes, read sense SWIM style <C437/25feb87>
|
||
|
||
MOVE SR,-(SP)
|
||
ORI #HiIntMask,SR ; no interrupts <29Jul85>
|
||
TST.B Q6H(A0) ; get into sense mode
|
||
MOVE.B Q7L(A0),D0 ; sense it
|
||
TST.B Q6L(A0) ; back to read mode
|
||
MOVE (SP)+,SR
|
||
TST.B D0
|
||
RTS
|
||
|
||
AdrAndStrb BSR.S AdrDisk
|
||
Pulse
|
||
TST.B mfmMode(A1) ;Are we in MFM mode? <C437/25feb87>
|
||
BMI mPulse ;-> yes, pulse LSTRB SWIM style <C437/25feb87>
|
||
|
||
MOVE SR,-(SP)
|
||
ORI #HiIntMask,SR ; no interrupts <29Jul85>
|
||
TST.B Ph3H(A0) ; pulse it high, then low
|
||
MOVE.B VBufD(A2),VBufD(A2) ; access VIA to kill some time <2.1>
|
||
if NonSerializedIO then
|
||
nop ; force write to complete
|
||
endif
|
||
TST.B Ph3L(A0)
|
||
MOVE (SP)+, SR
|
||
RTS
|
||
|
||
eject ; <A351/05nov86>
|
||
;_______________________________________________________________________
|
||
;
|
||
; Routine: Seek,Seek1
|
||
; Arguments: D6.W (input) -- track to seek to (bit 11=1 means side 1)
|
||
; D0 (output) -- result code
|
||
; Disk speed is set appropriately for the track.
|
||
; A3-A4/D3-D4 are preserved. D6, bit 11 is cleared.
|
||
; All other registers are clobbered
|
||
; This routine returns to one level above the caller during
|
||
; the seek (unless no seek is required).
|
||
; Seek1 is used when the speed table is not valid.
|
||
; Called By: (Seek1): MakeSpdTbl
|
||
; (Seek): ReSeek (in RWT logic)
|
||
; Function: Seek to a track.
|
||
;_______________________________________________________________________
|
||
|
||
Seek BCLR #11,D6 ; clear side bit (for now . . .)
|
||
|
||
Seek1 MOVE.L JSeek,-(SP)
|
||
RTS
|
||
|
||
jtSeek MOVE.L (SP)+,A6 ; save caller's address
|
||
|
||
; D6 holds the track sought . .
|
||
|
||
BSR GetDrv1
|
||
MOVE.W Track(A1,D1),D7 ; current track
|
||
BPL.S SeekLp ; br if curTrack is valid
|
||
|
||
BSR ReCal ; recal to get into a known state
|
||
MOVE.W D0,D7 ; current track
|
||
BRA.S SeekEnd ; exit after recal to avoid slipped cog
|
||
|
||
SeekLp MOVEQ #DirLAdr,D0 ;Assume step in <C437/17jun87>
|
||
MOVE.W D6,D5 ;Calculate the number of steps to take <C437/15dec87>
|
||
SUB.W D7,D5 ;Already there? <C437/15dec87>
|
||
BEQ.S SeekEnd1 ;-> yes, don't wait head settle time <C437/17jun87>
|
||
BGT.S @1 ; <C437/17jun87>
|
||
MOVEQ #DirHAdr,D0 ;We're stepping out <C437/17jun87>
|
||
NEG.W D5 ; so make the step count positive <C437/15dec87>
|
||
@1 BSR AdrAndStrb ;Set the stepper direction <C437/17jun87>
|
||
|
||
MOVEQ #cantStepErr,D7 ;Assume one of the steps will fail <C437/17jun87>
|
||
SUBQ.W #1,D5 ;Adjust count for DBRA <C437/15dec87>
|
||
SeekLp1 MOVEQ #StepLAdr,D0 ;Make sure /STEP starts out high <C437/17jun87>
|
||
BSR AdrAndSense ; <C437/17jun87>
|
||
BPL.S SeekEnd ;-> it wasn't, so exit with error <C437/17jun87>
|
||
BSR Pulse ;Then set it low <C437/17jun87>
|
||
BSR.S Wait100 ; and wait a while for it to go high <C437/17jun87>
|
||
DBRA D5,SeekLp1 ; <C437/15dec87>
|
||
MOVE.W D6,D7 ;Successful seek so update curr track <C437/17jun87>
|
||
|
||
SeekEnd BSR GetDrv1
|
||
MOVE.W D7,Track(A1,D1) ; update current track
|
||
|
||
TST.B mfmMode(A1) ;Are we in MFM mode? <C437/08dec87><1.1/28mar88>
|
||
BPL.S @00 ; <C437/08dec87>
|
||
BSR SetParams ;Yes, setup RAM parms for this disk zone<C437/08dec87>
|
||
BEQ.S @00 ; <C437/08dec87>
|
||
MOVE.W D0,D7 ;Error, so save the result code <C437/08dec87>
|
||
@00 ; <C437/08dec87>
|
||
|
||
MOVE.W HeadSettle(A1),D0 ; wait head settle time or until ready (new drive)
|
||
MOVEQ #5,D2 ; wait 500usec first time
|
||
BSR.S WaitReady ; <C437>
|
||
IF isUniversal THEN ; <H35>
|
||
TestFor hwCbPwrMgr ; is this a powerbook? <H35>
|
||
BEQ.W SeekEnd1 ; -> no, skip around artificial delay <H35>
|
||
MOVE.W #500,D0 ; need to wait 50 msec for drive to settle <H35>
|
||
BSR.W Wakeup ; just detecting /READY isn't enough <H35>
|
||
ENDIF ; <H35>
|
||
|
||
SeekEnd1 MOVE.W Wait(A1),D0 ; wait any speed change, power-on time
|
||
MOVEQ #0,D2 ; wait 0 time, first time
|
||
BSR.S WaitReady ; <C437>
|
||
|
||
MOVE.W D7,D0 ; positive value = success
|
||
SeekExit JMP (A6) ; A6 has return address
|
||
|
||
Wait100 MOVE.W SeekTime(A1),D0 ; wait 12 ms for old drive
|
||
BSR.S CheckNew ; go to WakeUp for the old interface
|
||
MOVEQ #80, D2 ; wait until step goes hi or timeout <C437/15dec87>
|
||
@1 MOVEQ #StepLAdr,D0
|
||
BSR AdrAndSense
|
||
DBMI D2, @1 ; <C437/15dec87>
|
||
|
||
; There appears to be an undocumented timing restriction related to sending step
|
||
; pulses to the drive. When /Step goes high, the spec indicates that you may immediatly
|
||
; set it low again to send the next pulse, however it appears that if you attempt to
|
||
; set it low within 18µsec of when it went high, it will not accept the step pulse,
|
||
; and will remain high. This will lead to seek errors, and is most noticable on
|
||
; processors that run at high clock rates (faster than the Mac IIx). If this is for
|
||
; a RAM based version of the MacPlus driver, we don't include it, since timeDBRA
|
||
; is not available on the MacPlus (but if we build a new MacPlus ROM we should support
|
||
; timeDBRA and this wait loop).
|
||
|
||
MOVE.W TimeDBRA,D2 ; 1000 µsec <2.0>
|
||
LSR.W #5,D2 ; 31.25 µsec (1000/32) <2.0><10>
|
||
@wait DBRA D2,@wait ; kill 31.25 µsec <2.0>
|
||
|
||
RTS
|
||
|
||
CheckNew TST.B NewIntf(A1,D1) ; new drive interface? <25Oct85>
|
||
BMI.S @1 ;-> yes (don't use wakeup) <C437/24nov86>
|
||
ADDQ #4, SP ; discard local return address <C437/24nov86>
|
||
TST.W D0 ; any time to wait? <C437/24nov86>
|
||
BNE.S WakeUp ; br if so <C437/24nov86>
|
||
@1 RTS ; <C437/24nov86>
|
||
|
||
waitReady BSR.S CheckNew ; go to WakeUp for the old interface
|
||
MOVE.L (SP)+, A4 ; get return address
|
||
MOVE.W #1000, D5 ; timeout (1 sec max to ready, any case)
|
||
|
||
MOVE.W D2, D0 ; first time wait
|
||
BEQ.S @2 ; check ready immediately if 0
|
||
|
||
@1 BSR.S WakeUp ; wait D0 * 100usec
|
||
@2 MOVEQ #ReadyAdr, D0 ; /Ready sense address
|
||
BSR AdrAndSense
|
||
BPL.S @3 ; br if /Ready asserted
|
||
MOVEQ #10,D0 ; check every millisec? - tune for seek
|
||
DBRA D5, @1 ; if we timeout, we must be ready?? Sony won't gate
|
||
; writes off if not ready (in case of bouncy ready line . . .)
|
||
@3 CLR.W Wait(A1) ; no extra wait time
|
||
JMP (A4)
|
||
eject ; <A351/05nov86>
|
||
|
||
;_______________________________________________________________________
|
||
;
|
||
; Routine: WakeUp,WakeSetUp,WakeGo
|
||
; Arguments: D0 (input) -- number of 100 usec intervals to wait (<65536)
|
||
; registers A3-A5 and D3-D7 are preserved.
|
||
; Called By: (WakeUp): Seek(3x),Eject,Recal,PowerUp
|
||
; (WakeSetUp,WakeGo): GotSect(RWT),WrgSectAdr(RWT)
|
||
; Function: Saves the return address in DskRtnAdr; it will call this
|
||
; routine after the timer interrupt in which the count is
|
||
; exhausted. Since the timer ticks away at 780 KHz,
|
||
; there are 78 timer ticks in each 100 microsecond interval.
|
||
; For MidMac timer ticks at 1.57 MHz so timer ticks = 157.
|
||
;_______________________________________________________________________
|
||
|
||
WakeUp
|
||
MOVE.L JWakeUp,-(SP)
|
||
RTS
|
||
|
||
jtWakeUp MOVEM.L D3-D7/A3-A6,SaveRegs(A1); save caller's regs first <C97/24jul86>
|
||
MOVE.L (SP)+,DskRtnAdr ; save return address next <C97/24jul86>
|
||
BSR.S WakeSetUp ; configure timer for D0 wait <25Oct85>
|
||
bra.s WakeRet ; go execute it. <C97/24jul86>
|
||
|
||
WakeGo MOVEM.L D3-D7/A3-A6,SaveRegs(A1); save caller's regs first <C97/24jul86>
|
||
MOVE.L (SP)+,DskRtnAdr ; save return address next <25Oct85>
|
||
WakeRet MOVEQ #0,D0 ; go back to user with no err
|
||
ANDI #$F8FF,SR ; and VIA interrupts enabled
|
||
RTS
|
||
|
||
WakeSetUp ; New WakeUp uses T2 Timer manager <25Oct85>
|
||
MOVE.L SonyVars,A1 ; <27Oct85>
|
||
|
||
SUB.W D0,Wait(A1) ; decrement any Wait time . . .
|
||
BGT.S @1 ;
|
||
CLR.W Wait(A1) ; pin at 0
|
||
|
||
@1 LEA TimeQEl(A1),A0 ; point at queue element
|
||
LEA GoWakeIt,A1 ; <27Oct85>
|
||
MOVE.L A1,tmAddr(A0) ; want to come here first <27Oct85>
|
||
AND.L #$0000FFFF,D0 ; clear high word of D0
|
||
CMP.W #10,D0 ; need to pin D0 to 10 (100usec intervals)
|
||
BCC.S @2
|
||
MOVEQ #10,D0
|
||
@2 DIVU #10,D0 ; divide by ten for msec
|
||
EXT.L D0 ; PrimeTime takes count in D0 long
|
||
|
||
MOVE.L jPrimeTime,A1 ; use dispatch table vector
|
||
JSR (A1) ; to start the timer (pass A0=TimeQEl ptr)
|
||
|
||
BRA GetDrv1 ; restore A1/D1 (and return) <27Oct85><C437/28jan88>
|
||
|
||
GoWakeIt MOVEM.L D0-D7/A0-A6,-(SP) ; save ALL regs
|
||
BSR GetDrive ;
|
||
MOVEM.L SaveRegs(A1),D3-D7/A3-A6 ; get back regs we saved
|
||
MOVEQ #0,D0 ; D0 = for RWT-MakeSpdTbl new intf path <25Oct85>
|
||
BSR DskRtn ; call DskRtnAdr
|
||
MOVEM.L (SP)+,D0-D7/A0-A6 ; restore registers
|
||
RTS ; we're done with it!
|
||
|
||
eject ; <A351/05nov86>
|
||
|
||
;_______________________________________________________________________
|
||
;
|
||
; Routine: Recal
|
||
; Arguments:
|
||
; D0 (output) -- result code
|
||
; This routine returns to one level above the caller during
|
||
; the recal (unless no seek is required).
|
||
; Called By: (Recal): Seek,DiskPrime,DoRecal
|
||
; Function: Recal to track 0. Leaves drive powered up. Sets IWM mode
|
||
; register.
|
||
;_______________________________________________________________________
|
||
|
||
Recal MOVE.L JRecal,-(SP) ; use RAM vector <03Mar85>
|
||
RTS ; <03Mar85>
|
||
|
||
jtRecal MOVE.L (SP)+,A5 ; save return address
|
||
BSR GetDrive
|
||
BSR InvalTrkCache ; invalidate track cache <A351/05nov86><24Oct85>
|
||
|
||
BSR SetChipMode ;Initialize appropriate register set<C437/19mar87>
|
||
|
||
bne.s RecalExit ; couldn't set IWM Mode <A351/05nov86>
|
||
BSR RWPowerUp ;Re-enable the interface <C437/19mar87>
|
||
MOVEQ #80,D7 ; maximum number of steps needed
|
||
|
||
MOVEQ #DirHAdr,D0 ;Set direction out (toward track 0) <C437/17jun87>
|
||
BSR AdrAndStrb ; <C437/17jun87>
|
||
|
||
TST.B NewIntf(A1,D1) ; new drive interface? <9>
|
||
BPL.S SlowLoop ; br if not (use slow step time) <9>
|
||
|
||
SUBQ #1,D7 ;Adjust count for DBRA <9>
|
||
@SeekLoop MOVEQ #StepLAdr,D0 ;Make sure /STEP starts out high <9>
|
||
BSR AdrAndSense ; <9>
|
||
BPL.S RecalFail ;-> it wasn't, so exit with error <9>
|
||
BSR Pulse ;Then set it low <9>
|
||
BSR.S Wait100 ;and wait a while for it to go high <9>
|
||
DBRA D7,@SeekLoop ;count track <9>
|
||
BRA.S ReCalled ;done 80 steps, exit... <9>
|
||
|
||
|
||
SlowLoop MOVE.W SeekTime(A1),D0 ; wait 12 ms <9>
|
||
BSR WakeUp
|
||
|
||
MOVEQ #Tk0Adr,D0 ;
|
||
BSR AdrAndSense ;
|
||
BPL.S ReCalled ; keep going until track 0 is true
|
||
|
||
MOVEQ #StepLAdr,D0 ; set step low
|
||
BSR AdrAndSense ; address it
|
||
BPL.S RecalFail ; can't recal (won't step, isn't at tk 0)
|
||
|
||
MOVEQ #tk0BadErr,D0 ; assume error
|
||
SUBQ.W #1,D7 ; reached maximum step count?
|
||
BEQ.S RecalExit ; exit if so
|
||
|
||
BSR Pulse ; then set it low
|
||
BRA.S SlowLoop ;
|
||
|
||
RecalFail MOVEQ #cantStepErr,D0 ; no track
|
||
BRA.S RecalExit
|
||
|
||
ReCalled MOVEQ #0,D0 ; track 0
|
||
RecalExit MOVE.W D0,Track(A1,D1)
|
||
JMP (A5)
|
||
eject ; <A351/05nov86>
|
||
;_______________________________________________________________________
|
||
;
|
||
; Routine: SetIWMMode
|
||
; Arguments:
|
||
; D0 (output) -- result code
|
||
; Called By: Recal,Seek,DiskPrime,DoRecal
|
||
; Function: Set the mode register of the IWM in case it glitched out (or first time).
|
||
; It no longer re-powers up the drive. <C437/08dec86>
|
||
;_______________________________________________________________________
|
||
|
||
SetIWMMode TST.B Q6H(A0) ; set IWM to sense mode
|
||
MOVEQ #$1F,D0 ;(mask for mode bits) <C437/20may87>
|
||
AND.B Q7L(A0),D0 ; sense the mode register <C437/20may87>
|
||
TST.B Q6L(A0) ; and back to read mode
|
||
CMP.B #IWMMode,D0 ; see if correct mode is set <A351/05nov86>
|
||
BEQ.S @2 ; br if so <C437/20may87>
|
||
|
||
MOVEQ #OneSecConst,D2 ; loop timeout count <29Jul85>
|
||
SWAP D2 ; should be about a second
|
||
|
||
@1 MOVEQ #initIWMErr,D0 ; assume timeout error
|
||
SUBQ.L #1,D2 ; decrement timeout loop
|
||
BMI.S @3 ; exit on error ... <A351/05nov86>
|
||
|
||
TST.B MtrOff(A0) ; change the IWM mode now
|
||
TST.B Q6H(A0) ; set IWM to sense state
|
||
MOVEQ #$3F,D0 ;(mask for sense, mode bits) <C437/20may87>
|
||
AND.B Q7L(A0),D0 ; sense the mode register <C437/20may87>
|
||
BCLR #5,D0 ; interface should be disabled <C437/20may87>
|
||
BNE.S @1 ; keep waiting
|
||
|
||
cmp.b #IWMMode,D0 ; see if low bits match <A351/05nov86>
|
||
BEQ.S @2 ; if so, we are done
|
||
|
||
MOVE.B #IWMMode,Q7H(A0) ; set to sony mode <A351/05nov86>
|
||
if NonSerializedIO then
|
||
nop ; force write to complete
|
||
endif
|
||
TST.B Q7L(A0) ; set IWM back to sense state
|
||
BRA.S @1 ; loop back just to check
|
||
|
||
@2 TST.B Q6L(A0) ; and back to read mode...
|
||
moveq #0,D0 ; repower the drive ... <A351/05nov86>
|
||
@3 rts ; <A351/05nov86>
|
||
eject ; <A351/05nov86>
|
||
;_______________________________________________________________________
|
||
;
|
||
; Routine: PowerDown,RWPowerDown
|
||
; Arguments: D0 (input) -- power-down time
|
||
; TimeOut (out) -- set to D0 input value
|
||
; TimeOutDrive (out) -- set to Drive if D0 nonzero
|
||
; Called By: DiskControl(Eject,KillIO calls),DskOff(RWT),DiskSelect
|
||
; Function: Does VBL task stuff; just powers off current drive if D0=0.
|
||
;_______________________________________________________________________
|
||
|
||
PowerDown BSR GetDrv1 ;
|
||
MOVE.W D0,TimeOut(A1) ; set up timeout
|
||
BEQ.S @1 ; branch if immediate power-down
|
||
MOVE.W Drive(A1),TimeOutDrive(A1) ; remember drive with timeout <25Oct85>
|
||
RTS
|
||
|
||
@1 MOVEQ #MtrOffAdr,D0
|
||
BSR AdrAndStrb ; turn it off both ways: PAL
|
||
|
||
MOVE.B #$86,wZeroes(A0) ;Kill the drive enable SWIM2 style <H2><SM6>
|
||
if NonSerializedIO then
|
||
nop ; force write to complete
|
||
endif
|
||
|
||
TST.B MtrOff(A0) ; cut the enable to power it down
|
||
RTS
|
||
|
||
;_______________________________________________________________________
|
||
;
|
||
; Routine: InvalTrkCache
|
||
; Arguments:
|
||
; A1 (input) -- SonyVars ptr
|
||
; D0 trashed
|
||
; Called By: Recal, Eject
|
||
; Function: Invalidates the track cache if it holds data for the current
|
||
; drive.
|
||
;_______________________________________________________________________
|
||
|
||
InvalTrkCache
|
||
MOVE.W TCDrive(A1),D0 ; get current track-cache drive <24Oct85>
|
||
CMP.W Drive(A1),D0 ; this drive? <24Oct85>
|
||
BNE.S @1 ; br if not <24Oct85>
|
||
CLR.W TCDrive(A1) ; invalidate it if so <24Oct85>
|
||
@1 RTS
|
||
|
||
;_______________________________________________________________________
|
||
;
|
||
; Routine: RWPowerUp,PowerUp
|
||
; Arguments: D0 (input) -- power-up time
|
||
; Timeout, Power, Wait, Drive
|
||
; Sets interrupt level 0 if powers up; uses A0-A2,D0-D2 (by wakeup) .
|
||
; 'Active' should be true when this routine is called.
|
||
; Called By: (RWPowerUp): RWPower,SetIWMMode
|
||
; (Fast Power): DiskControl(Eject call),DiskPrime
|
||
; Function: PowerUp is called to power up a disk drive. Waits out D0 time
|
||
; unless disk is already powered . . .
|
||
;_______________________________________________________________________
|
||
|
||
FastPower MOVEQ #0,D0
|
||
BRA.S PowerUp
|
||
|
||
RWPowerUp MOVE.W PwrOnTime(A1),D0
|
||
|
||
PowerUp MOVE.W D0,D2 ; save wait time
|
||
BSR.S DiskSelect ; go enable the interface
|
||
|
||
MOVE.B mfmDrive(A1,D1),D5 ;Is this a SuperDrive? <C437/28jan88>
|
||
BPL.S @1 ;-> no, don't have to set drive mode<C437/24nov86>
|
||
MOVEQ #GCRModeAdr,D0 ;find out which way the drive is set<C437/04feb88>
|
||
BSR AdrAndSense ; <C437/04feb88>
|
||
MOVE.B D0,-(SP) ; and save the state (bit7=1: MFM) <C437/04feb88>
|
||
MOVEQ #GCRModeAdr,D0 ;Assume we're in GCR mode <C437/24nov86>
|
||
MOVE.B mfmDisk(A1,D1),D5 ;Are we? <C437/28jan88>
|
||
BPL.S @0 ; <C437/24nov86>
|
||
MOVEQ #MFMModeAdr,D0 ;No, select MFM drive mode <C437/24nov86>
|
||
@0 BSR AdrAndStrb ;set the drive mode as desired <C437/04feb88>
|
||
MOVE.B (SP)+,D0 ;get the previous drive mode <C437/08feb88>
|
||
EOR.B D0,D5 ;bit 7=1 if the mode has changed <C437/04feb88>
|
||
@1 ; <C437/24nov86>
|
||
|
||
MOVEQ #MtrOnAdr,D0
|
||
BSR AdrAndSense ; is it already powered up?
|
||
|
||
OR.B D5,D0 ;or we just did a mode change? <C437/28jan88>
|
||
|
||
BPL.S @2 ; br if so <C437/28jan88>
|
||
BSR Pulse ; turn power on
|
||
|
||
MOVE.W D2,D0 ; get back wait time
|
||
MOVE #750,D2 ; wait at least 75ms the first time
|
||
MOVE.L (SP)+,D4 ;(jump up a stack level) <C437/26feb88>
|
||
BSR waitReady ; <C437/26feb88>
|
||
MOVE.L D4,-(SP) ;(restore stack level--rtn addr) <C437/26feb88>
|
||
|
||
CMP.B #ARdCmd,Command+1(A1) ; is it a read? <C437/26feb88>
|
||
BEQ.S @2 ;-> yes, all done <C437/26feb88>
|
||
MOVE.W #600*10,D0 ;for writes, we need to wait about <C437/26feb88>
|
||
BRA WakeUp ; 600ms after /READY for speed ±1.5%<C437/26feb88>
|
||
|
||
@2 RTS ; return <C437/28jan88>
|
||
|
||
eject ; <A351/05nov86>
|
||
;_______________________________________________________________________
|
||
;
|
||
; Routine: DiskSelect,DiskSel1
|
||
; Arguments: Drive -- drive to enable
|
||
; D1,A0,A1,A2 set up per GetDrive
|
||
; Clobbers D0.
|
||
; TimeOut cleared and TimeOutDrive powered off if not Drive.
|
||
; DiskSel1 is a quick entry for DiskSense
|
||
; Called By: (DiskSelect): PowerUp,DiskPrime,DiskOpen(2x),DiskControl,
|
||
; DCDStatus(Format/Verify),DCDHardReset.
|
||
; (DiskSel1): Ck4Disk
|
||
; Function: Assert the IWM enable to a drive. For DCDs, this is functionally
|
||
; equivalent to PowerOn since that function is not called. Whenever
|
||
; the enable to a floppy drive is cut, it is powered down automatically.
|
||
;
|
||
;_______________________________________________________________________
|
||
|
||
DiskSelect BSR GetDrive
|
||
|
||
DiskSel1
|
||
MOVE.L JDiskSel,-(SP) ; vector this routine
|
||
RTS
|
||
jtDiskSel
|
||
|
||
TST.W TimeOut(A1) ; timeout pending? <25Oct85>
|
||
BEQ.S @0 ; br if not <25Oct85>
|
||
MOVE.W TimeOutDrive(A1),D0 ; see if it's us <25Oct85>
|
||
CMP.W Drive(A1),D0 ; ? <25Oct85>
|
||
BEQ.S @0 ; br if so <25Oct85>
|
||
MOVEQ #0,D0 ; turn it off immediately <25Oct85>
|
||
BSR PowerDown ; (it will still be selected) <25Oct85>
|
||
|
||
@0 CLR.W TimeOut(A1) ; clear pending timeout <11Jun85>
|
||
|
||
TST.B mfmMode(A1) ;Are we in MFM mode? <C437/19mar87>
|
||
BMI mDiskSelect ;-> yes, do the MFM version <C437/19mar87>
|
||
|
||
CMP.W #drive1,D1 ; if Drive=1, it's internal
|
||
BNE.S @1 ; br if not
|
||
|
||
TST.B IntDrive(A0) ; select internal drive
|
||
TST.B MtrOn(A0) ; assert /enb
|
||
RTS
|
||
|
||
@1 TST.B Ph2H(A0) ; we may already be enabled in
|
||
TST.B Ph1H(A0) ; state 2, so go safely thru 6
|
||
TST.B Ph0H(A0) ; to state 7 (Ph0=Ph1=Ph2=1)
|
||
BCLR #vHeadSel,VBufD(A2) ; set HdSel low (/Exists addr)
|
||
if NonSerializedIO then
|
||
nop ; force write to complete
|
||
endif
|
||
|
||
@2 TST.B ExtDrive(A0) ; select the external
|
||
|
||
TST.B MtrOn(A0) ; and enable the disk, IWM style
|
||
RTS
|
||
|
||
eject ; <A351/05nov86>
|
||
;_______________________________________________________________________
|
||
;
|
||
; Routine: MakeSpdTbl,GetFreq1
|
||
; Arguments: Drive (input) -- current drive
|
||
; D0 (output) -- error code (-1 = drive not installed)
|
||
; all registers are used.
|
||
; current drive is powered up and recal'ed.
|
||
; Called By: (MakeSpdTbl) CheckDIP,DoRecal
|
||
; (GetFreq1) RWT, Format
|
||
; Function: Makes a speed table for the current drive.
|
||
;
|
||
; Note: Drive must spin at speed codes 128 and 256 for this routine
|
||
; to work.
|
||
;
|
||
; Note: Speed variation has three major factors, temperature drift, speed
|
||
; drift, and load variation. Temperature drift occurs as the drive gets
|
||
; warmer and generally? is a negative factor (drive slows) accounting for
|
||
; up tp 6%? of speed variation. Speed drift occurs during
|
||
; the first minute the drive is powered and is a negative factor accounting
|
||
; for less than 1/2 of 1% of speed variation. Load is a factor which
|
||
; varies between inside and outside tracks of a drive: the inner tracks
|
||
; present less loading to the head than the outer tracks; speed variation
|
||
; due to loading may be as much as 1%.
|
||
;
|
||
; The main read/write track logic adjusts for speed drift by periodically
|
||
; checking the disk speed and adjusting the speed code if the speed is off
|
||
; by more than 2% using a speed code delta figured out by this routine: this
|
||
; should also catch any speed drift problems, depending upon the period
|
||
; of the check.
|
||
;
|
||
; We ignore loading variation since it is only 1% max and we will recheck
|
||
; each speed class when we first seek to it. Temperature and speed drift
|
||
; are not as easy to compensate for, but since they are both negative factors,
|
||
; this routine rounds to higher speed values.
|
||
;
|
||
;_______________________________________________________________________
|
||
|
||
MakeSpdTbl MOVE.L JMakeSpdTbl,-(SP)
|
||
RTS
|
||
|
||
jtMakeSpdTbl
|
||
|
||
MOVE.W #8000,D0 ; delay for 800 ms on new drive <29Jul85>
|
||
BRA WakeUp ; (to seat diskette correctly) <25Oct85>
|
||
|
||
eject ; <A351/05nov86>
|
||
;_______________________________________________________________________
|
||
;
|
||
; Routine: FigTrkSpeed,DskRtn
|
||
; Arguments: D0 (output) -- -1=timeout reached or long VIA count for one rev
|
||
; Called By: (FigTrkSpeed): MakeSpdTBL
|
||
; (DskRtn): WrData,RdAddr,RdData,GoWakeIt(WakeUp)
|
||
; Function: This routine measures the time (in VIA counts) it takes
|
||
; for the disk to revolve .25 times; this test looks for the tach
|
||
; pulse which occurs 60 times per rev. VIA timer 2 is used; if
|
||
; 15 tach pulses are not seen in 78 msec, this routine
|
||
; will time out and take the error exit.
|
||
;
|
||
; The drive should be powered when this is called. Speeds as
|
||
; low as 192 RPM may be measured.
|
||
;_______________________________________________________________________
|
||
|
||
FigTrkSpeed MOVE.L JFigTrkSpd,-(SP)
|
||
RTS
|
||
|
||
jtFigTrkSpd MOVEQ #-1,D0 ; no PWM, don't use timer
|
||
RTS
|
||
|
||
DskRtn MOVE.L DskRtnAdr,-(SP)
|
||
TST.W D0 ; set CCR
|
||
RTS
|
||
eject ; <A351/05nov86>
|
||
|
||
;_______________________________________________________________________
|
||
;
|
||
; Routine: DiskVBLTask
|
||
; Arguments: A0.L (input) -- disk VBL queue block ptr
|
||
; This routine MUST preserve A4-A6 and D4-D7 (like any VBL task)
|
||
; TimeOut non-zero, positive value if power-down is pending
|
||
; DiskInPlace drive variable
|
||
; Power drive variable
|
||
;
|
||
; Function: This VBL task handles disk power-down delays and checks for
|
||
; diskette-inserted and disk-eject-switch when both drives are
|
||
; powered down.
|
||
;
|
||
; - on power-down delays, add a check for a flag which says "call flush volume
|
||
; first . . ."; this could be the paranoia bit . . .
|
||
;_______________________________________________________________________
|
||
|
||
DiskVBLTask
|
||
MOVE SR,-(SP)
|
||
MOVE.L SonyVars,A1
|
||
MOVE.W DskVBLTime(A1),VBLCount(A0) ; reset VBL task
|
||
|
||
IF hasPwrControls THEN ; <SM5>
|
||
TestFor hwCbPwrMgr
|
||
BEQ.S @pmgrdone
|
||
|
||
BSR TurnIWMon ; IWM needed now <C907><v2.3>
|
||
@pmgrdone
|
||
ENDIF ; <SM5>
|
||
|
||
MOVE.B isSWIM(A1),D0 ; see if the IWM/SWIM/... is installed <H15><SM6>
|
||
SUBQ.B #1,D0 ; <H15><SM6>
|
||
BNE.S @Done ; -> yes, just return <H15><SM6>
|
||
CLR.W TimeOut(A1) ; clear any pending timeouts <SM6>
|
||
CLR.W LastDrive(A1) ; and show no last drive <SM6>
|
||
@Done ; <SM6>
|
||
BEQ.S DiskVBLExit ; -> no IWM/SWIM/... chip installed <H5><SM6>
|
||
|
||
ORI #HiIntMask,SR ; no VBL & AppleTalk (fileserver) <A351/05nov86><A216/17oct86><29Jul85>
|
||
|
||
TST.B Active(A1) ; any active requests?
|
||
BNE.S DiskVBLExit ; exit if so
|
||
|
||
TST.W TimeOut(A1) ; timeout pending?
|
||
BEQ.S @1
|
||
|
||
@0 SUBQ.W #1,TimeOut(A1) ; wait for it to go to zero <C907>
|
||
BNE.S DiskVBLExit ; exit if there is a powered-up disk
|
||
|
||
; we timed out, so turn off the power (turn out the lights)
|
||
|
||
MOVEQ #MtrOffAdr,D0
|
||
BSR AdrAndStrb ; turn it off both ways: PAL
|
||
|
||
@1 MOVEQ #1,D3 ; start with drive 1
|
||
|
||
@2 BSR.S Check4Disk ; check for disk-in-place
|
||
ADDQ #1, D3
|
||
|
||
CMP.W #maxDrvNum, D3 ; 2 drives max for MidMac <29Jul85>
|
||
BLE.S @2 ; <C37/3Jun86>
|
||
|
||
@3
|
||
|
||
MOVE.B #$86,wZeroes(A0) ;Kill the drive enable SWIM2 style <H2><SM6>
|
||
if NonSerializedIO then
|
||
nop ; force write to complete
|
||
endif
|
||
|
||
TST.B MtrOff(A0) ; cut IWM enable (new drive fix)
|
||
|
||
IF hasPwrControls THEN ; <SM5>
|
||
TestFor hwCbPwrMgr
|
||
BEQ.S @pmgrdone2
|
||
|
||
tst.l d3 ; see if any drives ejecting? <1.6>
|
||
bmi.s DiskVBLExit ; if so, don't turn off drive power <1.6>
|
||
MOVE (SP), SR ; Re-enable interrupts <v2.3>
|
||
BSR TurnIWMoff ; IWM not needed now <C907>
|
||
@pmgrdone2
|
||
ENDIF ; <SM5>
|
||
|
||
DiskVBLExit MOVE (SP)+, SR
|
||
RTS
|
||
;
|
||
;Check up on drive #(D3); post DiskInPlace:0 events if a diskette is
|
||
;inserted, and post DiskInPlace:X events if the Eject switch is pressed.
|
||
;
|
||
Check4Disk
|
||
MOVE.W D3,Drive(A1)
|
||
BSR GetDrive ; set up A0,A1,D1
|
||
TST.B Installed(A1,D1) ; is there a drive attached?
|
||
BMI CkExit ; exit if not
|
||
|
||
TST.B DiskInPlace(A1,D1) ; if a diskette is in place, <C123/03sep86>
|
||
bgt.s CkEject ; go check for eject <C123/03sep86>
|
||
beq.s CkDIP ; else go check for one inserted <C123/03sep86>
|
||
|
||
IF hasPwrControls THEN ; <SM5>
|
||
TestFor hwCbPwrMgr
|
||
BEQ.S @pmgrdone
|
||
|
||
ADDQ.B #1,DiskInPlace(A1,D1) ; else if waiting for eject complete
|
||
bpl.s CkDIP ; when done, go check for a disk <1.6>
|
||
bset.l #31,d3 ; indicate drive is ejecting <1.6>
|
||
bra.s CkInval ; wait until eject timeout done <1.6>
|
||
@pmgrdone
|
||
ENDIF ; <SM5>
|
||
|
||
ADDQ.B #1,DiskInPlace(A1,D1) ; else if waiting for eject complete
|
||
bmi.s CkInval ; decrement until 0 <C123/03sep86>
|
||
bra.s CkDIP ; then go check for a disk <C123/03sep86>
|
||
;
|
||
;There is a disk in place; check to see if the eject switch was pushed, and
|
||
;if so, post a DiskInsertEvt:Eject event.
|
||
;
|
||
CkEject
|
||
bsr DiskSel1 ; select the drive, <C123/03sep86>
|
||
bsr.s CkEjSw ; go read the eject switch, <C123/03sep86>
|
||
bpl.s CkExit ; if not pressed do nothing <C123/03sep86>
|
||
MOVEQ #-1,D0 ; upper D0 = eject (-1) <C123/03sep86><C437>
|
||
move.w Drive(A1),D0 ; lower D0 = drive number <C123/04sep86>
|
||
move.w #DiskInsertEvt,A0 ; <C123/03sep86>
|
||
_PostEvent ; post the event <C123/03sep86>
|
||
bra.s CkExit ; any error is ignored <C123/03sep86>
|
||
;
|
||
;There is no disk in place; read the drive interface to see if one was inserted,
|
||
;and if so, post a DiskInsertEvt:DIP.
|
||
;
|
||
CkDIP bsr DiskSel1 ; select the disk, <C123/03sep86>
|
||
|
||
@1 moveq #DIPAdr,D0 ; for Sony drives, <C123/03sep86>
|
||
bsr AdrAndSense ; check DIP at the drive, <C123/03sep86>
|
||
bmi.s CkExit ; exit if none <C123/03sep86>
|
||
|
||
@2 bsr.s CkEjSw ; read, reset & ignore Eject Switch <C123/03sep86>
|
||
MOVEQ #DiskInsertEvt,D0 ; upper D0 = DIP (0) <C123/03sep86><C437>
|
||
MOVEA.L D0,A0 ; A0 = event type, <C123/03sep86><C437>
|
||
move.w Drive(A1),D0 ; lower D0 = drive number <C123/04sep86><C437>
|
||
_PostEvent ; post the event <C123/03sep86>
|
||
BNE.S CkInval ; br if not posted (probably boot time)
|
||
ADDQ.B #1,DiskInPlace(A1,D1) ; unclamped disk-in-place = 1
|
||
|
||
CkInval ST Track(A1,D1) ; mark current track invalid
|
||
MOVEA.L IWM,A0 ; restore IWM ptr
|
||
|
||
CkExit RTS
|
||
;
|
||
;See if the Eject Switch is pressed on the selected drive and
|
||
;reset the latched status bit. Returns BMI if switch pressed.
|
||
;
|
||
CkEjSw tst.b sides(a1,d1) ; just exit if 400K drive <1.2/26apr88>
|
||
BPL.S @DontEject ; <SM6>
|
||
MOVE.B mfmDrive(A1,D1),D0 ; is this drive a SuperDrive? <SM6>
|
||
NOT.B D0 ; BPL if so, BMI if not <SM6>
|
||
@DontEject ; any error is ignored <SM6>
|
||
bpl.s @1 ; because there's no eject switch <1.2/26apr88>
|
||
moveq #EjectLAdr,D0 ; eject latch address, <C123/04sep86>
|
||
bsr AdrAndSense ; go sample it, <C123/04sep86>
|
||
bpl.s @1 ; exit if no switch pressed, <C123/04sep86>
|
||
moveq #RdDta1Adr,D0 ; else reset the switch latch <C123/04sep86>
|
||
bsr AdrAndStrb ; by reading some damn thing <C123/04sep86>
|
||
MOVEQ #-1,D0 ; return BMI <C123/04sep86><C437>
|
||
@1 rts ; <C123/04sep86>
|
||
|
||
|
||
|
||
|