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