mirror of
https://github.com/elliotnunn/mac-rom.git
synced 2025-01-04 01:29:22 +00:00
5b0f0cc134
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.
1767 lines
65 KiB
Plaintext
1767 lines
65 KiB
Plaintext
;
|
|
; File: EDiskDrvr.a
|
|
;
|
|
; Contains: Electronic Disk Driver
|
|
;
|
|
; Written by: Gary G. Davidian
|
|
;
|
|
; Copyright: © 1988-1993 by Apple Computer, Inc., all rights reserved.
|
|
;
|
|
; Change History (most recent first):
|
|
;
|
|
; <SM7> 10/28/93 CCH Optimized read path to not disable writes on every call and
|
|
; disabled checksums on PDM.
|
|
; <SM6> 10/14/93 CCH Added write-protection support for PowerPC machines.
|
|
; <SM5> 4/15/93 chp Fix RADAR #1078337. Format csCode would crash given an invalid
|
|
; drive number. An error handler was branching to the wrong label.
|
|
; <SM4> 2/8/93 rab Sync up with Horror. Comments follow.
|
|
; <H6> 9/30/92 BG (for Dave Nelson) Added a patch to fix the problem of the driver
|
|
; not adjusting the usage count correctly if someone calls the
|
|
; driver with an invalid _Control call.
|
|
; <SM3> 8/31/92 PN Fix header
|
|
; <SM2> 8/31/92 PN First time this file is moved over from Horror so that RAMDisk
|
|
; works with Cyclone
|
|
; ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
; SuperMario ROM comments start here.
|
|
; ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
; <H3> 2/5/92 SWC Set bit 15 in the driveInfo for RAM disks so the Finder can have
|
|
; a way to determine that the media is volatile.
|
|
; <H2> 12/12/91 CCH Fixed Read-Verify bug in 24-bit mode.
|
|
; ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
; Pre-HORROR ROM comments begin here.
|
|
; ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
; <7> 6/30/91 CCH Updated icon.
|
|
; <6> 6/13/91 CCH Moved RamDiskSize to EDiskDriveInfo record and modified the way
|
|
; it is initialized.
|
|
; <5> 5/24/91 CCH Turned on write-protection of the EDisk's address space when not
|
|
; being accessed by the driver.
|
|
; <4> 3/19/91 CCH Modified to use seperate ram disk memory area set up by the MMU.
|
|
; <3> 2/25/91 CCH Removed redundant RAM test, changed to a jump vector for
|
|
; _SwapMMUMode, and preserved the result code in the verify
|
|
; routine. Also made modifications to keep RAM disk intact across
|
|
; memory-mode changes (24<->32).
|
|
; <2> 12/20/90 CCH Added changes to support 32-bit addressing.
|
|
; ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
; Pre-TERROR ROM comments begin here.
|
|
; ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
; <3> 5/16/90 JJ Modify to use only 1 byte of Pram.
|
|
; <2> 5/16/90 JJ Restructured to provide RAMDisk on Elsie and Erickson.
|
|
; {2} 2/6/90 GMR Fixed bug in Prime where it didn't update ioNumDone,
|
|
; dCtlPosition properly.
|
|
; {1.8} 8/16/89 BBM version 1.7 broke hcmac build by the addition of flag hasSlim.
|
|
; fixed same.
|
|
; {1.7} 8/16/89 BBM temporary hack to get edisks working on emacs.
|
|
; <1.6> 5/26/89 GMR Saves RAM disk size in new EDisk global in Open code, added new
|
|
; status call to retrieve it.
|
|
; <1.5> 4/25/89 GMR Let d6 accumulate MOD3 test results on each RAM test pass, since
|
|
; the MOD3 test OR's errors into d6. This fixes the format bug in
|
|
; version 1.4.
|
|
; <1.4> 4/11/89 GMR Tests RAM in 16K chunks, for better mouse movement.
|
|
; <1.3> 4/4/89 GMR Added new ICON's. Format now tests RAM in 64K chunks, so the
|
|
; mouse won't freeze on large RAM disks.
|
|
; <1.2> 2/21/89 GGD Added support for immediate calls, and KillIO. Made the Apple
|
|
; look better in SLIM Icon. Added support for new SLIM interface
|
|
; adapter.
|
|
; <1.1> 11/11/88 CCH Fixed Header.
|
|
; <1.0> 11/9/88 CCH Adding to EASE.
|
|
; <1.5> 11/2/88 GGD Added code to post events to drive some sort of user interface
|
|
; for the lack of an eject/locking mechanism (currently, and
|
|
; hopefully permanently, disabled). Added support for internal ROM
|
|
; Disks (untested). Removed drivers need to staticly know its
|
|
; driver refnum, no code needs to change if refnum needs to
|
|
; change. Storage is now only allocated for drives that exist.
|
|
; EDiskHeader format and signature changed. Probably lots of other
|
|
; improvements too.
|
|
; <1.3> 9/1/88 GGD Added official drive icons. Added partial support for ROM disks.
|
|
; Added DriveInfo support. Changed drive queue order and numbering
|
|
; to interface better with the Startup Device CDEV. Optimized a
|
|
; few routines. Deleted code associated with normandy work around.
|
|
; Deleted support for Non-Battery-Backed-Up SLIM EDisks. Added
|
|
; special RAM Disk format code to erase and delete from drive
|
|
; queue.
|
|
; <1.2> 8/5/88 MSH Cleared hardware workaround flag. New normandy necessary to use
|
|
; SLIMs.
|
|
; <1.1> 6/21/88 GGD Changed Internal EDisk size computation and space allocation to
|
|
; be in 64KB blocks ending at MemTop. Changed FormatVerify to
|
|
; check checksums if present, otherwise NoErr. Changed Format to
|
|
; call TestManager to test RAM.
|
|
; <1.0> 4/21/88 MSH New Today
|
|
;
|
|
; To Do:
|
|
;
|
|
|
|
;--------------------------------------------------------
|
|
;
|
|
;_______________________________________________________________________
|
|
;
|
|
; © Apple Computer, Inc. 1988,1989
|
|
;
|
|
; written by Gary G. Davidian 13-Mar-88
|
|
;
|
|
;_______________________________________________________________________
|
|
|
|
BLANKS ON
|
|
PRINT OFF
|
|
LOAD 'StandardEqu.d'
|
|
INCLUDE 'HardwareEqu.a'
|
|
INCLUDE 'MMUEqu.a'
|
|
INCLUDE 'BootEqu.a'
|
|
INCLUDE 'SonyEqu.a'
|
|
PRINT ON
|
|
INCLUDE 'EDiskEqu.a'
|
|
PRINT NOMDIR
|
|
|
|
MACHINE MC68020
|
|
|
|
NewEdiskProt EQU 1
|
|
|
|
_TestManager OPWORD $A06B
|
|
|
|
macro
|
|
assert &boolExpr
|
|
if not(&Eval(&boolExpr)) then
|
|
aerror &concat('Assertion Failed - ',&boolExpr)
|
|
endif
|
|
endm
|
|
title 'EDisk Driver - DRVR Header'
|
|
|
|
; Driver Header for Device Manager
|
|
|
|
EDiskDRVR PROC EXPORT
|
|
with EDiskVars,EDiskDriveInfo,StartGlobals,MMUConfigInfo
|
|
|
|
EDiskDRVRflags SET 0
|
|
EDiskDRVRflags SET EDiskDRVRflags!1<<dReadEnable
|
|
EDiskDRVRflags SET EDiskDRVRflags!1<<dWritEnable
|
|
EDiskDRVRflags SET EDiskDRVRflags!1<<dCtlEnable
|
|
EDiskDRVRflags SET EDiskDRVRflags!1<<dStatEnable
|
|
EDiskDRVRflags SET EDiskDRVRflags!1<<dNeedLock
|
|
|
|
dc.b EDiskDRVRflags,0 ; drvFlags (upper byte)
|
|
dc.w 0 ; drvDelay, no delay
|
|
dc.w 0 ; drvEMask, no event mask
|
|
dc.w 0 ; drvMenu, no menu
|
|
dc.w EDiskOpen-EDiskDRVR ; drvOpen, offset of OPEN routine
|
|
dc.w EDiskPrime-EDiskDRVR ; drvPrime, offset of PRIME routine
|
|
dc.w EDiskControl-EDiskDRVR ; drvCtl, offset of ConTroL routine
|
|
dc.w EDiskStatus-EDiskDRVR ; drvStatus, offset of STATUS routine
|
|
dc.w EDiskClose-EDiskDRVR ; drvClose, offset of CLOSE routine
|
|
|
|
string pascal
|
|
dc.b '.EDisk' ; drvName, including leading length byte
|
|
align 2 ; force back to even boundaries
|
|
|
|
; Decode table for Status Calls
|
|
|
|
StatusDecode
|
|
dc.w statFmtLst-(*+4)
|
|
dc.w fmtLstCode ; Get Format List status call
|
|
|
|
dc.w statDrvSts-(*+4)
|
|
dc.w drvStsCode ; Drive Status call
|
|
|
|
dc.w statDrvSize-(*+4) ; <1.7>
|
|
dc.w drvSizeCode ; Drive Size Status call <1.7>
|
|
|
|
dc.w -1 ; indicate end of status decode table
|
|
dc.w StatusErr ; return StatusErr if unknown csCode
|
|
|
|
; Decode table for Control Calls
|
|
|
|
ControlDecode
|
|
dc.w ctlKillIO-(*+4) ; <1.2>
|
|
dc.w killCode ; KillIO control call (not supported) <1.2>
|
|
|
|
dc.w ctlVerify-(*+4)
|
|
dc.w VerifyCC ; Verify control call
|
|
|
|
dc.w ctlFormat-(*+4)
|
|
dc.w FormatCC ; Format control call
|
|
|
|
dc.w ctlEject-(*+4)
|
|
dc.w EjectCode ; Eject control call
|
|
|
|
dc.w ctlDriveIcon-(*+4)
|
|
dc.w IconCC ; Physical Drive Icon control call
|
|
|
|
dc.w ctlMediaIcon-(*+4)
|
|
dc.w IconLogCC ; Disk Media Icon control call
|
|
|
|
dc.w ctlDriveInfo-(*+4)
|
|
dc.w infoCC ; Drive Info control call
|
|
|
|
dc.w -1 ; indicate end of control decode table
|
|
dc.w ControlErr ; return ControlErr if unknown csCode
|
|
title 'EDisk Driver - Open processing'
|
|
|
|
;_______________________________________________________________________
|
|
;
|
|
; Routine: EDiskOpen
|
|
; Inputs: A0 - pointer to I/O ParamBlock
|
|
; A1 - pointer to Device Control Entry (DCE)
|
|
; Outputs: D0 - Result Code (noErr/openErr)
|
|
; Destroys:
|
|
; Calls: none
|
|
; Called by: Device Manager
|
|
;
|
|
; Function: Driver initialization routine
|
|
;
|
|
; NOTE: EDisks are installed in the following order, Slim1 (lower),
|
|
; Slim0 (upper), ROM Disk, RAM Disk. This is the order that
|
|
; the start code will attempt to boot from them, unless this
|
|
; has been overriden with the Startup Device CDEV. This order
|
|
; was chosen as follows, removable devices first, fixed devices
|
|
; last. For Slims, the lower Slim is checked first to be consistent
|
|
; with the two drive Mac SE / Harpo Floppy drive search order,
|
|
; which checks the lower drive first. For ROM/RAM disks, the RAM
|
|
; disk is searched first, and then the ROM disks are searched. The
|
|
; user can still override this order, by picking one with the CDEV.
|
|
; Also, gaps may be left in the drive numbering for drive which
|
|
; aren't found, when installing them in the drive queue, because
|
|
; the startup device drive number is saved in parameter ram,
|
|
; and we don't want it moving around across boots.
|
|
;_______________________________________________________________________
|
|
|
|
InitTable
|
|
dc.l 0 ; RamDisk doesn't have poll pointer
|
|
dc.w RAMDiskHandler-(*+2) ; RamDisk function handler
|
|
dc.w RAMDiskMediaIcon-(*+2) ; RamDisk media icon pointer
|
|
dc.w RAMDiskDriveIcon-(*+2) ; RamDisk drive icon pointer
|
|
dc.w RAMDiskName-(*+2) ; RamDisk drive name pointer
|
|
dc.l (1<<15)+\ ; volatile media
|
|
(0<<11)+\ ; primary
|
|
(1<<10)+\ ; fixed
|
|
(0<<9)+\ ; iwm (not SCSI)
|
|
(0<<8)+\ ; internal
|
|
ramDiskType ; RAM disk
|
|
dc.b (1<<CreateWithXSums) ; flags
|
|
dc.b $48 ; DiskInPlaceInit = non-ejectable, re-mount
|
|
|
|
InitTablePPC
|
|
dc.l 0 ; RamDisk doesn't have poll pointer
|
|
dc.w RAMDiskHandlerPPC-(*+2) ; RamDisk function handler for PowerPC
|
|
dc.w RAMDiskMediaIcon-(*+2) ; RamDisk media icon pointer
|
|
dc.w RAMDiskDriveIcon-(*+2) ; RamDisk drive icon pointer
|
|
dc.w RAMDiskName-(*+2) ; RamDisk drive name pointer
|
|
dc.l (1<<15)+\ ; volatile media
|
|
(0<<11)+\ ; primary
|
|
(1<<10)+\ ; fixed
|
|
(0<<9)+\ ; iwm (not SCSI)
|
|
(0<<8)+\ ; internal
|
|
ramDiskType ; RAM disk
|
|
dc.b (0<<CreateWithXSums) ; flags
|
|
dc.b $48 ; DiskInPlaceInit = non-ejectable, re-mount
|
|
|
|
PrimaryROMdisk
|
|
dc.l 0 ; RomDisk doesn't have poll pointer
|
|
dc.w ROMDiskHandler-(*+2) ; RomDisk function handler
|
|
dc.w ROMDiskMediaIcon-(*+2) ; RomDisk media icon pointer
|
|
dc.w ROMDiskDriveIcon-(*+2) ; RomDisk drive icon pointer
|
|
dc.w ROMDiskName-(*+2) ; RomDisk drive name pointer
|
|
dc.l (0<<11)+\ ; primary
|
|
(1<<10)+\ ; fixed
|
|
(0<<9)+\ ; iwm (not SCSI)
|
|
(0<<8)+\ ; internal
|
|
romDiskType ; ROM disk
|
|
dc.b (1<<CreateWithXSums) ; flags
|
|
dc.b $08 ; DiskInPlaceInit = non-ejectable
|
|
InitEntrySize equ *-PrimaryROMdisk ; size of an initialization table entry
|
|
|
|
SecondaryROMdisk
|
|
dc.l 0 ; RomDisk doesn't have poll pointer
|
|
dc.w ROMDiskHandler-(*+2) ; RomDisk function handler
|
|
dc.w ROMDiskMediaIcon-(*+2) ; RomDisk media icon pointer
|
|
dc.w ROMDiskDriveIcon-(*+2) ; RomDisk drive icon pointer
|
|
dc.w ROMDiskName-(*+2) ; RomDisk drive name pointer
|
|
dc.l (1<<11)+\ ; secondary
|
|
(1<<10)+\ ; fixed
|
|
(0<<9)+\ ; iwm (not SCSI)
|
|
(0<<8)+\ ; internal
|
|
romDiskType ; ROM disk
|
|
dc.b (1<<CreateWithXSums) ; flags
|
|
dc.b $08 ; DiskInPlaceInit = non-ejectable
|
|
|
|
EDiskOpen ; all regs saved by Device Manager
|
|
move.l a0,-(sp) ; save pointer to I/O param block
|
|
|
|
; Find the highest used drive number
|
|
|
|
move.l DCtlRefNum(a1),d7 ; d7.high := driver ref num
|
|
move.w #5,d7 ; d7 := refnum/highest drive number
|
|
move.l DrvQHdr+QHead,d0 ; get the drive queue head
|
|
beq.s @FoundDriveNumber ; if drive queue is empty
|
|
@NextDriveQueue
|
|
movea.l d0,a0 ; a0 := drive queue element
|
|
cmp.w DQDrive(a0),d7 ; check for a match
|
|
bhs.s @NextDriveNumber ; if drive number already in use
|
|
move.w DQDrive(a0),d7 ; this is now the highest drive number
|
|
@NextDriveNumber
|
|
move.l QLink(a0),d0 ; check next drive queue element
|
|
bne.s @NextDriveQueue ; if queue element exists
|
|
@FoundDriveNumber
|
|
addq.w #1,d7 ; d7 := next drive number
|
|
|
|
lea InitTable,a6 ; a6 := assume pointer to 68k initial values <2>
|
|
|
|
IF newEdiskProt THEN
|
|
cmpi.b #EMMU1,MMUType ; check for an emulated MMU
|
|
bne.s @NoEMMU
|
|
lea InitTablePPC,a6 ; a6 := pointer to PowerPC initial values
|
|
@NoEMMU
|
|
ENDIF
|
|
|
|
move.l BootGlobPtr,a2 ; get ptr to BootGlobs <T2>
|
|
move.l sgRamDiskBase(a2),d2 ; base of RAM disk <T4>
|
|
move.l d2,d3 ; get a copy in d3 <T4>
|
|
add.l sgRamDiskSize(a2),d3 ; end of ram disk in d3 <T4>
|
|
|
|
suba.l a2,a2 ; a2 := HeaderInfoPtr (none for RamDisk) <2>
|
|
move.l d2,d1 ; get start addr in d2 <T4>
|
|
moveq.l #0,d2 ; DataStartPtr := 0 <2>
|
|
cmp.l d1,d3 ; see if it has any bytes
|
|
bsr CreateEDrive ; create the RAM disk
|
|
@noDisk ; ENDIF
|
|
|
|
; search for, and install ROM disks
|
|
|
|
movea.l RomBase,a2 ; start searching at the base of ROM
|
|
@RomDiskLoop ;
|
|
bsr.w CheckForRomDisk ; see if it is a ROM disk
|
|
bne.s @NextRomDisk ; if not, try the next block
|
|
|
|
moveq.l #0,d1 ; assume no checksums unless header says otherwise
|
|
move.l a2,d2 ; DataStartPtr := base of rom disk for now
|
|
move.l a2,d3 ; DataEndPtr := base of rom disk for now
|
|
bsr.s CreateEDrive ; create the RAM disk
|
|
lea SecondaryROMdisk,a6 ; all future ROM disks are secondary
|
|
|
|
@NextRomDisk ;
|
|
adda.l #RomDiskAlign,a2 ; point to next block to check
|
|
cmpa.l #RomSpaceEnd,a2 ; see if end reached
|
|
blo.s @RomDiskLoop ; search the entire space
|
|
|
|
; see if we have any EDisks to drive, abort OPEN if none.
|
|
|
|
moveq.l #OpenErr,d0 ; if no drives found, return OpenErr
|
|
swap d7 ; d7.low := driver ref num
|
|
lea DrvQHdr+QHead-QLink,a0 ; point to the drive queue head
|
|
@CheckNeXTDrive
|
|
move.l QLink(a0),d1 ; check next drive queue element
|
|
beq.s @OpenDone ; if end of queue, and not found, kill the open
|
|
movea.l d1,a0 ; a0 := drive queue element
|
|
cmp.w dQRefNum(a0),d7 ; is this one of ours
|
|
bne.s @CheckNeXTDrive ; if not, check the NeXT one
|
|
|
|
; there are some EDisks in the drive queue, guess we need a driver for them.
|
|
|
|
move.l #EDiskVarsSize,d0 ; size of block to allocate
|
|
_NewPtr ,SYS,CLEAR ; allocate memory for globals
|
|
movea.l a0,a2 ; a2 := pointer to globals
|
|
move.l a2,DCtlStorage(a1) ; save globals pointer in DCE
|
|
move.l a1,DCEpointer(a2) ; save pointer to DCE in globals
|
|
move.w @RTS,FindDqePatch(a2) ; initialize FindDQE patch routine
|
|
move.w @RTS,PrimePatch(a2) ; initialize Prime patch routine
|
|
|
|
; Install the VBL task to look for SLIM insertions and removals
|
|
|
|
lea EDiskPollTask,a4 ; get the task address
|
|
moveq.l #8-1,d4 ; loop counter (8 times)
|
|
@InitPolling
|
|
lea VTask(a2),a0 ; a0 := pointer to VTask
|
|
jsr (a4) ; poll 8 times to init inserted status
|
|
dbra d4,@InitPolling ; and mount drives, and compute sizes
|
|
|
|
lea VTask(a2),a0 ; a0 <- VBL task
|
|
addq.w #vType,qType(a0) ; initialize qType field
|
|
move.l a4,vblAddr(a0) ; initialize vblAddr field
|
|
_VInstall ; install the VBL task
|
|
|
|
moveq.l #NoErr,d0 ; no error
|
|
@OpenDone
|
|
movea.l (sp)+,a0 ; restore pointer to I/O param block
|
|
move.w d0,ioResult(a0) ; return open status in ioResult
|
|
@rts rts
|
|
title 'EDisk Driver - Create EDrive'
|
|
|
|
;_______________________________________________________________________
|
|
;
|
|
; Routine: CreateEDrive
|
|
; Inputs: ccr.z - bne if drive should be created, beq if not
|
|
; A2 - HeaderInfoPtr
|
|
; D1 - CheckSumPtr
|
|
; D2 - DataStartPtr
|
|
; D3 - DataEndPtr
|
|
; D7.hi - EDisk Driver RefNum
|
|
; D7.lo - drive number
|
|
; A6 - pointer to InitTable info for this drive
|
|
; Outputs: D7.hi - EDisk Driver RefNum
|
|
; D7.lo - drive number + 1
|
|
; A6 - pointer to InitTable info for next drive
|
|
; Destroys: D0, A0, A3, A4
|
|
; Calls: none
|
|
; Called by: EDiskOpen
|
|
;
|
|
; Function: Creates and initializes the EDiskDriveInfo for the specified
|
|
; EDisk, and installs the drive queue entry for it.
|
|
;
|
|
;_______________________________________________________________________
|
|
|
|
CreateEDrive
|
|
beq.s @Done ; skip it if not used
|
|
|
|
moveq.l #EDiskDriveInfoSize,d0 ; size of info to allocate
|
|
_NewPtr ,Sys,Clear ; allocate the drive info
|
|
bne.s @Done ; if can't allocate, don't create drive
|
|
|
|
add.l #DQE-SLIMRegPtr,a0 ; point to the drive queue entry <T6>
|
|
|
|
movea.l a6,a3 ; a3 := running pointer to init table entry
|
|
move.l (a3)+,SLIMRegPtr(a0) ; initialize the SLIMRegPtr <T6>
|
|
movea.w (a3)+,a4 ; get the icon/name ptr
|
|
adda.l a3,a4 ; make it absolute
|
|
move.l a4,HWDepProcPtr(a0) ; initialize the HWDepProcPtr <T6>
|
|
move.l a2,HeaderInfoPtr(a0) ; initialize the HeaderInfoPtr <T6>
|
|
|
|
move.l d1,CheckSumPtr(a0) ; initialize CheckSumPtr <T6>
|
|
move.l d2,DataStartPtr(a0) ; initialize DataStartPtr |
|
|
move.l d3,DataEndPtr(a0) ; initialize DataEndPtr v
|
|
|
|
movea.w (a3)+,a4 ; get the icon/name ptr
|
|
adda.l a3,a4 ; make it absolute
|
|
move.l a4,MediaIconPtr(a0) ; initialize the icon ptr
|
|
movea.w (a3)+,a4 ; get the icon/name ptr
|
|
adda.l a3,a4 ; make it absolute
|
|
move.l a4,DriveIconPtr(a0) ; initialize the icon ptr
|
|
movea.w (a3)+,a4 ; get the icon/name ptr
|
|
adda.l a3,a4 ; make it absolute
|
|
move.l a4,WhereStringPtr(a0) ; initialize the name ptr
|
|
|
|
move.l (a3)+,DriveInfo(a0) ; initialize DriveInfo
|
|
move.w (a3)+,Flags(a0) ; initialize flags, DiskInPlaceInit
|
|
move.b #%01010101,InsertedStatus(a0) ; initialize inserted status to bouncing ^
|
|
sub.l d1,d3 ; calculate ram disk size |
|
|
move.l d3,RamDiskSize(a0) ; store it in globals <T6>
|
|
|
|
addq.w #1,qType(a0) ; use long drive size format
|
|
addq.w #1,Installed(a0) ; mark the drive as installed
|
|
move.l d7,d0 ; get disk drive number, and refNum
|
|
swap d0 ; move to high word, refNum to low word
|
|
move.l a0,a3 ; make a copy of ptr to info
|
|
_AddDrive ; add the drive to the drive queue
|
|
|
|
move.l d1,a0 ; get ptr to base of Edisk data
|
|
move.l d3,d1 ; get RamDiskSize
|
|
moveq.l #DisableEDiskWrites,d0 ; always disable writes at startup
|
|
bsr.w HWDependent ; disable writing to the EDisk
|
|
|
|
@Done addq.w #1,d7 ; update drive number
|
|
adda.w #InitEntrySize,a6 ; point to next drive init entry
|
|
rts ; EDisk drive is installed
|
|
title 'EDisk Driver - Check for ROM Disk'
|
|
|
|
;_______________________________________________________________________
|
|
;
|
|
; Routine: CheckForRomDisk
|
|
; Inputs: A2 - HeaderInfoPtr
|
|
; D7.hi - EDisk Driver RefNum
|
|
; Outputs: D0 - zero if valid ROM disk header, else non-zero
|
|
; ccr.z - bne if invalid header
|
|
; Destroys: D0, D1, A0, A3, A4
|
|
; Calls: none
|
|
; Called by: EDiskOpen
|
|
;
|
|
; Function: Checks the EDisk header to see if it exists (no bus error),
|
|
; and has a valid signature. If it is valid, compares it
|
|
; against all other ROM Disks found, and if it's header block
|
|
; is not identical to any other ROM Disk (in case address
|
|
; wrap around causes repeated images), returns a result
|
|
; indicating that it should be created.
|
|
;
|
|
;_______________________________________________________________________
|
|
|
|
with EDiskHeader
|
|
CheckForRomDisk
|
|
move.w sr,-(sp) ; save old interrupt mask
|
|
ori.w #HiIntMask,sr ; disable interrupts (stealing BusErrVct)
|
|
move.l BusErrVct,-(sp) ; save old bus error vector
|
|
lea @NotFound,a0 ; new handler address
|
|
move.l a0,BusErrVct ; setup bus error handler
|
|
movea.l sp,a4 ; mark the stack
|
|
|
|
lea HeaderTemplate,a3 ; point to expected values
|
|
lea HdrBlockSize(a2),a0 ; point to header data
|
|
moveq.l #(HdrDeviceSize-HdrBlockSize)/4-1,d0 ; loop counter
|
|
@SigCmpLoop
|
|
cmpm.l (a0)+,(a3)+ ; compare the values
|
|
dbne d0,@SigCmpLoop ; compare the blocks
|
|
@NotFound
|
|
movea.l a4,sp ; pop stack in case of bus error
|
|
move.l (sp)+,BusErrVct ; restore bus error vector
|
|
move.w (sp)+,sr ; restore interrupt mask
|
|
addq.w #1,d0 ; see if we had a match
|
|
bne.s @Done ; exit if not
|
|
|
|
; valid header found, now let's see if it's unique.
|
|
|
|
move.l d7,d1 ; get driver ref num
|
|
swap d1 ; d1.low := driver ref num
|
|
lea DrvQHdr+QHead-QLink,a0 ; point to the drive queue head
|
|
@CheckNeXTDrive
|
|
move.l QLink(a0),d0 ; check next drive queue element
|
|
beq.s @Done ; if not found, it's unique (d0=0)
|
|
movea.l d0,a0 ; a0 := drive queue element
|
|
cmp.w dQRefNum(a0),d1 ; is this one of ours
|
|
bne.s @CheckNeXTDrive ; if not, check the NeXT one
|
|
cmpi.b #romDiskType,\ ; it's one of ours
|
|
DriveInfo+3(a0) ; is it a ROM disk
|
|
bne.s @CheckNeXTDrive ; if not, check the NeXT one
|
|
|
|
|
|
moveq.l #EDiskHeaderSize/4-1,d0 ; compare the entire header
|
|
movea.l a2,a3 ; point to our header
|
|
movea.l HeaderInfoPtr(a0),a4 ; point to existing drive's header
|
|
@HdrCmpLoop
|
|
cmpm.l (a3)+,(a4)+ ; compare the values
|
|
dbne d0,@HdrCmpLoop ; compare the blocks
|
|
bne.s @CheckNeXTDrive ; if not the same, check the NeXT one
|
|
|
|
@Done tst.l d0 ; set ccr based on D0
|
|
rts ; all done
|
|
endwith
|
|
title 'EDisk Driver - Close processing'
|
|
|
|
;_______________________________________________________________________
|
|
;
|
|
; Routine: EDiskClose
|
|
; Inputs: A0 - pointer to I/O ParamBlock
|
|
; A1 - pointer to Device Control Entry (DCE)
|
|
; Outputs: D0 - Result Code (closErr)
|
|
; Destroys:
|
|
; Calls: none
|
|
; Called by: Device Manager
|
|
;
|
|
; Function: Driver shutdown routine
|
|
;
|
|
;_______________________________________________________________________
|
|
|
|
EDiskClose ; all regs saved by Device Manager
|
|
moveq.l #closErr,d0 ; return Close Error status
|
|
rts ; not closable at present
|
|
title 'EDisk Driver - Read / Write processing'
|
|
|
|
;_______________________________________________________________________
|
|
;
|
|
; Routine: EDiskPrime
|
|
; Inputs: A0 - pointer to I/O ParamBlock
|
|
; A1 - pointer to Device Control Entry (DCE)
|
|
; Outputs: D0 - Result Code
|
|
; Destroys:
|
|
; Calls: IODone
|
|
; Called by: Device Manager
|
|
;
|
|
; Function: Driver Read/Write routines
|
|
;
|
|
;_______________________________________________________________________
|
|
|
|
EDiskPrime ; all regs saved by Device Manager
|
|
;_Debugger
|
|
move.w ioTrap(a0),-(sp) ; save trap word to test immediate on exit <1.2>
|
|
moveq.l #0,d4 ; d4 := bytes transferred
|
|
movem.l a0/a1/d4,-(sp) ; save iopb, dce. allocate scratch longword
|
|
bsr.w FindDQE ; Find the drive queue element
|
|
bne.w @PrimeAbort ; return with error if not found or offLine <H1>
|
|
|
|
; check buffer paramaters
|
|
|
|
moveq.l #ParamErr,d0 ; assume parameter error
|
|
move.l ioByteCount(a0),d1 ; d1 := byte count
|
|
beq @PrimeAbort ; if byte count is zero <H1>
|
|
move.l dCtlPosition(a1),d2 ; d2 := starting byte offset
|
|
movem.l CheckSumPtr(a3),a4/a5/a6; get checksum/start/end pointers
|
|
adda.l d2,a5 ; a5 := RAM disk start addr
|
|
suba.l a5,a6 ; a6 := max byte count allowed
|
|
cmpa.l d1,a6 ; check for out of bounds
|
|
blt @PrimeAbort ; read past end of disk <H1>
|
|
|
|
; check alignment and direction
|
|
|
|
move.l d1,d7 ; get byte count
|
|
or.l d2,d7 ; check offset and byte count
|
|
andi.w #$01FF,d7 ; for multiples of block size (512)
|
|
bne @PrimeAbort ; if request not block aligned <H1>
|
|
move.l ioBuffer(a0),d6 ; d6 := buffer addr
|
|
moveq.l #rdVerify,d7 ; prepare to test for read verify
|
|
and.w IOPosMode(a0),d7 ; test for verify mode
|
|
sne d7 ; d7 := $FF if read verify
|
|
neg.b d7 ; d7 := 0 if read, 1 if read verify
|
|
move.l d6,d0 ; get destination addr in d0 <T2>
|
|
_StripAddress ; clear upper byte if necessary <T2>
|
|
cmpi.b #aWrCmd,ioTrap+1(a0) ; check for write cmd
|
|
movea.l a5,a0 ; a0 := source address
|
|
movea.l d0,a1 ; a1 := clean dest address <T2>
|
|
bne.s @paramsOK ; if not write, continue setting up for I/O
|
|
|
|
; check write params
|
|
|
|
moveq.l #2,d7 ; d7 := 2 if write
|
|
moveq.l #wPrErr,d0 ; assume write protect error
|
|
tst.b WriteProtected(a3) ; can we write to this disk?
|
|
bmi.s @PrimeAbort ; return with error if write protected <H1>
|
|
|
|
; d1 := byte count
|
|
; a0 := source address
|
|
; a1 := clean dest address
|
|
movem.l a0/d1,-(sp) ; save size, length for disabling the disk
|
|
moveq.l #EnableEDiskWrites,d0 ; hardware dependent function code
|
|
bsr.w HWDependent ; allow writing to the EDisk
|
|
|
|
exg a0,a1 ; swap source and dest if write
|
|
|
|
; select data transfer routine
|
|
|
|
@paramsOK
|
|
roxr.b #1,d6 ; ccr.x := ioBuffer is odd
|
|
addx.b d7,d7 ; shift result into d7
|
|
move.l a4,d6 ; prepare to test for checksumming
|
|
subq.l #1,d6 ; ccr.x := checksumming is disabled
|
|
roxl.w #2,d7 ; shift result into d7, and mult by 2 for index
|
|
lsr.l #9-2,d2 ; compute index into checksum table
|
|
adda.l d2,a4 ; a4 := pointer to checksum for first block
|
|
lea @DispatchTable,a5 ; point to the dispatch table
|
|
adda.w (a5,d7.w),a5 ; a5 := pointer to the routine
|
|
jsr PrimePatch(a2) ; allow patching here
|
|
move.l #512,d3 ; d3 := constant 512
|
|
|
|
; transfer the data a block at a time (usually)
|
|
|
|
@BlockLoop
|
|
moveq.l #0,d5 ; d5 := checksum, initialize to zero
|
|
moveq.l #(512/4)-1,d2 ; d2 := loop count for 1 block (4 bytes per loop)
|
|
jmp (a5) ; dispatch to the routine
|
|
@BlockDone
|
|
add.l d3,d4 ; update num done (512 more bytes done)
|
|
sub.l d3,d1 ; decrement bytecount
|
|
bhi.s @BlockLoop ; do next block if any blocks left
|
|
|
|
; transfer complete
|
|
|
|
@PrimeDone
|
|
moveq.l #noErr,d0 ; success
|
|
@PrimeErr
|
|
btst #EDiskProtect,Flags(a3) ; check if EDisk is protected
|
|
bne.s @ediskProtected ; IF EDisk is not protected THEN
|
|
move.l d0,d2 ; save result code in d2
|
|
movem.l (sp)+,a0/d1 ; restore size, length for disable code
|
|
moveq.l #DisableEDiskWrites,d0 ; hardware dependent function code
|
|
bsr.w HWDependent ; disable writing to the EDisk
|
|
move.l d2,d0 ; restore d0 with result code
|
|
@ediskProtected ; ENDIF
|
|
@PrimeAbort
|
|
movem.l (sp)+,a0/a1/d1 ; restore iopb, dce. pop scratch longword <2>
|
|
move.l d4,ioNumDone(a0) ; return number of bytes transferred
|
|
add.l d4,dCtlPosition(a1) ; update position pointer
|
|
bra.w EDiskDone ; return with error
|
|
|
|
|
|
; EDisk <-> Buffer, even or odd aligned, no checksumming (all blocks at once)
|
|
|
|
@ReadWrite
|
|
move.l d1,d0 ; get the byte count
|
|
_BlockMove ; move the data
|
|
move.l d1,d4 ; indicate all bytes moved
|
|
bra.s @PrimeDone ; return with success
|
|
title 'EDisk Driver - Read processing'
|
|
|
|
|
|
; EDisk -> Buffer, with checksumming, buffer even aligned (one block at a time)
|
|
|
|
@ReadEvenXsum
|
|
moveq.l #(512/8)-1,d2 ; d2 := loop count for 1 block (8 bytes per loop)
|
|
@ReadEvenLoop
|
|
move.l (a0)+,d7 ; fetch the source
|
|
add.l d5,d5 ; rotate the checksum
|
|
addx.l d7,d5 ; add source to the checksum
|
|
move.l d7,(a1)+ ; write it to the destination
|
|
move.l (a0)+,d7 ; fetch the source
|
|
add.l d5,d5 ; rotate the checksum
|
|
addx.l d7,d5 ; add source to the checksum
|
|
move.l d7,(a1)+ ; write it to the destination
|
|
dbra d2,@ReadEvenLoop ; loop through the entire block
|
|
@ReadDone
|
|
cmp.l (a4)+,d5 ; check the checksum
|
|
beq.s @BlockDone ; done with this block
|
|
moveq.l #badDCksum,d0 ; indicate data checksum error
|
|
bra.s @PrimeErr ; return with checksum error
|
|
|
|
|
|
|
|
; EDisk -> Buffer, with checksumming, buffer odd aligned (one block at a time)
|
|
|
|
@ReadOddXsum
|
|
subq.l #3,a1 ; back up the dest ptr, make it even
|
|
move.l (a1),d7 ; d7 := x x x A
|
|
addq.l #*+2-@ReadOddXsum,a5 ; after first block skip the code above
|
|
@ReadOddLoop
|
|
move.l (a0)+,d6 ; d6 := A B C D
|
|
add.l d5,d5 ; rotate the checksum
|
|
addx.l d6,d5 ; add source to the checksum
|
|
rol.l #8,d6 ; d6 := B C D A
|
|
move.b d6,d7 ; d7 := x x x A
|
|
move.l d7,(a1)+ ; write it to the destination
|
|
move.l d6,d7 ; d7 := B C D A
|
|
dbra d2,@ReadOddLoop ; loop through the entire block
|
|
move.b 3(a1),d7 ; d7 := B C D x
|
|
move.l d7,(a1) ; update last long word
|
|
bra.s @ReadDone ; done with this block
|
|
title 'EDisk Driver - Verify processing'
|
|
|
|
|
|
; Read Verify calls with and without checksumming
|
|
; buffer even aligned (one block at a time)
|
|
|
|
@VerifyEven
|
|
movea.l sp,a4 ; if no checksum, point to stack
|
|
@VerifyEvenXsum
|
|
@VerifyEvenLoop
|
|
move.l (a0)+,d7 ; fetch the source
|
|
add.l d5,d5 ; rotate the checksum
|
|
addx.l d7,d5 ; add source to the checksum
|
|
cmp.l (a1)+,d7 ; compare the buffers
|
|
dbne d2,@VerifyEvenLoop ; loop through the entire block
|
|
beq.s @VerifyGood ; if blocks are equal
|
|
@VerifyError
|
|
moveq.l #dataVerErr,d0 ; indicate verify failed
|
|
bra.s @PrimeErr ; return with error
|
|
|
|
|
|
|
|
; Read Verify calls with and without checksumming
|
|
; buffer odd aligned (one block at a time)
|
|
|
|
@VerifyOddXsum
|
|
lea @VerifyOddLoop,a5 ; skip the following code after the first time
|
|
@VerifyOddSetup
|
|
subq.l #1,a1 ; back up 1 byte to align
|
|
move.l (a1)+,d6 ; d6 := x A B C
|
|
rol.l #8,d6 ; d6 := A B C x
|
|
jmp (a5) ; start the loop
|
|
@VerifyOdd
|
|
addq.l #4,a5 ; resume after the next instruction
|
|
bra.s @VerifyOddSetup ; setup for the odd aligned compare
|
|
movea.l sp,a4 ; if no checksum, point to stack
|
|
@VerifyOddLoop
|
|
move.l d6,d7 ; d7 := A B C x
|
|
move.l (a1)+,d6 ; d6 := D E F G
|
|
rol.l #8,d6 ; d6 := E F G D
|
|
move.b d6,d7 ; d7 := A B C D
|
|
add.l d5,d5 ; rotate the checksum
|
|
addx.l d7,d5 ; add source to the checksum
|
|
cmp.l (a0)+,d7 ; compare the buffers
|
|
dbne d2,@VerifyOddLoop ; loop through the entire block
|
|
bne.s @VerifyError ; if not a match
|
|
@VerifyGood
|
|
move.l d5,(sp) ; force compare when not checksumming
|
|
bra.s @ReadDone ; check the checksum
|
|
title 'EDisk Driver - Write processing'
|
|
|
|
|
|
; EDisk <- Buffer, with checksumming, buffer even aligned (one block at a time)
|
|
|
|
@WriteEvenXsum
|
|
moveq.l #(512/8)-1,d2 ; d2 := loop count for 1 block (8 bytes per loop)
|
|
@WriteEvenLoop
|
|
move.l (a0)+,d7 ; fetch the source
|
|
add.l d5,d5 ; rotate the checksum
|
|
addx.l d7,d5 ; add source to the checksum
|
|
move.l d7,(a1)+ ; write it to the destination
|
|
move.l (a0)+,d7 ; fetch the source
|
|
add.l d5,d5 ; rotate the checksum
|
|
addx.l d7,d5 ; add source to the checksum
|
|
move.l d7,(a1)+ ; write it to the destination
|
|
dbra d2,@WriteEvenLoop ; loop through the entire block
|
|
@WriteDone
|
|
move.l d5,(a4)+ ; write out the checksum
|
|
bra.w @BlockDone ; done with this block
|
|
|
|
|
|
|
|
; EDisk <- Buffer, with checksumming, buffer odd aligned (one block at a time)
|
|
|
|
@WriteOddXsum
|
|
subq.l #1,a0 ; back up the source ptr, make it even
|
|
move.l (a0)+,d7 ; d7 := x A B C
|
|
rol.l #8,d7 ; d7 := A B C x
|
|
addq.l #*+2-@WriteOddXsum,a5 ; after first block skip the code above
|
|
@WriteOddLoop
|
|
move.l (a0)+,d6 ; d6 := D E F G
|
|
rol.l #8,d6 ; d6 := E F G D
|
|
move.b d6,d7 ; d7 := A B C D
|
|
add.l d5,d5 ; rotate the checksum
|
|
addx.l d7,d5 ; add source to the checksum
|
|
move.l d7,(a1)+ ; write it to the destination
|
|
move.l d6,d7 ; d7 := E F G D
|
|
dbra d2,@WriteOddLoop ; loop through the entire block
|
|
bra.s @WriteDone ; done with this block
|
|
|
|
|
|
|
|
; Table to dispatch to proper routine
|
|
|
|
@DispatchTable
|
|
dc.w @ReadEvenXsum-@DispatchTable ; 0 0 0 0 - read, even, xsum enabled
|
|
dc.w @ReadWrite-@DispatchTable ; 0 0 0 1 - read, even, xsum disabled
|
|
dc.w @ReadOddXsum-@DispatchTable ; 0 0 1 0 - read, odd, xsum enabled
|
|
dc.w @ReadWrite-@DispatchTable ; 0 0 1 1 - read, odd, xsum disabled
|
|
dc.w @VerifyEvenXsum-@DispatchTable ; 0 1 0 0 - verify, even, xsum enabled
|
|
dc.w @VerifyEven-@DispatchTable ; 0 1 0 1 - verify, even, xsum disabled
|
|
dc.w @VerifyOddXsum-@DispatchTable ; 0 1 1 0 - verify, odd, xsum enabled
|
|
dc.w @VerifyOdd-@DispatchTable ; 0 1 1 1 - verify, odd, xsum disabled
|
|
dc.w @WriteEvenXsum-@DispatchTable ; 1 0 0 0 - write, even, xsum enabled
|
|
dc.w @ReadWrite-@DispatchTable ; 1 0 0 1 - write, even, xsum disabled
|
|
dc.w @WriteOddXsum-@DispatchTable ; 1 0 1 0 - write, odd, xsum enabled
|
|
dc.w @ReadWrite-@DispatchTable ; 1 0 1 1 - write, odd, xsum disabled
|
|
title 'EDisk Driver - Control / Status processing'
|
|
|
|
;_______________________________________________________________________
|
|
;
|
|
; Routine: EDiskControl / EDiskStatus / KillIO
|
|
; Inputs: A0 - pointer to I/O ParamBlock
|
|
; A1 - pointer to Device Control Entry (DCE)
|
|
; Outputs: D0 - Result Code
|
|
; Destroys:
|
|
; Calls: FindDQE, EDiskDone
|
|
; Called by: Device Manager
|
|
;
|
|
; Function: Driver Control and Status routines
|
|
;
|
|
;_______________________________________________________________________
|
|
|
|
|
|
EDiskControl ; all regs saved by Device Manager
|
|
lea ControlDecode,a2 ; offset of decode table
|
|
bra.s HandleControlStatus ; join common code
|
|
|
|
|
|
EDiskStatus ; all regs saved by Device Manager
|
|
lea StatusDecode,a2 ; offset of decode table
|
|
* bra.s HandleControlStatus ; join common code (fall into it)
|
|
|
|
HandleControlStatus
|
|
move.w ioTrap(a0),-(sp) ; save trap word to test immediate on exit <1.2>
|
|
pea EDiskDone ; return through EDiskDone
|
|
move.w csCode(a0),d1 ; get the control/status code
|
|
@search move.l (a2)+,d0 ; get table entry
|
|
bmi.s @exit ; exit with error if not in list
|
|
cmp.w d0,d1 ; is it a match
|
|
bne.s @search ; keep looking until found
|
|
|
|
swap d0 ; get offset of routine
|
|
pea (a2,d0.w) ; push address of the routine
|
|
bra.w FindDQE ; find the DQE before calling routine
|
|
|
|
@exit movea.l dCtlStorage(a1),a2 ; a2 := pointer to EDiskVars
|
|
addq.l #4,sp ; <SM4>
|
|
bra.w EDiskDone2 ; return through EDiskDone2 <SM4>
|
|
|
|
|
|
ctlKillIO
|
|
move.w #immed,4(sp) ; make saved ioTrap an immediate call <1.2>
|
|
moveq.l #ControlErr,d0 ; we don't support KillIO, return an error <1.2>
|
|
rts ; return through EDiskDone
|
|
title 'EDisk Driver - Control / Status processing - Eject'
|
|
|
|
|
|
ctlEject
|
|
move.l d1,d0 ; get found status, ignore offline
|
|
bne.s @EjectErr ; return error if not found
|
|
bclr.b #MountedFlag,Flags(a3) ; mark it as not mounted
|
|
move.b DiskInPlace(a3),d0 ; see if any disk
|
|
ble.s @EjectDone ; if no disk, just ignore it
|
|
|
|
subq.b #8,d0 ; see if ejectable
|
|
beq.s @EjectDone ; if not ejectable, just ignore it
|
|
|
|
; if disk in place was $48 (non-ejectable, but call driver anyway) we will force a
|
|
; disk in place event to be posted by the polling task, to re-mount the volume.
|
|
|
|
moveq.l #EjectEDisk,d0 ; hardware dependent function code
|
|
bsr.w HWDependent ; start the eject, update DiskInPlace
|
|
@EjectDone
|
|
moveq.l #noErr,d0 ; return with success
|
|
@EjectErr
|
|
rts ; all done
|
|
title 'EDisk Driver - Control / Status processing - Format'
|
|
|
|
|
|
ctlFormat
|
|
bne @exit ; return with error if no drive or offline
|
|
|
|
; d1 := byte count
|
|
; a0 := source address
|
|
; a3 := ptr to drive queue element
|
|
move.l CheckSumPtr(a3),a0 ; put base addr of Edisk in a0
|
|
tst.l a0 ; check for no checksums
|
|
bne.s @checksumsOn ; IF no checksums THEN
|
|
move.l DataStartPtr(a3),a0 ; get real start of disk
|
|
@checksumsOn ; ENDIF
|
|
move.l DataEndPtr(a3),d1 ; put end of edisk in d1
|
|
sub.l a0,d1 ; get length in d1
|
|
movem.l a0/d1,-(sp) ; save size, length for enabling the disk
|
|
|
|
moveq.l #EnableEDiskWrites,d0 ; hardware dependent function code
|
|
bsr.w HWDependent ; enable writing to the EDisk
|
|
moveq.l #paramErr,d0 ; assume parameter error
|
|
move.w (a4),d1 ; get the format kind parameter
|
|
subq.w #1,d1 ; only allow 0 or 1
|
|
bls.s @CheckWrProt ; if in range, continue
|
|
|
|
addq.w #2,d1 ; -1 is a special case (destroys signature too)
|
|
bne.s @done ; if not -1, 0, or 1, return paramErr
|
|
cmpi.b #ramDiskType,DriveInfo+3(a3) ; see if it is a ram disk
|
|
bne.s @done ; if not, return the paramErr
|
|
|
|
lea DrvQHdr,a1 ; get the queue header
|
|
movea.l a3,a0 ; get the Ram Disk drive queue element
|
|
_DeQueue ; remove it from the drive queue
|
|
|
|
moveq.l #0,d6 ; fake RAM test passed
|
|
bra.s @SkipTest ; skip the test, and just clear it
|
|
|
|
@CheckWrProt
|
|
moveq.l #wPrErr,d0 ; assume write protect error
|
|
tst.b WriteProtected(a3) ; can we write to this disk?
|
|
bmi.s @done ; return write protect error if not
|
|
bsr.w CreateEDiskHeader ; write out a signature
|
|
|
|
moveq.l #0,d6 ; fake RAM test passed
|
|
|
|
@SkipTest
|
|
|
|
movem.l CheckSumPtr(a3),a0/a1/a4; get the checksum/start/end pointers
|
|
move.l a0,d2 ; see if has checksums, assume no error.
|
|
bne.s @ClearDisk ; if has checksums, clear them
|
|
movea.l a1,a0 ; otherwise, clear data as checksums
|
|
@ClearDisk
|
|
moveq.l #0,d0 ; clear to zero, assume success
|
|
tst.l d6 ; see if test passed <1.3>
|
|
beq.s @FormatStart ; if passed, initialize RAM and checksums
|
|
moveq.l #Fmt1Err,d0 ; indicate that format failed
|
|
bra.s @done ; all done
|
|
|
|
@NextBlock
|
|
moveq.l #(512/4)-1,d1 ; inner loop counter
|
|
@BlockLoop
|
|
move.l d0,(a1)+ ; clear a longword at a time
|
|
dbra d1,@BlockLoop ; clear the whole block
|
|
move.l d0,(a0)+ ; clear the checksum too
|
|
@FormatStart
|
|
cmpa.l a1,a4 ; see if all blocks cleared
|
|
bhi.s @NextBlock ; loop through all of the blocks
|
|
@done move.l d0,d2 ; save error code
|
|
IF newEdiskProt THEN
|
|
; d1 := byte count
|
|
; a0 := source address
|
|
; a3 := ptr to drive queue element
|
|
movem.l (sp)+,a0/d1 ; restore size, length for disabling the disk
|
|
ENDIF
|
|
moveq.l #DisableEDiskWrites,d0 ; hardware dependent function code
|
|
bsr.w HWDependent ; disable writing to the EDisk
|
|
move.l d2,d0 ; restore error code
|
|
@exit rts ; all done
|
|
title 'EDisk Driver - Control / Status processing - Verify'
|
|
|
|
|
|
; Verify that each block on the disk can be read
|
|
|
|
ctlVerify
|
|
bne.s @done ; return with error if no drive or offline
|
|
movem.l CheckSumPtr(a3),a0/a1/a4; get the checksum/start/end pointers
|
|
move.l a0,d0 ; see if has checksums, assume no error.
|
|
beq.s @done ; if has checksums, check them
|
|
|
|
moveq.l #noErr,d0 ; assume success, init checksum
|
|
@NextBlock
|
|
cmpa.l a1,a4 ; see if all blocks checked
|
|
bls.s @done ; exit when all blocks checked
|
|
|
|
moveq.l #(512/4)-1,d1 ; inner loop counter
|
|
@BlockLoop
|
|
move.l (a1)+,d3 ; fetch a longword at a time
|
|
add.l d0,d0 ; rotate the checksum
|
|
addx.l d3,d0 ; add in the data word
|
|
dbra d1,@BlockLoop ; check the whole block
|
|
|
|
sub.l (a0)+,d0 ; check the checksum
|
|
beq.s @NextBlock ; if checksum ok, check the next block
|
|
|
|
@error moveq.l #verErr,d0 ; return verify error.
|
|
@done rts ; all done
|
|
title 'EDisk Driver - Control / Status processing - FmtLst/DrvSts/DriveInfo'
|
|
|
|
|
|
; Return the list of sizes that can be formatted
|
|
|
|
statFmtLst
|
|
bne.s @done ; return with error if no drive or offline
|
|
moveq.l #paramErr,d0 ; assume parameter error
|
|
tst.w (a4) ; test number of entries in buffer
|
|
ble.s @Done ; if less than 1 entry, report error
|
|
move.w #1,(a4)+ ; indicate 1 entry returned
|
|
movea.l (a4),a4 ; get the buffer pointer
|
|
move.l dQDrvSz(a3),d0 ; get the swapped drive size
|
|
swap d0 ; un-swap it
|
|
move.l d0,(a4)+ ; return the drive size
|
|
move.l #$40000000,(a4) ; current disk has this format
|
|
moveq.l #noErr,d0 ; indicate success
|
|
@Done rts ; all done
|
|
|
|
|
|
|
|
; Return the drive status and drive queue element
|
|
|
|
statDrvSts
|
|
move.l d1,d0 ; get found status, ignore offline
|
|
bne.s @Done ; return error if not found
|
|
movea.l a4,a1 ; dest address is csParam area
|
|
clr.w (a1)+ ; return zero for track
|
|
lea WriteProtected(a3),a0 ; start copy with write protected flag
|
|
moveq.l #(DQE-WriteProtected)+dQDrvSz2+2,d0 ; number of bytes to copy
|
|
_BlockMove ; copy the drive info, and return noErr
|
|
@Done rts ; all done
|
|
|
|
|
|
; Return the RAM disk size
|
|
|
|
statDrvSize
|
|
move.l RamDiskSize(a3),(a4) ; return the RAM disk size, in bytes <T6>
|
|
rts ; all done <1.6>
|
|
|
|
|
|
; Return the drive type and info flags.
|
|
|
|
ctlDriveInfo
|
|
move.l d1,d0 ; get found status, ignore offline
|
|
bne.s @Done ; return error if not found
|
|
move.l DriveInfo(a3),(a4) ; return the drive info
|
|
@Done rts ; all done
|
|
title 'EDisk Driver - Control / Status processing - Drive/Media Icon'
|
|
|
|
|
|
; Return the Icon representing the location of the disk drive
|
|
|
|
ctlDriveIcon
|
|
movea.l DriveIconPtr(a3),a0 ; get drive icon ptr, setup source address
|
|
bra.s IconCommon ; join common icon code
|
|
|
|
|
|
; Return the Icon representing the disk media
|
|
|
|
ctlMediaIcon
|
|
movea.l MediaIconPtr(a3),a0 ; get media icon ptr, setup source address
|
|
IconCommon
|
|
move.l d1,d0 ; get found status, ignore offline
|
|
bne.s @Done ; return error if not found
|
|
moveq.l #ControlErr,d0 ; return control error if no icon found
|
|
move.l a0,d1 ; see if icon exists
|
|
beq.s @Done ; if no icon exists, return with error
|
|
|
|
; copy the icon into the buffer
|
|
|
|
lea IconBuffer(a2),a1 ; get buffer address (dest address)
|
|
move.l a1,(a4) ; return buffer pointer
|
|
move.l #IconAndMaskSize,d0 ; setup byte count for icon and mask
|
|
_BlockMove ; copy the icon into the buffer
|
|
|
|
; copy the "Where String" into the buffer
|
|
|
|
lea WhereStringBuff(a2),a1 ; point past icon, to "where string"
|
|
clr.b (a1) ; string length of zero, in case no string found
|
|
move.l WhereStringPtr(a3),d1 ; get where string pointer
|
|
beq.s @Done ; if no string, don't copy it
|
|
movea.l d1,a0 ; setup source address
|
|
moveq.l #1,d0 ; zero extend / adjust count
|
|
add.b (a0),d0 ; fetch the string length, count the length byte too
|
|
cmpi.w #WhereStringSize,d0 ; check to see if too long
|
|
bls.s @CopyString ; if in range just copy it
|
|
moveq.l #WhereStringSize,d0 ; otherwise truncate to max size
|
|
@CopyString
|
|
_BlockMove ; copy the string into the buffer
|
|
|
|
@Done rts ; all done (d0 is noErr from _BlockMove)
|
|
title 'EDisk Driver - FindDQE - Find Drive Queue Element'
|
|
|
|
;_______________________________________________________________________
|
|
;
|
|
; Routine: FindDQE
|
|
; Inputs: A0 - pointer to I/O ParamBlock
|
|
; A1 - pointer to Device Control Entry (DCE)
|
|
; Outputs: D0 - Drive Found and OnLine Status (noErr, NSDrvErr or offLinErr)
|
|
; D1 - Drive Found Status (noErr or NSDrvErr)
|
|
; A2 - pointer to EDiskVars
|
|
; A3 - pointer to DriveQueueElement for specified drive
|
|
; A4 - pointer to csParam field of I/O ParamBlock
|
|
; Destroys: D2, D3
|
|
; Calls: none
|
|
; Called by: Prime, Control, Status routines
|
|
;
|
|
; Function: Searches the drive queue for the Drive Queue Element
|
|
; associated with this Driver Request.
|
|
;
|
|
;_______________________________________________________________________
|
|
|
|
FindDQE ; find the drive queue element
|
|
movea.l dCtlStorage(a1),a2 ; a2 := pointer to EDiskVars
|
|
addq.b #1,Active(a2) ; request in progress, exclude polling <1.2>
|
|
jsr FindDqePatch(a2) ; allow patching here
|
|
lea DrvQHdr+QHead-QLink,a3 ; get the drive queue head
|
|
move.w IODrvNum(a0),d2 ; d2 := drive number
|
|
bpl.s @search ; start searching if drivenum is positive
|
|
neg.w d2 ; d2 := abs (IODrvNum)
|
|
|
|
; search the drive queue for the requested drive
|
|
|
|
@search
|
|
move.l QLink(a3),d3 ; check next drive queue element
|
|
beq.s @notFound ; if drive queue is empty
|
|
movea.l d3,a3 ; a3 := drive queue element
|
|
cmp.w DQDrive(a3),d2 ; check for a match
|
|
bne.s @search ; if not our drive
|
|
move.w dCtlRefNum(a1),d2 ; d2 := our driver ref number
|
|
cmp.w DQRefNum(a3),d2 ; compare to drive queue ref num
|
|
bne.s @search ; if not for our driver
|
|
|
|
moveq.l #noErr,d1 ; indicate drive is found
|
|
|
|
; now check to see if it is really present (onLine)
|
|
|
|
tst.b DiskInPlace(a3) ; is there a disk
|
|
ble.s @offLine ; return off line error if not
|
|
|
|
moveq.l #CheckEDiskInserted,d0 ; hardware dependent function code
|
|
bsr.s HWDependent ; see if disk is inserted
|
|
beq.s @offLine ; if not, return offline error
|
|
moveq.l #noErr,d0 ; indicate no disk-in-place
|
|
|
|
@Done lea csParam(a0),a4 ; point to param area
|
|
rts ; return with success (d0 = 0 = noErr)
|
|
|
|
@offLine
|
|
moveq.l #offLinErr,d0 ; indicate no disk-in-place
|
|
bra.s @Done ; return with error
|
|
|
|
|
|
@notFound
|
|
moveq.l #NSDrvErr,d1 ; indicate no such drive error
|
|
moveq.l #NSDrvErr,d0 ; indicate no such drive error
|
|
bra.s @Done ; return with error
|
|
title 'EDisk Driver - EDiskDone - Command Completion'
|
|
|
|
;_______________________________________________________________________
|
|
;
|
|
; Routine: EDiskDone
|
|
; Inputs: A2 - pointer to EDiskVars
|
|
; D0 - Result Code
|
|
; Destroys:
|
|
; Calls: IODone
|
|
; Called by: Prime, Control, Status routines
|
|
;
|
|
; Function: Completes request processing, by checking error result code,
|
|
; and returns control to the device manager through IODone.
|
|
;
|
|
;_______________________________________________________________________
|
|
|
|
EDiskDone
|
|
subq.b #1,Active(a2) ; request complete, allow polling <1.2>
|
|
EDiskDone2 ; <H6><SM4>
|
|
movea.l DCEpointer(a2),a1 ; setup DCE pointer in a1 for JIODone
|
|
btst.b #NoQueueBit-8,(sp)+ ; check for immediate request <1.2>
|
|
bne.s @immed ; if immediate, don't use jIODone <1.2>
|
|
move.l jIODone,-(sp) ; get IODone routine address
|
|
@immed ext.l d0 ; test for errors
|
|
beq.s @done ; if no error
|
|
move.w d0,DskErr ; save last error for file system
|
|
@done rts ; all done
|
|
title 'EDisk Driver - HWDependent - Hardware Dependent Functions'
|
|
|
|
;_______________________________________________________________________
|
|
;
|
|
; Routine: HWDependent
|
|
; Inputs: A3 - pointer to DriveQElement for specified drive
|
|
; D0 - function selector
|
|
; Outputs: none
|
|
; Destroys: D0
|
|
; Calls: none
|
|
; Called by:
|
|
;
|
|
; Function: Tests or performs a hardware dependent function.
|
|
;
|
|
;_______________________________________________________________________
|
|
|
|
HWDependent
|
|
move.l HWDepProcPtr(a3),-(sp) ; get the handler address
|
|
rts ; jump to it
|
|
|
|
RAMDiskHandler
|
|
move.b @decode(pc,d0.w),d0 ; get the routine offset
|
|
jmp @decode(pc,d0.w) ; jump to it
|
|
@decode
|
|
assert (*-@decode)=CheckEDiskInserted
|
|
dc.b @checkInserted-@decode
|
|
assert (*-@decode)=CheckEDiskReadOnly
|
|
dc.b @checkReadOnly-@decode
|
|
assert (*-@decode)=EnableEDiskWrites
|
|
dc.b @enableWrites-@decode
|
|
assert (*-@decode)=DisableEDiskWrites
|
|
dc.b @disableWrites-@decode
|
|
assert (*-@decode)=EjectEDisk
|
|
dc.b @eject-@decode
|
|
align 2
|
|
|
|
@checkInserted
|
|
moveq.l #-1,d0 ; always inserted
|
|
rts
|
|
@checkReadOnly
|
|
moveq.l #0,d0 ; never read only
|
|
@enableWrites
|
|
movem.l a0-a1/d1,-(sp) ; save registers <T5>
|
|
moveq #8,d0 ; _EDiskProtect selector |
|
|
move.l CheckSumPtr(a3),a0 ; put base addr of ram disk in a0 v
|
|
move.l #0,a1 ; indicate we want to unprotect edisk
|
|
_HwPriv ; unprotect the disk
|
|
movem.l (sp)+,a0-a1/d1
|
|
bclr #EDiskProtect,Flags(a3) ; indicate the disk is not protected
|
|
rts
|
|
@disableWrites
|
|
movem.l a0-a1/d1,-(sp) ; save registers
|
|
moveq #8,d0 ; _EDiskProtect selector
|
|
move.l CheckSumPtr(a3),a0 ; put base addr of ram disk in a0
|
|
move.l #1,a1 ; indicate we want to protect edisk
|
|
_HwPriv ; write-protect the disk ^
|
|
movem.l (sp)+,a0-a1/d1 ; restore registers |
|
|
bset #EDiskProtect,Flags(a3) ; indicate the disk is protected
|
|
rts ; <T5>
|
|
@eject clr.b DiskInPlace(a3) ; mark it as offline
|
|
@done rts
|
|
|
|
|
|
IF newEdiskProt THEN
|
|
;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
; PowerPC Edisk Routines
|
|
;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ
|
|
RAMDiskHandlerPPC
|
|
move.b @decode(pc,d0.w),d0 ; get the routine offset
|
|
jmp @decode(pc,d0.w) ; jump to it
|
|
@decode
|
|
assert (*-@decode)=CheckEDiskInserted
|
|
dc.b @checkInserted-@decode
|
|
assert (*-@decode)=CheckEDiskReadOnly
|
|
dc.b @checkReadOnly-@decode
|
|
assert (*-@decode)=EnableEDiskWrites
|
|
dc.b @enableWrites-@decode
|
|
assert (*-@decode)=DisableEDiskWrites
|
|
dc.b @disableWrites-@decode
|
|
assert (*-@decode)=EjectEDisk
|
|
dc.b @eject-@decode
|
|
align 2
|
|
|
|
@checkInserted
|
|
moveq.l #-1,d0 ; always inserted
|
|
rts
|
|
@checkReadOnly
|
|
moveq.l #0,d0 ; never read only
|
|
@enableWrites
|
|
; a3 = ptr to driveQElement
|
|
; d1 = transfer length
|
|
; a0 = transfer base
|
|
movem.l a0-a1/d1,-(sp) ; save registers
|
|
move.l #$80000008,d0 ; selector for PPC EDiskProtect, "unprotect"
|
|
move.l d1,a1 ; put size of xfer in a1
|
|
_HwPriv ; unprotect the disk
|
|
move.l CheckSumPtr(a3),a0 ; put base of checksums in a0
|
|
tst.l a0 ; check if checksums are in use
|
|
beq.s @noCksums ; IF using checksums THEN
|
|
move.l #$80000008,d0 ; selector for PPC EDiskProtect, "unprotect"
|
|
move.l DataStartPtr(a3),a1 ; put end of checksums in a1
|
|
suba.l a0,a1 ; leave length of checksum area in a1
|
|
_HwPriv ; unprotect the disk
|
|
@noCksums ; ENDIF
|
|
movem.l (sp)+,a0-a1/d1
|
|
bclr #EDiskProtect,Flags(a3) ; indicate the disk is not protected
|
|
rts
|
|
@disableWrites
|
|
movem.l a0-a1/d1,-(sp) ; save registers
|
|
move.l #$80010008,d0 ; selector for PPC EDiskProtect, "protect"
|
|
move.l d1,a1 ; put size of xfer in a1
|
|
_HwPriv ; write-protect the disk
|
|
move.l CheckSumPtr(a3),a0 ; put base of checksums in a0
|
|
tst.l a0 ; check if checksums are in use
|
|
beq.s @noCksumsDis ; IF using checksums THEN
|
|
move.l #$80010008,d0 ; selector for PPC EDiskProtect, "protect"
|
|
move.l DataStartPtr(a3),a1 ; put end of checksums in a1
|
|
suba.l a0,a1 ; leave length of checksum area in a1
|
|
_HwPriv ; write-protect the checksums
|
|
@noCksumsDis ; ENDIF
|
|
movem.l (sp)+,a0-a1/d1 ; restore registers
|
|
bset #EDiskProtect,Flags(a3) ; indicate the disk is protected
|
|
rts ;
|
|
|
|
@eject clr.b DiskInPlace(a3) ; mark it as offline
|
|
@done rts
|
|
|
|
ENDIF
|
|
|
|
ROMDiskHandler
|
|
move.b @decode(pc,d0.w),d0 ; get the routine offset
|
|
jmp @decode(pc,d0.w) ; jump to it
|
|
@decode
|
|
assert (*-@decode)=CheckEDiskInserted
|
|
dc.b @checkInserted-@decode
|
|
assert (*-@decode)=CheckEDiskReadOnly
|
|
dc.b @checkReadOnly-@decode
|
|
assert (*-@decode)=EnableEDiskWrites
|
|
dc.b @enableWrites-@decode
|
|
assert (*-@decode)=DisableEDiskWrites
|
|
dc.b @disableWrites-@decode
|
|
assert (*-@decode)=EjectEDisk
|
|
dc.b @eject-@decode
|
|
align 2
|
|
|
|
@checkInserted
|
|
@checkReadOnly
|
|
moveq.l #-1,d0 ; always inserted, always read only
|
|
@enableWrites
|
|
@disableWrites
|
|
rts
|
|
|
|
@eject clr.b DiskInPlace(a3) ; mark it as offline
|
|
@done rts
|
|
title 'EDisk Driver - EDiskPollTask - Drive Polling Task'
|
|
|
|
;_______________________________________________________________________
|
|
;
|
|
; Routine: EDiskPollTask
|
|
; Inputs: A0 - address of VTask (passed by Vertical Retrace Manager)
|
|
; Outputs: none
|
|
; Destroys:
|
|
; Calls: none
|
|
; Called by: Vertical Retrace Manager
|
|
;
|
|
; Function: Polls the SLIM cards to check for insertions and removals.
|
|
; Debounces the result, and post events to reflect the action.
|
|
;
|
|
;_______________________________________________________________________
|
|
|
|
EDiskPollTask ; a0-a3/d0-d3 saved by int handler
|
|
lea EDiskVars-VTask(a0),a2 ; a2 := pointer to EDiskVars
|
|
lea DrvQHdr+QHead-QLink,a3 ; get the drive queue head
|
|
movea.l DCEpointer(a2),a1 ; get DCE pointer
|
|
move.w dCtlRefNum(a1),d3 ; d3 := driver refnum
|
|
|
|
tst.b Active(a2) ; see if request in progress
|
|
beq.s @next ; if not, start searching the drive queue
|
|
|
|
addq.w #1,VTask+vblCount(a2) ; if active, try again real soon
|
|
rts ; return
|
|
|
|
@search movea.l d2,a3 ; a3 := DriveQElement
|
|
cmp.w dQRefNum(a3),d3 ; see if we are the driver
|
|
beq.s @CheckDrive ; check our drives
|
|
@next move.l QLink(a3),d2 ; check next drive queue element
|
|
bne.s @search ; search until end of drive queue
|
|
|
|
move.w #EDiskPollRate,VTask+vblCount(a2) ; re-initialize the VBL count
|
|
rts ; return
|
|
|
|
|
|
@CheckDrive
|
|
moveq.l #CheckEDiskInserted,d0 ; hardware dependent function code
|
|
bsr.w HWDependent ; see if disk is inserted
|
|
addq.w #1,d0 ; ccr.x := 1 if EDisk inserted
|
|
move.b InsertedStatus(a3),d1 ; prepare to shift in new inserted status
|
|
addx.b d1,d1 ; shift in new inserted status
|
|
move.b d1,InsertedStatus(a3) ; update inserted status
|
|
moveq.l #InsertedMask,d0 ; prepare to de-bounce, and test inserted
|
|
|
|
and.b d0,d1 ; see if offline, without bounce
|
|
bne.s @CheckOnLine ; if not offline, check online or bounce
|
|
|
|
@OffLine
|
|
tst.b DiskInPlace(a3) ; check online status
|
|
bpl.s @next ; if not ejecting, do nothing
|
|
clr.b DiskInPlace(a3) ; now mark it offline (ejected)
|
|
bra.s @next ; eject complete, check next drive
|
|
|
|
|
|
@CheckOnLine
|
|
cmp.b d0,d1 ; see if online, without bounce
|
|
bne.s @next ; if bouncing, ignore it until it stops
|
|
tst.b DiskInPlace(a3) ; check online status
|
|
bmi.s @next ; if ejecting, do nothing
|
|
beq.s @OnLine ; if was offline, and just went online
|
|
|
|
@mount btst.b #MountedFlag,Flags(a3) ; see if it was mounted
|
|
bne.s @next ; if already mounted, don't do it again
|
|
moveq.l #DiskInsertEvt,d0 ; disk inserted event (zero high word)
|
|
movea.l d0,a0 ; disk inserted event passed in a0
|
|
move.w DQDrive(a3),d0 ; disk drive number in low word
|
|
_PostEvent ; post the disk inserted event
|
|
bne.s @next ; if error, don't mark as mounted
|
|
bset.b #MountedFlag,Flags(a3) ; mark it as mounted
|
|
@toNext bra.s @next ; check the next drive
|
|
|
|
@OnLine
|
|
@SetupDriveInfo
|
|
move.b DiskInPlaceInit(a3),\
|
|
DiskInPlace(a3) ; mark it as inserted
|
|
clr.b WriteProtected(a3) ; mark it as writeable (assume RAM)
|
|
move.l HeaderInfoPtr(a3),d0 ; see if it supports headers
|
|
beq.s @SetupRAMDisk ; if no headers, must be a RAM based disk
|
|
|
|
with EDiskHeader
|
|
movea.l d0,a0 ; a0 points to device header
|
|
move.l HdrFormatTime(a0),\
|
|
FormatTime(a3) ; get the unique ID from the header
|
|
move.l HdrFormatTicks(a0),\
|
|
FormatTicks(a3) ; get the unique ID from the header
|
|
|
|
; see if device is ROM or RAM
|
|
|
|
moveq.l #CheckEDiskReadOnly,d0 ; hardware dependent function code
|
|
bsr.w HWDependent ; see if disk is read only
|
|
move.b d0,WriteProtected(a3) ; setup the RAM=$00 / ROM=$FF flag
|
|
bne.s @SetupROMDisk ; if ROM disk, all info comes from header
|
|
|
|
tst.l SLIMRegPtr(a3) ; see if this is a SLIM (which needs to be sized)
|
|
beq.s @SetupRAMDisk ; if not, base and end must already be valid
|
|
|
|
moveq.l #EnableEDiskWrites,d0 ; hardware dependent function code
|
|
bsr.w HWDependent ; allow writes while sizing
|
|
bsr.w ComputeSLIMSize ; see how big the SLIM card is
|
|
add.l a0,d0 ; compute end ptr
|
|
move.l d0,DataEndPtr(a3) ; setup pointer to end of device data
|
|
adda.w #EDiskHeaderSize,a0 ; point past the header
|
|
move.l a0,CheckSumPtr(a3) ; checksums start just after the header
|
|
moveq.l #DisableEDiskWrites,d0 ; hardware dependent function code
|
|
bsr.w HWDependent ; no writes now
|
|
endwith
|
|
|
|
@SetupRAMDisk
|
|
movem.l CheckSumPtr(a3),d0/d1/d2; get checksum/start/end ptrs
|
|
tst.l d0 ; see if checksum ptr is valid
|
|
beq.s @BaseFound ; if not, then d1 = base address = start ptr
|
|
move.l d0,d1 ; otherwise d1 := base address = checksum ptr
|
|
moveq.l #0,d0 ; default to no checksums for now
|
|
@BaseFound
|
|
btst.b #CreateWithXSums,Flags(a3) ; see if we want checksums
|
|
beq.s @UpdateBasePtrs ; if no checksums, DataStartPtr is base
|
|
|
|
move.l d1,d0 ; checksum ptr := base address
|
|
sub.l d2,d1 ; base - end
|
|
neg.l d1 ; total size := end - base
|
|
addi.l #512*128-1,d1 ; prepare to round up
|
|
lsr.l #7,d1 ; divide by 128 (512/4)
|
|
andi.w #~(512-1),d1 ; round to block boundary
|
|
add.l d0,d1 ; data starts after checksum table
|
|
|
|
@UpdateBasePtrs
|
|
movem.l d0/d1,CheckSumPtr(a3) ; write back checksum/start ptrs
|
|
@SetupDriveSize
|
|
sub.l d1,d2 ; byte size := end ptr - start ptr
|
|
bhs.s @DriveSizeOK ; if size >= 0, use it, else force null range
|
|
|
|
move.l d1,DataEndPtr(a3) ; setup end of null range
|
|
moveq.l #0,d2 ; range is zero bytes
|
|
|
|
@DriveSizeOK
|
|
rol.l #16-9,d2 ; convert to blocks, and swap halves
|
|
move.l d2,dqDrvSz(a3) ; fill in the drive size (in blocks)
|
|
bra.w @mount ; now mount the drive
|
|
|
|
|
|
@SetupROMDisk
|
|
move.l a0,d0 ; remember header address
|
|
lea HeaderTemplate,a1 ; point to expected values
|
|
with EDiskHeader
|
|
lea HdrBlockSize(a0),a0 ; point to header data
|
|
moveq.l #(HdrDeviceSize-HdrBlockSize)/4-1,d2 ; loop counter
|
|
@cmpLoop
|
|
cmpm.l (a0)+,(a1)+ ; compare the values
|
|
dbne d2,@cmpLoop ; compare the blocks
|
|
beq.s @SigOK ; get header info if signature valid
|
|
|
|
move.l d0,d1 ; start ptr is header ptr
|
|
move.l d1,d2 ; end ptr is start ptr
|
|
bra.s @UpdateBasePtrs ; create an empty ROM disk (pretty useless)
|
|
|
|
@SigOK move.l (a0)+,d0 ; get device size
|
|
addq.w #HdrCheckSumOff-HdrFormatTime,a0 ; point to checksum offset in header
|
|
lea CheckSumPtr(a3),a1 ; point to checksum ptr in drive info
|
|
|
|
moveq.l #(HdrMediaIconOff-\
|
|
HdrCheckSumOff)/4-1,d2 ; loop for next 3 fields
|
|
|
|
tst.l SLIMRegPtr(a3) ; see if this is a SLIM (which is ejectable)
|
|
bne.s @offsetLoop ; if ejectable, don't get the icon info
|
|
|
|
moveq.l #(HdrDriveInfo-\
|
|
HdrCheckSumOff)/4-1,d2 ; loop for next 6 fields
|
|
|
|
move.l HdrDriveInfo-HdrCheckSumOff(a0),d1 ; get drive info
|
|
beq.s @offsetLoop ; if none specified, use default
|
|
move.l d1,DriveInfo(a3) ; setup new drive info
|
|
@offsetLoop
|
|
addq.l #4,a1 ; leave pointer alone, assume default
|
|
move.l (a0)+,d1 ; get the offset
|
|
beq.s @nextOffset ; if none, ignore it
|
|
cmp.l d0,d1 ; see if offset is reasonable
|
|
bhi.s @nextOffset ; if offset past end of device, ignore it
|
|
add.l HeaderInfoPtr(a3),d1 ; add device base to offset
|
|
move.l d1,-4(a1) ; update the pointer
|
|
@nextOffset
|
|
dbra d2,@offsetLoop ; loop through all of the fields
|
|
|
|
movem.l DataStartPtr(a3),d1/d2 ; get start/end ptrs
|
|
bra.s @SetupDriveSize ; setup the drive queue size info
|
|
endwith
|
|
title 'EDisk Driver - ComputeSLIMSize - Get Signature Information'
|
|
|
|
;_______________________________________________________________________
|
|
;
|
|
; Routine: ComputeSLIMSize
|
|
; Inputs: A0 - pointer to base of SLIM address space for this card
|
|
; Outputs: D0 - Device Size in bytes
|
|
; Destroys: A1, D1, D2
|
|
; Calls: none
|
|
; Called by:
|
|
;
|
|
; Function: Returns the device size for the specified SLIM card.
|
|
;
|
|
;_______________________________________________________________________
|
|
|
|
SegmentSize equ 512*1024 ; slims have up to 4 512K byte segments
|
|
|
|
ComputeSLIMSize
|
|
adda.l #4*SegmentSize,a0 ; point past end of last segment
|
|
movea.l a0,a1 ; save copy of end address
|
|
moveq.l #%0000,d0 ; assume all 4 segments are missing
|
|
move.l #'Gary',d1 ; rotating pattern
|
|
moveq.l #4-1,d2 ; loop counter
|
|
@FillLoop
|
|
suba.l #SegmentSize,a0 ; point to base of previous segment
|
|
move.l (a0),-(sp) ; save the old contents
|
|
rol.l #8,d1 ; change the pattern
|
|
move.l d1,(a0) ; write to the ram
|
|
cmp.l (a0),d1 ; see if we can read it back
|
|
bne.s @NotRAM1 ; if not, it's not RAM
|
|
not.l d1 ; complement the pattern
|
|
move.l d1,(a0) ; write to the ram
|
|
cmp.l (a0),d1 ; see if we can read it back
|
|
bne.s @NotRAM2 ; if not, it's not RAM
|
|
bset.l d2,d0 ; indicate that the segment is RAM
|
|
@NotRAM2
|
|
not.l d1 ; restore pattern
|
|
@NotRAM1
|
|
dbra d2,@FillLoop ; loop through all 4 segments
|
|
|
|
not.l d1 ; get expected pattern
|
|
moveq.l #4-1,d2 ; loop counter
|
|
@CheckLoop
|
|
suba.l #SegmentSize,a1 ; point to base of previous segment
|
|
rol.l #8,d1 ; change the pattern
|
|
cmp.l (a1),d1 ; see if we can read it back
|
|
beq.s @IsRAM ; if so, it's RAM that didn't wrap around
|
|
bclr.l d2,d0 ; indicate that the segment isn't RAM
|
|
@IsRAM
|
|
dbra d2,@CheckLoop ; loop through all 4 segments
|
|
|
|
moveq.l #4-1,d2 ; loop counter
|
|
@RestoreLoop
|
|
move.l (sp)+,(a1) ; restore the old contents
|
|
adda.l #SegmentSize,a1 ; point to base of next segment
|
|
dbra d2,@RestoreLoop ; loop through all 4 segments
|
|
|
|
move.b @SizesTable(d0.w),d0 ; encode the segment present bits
|
|
moveq.l #19,d1 ; shift amount
|
|
lsl.l d1,d0 ; convert segment count to byte count
|
|
rts ; all done
|
|
|
|
@SizesTable
|
|
dc.b 0 ; 0000 - RAM, 0.0MB, 0 segments
|
|
dc.b 1 ; 0001 - RAM, 0.5MB, 1 segment
|
|
dc.b 0 ; 0010 - RAM, illegal configuration
|
|
dc.b 2 ; 0011 - RAM, 1.0MB, 2 segments
|
|
dc.b 0 ; 0100 - RAM, illegal configuration
|
|
dc.b 0 ; 0101 - RAM, illegal configuration
|
|
dc.b 0 ; 0110 - RAM, illegal configuration
|
|
dc.b 3 ; 0111 - RAM, 1.5MB, 3 segments
|
|
dc.b 0 ; 1000 - RAM, illegal configuration
|
|
dc.b 0 ; 1001 - RAM, illegal configuration
|
|
dc.b 0 ; 1010 - RAM, illegal configuration
|
|
dc.b 0 ; 1011 - RAM, illegal configuration
|
|
dc.b 0 ; 1100 - RAM, illegal configuration
|
|
dc.b 0 ; 1101 - RAM, illegal configuration
|
|
dc.b 0 ; 1110 - RAM, illegal configuration
|
|
dc.b 4 ; 1111 - RAM, 2.0MB, 4 segments
|
|
title 'EDisk Driver - CreateEDiskHeader - Create Header Information'
|
|
|
|
;_______________________________________________________________________
|
|
;
|
|
; Routine: CreateEDiskHeader
|
|
; Inputs: A3 - pointer to Drive Queue Element for specified drive
|
|
; Destroys: A0, A1, D0, D1, D2, D3
|
|
; Calls: none
|
|
; Called by: ctlFormat
|
|
;
|
|
; Function: Writes an EDisk Header to the specified device.
|
|
;
|
|
;_______________________________________________________________________
|
|
|
|
CreateEDiskHeader
|
|
with EDiskHeader
|
|
move.l HeaderInfoPtr(a3),d0 ; get header base
|
|
beq.s @Done ; if no headers, nothing to do
|
|
|
|
movea.l d0,a0 ; setup header pointer
|
|
moveq.l #EDiskHeaderSize/4-1,d3 ; loop counter
|
|
@clrLoop
|
|
clr.l (a0)+ ; clear the header block
|
|
dbra d3,@clrLoop ; 4 bytes at a time
|
|
|
|
lea HeaderTemplate,a1 ; point to default values
|
|
lea HdrBlockSize-EDiskHeaderSize(a0),a0 ; point to header data
|
|
moveq.l #(HdrDeviceSize-HdrBlockSize)/4-1,d3 ; loop counter
|
|
@cpyLoop
|
|
move.l (a1)+,(a0)+ ; copy the template
|
|
dbra d3,@cpyLoop ; 4 bytes at a time
|
|
|
|
move.l DataEndPtr(a3),d2 ; find end of device (assume = end of data)
|
|
sub.l d0,d2 ; d2 := device size
|
|
move.l d2,(a0)+ ; setup HdrDeviceSize
|
|
|
|
lea FormatTime(a3),a1 ; point to drive info
|
|
move.l Time,(a1) ; setup the format time
|
|
move.l (a1)+,(a0)+ ; setup HdrFormatTime
|
|
move.l Ticks,(a1) ; setup the format ticks
|
|
move.l (a1)+,(a0)+ ; setup HdrFormatTicks
|
|
|
|
moveq.l #(HdrDriveInfo-\
|
|
HdrCheckSumOff)/4-1,d3 ; loop for next 6 fields
|
|
@offsetLoop
|
|
addq.l #4,a0 ; leave offset zero, assume not supported
|
|
move.l (a1)+,d1 ; get next ptr field
|
|
sub.l d0,d1 ; make it an offset from base of device
|
|
cmp.l d1,d2 ; see if in range
|
|
blo.s @nextOffset ; if out of range, try next one
|
|
move.l d1,-4(a0) ; if in range, put it into the header
|
|
@nextOffset
|
|
dbra d3,@offsetLoop ; loop through all of the fields
|
|
|
|
@Done rts ; all done
|
|
endwith
|
|
|
|
string asis ; no length on strings
|
|
align 2
|
|
HeaderTemplate
|
|
dc.w 512 ; signature block size
|
|
dc.w 1 ; version number 1
|
|
dc.b 'EDisk ' ; 12 byte signature
|
|
dc.b 'Gary D' ; (brought to you by Gary D)
|
|
|
|
|
|
|
|
string pascal ; name strings have leading length byte
|
|
|
|
IF not padForOverPatch THEN ; removing string to adjust for mods <H1>
|
|
align 2
|
|
SlimDrive0Name
|
|
dc.b 'Upper SLIM Drive'
|
|
ENDIF
|
|
|
|
align 2
|
|
SlimDrive1Name
|
|
dc.b 'Lower SLIM Drive'
|
|
|
|
align 2
|
|
ROMDiskName
|
|
dc.b 'Internal ROM Disk'
|
|
|
|
align 2
|
|
RAMDiskName
|
|
dc.b 'Internal RAM Disk'
|
|
|
|
align 2
|
|
title 'EDisk Driver - RAM / ROM Disk Icons'
|
|
|
|
ROMDiskMediaIcon
|
|
ROMDiskDriveIcon
|
|
|
|
RAMDiskMediaIcon
|
|
RAMDiskDriveIcon
|
|
dc.l %01111111111111111111111111110000
|
|
dc.l %10000001000000000000000100001000
|
|
dc.l %10000001000000000111000100000100
|
|
dc.l %10000001000000001000100100000010
|
|
dc.l %10000001000000001000100100000001
|
|
dc.l %10000001000000001000100100000001
|
|
dc.l %10000001000000001000100100000001
|
|
dc.l %10000001000000001000100100000001
|
|
dc.l %10000001000000001000100100000001
|
|
dc.l %10000001000000000111000100000001
|
|
dc.l %10000000111111111111111100000001
|
|
dc.l %10000000000000000000000000000001
|
|
dc.l %10000000000000000010000000000001
|
|
dc.l %10000000000000001101000000000001
|
|
dc.l %10000000000000001000100000000001
|
|
dc.l %10000000000000110000010000000001
|
|
dc.l %10000000000000100000011000000001
|
|
dc.l %10000000000011000000110000000001
|
|
dc.l %10000000000010000001111000000001
|
|
dc.l %10000000001100000011001000000001
|
|
dc.l %10000000001000000111101000000001
|
|
dc.l %10000000110000001100101000000001
|
|
dc.l %10000000110000011110100000000001
|
|
dc.l %10000000111000110010100000000001
|
|
dc.l %10000000111101111010000000000001
|
|
dc.l %10000000101111001010000000000001
|
|
dc.l %10000000100111101000000000000001
|
|
dc.l %10000000000010101000000000000001
|
|
dc.l %10000000000000100000000000000001
|
|
dc.l %10000000000000100000000000000001
|
|
dc.l %10000000000000000000000000000001
|
|
dc.l %11111111111111111111111111111110
|
|
|
|
dc.l %01111111111111111111111111110000
|
|
dc.l %11111111111111111111111111111000
|
|
dc.l %11111111111111111111111111111100
|
|
dc.l %11111111111111111111111111111110
|
|
dc.l %11111111111111111111111111111111
|
|
dc.l %11111111111111111111111111111111
|
|
dc.l %11111111111111111111111111111111
|
|
dc.l %11111111111111111111111111111111
|
|
dc.l %11111111111111111111111111111111
|
|
dc.l %11111111111111111111111111111111
|
|
dc.l %11111111111111111111111111111111
|
|
dc.l %11111111111111111111111111111111
|
|
dc.l %11111111111111111111111111111111
|
|
dc.l %11111111111111111111111111111111
|
|
dc.l %11111111111111111111111111111111
|
|
dc.l %11111111111111111111111111111111
|
|
dc.l %11111111111111111111111111111111
|
|
dc.l %11111111111111111111111111111111
|
|
dc.l %11111111111111111111111111111111
|
|
dc.l %11111111111111111111111111111111
|
|
dc.l %11111111111111111111111111111111
|
|
dc.l %11111111111111111111111111111111
|
|
dc.l %11111111111111111111111111111111
|
|
dc.l %11111111111111111111111111111111
|
|
dc.l %11111111111111111111111111111111
|
|
dc.l %11111111111111111111111111111111
|
|
dc.l %11111111111111111111111111111111
|
|
dc.l %11111111111111111111111111111111
|
|
dc.l %11111111111111111111111111111111
|
|
dc.l %11111111111111111111111111111111
|
|
dc.l %11111111111111111111111111111111
|
|
dc.l %11111111111111111111111111111110
|
|
|
|
END
|