sys7.1-doc-wip/Tidbits/LateLoad.a

284 lines
9.5 KiB
Plaintext

;———————————————————————————————————————————————————————————————————————————————————
;
; File: LateLoad.a
;
; Contains: LateLoad
;
; This LinkedPatch is responsible for mounting slow
; SCSI drives on TERROR machines. Because TERROR waits for the default
; Startup Drive instead of the "internal" drive, unlike older ROMs, LateLoad is
; needed to make sure that the internal drive (or drives on Eclipse or similar)
; are spun up. This is done at LP time instead of at boot time because by then,
; most drives will have spun up already and we won't have to wait at all.
;
;
; Written by: Paul Wolf
;
; Copyright: © 1991-1992 by Apple Computer, Inc., All rights reserved.
;
; Change History (most recent first):
;
; <SM2> 2/1/93 PN Adding LateLoad from Reality and also moved LateLoad.a into
; SCSIMgr folder
; <1> 10/24/91 SAM Rolled in Regatta file.
;
; Regatta Change History:
;
; <3> 8/29/91 SAM (pdw) Added exception for portables. They will no longer wait
; for any drives other than the "internal" drive.
; <2> 8/21/91 SAM (pdw) Changed location of drive 0 bit in PRAM from bit 0 of byte
; 3 to bit 6 of byte 8A.
; <1> 7/30/91 SAM first checked in
; <0> 6/20/91 PDW Created.
;
; To Do:
;__________________________________________________________________________________________________
BLANKS ON ; assembler accepts spaces & tabs in operand field
STRING ASIS ; generate string as specified
PRINT OFF ; do not send subsequent lines to the listing file
; don't print includes
LOAD 'StandardEqu.d' ; from StandardEqu.a and for building ROMs
INCLUDE 'HardwarePrivateEqu.a'
INCLUDE 'UniversalEqu.a' ; for VIA bit and -TestFor- definitions
INCLUDE 'FSEqu.a' ; for VCB and DrvQ stuff
INCLUDE 'SCSIEqu.a' ; for SCSIDrvrs
INCLUDE 'LinkedPatchMacros.a'
PRINT ON ; do send subsequent lines to the listing files
; CASE OBJECT ; use case as specified in source text, C
; Note ••••
; This file is moved over to scsiLateLoad.a in SCSIMgr folder in SuperMario ROM
; ******************************************************************************
;---------------------------------------------------------------------
MACRO
_WaitForSCSIDevs
exg.l D0, A0
moveq #10,D0 ; WaitForSCSIDevs selector
_HWPriv
exg.l D0, A0
ENDM
;————————————————————————————————————————————————————————————————————————————
; LateLoad
;
;
;————————————————————————————————————————————————————————————————————————————
LateLoad InstallProc (IIci,hasTERROR) ; TERROR machines only!
;--- Get the stored list of drives to wait for
bsr.s GetOldDriveList ; D1.b = list of drives to wait for
;--- First, try just searching for these devices once, to see if they're there
move.w D1, D0 ; search for these devices
swap D0
move.w #0, D0 ; wait for no devices
_WaitForSCSIDevs
;--- If they are already mounted, don't do any more scans
move.b SCSIDrvrs, D0
and.b D1, D0 ; only test for those devices were interested in
cmp.b D1, D0 ; do we have them?
beq.s @gotThem ; yes - update stored drive list
;--- If they didn't get mounted by now, wait for them while scanning all SCSI IDs
move.w #$FF, D0 ; now search for all devices
swap D0
move.w D1, D0 ; and wait for the stored list of devices
_WaitForSCSIDevs
@gotThem
;--- Determine which SCSI IDs have drives that we want to remember about
bsr GetNewDriveList ; D1.w=list
;--- Update the stored drive list with the new configuration
bsr.s PutNewDriveList ; write changed drive list out to resource if needed
@end
rts
;---------------------------------------------------------------------
;
; Read the old drive list from PRAM.
;
; D1.b <-- drive list
;
;---------------------------------------------------------------------
DrvZeroBit EQU 6 ; Bit 6 in MMFlags PRAM byte 8A (for ID 0) <2>
GetOldDriveList
;--- Look at parameter RAM (1 byte at offset $89) for drives 1-6
moveq.l #0, D1
lea -2(SP),SP ; make read area for _ReadXPram
move.l sp,A0 ; place to read
move.l #$00010089, d0 ; one byte, location 89 (Bits 2-7)
_ReadXPRam ; trashes D0, puts byte in (a0)
move.b (sp)+,D1 ; "pop" the return value
lsr.b #2,D1 ; move the upper 6 bits right two places
lsl.b #1,D1 ; shift them all left 1 leaving a zero in bit 0
bsr.s GetDriveZeroBit
beq.s @exit
bset #0, D1
@exit
rts
;---------------------------------------------------------------------
;
; Put the new drive list wherever (how about a resource, no make it
; PRAM, no a resource, no ...).
;
; D1.b --> drive list
;
;---------------------------------------------------------------------
PutNewDriveList
;--- Update the "is SCSI ID 0 spinning" PRAM byte ---
bsr.s GetDriveZeroByte ; returns byte in D2 <2> thru next <2>
btst #0, D1 ; is drive 0 spun up?
beq.s @disableZero ; -> Nope, clear bit zero
@enableZero
bset #DrvZeroBit, D2 ; yes, wait for it next time too
bra.s @1
@disableZero
bclr #DrvZeroBit, D2 ; no, don't wait for it next time
@1
bsr.s PutDriveZeroByte ; accepts byte in D2 <2> from last <2>
;--- Update the bitmap of SCSI ids 1-6 in PRAM ---
lea -2(SP),SP ; make read area for _ReadXPram
move.l SP,A0 ; place to read
move.l #$00010089,D0 ; one byte, location 89 (Bits 2-7)
_ReadXPRam ; trashes D0, puts byte in (a0)
move.b (SP)+,D0 ; "pop" the return value
and.b #%11111110,D1 ; Mask out drive zero's bit (bit zero) from the drive mask
lsl.b #1,D1 ; Shift the 6 bits left 1
and.b #%00000011,D0 ; Mask out the serial bits from the PRAM byte $89
or.b D0,D1 ; Add our 6 bits to the 2 bits already there
move.b D1, -(SP) ; push new value on stack
move.l SP, A0 ; address of new PRAM value
move.l #$00010089, D0 ; write 1 bytes of PRAM to offset 3
_WriteXPRam ; save the IDs in parameter RAM
move.b (SP)+, D1
rts
;--------------------------------------------------------------------- <2> thru next <2>
GetDriveZeroBit
GetDriveZeroByte
;---------------------------------------------------------------------
;--- Look at parameter RAM (1 byte at offset 8a) for drive 0
lea -2(sp), sp ; make space for PRAM SCSI id
move.l sp, A0 ; address of PRAM return buffer
move.l #$0001008A,D0 ; read 1 byte of PRAM at offset 8a
_ReadXPRam ; get the byte
move.b (sp)+, D2 ;
btst #DrvZeroBit, D2 ; return Z flag according to drive 0 bit
rts
;---------------------------------------------------------------------
PutDriveZeroByte
;---------------------------------------------------------------------
;--- Modify parameter RAM (1 byte at offset 8a) for drive 0
move.b D2, -(SP) ; push new value on stack
move.l SP, A0 ; address of new PRAM value
move.l #$0001008A, D0 ; write 1 byte of PRAM to offset 8a
_WriteXPRam ; save the IDs in parameter RAM
move.w (SP)+, D2
rts ; <2> from last <2>
;---------------------------------------------------------------------
GetNewDriveList
;---------------------------------------------------------------------
; WITH scsiGlobalRecord
bsr.s FindFixedDrives ; Find all SCSI ID's with fixed drives in DrvQ
;--- if we are on a portable then strip all bits except for internal drive's <3> to next <3>
TestFor hwCbPwrMgr
beq.s @exit
; Look at parameter RAM (byte at offset 3) for internal drive's SCSI id
subq.l #2, sp ; make space for PRAM SCSI id
move.l sp, A0 ; address of PRAM return buffer
move.l #$00010003, D0 ; read 1 byte of PRAM at offset 3 (internal drive)
_ReadXPRam ; get the SCSI id
move.b (sp), D0 ; check high bits for validity
and.b #$78, D0 ; mask upper bits
cmp.b #$48, D0 ; equal to magic pattern?
beq.s @continue ; <2> if so, go do the real stuff
addq.w #2, sp ; <2> remove the answer from the stack
bra.s @exit ; <2> and just bail
@continue
move.b (sp)+, D0 ; check high bits for validity
and.w #$07, D0 ; mask lower 3 bits
moveq.l #0, D3
bset D0, D3 ; set only internal drive's bit in mask
and.b D3, D1 ; clear all but that drive's bit
@exit ; <3> from last <3>
rts
; ENDWITH
;---------------------------------------------------------------------
FindFixedDrives
;---------------------------------------------------------------------
move.b #0, D1 ; we start with no fixed disks
move.l DrvQHdr+qHead, A0 ; point to DrvQHdr (which points to 1st Qel)
@loop
move.b -3(A0), D0 ; is it fixed?
and.b #$0f, D0
cmp.b #$08, D0
bne.s @next
move.w dqRefNum(A0), D0
not.w D0
sub.w #$20, D0
blt.s @next ; not a SCSI driver
cmp.b #$7, D0
bgt.s @next
bset.l D0, D1 ; set the bit for this drive(r)
@next
move.l qLink(A0), A0 ; is this the end of the linked list?
move.l A0, D3 ; (test for zero link)
bne.s @loop
@exit
rts
ENDP
END.