mirror of
https://github.com/elliotnunn/sys7.1-doc-wip.git
synced 2024-12-12 04:29:09 +00:00
550 lines
21 KiB
Plaintext
550 lines
21 KiB
Plaintext
|
;
|
|||
|
; File: SCSIBoot.a
|
|||
|
;
|
|||
|
; Contains: This is the SCSI boot code for the Macintosh.
|
|||
|
;
|
|||
|
; Written by: Erich Ringewald
|
|||
|
;
|
|||
|
; Copyright: © 1985-1993 by Apple Computer, Inc. All rights reserved.
|
|||
|
;
|
|||
|
; Change History (most recent first):
|
|||
|
;
|
|||
|
; <SM9> 10/14/93 pdw Comment changes.
|
|||
|
; <SM8> 5/29/93 PW Added line to heap munging code (after driver is called) that
|
|||
|
; updates TheZone as well as ApplZone.
|
|||
|
; <SM7> 2/13/93 PW Added <LW2> change.
|
|||
|
; <LW2> 2/11/93 PW Added ability to tell drivers not to munge the heap by passing a
|
|||
|
; flag register (D6) from StartSearch or LateLoad.
|
|||
|
; <SM6> 11/3/92 SWC Changed SCSIEqu.a->SCSI.a.
|
|||
|
; <SM5> 10/22/92 CSS Change some branch short instructions to branches.
|
|||
|
; <SM4> 6/2/92 kc Roll in Pandora/Horror/Zydeco changes. Comments follow:
|
|||
|
; <H2> 12/21/91 jmp (BG,Z3) Added fix for busy status from drive while spinning up.
|
|||
|
; <Z2> 10/2/90 CCH Added a cache flush after SCSI reads during boot.
|
|||
|
; <SM1> 5/22/92 CS Cyclone (Pandora) roll in.
|
|||
|
; <9> 5/1/92 JSM Don’t use onMacXX style conditionals. This file now has no
|
|||
|
; conditionals.
|
|||
|
; <8> 12/27/91 RB Changed the flush cache code for 040's so it calls CacheFlush
|
|||
|
; <7> 9/16/91 JSM Cleanup header.
|
|||
|
; <6> 6/12/91 LN Changed #include 'HardwareEqu.a' to 'HardwarePrivateEqu.a'
|
|||
|
; <5> 9/21/90 BG Removing EclipseNOPS and other 040-related kludges as 040s are
|
|||
|
; now working more reliably.
|
|||
|
; <4> 7/19/90 BG Added EclipseNOPs for flakey 040s.
|
|||
|
; <3> 6/22/90 CCH Added a data cache push for 68040's after a SCSI block read.
|
|||
|
; <2> 5/16/90 MSH Added hasPowerControls to hcmac conditional.
|
|||
|
; <1.4> 8/22/89 SES Removed references to nFiles.
|
|||
|
; <1.3> 5/26/89 GGD Deleted the hack that was added for flakey PRAM on MvMac in
|
|||
|
; December.
|
|||
|
; <1.2> 12/13/88 rwh Added hack to set default OS to Mac OS while MvMac PRAM is
|
|||
|
; flakey.
|
|||
|
; <1.1> 11/10/88 CCH Fixed Header.
|
|||
|
; <1.0> 11/9/88 CCH Adding to EASE.
|
|||
|
; <•1.2> 9/23/88 CCH Got rid of inc.sum.d and empty nFiles
|
|||
|
; <1.1> 4/18/88 CSL Added support for JVC drive for HcMac
|
|||
|
; <1.0> 2/10/88 BBM Adding file for the first time into EASE…
|
|||
|
; <C895> 9/30/87 MSH Port to HcMac (Laguna)
|
|||
|
; <C859> 6/15/87 SHF Fixed bug in register usage in SRead routine.
|
|||
|
; <C846> 4/28/87 SHF Bug fixes.
|
|||
|
; <C770> 2/7/87 SHF Fixed bug in SRead read retry (stack problem).
|
|||
|
; <C613> 1/12/87 SHF Fixed driver count decrement size (long to word).
|
|||
|
; <C608> 1/9/87 SHF Fixed register-usage bug for booting non-Mac drivers.
|
|||
|
; <C478> 12/11/86 SHF Changes for Becks to allow booting a non-Mac OS.
|
|||
|
; <A382> 11/8/86 SHF Took out checksum bypass for driver checksums of 0.
|
|||
|
; <A349> 11/4/86 SHF Made the error-handling more forgiving (especially for 532-byte
|
|||
|
; sectors).
|
|||
|
; <A311> 10/31/86 SHF Added checksum for drivers having the appropriate boot code
|
|||
|
; partition map entry; we now search for appropriate driver
|
|||
|
; partition map entries and data partition map entries.
|
|||
|
; <A300> 10/29/86 SHF Go through all 8 devices (InitSCSIMgr sets the bit in SCSIDrvrs
|
|||
|
; corresponding to the CPU's SCSI id).
|
|||
|
; <A244> 10/27/86 SHF Read 512 instead of 256 bytes of blocks 0 and 1.
|
|||
|
; <A211> 10/17/86 SHF Put the Status phase check after the Command trap, added retry
|
|||
|
; to accomodate Unit Attention devices.
|
|||
|
; <C185> 9/30/86 SHF Fixed the mask value for the Status phase check.
|
|||
|
; <C165> 9/29/86 SHF Checks for Status phase after bad Select.
|
|||
|
; <C136> 9/3/86 SHF Added explicit .b, .w, .l; now checks NewPtr value
|
|||
|
; <C66> 7/9/86 SHF Fixed zero sbDrvrCount field bug in 'Openit'
|
|||
|
; <C26> 5/29/86 SHF Deleted _SCSIReset call in SCSILoad to avoid Unit Attn
|
|||
|
; recurrence. InitIO in StartInit now does the reset.
|
|||
|
; <C1> 4/15/86 RDC Deleted old MidMac changes
|
|||
|
; 2/19/86 BBM Made some modifications to work under MPW
|
|||
|
; 1/16/86 ELR Fixed polarity of beq to bpl for tst of SCSI byte.
|
|||
|
; 10/28/85 ELR Fixed bug in SCSILoad which didn't correctly look at SCSIFlags
|
|||
|
; 10/27/85 ELR Removed inclusion of SCSIMacs and SCSIBootEqu; this is now
|
|||
|
; included in NewEqu.
|
|||
|
; 10/27/85 ELR Added Flag "SCSIDrvrs" which is a bitmap for loaded SCSI
|
|||
|
; drivers. Now SCSILoad can be called repeatedly to check for new
|
|||
|
; devices coming online. A call to SCSILoad was placed in the
|
|||
|
; RDBootBlocks loop in StartInit to facilitate this.
|
|||
|
; 9/27/85 ELR Bunch of changes in a last ditch effort to get something to
|
|||
|
; work.
|
|||
|
; 9/16/85 RDC More changes for MidMac
|
|||
|
; 9/13/85 RDC Added changes for Milwaukee (MidMac) Fixed SetTrapaddress call
|
|||
|
; to work with new ROM's Added include of HWequ.text
|
|||
|
; 9/6/85 ELR New Today.
|
|||
|
;
|
|||
|
|
|||
|
BLANKS ON
|
|||
|
STRING ASIS
|
|||
|
|
|||
|
PRINT OFF
|
|||
|
LOAD 'StandardEqu.d'
|
|||
|
INCLUDE 'HardwarePrivateEqu.a'
|
|||
|
INCLUDE 'SCSI.a'
|
|||
|
PRINT ON
|
|||
|
|
|||
|
MACHINE MC68020
|
|||
|
|
|||
|
;
|
|||
|
; Equates for the partition map blocks
|
|||
|
;
|
|||
|
|
|||
|
PMSigWord EQU $504D ; offset 0
|
|||
|
|
|||
|
map_blks EQU 4 ; see partition design document
|
|||
|
part_phys_blk EQU 8
|
|||
|
part_blks EQU 12
|
|||
|
name EQU 16
|
|||
|
type EQU 48
|
|||
|
boot_size EQU 96
|
|||
|
boot_cksum EQU 116
|
|||
|
|
|||
|
|
|||
|
|
|||
|
SCSIBoots PROC EXPORT
|
|||
|
|
|||
|
EXPORT SCSILoad ; this is called by startinit
|
|||
|
;---------------------------------------------------------------
|
|||
|
;
|
|||
|
; SCSILoad -- loads in SCSI device drivers. Called by the start code.
|
|||
|
;
|
|||
|
; Modified to handle arbitrary combinations of requested drivers. <A349/03Nov86>
|
|||
|
;
|
|||
|
; On entry, d0.b is a bit map of devices for which we want to load drivers.
|
|||
|
; D6 = mask to OR with D5 when calling driver's installation point
|
|||
|
; On exit, d0.b is a bit map of devices for which we either:
|
|||
|
;
|
|||
|
; (a) successfully loaded drivers - or -
|
|||
|
; (b) the device(s) didn't respond and it would be useful to try
|
|||
|
; them later (possibly when they are powered up, etc.).
|
|||
|
;
|
|||
|
; If a device responded to the select but didn't have a valid driver, then
|
|||
|
; we clear the bit associated with that SCSI ID so that we don't waste any
|
|||
|
; more time polling it.
|
|||
|
;
|
|||
|
; --------------------------------------
|
|||
|
;
|
|||
|
; For NuMac only....
|
|||
|
;
|
|||
|
; d3 contains the following fields taken from parameter RAM in StartSearch.a:
|
|||
|
;
|
|||
|
; bits 0-7: partition number
|
|||
|
; bits 8-15: device ID (used for slots)
|
|||
|
; bits 16-23: OS type to boot (normally Mac OS)
|
|||
|
; bits 24-31: reserved
|
|||
|
;
|
|||
|
|
|||
|
SCSILoad
|
|||
|
|
|||
|
btst.b #7,HWCfgFlags ; is there a SCSI chip? <A349/03Nov86>
|
|||
|
bne.s Start ; yes, so continue <A349/03Nov86>
|
|||
|
moveq.l #0,d0 ; 0: don't try any more devices <A349/03Nov86>
|
|||
|
rts ; <A349/03Nov86>
|
|||
|
|
|||
|
; deleted old code <C1/15Apr86>
|
|||
|
|
|||
|
|
|||
|
; Start the load procedure. Assumes the SCSI bus has already been reset
|
|||
|
; <C26/29May86>; makes a pass through the 7 SCSI devices,
|
|||
|
; attempting to load 0-7 drivers. On entry, d0 has a bit map (byte wide)
|
|||
|
; of drivers to attempt to load. We compare this with the list of drivers
|
|||
|
; already loaded in order to decide which ones to load now. <A311/31Oct86>
|
|||
|
; InitSCSIMgr has already set the SCSIDrvrs bit corresponding to the CPU's
|
|||
|
; SCSI bus ID.
|
|||
|
|
|||
|
|
|||
|
Start
|
|||
|
movem.l a0-a6/d1-d7,-(sp) ; don't clobber this stuff
|
|||
|
move.b d0,-(sp) ; save the map <A311>
|
|||
|
|
|||
|
; hard reset of the SCSI bus removed here <C26/29May86>
|
|||
|
; start command to portable drives removed here
|
|||
|
|
|||
|
moveq.l #7,d5 ; start with SCSI device 7 <A300>
|
|||
|
CheckNext
|
|||
|
btst.b d5,(sp) ; do we want this one? <A311>
|
|||
|
beq.s @1 ; nope <A311>
|
|||
|
btst.b d5,SCSIDrvrs ; is it already loaded? <A349/04Nov86>
|
|||
|
bne.s @1 ; yes, so skip it <A349/04Nov86>
|
|||
|
bsr.s OpenIt ; try to install the driver
|
|||
|
beq.s @1 ; don't clear bit in map <A349/04Nov86>
|
|||
|
|
|||
|
; If the return value is non-zero, then it means a drive was there but that
|
|||
|
; block 0 or 1 (or the driver's checksum) weren't cool. In this case we
|
|||
|
; clear the bit in the map to be returned to the caller. <A349/04Nov86>
|
|||
|
|
|||
|
bclr.b d5,(sp) ; don't try this one again <A349/04Nov86>
|
|||
|
|
|||
|
@1
|
|||
|
dbra d5,CheckNext ; do the next one
|
|||
|
moveq.l #0,d0 ; clear upper nonsense <A349/04Nov86>
|
|||
|
move.b (sp)+,d0 ; pop the map byte <A311>
|
|||
|
movem.l (sp)+,a0-a6/d1-d7 ; restore everything else
|
|||
|
tst.w d0 ; set con. codes for word <A349/04Nov86>
|
|||
|
rts
|
|||
|
|
|||
|
;---------------------------------------------------------------
|
|||
|
;
|
|||
|
; OpenIt. This routine solicits the SCSI device whose ID is in d5
|
|||
|
; for a driver. If one is found, it is loaded into the system heap
|
|||
|
; and given an installation call. d3 contains boot information
|
|||
|
; passed in by StartSearch.a.
|
|||
|
;
|
|||
|
|
|||
|
;
|
|||
|
; Equates for the local stack frame <A311>
|
|||
|
;
|
|||
|
|
|||
|
DriverStart EQU -4 ; 1st blk # of driver (long)
|
|||
|
DriverBlks EQU DriverStart-4 ; # of blks in driver (long)
|
|||
|
|
|||
|
BootOS EQU DriverBlks-2 ; boot OS type (word)
|
|||
|
MapCnt EQU BootOS-4 ; # of part. map blocks (long)
|
|||
|
|
|||
|
CurMapBlk EQU MapCnt-4 ; counter variable (long)
|
|||
|
BlockBuf EQU CurMapBlk-512 ; after link, EA = 0(sp)
|
|||
|
FrameSize EQU BlockBuf ; value for link instruction
|
|||
|
|
|||
|
|
|||
|
OpenIt
|
|||
|
move.l d3,-(sp) ; preserve register <C478>
|
|||
|
|
|||
|
link a6,#FrameSize ; need some locals <A311>
|
|||
|
move.l sp,a2 ; start of blk buffer <A311>
|
|||
|
|
|||
|
swap d3 ; OS type (low byte) <C478>
|
|||
|
moveq.l #0,d0 ; clear upper bits <C478>
|
|||
|
move.b d3,d0 ; get the byte <C478>
|
|||
|
move.w d0,BootOS(a6) ; store as a word <C478>
|
|||
|
|
|||
|
moveq.l #0,d3 ; d3 gets block location
|
|||
|
moveq.l #1,d2 ; d2 gets block count
|
|||
|
move.w #512,d4 ; d4 gets block size <A244>
|
|||
|
bsr SRead ; read the block from unit in d5
|
|||
|
bne.w ZeroExit ; OK to try later <A349/04Nov86>
|
|||
|
cmpi.w #SBSigWord,SBSig(sp) ; is it for real?
|
|||
|
bne.w NonZeroExit ; no -- don't try again <A349/04Nov86>
|
|||
|
|
|||
|
move.w SBBlkSize(sp),d4 ; get the block size
|
|||
|
move.w SBDrvCount(sp),d0 ; get the driver count
|
|||
|
beq NonZeroExit ; no drivers: no retry <A349/04Nov86><SM5> CSS
|
|||
|
lea SBDrvrs(sp),a0 ; point at driver list
|
|||
|
move.l SBData(sp),d7 ; save the default data block pointer...
|
|||
|
|
|||
|
NextDD
|
|||
|
move.w BootOS(a6),d1 ; desired driver type <C608>
|
|||
|
cmp.w DDType(a0),d1 ; is this the one? <C608>
|
|||
|
|
|||
|
beq.s FoundDD
|
|||
|
|
|||
|
addq.l #DDLen,a0 ; move to the next driver
|
|||
|
|
|||
|
subq.w #1,d0 ; decrement count <C613>
|
|||
|
|
|||
|
bne.s NextDD
|
|||
|
bra NonZeroExit ; no matching drivers... <A349/04Nov86><SM5> CSS
|
|||
|
|
|||
|
FoundDD
|
|||
|
|
|||
|
bset.b d5,SCSIDrvrs ; show we tried to load the driver
|
|||
|
move.l DDBlock(a0),d3 ; block #
|
|||
|
move.l d3,DriverStart(a6) ; save a local copy <A311>
|
|||
|
moveq.l #0,d2 ; clear high word <A311>
|
|||
|
move.w DDSize(a0),d2 ; # blocks
|
|||
|
move.l d2,DriverBlks(a6) ; local copy <A311>
|
|||
|
|
|||
|
move.l d4,d0 ; block size of driver
|
|||
|
mulu d2,d0 ; times # blocks is byte size
|
|||
|
_NewPtr ,SYS ; head for the system heap
|
|||
|
bne.s NonZeroExit ; no room in the inn <A349/04Nov86>
|
|||
|
move.l a0,a3 ; put the driver here
|
|||
|
move.l a0,a2
|
|||
|
|
|||
|
bsr SRead ; load the driver
|
|||
|
bne.s DisposExit ; deallocate on error <A349/04Nov86>
|
|||
|
|
|||
|
moveq.l #1,d3 ; now read block 1
|
|||
|
move.l d3,CurMapBlk(a6) ; initialize counter <A311>
|
|||
|
moveq.l #1,d2 ; do a single block
|
|||
|
move.w #512,d4 ; full block <A244>
|
|||
|
move.l sp,a2 ; ontop of block 0 is OK
|
|||
|
bsr SRead ; preserves a2
|
|||
|
bne.s DisposExit ; error in read of block 1
|
|||
|
|
|||
|
cmp.w #SBMac,BootOS(a6) ; are we booting Mac OS? <C478>
|
|||
|
bne.s CallDriver ; no, so skip partition stuff <C478>
|
|||
|
|
|||
|
cmp.w #PDSigWord,(a2) ; old partition map? <A311>
|
|||
|
beq.s CallDriver ; yes, so just call it <A311>
|
|||
|
|
|||
|
; Just in case someone defines a new signature word for block 1, we'll
|
|||
|
; be nice and assume that the driver knows how to handle this new type.
|
|||
|
|
|||
|
cmp.w #PMSigWord,(a2) ; new partition entry? <A311>
|
|||
|
bne.s CallDriver ; no, so be nice <A311>
|
|||
|
|
|||
|
move.l map_blks(a2),d0 ; get count of map blocks <A311>
|
|||
|
move.l d0,MapCnt(a6) ; and save it locally
|
|||
|
bra.s DoNewPartition ; go do everything else
|
|||
|
CallDriver
|
|||
|
move.l a2,a0 ; pointer to the partition block
|
|||
|
|
|||
|
; We assume that if the driver is for the Mac OS, it will install itself and return.
|
|||
|
; If it's another OS type (such as UNIX), it should take control of the machine
|
|||
|
; and never return.
|
|||
|
; <LW2>pdw thru next
|
|||
|
or.l D6, D5 ; OR in control mask from client
|
|||
|
jsr (a3) ; install the driver...
|
|||
|
and.l #$00FFFFFF, D5 ; get rid of bit(s) that were in D6
|
|||
|
|
|||
|
; Make the System Heap growable by making the App Heap and TheZone the same zone as the System.
|
|||
|
MOVE.L SysZone,A0 ; which zone is the system zone
|
|||
|
MOVE.L A0,TheZone ; make THE REAL zone that zone
|
|||
|
MOVE.L A0,ApplZone ; good-bye to the app zone (make it same zone)
|
|||
|
MOVE.L bkLim(A0),HeapEnd ; end of System heap is now end of App Heap.
|
|||
|
; <LW2>pdw from prev
|
|||
|
ZeroExit
|
|||
|
moveq.l #0,d0 ; assume success <A349/04Nov86>
|
|||
|
bra.s OpenItRts ; <A349/04Nov86>
|
|||
|
DisposExit
|
|||
|
move.l a3,a0 ; restore ptr to driver <A349/04Nov86>
|
|||
|
_DisposPtr ; get rid of bad driver <A349/04Nov86>
|
|||
|
NonZeroExit
|
|||
|
moveq.l #-1,d0 ; bad sig or checksum <A349/04Nov86>
|
|||
|
OpenItRts
|
|||
|
unlk a6 ; clean up <A311>
|
|||
|
|
|||
|
move.l (sp)+,d3 ; restore register <C478>
|
|||
|
tst.w d0 ; set con. codes <C545>
|
|||
|
|
|||
|
rts
|
|||
|
|
|||
|
|
|||
|
;---------------------------------------------------------------
|
|||
|
;
|
|||
|
; DoNewPartition -- This is called when the signature word on block 1
|
|||
|
; matches the new partition map signature value. The first task is to
|
|||
|
; look for the partition map block for the driver itself (which contains a
|
|||
|
; checksum field, among other things). After we find one that matches the
|
|||
|
; Mac driver information we found in block 0, we do a checksum on the
|
|||
|
; driver (this helps to avoid loading garbage or trashed drivers, which
|
|||
|
; will cause a sad Mac at bootup time). If the checksum is good, we try
|
|||
|
; to find the first HFS partition entry in the partition map. If we pass
|
|||
|
; all these stages, then we finally call the driver.
|
|||
|
;
|
|||
|
|
|||
|
DoNewPartition ; new subroutine <A311>
|
|||
|
|
|||
|
cmp.l #'Appl',type+0(a2) ; 'Apple_Driver' type?
|
|||
|
bne.s NextMapEntry
|
|||
|
cmp.l #'e_Dr',type+4(a2)
|
|||
|
bne.s NextMapEntry
|
|||
|
cmp.l #'iver',type+8(a2)
|
|||
|
bne.s NextMapEntry
|
|||
|
cmp.l #'Maci',name+0(a2) ; 'Macintosh' name?
|
|||
|
bne.s NextMapEntry ; only check 4 letters
|
|||
|
move.l DriverStart(a6),d0 ; starting block of driver
|
|||
|
cmp.l part_phys_blk(a2),d0 ; same driver from block 0?
|
|||
|
bne.s NextMapEntry ; starts somewhere else...
|
|||
|
|
|||
|
move.l a3,a0 ; pointer to driver
|
|||
|
move.l boot_size(a2),d1 ; size of driver (bytes)
|
|||
|
bsr DoCksum ; put checksum in d0
|
|||
|
cmp.l boot_cksum(a2),d0 ; matches saved value?
|
|||
|
beq.s CkSumOK ; yes, so continue
|
|||
|
bra.s DisposExit ; else remove driver <A349/04Nov86>
|
|||
|
|
|||
|
NextMapEntry
|
|||
|
addq.l #1,CurMapBlk(a6) ; increment to next map block
|
|||
|
move.l CurMapBlk(a6),d3 ; get updated value
|
|||
|
cmp.l MapCnt(a6),d3 ; greater than maximum?
|
|||
|
bhi.s CksumOK ; if so, just look for data partition
|
|||
|
moveq.l #1,d2 ; read 1 block (from blk d3)
|
|||
|
move.w #512,d4 ; block size
|
|||
|
bsr.s SRead ; preserves a2 (ptr to block)
|
|||
|
bne.s NextMapEntry ; error in read
|
|||
|
cmp.w #PMSigWord,(a2) ; new partition entry?
|
|||
|
bne.s NextMapEntry ; try another if not
|
|||
|
bra.s DoNewPartition ; try to use this one
|
|||
|
|
|||
|
|
|||
|
; We have validated this partition map entry as belonging to a Macintosh
|
|||
|
; driver, and it has a good checksum (or none at all). Now we'll scan the
|
|||
|
; list of partition map blocks again, this time looking for the first
|
|||
|
; Macintosh HFS partition. If we find one, we'll load it, and call the
|
|||
|
; driver, passing a pointer to it. If we don't find an HFS partition,
|
|||
|
; then we deallocate the driver and continue with the next drive.
|
|||
|
|
|||
|
|
|||
|
CkSumOK
|
|||
|
moveq.l #0,d0 ; prime the loop variable
|
|||
|
move.l d0,CurMapBlk(a6) ; save it
|
|||
|
|
|||
|
LookForDataPt
|
|||
|
addq.l #1,CurMapBlk(a6) ; increment to next map block
|
|||
|
move.l CurMapBlk(a6),d3 ; get updated value
|
|||
|
cmp.l MapCnt(a6),d3 ; greater than maximum?
|
|||
|
bhi.w DisposExit ; if so, we give up
|
|||
|
moveq.l #1,d2 ; read 1 block (from blk d3)
|
|||
|
move.w #512,d4 ; block size
|
|||
|
bsr.s SRead ; preserves a2 (ptr to block)
|
|||
|
bne.s LookForDataPt ; error in read
|
|||
|
cmp.w #PMSigWord,(a2) ; new partition entry?
|
|||
|
bne.s LookForDataPt ; try another if not
|
|||
|
|
|||
|
cmp.l #'Appl',type+0(a2) ; 'Apple_HFS' type?
|
|||
|
bne.s LookForDataPt
|
|||
|
cmp.l #'e_HF',type+4(a2)
|
|||
|
bne.s LookForDataPt
|
|||
|
cmp.b #'S',type+8(a2)
|
|||
|
bne.s LookForDataPt
|
|||
|
bra.w CallDriver ; finally got a data partition
|
|||
|
|
|||
|
|
|||
|
;------------------------------------------------------------------
|
|||
|
;
|
|||
|
; Read block. d3 is block. d2 is block count. d4 is blocksize. d5 is unit.
|
|||
|
; a2 is the transfer address. d6 used for a pointer into the stack.
|
|||
|
; d7 is as follows: bit 31 is a retry flag, d7.w is the error code. <A349/04Nov86>
|
|||
|
;
|
|||
|
|
|||
|
SRead
|
|||
|
move.l d6,-(sp) ; save d6 <LW2>pdw
|
|||
|
move.l d7,-(sp) ; save d7 <A349/04Nov86>
|
|||
|
moveq.l #0,d7 ; clear flag & errcode <A349/04Nov86>
|
|||
|
swap d2 ; save block count <C846>
|
|||
|
move.w d4,d2 ; block size to LSW <C846>
|
|||
|
SReadAgain
|
|||
|
lea Scratch8,a0
|
|||
|
move.b #8,(a0)+ ; read command
|
|||
|
|
|||
|
swap d3
|
|||
|
andi.b #$1F,d3 ; isolate disk address
|
|||
|
move.b d3,(a0)+ ; LUN and disk address
|
|||
|
swap d3
|
|||
|
|
|||
|
move.w d3,(a0)+ ; disk address
|
|||
|
|
|||
|
move.l d2,d4 ; block count & size <C846>
|
|||
|
swap d4 ; block count in low word
|
|||
|
move.b d4,(a0)+ ; block count (byte) <C859>
|
|||
|
clr.b (a0)+ ; cmdbyte
|
|||
|
|
|||
|
mulu.w d2,d4 ; size (d2) * count (d4) = total bytes
|
|||
|
|
|||
|
sub.w #(SCSIZE*2),sp ; make room for 2 commands...
|
|||
|
move.l sp,d6 ; save this pointer...
|
|||
|
|
|||
|
subq.l #2,sp ; space for return value
|
|||
|
_SCSIGet
|
|||
|
move.w (sp),d7 ; error condition? <A349/04Nov86>
|
|||
|
bne RdDone ; go report it <A349/04Nov86>
|
|||
|
|
|||
|
move.w d5,-(sp) ; selid
|
|||
|
_SCSISelect
|
|||
|
move.w (sp),d7 ; error condition? <A349/04Nov86>
|
|||
|
bne RdDone ; go report it <A349/04Nov86> <SM5> CSS
|
|||
|
|
|||
|
pea Scratch8
|
|||
|
move.w #6,-(sp) ; count
|
|||
|
_SCSICmd
|
|||
|
move.w (sp),d7 ; remember the result <A349/04Nov86>
|
|||
|
bne.s Compl ; try to clean up <A349/04Nov86>
|
|||
|
|
|||
|
move.l d6,a0 ; point at command block
|
|||
|
move.w #SCINC,(a0)+ ; read command
|
|||
|
move.l a2,(a0)+ ; to this address
|
|||
|
move.l d4,(a0)+ ; this many bytes
|
|||
|
move.w #SCSTOP,(a0) ; then stop
|
|||
|
|
|||
|
move.l d6,-(sp) ; pass a pointer to this thing
|
|||
|
|
|||
|
_SCSIRead ; we'll save the error, <A349/04Nov86>
|
|||
|
move.w (sp),d7 ; but still do completion
|
|||
|
|
|||
|
Compl
|
|||
|
pea Scratch8 ; address for status byte
|
|||
|
pea Scratch8+2 ; address for message byte
|
|||
|
move.l #OneSecTicks,-(sp) ; wait up to one sec
|
|||
|
_SCSIComplete
|
|||
|
tst.w d7 ; error before complete? <A349/04Nov86>
|
|||
|
beq.s ChkComplErr ; no, so continue <C846>
|
|||
|
cmp.w #scPhaseErr,d7 ; phase error? <C846>
|
|||
|
beq.s ChkStat ; yes, so check status <C846>
|
|||
|
|
|||
|
;
|
|||
|
; Ignore SCSIComplete's phase error because it means it had <A349/04Nov86>
|
|||
|
; to read extra bytes beyond the 512 requested to get to the
|
|||
|
; Status phase. In the case of 532-byte sector sizes, we'll
|
|||
|
; get this error each time during boot, so we want to ignore
|
|||
|
; it. Note: the Mac+ SCSIMgr code doesn't signal this error.
|
|||
|
;
|
|||
|
ChkComplErr
|
|||
|
move.w (sp),d7 ; check Complete ret code <A349/04Nov86>
|
|||
|
cmp.w #scComplPhaseErr,d7 ; an error to ignore? <A349/04Nov86>
|
|||
|
bne.s RdDone ; only ignore phase errors <A349/04Nov86>
|
|||
|
ChkStat
|
|||
|
move.w Scratch8,d7 ; SCSI command status byte
|
|||
|
beq.s RdDone ; no error <A349/04Nov86>
|
|||
|
|
|||
|
cmp.w #2,d7 ; 'check condition' or 'busy' status? <H2>
|
|||
|
beq.s @ChkOrBsy ; ...check condition <H2>
|
|||
|
cmp.w #8,d7 ; ...busy condition <H2>
|
|||
|
bne.l RdDone ; we got neither condition...bail <H2>
|
|||
|
|
|||
|
@ChkOrBsy
|
|||
|
bset.l #31,d7 ; have we done a retry? <A349/04Nov86>
|
|||
|
bne.s RdDone ; yes, so return <C770/07Feb87>
|
|||
|
add.w #(SCSIZE*2)+2,sp ; clean up for retry... <C770/07Feb87>
|
|||
|
bra.w SReadAgain ; try 1 more time only <C770/07Feb87>
|
|||
|
|
|||
|
RdDone
|
|||
|
jsr ([jCacheFlush]) ; flush the cache <Z2>
|
|||
|
|
|||
|
add.w #(SCSIZE*2)+2,sp ; remove TIB and return value
|
|||
|
move.w d7,d0 ; return error code <A349/04Nov86>
|
|||
|
move.l (sp)+,d7 ; restore old d7 <A349/04Nov86>
|
|||
|
move.l (sp)+,d6 ; restore old d6 <LW2>pdw
|
|||
|
|
|||
|
tst.w d0 ; test return value <A349/04Nov86>
|
|||
|
rts
|
|||
|
|
|||
|
|
|||
|
;-----------------------------------------------
|
|||
|
;
|
|||
|
; Checksum routine added <A311/31Oct86>. It uses the algorithm in the
|
|||
|
; partition design document. On entry, a0 points to the driver and d1
|
|||
|
; has the size in bytes (word quantity).
|
|||
|
;
|
|||
|
; Returns 16-bit checksum in d0. Destroys d1,d7,a0.
|
|||
|
;
|
|||
|
|
|||
|
DoCksum
|
|||
|
moveq.l #0,d0 ; initialize sum register
|
|||
|
moveq.l #0,d7 ; zero-extended byte
|
|||
|
bra.s CkDecr ; handle 0 bytes <A349/04Nov86>
|
|||
|
CkLoop
|
|||
|
move.b (a0)+,d7 ; get a byte
|
|||
|
add.w d7,d0 ; add to checksum
|
|||
|
rol.w #1,d0 ; and rotate
|
|||
|
CkDecr
|
|||
|
dbra d1,CkLoop ; next byte
|
|||
|
tst.w d0 ; convert a checksum of 0
|
|||
|
bne.s @1 ; into $FFFF (as per
|
|||
|
subq.w #1,d0 ; algorithm description).
|
|||
|
@1
|
|||
|
rts
|
|||
|
|
|||
|
|
|||
|
END
|
|||
|
|