1497 lines
60 KiB
Plaintext
Raw Normal View History

;
; File: Sony.a
;
; Contains: Sony Floppy Driver
;
; Written by: Larry Kenyon
;
; Copyright: <09> 1985-1993 by Apple Computer, Inc., all rights reserved.
;
; Change History (most recent first):
;
; <SM13> 12/13/93 PN Roll in KAOs and Horror changes to support Malcom and AJ
; machines
; <SM12> 5/19/93 GMR Removed call to InitICON, since we now use Universal tables for
; this info.
; <SM11> 1/10/93 RC added more nops for SMurf
; <SM10> 01/09/93 HY Added RawTrackDump entry in CtlTbl for SWIM2 machines.
; <SM9> 12/14/92 RC Restore Pre-PDM D2 with Horror Roll in
; <SM7> 12/7/92 rab Roll in Horror changes. Comments follow<6F>
; <H24> 7/13/92 SWC Fixed a bug in the sleep task which prevented us from going to
; sleep if we time out waiting for SWIM power to go off.
; <H23> 7/2/92 SWC Cleared ChipState in wakeup code to force SWIM power on since
; it's possible that power could still have been on before going
; to sleep.
; <H22> 6/26/92 SWC Fixed a bug that was trashing a register in the wakeup code.
; Sleep/wakeup code now sets/clears <20>active<76> to prevent VBLs from
; running before everything is re-initialized on wakeup.
; <H15> 3/18/92 SWC Changed the chip test patches to use isSWIM>0 to flag that no
; chip is currently connected instead of diddling with the chip
; all the time. TestForChip will now only be called in Open and in
; the sleep task when we wake up. The sleep task will now also run
; the ChkConnect code in Open to initialize the drive info if
; nothing was connected at startup but was added during sleep.
; <H13> 2/25/92 CMP Added code for speed check status call.
; <H11> 2/13/92 CMP Put in code for CtlRetries control call. Also, code to
; initialize and check for retry disable flag.
; <H9> 3/18/92 SWC Added a label and some extra checking so we can reuse the
; ChkConnect code when coming out of sleep. Marked some lines in
; the cache installation code for removal in the next
; non-overpatch ROM (and NOP'd some branches) since they're either
; way out of date (check for a 128K Mac?), or cuz they allocate
; too small a cache if there are no drives connected at startup
; (which is possible on DBLite, at least).
; <H8> 1/9/92 CMP Changed TestForChip so that ROMBASE is read to clear bus lines
; instead of writing to rPhase register of SWIM2.
; <H5> 12/18/91 SWC Changed the check in TestForChip so that it looks for IWM or
; SWIM/SWIM2 registers in addition to doing a bus error check cuz
; the final MSC doesn't bus error if the chip isn't there.
; <H4> 11/14/91 SWC Moved code that had been added to other files but not
; overpatched. Shortened SWIM2 patches where possible. Removed
; SetIWMMode patch since SetIWMMode won't be called on a SWIM2.
; Added a SWIM chip bus error handler to check if the chip is
; currently installed for DB-Lite. Converted the SCC polling code
; to a macro so it's easier to overpatch. Added patch to mAdrDisk
; to use the SWIM/SWIM2 HDSEL pin for head selection in addition
; to the VIA bit. Added DB-Lite's drive icon.
; <H2> 10/18/91 CMP Added support for SWIM2.
; <SM6> 12/02/92 HY Added IF hasPwrControls around pwmgr specific code.
; <SM5> 10/18/92 CCH Added nop's for systems with non-serial writes to IO space.
; <9> 7/14/92 CSS Fixed the comment below so an exact version of this
; file could be copied into SuperMario.
; <8> 4/27/92 JSM Get rid of conditionals: supportsPWM, supportsDCD, and
; has3rdFloppy are always false, forROM, supportsMFM, forDiskDup,
; isUniversal, hasPowerMgr, and hasPwrControls are always true
; (although hasPowerMgr currently isn<73>t for the ROM, it will be
; and was always ORed with hasPwrControls here anyway). This file
; now has no conditionals.
; <7> 12/26/91 RB Updated to use the new Power Mgr records
; <6> 9/25/90 GMR Changed the eject track to 40 (was 79) because Peripherals wants
; it there (questions? Call Damon Rando).
; <5> 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.
; <4> 2/2/90 GMR Changed the time-out in Eject from 1.5 seconds to 3 seconds to
; support the low-cost 800k drives and hopefully low cost
; SuperDrives.
; <3> 1/16/90 MSH Roll in Portable changes from Fiction.
; <2> 1/15/90 MSH Preparing comment header for conversion.
; <2.4> 5/23/89 GGD Moved driver header and version equates to SonyHdr.a Converted
; to use new interface to InitIcon routine. Fixed branch bug in
; HcMac Sleep/Wakeup code from code review.
; <2.3> 4/29/89 GGD Fixed Open code to pass Physical drive number _AddDrive on 2
; drive systems to avoid problems when drive 1 is not connected
; but drive 2 is.
; <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 SWC added DupVerSts for Disk Duplicator version of the driver.
; GGD Removed temporary delay loop in wakeup code for HcMac, since
; hardware fix is now implemented. Changed bit numbering of bits
; in chipState, now same as pmgr enables bits. Added new routine
; UpdateChipState, to read the power/clock enable bits. Fixed bug
; in GetFormatList status call when assembled for NOT SupportsMFM
; it would return just one entry (400K) when called for an 800K
; drive.
; <2.0> 12/15/88 GGD Changed some machine based conditionals to feature based.
; <1.2> 11/21/88 CCH Changed ForRam equates to ForRom.
; <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 Added entries in the control/status dispatch tables for disk
; duplicator. Made driveXLAT references conditional for everyone
; but onMac. Changed reference of sQType to slpQType, since its
; name changed.
; <1.8> 8/19/88 SWC Added entries in the control/status dispatch tables for disk
; duplicator. Made driveXLAT references conditional for everyone
; but onMac.
; <1.7> 8/16/88 GGD Added Sleep Queue Handler and installation for HcMac. Fixed bug
; in turning on IWM in Open on 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 Changed jump vector initialization for jSetSpeed to point to an
; RTS when PWM is not supported. SWC/Check for SuperDrives all the
; time since they look like they have an old interface which slows
; things down. Made cache size bigger ONLY if at least 1
; SuperDrive is connected.
; <1.2> 4/26/88 GGD Changed jSetSpeed to point to DiskRTS if PWM not supported.
; <1.2> 4/26/88 SWC Made cache size bigger ONLY if at least 1 SuperDrive is
; connected.
; <1.1> 4/18/88 GGD Merged in MFM support <C437> by Steve Christensen call InitIcon
; for new 'patcheable' disk icons <S024><S025> Change Passport
; status to check TwoMegFmt before mfmDisk for GCRonMFM Fixed bug
; with eject being ignored during boot. Added vector
; initialization for MFM I/O routines.
; <1.1> 3/9/88 GGD Added vector initialization for MFM I/O routines.
; <1.1> 3/9/88 GGD Fixed above fix, to really avoid clicking again.
; <1.1> 3/7/88 GGD Fixed eject/DIP check, to really check at the drive, to fix
; mousekey eject.
; <1.1> 2/29/88 GGD Change version to 2 when supportsMFM
; 2/26/88 SWC Fixed DIP and error code bugs in status call 6.
; <1.0> 2/12/88 BBM Adding file for the first time into EASE<53>
; 2/4/88 SWC Fixed a bug in MFMStatus: forgot A0 was already offset to
; csParam.
; 10/26/87 SWC Added a check in PassportSts to make sure the disk is clamped so
; that the info that's returned is valid.
; <C913> 10/16/87 MSH Used the same name for two different things. Not good.
; 10/14/87 SWC Added a seek to track 79 when ejecting to make sure the head is
; off of all important parts of the disk.
; <C907> 10/8/87 MSH Port to HcMac (Laguna).
; 10/7/87 SWC Changed disk format status to return disk size in BLOCKS not
; BYTES.
; 9/18/87 SWC DiskStatus: changed order of error checking to bad csCode first.
; 5/1/87 SWC Added a control call to set the format mode for MFM or GCR.
; Added a status call to return extended status (including MFM
; info). Added new status call to return list of possible disk
; formats. Now dispatch status calls the same way as control
; calls.
; <C437> 2/22/87 SWC Ignore the eject call if no disk is in the drive (avoids
; clicking).
; <C437> 11/24/86 SWC Check to see if we're using a SWIM and/or SuperDrives, and
; initialize isSWIM(A1) and mfmDrive(A1,D1).
; <A351> 11/5/86 TJ Removed Grow Zone stuff. Cleaned up comments, added eject
; statements.
; <C216> 10/17/86 TJ Correct comment only in Control calls #21, #22.
; <C123> 8/21/86 TJ Cleaned up ctlDispatch code and added Icon and Info control
; calls. Removed reference to TFSDEBUG; seemed like old debug junk
; anyways. Not defined in new equate system.
; <C115> 8/13/86 TJ Made conditional some references to DCD, etc that dont apply to
; nuMac. Fixed some bugs in xlat table creation.
; <C97> 8/1/86 TJ Removed hardcoded drive number stuff from Open call, when
; determining Sony/DCD; changed to use firstDCD, etc. Added drive
; number translate table build at Open time.
; <C37> 6/3/86 CSL Support 2nd internal floppy drive for Aladdin.
; <C1> 5/5/86 RDC Changed old onMidMac conditional to onNuMac
; <C1> 4/25/86 RDC Changed forMac conditional equate to onMac
; 10/29/85 LAK Fixed bug in control exit.
; 10/27/85 LAK Added routine DispSetUp to fix bug.
; 10/25/85 LAK CkDrvNum saves old Drive value in LastDrive. Ignore KillIO (DCD
; has no way to notify, new Time manager needs call to abort any
; current request - if we can't do it right, don't do it at all).
; Init NewIntf drive var. Use NewIntf rather than Sides to
; determine whether drive has new interface. Assert /enb for >150
; usec after /cstin goes away for new drive.
; 10/24/85 LAK Changed version number back to 1 because old format packages
; assume version 4 drivers have their correct size in drive queue
; entry. Invalidate any track cache data on ejects.
; 9/6/85 LAK Only write DskErr if there WAS an error.
; 7/31/85 RDC Modified control dispatch table and routine to remove DCD
; dependencies for MidMac
; 7/29/85 RDC Changed interrupt level settings to use equates Eliminated DCD
; code for MidMac
; 7/24/85 LAK Converted back from MDS to the WorkSlop. Old Mod history moved
; to SonyHdr file. SonyRAM now cuts back the driver after install.
;_______________________________________________________________________
; offset table for jump table initialization
DiskClose MOVEQ #ClosErr,D0 ; report error: not closable at present
RTS
InitDskTbl
DC.W jtFigTrkSpd-InitDskTbl
DC.W jtDiskPrime-InitDskTbl
DC.W jtRdAddr-InitDskTbl
DC.W jtRdData-InitDskTbl
DC.W jtWrData-InitDskTbl
DC.W jtSeek-InitDskTbl
DC.W jtSetUpPoll-InitDskTbl
DC.W jtRecal-InitDskTbl
DC.W jtControl-InitDskTbl
DC.W jtWakeUp-InitDskTbl
DC.W jtReSeek-InitDskTbl
DC.W jtMakeSpdTbl-InitDskTbl
DC.W AdrDisk-InitDskTbl ; provide access to these routines
dc.w DiskRTS-InitDskTbl ; SetSpeed does nothing if no PWM <C115/22aug86><1.2/26apr88>
DC.W Nibl-InitDskTbl ; programs (not patchable)
InitDsk2
DC.W jtDiskSel-InitDskTbl ; interface select routine <25Oct85>
DC.W jtMRdAddr-InitDskTbl ; Read MFM address routine <1.1/09mar88>
DC.W jtMRdData-InitDskTbl ; Read MFM data routine <1.1/09mar88>
DC.W jtMWrData-InitDskTbl ; Write MFM data routine <1.1/09mar88>
InitParams
DC.B 8,0 ; max 8 soft errs per recal/track
DC.B 2,0 ; max 2 recals per track
DC.B 64,0 ; max 64 wrong sectors per sector
DC.B 8,0 ; max 8 wrong speeds per track
DC.W 0 ; I/O command 0
DC.W KHdSetTime ; deflt head settle time = 30 ms
DC.W KSpdChgTime ; deflt speed chg wait time = 150 ms
DC.W KPowerOn ; deflt pwr-on = .4 sec
DC.W KRWPOff ; deflt pwr-off = 2-2.5 sec
DC.W KSeekTime ; deflt seek wait time = 12 ms
DC.W KSectTime ; deflt sector time = 10 ms
DC.W KDskVBLTime ; deflt disk VBL time = .5 sec
DC.W KEjectTime ; deflt eject time = .75 seconds
DC.L KCkDelta ; deflt speed check time = 4 min
DC.B KEjectWait,0 ; deflt dip ck wait after eject = 1.5 sec
InitBCnt EQU *-InitParams ; 16 words to init (32 bytes)
DispSetUp MOVEQ #0,D2 ; clear high part for arithmetic <27Oct85>
MOVE.W (A0)+,D2 ; get the next offset
ADD.L D0,D2 ; compute the address
MOVE.L D2,(A1)+ ; install it in the jump table
DBRA D1,DispSetUp ; loop for vectors <27Oct85>
RTS ; <27Oct85>
eject ; <A351/05nov86>
; Disk Driver Initialization routine
DiskOpen MOVE.L #DiskVarLth,D0 ; get memory for driver variables
_NewPtr ,SYS,CLEAR
MOVE.L A0,SonyVars ; and keep pointer in low memory
MOVE.L A1,(A0) ; DCE pointer
MOVE.B #Version,DCtlQueue+1(A1) ; put our version number in
ST Active(A0) ; mark driver active for VBL exclusion
CLR.B DisableRetries(A0) ; make sure we do retries <H11><SM7>
IF hasPwrControls THEN ; <SM6>
TestFor hwCbPwrMgr
BEQ.S @pmgrdone
MOVEA.L A0,A1 ; A1 := pointer to SonyVars <1.7>
BSR TurnIWMon ; Turn IWM on with pmgr call <C907><C913><1.7>
@pmgrdone
ENDIF ; <SM6>
move.l UnivInfoPtr,a2 ; <SM12>
adda.l ProductInfo.IconInfoPtr(a2),a2 ; point to icon info table for this machine <SM12>
move.l a2,DrvTblPtr(a0) ; save in our locals <2.4>
MOVE.L A0,A2 ; save locals ptr for later
; initialize the disk routine jump table
LEA InitDskTbl,A0 ; point to the offset table
LEA JFigTrkSpd,A1 ; point to 1st jump table entry
MOVEQ #14,D1 ; there are 15 vectors
MOVE.L A0,D0 ; remember its address
BSR.S DispSetUp ; do these <27Oct85>
LEA JDiskSel,A1 ; point to 1st jump tbl entry, 2nd JT <25Oct85>
MOVEQ #0,D1 ; 1 vector here <25Oct85>
BSR.S DispSetUp ; do these <27Oct85>
MOVEQ #3-1,D1 ; 3 vectors here <1.1/09mar88>
LEA jMRdAddr,A1 ; point to 1st jump tbl entry, 2nd JT<1.1/09mar88>
BSR.S DispSetUp ; install the MFM vectors <1.1/09mar88>
ST OneToOne(A2) ; go 1 to 1 for now . . . ???
LEA ReadErrInit(A2),A1 ; destination
LEA InitParams,A0 ; source
MOVEQ #InitBCnt,D0
_BlockMove
; allocate a VBL task to handle disk power-down and disk-in-place sensing
; (note that VBL phase was cleared by disk variable initialization)
LEA DiskQVE(A2),A0 ; get address of VBL ctl blk
MOVE.W #VType,QType(A0) ; init queuing fields
LEA DiskVBLTask,A1 ; get addr of powerdown task
MOVE.L A1,VBLAddr(A0) ; set up address
MOVE.W #KDskVBLTime,VBLCount(A0)
; it gets called every 1/2 second
_VInstall ; install the disk task
; install the time manager queue element for use later by the wakeup routines.
LEA TimeQEl(A2),A0 ; point at the time Q Element
_InsTime ; make the time manager aware of us
IF hasPwrControls THEN ; <SM6>
TestFor hwCbPwrMgr
BEQ.S @pmgrdone2
WITH SleepqRec ; <7> rb
LEA DiskSleepQEL(A2),A0 ; get address of sleep queue element<1.7>
CLR.W SleepqFlags(A0) ; fill in Flags <1.7>
MOVE.W #slpQType,SleepqType(A0) ; fill in qType field <1.7><1.8>
LEA HandleSleep,A1 ; get handler routine address <1.7>
MOVE.L A1,SleepqProc(A0) ; setup handler address <1.7>
_SlpQInstall ; Add to sleep queue <1.7><2.3>
@pmgrdone2
ENDWITH ; <7> rb
ENDIF ; <SM6>
BSR TestForChip ; see if the IWM/SWIM/... is installed <H4><SM7>
BEQ.S @Continue ; -> it is, so continue <H4><SM7>
MOVEA.L SonyVars,A1 ; point to driver variables <H4><SM7>
MOVE.B #1,isSWIM(A1) ; mark that no disk controller is connected <H15><SM7>
CLR.B Active(A1) ; no longer active <SM7>
IF hasPwrControls THEN ; <SM6>
TestFor hwCbPwrMgr ; <SM7>
BEQ.S @pmgrdone3 ; <SM7>
BSR TurnIWMoff ; Turn IWM off with pmgr call <C907><C913><SM7>
@pmgrdone3 ; <SM7>
ENDIF ; <SM6>
MOVEQ #0,D0 ; return noErr to the Device Manager <H4><SM7>
bra.w DiskRTS ; <SM7>
@Continue ; <H4><SM7>
; Check that pass-thru is working on the external connect - if a DCD is
; connected which doesn't implement pass-thru, it will look like there
; are an infinite number of hard disks connected (we assume 7=infinite).
;
; Pass thru logic is still used if only a single floppy is connected
; externally (simplifies the logic and shouldn't matter).
BSR Check4SWIM ;Is a SWIM installed? <C437/24nov86>
; Now see what drives are connected - install drive queue entries for them. We
; build the drive number translate table now also; we previously set it up
; 1:1 to start. Existing drives end up and the low end of the Sony drive
; number sequence (1 to firstDCD) with non-existent ones near the end; this
; accomodates (hopefully) copy protection schemes that assume drive #2 is
; the "second" disk, where in macPP this may not be true.
MOVEQ #1, D2 ; start with drive 1
move.l D2,D5 ; first drive # to translate <c97/01aug86>
ChkConnect MOVE.W D2, Drive(A1)
BSR GetDrive ; set up A0, A1, A2, D1
TST.B Installed(A1,D1) ; has this drive already been installed? <H9><SM7>
BGT.S @5 ; -> yes, leave it alone <H9><SM7>
ST Installed(A1,D1) ; start by marking it 'not installed'
@1
BSR DiskSelect ; select the interface
@2 MOVEQ #DrvExstAdr, D0 ; check floppy-exist sense bit
BSR AdrAndSense ; connected?
BMI.S @5 ; exit if not
MOVEQ #SidesAdr, D0 ; see how many sides it has
BSR AdrAndSense ;
SMI Sides(A1,D1) ; $FF=two-sided
MOVEQ #NewIntfAdr, D0 ; see if it implements the new intf <25Oct85>
BSR AdrAndSense ; <25Oct85>
SMI NewIntf(A1,D1) ; $FF=new interface <25Oct85>
MOVEQ #mfmDrvAdr,D0 ;See if the drive's a SuperDrive <C437/24nov86>
BSR AdrAndSense ; <C437/24nov86>
BPL.S @3 ; <C437/24nov86>
ST NewIntf(A1,D1) ;SuperDrives have the new interface <C437/24nov86>
TST.B isSWIM(A1) ;Is a SWIM installed? <C437/24nov86>
BPL.S @3 ;-> no <C437/24nov86>
ST mfmDrive(A1,D1) ;$FF=SuperDrive, $00=400K or 800K <C437/24nov86>
ST hasSuperDrives(A1) ;$FF=at least 1 SuperDrive connected<1.2/26apr88>
@3 MOVEQ #SonyRfN,D3 ; use regular refnum for floppies
@4
MOVE.W D2,D0 ; Physical drive num in the queue <2.3>
MOVE.B #1,Installed(A1,D1) ; mark 'installed' in Drive vars
SWAP D0
MOVE.W D3, D0 ; driver refnum (-5 for Sony, -2 for DCD)
LEA DQEL(A1,D1), A0 ; drive queue element for this drive
_AddDrive ; D0=[drive num][driver refnum]
; returns D0=0
addq #1,D5 ; next logical drive ... <C97/01aug86>
@5 ADDQ.W #1, D2 ; check the next physical drive
CMP.W #maxDrvNum,D2
BLE.S ChkConnect
CLR.B Active(A1) ; no longer active
IF hasPwrControls THEN ; <SM6>
TestFor hwCbPwrMgr
BEQ.S @pmgrdone
BSR TurnIWMoff ; Turn IWM off with pmgr call <C907><C913>
@pmgrdone
ENDIF ; <SM6>
MOVEQ #0, D0 ; we're cool
DiskRTS RTS
eject ; <A351/05nov86>
;_______________________________________________________________________
;
; DiskDone
;
; D0: return code
;
; DiskDone is used to indicate IO completion to the device
;manager, by dispatching through jIODone. The driver active flag
;is cleared, and the error code in D0 is stored for debugging.
;
;_______________________________________________________________________
DiskCtlErr MOVEQ #ControlErr,D0
DiskDone TST.W D0 ; error? <06Sep85>
BEQ.S @1 ; br if not <06Sep85>
MOVE.W D0,DskErr ; save last error for debugging
@1 MOVE.L SonyVars,A1 ; get pointer to locals
CLR.B Active(A1) ; clear driver active indication
MOVE.L DiskUnitPtr(A1),A1 ; and pointer to disk DCE
MOVE.L JIODone,-(SP) ; use IODone vector
RTS ;
;_______________________________________________________________________
;
; Routine: DiskControl
; Arguments:
; A0 (input) -- pointer to control call parameter block:
; CSCode(A0) =
; 1 for KillIO
; 5 for Verify
; 6 for Format
; 7 for Eject
; 8 for setting tag buffer
; 9 for track cache install/remove/enable/disable
;
;
; Opcode 1 KillIO (not supported, returns -1)
; Opcode 5 Verify the drive specified by ioRefNum
; Opcode 6 Format drive (ioRefNum). CSParam = 0, except
; CSParam = 1 for 400K disks.
; Opcode 7 Eject the diskette currently in the specified drive.
; IODone is jumped to when the eject has been completed.
; The drive is immediately powered down.
; (26) = [$0007]
; Opcode 8 Set the buffer to store file tags.
; (26) = pointer to tag buffer or 0 to stop saving tags.
; Opcode 9 Cache control is used to control the track cache.
; (26) = [$0009]
; (28) = non-zero to enable, zero to disable
; (29)= $00 for neither, $01 to install, $FF to remove
; Opcode 21 Returns a pointer to an icon for the PHYSICAL drive.
; Opcode 22 Returns a pointer to an icon for the MEDIA.
; Opcode 23 Drive info control; returns a 32 bit int describing the
; drive. See SonyIcon.a.
; To Do:
; - report errors for immediate calls other than KillIO??
;_______________________________________________________________________
;
;The dispatch table contains WORD offsets from the table itself to the
;various routines; this allows 16 bit offsets instead of 32 bit addresses.
;
CtlTbl
; (Code) (offset)
dc.w KillCode, ctlKillIO-CtlTbl ; <C123/21aug86>
DC.W VerifyCC, ctlSonyVer-CtlTbl ; <C123/21aug86>
DC.W FormatCC, ctlSonyFmt-CtlTbl ; <C123/21aug86>
DC.W EjectCode, CtlSonyEjc-CtlTbl ; <C123/21aug86>
dc.w TagBufCC, ctlTagBuf-CtlTbl ; <C123/21aug86>
dc.w TCacheCC, ctlTrkCache-CtlTbl ; <C123/21aug86>
DC.W IconCC, ctlPhysIcon-CtlTbl ; <C123/18sep86>
DC.W IconLogCC, ctlLogIcon-CtlTbl ; <C123/18sep86>
dc.w infoCC, ctlDrvInfo-CtlTbl ; <C123/29aug86>
DC.W FmtCopyCC, CtlFmtCopy-CtlTbl ; <1.8>
DC.W GetRawDataCC,CtlRawTrackDump-CtlTbl ; <SM10><HY>
DC.W RetriesCC, CtlRetries-CtlTbl ; <H6><SM7>
TBLLEN equ 4 ; bytes per table entry ; <C123/25aug86>
dc.w 0 ; <C123/21aug86>
;
;Dispatch off the Control Opcode. A0 points to the ParamBlk from the caller.
;We precheck the drive number passed; D0 contains an error code if the
;drive does not exist. Some calls do not need a drive number passed, and can
;ignore the error.
;
; A0 ParamBlk from the caller
; A1 SonyVars
; D1 Drive locals offset
; D0 Error code if no such drive else 0
;
DiskControl MOVE.L JControl,-(SP)
RTS
jtControl bsr CkDrvNum ;check drive # validity, <C123/21aug86>
bne.s @1 ;D0= error if not valid <C437/11may87>
tst.b Installed(A1,D1) ;check if drive actually installed <C123/21aug86>
bpl.s @1 ;D0= 0 if Installed <C123/21aug86>
moveq #NoDriveErr,D0 ;else D0= error <C123/21aug86>
@1 lea CtlTbl,A3 ;dispatch table base address, <C123/21aug86>
move.l A3,A4 ;save a copy for later, <C123/21aug86>
@2 move.w (A3)+,D2 ;sample the table, <C437/11may87>
beq.s @5 ; error exit if end of table, <C123/21aug86>
cmp.w CSCode(A0),D2 ; <C123/21aug86>
bne.s @4 ;if the right opcode <C123/21aug86>
@3 add.w (A3),A4 ;add table base + routine offset <C123/21aug86>
tst.w D0 ;pretest drive installed indicator <A351/05nov86>
jmp (A4) ;go there <C123/21aug86>
@4 ADDQ.W #TBLLEN-2,A3 ;next table entry ... <C437/11may87>
bra.s @2 ; <C123/21aug86>
@5 moveq #ControlErr,D0 ;none of the above?? <C123/21aug86>
bra DiskDone ; <C123/21aug86>
;
; - - - - - - - - - - - - - - - - - - - ; <C123/21aug86>
;Handle all KillIo calls. Who cares whether the drive exists or not. <C123/21aug86>
; <C123/21aug86>
ctlKillIO MOVEQ #-1,D0 ; we don't support KillIO <C123/21aug86>
bra DiskDone ; <C123/25aug86>
;
; - - - - - - - - - - - - - - - - - - - ; <C123/21aug86>
;Format a Sony; check drive existence first.
;
ctlSonyFmt bne.s DiskDone ;if no drive, exit now <C123/21aug86>
bra ctlFormat ;else go format <C123/21aug86>
;
; - - - - - - - - - - - - - - - - - - - ; <C123/21aug86>
;Verify a Sony; check drive existence first.
;
ctlSonyVer bne.s DiskDone ;if no drive, exit now <C123/21aug86>
bra ctlVerify ;else go verify <C123/21aug86>
;
; - - - - - - - - - - - - - - - - - - - ; <C123/21aug86>
;Set a new tag buffer (CSParam != 0) else revert to the one in the driver. <C123/21aug86>
;No drive number not specified.
;
ctlTagBuf MOVE.L CSParam(A0),TagBufPtr(A1) ; set or clear ptr to separate buffer
moveq #noErr,D0 ;always no error <C123/21aug86>
bra DiskDone ; <C123/21aug86>
;
; - - - - - - - - - - - - - - - - - - - ; <C123/21aug86>
;Control Track Cache. Drive number not specified.
;
ctlTrkCache
ADD #CSParam,A0 ; <25Oct85>
MOVE.B (A0)+,D1 ; get enable flag <25Oct85>
MOVE.B (A0)+,D0 ; get install flag <25Oct85>
BEQ.S ctlTCEnb ; br if neither install/remove <25Oct85>
BPL.S ctlTCInst ; br for install <25Oct85>
BSR.S TCdispose ; get rid of any buffer <25Oct85><C437>
BRA.S ctlTCEnb ; disable the cache <25Oct85>
ctlTCInst TST.L TCBuffer(A1) ; already installed? <25Oct85>
BNE.S ctlTCEnb ; br if so <25Oct85>
MOVE.L #524*MaxMFMSectors,D0 ; allocate a track buffer <SM7>
_NewPtr ,SYS,CLEAR ; <25Oct85>
BNE.S ctlTCEnb ; br if we couldn't get it <25Oct85>
MOVE.L A0,TCBuffer(A1) ; <25Oct85>
CLR.W TCDrive(A1) ; inval drive number to start <25Oct85>
ctlTCEnb TST.L TCBuffer(A1) ; any buffer? <25Oct85>
SNE TCInstalled(A1) ; always disable if not <25Oct85>
BEQ.S @1 ; br if no buffer <25Oct85>
TST.B D1 ; enable/disable? <25Oct85>
SNE TCInstalled(A1) ; turn it on or off <25Oct85>
@1 moveq #noErr,D0 ;always return OK <C123/21aug86>
bra DiskDone ; <C123/21aug86>
TCdispose CLR.L -(SP) ; assume no space freed <A351/05nov86>
MOVE.L TCBuffer(A1),D0 ; get buffer ptr <A351/05nov86>
BEQ.S @1 ; br if none <A351/05nov86>
MOVE.L D0,A0 ; <A351/05nov86>
_GetPtrSize ; <A351/05nov86>
MOVE.L D0,(SP) ; size we free <A351/05nov86>
_DisposPtr ; get rid of it <A351/05nov86>
CLR.L TCBuffer(A1) ; no more buffer <A351/05nov86>
CLR.B TCInstalled(A1) ; no more installed <A351/05nov86>
@1 MOVE.L (SP)+,D0 ; space freed <A351/05nov86>
RTS ; <A351/05nov86>
;
; - - - - - - - - - - - - - - - - - - - -
;Eject a Sony disk. Error if the drive does not exist.
;
ctlSonyEjc bne.s DiskDone ; exit if no drive <C123/21aug86>
IF hasPwrControls THEN ; <SM6>
TestFor hwCbPwrMgr
BEQ.S @pmgrdone
BSR TurnIWMon ; Turn IWM on with pmgr call <C907><C913>
@pmgrdone
ENDIF ; <SM6>
TST.B DiskInPlace(A1,D1) ; Has a disk been seen in drive? <C437/14oct87><1.1/07mar88>
BLE.S @02 ;-> no, skip seek <C437/22feb88><1.1/07mar88>
BSR RWPowerUp ;Make sure the drive's powered up <C437/14oct87>
MOVEQ #40,D6 ;Seek to track 40 to get away from MDB's, etc. <6>
BSR Seek ;Peripherals wanted 79 before but now changed their minds!
BGT.S @02 ;(seek was successful) <C437/14oct87>
BEQ.S @01 ;(recal'd) <C437/14oct87>
BSR Recal ;Seek failed: recal first <C437/14oct87>
BMI.S @02 ; <C437/14oct87>
@01 MOVEQ #40,D6 ;Try seeking again <C437/14oct87> <6>
BSR Seek ; <C437/14oct87>
@02 BSR InvalTrkCache ; invalidate track cache buffer <24Oct85>
MOVEQ #0,D0 ; immediate power off
BSR PowerDown ; make sure power is off
BSR DiskSelect ; but leave interface enabled
MOVEQ #DIPAdr,D0 ; See if disk is in drive <1.1/07mar88>
BSR AdrAndSense ; check DIP at the drive, <1.1/07mar88>
BPL.S @03 ; eject it if there is a diskette <1.1/09mar88>
MOVEQ #0,D0 ; immediate power off <1.1/09mar88>
BSR PowerDown ; if no disk, turn off power now <1.1/09mar88>
BRA.S CtlEjtOK ; exit (silently) if none <1.1/09mar88>
@03 ; <1.1/09mar88>
MOVE #2000, D0 ; and wait 200 msec
BSR WakeUp
MOVEQ #EjectHAdr, D0 ; addr eject
BSR AdrDisk ;
TST.B mfmMode(A1) ;Are we in MFM mode? <C437/19mar87>
BPL.S @00 ; <C437/19mar87>
MOVE.B #$FF,wPhase(A0) ;Yes, set LSTRB high the SWIM way <C437/19mar87>
if NonSerializedIO then
nop ; force write to complete <SM5>
endif
BRA.S @1 ; <C437/19mar87>
@00 ; <C437/19mar87>
TST.B Ph3H(A0) ; set LSTRB high
@1 TST.B NewIntf(A1,D1) ; set LSTRB low if new drive
BMI.S NewDrvEject
;
;Eject old style drive.
;
MOVE.W EjectTime(A1), D0 ; wait >.75 sec
BSR WakeUp ;
TST.B mfmMode(A1) ;Are we in MFM mode? <C437/19mar87>
BPL.S @10 ; <C437/19mar87>
MOVE.B #$F7,wPhase(A0) ;Yes, set LSTRB low the SWIM way <C437/19mar87>
if NonSerializedIO then
nop ; force write to complete <SM5>
endif
BRA.S CtlEjtOK ; <C437/19mar87>
@10 ; <C437/19mar87>
TST.B Ph3L(A0) ; set LSTRB low
bra.s ctlEjtOK ; done <C123/21aug86>
;
;Eject new style drive.
;
NewDrvEject ; <25Oct85>
TST.B mfmMode(A1) ;Are we in MFM mode? <C437/19mar87>
BPL.S @00 ; <C437/19mar87>
MOVE.B #$F7,wPhase(A0) ;Yes, set LSTRB low the SWIM way <C437/19mar87>
if NonSerializedIO then
nop ; force write to complete <SM5>
endif
BRA.S @0 ; <C437/19mar87>
@00 ; <C437/19mar87>
TST.B Ph3L(A0) ; 1us < assert LSTRB < 300ms <25Oct85>
@0 MOVEQ #30,D3 ; loop counter 3.0 sec max <25Oct85><4>
@1 MOVE.W #1000, D0 ; wait 100 msec <25Oct85>
BSR WakeUp ; <25Oct85>
MOVEQ #DIPAdr,D0 ; new drive needs /enb asserted until<25Oct85>
BSR AdrAndSense ; 150usec after /cstin goes away. <25Oct85>
DBMI D3,@1 ; fall through if no disk in place <25Oct85>
MOVEQ #10,D0 ; wait 1ms <25Oct85>
BSR WakeUp ; <25Oct85>
CtlEjtOK MOVE.B EjectWait(A1), DiskInPlace(A1,D1) ; set to DIP wait <29Oct85>
moveq #noErr,D0 ;no error <C123/21aug86>
BRA DiskDone
eject ; <A351/05nov86>
;
;_______________________________________________________________________
;
; Routine: DiskStatus
; Arguments: A0 (input) -- pointer to status call parameter block:
; CSCode = 6 for list of possible disk formats <C437/01may87>
; CSParam: <C437/01may87>
; (0) = number of entries requested (input) and <C437/01may87>
; number of entries returned (output) <C437/01may87>
; (2) = pointer to location to stuff format info <C437/01may87>
; CSCode = 8 for drive status
; CSParam:
; (0) current track location
; (2) bit7=1=write-protected
; (3) $FC-$FF= just ejected, 0=no DIP,1=DIP, 2=clamped
; (4) 0=don't know, 1=inst., $FF=not inst.
; (5) $FF for 2-sided drive, $00 for 1-sided
; (6) drive queue element
; (18) $FF for 2-sided format current diskette
; (19) $FF for new interface drive
; (20) soft error count (word)
; CSCode = 10 for extended status (includes MFM info) <C437/01may87>
; CSParam: <C437/01may87>
; (0) drive type: $FF=SuperDrive (MFM/GCR), $00=400K/800K GCR <C437/01may87>
; (1) disk format: $FF=MFM, $00=GCR (only valid when installed) <C437/01may87>
; (2) MFM format: $FF=1440K, $00=720K <C437/01may87>
; (3) disk controller: $FF=SWIM, $00=IWM <C437/01may87>
;
; Function: The status call returns current status for the drive requested.
;_______________________________________________________________________
;
;The dispatch table contains WORD offsets from the table itself to the
;various routines; this allows 16 bit offsets instead of 32 bit addresses.
;
; (Code) (offset)
StatusTbl DC.W FmtLstCode, PassportSts-StatusTbl ;<C437/01may87>
DC.W DrvStsCode, DriveStatus-StatusTbl ;<C437/01may87>
DC.W MFMStsCode, MFMStatus-StatusTbl ;<C437/01may87>
DC.W DupVerSts, DupVersion-StatusTbl ;<2.1>
DC.W FmtByteSts, GetFmtByte-StatusTbl ;<1.8>
DC.W SpdChkSts, StsSpeedChk-StatusTbl ; <H7><SM7>
DC.W 0 ;<C437/01may87>
DiskStatus MOVEQ #StatusErr,D0 ;Assume unsupported status call <C437/01may87>
LEA StatusTbl,A3 ;Dispatch table base address <C437/01may87>
MOVEA.L A3,A4 ;Save a copy for later <C437/01may87>
BRA.S @2
@1 ADDQ.W #2,A3 ;Next table entry <C437/01may87>
@2 MOVE.W (A3)+,D2 ;Get the entry's opcode <C437/01may87>
BEQ.S @3 ;-> error: end of table <C437/01may87>
CMP.W CSCode(A0),D2 ;Is this the right opcode? <C437/01may87>
BNE.S @1 ;-> nope, try the next one <C437/01may87>
BSR CkDrvNum ;Check for valid drive number <C437/01may87>
BNE.S @3 ;-> it wasn't so exit with an error <C437/18sep87>
MOVEQ #NoDriveErr,D0 ;Set up the error code in case a <C437/18sep87>
TST.B Installed(A1,D1) ; routine status cares and pre-test <C437/18sep87>
LEA CSParam(A0),A0 ;Point to parameters <C437/01may87>
ADDA.W (A3),A4 ;Add table base + routine offset <C437/01may87>
JSR (A4) ;Do it <C437/01may87>
@3 BRA DiskDone ; <C437/01may87>
; - - - - - - - - - - - - - - - - - - - ; <C437/01may87>
DriveStatus MOVEQ #11,D0 ; return all drive vars except speeds
ADD.W D1,A1 ; (11 words)
@1 MOVE.W (A1)+,(A0)+ ; move it in a word at a time
SUBQ.W #1,D0
BGT.S @1 ; leave D0=0
RTS
; - - - - - - - - - - - - - - - - - - - ; <C437/01may87>
PassportSts BLE.S @0 ;-> drive not installed: error! <C437/26feb88>
MOVEQ #offLinErr,D0 ;assume no disk-in-place <C437/26feb88>
CMPI.B #2,DiskInPlace(A1,D1) ;Is the disk clamped? <C437/26oct87>
BLT.S @0 ;-> no, this info isn't valid <C437/01mar88>
MOVEQ #paramErr,D0 ; <C437/26feb88>
MOVE.W (A0),D2 ;Get the number of entries requested<C437/01may87>
@0 BLE.S @6 ;-> it's unreasonable, so error <C437/26feb88>
LEA diskFmtTbl,A2 ; <C437/20aug87>
MOVEQ #1,D3 ;Assume single-sided drive <C437/20aug87>
MOVEQ #0,D0 ;(0=400K) <C437/20aug87>
TST.B sides(A1,D1) ;Is it? <C437/20aug87>
BPL.S @1 ;-> yep <C437/20aug87>
MOVE.B twoSideFmt(A1,D1),D0;How many sides does it actually <C437/20aug87>
NEG.B D0 ; have? 0=1-sided, 1=2-sided <C437/20aug87>
MOVEQ #numSDFmts-1,D3 ;Assume a standard 2-sided drive <C437/20aug87><2.1>
TST.B mfmDrive(A1,D1) ;Is it? <C437/20aug87>
BPL.S @01 ; <C437/20aug87>
MOVEQ #numSDFmts,D3 ;No, it's a SuperDrive <C437/20aug87>
TST.B mfmDisk(A1,D1) ;Is it MFM? <C437/03sep87>
BPL.S @01 ; <C437/03sep87>
MOVEQ #numSDFmts-1,D0 ;Yes, it could be 720K <C437/03sep87>
TST.B twoMegFmt(A1,D1) ;Is this a double-density disk? <C437/20aug87>
BPL.S @01 ; <C437/20aug87>
LEA diskFmtTbl+8*numSDFmts,A2 ;Yes, it must be 1440K <C437/20aug87>
MOVEQ #0,D0 ; <C437/20aug87>
MOVEQ #numDDFmts,D3 ; <C437/20aug87>
@01 ; <C437/20aug87>
@1 CMP.W D3,D2 ;Does user want more than we've got?<C437/01may87>
BLE.S @2 ; <C437/01may87>
MOVE.W D3,D2 ;Yep, so tell 'em how many there are<C437/01may87>
@2 MOVE.W D2,(A0)+ ;and stuff it so the user knows too <C437/01may87>
SUBQ.W #1,D2 ;Adjust for the DBRA to follow <C437/01may87>
MOVE.W D2,D3 ;Loop value for current format <C437/20aug87>
SUB.W D0,D3 ;Calculate index to current format <C437/20aug87>
; (relative to starting D3) <C437/20aug87>
MOVEA.L (A0),A0 ;Get the user's format table address<C437/01may87>
@3 MOVE.L (A2)+,(A0)+ ;and fill in the disk size <C437/01may87>
MOVE.L (A2)+,D0 ;Get the characteristics <C437/01may87>
CMP.W D2,D3 ;Is this the current format? <C437/01may87>
BNE.S @4 ; <C437/01may87>
BSET #30,D0 ;Yes, mark it as such <C437/01may87>
@4 MOVE.L D0,(A0)+ ;and copy the characteristics <C437/01may87>
DBRA D2,@3 ; <C437/01may87>
@5 MOVEQ #0,D0 ; <C437/20aug87>
@6 RTS ; <C437/20aug87>
; The information for each possible disk format is an 8-byte record: <C437/01may87>
; Byte 0-3: disk capacity in blocks <C437/01may87>
; (is [#tracks][#heads][#sectors][#bytes/sector]) <C437/01may87>
; 4: bit 7=1: number of tracks, sides, sectors is valid <C437/01may87>
; 6=1: current disk has this format <C437/01may87>
; 5=0: reserved for future expansion, should be zero <C437/01may87>
; 4=0: single density, =1: double density <C437/01may87>
; 0-3: number of heads (or zero if don't care) <C437/01may87>
; 5: number of sectors (or zero if don't care) <C437/01may87>
; 6-7: number of tracks (or zero if don't care) <C437/01may87>
diskFmtTbl DC.L 2*400 ;400K GCR <C437/01may87>
DC.B (%1000<<4)+1 ; THS valid, SD, 1 head <C437/01may87>
DC.B 10 ; 10 sectors (average) <C437/18sep87>
DC.W 80 ; 80 tracks <C437/18sep87>
DC.L 2*800 ;800K GCR <C437/01may87>
DC.B (%1000<<4)+2 ; THS valid, SD, 2 heads <C437/01may87>
DC.B 10 ; 10 sectors (average) <C437/18sep87>
DC.W 80 ; 80 tracks <C437/18sep87>
DC.L 2*720 ;720K (1M) MFM <C437/01may87>
DC.B (%1000<<4)+2 ; THS valid, SD, 2 heads <C437/01may87>
DC.B 9 ; 9 sectors <C437/18sep87>
DC.W 80 ; 80 tracks <C437/18sep87>
DC.L 2*1440 ;1440K (2M) MFM <C437/01may87>
DC.B (%1001<<4)+2 ; THS valid, DD, 2 heads <C437/20aug87>
DC.B 18 ; 18 sectors <C437/18sep87>
DC.W 80 ; 80 tracks <C437/18sep87>
; - - - - - - - - - - - - - - - - - - - ; <C437/01may87>
;Return MFM related drive/disk/FDC info ; <C437/01may87>
MFMStatus MOVE.L mfmDrive(A1,D1),D0 ;Get mfmDrive, mfmDisk, twoMegFmt <C437/01may87>
MOVE.B isSWIM(A1),D0 ;Stuff the FDC type into the lsb <C437/01may87>
MOVE.L D0,(A0) ;Disk size in bytes <C437/01may87>
MOVEQ #0,D0 ;Always return no error <C437/01may87>
RTS ; <C437/01may87>
; Set up A1/D1 to point to SonyVars and the drive locals, and error check the
;drive number; returns an NSDrvErr if no such drive. (BNE error)
;
CkDrvNum
MOVEA.L SonyVars,A1 ; get pointer to locals
ST Active(A1) ; set active true to exclude VBL task
MOVE.W IOVDrvNum(A0),D0
BEQ.S @1 ; drive number must be in 1..maxDrvNum
CMPI.W #maxDrvNum,D0 ;
BHI.S @1 ;(changed BGT to BHI: what if someone <C437/18sep87>
; uses a negative drive number?) <C437/18sep87>
MOVE.W Drive(A1),LastDrive(A1) ; save the former drive <25Oct85>
MOVE.W D0,Drive(A1) ; drive in question
MOVEQ #noDriveErr,D0 ; assume the chip isn't there <H15><SM7>
TST.B isSWIM(A1) ; see if the IWM/SWIM/... is connected <H15><SM7>
BGT.S @2 ; -> it isn't, so return to caller <H15><SM7>
BSR GetDrv1 ; get (A1,D1) to point to drive vars
MOVEQ #0,D0
RTS
@1 MOVEQ #NSDrvErr,D0 ; bad drive number
@2 RTS ; <SM7>
IF hasPwrControls THEN ; <SM7>
;<3B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
; Routine: TurnIWMoff/TurnIWMon
;
; Input: A1 - SonyVars
;
; Destroys: None
;
; Called by: CommonTurnIWMon, CommonTurnIWMoff
;
; Function: Turn the clocks and power on/off to the IWM
;<3B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
TurnIWMoff MOVEM.L D0/A0,-(SP) ; Save A0 and D0 <C907><C913>
MOVEQ.L #(iwmOn**$7F),D0 ; setup to check IWM on bit <2.1>
AND.B ChipState(A1),D0 ; see if IWM clock is enabled <2.1>
BEQ.S TurnExit ; Don't do anything if already off
CLR.B ChipState(A1) ; remember that the IWM is off <2.1>
MOVEQ.L #IWMoff,D0 ; Turning off IWM <2.1>
BRA.S TurnIWM
TurnIWMon MOVEM.L D0/A0,-(SP)
MOVEQ.L #(iwmOn**$7F),D0 ; setup to check IWM on bit <2.1>
AND.B ChipState(A1),D0 ; see if IWM clock is enabled <2.1>
BNE.S TurnExit ; Don't do anything if already on
MOVE.W #IWMon,D0 ; Turning on IWM
MOVE.B D0,ChipState(A1) ; remember that the IWM is on <2.1>
TurnIWM MOVE.B D0,-(SP) ; Turn off unused devices <2.1>
MOVE.L SP,-(SP) ; Load pointer to receive buffer
MOVE.L (SP),-(SP) ; Load pointer to xmit buffer
MOVE.L #(PowerCntl<<16)+1,-(SP) ; PMGR command, 1 byte of xmit data <2.1>
MOVE.L SP,A0 ; A0 gets pointer to parameter block
_PmgrOp
ADDA.W #14,SP ; Remove stack frame <2.1>
TurnExit MOVEM.L (SP)+,D0/A0
RTS
UpdateChipState ; get PMGR chip pwr/clk enables <2.1>
MOVEM.L D0/A0,-(SP) ; save registers <2.1>
PEA ChipState(A1) ; Load pointer to receive buffer <2.1>
MOVE.L (SP),-(SP) ; Load pointer to xmit buffer <2.1>
MOVE.L #(powerRead<<16)+0,-(SP) ; PMGR command, 0 bytes of xmit data <2.1>
MOVE.L SP,A0 ; A0 gets pointer to parameter block <2.1>
_PmgrOp ; <2.1>
ADDA.W #12,SP ; Remove stack frame <2.1>
MOVEM.L (SP)+,D0/A0 ; Restore registers <2.1>
RTS ; <2.1>
HandleSleep ; <11> HJR<SM7>
@SleepQRegs REG D1-D7/A0-A6 ; <SM7>
MOVEM.L @SleepQRegs,-(SP) ; Save regs <SM7>
MOVEA.L SonyVars,A1 ; Get a pointer to sonyvars <SM7>
CMPI.W #SleepWakeUp,D0 ; are we waking up?
beq.s @WakeUp ; if so, go deal with it. <1.7>
ST active(A1) ; make sure VBLs are excluded when we wake up <H22><SM7>
TST.B isSWIM(A1) ; is a disk controller connected? <H24><SM7>
BPL.S @JustSleep ; -> no, don't bother waiting <H24><SM7>
MOVEQ #90,D1 ; limit the wait to 1.5 secs <v2.5>
ADD.L Ticks,D1 ; limit the wait time <v2.5>
@Sleep ; else, a sleep request or demand <1.7>
CMP.L Ticks,D1
BLS.S @JustSleep ; <H24><SM7>
MOVEQ.L #(iwmOn**$7F),D0 ; setup to check IWM on bit
AND.B ChipState(A1),D0 ; if IWM off, OK to sleep
BNE.S @Sleep ; wait for eject/power down to finish
@JustSleep MOVEQ #0,D0 ; make sure we say it's OK to sleep <H24><SM7>
BRA.S @exit ; all done <SM7>
@WakeUp MOVE SR,-(SP) ; save the SR <H24>
ORI #$0700,SR ; and disable interrupts <H24>
MOVEQ.L #(iwmOn**$7F),D1 ; setup to check IWM on bit
AND.B ChipState(A1),D1 ; save SWIM powered state
CLR.B ChipState(A1) ; and clear it to force a power up <H23>
BSR.S TurnIWMon ; power up the chip
MOVEA.L IWM,A0 ; get IWM base address
move.b #$F8,wZeroes(a0) ; switch to IWM mode
if NonSerializedIO then
nop ; force write to complete <SM5>
endif
tst.b Q7L(a0) ; and get out of write mode
MOVE.B #1,isSWIM(A1) ; mark as no chip installed <H15>
BSR TestForChip ; is a disk controller connected? <H15>
BNE.S @SetIWMoff ; -> nope, just exit <H15>
CLR.B isSWIM(A1) ; assume it's an IWM <H15>
BSR Check4SWIM ; find out what kind of chip it is <H15>
cmp.b #-2,isSWIM(a1) ; do we have a SWIM2? <H2><SM7>
bne.s @noSWIM2 ; if not, do it the old way <SM7>
SEQ mfmMode(A1) ; SWIM2 is always in ISM mode <H4>
bra.s @1 ; jump over the SWIM1 stuff <SM7><SM7>
@noSWIM2 CLR.B mfmMode(A1) ; IWM and SWIM power up in IWM mode <H4><SM7>
@1 MOVE.B D1,-(SP) ; save the state of the SWIM power <H22><SM7>
BSR SetChipMode ; set mode for drive
TST.B (SP)+ ; see if SWIM was on at sleep time <H22>
BEQ.S @SetIWMoff ; if not, turn it off now, and exit
@WakeupDone CLR.B active(A1) ; VBLs can run now that everything's initialized<H22>
MOVE (SP)+,SR ; re-enable interrupts <H24>
@exit MOVEM.L (SP)+,@SleepQRegs ; restore registers
RTS ; all done
@SetIWMoff BSR.S TurnIWMoff ; turn the IWM off
BRA.S @WakeupDone ; time to go
ENDIF ; <SM7>
;<3B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <H4><SM7> begin
;
; Routine: TestForChip
;
; Inputs: none
;
; Outputs: D0 -- result code
; CCR-- BNE if no chip is connected
;
; Function: Checks to see if the disk controller chip (that's IWM, SWIM, or
; SWIM2 to the rest of us) is actually connected. Boxes like DB-Lite
; have a SWIM on an external board that may or may not be plugged in
; when driver calls are made.
;<3B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
TestForChip MOVEM.L A0-A1/D2,-(SP) ; <H8>
MOVEQ #noErr,D0 ; asssume no error return <H42>
MOVEA.L IWM,A0 ; get the chip's base address <H42>
MOVEA.L ROMBASE,A1 ; get ROM base address for bus clearing <H42>
; <H42> We used to check first for a bus error, but that is not necessary, since MSC chips
; do not bus error on SWIM accesses when there is no SWIM, so we go right to the meat of
; the problem instead.
MOVE.B #$F8,wZeroes(A0) ; try to switch to the IWM register set <H5>
MOVEQ #$F5-256,D2 ; <H5>
MOVE.B D2,wPhase(A0) ; write a value to the phase register <H5>
TST.B (A1) ; read first location of ROM to clear bus lines <H8>
NOP ; make sure the previous instruction does not get cached <H42>
CMP.B rPhase(A0),D2 ; did we get back what was originally written? <H5>
BEQ.S @Done ; -> yes, we've got a SWIM2 <H5>
; At this point, we know we don't have a SWIM2 connected. We either have an IWM/SWIM or no chip...
TST.B q7L(A0) ; select "Read Handshake" <H5>
TST.B q6L(A0) ; <H5>
MOVE.B D0,q7H(A0) ; <H5>
MOVEQ #%00111111,D2 ; mask to just the low 6 bits <H5>
AND.B q6L(A0),D2 ; and read the register <H5>
TST.B q7L(A0) ; back into a read mode <H5>
CMPI.B #%00111111,D2 ; did we get what we expected? <H5>
BEQ.S @Done ; -> yes <H5>
MOVEQ #noDriveErr,D0 ; the chip isn't there <H5>
@Done MOVEM.L (SP)+,A0-A1/D2 ; <H8>
RTS
;_______________________________________________________________________ <H13>
;
; Routine: StsSpeedChk
;
; Inputs: A0 -- pointer to user's csParams
; csParam+ 0: Track Number (word)
; A1 -- pointer to SonyVars
; D1 -- offset to drive's private variables
;
; Outputs: D0 -- result code (0 if no errors)
; csParam+ 2: milliseconds per revolution (word)
;
; Function: measures the time in milliseconds per revolution of the disk
; at the specified track.
;_______________________________________________________________________
StsSpeedChk
BLE DiskDone ; -> no drive installed so exit with error
IF hasPwrControls THEN ; <SM7>
TestFor hwCbPwrMgr ; <SM7>
BEQ.S @pmgrdone ; <SM7>
BSR TurnIWMon ; Turn IWM on with pmgr call <SM7>
@pmgrdone ; <SM7>
ENDIF ; <SM7>
MOVE.W (A0),SideTrack(A1) ; load track number
MOVE.L A0,-(SP) ; save pointer to csParams
TST.B isSWIM(A1) ; Is a SWIM installed?
BPL.S @0 ; -> no, skip
BSR SetChipMode ; Set up the mode for MFM or GCR
BNE SpeedChkExit ; -> couldn't initialize the chip
@0
BSR DiskSelect ; Re-select the interface
BSR FVPowerUp ; start up the drive (synchronously)
BSR GetDrv1
BSR SpdSeek ; seek to desired track
BNE.S SpeedChkExit ; exit on errors
BSR GetDrv1
TST.B mfmDisk(A1,D1) ; Are we in MFM mode?
BPL.S @1 ; -> no
BSR mFindSpeed ; Check speed MFM style
BRA.S @2
@1
BSR gFindSpeed ; Check speed GCR style
@2 BMI.S SpeedChkExit ; exit on errors
MOVE.L (SP),A0 ; get csParam pointer
MOVE.W D0,2(A0) ; put speed result into csParams+2
; if D0 is positive, it is speed in milliseconds
MOVEQ #0,D0 ; successful exit
SpeedChkExit
ADDQ #4,SP ; toss the saved register
BRA DskRWOff ; Share SonyRWT exit routine
; (sets up the power down time)
;_______________________________________________________________________ <Z18> thru next <Z18>
;
; Routine: ReGenSoundInt
;
; Desc: Since reading vBufB (like the below routines) causes
; interrupts to cleared, this re-generates those sound
; interrupts. This routine stolen from
;
; {Regatta}Toolbox:SoundMgr:SoundMgrPatch.a
;
; Apologies to those reading this since the constants
; and constant offsets used here were not made symbolic
; in the original code.
;
;_______________________________________________________________________
interruptControlA EQU $F09 ; interrupt mask registers for Batman
interruptControlB EQU $F29
ReGenSoundInt
btst.b #ifCB1,vIFR(a1) ; check if we still think there's an interrupt
bne.s @rts ; yes, we still have an interrupt - exit
movea.l ASCBase,a1 ; point to Batman
cmpa.l #-1,a1 ; check if it's been set up yet
beq.s @rts ; exit if not
move.w sr,-(sp) ; preserve the status register
ori.w #$0700,sr ; mask interrupts
tst.b interruptControlA(a1) ; channel A interrupt enabled?
bne.s @checkB ; BRIF not enabled
move.b #1,interruptControlA(a1); disable chnl A interrupts
nop ; give Batman time to process the disable
clr.b interruptControlA(a1) ; clear the interrupt mask to re-generate
@checkB
tst.b interruptControlB(a1) ; channel B interrupt enabled?
bne.s @Done ; interrupt not enabled - done
; To re-generate Batman interrupts, first disable interrupts on both channels,
; then re-enable them.
@reGen
move.b #1,interruptControlB(a1); disable chnl B interrupts
nop ; give Batman time to process the disable
clr.b interruptControlB(a1) ; clear the interrupt mask to re-generate
@Done
move.w (sp)+,sr
@rts rts
;_______________________________________________________________________ <H13>
;
; Routine: gFindSpeed
;
; inputs: none.
;
; outputs: D0 -- if positive, number of milliseconds per revolution
; if negative, error code
;
; 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.
;_______________________________________________________________________
gFindSpeed
MOVE SR,-(SP)
MOVEM.L D1-D7/A0-A6,-(SP)
MOVEQ #4,D0 ; init PollStack 4 bytes down
BSR SetUpPoll ; and disable interrupts . . .
MOVEQ #TachAdr,D0
BSR AdrDisk ; address tach signal
MOVEA.L IWM,A0 ;
TST.B Q6H(A0) ; get into sense mode
; D0 = A0 = DBase ptr
; D1 = -1 (timer load value) A1 = Q7L ptr
; D2 = pulse counter A2 = VIA ptr
; D3 = 5 (VIA timer2 flag reg bit) A3 = VIA flag reg ptr
; D4 =
MOVEQ #-1,D1 ; timer load value
MOVEQ #5,D3 ; VIA timer 2 flag bit in flag reg
MOVE.L VIA,A2
LEA VIFR(A2),A3 ; points to VIA flag reg
CMP.B #-2,isSWIM(A1) ; is this a SWIM2?
BEQ.S @0 ; -> yes
LEA Q7L(A0),A4 ; this is a IWM/SWIM, use Q7L
BRA.S @1 ;
@0 LEA rHandshake(A0),A4 ; for SWIM2 use handshake register
@1
; first make sure we can see some pulses
BSR.W StrtTimer ; now start the timer
; wait for an edge
CMP.B #-2,isSWIM(A1) ; is this a SWIM2?
BEQ.S @2 ; -> yes
BSR.W GetNxtEdge ; use the IWM/SWIM version
BRA.S @3 ;
@2 MOVEQ #0,D4 ; use only one timer pass
BSR.W GetNxtEdge2 ; use the SWIM2 version
@3 BNE.S gFSExit ; exit on error
BRA.S Wait15Pulses ; then wait for 15 more
gFSExit TST.B Q6L(A0) ; back to read mode
BSR EmptyPD ; get rid of polled data from SCC
moveq #1,D1 ; set T2 to go off ASAP,
move.l VIA,A2 ; TimeMgr gets massively bummed
bsr.w StrtTimer ; when it misses interrupts
MOVEM.L (SP)+,D1-D7/A0-A6
MOVE (SP)+,SR
TST.L D0
RTS
Wait15Pulses
BSR.W StrtTimer
MOVEQ #14,D2 ; set up counter for 15 pulses
Wait1Pulse
CMP.B #-2,isSWIM(A1) ; is this a SWIM2?
BEQ.S @0 ; -> yes
BSR.W GetNxtEdge ; use the IWM/SWIM version
BRA.S @00 ;
@0 MOVEQ #0,D4 ; use only one timer pass
BSR.W GetNxtEdge2 ; use the SWIM2 version
@00 BNE.S gFSExit ; branch if too slow
DBRA D2,Wait1Pulse
MOVEQ #0,D2 ; clear D2
MOVE.B VT2CH(A2),D2 ; get timer high byte
MOVE.B VT2C(A2),D1 ; and timer low byte
CMP.B VT2CH(A2),D2 ; did high byte change?
BEQ.S @1 ; branch if not
MOVEQ #0,D1 ; if so, low byte should be 00
; (since value decrements!)
@1 BTST D3,(A3) ; timer flag bit set?
BNE.S gFSExit ; then exit with error
LSL.W #8,D2 ; get into correct order
OR.B D1,D2
NOT.W D2 ; and convert to positive count
ASL.L #2,D2 ; multiply by four to get ticks per full revolution
DIVU.L #nTicks,D2 ; then convert to milliseconds
MOVEQ #0,D0 ; clear high word
MOVE.W D2,D0 ; return speed
BRA.S gFSExit
;_______________________________________________________________________ <H13>
;
; Routine: mFindSpeed
;
; inputs: none.
;
; outputs: D0 -- if positive, number of milliseconds per revolution
; if negative, error code
;
; Function: This routine measures the time (in VIA counts) it takes
; for the disk to revolve one time; this test looks for the index
; pulse which occurs one time per rev. VIA timer 2 is used; if
; an index pulse is not seen in 334 msec, this routine
; will time out and take the error exit.
;
; The drive should be powered when this is called.
;_______________________________________________________________________
mFindSpeed
MOVE SR,-(SP)
MOVEM.L D1-D7/A0-A6,-(SP)
MOVEQ #4,D0 ; init PollStack 4 bytes down
BSR SetUpPoll ; and disable interrupts . . .
MOVEQ #TachAdr,D0
BSR AdrDisk ; address tach signal
MOVEA.L IWM,A0 ;
; D0 = A0 = DBase ptr
; D1 = -1 (timer load value) A1 = Q7L ptr
; D2 = pulse counter A2 = VIA ptr
; D3 = 5 (VIA timer2 flag reg bit) A3 = VIA flag reg ptr
; D4 =
MOVEQ #-1,D1 ; timer load value
MOVEQ #5,D3 ; VIA timer 2 flag bit in flag reg
MOVE.L VIA,A2
LEA VIFR(A2),A3 ; points to VIA flag reg
LEA rHandshake(A0),A4 ; for SWIM2 use handshake register
; first make sure we can see some pulses
BSR.S StrtTimer ; start the timer
; wait for an edge
MOVEQ #3,D4 ; wait up to four timer passes
BSR.W GetNxtEdge2 ; use the ISM/SWIM2 version
BEQ.S Wait4Index ; then wait for one more edge
mFSExit BSR EmptyPD ; get rid of polled data from SCC
moveq #1,D1 ; set T2 to go off ASAP,
move.l VIA,A2 ; TimeMgr gets massively bummed
bsr.s StrtTimer ; when it misses interrupts
MOVEM.L (SP)+,D1-D7/A0-A6
MOVE (SP)+,SR
TST.L D0
RTS
Wait4Index
BSR.S StrtTimer
MOVEQ #3,D4 ; wait up to four timer passes
BSR.W GetNxtEdge2 ; use the ISM/SWIM2 version
BNE.S mFSExit ; branch if too slow
MOVEQ #3,D2 ;
SUB.B D4,D2 ; Find out how many timer passes we used
MOVEQ #0,D4 ; initialize D4
BRA.S @01 ; start looping
@00 ADD.L #$FFFF,D4 ; add in FFFF ticks for each complete timer
@01 DBRA D2,@00 ; pass used
MOVEQ #0,D2 ; clear high word of D2
MOVE.B VT2CH(A2),D2 ; get timer high byte
MOVE.B VT2C(A2),D1 ; and timer low byte
CMP.B VT2CH(A2),D2 ; did high byte change?
BEQ.S @1 ; branch if not
MOVEQ #0,D1 ; if so, low byte should be 00
; (since value decrements!)
@1 BTST D3,(A3) ; timer flag bit set?
BNE.S mFSExit ; then exit with error
LSL.W #8,D2 ; get into correct order
OR.B D1,D2
NOT.W D2 ; and convert to positive count
ADD.L D4,D2 ; Add in ticks for previous timer passes
DIVU.L #nTicks,D2 ; then convert to milliseconds
MOVEQ #0,D0 ; clear high word
MOVE.W D2,D0 ; return speed
BRA.S mFSExit
;_______________________________________________________________________ <H13>
; Utility routines for finding disk speed
;_______________________________________________________________________
;
;Set T2 to the value in D1.
;
StrtTimer move.b D1,VT2C(A2) ; write timer low count
ror.w #8,D1 ; MSB in low byte D1
move.b D1,VT2CH(A2) ; write timer high count, load T2,
; clear int flag
ror.w #8,D1 ; LSB in low D1 again
RTS
; wait for a rising edge on the tach feedback
GetNxtEdge MOVE.L (SP)+,DskRtnAdr ; save return address here
WaitForLow _PollSCC ; poll the SCC modem port
TST.B (A4) ; tach feedback is bit 7 (sense)
BMI.S @1 ; br if still high
TST.B (A4) ; tach feedback is bit 7 (sense)
BPL.S WaitForHigh ; br if it is still low
@1 BTST D3,(A3) ; timer flag bit set yet?
BEQ.S WaitForLow
NoPulse MOVEQ #NoDriveErr,D0 ; probably no drive installed
BRA.W DskRtn
WaitForHigh _PollSCC ; poll the SCC modem port
BTST D3,(A3) ; timer flag bit set yet?
BNE.S NoPulse
TST.B (A4) ; tach feedback is bit 7 (sense)
BPL.S WaitForHigh ; br if still low
TST.B (A4) ; tach feedback is bit 7 (sense)
BPL.S WaitForHigh ; br if it was a glitch
MOVEQ #0,D0 ; success
BRA.W DskRtn
; wait for a rising edge on the tach feedback for ISM/SWIM2
GetNxtEdge2 MOVE.L (SP)+,DskRtnAdr ; save return address here
WaitForLow2 _PollSCC ; poll the SCC modem port
BTST #3,(A4) ; tach feedback is bit 3 (sense)
BNE.S @1 ; br if still high
BTST #3,(A4) ; tach feedback is bit 3 (sense)
BEQ.S WaitForHigh2 ; br if it is still low
@1 BTST D3,(A3) ; timer flag bit set yet?
BEQ.S WaitForLow2
TST.B D4 ; how many timer passes are left?
BEQ.S NoPulse2 ; none, exit with error
BSR.S StrtTimer ; restart timer, D1 still valid
SUBQ #1,D4 ; decrement count
BRA.S WaitForLow2 ; go back and keep waiting
NoPulse2 MOVEQ #NoDriveErr,D0 ; probably no drive installed
BRA.W DskRtn
WaitForHigh2 _PollSCC ; poll the SCC modem port
BTST D3,(A3) ; timer flag bit set yet?
BEQ.S @1
TST.B D4 ; how many timer passes are left?
BEQ.S NoPulse2 ; none, exit with error
BSR.S StrtTimer ; restart timer, D1 still valid
SUBQ #1,D4 ; decrement count
@1
BTST #3,(A4) ; tach feedback is bit 3 (sense)
BEQ.S WaitForHigh2 ; br if still low
BTST #3,(A4) ; tach feedback is bit 3 (sense)
BEQ.S WaitForHigh2 ; br if it was a glitch
MOVEQ #0,D0 ; success
BRA.W DskRtn
;<3B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
PollSCC BTST #RxCA,aCtl-aData(A6) ; SCC data available?
BEQ.S @NoSCCData ; -> no, done
SUBQ.W #2,SP ; make space for the byte,
MOVE.L 2(SP),(SP) ; move the return address down to make space,
MOVE.B (A6),4(SP) ; and "push" the SCC byte on the stack
@NoSCCData RTS
;<3B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
;Control retry enabling/disabling. Drive number not specified. <H11>
;
ctlRetries
TST.W CSParam(A0) ; what does the caller want?
BNE.S @0 ;
ST.B DisableRetries(A1) ; disable retries if zero
BRA.S @1 ;
@0 CLR.B DisableRetries(A1) ; else enable retries
@1 moveq #noErr,D0 ;always return OK
bra DiskDone ;
;<3B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <SM7> end