mirror of
https://github.com/elliotnunn/mac-rom.git
synced 2025-01-01 11:29:27 +00:00
0ba83392d4
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.
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
|
|
|