mirror of
https://github.com/elliotnunn/mac-rom.git
synced 2024-12-28 01:29:20 +00:00
4325cdcc78
Resource forks are included only for .rsrc files. These are DeRezzed into their data fork. 'ckid' resources, from the Projector VCS, are not included. The Tools directory, containing mostly junk, is also excluded.
1497 lines
60 KiB
Plaintext
1497 lines
60 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
|
||
|