sys7.1-doc-wip/Drivers/Sony/Sony.a
2019-07-27 22:37:48 +08:00

1497 lines
61 KiB
Plaintext
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

;
; 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 isnt 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