mirror of
https://github.com/elliotnunn/sys7.1-doc-wip.git
synced 2024-10-31 19:05:04 +00:00
1497 lines
61 KiB
Plaintext
1497 lines
61 KiB
Plaintext
;
|
||
; File: Sony.a
|
||
;
|
||
; Contains: Sony Floppy Driver
|
||
;
|
||
; Written by: Larry Kenyon
|
||
;
|
||
; Copyright: © 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…
|
||
; <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 ‘active’ 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’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…
|
||
; 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>
|
||
;———————————————————————————————————————————————————————————————————————————————
|
||
; Routine: TurnIWMoff/TurnIWMon
|
||
;
|
||
; Input: A1 - SonyVars
|
||
;
|
||
; Destroys: None
|
||
;
|
||
; Called by: CommonTurnIWMon, CommonTurnIWMoff
|
||
;
|
||
; Function: Turn the clocks and power on/off to the IWM
|
||
;———————————————————————————————————————————————————————————————————————————————
|
||
|
||
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>
|
||
|
||
;——————————————————————————————————————————————————————————————————————————————— <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.
|
||
;———————————————————————————————————————————————————————————————————————————————
|
||
|
||
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
|
||
|
||
;———————————————————————————————————————————————————————————————————————————————
|
||
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
|
||
|
||
;———————————————————————————————————————————————————————————————————————————————
|
||
;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 ;
|
||
|
||
|
||
;——————————————————————————————————————————————————————————————————————————————— <SM7> end
|
||
|