mirror of
https://github.com/elliotnunn/sys7.1-doc-wip.git
synced 2024-12-13 11:29:15 +00:00
1828 lines
64 KiB
Plaintext
1828 lines
64 KiB
Plaintext
;
|
||
; File: StartSearch.a
|
||
;
|
||
; Contains: This collection of subroutines is used to search out the most appropriate device to become
|
||
; the startup device, and to load the boot blocks from that device. It also provides the user
|
||
; with feedback as to what is happening.
|
||
;
|
||
; Written by: Wayne R. Loofbourrow - September, 1986
|
||
;
|
||
; Copyright: © 1986-1993 by Apple Computer, Inc. All rights reserved.
|
||
;
|
||
; Change History (most recent first):
|
||
;
|
||
; <SM13> 11/22/93 pdw Rolling in <MC3>
|
||
; <MC3> 11/9/93 pdw Fixed the "failed floppy boot causing wrong device boot" bug.
|
||
; Moved initialization of SCSIDrvrs back out of here and into
|
||
; SCSIMgrInit and BootItt (IttBoot) because on a failed boot,
|
||
; FindStartupDevice is called again and it wipes out SCSIDrvrs.
|
||
; Same with call to InitSCSIBoot.
|
||
; <SM12> 10/14/93 pdw Added selectable partition booting. Added forceBoot for
|
||
; InstallMeFirst CD-ROMs. Fixed Cmd-Shift-Opt-Del bugs with async
|
||
; SCSI. Rearranged some stuff and cleaned up some stuff.
|
||
; <SM11> 9/9/93 pdw Changed Peril to SetOSPassword and put it in SysEqu.a.
|
||
; <SM10> 8/23/93 pdw Added support for LimitPRAMClear, IgnoreCmdOptShDel,
|
||
; LoadDefaultOnly - three options required for AIX security,
|
||
; enabled by setting bits in PRAM $76.
|
||
; <SM9> 6/14/93 kc Roll in Ludwig.
|
||
; <LW5> 6/11/93 KW Do not call HideCursor in routine ShowSuccess if cursor is
|
||
; already hidden i.e. CrsState < 0. Fixes Radar bug #1087192
|
||
; <SM8> 2/13/93 PW Added Ludwig changes <LW2> and <LW3>.
|
||
; <LW3> 2/12/93 PW Added passing of drivers' "don't munge heaps" bit into SCSILoad.
|
||
; <LW2> 1/27/93 DCB Added code for CmdShiftOptDel startup sequence to fix Radar Bug
|
||
; 1051033.
|
||
; <SM7> 12/16/92 SWC Moved CenterRect here from StartBoot.a. Did some cleanup.
|
||
; <SM6> 11/30/92 PW Changed COUSIN_ITT uses to COUSIN_ITT AND hasAsyncSCSI.
|
||
; (Reserving use of COUSIN_ITT for special test builds.)
|
||
; <SM5> 11-12-92 jmp Eliminated assembler warning when not building with the
|
||
; COUSIN_ITT flag enabled.
|
||
; <SM4> 7/28/92 PW Turned on Cousin Itt (SCSIMgr4pt3).
|
||
; <SM3> 7/28/92 PW Added Cousin Itt stuff.
|
||
; <SM2> 5/16/92 kc Roll in Horror. Remove conditionals.
|
||
; <5> 1/2/92 RB Include UniversalEqu.a for TestFor macro.
|
||
; <4> 1/2/92 RB Do universal test for PowerMgr before calling it so that the
|
||
; conditionals can be taken out. Flush the cpu cache before boot
|
||
; block validation.
|
||
; <3> 9/16/91 JSM Cleanup header.
|
||
; <2> 6/12/91 LN Changed #include 'HardwareEqu.a' to 'HardwarePrivateEqu.a'
|
||
; <1.9> 11/13/89 MSH Pmgr equates now in record format.
|
||
; <1.8> 8/22/89 SES Removed references to nFiles. Changed include DeclRomEqu.a to
|
||
; RomEqu.a. Changed sRsrc_BootRec to sRsrcBootRec.
|
||
; <1.7> 6/10/89 SWC Converted the HappyMac and disk icon drawing routines to use
|
||
; QuickDraw on all machines.
|
||
; <1.6> 5/24/89 GGD Converted to feature based conditionals in more places, more
|
||
; works is needed for the 16 bit machines.
|
||
; <1.5> 4/10/89 gmr Removed specific drive checks in InBootMask, now just check for
|
||
; drive number within range (0..15). This allows BootMask to work
|
||
; with RAM disks, as well as future drivers. Eliminated IsItSCSI,
|
||
; IsItHD20 in the process.
|
||
; <•1.4> 3/13/89 BBM SetOSDefault blindly set pram to the values pointed at by A0.
|
||
; Master pointers to rom resources on a macintosh ][ are of the
|
||
; form A083XXXX. The Trap number for SetOSDefault is A083. If a
|
||
; program crashed and started executing random blocks, then there
|
||
; was a good chance that it would try to execute a master pointer.
|
||
; The result would be that the default OS on reboot is not valid.
|
||
; Cross reference PB337 in system sources. The fix is to require a
|
||
; password, to prevent wandering programs from creating Chaos.
|
||
; <1.3> 2/27/89 jwk Added BigJSR's to SCSILoad as part of async SCSI roll in.
|
||
; <1.2> 2/16/89 rwh removed Mv conditionals for Vias not working.
|
||
; <1.1> 11/10/88 CCH Fixed Header.
|
||
; <1.0> 11/9/88 CCH Adding to EASE.
|
||
; <2.0> 11/7/88 rwh fixed bug in 'command-shift-option-del' disabling of internal
|
||
; drive
|
||
; <1.9> 9/24/88 rwh roll in on MvMac changes
|
||
; <•1.8> 9/23/88 CCH Got rid of inc.sum.d and empty nFiles
|
||
; <1.7> 9/12/88 MSH Last version of sleep count down. Time saved on stack.
|
||
; <1.6> 9/9/88 MSH Screen clearing before shut down uses lomem values instead of
|
||
; equates.
|
||
; <1.5> 9/8/88 MSH Slightly revised sleep count down method.
|
||
; <1.4> 6/24/88 MSH HcMac: Fixed the time out waiting for boot device to two
|
||
; minutes. Sleep command now requires a signature word sent with
|
||
; the command.
|
||
; <1.3> 6/15/88 MSH fix for ramdisk stuff
|
||
; <1.2> 6/7/88 MSH Converted to Mac ][ boot screen and SCSI boot device selection
|
||
; for HcMac.
|
||
; <1.1> 5/23/88 BBM fixed name conflicts by adding i to internal routines.
|
||
; <1.0> 2/10/88 BBM Adding file for the first time into EASE…
|
||
; <C914> 10/29/87 rwh Port to Modern Victorian (on MvMac). Removed those ugly "---
|
||
; NuMac ---)))"s.
|
||
; <C878> 9/2/87 MSH Port to HcMac (Laguna)
|
||
; <C772> 2/8/87 SHF Added delay between calls to SCSILoad in WaitForInternal to
|
||
; accomodate drives which don't like to be polled too quickly.
|
||
; <C736> 2/2/87 GWN Renamed SDM selector. Changed HandleSlotDev to LoadSlotDrivers.
|
||
; Fixed bug in NeverAgain.
|
||
; <C720> 1/29/87 GWN Cleared spExtDev field where neccessary.
|
||
; <C706> 1/27/87 SHF Changed the internal drive wait timeout value to 20 seconds.
|
||
; <C682> 1/24/87 WRL [NuMac] Modified the disk and happy Mac plotting routines to use
|
||
; QuickDraw. HappyMac routine moved here from startfail.
|
||
; <C677> 1/23/87 SHF Increased the internal drive wait timeout value to 25 seconds.
|
||
; <C638> 1/15/87 GWN Changed the interface of GetVideoDefault and SetVideoDefault.
|
||
; <C619> 1/13/87 GWN Test the status of the sLoad code.
|
||
; <C613> 1/12/87 SHF Now uses low-memory global for SCSI ID of the internal hard disk
|
||
; (used to always assume 0).
|
||
; <C600> 1/7/87 GWN Made minor changes for slot booting.
|
||
; <C593> 1/5/87 GWN Added code to center disk icon & company.
|
||
; <C587> 1/4/87 JTC Changed MyIOPB to $380, but then restored it to $400.
|
||
; <C515> 12/12/86 GWN Changed PRAM address of Video default to $80.
|
||
; <C474> 12/2/86 GWN Added code to enable boot off of a default slot device. Modified
|
||
; EmbarkOnSearch to get more parameters from PRAM. Added
|
||
; GetOSDefault and SetOSDefault routines. Added GetVideoDefault
|
||
; and SetVideoDefault traps (code by WRL).
|
||
; <A383> 11/8/86 CSL Load SCSI driver 0 in general LoadDriver routine if no
|
||
; don't-load drive 0 keys (command, shift, option and delete) are
|
||
; down.
|
||
; <A362> 11/6/86 CSL Power user - don't load internal hard disk - command, if hold
|
||
; down command, shift, option and delete keys are bootup time,
|
||
; internal hard disk would not be loaded, code in startsearch,
|
||
; with this power user command, check internal disk disable is
|
||
; changed from FullWaitMask to DynWaitMask.
|
||
; <A349> 11/4/86 SHF Changed mask value in SetWaitFlags which caused the timeout
|
||
; value to always have been reset to 0 and the wait flags to
|
||
; always retain their current value (meaning Permanent Disable was
|
||
; always set). Removed nWaitMacs.a include (rolled into
|
||
; StartMacs.a).
|
||
; <A345> 11/4/86 WRL Add new internal wait disable bit. Don't continue internal wait
|
||
; if device is there, but driver fails to load. Added new
|
||
; _InternalWait trap.
|
||
; <A344> 11/3/86 WRL Put LoadSCSIDrivers ahead of InternalWait so that SCSI devices
|
||
; 7..1 get priority in the drive queue over SCSI device 0 if no
|
||
; default is set.
|
||
; <A321> 10/31/86 WRL Cut SCSILoad related delays down to 1.75 seconds (from 3.5
|
||
; seconds). Fixed bug: No, SEQ doesn't affect the CCR!!! Fixed
|
||
; bug: Branch in WaitForInternal was wrong polarity. Enhancement:
|
||
; Don't try to load internal hard disk's driver if corrupted.
|
||
; <A306> 10/30/86 WRL Changed GetDefaultStartup, SetDefaultStartup, and InternalWait
|
||
; to use an OS style interface, as they should.
|
||
; <A300> 10/30/86 SHF Changed GetStartupDevice trap to bsr since the trap was OS but
|
||
; expected to be called ToolBox style. Fixed stack bug in
|
||
; SetRawTimeOut routine.
|
||
; <A297> 10/29/86 WRL After case-laden discussions with Jerome, Tony, Steve, Sheila,
|
||
; and Rich, we decided to have the time delay refer only to the
|
||
; maximum amount of time the system will wait for the internal
|
||
; SCSI device (whose ID must be zero). If the delay is exhausted,
|
||
; it is assumed that the user doesn't have an internal drive, and
|
||
; the delay in PRAM is reset to zero. The delay now refers to
|
||
; total time since Ticks was cleared. Isn't this fun?
|
||
; <A286> 10/28/86 WRL Made delay apply up front, to give drives a chance to warm up.
|
||
; <A276> 10/27/86 SMH modified rom search procedure.
|
||
; <C206> 10/9/86 bbm Modified to mpw aincludes.
|
||
; <C198> 10/2/86 Fixed bug in flashing X on disk icon.
|
||
; <C152> 9/30/86 Creation based loosely on the Mac Plus boot code.
|
||
;
|
||
|
||
PRINT OFF
|
||
LOAD 'StandardEqu.d'
|
||
INCLUDE 'HardwarePrivateEqu.a'
|
||
INCLUDE 'UniversalEqu.a'
|
||
INCLUDE 'Devices.a'
|
||
INCLUDE 'PowerPrivEqu.a'
|
||
INCLUDE 'SlotMgrEqu.a'
|
||
INCLUDE 'ROMEqu.a'
|
||
INCLUDE 'SCSI.a'
|
||
PRINT ON
|
||
|
||
MACHINE MC68020
|
||
|
||
;---------------
|
||
; Local Equates
|
||
;---------------
|
||
|
||
MyIOPBA6 EQU -$400 ; A6 offset for IOPB
|
||
|
||
FlashEnable EQU 8 ; (bit) 0 = disable; 1 = enable.
|
||
FlashParity EQU 9 ; (bit) 0 = no marks in disk icon, 1 = mark present (X or ?)
|
||
XEnable EQU 10 ; (bit) 1 = enable X flash next time
|
||
|
||
FlashTicks EQU 60 ; min number of ticks between half-flashes of X or ?
|
||
NumFlashX EQU 3 ; number of times to flash X before going
|
||
; back to flashing ? on disk icon.
|
||
|
||
FloppyRefNum EQU -5 ; floppy driver refnum
|
||
IntHDRefNum EQU -33 ; refnum of driver for SCSI ID 0
|
||
|
||
DefaultTimeOut EQU 20 ; number of seconds timeout if PRAM is pristine
|
||
MaxTimeOut EQU 31 ; maximum number of seconds allowed as timeout
|
||
PollDelay EQU 15 ; delay (in ticks) between poll drive SCSILoads
|
||
|
||
TimeOutMask EQU $1F ; mask for bits used as timeout
|
||
WaitFlagsMask EQU $E0 ; mask for bits used as flags
|
||
|
||
DynWaitBit EQU 7 ; 0 = enable; 1 = disable dynamic wait
|
||
PermWaitBit EQU 6 ; 0 = enable; 1 = disable permanent wait
|
||
|
||
DynWaitMask EQU (1<<DynWaitBit)
|
||
|
||
CmdShiftOptDel EQU $8805 ; command, shift, option and delete keys down bits
|
||
|
||
NoDefaultVal EQU $6666 ; the sign of the ... no default disk selected
|
||
|
||
IMPORT CacheFlush ; Dispatch.a
|
||
IMPORT SCSILoad ; :SCSIMgr:SCSIBoot.a
|
||
IF hasAsyncSCSI THEN
|
||
IMPORT INITSCSIBOOT ; :SCSIMgr4pt3:BootItt.c
|
||
IMPORT ISITT ; BootItt.c
|
||
IMPORT ITTBOOT ; BootItt.c
|
||
ENDIF
|
||
|
||
|
||
|
||
Locals RECORD {link},INCR
|
||
|
||
frameSize equ *
|
||
|
||
flashTime ds.l 1 ; time to flash icon
|
||
startTicks ds.l 1 ; Ticks when we first get into FindStartupDevice
|
||
|
||
ckPartition ds.b 1 ; flag = we need to check to see if the partition #s match
|
||
noDefaultDrive ds.b 1 ; flag = we have no default drive
|
||
foundDrvr ds.b 1 ; flag = we have seen the driver in the drive Q
|
||
forcedBoot ds.b 1 ; flag = boot has been forced to a non-default device
|
||
|
||
csPB ds CntrlParam ; pb for Control and Status
|
||
|
||
pmCommandPB ds pmCommandRec ; pb for sending SleepReq to power manager
|
||
|
||
startPRAM ;(ds.l 1)
|
||
lsdExtDevID ds.b 1 ; slot device ExtDevID (for SCSI target/lun)
|
||
lsdPartition ds.b 1 ; slot device Partition (for SCSI partition #)
|
||
lsdRefNum ;(ds.w 1) ; SCSI device refnum
|
||
lsdSlotNum ds.b 1 ; slot number
|
||
lsdSRsrcID ds.b 1 ; sRsrc ID (for native SCSI, bus #; for plug-in, sRsrc ID)
|
||
|
||
link ds.l 1 ; old A4 = (A4)
|
||
|
||
ENDR
|
||
|
||
; Register Convention for entire file
|
||
; Scratch: D0-D2, A0-A1
|
||
|
||
D3_partDevOS EQU D3
|
||
D4_refNum EQU D4
|
||
|
||
A2_driveQel EQU A2
|
||
A3_IsIt_Proc EQU A3
|
||
A4_locals EQU A4
|
||
A5_bootGlobs EQU A5
|
||
A6_bootBlocks EQU A6
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: FindStartupDevice
|
||
;
|
||
; Inputs: none
|
||
;
|
||
; Outputs: (A6)- contains the boot blocks (1024 bytes)
|
||
; BtDskRfn contains the refNum of the startup device
|
||
; BootDrive contains the drive number of the startup device
|
||
;
|
||
; Trashes: D0-D6, A0-A4
|
||
;
|
||
; Function: finds the startup device, and loads and verifies the boot blocks from it
|
||
; (on portables, if no boot device is found within the sleep timeout, then
|
||
; go to sleep)
|
||
;________________________________________________________________________________________
|
||
|
||
FindStartupDevice PROC EXPORT
|
||
|
||
WITH Locals
|
||
|
||
EXPORT EraseMyIcon
|
||
|
||
IMPORT GetDefaultStartup ; StartSearch.a
|
||
|
||
link A4, #frameSize
|
||
|
||
BSR EmbarkOnSearch ; Initialize our state.
|
||
|
||
BSR LoadSlotDrivers ; Default is a slot device, execute boot code
|
||
; When booting a Mac OS, execution will continue here
|
||
MOVE.L Ticks, startTicks(A4) ; Init the time we got here in case we have PowerMgr
|
||
|
||
BSR LoadSCSIDrivers ; Load all the drivers we can
|
||
BSR WaitForPollDrive ; Wait until the boot drive has warmed up
|
||
BRA.S @FirstEntry ; First time through: keep original goal
|
||
|
||
@NextPass
|
||
IF hasPwrControls THEN ; <SM7>
|
||
WITH PmgrRec,pmCommandRec
|
||
TestFor hwCbPwrMgr ; do we have Power Manager?
|
||
beq.s @noSleep ; if not then skip time check
|
||
|
||
MOVE.L Ticks,D0 ; Get the current time
|
||
SUB.L startTicks(A4),D0 ; Determine the time to go back to sleep
|
||
CMP.L #BootDevTicks,D0 ; See if time out has occured
|
||
BLS.S @nosleep
|
||
@sleepnow
|
||
LEA pmCommandPB(A4), A0 ; A0 gets pointer to parameter block
|
||
MOVE.W #SleepReq, pmCommand(A0) ; PMGR command, Go to sleep
|
||
MOVE.W #4, pmLength(A0) ; Four bytes of data to send
|
||
LEA pmData(A0), A1
|
||
MOVE.L A1, pmSBuffer(A0) ; pointer to send buffer
|
||
MOVE.L A1, pmRBuffer(A0) ; pointer to receive buffer
|
||
MOVE.L #SleepSig, pmData(A0) ; Put sleep signature in buffer
|
||
_PmgrOp
|
||
CMPI.W #SleepAck,pmData(A0) ; is the reply a sleep confirmation?
|
||
@waitsleep BEQ.S @waitsleep ; Wait for the drugs to take affect
|
||
@nosleep
|
||
ENDWITH
|
||
ENDIF ; <SM7>
|
||
|
||
CMPI.W #FloppyRefNum,D4 ; do we have floppy set as the default?
|
||
BEQ.S @NoChange ; -> yes, keep looking for floppies
|
||
LEA IsItAnything,A3 ; no, from now on, any device will do
|
||
@NoChange
|
||
BSR LoadSCSIDrivers ; load more drivers if we can
|
||
|
||
@TryAgain
|
||
BSR VisualUpdate ; Update dynamic user feedback
|
||
|
||
@FirstEntry
|
||
BSR FindNextCandidate ; Find the next potential Startup Device.
|
||
BEQ.S @NextPass ; Branch if we're at the end of the queue.
|
||
|
||
BSR SelectDevice ; Set up parameter block for this device.
|
||
BSR CheckMouseEject ; Eject it if requested by mouse-down.
|
||
BEQ.S @TryAgain ; Branch if ejected (we won't try reading it).
|
||
|
||
BSR GetStartupInfo ; Try to read the boot blocks from the device.
|
||
BEQ.S @GotIt ; Branch if success.
|
||
|
||
BSR ReactToFailure ; Handle the failure case.
|
||
BRA.S @TryAgain ; Try to find another Startup Device.
|
||
@GotIt
|
||
|
||
; show that we have succeeded in finding a startup device
|
||
|
||
TST CrsrState ; if negative, don't call HideCursor
|
||
BMI.S @ShowHappyMac ; prevents cursor depth from sinking
|
||
; to far if can't find boot drive
|
||
_HideCursor
|
||
|
||
@ShowHappyMac
|
||
|
||
MOVE.L A5, -(SP)
|
||
BSR HappyMac ; Plot the Happy Mac
|
||
MOVE.L (SP)+, A5
|
||
|
||
unlk A4
|
||
RTS
|
||
|
||
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: EmbarkOnSearch
|
||
;
|
||
; Inputs: none
|
||
;
|
||
; Outputs: D3 - bits 31-24: -reserved-
|
||
; 23-16: default OS
|
||
; 15- 8: default device ID (for slots)
|
||
; 7- 0: default partition
|
||
; D4 - default driver reference number
|
||
; D6 - bits: 10: 1=enable X flash next time, 0=flash ? next time
|
||
; 9: 1=mark present (X or ?)
|
||
; 8: 1=flashing enabled, 0=flashing disabled
|
||
; 7- 0: counter for how long to wait before switch from X back to ?
|
||
; A2 - pointer to current drive queue entry (or nil)
|
||
; A3 - pointer to routine to filter out desired drive queue entries
|
||
; flashTime - absolute time at which we next flash the disk icon
|
||
;
|
||
; Trashes: D0-D2, A0-A1
|
||
;
|
||
; Function: initializes the above variables to their default states, preparing for
|
||
; a fresh search to be embarked upon
|
||
;________________________________________________________________________________________
|
||
|
||
EmbarkOnSearch
|
||
|
||
; get the scoop on the default startup device
|
||
|
||
SUBQ.W #4,SP ; make room for parameters on the stack
|
||
MOVE.L SP,A0 ; and point to them
|
||
_GetDefaultStartup ; get info about the default device
|
||
MOVE.L (SP), startPRAM(A4) ; store for later partition check
|
||
MOVE.W (SP)+,D3 ; D3.L = <xx><xx><device-ID><partition>
|
||
MOVE.W (SP)+,D4 ; get the driver's refNum/<slot#><sRsrc#>
|
||
|
||
; get the default OS of startup device
|
||
|
||
SUBQ.W #2,SP ; make room for parameters on the stack
|
||
MOVE.L SP,A0 ; and point to them
|
||
_GetOSDefault ; get info about the default OS
|
||
SWAP D3
|
||
MOVE.W (SP)+,D3
|
||
SWAP D3 ; D3.L = <reserved><OSType><device-ID><partition>
|
||
|
||
; do we have a default drive?
|
||
|
||
cmp.w #NoDefaultVal, D4 ; magic value?
|
||
bne.s @weHaveDefault
|
||
|
||
move.b #1, noDefaultDrive(A4) ; set flag
|
||
clr.b ckPartition(A4) ; we don't want to ck partition number
|
||
bra.s @1
|
||
@weHaveDefault
|
||
clr.b noDefaultDrive(A4) ; we have default
|
||
move.b #1, ckPartition(A4) ; at start, we need to check the partition num
|
||
@1
|
||
clr.b foundDrvr(A4) ; we start off not having found the drvr
|
||
clr.b forcedBoot(A4) ; assume - not a forced boot
|
||
|
||
; initialize the rest of the register variables
|
||
|
||
SUBA.L A2,A2 ; initialize the drive queue pointer
|
||
|
||
LEA IsItFloppyOrDefault,A3 ; ASSUME match default or floppy devices.
|
||
|
||
CASE OBJ
|
||
IMPORT Ck4OnlyLoadFromDefault ; :SCSIMgr4pt3:BootItt.a
|
||
BSR.L Ck4OnlyLoadFromDefault ; supposed to limit our search to default device?
|
||
CASE OFF
|
||
BEQ.S @ck4NoDefault
|
||
LEA IsItDefault, A3 ; match only default device
|
||
@ck4NoDefault
|
||
TST.B noDefaultDrive(A4) ; is there a default drive? <MC2>
|
||
BEQ.S @HaveDefault ; -> yes
|
||
LEA IsItAnything,A3 ; no, match any device
|
||
@HaveDefault
|
||
MOVE.L Ticks,flashTime(A4) ; let flash time expire immediately.
|
||
CLR.W D6 ; clear visual state information.
|
||
|
||
|
||
;--- Initialize SCSIPoll (used to tell StartSearch which ID to wait for)
|
||
; and set up SCSIDrvrs to contain only the CPU's ID bit (so far the only ID we know of)
|
||
; At first, we default to the "internal" drive ID (SCSI ID 0). If not on a portable
|
||
; and the default driver is a valid old-SCSI driver, we use the default startup device number.
|
||
|
||
subq.l #2, sp ; make space for PRAM SCSI id <v1.4>
|
||
move.l sp, A0 ; address of PRAM return buffer
|
||
move.l #$00020002, D0 ; read 2 bytes of PRAM at offset 2
|
||
_ReadXPRam ; get the SCSI IDs of concern
|
||
move.w (sp)+, D0 ;
|
||
and.w #$0707,d0 ; mask all but the ID bits
|
||
move.b D0, SCSIPoll ; initialize hd flag (bit 7=0) & ID
|
||
|
||
TestFor hwCbPwrMgr ; is this a portable?
|
||
bne.s @exit ; yes -> use Internal Drive
|
||
|
||
; Put Default Startup Device number into SCSIPoll - assume no SCSIMgr4pt3 and corresponding
|
||
; multi-bus support. If SCSIMgr4pt3 does run, it will just ignore SCSIPoll. If it
|
||
; doesn't run, SCSIPoll will be used by WaitForPollDrive.
|
||
|
||
move.w D4, D1 ; get refNum (maybe)
|
||
not.w D1 ; convert refNum to unit number
|
||
sub.w #$20, D1 ; convert to SCSI ID
|
||
blt.s @exit ; out of range -> use previous value
|
||
cmpi.w #$07, D1
|
||
bgt.s @exit ; out of range -> use previous value
|
||
|
||
move.b SCSIPoll, D0
|
||
and.b #$F8, D0 ; strip out old internal HD SCSI ID
|
||
or.b D1, D0 ; put in new one
|
||
move.b D0, SCSIPoll ; initialize hd flag (bit 7=0) & ID
|
||
@NoDefault ;
|
||
@exit
|
||
RTS
|
||
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: LoadSlotDrivers
|
||
;
|
||
; Inputs: D3 - bits 31-24: -reserved-
|
||
; 23-16: default OS
|
||
; 15- 8: default device ID (for slots)
|
||
; 7- 0: default partition
|
||
; D4 - may contain a slot number (bits 8-15) and sRsrc ID (bits 0-7),
|
||
; if not, the routine just exits
|
||
;
|
||
; Outputs: D4 - default driver reference number, or zero if none
|
||
;
|
||
; Trashes: D0-D2, A0-A1
|
||
;
|
||
; Function: If D4 specifies a slot device, use it to load and execute boot code. If a
|
||
; Mac OS is to be booted, then a driver will be loaded and execution will
|
||
; continue here, otherwise a different OS will be brought up, so we're done.
|
||
;________________________________________________________________________________________
|
||
|
||
LoadSlotDrivers
|
||
WITH spBlock,seBlock
|
||
|
||
TST.B noDefaultDrive(A4) ; is there a default device?
|
||
BNE.S @exit ; no -> out of here
|
||
|
||
; Test for slot device.
|
||
|
||
TST.W D4 ;Is this a real slot device?
|
||
BLE.S @Exit ;Branch if not (n=0,n<0 => not slot)
|
||
; note: even tho newSCSI uses slot 0, we
|
||
; don't have any sRsrc to load so we exit
|
||
; Find the default sResource.
|
||
|
||
LEA -spBlockSize(SP),SP ;Allocate parameter block for SDM calls.
|
||
MOVE.L SP,A0
|
||
|
||
LEA -seBlockSize(SP),SP ;Allocate parameter block for code executed by _sExec.
|
||
MOVE.L SP,A1
|
||
MOVE.L A1,spsExecPBlk(A0)
|
||
|
||
MOVE.B D4,spId(A0) ;Default Id,
|
||
LSR.W #8,D4
|
||
MOVE.B D4,spSlot(A0) ;Default Slot,
|
||
_sFindsRsrcPtr ;Get a pointer to the sResource list
|
||
BNE.S @Fail ;Branch if error
|
||
|
||
; Set the parameters for the code in sExec.
|
||
|
||
MOVE.B spSlot(A0),seSlot(A1) ;Default Slot,
|
||
MOVE.B spId(A0),sesRsrcId(A1) ;Default sResource.
|
||
|
||
MOVE.L D3,D0 ;Boot code extensions.
|
||
MOVE.B D0,sePartition(A1) ;Default Partition,
|
||
LSR.L #8,D0
|
||
MOVE.B D0,seDevice(A1) ;Default Device, and
|
||
LSR.L #8,D0
|
||
MOVE.B D0,seOSType(A1) ;Default OS.
|
||
LSR.L #8,D0
|
||
MOVE.B D0,seReserved(A1) ;Reserved field.
|
||
MOVE.B #sbState0,seBootState(A1) ;State of StartBoot code.
|
||
|
||
; Execute the code in the sBoot record.
|
||
|
||
MOVE.B #sRsrcBootRec,spId(A0) ;Execute the code:
|
||
_sExec ; On entry to the boot code, A0 points to the SE parameter block.
|
||
BNE.S @Fail ;Branch if fail.
|
||
|
||
TST.W seStatus(A1) ;Test the status of the sLoad code
|
||
BNE.S @Fail ;Branch if error
|
||
|
||
@Good MOVE.W seRefNum(A1),D4 ;Set D4 to default RefNum.
|
||
@End LEA spBlockSize+seBlockSize(SP),SP ;Deallocate parameter blocks.
|
||
|
||
@Exit RTS
|
||
|
||
@Fail CLR.W D4 ;Clear default (match any device)
|
||
BRA.S @End ;Good, now exit.
|
||
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: LoadSCSIDrivers
|
||
;
|
||
; Inputs: D3 - bits 31-24: -reserved-
|
||
; 23-16: default OS
|
||
; 15- 8: default device ID (for slots)
|
||
; 7- 0: default partition
|
||
; D4 - default driver reference number
|
||
;
|
||
; Outputs: D3 - bits 31-24: -reserved-
|
||
; 23-16: default OS
|
||
; 15- 8: default device ID (for slots)
|
||
; 7- 0: default partition
|
||
; D4 - default driver reference number
|
||
;
|
||
; Trashes: D0-D2, A0-A1
|
||
;
|
||
; Function: loads more SCSI device drivers from the devices themselves, if they're available
|
||
;________________________________________________________________________________________
|
||
|
||
LoadSCSIDrivers
|
||
IF hasAsyncSCSI THEN
|
||
BSR.L ISITT ; check if we're running SCSI 4.3
|
||
TST.B D0 ; are we?
|
||
BEQ.S @UseOldSCSI ; -> no, use the old code to load drivers
|
||
|
||
PEA forcedBoot(A4) ; ptr to flag indicating a forcedBoot
|
||
CLR.L -(SP) ; load all drivers
|
||
BSR.L ITTBOOT ; Load Drivers and look for startup disk
|
||
ADDQ.W #8,SP ; (clean up the stack)
|
||
|
||
tst.b forcedBoot(A4) ; was it a forced boot?
|
||
beq.s @1 ; no -> nothing special
|
||
clr.b ckPartition(A4) ; yes:don't ck part'n (for a different drvr)
|
||
@1
|
||
tst.w d0 ; did we get a startup disk?
|
||
bge.s @StageLeft ; nope, exit
|
||
move.w D0, D4 ; yep, change d4 to reflect that
|
||
@StageLeft
|
||
RTS
|
||
@UseOldSCSI
|
||
ENDIF
|
||
|
||
; there is a new mechanism to disable loading of poll drive, so, check power
|
||
; user command, "command, shift, option and delete keys", if those keys are
|
||
; not down, go load the poll drive.
|
||
; Make sure that command, shift, option and delete keys are not down
|
||
|
||
MOVEQ #-1,D0 ; try to load all SCSI devices
|
||
CMPI.W #CmdShiftOptDel,KeyMap+6 ; are command, shift, option and delete keys down?
|
||
BNE.S @GoLoadD ; -> no, continue
|
||
MOVEQ #$07,D1
|
||
AND.B SCSIPoll,D1 ; get the SCSI ID of the poll drive
|
||
BCLR D1,D0 ; and clear the bit in the available drive list
|
||
|
||
@GOLoadD move.l d6,-(sp) ; save d6 <LW3>pdw
|
||
move.l a0,-(sp) ; save a0
|
||
moveq.l #0, D6 ; allow drivers to munge heap <LW3>pdw
|
||
BSR.L SCSILoad ; try to load driver(s) from disk
|
||
move.l (sp)+,a0 ; restore a0
|
||
move.l (sp)+,d6 ; restore d6 <LW3>pdw
|
||
RTS
|
||
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: WaitForPollDrive
|
||
;
|
||
; Inputs: none
|
||
;
|
||
; Outputs: none
|
||
;
|
||
; Trashes: D0-D2, A0-A1
|
||
;
|
||
; Function: Waits until the poll hard disk has had a chance to warm up.
|
||
; If it doesn't appear after the recommended amount of time, it
|
||
; is assumed absent and parameter RAM is updated accordingly.
|
||
;________________________________________________________________________________________
|
||
|
||
WaitForPollDrive
|
||
MOVEM.L A2/D5,-(SP) ; Save my registers.
|
||
|
||
; make sure the poll wait feature is enabled.
|
||
|
||
_GetWaitFlags ; get the current flags
|
||
AND.B #DynWaitMask,D0 ; and mask off the dynamic flag
|
||
BNE @RawExit ; -> exit if dynamic wait is disabled
|
||
|
||
; get the timeout value and convert it to ticks
|
||
|
||
_GetTimeOut ; get the timeout parameter
|
||
BNE.S @UseGivenTime ; -> use the returned parameter
|
||
MOVEQ #DefaultTimeOut,D0 ; no parameter returned, so use the default timeout.
|
||
@UseGivenTime
|
||
MOVEQ #60,D5 ; convert the timeout to ticks
|
||
MULU D0,D5 ; and save it
|
||
|
||
; We now disable waiting for the poll device in the future.
|
||
; This way, if loading the driver causes a crash, then next time
|
||
; the system boots, it won't wait for it.
|
||
; The waiting feature gets re-enabled if no crash occurs.
|
||
|
||
_DisablePermWait ; Disable permanent wait in case driver crashes
|
||
|
||
|
||
@WaitForIt
|
||
|
||
IF hasAsyncSCSI THEN
|
||
BSR.L ISITT ; check if we're running SCSI 4.3
|
||
TST.B D0 ; are we?
|
||
BEQ.S @UseOldSCSI ; -> no, use the old code to load drivers
|
||
PEA forcedBoot(A4) ; ptr to flag indicating a forcedBoot
|
||
PEA 1 ; only look for the startup device
|
||
BSR.L ITTBOOT ; get the startup device's refnum in D0
|
||
ADDQ.W #8,SP ; (clean up the stack)
|
||
|
||
tst.b forcedBoot(A4) ; was it a forced boot?
|
||
beq.s @1 ; no -> nothing special
|
||
clr.b ckPartition(A4) ; yes:don't ck part'n (for a different drvr)
|
||
@1
|
||
CMP.W #1, D0 ; CmdShiftOptDel or Nonbootable?
|
||
BEQ.S @RawExit ; yes -> don't wait no more
|
||
TST.W D0 ; no: did we get a drive?
|
||
BEQ.S @ckTimeout ; no -> check timeout and loop
|
||
MOVE.W D0, D4 ; yes: go with it
|
||
BRA.B @MyExit ;
|
||
@UseOldSCSI
|
||
ENDIF
|
||
|
||
; make sure that command, shift, option and delete keys are not down
|
||
|
||
MOVE.W KeyMap+6,D0 ; get keys down
|
||
CMP.W #CmdShiftOptDel,D0 ; are command, shift, option and delete keys down?
|
||
BEQ.S @RawExit ; -> exit if so
|
||
|
||
MOVEQ #$07,D1
|
||
AND.B SCSIPoll,D1 ; Get SCSI ID of poll drive
|
||
MOVEQ #0,D0 ; Clear register
|
||
BSET D1,D0 ; Set the bit for the drive
|
||
|
||
; Call SCSILoad with bit map in D0 and heap_munge_flag in D6
|
||
|
||
move.l d6,-(sp) ; save d6 <LW3>pdw
|
||
move.l a0,-(sp) ; save a0
|
||
moveq.l #0, D6 ; allow drivers to munge heap <LW3>pdw
|
||
BSR.L SCSILoad ; Try to load driver for poll disk
|
||
move.l (sp)+,a0 ; restore a0
|
||
move.l (sp)+,d6 ; restore d6 <LW3>pdw
|
||
BEQ.S @MyExit ; Branch if warmed up, but driver is invalid
|
||
|
||
MOVEQ #IntHDRefNum,D0 ; Refnum for ID 0
|
||
SUB.W SCSIPoll,D0 ; Convert to refnum for poll drive
|
||
MOVE.W D0,D1 ; Put back in D1 for comparison
|
||
|
||
|
||
; Let's see if the poll hard disk is actually in the queue
|
||
@ExamDQ SUBA.L A2,A2 ; Start at beginning of drive queue
|
||
@FindIntHD
|
||
BSR NextDQEntry ; Get the next drive queue entry
|
||
BEQ.S @EndOfQueue ; Branch if we're out of queue entries
|
||
|
||
CMP.W dqRefNum(A2),D1 ; Is it our trusty poll hard disk?
|
||
|
||
BNE.S @FindIntHD ; Nope, see if the next one's it
|
||
|
||
@Warm_n_Toasty ; We found the drive; it must have warmed up
|
||
BRA.S @MyExit ; That's all folks
|
||
|
||
@ckTimeout
|
||
@EndOfQueue
|
||
CMP.L Ticks,D5 ; Should the poll HD be visible by now?
|
||
BLO.S @NoDrivePresent ; Yes, so quit waiting for it
|
||
MOVEQ.L #PollDelay,D0 ; Get number of ticks to wait before retrying
|
||
ADD.L Ticks,D0 ; Calculate new time to try it again
|
||
@DelayLoop
|
||
CMP.L Ticks,D0 ; Time to try again?
|
||
BHS.S @DelayLoop ; No, so just be patient
|
||
BRA.S @WaitForIt ; Ready to try the poll drive again
|
||
|
||
@NoDrivePresent ; Time expired, drive must not be there
|
||
_DisableDynWait ; Drive not found, disable dynamic wait
|
||
|
||
@MyExit
|
||
_EnablePermWait ; No crash, re-enable disk wait
|
||
|
||
@RawExit
|
||
MOVEM.L (SP)+,A2/D5 ; Restore my registers
|
||
RTS ; Return to the world
|
||
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: FindNextCandidate
|
||
;
|
||
; Inputs: A2 - Points to the drive queue entry which was tried last time; the search
|
||
; for an appropriate device will begin with the NEXT drive queue entry.
|
||
; A nil pointer means you wish to search from the beginning of the queue.
|
||
;
|
||
; Outputs: A2 - pointer to the next appropriate drive queue entry found
|
||
; A3 - pointer to a subroutine which returns BEQ if A2 is pointing to a drive
|
||
; queue entry that we are interested in, otherwise it returns BNE. All
|
||
; registers except D0/A2 are passed through to the subroutine untouched
|
||
; (A2 points to the "next" queue entry). The subroutine must preserve
|
||
; all registers except D0-D2/A0-A1.
|
||
; CCR - BNE if we found an appropriate entry, BEQ if we've reached the end of the queue
|
||
;
|
||
; Trashes: D0-D2, A0-A1
|
||
;
|
||
; Function: finds the next possible startup device
|
||
;________________________________________________________________________________________
|
||
|
||
FindNextCandidate
|
||
BSR.S NextDQEntry ; Find the next drive queue entry.
|
||
BNE.S @ckThisOut ; valid -> check out the drive
|
||
; not: we've searched the whole queue.
|
||
tst.b ckPartition(A4) ; were we looking for right partition
|
||
beq.s @DoneLooking ; no-> return to scan bus some more
|
||
tst.b foundDrvr(A4) ; did we see a drive for the default drvr?
|
||
beq.s @DoneLooking ; no-> return to scan bus some more
|
||
clr.b ckPartition(A4) ; yes: no longer look for right partition
|
||
bra.s FindNextCandidate ; and search the DrvQ again
|
||
|
||
@ckThisOut
|
||
MOVE.W dqDrive(A2),D1 ; get the drive number
|
||
CMPI.W #15,D1 ; is it in range?
|
||
BHI.S @OuttaRange ; -> no, try it regardless
|
||
MOVE.W BootMask,D0 ; get failure info
|
||
BTST D1,D0 ; is this drive one we've rejected before?
|
||
BEQ.S FindNextCandidate ; -> yes, skip it
|
||
|
||
@OuttaRange JSR (A3) ; is this one of the devices we're looking for?
|
||
BNE.S FindNextCandidate ; -> no, keep looking
|
||
@DoneLooking
|
||
MOVE.L A2,D0 ; Return result.
|
||
RTS
|
||
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: NextDQEntry
|
||
;
|
||
; Inputs: A2 - points to the drive queue entry which was tried last time (nil if
|
||
; at the end of the queue)
|
||
;
|
||
; Outputs: A2 - pointer to the next drive queue entry (nil if at the end of the queue)
|
||
; CCR - BEQ if we're reached the end of the queue, BNE if A2 is valid
|
||
;
|
||
; Trashes: D0
|
||
;
|
||
; Function: advances A2 to point to the next drive queue entry. If the pointer is nil,
|
||
; point to the start of the queue
|
||
;________________________________________________________________________________________
|
||
|
||
NextDQEntry MOVE.L A2,D0 ; is the pointer NIL?
|
||
BNE.S @NextEntry ; -> no, more entries left in the queue
|
||
LEA DrvQHdr+QHead,A2 ; point to the head of the queue
|
||
@NextEntry MOVE.L qLink(A2),A2 ; point to next entry
|
||
MOVE.L A2,D0 ; test for end of queue
|
||
RTS
|
||
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: SelectDevice
|
||
;
|
||
; Inputs: A2 - points to the current drive queue entry
|
||
;
|
||
; Outputs: A0 - pointer to A6-based I/O parameter block
|
||
; A2 - points to the current drive queue entry
|
||
; BtDskRfn contains the driver reference number of the startup device
|
||
; BootDrive contains the drive number of the startup device
|
||
;
|
||
; Trashes: D0
|
||
;
|
||
; Function: sets up variables to make the current device the startup device
|
||
;________________________________________________________________________________________
|
||
|
||
SelectDevice
|
||
LEA MyIOPBA6(A6),A0 ; Point to my parameter block
|
||
|
||
MOVE.W dqRefNum(A2),D0 ; Get driver reference number.
|
||
MOVE.W D0,IORefNum(A0) ; Put it in parameter block.
|
||
MOVE.W D0,BtDskRfn ; Save RefNum in case this is boot device.
|
||
|
||
MOVE.W dqDrive(A2),D0 ; Get drive number.
|
||
MOVE.W D0,IODrvNum(A0) ; Put it in param block.
|
||
MOVE.W D0,BootDrive ; Save DrvNum in case this is boot device.
|
||
RTS
|
||
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: CheckMouseEject
|
||
;
|
||
; Inputs: A0 - pointer to A6-based I/O parameter block
|
||
;
|
||
; Outputs: CCR - BEQ if the disk was ejected
|
||
;
|
||
; Trashes: D0
|
||
;
|
||
; Function: ejects the disk from the current device if the mouse button is down
|
||
;________________________________________________________________________________________
|
||
|
||
CheckMouseEject
|
||
TST.B MBState ; does user want eject?
|
||
BMI.S DontEject ; -> no, skip
|
||
; fall thru into EjectMe
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: EjectMe
|
||
;
|
||
; Inputs: A0 - pointer to A6-based I/O parameter block
|
||
;
|
||
; Outputs: CCR - BEQ if the disk was ejected
|
||
;
|
||
; Trashes: D0
|
||
;
|
||
; Function: ejects the disk from the current device
|
||
;________________________________________________________________________________________
|
||
|
||
EjectMe LEA MyIOPBA6(A6),A0 ; Point to my parameter block
|
||
MOVE.W #EjectCode,csCode(A0)
|
||
_Control ; Issue an eject command to the device
|
||
DontEject RTS ; Return with status
|
||
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: GetStartupInfo
|
||
;
|
||
; Inputs: A0 - pointer to A6-based I/O parameter block
|
||
; A6 - pointer to buffer for holding the boot blocks
|
||
;
|
||
; Outputs: CCR - BEQ if the blocks were read successfully and they're boot blocks
|
||
;
|
||
; Trashes: D0
|
||
;
|
||
; Function: reads the boot blocks from the current device
|
||
;________________________________________________________________________________________
|
||
|
||
GetStartupInfo
|
||
MOVE.W #1,IOPosMode(A0) ; position relative to start
|
||
CLR.L IOPosOffset(A0) ; start at byte position 0
|
||
MOVE.L A6,IOBuffer(A0) ; load boot blocks at (A6)
|
||
MOVE.L #$400,IOReqCount(A0) ; two 512-byte blocks
|
||
_Read ; read the boot blocks
|
||
BNE.S @Exit ; -> error, so exit
|
||
move.l a0,-(sp)
|
||
BSR.L CacheFlush ; flush the caches
|
||
move.l (sp)+,a0
|
||
CMP.W #'LK',(A6) ; check if it's a true boot block
|
||
@Exit RTS ; and return BEQ if so
|
||
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: ReactToFailure
|
||
;
|
||
; Inputs: D0 - error code indicating what went wrong
|
||
; D4 - default device's driver reference number
|
||
;
|
||
; Outputs: D6 - may have the XEnable bit set
|
||
; BootMask is modified to prevent retries to the current device
|
||
;
|
||
; Trashes: D0-D1
|
||
;
|
||
; Function: responds to a failure to read the boot blocks correctly (this may include
|
||
; ejecting the disk)
|
||
;________________________________________________________________________________________
|
||
|
||
ReactToFailure
|
||
CMP.W #OffLinErr,D0 ; is the disk present and up to speed?
|
||
BEQ.S @Exit ; -> no, leave it alone so we can try it later
|
||
CMP.W #NoDriveErr,D0 ; is the drive present?
|
||
BEQ.S @This1NoMo ; -> no, don't talk to it again
|
||
BSR.S EjectMe ; for any other error, eject the device
|
||
BEQ.S @ShowMe ; -> its ejectable, so we can try it again
|
||
|
||
@This1NoMo MOVE.W dqDrive(A2),D1 ; get the drive number
|
||
CMPI.W #15,D1 ; is it in range?
|
||
BHI.S @ShowMe ; -> skip if not
|
||
MOVE.W BootMask,D0 ; get failure info
|
||
BCLR D1,D0 ; disable this device
|
||
MOVE.W D0,BootMask ; and update the failure info
|
||
|
||
@ShowMe BSR IsItFloppy ; is it a floppy that failed?
|
||
BNE.S @Exit ; -> no, don't do anything special
|
||
BSET #XEnable,D6 ; enable the flashing X on the disk icon
|
||
@Exit RTS
|
||
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: Ck4SupportsPartition
|
||
;
|
||
; Inputs: A2 - pointer to the current drive queue entry (must not be nil!)
|
||
; D4 - default device's driver reference number
|
||
;
|
||
; Outputs: CCR - BEQ if the current device support the partition field of PRAM
|
||
; D0 - long returned by driver to check against startPRAM
|
||
;
|
||
; Trashes: D0-D2/A0-A1
|
||
;
|
||
; Function: determines whether the current drive queue entry is the default boot device
|
||
;________________________________________________________________________________________
|
||
|
||
Ck4SupportsPartition
|
||
;
|
||
; Get the DCE using the Device Manager's statusGetDCE call
|
||
;
|
||
lea csPB(A4), A0 ; point to pb
|
||
move.w D4, ioRefNum(A0) ; pass driver refNum
|
||
move.w #statusGetDCE, csCode(A0) ; (Device Mgr call, not driver)
|
||
_Status
|
||
movea.l csParam(A0), A0 ; get DCE handle (doesn’t touch CCR)
|
||
bmi @notSupported ; no such Driver (i.e. DCE not installed)
|
||
|
||
;
|
||
; now check this driver to see if it "follows new rules" and responds
|
||
; to driverGestalt status call
|
||
;
|
||
move.w dCtlFlags(A0), D0 ; does it Follow New Rules?
|
||
btst #FollowsNewRules, D0 ; (word-relative bit #)
|
||
beq.s @notSupported ; no -> skip driverGestalt call
|
||
|
||
lea csPB(A4), A0 ; point to it
|
||
move.w #driverGestaltCode, csCode(A0)
|
||
move.l #'boot', DriverGestaltParam.driverGestaltSelector(A0)
|
||
|
||
move.w dqDrive(A2), ioVRefNum(A0) ; put drive q num in ioVRefNum
|
||
move.w D4, ioRefNum(A0)
|
||
_Status ; make driverGestalt call
|
||
tst.w D0
|
||
bne.s @notSupported
|
||
move.l DriverGestaltParam.driverGestaltResponse(A0), D0
|
||
|
||
@exit
|
||
cmp.l #NoDefaultVal, D0 ; set Z if not supported
|
||
rts
|
||
|
||
@notSupported
|
||
clr.b ckPartition(A4) ; no longer look for right partition
|
||
move.l #NoDefaultVal, D0
|
||
bra.s @exit
|
||
|
||
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: IsItDefault
|
||
;
|
||
; Inputs: A2 - pointer to the current drive queue entry (must not be nil!)
|
||
; D4 - default device's driver reference number
|
||
;
|
||
; Outputs: CCR - BEQ if the current device is the default device
|
||
;
|
||
; Trashes: none
|
||
;
|
||
; Function: determines whether the current drive queue entry is the default boot device
|
||
;________________________________________________________________________________________
|
||
|
||
IsItDefault
|
||
cmp.w dqRefNum(A2), D4 ; is this driver for the default device?
|
||
bne.s @notTheDisk ; no-> definitely no the disk then
|
||
|
||
move.b #1, foundDrvr(A4) ; so we know to clr ckPartition if end-of-Q
|
||
tst.b ckPartition(A4) ; do we need to check the partition num?
|
||
beq.s @isTheDisk ; no-> well then, it is the right disk
|
||
|
||
bsr Ck4SupportsPartition ; does driver support partition info?
|
||
beq.s @isTheDisk ; no-> then this is the right volume
|
||
|
||
cmp.l startPRAM(A4), D0 ; yes: does returned boot value eq pram?
|
||
beq.s @isTheDisk ; yes-> selected disk
|
||
@notTheDisk
|
||
moveq.l #1, D0
|
||
rts
|
||
@isTheDisk
|
||
moveq.l #0, D0
|
||
@exit
|
||
rts ; return result of compare
|
||
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: IsItFloppyOrDefault
|
||
;
|
||
; Inputs: A2 - pointer to the current drive queue entry (must not be nil!)
|
||
; D4 - default device's driver reference number
|
||
;
|
||
; Outputs: CCR - BEQ if the current device is a floppy or the default device
|
||
;
|
||
; Trashes: none
|
||
;
|
||
; Function: determines whether the current drive queue entry is either a floppy or
|
||
; the default boot device
|
||
;________________________________________________________________________________________
|
||
|
||
IsItFloppyOrDefault
|
||
bsr.s IsItDefault
|
||
beq.s @exit
|
||
bsr.s IsItFloppy
|
||
@exit rts
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: IsItFloppy
|
||
;
|
||
; Inputs: A2 - pointer to the current drive queue entry (must not be nil!)
|
||
; D4 - default device's driver reference number
|
||
;
|
||
; Outputs: CCR - BEQ if the current device is a floppy
|
||
;
|
||
; Trashes: none
|
||
;
|
||
; Function: determines whether the current drive queue entry is a floppy
|
||
;________________________________________________________________________________________
|
||
|
||
IsItFloppy CMPI.W #FloppyRefNum,dqRefNum(A2) ; check if this drive is a floppy
|
||
ItsDefault RTS ; and return BEQ if so
|
||
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: IsItAnything
|
||
;
|
||
; Inputs: A2 - pointer to the current drive queue entry (must not be nil!)
|
||
; D4 - default device's driver reference number
|
||
;
|
||
; Outputs: CCR - always BEQ
|
||
;
|
||
; Trashes: none
|
||
;
|
||
; Function: always returns true to let all devices be accepted as startup candidates
|
||
;________________________________________________________________________________________
|
||
|
||
IsItAnything
|
||
CMP D0,D0 ; return BEQ
|
||
RTS
|
||
|
||
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: VisualUpdate
|
||
;
|
||
; Inputs: flashTime(A4) - the absolute time of the next flash of the ? or X
|
||
; D6 - the current state of the icons on the screen
|
||
; bits: 10: 1=enable X flash next time, 0=flash ? next time
|
||
; 9: 1=mark present (X or ?)
|
||
; 8: 1=flashing enabled, 0=flashing disabled
|
||
; 7- 0: counter for how long to wait before switch from X back to ?
|
||
;
|
||
; Outputs: same as inputs
|
||
;
|
||
; Trashes: D0-D2, A0-A1
|
||
;
|
||
; Function: keeps the user interface magic alive: flashes the disk icon when appropriate
|
||
;________________________________________________________________________________________
|
||
|
||
VisualUpdate
|
||
; Prevent a visual glitch if device is ready right away.
|
||
BSET #FlashEnable,D6 ; Enable flashing icon.
|
||
BEQ.S @DoneDisk ; Branch if previously disabled.
|
||
|
||
MOVE.L flashTime(A4), D0
|
||
CMP.L Ticks, D0 ; Is it time to flash?
|
||
BHI.S @DoneDisk ; Branch if not.
|
||
|
||
MOVE.L Ticks, flashTime(A4) ; Get current time.
|
||
ADD.L #FlashTicks, flashTime(A4) ; Compute next time to flash.
|
||
|
||
BCLR #XEnable,D6 ; Disable XEnable for next time;
|
||
; Should we enable it for this time?
|
||
BEQ.S @NoSwitch ; Branch if not
|
||
|
||
MOVE.B #NumFlashX,D6 ; Enable X flash by getting its count.
|
||
|
||
@NoSwitch BCHG #FlashParity,D6 ; Switch parity.
|
||
BNE.S @XorQ ; Branch if we need X or ? showing.
|
||
LEA DiskIcon,A0 ; plot the plain disk icon
|
||
BRA.S PlotMyIcon
|
||
|
||
@XorQ TST.B D6 ; Are we showing an ?
|
||
BEQ.S @ShowQ ; Branch if so.
|
||
SUBQ.B #1,D6 ; Eventually, we go back to a ?.
|
||
LEA XDiskIcon,A0 ; but for now, plot the disk icon with the X
|
||
BRA.S PlotMyIcon
|
||
|
||
@ShowQ LEA QDiskIcon,A0 ; plot the disk icon with the question mark
|
||
BRA.S PlotMyIcon
|
||
|
||
@DoneDisk RTS
|
||
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: HappyMac
|
||
;
|
||
; Inputs: none
|
||
;
|
||
; Outputs: none
|
||
;
|
||
; Trashes: D0-D2, A0-A1
|
||
;
|
||
; Function: displays the Happy Mac icon, centered on the main video device
|
||
;________________________________________________________________________________________
|
||
|
||
HappyMac BSR.S EraseMyIcon ; erase what's on the screen where the icon goes
|
||
LEA HappyIcon,A0 ; plot the happy mac icon
|
||
BSR.S PlotMyIcon
|
||
RTS
|
||
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: EraseMyIcon
|
||
;
|
||
; Inputs: none
|
||
;
|
||
; Outputs: none
|
||
;
|
||
; Trashes: none
|
||
;
|
||
; Function: erases the ICN# in the center of the main screen
|
||
;________________________________________________________________________________________
|
||
|
||
EraseMyIcon MOVEM.L D0-D2/A0-A1,-(SP)
|
||
BSR.S PushIconRect ; push the icon's rectangle onto the stack
|
||
MOVE.L SP,-(SP) ; and point to it
|
||
MOVE.L grafGlobals(A5),A0 ; point to the QuickDraw globals
|
||
PEA gray(A0) ; and use 50% gray as the background
|
||
_FillRect ; erase the rectangle with the desktop pattern
|
||
ADDQ.W #8,SP ; clean up the stack
|
||
MOVEM.L (SP)+,D0-D2/A0-A1
|
||
RTS
|
||
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: PlotMyIcon
|
||
;
|
||
; Inputs: A0 - pointer to ICN# to plot
|
||
;
|
||
; Outputs: none
|
||
;
|
||
; Trashes: D0-D2, A0-A1
|
||
;
|
||
; Function: plots an icon, centered on the main video device
|
||
;________________________________________________________________________________________
|
||
|
||
PlotMyIcon MOVE.L A0,D2 ; save the pointer to the ICN#
|
||
|
||
; put the source bitmap on the stack (icon's bit image)
|
||
|
||
BSR.S PushIconRect ; bounds = 32x32 rectangle, centered on the main screen
|
||
MOVE.W #32/8,-(SP) ; rowBytes
|
||
MOVE.L D2,-(SP) ; baseAddr = pointer to the icon
|
||
|
||
; put the mask bitmap on the stack (icon's mask image)
|
||
|
||
LEA bitMapRec(SP),A0 ; point to the end of this bitmap so we can make a copy
|
||
MOVE.L -(A0),-(SP) ; bounds
|
||
MOVE.L -(A0),-(SP)
|
||
MOVE.W -(A0),-(SP) ; rowBytes
|
||
MOVEA.L -(A0),A1
|
||
PEA 128(A1) ; baseAddr = pointer to icon's mask
|
||
|
||
; now copy the icon to the screen using CopyMask...
|
||
|
||
MOVE.L A0,-(SP) ; srcBits
|
||
PEA 4(SP) ; maskBits
|
||
MOVEA.L grafGlobals(A5),A1 ; point to QuickDraw's globals
|
||
MOVEA.L thePort(A1),A1 ; and from there get the current grafport
|
||
PEA portBits(A1) ; dstBits
|
||
PEA bounds(A0) ; srcRect
|
||
MOVE.L (SP),-(SP) ; maskRect
|
||
MOVE.L (SP),-(SP) ; dstRect
|
||
_CopyMask ; blast it
|
||
|
||
LEA 2*bitmapRec(SP),SP ; clean up the stack
|
||
RTS
|
||
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: PushIconRect
|
||
;
|
||
; Inputs: none
|
||
;
|
||
; Outputs: none
|
||
;
|
||
; Trashes: D0-D1, A0-A1
|
||
;
|
||
; Function: pushes a 32x32 rectangle on the stack, and then centers it on the main screen
|
||
;________________________________________________________________________________________
|
||
|
||
PushIconRect
|
||
MOVEA.L (SP)+,A0 ; pop the return address
|
||
MOVE.L #(32<<16)+32,-(SP) ; push an icon rect (0,0,32,32) on the stack
|
||
CLR.L -(SP)
|
||
MOVEA.L SP,A1 ; and point to it
|
||
|
||
MOVE.L A0,-(SP) ; push the return address back on the stack
|
||
|
||
MOVE.L grafGlobals(A5),A0 ; point to QuickDraw globals
|
||
LEA screenBits+bounds(A0),A0 ; and use the screen's rectangle as a guide
|
||
BSR.S @TranslateEdge ; translate the top and bottom edges
|
||
* BRA.S @TranslateEdge ; translate the left and right edges
|
||
NOP ; (we need this otherwise the assembler barfs on the BSR.S)
|
||
|
||
@TranslateEdge
|
||
MOVE.W bottom-top(A0),D0 ; calculate the height or width
|
||
SUB.W (A0),D0 ; of the guide rect
|
||
|
||
MOVE.W bottom-top(A1),D1 ; calculate the height or width
|
||
SUB.W (A1),D1 ; of the rect to be centered
|
||
|
||
SUB.W D1,D0 ; calculate how much to shift the position
|
||
ASR.W #1,D0 ; of the rect to be centered (half the difference)
|
||
|
||
ADD.W (A0)+,D0 ; calculate the new top or left edge
|
||
MOVE.W D0,(A1)+ ; of the rect to be centered
|
||
|
||
ADD.W D1,D0 ; do the same for the bottom or right edge
|
||
MOVE.W D0,bottom-top-2(A1)
|
||
RTS
|
||
|
||
|
||
;---------------------------------------------------------------------------------------------
|
||
; The ICN# bitmaps (icon and mask).
|
||
;---------------------------------------------------------------------------------------------
|
||
|
||
HappyIcon DC.L $07FFFFC0,$08000020,$10000010,$11FFFF10,$12000090,$12000090,$12000090,$12111090
|
||
DC.L $12111090,$12010090,$12010090,$12030090,$12000090,$12084090,$12078090,$12000090
|
||
DC.L $12000090,$11FFFF10,$10000010,$10000010,$10000010,$10000010,$13003F10,$10000010
|
||
DC.L $10000010,$10000010,$10000010,$0FFFFFE0,$08000020,$08000020,$08000020,$0FFFFFE0
|
||
|
||
DC.L $07FFFFC0,$0FFFFFE0,$1FFFFFF0,$1FFFFFF0,$1FFFFFF0,$1FFFFFF0,$1FFFFFF0,$1FFFFFF0
|
||
DC.L $1FFFFFF0,$1FFFFFF0,$1FFFFFF0,$1FFFFFF0,$1FFFFFF0,$1FFFFFF0,$1FFFFFF0,$1FFFFFF0
|
||
DC.L $1FFFFFF0,$1FFFFFF0,$1FFFFFF0,$1FFFFFF0,$1FFFFFF0,$1FFFFFF0,$1FFFFFF0,$1FFFFFF0
|
||
DC.L $1FFFFFF0,$1FFFFFF0,$1FFFFFF0,$0FFFFFE0,$0FFFFFE0,$0FFFFFE0,$0FFFFFE0,$0FFFFFE0
|
||
|
||
DiskIcon DC.L $7FFFFFF0,$81000108,$81007104,$81008902,$81008901,$81008901,$81008901,$81008901
|
||
DC.L $81007101,$81000101,$80FFFE01,$80000001,$80000001,$80000001,$87FFFFE1,$88000011
|
||
DC.L $88000011,$88000011,$88000011,$88000011,$88000011,$88000011,$88000011,$88000011
|
||
DC.L $88000011,$88000011,$88000011,$88000011,$88000011,$88000011,$88000011,$FFFFFFFE
|
||
|
||
DC.L $7FFFFFF0,$FFFFFFF8,$FFFFFFFC,$FFFFFFFE,$FFFFFFFF,$FFFFFFFF,$FFFFFFFF,$FFFFFFFF
|
||
DC.L $FFFFFFFF,$FFFFFFFF,$FFFFFFFF,$FFFFFFFF,$FFFFFFFF,$FFFFFFFF,$FFFFFFFF,$FFFFFFFF
|
||
DC.L $FFFFFFFF,$FFFFFFFF,$FFFFFFFF,$FFFFFFFF,$FFFFFFFF,$FFFFFFFF,$FFFFFFFF,$FFFFFFFF
|
||
DC.L $FFFFFFFF,$FFFFFFFF,$FFFFFFFF,$FFFFFFFF,$FFFFFFFF,$FFFFFFFF,$FFFFFFFF,$FFFFFFFE
|
||
|
||
QDiskIcon DC.L $7FFFFFF0,$81000108,$81007104,$81008902,$81008901,$81008901,$81008901,$81008901
|
||
DC.L $81007101,$81000101,$80FFFE01,$80000001,$80000001,$80000001,$87FFFFE1,$88000011
|
||
DC.L $88000011,$8807E011,$880FF011,$880C3011,$880C3011,$88007011,$8800E011,$8801C011
|
||
DC.L $88018011,$88018011,$88000011,$88018011,$88018011,$88000011,$88000011,$FFFFFFFE
|
||
|
||
DC.L $7FFFFFF0,$FFFFFFF8,$FFFFFFFC,$FFFFFFFE,$FFFFFFFF,$FFFFFFFF,$FFFFFFFF,$FFFFFFFF
|
||
DC.L $FFFFFFFF,$FFFFFFFF,$FFFFFFFF,$FFFFFFFF,$FFFFFFFF,$FFFFFFFF,$FFFFFFFF,$FFFFFFFF
|
||
DC.L $FFFFFFFF,$FFFFFFFF,$FFFFFFFF,$FFFFFFFF,$FFFFFFFF,$FFFFFFFF,$FFFFFFFF,$FFFFFFFF
|
||
DC.L $FFFFFFFF,$FFFFFFFF,$FFFFFFFF,$FFFFFFFF,$FFFFFFFF,$FFFFFFFF,$FFFFFFFF,$FFFFFFFE
|
||
|
||
XDiskIcon DC.L $7FFFFFF0,$81000108,$81007104,$81008902,$81008901,$81008901,$81008901,$81008901
|
||
DC.L $81007101,$81000101,$80FFFE01,$80000001,$80000001,$80000001,$87FFFFE1,$88000011
|
||
DC.L $88000011,$88100811,$88381C11,$881C3811,$880E7011,$8807E011,$8803C011,$8803C011
|
||
DC.L $8807E011,$880E7011,$881C3811,$88381C11,$88100811,$88000011,$88000011,$FFFFFFFE
|
||
|
||
DC.L $7FFFFFF0,$FFFFFFF8,$FFFFFFFC,$FFFFFFFE,$FFFFFFFF,$FFFFFFFF,$FFFFFFFF,$FFFFFFFF
|
||
DC.L $FFFFFFFF,$FFFFFFFF,$FFFFFFFF,$FFFFFFFF,$FFFFFFFF,$FFFFFFFF,$FFFFFFFF,$FFFFFFFF
|
||
DC.L $FFFFFFFF,$FFFFFFFF,$FFFFFFFF,$FFFFFFFF,$FFFFFFFF,$FFFFFFFF,$FFFFFFFF,$FFFFFFFF
|
||
DC.L $FFFFFFFF,$FFFFFFFF,$FFFFFFFF,$FFFFFFFF,$FFFFFFFF,$FFFFFFFF,$FFFFFFFF,$FFFFFFFE
|
||
|
||
ENDWITH
|
||
ENDPROC
|
||
|
||
|
||
|
||
;----------------------------------------------------------------------
|
||
; Execute one of the subroutines related to the timeout while waiting for
|
||
; the poll hard disk to warm up.
|
||
;
|
||
; A0 -> Selector indicating which routine to call.
|
||
; D0 <-> The meaning of these parameters depends upon which routine is called.
|
||
;
|
||
; Destroys D0-D2/A0-A1.
|
||
;----------------------------------------------------------------------
|
||
|
||
InternalWait PROC EXPORT
|
||
|
||
MaxDispVal EQU 9 ; Entries 0-9 exist.
|
||
|
||
MOVE.L A0,D1 ; Get selector.
|
||
CMP.W #MaxDispVal,D1 ; Is value in range?
|
||
BHI.S @Exit ; If not, do nothing.
|
||
|
||
ADD.W D1,D1 ; Multiply by table entry size
|
||
LEA @MyTable,A1 ; Point to jump table.
|
||
MOVE.W (A1,D1.W),D1 ; Get table entry.
|
||
JMP (A1,D1.W) ; Execute proper subroutine.
|
||
|
||
@Exit RTS ; Return
|
||
|
||
|
||
@MyTable DC.W iGetTimeOut-@MyTable ; 0
|
||
DC.W iSetTimeOut-@MyTable ; 1
|
||
|
||
DC.W iGetWaitFlags-@MyTable ; 2
|
||
DC.W iSetWaitFlags-@MyTable ; 3
|
||
|
||
DC.W iDisableDynWait-@MyTable ; 4
|
||
DC.W iEnableDynWait-@MyTable ; 5
|
||
|
||
DC.W iDisablePermWait-@MyTable ; 6
|
||
DC.W iEnablePermWait-@MyTable ; 7
|
||
|
||
|
||
;---------------------------------------------------------------------- <A345>
|
||
; Get the timeout value.
|
||
;
|
||
; D0.L <- Timeout value (zero means use default).
|
||
; Z <- EQ if timeout indicates default; NE otherwise.
|
||
;
|
||
; Destroys D0/A0.
|
||
;---------------------------------------------------------------------- <A345>
|
||
|
||
iGetTimeOut
|
||
BSR.S GetRawTimeOut ; Get the current timeout parameter
|
||
AND.B #TimeOutMask,D0 ; Mask out significant bits
|
||
RTS ; Return
|
||
|
||
|
||
;----------------------------------------------------------------------
|
||
; Get the internal wait flags.
|
||
;
|
||
; D0.B <- Current wait flags.
|
||
;
|
||
; Destroys D0/A0.
|
||
;----------------------------------------------------------------------
|
||
|
||
iGetWaitFlags
|
||
BSR.S GetRawTimeOut ; Get the current timeout parameter
|
||
AND.B #WaitFlagsMask,D0 ; Mask out significant bits
|
||
RTS ; Return
|
||
|
||
|
||
;----------------------------------------------------------------------
|
||
; Set the timeout value.
|
||
;
|
||
; D0.B -> Timeout value (zero means use default).
|
||
;
|
||
; Destroys D0-D1/A0.
|
||
;----------------------------------------------------------------------
|
||
|
||
iSetTimeOut
|
||
MOVE.B D0,-(SP) ; Save timeout value
|
||
BSR.S GetRawTimeOut ; Get the current timeout parameter
|
||
MOVE.B (SP)+,D1 ; Get timeout value
|
||
|
||
CMP.B #MaxTimeOut,D1 ; Is proposed timeout greater than max?
|
||
BLS.S @InRange ; Branch if not
|
||
MOVEQ #MaxTimeOut,D1 ; If out of range, use max
|
||
@InRange
|
||
AND.B #$FF-TimeOutMask,D0 ; Clear out timeout bits
|
||
OR.B D1,D0 ; Put in new timeout value
|
||
BRA.S SetRawTimeOut ; Set new timeout parameter
|
||
|
||
|
||
;----------------------------------------------------------------------
|
||
; Set the timeout value.
|
||
;
|
||
; D0.B -> Wait flags to set.
|
||
;
|
||
; Destroys D0-D1/A0.
|
||
;----------------------------------------------------------------------
|
||
|
||
iSetWaitFlags
|
||
MOVE.B D0,-(SP) ; Save wait flags
|
||
BSR.S GetRawTimeOut ; Get the current timeout parameter
|
||
MOVE.B (SP)+,D1 ; Get wait flags
|
||
|
||
AND.B #WaitFlagsMask,D1 ; Mask out the wait flags
|
||
AND.B #TimeOutMask,D0 ; Clear out wait flag bits
|
||
OR.B D1,D0 ; Put in new wait flags
|
||
; fall into SetRawTimeOut
|
||
|
||
|
||
;----------------------------------------------------------------------
|
||
; Set the raw timeout parameter.
|
||
;
|
||
; D0.B -> Timeout parameter.
|
||
;
|
||
; Destroys D0/A0.
|
||
;----------------------------------------------------------------------
|
||
|
||
SetRawTimeOut
|
||
MOVE.B D0,-(SP) ; Save new value on stack.
|
||
|
||
MOVE.L SP,A0 ; Point to parameter.
|
||
MOVE.L #$00010001,D0 ; Write 1 byte starting at loc $01
|
||
_WriteXPRam ; Write it to PRAM.
|
||
|
||
MOVE.B (SP)+,D0 ; Clean up stack
|
||
RTS ; Return.
|
||
|
||
|
||
;----------------------------------------------------------------------
|
||
; Get the raw timeout parameter.
|
||
;
|
||
; D0.L <- Timeout parameter (only lowest byte is significant).
|
||
; Z <- EQ if timeout indicates default; NE otherwise.
|
||
;
|
||
; Destroys A0.
|
||
;----------------------------------------------------------------------
|
||
|
||
GetRawTimeOut
|
||
CLR.B -(SP) ; Create a place to put result.
|
||
MOVE.L SP,A0 ; Point to parameter block.
|
||
MOVE.L #$00010001,D0 ; Read 1 byte starting at loc $01
|
||
_ReadXPRam ; Read it from PRAM.
|
||
|
||
MOVEQ.L #0,D0 ; Clear upper bits.
|
||
MOVE.B (SP)+,D0 ; Return value in timeout field.
|
||
RTS ; Return.
|
||
|
||
|
||
;----------------------------------------------------------------------
|
||
; Disable the dynamic wait feature.
|
||
;
|
||
; Destroys D0/A0.
|
||
;----------------------------------------------------------------------
|
||
|
||
iDisableDynWait
|
||
_GetWaitFlags ; Get the current wait flags.
|
||
BSET #DynWaitBit,D0 ; Disable the dynamic wait feature.
|
||
_SetWaitFlags ; Set the new wait flags.
|
||
RTS
|
||
|
||
|
||
;----------------------------------------------------------------------
|
||
; Enable the dynamic wait feature.
|
||
;
|
||
; Destroys D0/A0.
|
||
;----------------------------------------------------------------------
|
||
|
||
iEnableDynWait
|
||
_GetWaitFlags ; Get the current wait flags.
|
||
BCLR #DynWaitBit,D0 ; Enable the dynamic wait feature.
|
||
_SetWaitFlags ; Set the new wait flags.
|
||
RTS
|
||
|
||
|
||
;----------------------------------------------------------------------
|
||
; Disable the permanent wait feature.
|
||
;
|
||
; Destroys D0/A0.
|
||
;----------------------------------------------------------------------
|
||
|
||
iDisablePermWait
|
||
_GetWaitFlags ; Get the current wait flags.
|
||
BSET #PermWaitBit,D0 ; Disable the permanent wait feature.
|
||
_SetWaitFlags ; Set the new wait flags.
|
||
RTS
|
||
|
||
|
||
;----------------------------------------------------------------------
|
||
; Enable the permanent wait feature.
|
||
;
|
||
; Destroys D0/A0.
|
||
;----------------------------------------------------------------------
|
||
|
||
iEnablePermWait
|
||
_GetWaitFlags ; Get the current wait flags.
|
||
BCLR #PermWaitBit,D0 ; Enable the permanent wait feature.
|
||
_SetWaitFlags ; Set the new wait flags.
|
||
RTS
|
||
|
||
ENDPROC
|
||
|
||
|
||
;----------------------------------------------------------------------
|
||
; Get information about the current default startup device.
|
||
;
|
||
; A0 -> A pointer to the record in which the info should be put.
|
||
;
|
||
; The record has the following format:
|
||
;
|
||
; RECORD
|
||
; sdDrvNum: INTEGER; { Drive number }
|
||
; sdRefNum: INTEGER; { Driver reference number }
|
||
; END;
|
||
;
|
||
; The sdDrvNum field is $FFFF if the drive number is irrelevant.
|
||
; The sdRefNum field is $0000 if the first available device should be chosen.
|
||
;
|
||
; Destroys D0-D2/A0-A1.
|
||
;----------------------------------------------------------------------
|
||
|
||
GetDefaultStartup PROC EXPORT
|
||
|
||
; Read info from parameter RAM. Format is:
|
||
; $78 [ (byte) DriveId{for slots} | (byte) PartitionId | (word) RefNum ]
|
||
|
||
MOVE.L #$00040078,D0 ; Read 4 bytes starting at loc $78
|
||
_ReadXPRam ; Get it from PRAM.
|
||
RTS ; Return.
|
||
|
||
ENDPROC
|
||
|
||
|
||
;----------------------------------------------------------------------
|
||
; Set a new default startup device.
|
||
;
|
||
; A0 -> A pointer to the record from which the info should be taken.
|
||
;
|
||
; The record has the following format:
|
||
;
|
||
; RECORD
|
||
; sdDrvNum: INTEGER; { Drive number }
|
||
; sdRefNum: INTEGER; { Driver reference number }
|
||
; END;
|
||
;
|
||
; The sdDrvNum field is $FFFF if the drive number is irrelevant.
|
||
; The sdRefNum field is $0000 if the first available device should be chosen.
|
||
;
|
||
; Destroys D0-D2/A0-A1.
|
||
;----------------------------------------------------------------------
|
||
|
||
SetDefaultStartup PROC EXPORT
|
||
|
||
; Write info to parameter RAM. Format is:
|
||
; $78 [ (byte) DriveId{for slots} | (byte) PartitionId | (word) RefNum ]
|
||
|
||
MOVE.L #$00040078,D0 ; Write 4 bytes starting at loc $78
|
||
_WriteXPRam ; Write it to PRAM.
|
||
RTS ; Return.
|
||
|
||
ENDPROC
|
||
|
||
|
||
IF hasSlotMgr THEN ; (what condition should this be???)
|
||
;----------------------------------------------------------------------
|
||
; Get more information about the current default startup device
|
||
;
|
||
; A0 -> A pointer to the record in which the info should be put.
|
||
;
|
||
; The record has the following format:
|
||
;
|
||
; RECORD
|
||
; sdOSType: BYTE; { Default OS type }
|
||
; sdReserved: BYTE; { Reserved }
|
||
; END;
|
||
;
|
||
; Destroys D0-D2/A0-A1.
|
||
;----------------------------------------------------------------------
|
||
|
||
GetOSDefault PROC EXPORT
|
||
|
||
; Read info from parameter RAM. Format is:
|
||
; $76 [ (byte) Reserved | (byte) OSType ]
|
||
|
||
MOVE.L #$00020076,D0 ; Read 2 bytes starting at loc $76
|
||
_ReadXPRam ; Get it from PRAM.
|
||
move.b #0, (A0) ; clear high byte
|
||
RTS ; Return.
|
||
|
||
ENDPROC
|
||
|
||
|
||
;----------------------------------------------------------------------
|
||
; Set more information about a new default startup device.
|
||
;
|
||
; A0 -> A pointer to the record from which the info should be taken.
|
||
;
|
||
; The record has the following format:
|
||
;
|
||
; RECORD
|
||
; sdOSType: BYTE; { Default OS type }
|
||
; sdReserved: BYTE; { Reserved }
|
||
; END;
|
||
;
|
||
; Destroys D0-D2/A0-A1.
|
||
;
|
||
; <1.4> SetOSDefault blindly set pram to the values pointed at by A0.
|
||
; Master pointers to rom resources on a macintosh ][ are of the
|
||
; form A083XXXX. The Trap number for SetOSDefault is A083. If
|
||
; a program crashed and started executing random blocks, then
|
||
; there was a good chance that it would try to execute a master
|
||
; pointer. The result would be that the default OS on reboot is
|
||
; not valid. Cross reference PB337 in system sources. The fix
|
||
; is to require a password, to prevent wandering programs from
|
||
; creating Chaos.
|
||
;
|
||
;----------------------------------------------------------------------
|
||
|
||
SetOSDefault PROC EXPORT
|
||
|
||
AppPhne EQU $09961010
|
||
|
||
cmpi.l #AppPhne, SetOSPassword ; check if oneshot is on
|
||
bne.s @errexit
|
||
clr.l SetOSPassword
|
||
|
||
; Write info to parameter RAM. Format is:
|
||
; $76 [ (byte) Reserved | (byte) OSType | (byte) DriveId{for slots} | (byte) PartitionId | (word) RefNum ]
|
||
|
||
MOVE.L #$00020076,D0 ; Write 2 bytes starting at loc $76
|
||
_WriteXPRam ; Write it to PRAM.
|
||
RTS ; Return.
|
||
|
||
@errexit clr.l SetOSPassword
|
||
moveq #-1,d0 ; signal error
|
||
rts ; and return
|
||
|
||
ENDPROC
|
||
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: Ck4LimitPRAMClear
|
||
;
|
||
; Inputs: none
|
||
;
|
||
; Outputs: Z: NE = only boot from Default device
|
||
; EQ = boot from Floppy or Default
|
||
; D0: NE = only boot from Default device
|
||
; EQ = boot from Floppy or Default
|
||
;
|
||
; Trashes: D0, A0
|
||
;
|
||
;________________________________________________________________________________________
|
||
|
||
Ck4LimitPRAMClear PROC EXPORT
|
||
|
||
IMPORT ValidatePRAM76 ; StartSearch.a
|
||
bsr ValidatePRAM76
|
||
subq.w #2,sp ; allocate buffer on stack
|
||
movea.l sp, A0 ; get buffer ptr
|
||
MOVE.L #$00010076, D0 ; Read 1 bytes starting at loc $76
|
||
_ReadXPRam
|
||
move.b (sp)+, D0
|
||
and.b #1, D0 ; low bit
|
||
rts
|
||
|
||
ENDPROC
|
||
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: ValidatePRAM76
|
||
;
|
||
; Inputs: none
|
||
;
|
||
; Outputs: none
|
||
;
|
||
; Trashes: none
|
||
;
|
||
; Function: Validates byte $76 of xpram: counts set bits in lower 6 and compares with
|
||
; upper two bits. If not equal, zeros out the byte.
|
||
;
|
||
; Note: Byte $76 (previously reserved but used by OSDefault stuff) is
|
||
; being defined as sensitive boot bits generally having to do with
|
||
; security issues driven by AIX but these functions can be used
|
||
; by other OSes as well. The upper two bits of byte $76 are a
|
||
; "checksum" of the other 6 bits (i.e. count of bits set). This
|
||
; is desired because of the danger if one of these bits is set
|
||
; accidentally by some bogus client. Failing this checksum will
|
||
; cause the byte to revert to 00 - a safe value. Currently defined
|
||
; bits are:
|
||
; 0: limit PRAM clear - don't clear PSWD, AUXPRAM, OSType, DefBoot
|
||
; 1: only load drivers from default device, don't boot from floppy
|
||
; 2: ignore CmdShiftOptDel
|
||
;
|
||
;________________________________________________________________________________________
|
||
vp76trashedRegs REG D0-D2/A0
|
||
|
||
ValidatePRAM76 PROC EXPORT
|
||
|
||
movem.l vp76trashedRegs, -(sp)
|
||
|
||
subq.w #2, sp ; allocate buffer on stack
|
||
movea.l sp, A0 ; get buffer ptr
|
||
MOVE.L #$00010076, D0 ; Read 1 bytes starting at loc $76
|
||
_ReadXPRam ; Get it from PRAM.
|
||
move.b (sp)+, D0
|
||
|
||
move.b #0, D2 ; zero reg for addx
|
||
moveq.l #0, D1 ; clear checksum
|
||
and.b #$3F, D0 ; get data bits (strip sum bits)
|
||
@bitloop
|
||
lsr.b #1, D0 ; get a bit
|
||
addx.b D2, D1 ; add that bit to checksum
|
||
tst.b D0 ; loop until no more bits
|
||
bne.s @bitloop
|
||
|
||
and.b #3, D1 ; only 2 low bits are valid
|
||
|
||
move.b (A0), D0 ; get byte 76 again
|
||
lsr.b #6, D0 ; get only checksum bits
|
||
|
||
cmp.b D0, D1 ; valid signature?
|
||
beq @valid ; Yes, don't clear all
|
||
|
||
move.b #00, -(sp) ; clean up bogus value
|
||
movea.l sp, A0 ; get buffer ptr
|
||
move.l #$00010076, D0 ; get #, addr PRAM bytes
|
||
_WriteXPram ; write out zeros to 76
|
||
move.b (sp)+, D0
|
||
@valid
|
||
movem.l (sp)+, vp76trashedRegs
|
||
rts
|
||
|
||
ENDP
|
||
|
||
|
||
;----------------------------------------------------------------------
|
||
; Get information about the current default video device.
|
||
;
|
||
; A0 -> A pointer to the record from which the info should be put.
|
||
;
|
||
; The record has the following format:
|
||
;
|
||
; RECORD
|
||
; sdSlot: BYTE;
|
||
; sdsRsrcId: BYTE
|
||
; END;
|
||
;
|
||
; sdSlot and sdsRsrcId are zero if no default.
|
||
;
|
||
; Destroys D0-D2/A0-A1.
|
||
;----------------------------------------------------------------------
|
||
|
||
GetVideoDefault PROC EXPORT
|
||
|
||
; Read info from parameter RAM. Format is:
|
||
; $80 [ (byte) Slot Number | (byte) sResource Number ]
|
||
|
||
MOVE.L #$00020080,D0 ; Read 2 bytes starting at loc $80
|
||
_ReadXPRam ; Get it from PRAM.
|
||
RTS ; Return.
|
||
|
||
ENDPROC
|
||
|
||
|
||
;----------------------------------------------------------------------
|
||
; Set information about the default video device.
|
||
;
|
||
; A0 -> A pointer to the record from which the info should be put.
|
||
;
|
||
; The record has the following format:
|
||
;
|
||
; RECORD
|
||
; sdSlot: BYTE;
|
||
; sdsRsrcId: BYTE
|
||
; END;
|
||
;
|
||
; sdSlot and sdsRsrcId are zero if no default.
|
||
;
|
||
; Destroys D0-D2/A0-A1.
|
||
;----------------------------------------------------------------------
|
||
|
||
SetVideoDefault PROC EXPORT
|
||
|
||
; Write info to parameter RAM. Format is:
|
||
; $80 [ (byte) Slot Number | (byte) sResource Number ]
|
||
|
||
MOVE.L #$00020080,D0 ; Write 2 bytes starting at loc $80
|
||
_WriteXPRam ; Write them to PRAM.
|
||
RTS ; Return.
|
||
|
||
ENDPROC
|
||
|
||
ENDIF
|
||
|
||
|
||
END
|
||
|