mac-rom/OS/SlotMgr/SlotMgrInit.a
Elliot Nunn 0c319592a9 Build Slot Mgr from source
(Slot Mgr is for compatibility only on PCI Macs.)
2017-12-26 09:53:21 +08:00

1517 lines
58 KiB
Plaintext

;_______________________________________________________________________________________
;
; File: SlotMgrInit.a
;
; Contains: This file contains all the slot manager initialization routines. The routines
; in this file are used for the ROM version, the 32bit QuickDraw INIT version,
; and the system patch version(for Mac II's, IIx's, IIcx's, and Mac SE/30's).
; When this code is used in RAM, it is cut back after executing.
;
; Written by: David Wong, September 17, 1989
;
; Copyright: © 1989-1993 by Apple Computer, Inc., all rights reserved.
;
; Change History (most recent first):
;
; <SM15> 9/12/93 pdw Removed a push,SwapMMU,pop sequence.
; <SM14> 9/1/93 SKH Fixed a bug where only LastSDMSelts were being allocated in the dispatch
; table.
; <SM13> 8/4/93 GMR RC: Added code to enable slave block transfers for BART machines
; (PDM,CF).
; <SM12> 6/14/93 kc Roll in Ludwig.
; <LW2> 3/24/93 mal Added EnableBlockXfer after PrimaryInit for each slot.
; EnableBlockXfer sets bits in a MUNI register if slot has block
; xfer sRsrcs indicating it supports block xfers.
; <SM11> 11/17/92 kc Add "IF NOT LC930 THEN" around patchPrimaryInit to facilitate
; dead code stripping for the LC930 build.
; <SM10> 10/14/92 CSS Change some branch short instructions to branches.
; <SM9> 09-24-92 jmp Added a pRAM-based mechanism for skipping BootBug altogether if
; it is installed.
; <SM8> 08-27-92 jmp Added support for Brigent, Inc.Õs BootBug card.
; <SM7> 6/30/92 kc Roll in Horror, comments follow:
; ÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊ ¥ From SlotMgr.a
; <H5> djw Add new selector for DoSecondaryInit.
; ¥ From SlotMgrPatch.a
; <H11> djw Added DoSecondaryInit routine.
; <SM6> 5/16/92 kc Roll in Horror changes. Comments follow:
; ÊÊÊÊÊÊNote: This is going to take some work for the system build but
; it is likely to change so we might want to hold off awhile.
; ¥ From SlotMgr.a
; <H3> 3/18/92 djw Add new calls to support docking code - AddCard, RemoveCard,
; CheckSlot, and GetSRTEntry.
; <H2> 3/5/92 djw Replaced InitSlotMgr, InitsRsrcTable, InitPRAMRecs, and
; Primary_Init entries in the table with new routines.
; ¥ From SlotMgrPatch.a
; <H5> 02/05/92 jmp Unfortunately, I put some tables in the middle of this file
; that, in Cyclone, will get bigger. So, I moved them from the
; middle of the file into the pad space. Also, I generalized the
; routine that decides whether a DeclROMÕs PrimaryInit/Driver
; should be patched by not stopping once I found the version I was
; looking for (e.g., in case we need to patch out versions 1, 2,
; and 3 of the 8¥24 card).
; <H2> 10/22/91 SAM/jmp Discontinued patching out the JMFB PrimaryInit & Driver on the
; Bungee (1.1) version of the 4¥8/8¥24 Card ROM. From Zydeco-TERROR ROM.
; <T6> 2/25/91 jmp Added code to check version number of the driver before doing
; PrimaryInit and GetDriver patches.
; <T3> 11/19/90 jmp Added in patches for PrimaryInit and GetDriver.
; ¥ From SlotInfo.a
; <H5> 3/18/92 djw Add stub entry points for new docking support routines -
; StubAddCard and StubRemoveCard
; <H4> 3/6/92 SWC We thank Dave for <H3> (getting it working in under 25 triesÉ),
; and move the Docking Manager initialization to StartSDeclMgr
; just before running the primary inits so that we can decided
; whether or not to install the built-in LCD driver when DBLite
; (etc.) is inside a docking station and thus the LCD screen is
; not useable.
; <H3> 3/5/92 djw Rewrote slot manager initialization code (major routines from
; beginning of file to SecondaryInit) to facilitate new code for
; DBLite docking station. The major change was to modify the
; routines to execute their functions for a single slot instead of
; for every slot.
; <H2> 10/29/91 jmp Added a patch to the VerifySlot routine for supporting super
; sRsrc directories in Slot $0.
; <SM5> 5/5/92 JSM Roll-in changes from Reality:
; <17> 5/4/92 JSM The checks for isUniversal in this file should just be forROM.
; (Dean really didnÕt have to do all that work in <14>).
; <SM4> 2/21/92 RB delete rude code which snuck in late at night while no one was
; lookingÉ
; <SM3> 2/12/92 RM Change BRA.S to BRA.L.
; <SM2> 2/11/92 RB Fixed InitPRamRecs. It was not working right on the Quadras due
; to a confusing situation caused when using forROM, and NOT
; forROM in diferent places of the same routine. I hate
; them...conditionals.
; <15> 1/7/92 RB Rolled in Terror changes.
; <14> 8/30/91 DTY Define isUniversal here since itÕs no longer defined in
; BBSStartup.
; <13> 6/12/91 LN removed #include 'HardwareEqu.a'
; <12> 12/10/90 BBM (dba) Eliminate cutback code now that this is a linked patch.
; <11> 8/17/90 DTY Dean screws up the ROM build again. Have the ROM build use the
; SeparateFile code. Merge the two jump tables into one, and use a
; macro to decide which format to use.
; <10> 8/17/90 DTY Made second copy of SDMJumpTable which uses dcImportResident for
; system patch case. (Darin said I could check it in.)
; <9> 7/30/90 BG Removed CPU = 040 conditional in preparation for moving from
; Mac040 to Mac32 build.
; <8> 6/29/90 djw Fix bug in InitPRAMRecs where there is only a slot zero if
; "hasRBV" is set. Rewrote primaryInit to execute slot zero's
; before any other slots. Moved SecondaryInit code here, so it
; would be cut back. Added call to ReconfigVideo into
; SecondaryInit for patch version. Added code into SecondaryInit
; to cutback itself when done (for 7.0 patch).
; <7> 4/5/90 djw Fix bug introduced in non-universal version of code in routine
; alloc_sInfo
; <6> 4/2/90 djw Modify Alloc_sInfo to scan only enabled slots using universal
; tables.
; <5> 3/15/90 djw Moved code in InitJmpTbl to slotmgrpatch.a which was only used
; for the patch version. Fixed InitPramRecs bug where I was
; writting a bad board id when init-ing the pram rec.
; <4> 1/21/90 BG Added code to modify the JmpTbl entry for the SlotMgr Bus Error
; Exception Handler to be the 040 bus error exception handler if
; we are running on an 040.
; <3> 1/17/90 djw Modified init code so same source could be used in RAM and ROM.
; Modify InitJmpTbl to install slot mgr A-trap if in RAM. Add code
; back to initjmptbl to install slot mgr trap if a patch. Moved
; SecondaryInit and GetBoard to SlotMgr.a - added them to jump
; table.
; <2> 1/11/90 CCH Added include of ÒHardwarePrivateEqu.aÓ.
; <1.1> 10/10/89 djw removed code in initjmptbl which installed the slot mgr trap if
; a patch.
; <1.0> 9/18/89 djw New file combining all slotmgr initialization code for sharing
; with system 7.0 patch.
;
;_______________________________________________________________________________________
Machine MC68020
String Asis
Print Off
LOAD 'StandardEqu.d'
Include 'HardwarePrivateEqu.a'
Include 'RomEqu.a'
Include 'UniversalEqu.a'
Include 'SlotMgrEqu.a'
Include 'ComVideoEqu.a' ; <15> rb
Print On
IMPORT ReadSlotByte
IMPORT ReadSlotWord
IMPORT ReadSlotLong
IMPORT GetcString
IMPORT GetSlotBlock
IMPORT FindSlotStruct
IMPORT ReadSlotStruct
IMPORT SlotVersion
IMPORT InsertSRT
IMPORT SetsRsrcState
IMPORT ReadSlotInfo
IMPORT ReadSlotPRAM
IMPORT PutSlotPRAM
IMPORT ReadFHeader
IMPORT NextsRsrc
IMPORT NextTypesRsrc
IMPORT SlotRsrcInfo
IMPORT SlotDisposPtr
IMPORT CkCardStat
IMPORT ReadSlotDrvrName
IMPORT FindDevBase
IMPORT GetsRsrc
IMPORT GetTypesRsrc
IMPORT FindSRTRec
IMPORT CardChanged
IMPORT SlotExec
IMPORT OffsetData
IMPORT ReadPBSize
IMPORT CalcStep
IMPORT SearchSRT
IMPORT UpdateSRT
IMPORT CalcsPointer
IMPORT GetSlotDrvr
IMPORT PtrToSlot
IMPORT FindsInfoRecPtr
IMPORT DeleteSRTRec
IMPORT InitSlotPRAM
IMPORT FindsRsrcPtr
IMPORT GetsRsrcPtr
IMPORT pNewSRTEntry
IMPORT pInitEntry
IMPORT pSrToSpBlock
IMPORT pRead4Bytes
IMPORT pBusException
IMPORT pInstallBus
IMPORT pRestoreBus
IMPORT pAllocSRTBlk
IMPORT GetSRTEntry ; <h3> djw
IMPORT SlotEmpty ; <djw>
IMPORT pGetBoard ; <3>
IMPORT SlotManager ; <3>
IMPORT p040BusException ; <4>
EXPORT InitsInfo,InitPrimary,InitsPram,InitsRsrc,InitsInfo
EXPORT Secondary_Init,StubCheckSlot,StubAddCard,StubRemoveCard,SDMJmpTable
EXPORT DoSecondaryInit
If (&TYPE('SeparateFile') = 'UNDEFINED') Then ; equ indicating whether we are <3>
SeparateFile Equ 0 ; ... building for 32bit QD INIT
Endif ; ... or as a system patch
If (&TYPE('forAUX') = 'UNDEFINED') Then ; equ indicating whether we are <8>
forAUX Equ 0 ; ... building for an A/UX patch
Endif
if not(forAUX) then
Include 'LinkedPatchMacros.a'
endif
Macro
DispatchVector &ROMAddress
if SeparateFile or forAUX or forROM then
dc.w &ROMAddress-*
else
dcImportResident &ROMAddress
endif
EndM
;_______________________________________________________________________________________ <1.6>
; InitJmpTbl - initialize the slot manager's secondary dispatch table
;
; Build the slot manager's jump table in RAM, from the ROM table.
;
; Input : none
;
; Output :
;
InitJmpTbl Proc Export
IF SeparateFile or forAUX or forROM then
movem.l a0-a2,-(sp)
; SKH, was only allocating lastsdmselt's
move.l #(LastSDMSelt + 1)*4,D0 ; alloc new jmp tbl <SM14>
_NewPtr ,SYS,CLEAR
move.l a0,SDMJmpTblPtr ; put in low mem
; Convert ROM table offsets to address vectors for RAM jump table
; SKH, was only copying the first LastSDMSelt-1 elements
moveq #LastSDMSelt,d0 ; d0 = number entries in jump tbl <SM14>
lea SDMJmpTable,A1 ; A1 = addr of ROM jump tbl
@Loop
movea.l a1,a2 ; a2 = current base to calc addr from
adda.w (a1)+,a2 ; a2 = add offset to base
move.l a2,(a0)+ ; move vector to RAM jump tbl
dbra d0,@Loop
cmpi.b #cpu68040,CpuFlag ; are we running on an 040? <4>
bne.s @notAn040 ; NO ... we're done <4>
lea p040BusException,a0 ; YES ... retrieve address of 040 handler <4>
move.l a0,([SDMJmpTblPtr],BusException*4) ; replace bus error handler with 040 version <4>
@notAn040 ; <4>
movem.l (sp)+,a0-a2
moveq #0,d0
rts
ELSE ; Not SeparateFile or forAUX or forROM then
movem.l a0-a2,-(sp)
leaResident SDMJmpTable,a0 ; Load up the jump table
move.l a0,SDMJmpTblPtr ; Stash it in lowmem
movem.l (sp)+,a0-a2
moveq #0,d0
rts
ENDIF ; SeparateFile or forAUX or forROM then
;_______________________________________________________________________________________ <1.6>
; ROM Jump table
;
SDMJmpTable Proc
DispatchVector ReadSlotByte ;$00
DispatchVector ReadSlotWord ;$01
DispatchVector ReadSlotLong ;$02
DispatchVector GetcString ;$03
DispatchVector SlotEmpty ;$04
DispatchVector GetSlotBlock ;$05
DispatchVector FindSlotStruct ;$06
DispatchVector ReadSlotStruct ;$07
DispatchVector SlotVersion ;$08 <1.2>
DispatchVector SetsRsrcState ;$09 <1.2>
DispatchVector InsertSRT ;$0A <1.2>
DispatchVector GetsRsrc ;$0B <1.2>
DispatchVector GetTypesRsrc ;$0C <1.2>
DispatchVector SlotEmpty ;$0D
DispatchVector SlotEmpty ;$0E
DispatchVector DoSecondaryInit ;$0F <H5>
; Specialized
DispatchVector ReadSlotInfo ;$10
DispatchVector ReadSlotPRAM ;$11
DispatchVector PutSlotPRAM ;$12
DispatchVector ReadFHeader ;$13
DispatchVector NextsRsrc ;$14
DispatchVector NextTypesRsrc ;$15
DispatchVector SlotRsrcInfo ;$16
DispatchVector SlotDisposPtr ;$17
DispatchVector CkCardStat ;$18
DispatchVector ReadSlotDrvrName ;$19
DispatchVector FindSRTRec ;$1A <1.2>
DispatchVector FindDevBase ;$1B
DispatchVector FindDevBase ;$1C map findbigdevbase to finddevbase <1.6>
DispatchVector GetsRsrcPtr ;$1D <1.3>
DispatchVector StubAddCard ;$1E <h3> djw
DispatchVector StubRemoveCard ;$1F <h3> djw
; Advanced (SDM private routines).
DispatchVector InitsInfo ;$20 <h2> djw
DispatchVector InitPrimary ;$21 <h2> djw
DispatchVector CardChanged ;$22
DispatchVector SlotExec ;$23
DispatchVector OffsetData ;$24
DispatchVector InitsPram ;$25 <h2> djw
DispatchVector ReadPBSize ;$26
DispatchVector StubCheckSlot ;$27 <h3> djw
DispatchVector CalcStep ;$28
DispatchVector InitsRsrc ;$29 <h2> djw
DispatchVector SearchSRT ;$2A
DispatchVector UpdateSRT ;$2B
DispatchVector CalcsPointer ;$2C
DispatchVector GetSlotDrvr ;$2D
DispatchVector PtrToSlot ;$2E
DispatchVector FindsInfoRecPtr ;$2F
DispatchVector FindsRsrcPtr ;$30
DispatchVector DeleteSRTRec ;$31
DispatchVector Secondary_Init ;$32 <3>
DispatchVector InitSlotPRAM ;$33 <v1.5>
; New private routines - vectored to (not through the trap dispatcher)
DispatchVector pNewSRTEntry ;$34
DispatchVector pInitEntry ;$35
DispatchVector pSrToSpBlock ;$36
DispatchVector pRead4Bytes ;$37
DispatchVector pGetBoard ;$38 <3>
DispatchVector pBusException ;$39
DispatchVector pInstallBus ;$3A
DispatchVector pRestoreBus ;$3B
DispatchVector pAllocSRTBlk ;$3C
DispatchVector GetSRTEntry ;$3D <h3> djw
;=======================================================================================
; Re-wrote the following old routines:
; StartSDeclMgr
; InitSlotMgr
; InitsRsrcTable
; InitPRAMRecs
; Primary_Init
;
; ...into these new routines:
; StartSDeclMgr
; AllocSlot
; InitsInfo
; InitsRsrc
; InitsPram
; InitPrimary
;
; The major rewrite of the slot manager initialization code was to go from each routine
; executing a single function for all slot, to routines which would only execute the
; function for a given slot. This change was to facilitate slot manager changes for
; DBLite to accomodate their docking module. The end resulting data structures are
; not changed from the previous slot manager version.
;=======================================================================================
;_______________________________________________________________________________________ <h3> djw
; StartSDeclMgr - start the slot manager
;
; Initialize the slot manager. Create the sInfo and the slot resource table. Load
; and init any slot PRAM records, and load and execute any primary init records.
; This routine is called from startinit.a
;
; Input : none
; Output : d0 = status
;
Proc
Export StartSDeclMgr
Import InitJmpTbl, InitDocking
with spBlock,sInfoRecord,FHeaderRec,slotGlobals,seBlock
StartSDeclMgr
sub.w #spBlockSize,sp ; allocate spBlock
movea.l sp,a0 ; setup a0 = ptr to spBlock
jsr InitJmpTbl ; create the slot manager's dispatch table
bne @Done
bsr AllocSlot ; allocate all the slot manager data structures
bne @Done
; For all the slots, determine its status, verify its format record, log its
; sResources, initialize the PRAM for the slot.
moveq.l #sLastSlot,d1 ; d1 = slot loop counter from last slot
@Loop
move.b d1,spSlot(a0) ; set slot number
bsr InitsInfo ; initialize the sInfo table
bsr InitsRsrc ; initialize the slot resource table (SRT)
bsr InitsPram ; initial a slot's PRAM
dbra d1,@Loop
; Set up the warm/cold start flag for later. <SM8>
Moveq.l #0,D2 ; D2 = flag for cold start.
Cmpi.l #WmStConst,WarmStart ; Check low mem for warm start value.
Bne.s @Continue ; Cold start.
Bset.l #fWarmStart,D2 ; Warm start.
@Continue
; Determine if thereÕs a BootBug card installed or not. If one is installed,
; execute it first. Otherwise, just run the normal sequence.
Clr.b -(Sp) ; Initialize our ÒsavedSlotÓ space.
Clr.b spSlot(A0) ; Start with Slot $0.
Clr.b spID(A0) ; Begin search with ID 0.
Clr.b spExtDev(A0) ; No external device(s).
Clr.b spTBMask(A0) ; No mask in search.
Move.w #CatProto,spCategory(A0) ; Look for: Proto,
Move.w #TypDebugger,spCType(A0) ; Debugger,
Move.w #DrSwMacsBug,spDrvrSW(A0) ; MacsBug,
Move.w #DrHwBootBug,spDrvrHW(A0) ; BootBug.
Clr.l spParamData(A0) ; Clear the flags field.
Ori.b #(1<<fNext),spParamData+3(A0) ; Search for the 1st one.
_GetTypeSRsrc ; If we donÕt find a BootBug card
Bne.s @DoZeroFirst ; then just run the normal sequence.
Move.b spSlot(A0),(Sp) ; Remember which slot has BootBug in it.
Move.l A0,-(Sp) ; Save SpBlockPtr. <H15>
Subq #4,Sp ; Make a pRAM buffer on the stack.
Move.l Sp,A0 ; Point to it.
Move.l #$000400FC,D0 ; Set up to read 4 bytes starting at $FC.
_ReadXPRAM ; Read Õem.
Move.l (Sp)+,D0 ; Get the result, release buffer.
Move.l (Sp)+,A0 ; Restore SpBlockPtr.
Cmpi.l #'Skip',D0 ; If the BootBug skip signature is set,
Beq.s @DoZeroFirst ; then skip it.
; Now, go execute all the PrimaryInits as usual, except run the BootBug PrimaryInit
; first.
Move.b D2,spFlags(A0) ; Set flag for warm or cold start.
Bsr InitPrimary ; Execute the PrimaryInit.
@DoZeroFirst
Clr.b spSlot(A0) ; Set slot 0.
Move.b D2,spFlags(A0) ; Set flag for warm or cold start.
Bsr InitPrimary ; Execute the PrimaryInit.
Moveq.l #sLastSlot,D1 ; D1 = slot loop counter from last slot.
@Loop1
Move.b D1,spSlot(A0) ; Set the Slot number.
Cmp.b (Sp),D1 ; If this is the BootBug slot,
Beq.s @Skip ; then skip it this time.
Move.b D2,spFlags(A0) ; Set flag for warm or cold start.
Bsr InitPrimary ; Execute the PrimaryInit.
Bsr EnableBlockXfer ; Enable block xfer, if this slot is capable <LW2>
@Skip Subq.b #1,D1
Bne.s @Loop1 ; Continue for all slots.
Tst.b (Sp)+ ; Free up ÒsavedSlotÓ space.
@Done
Add.w #spBlockSize,Sp ; Free SpBlock.
Moveq.l #noErr,D0 ; Return noErr.
Rts ; <SM8>
;_______________________________________________________________________________________ <h3> djw
; AllocSlot - allocate slot manager data structures
;
; Allocate the slot manager globals, the sInfo table, the sInfoRecords for disabled
; and reserved slots, and the first block of sRsrcRecords for the SRT.
;
; Input : a0 = ptr to spBlock
; Output : d0 = status ccr reflects status
;
AllocSlot
@regs reg a0-a1
movem.l @regs,-(sp) ; save registers
; Allocate the necessary memory as one contiguous block
move.l #(slotGlobalSize \ ; size of globals
+(4*TotalSlots) \ ; size of sInfor vector table
+(3*sInfoNewSize) \ ; size of 3 sInfoRecords (disabled,reserved,empty)
),d0 ; d0 = number of bytes to alloc
_NewPtr ,sys,clear ; alloc block
bne.s @Done ; some error - done
adda.w #slotGlobalSize,a0 ; globals are at a negative offset from sInfo tbl
move.l a0,sInfoPtr ; set ptr to sInfo table
; There are three special sInfoRecords which we are setting up. These records are shared by
; all slots which have a disabled, reserved, or empty status. The records are shared because
; the sInfoTable is mainly empty and there is no sense wasting an sInfoRecord. The two
; records are at the end of the sInfoTable: first the disabled, followed by the reserved,
; followed by the empty.
lea 4*TotalSlots(a0),a0 ; inc a0 past sInfoTable to disable sInfoRecord
move.w #smDisabledSlot, \
siInitStatusA(a0) ; set slot status to disabled
lea sInfoNewSize(a0),a0 ; inc a0 to reserved sInfoRecord
move.w #smReservedSlot, \
siInitStatusA(a0) ; set slot status to reserved
lea sInfoNewSize(a0),a0 ; inc a0 to empty sInfoRecord
move.w #smEmptySlot, \
siInitStatusA(a0) ; set slot status to reserved
; Allocate the first SRT block.
slotjsr AllocSRTBlk ; return a1 = ptr to blk
move.l a1,sRsrcTblPtr ; save ptr in low mem
move.l a1,([sInfoPtr],lastSRTPtr) ; set ptr to last entry in SRT
@Done
tst.w d0 ; return err in ccr
movem.l (sp)+,@regs
rts
;_______________________________________________________________________________________ <h3> djw
; InitsInfo - init a slot's sinfoRecord
;
; Check the NuBus info in the universal tables to see if the given slot is enabled.
; If so, then scan the slot to determine whether it is occupied or empty. If occupied,
; then verify the declaration ROM.
;
; Input : a0 = ptr to spBlock
; Output : none
;
; spBlock : -> spSlot slot number
Export InitsInfo
InitsInfo
@regs reg d1/a0-a3
movem.l @regs,-(sp)
moveq.l #0,d1
move.b spSlot(a0),d1 ; d1 = slot number in question
movea.l sInfoPtr,a1 ; a1 = ptr to beginning of sInfoTable
; Check if the slot is enabled in the universal tables. The two currently defined
; states are enabled (no bit set), disabled (do no scan), and reserved (hack for VM
; to disable VM from looking into slot's address space. Previously, VM ignored
; the disabled error).
movea.l a1,a3
lea 4*TotalSlots(a3),a3 ; a3 = ptr to disabled sInfoRecord
move.l a3,(a1,d1.w*4) ; set slot pointing to disabled record
with NuBusInfo
movea.l UnivInfoPtr,a2
adda.l ProductInfo.NuBusInfoPtr(a2),a2 ; a2 = ptr to universal slot info tbl
btst.b #slotDisabled,(a2,d1.w) ; test if slot is disabled
bne @Done
lea sInfoNewSize(a3),a3 ; a3 = ptr to reserved record
move.l a3,(a1,d1.w*4) ; set slot pointing to reserved record
btst.b #slotReserved,(a2,d1.w) ; test if the slot is reserved
bne @Done ; <SM10> CSS
endwith
; The slot is enabled for use. Initially, set the slot to point to the empty sInfoRecord.
lea sInfoNewSize(a3),a3 ; a3 = ptr to empty record
move.l a3,(a1,d1.w*4) ; set slot pointing to empty record
; If this is slot zero, then special case the declaration ROM address
tst.b d1 ; slot 0 ?
bne.s @doRead ; not slot 0
movea.l RomBase,a3 ; get base of rom
adda.l ROMHeader.RomSize(a3),a3 ; a3 = addr of end of ROM
suba.l #1,a3 ; adjust to last byte in ROM
bra.s @Verify ; verify slot 0
; Do a nubus read to see if the slot is occupied. If it is, then when we
; read, we will not get a bus error.
@doRead
moveq.l #-1,d0
bfins d1,d0{4,4} ; inset slot number to get $fsffffff
movea.l d0,a3 ; a3 = minor space nubus addr for slot
lea @Empty,a2 ; a2 = addr to go if bus error occurs
slotjsr InstallBus ; replace bus excptn, 32 bit mode
move.b (a3),d0 ; NUBUS READ - read byte from minor space
slotjsr RestoreBus ; restore mmu state and bus exception vector
bra.s @Verify ; slot is occupied - verify config rom
@Empty
slotjsr RestoreBus ; restore mmu state and bus exception vector
bra.s @Done
; The slot is not empty. Allocate an sInfoRecord for it and verify the card.
; a0 = ptr to spBlock, a1 = ptr to sInfoTable, a3 = ptr to top of config rom
@Verify
movea.l a0,a2 ; save ptr to spBlock
move.l #sInfoNewSize,d0 ; size of sInfoRecord
_NewPtr ,sys,clear
bne.s @Done ; err - leave pointing to empty record
move.l a0,(a1,d1.w*4) ; set ptr in sInfo vector table
movea.l a0,a1 ; a1 = ptr to sInfoRecord for this slot
movea.l a2,a0 ; restore a0 = ptr to spBlock
move.w #retryCnt,siTOConst(a1) ; set default bus error retry cnt (not used)
move.b d1,siSlot(a1) ; set slot number
move.l a3,siROMAddr(a1) ; set ROM address
bsr.s VerifySlot ; verify the config rom format
@Done
movem.l (sp)+,@regs
rts
;_______________________________________________________________________________________
; VerifySlot - verify a slot's declaration ROM
;
; Verify a slot's declaration ROM. Fill in the information from the ROM format
; block to the sInfo record for that card. This routine is called in 32 bit mode.
;
; <***Problem - at every error return, should we try the next byte lane, or do as we
; do now, and just give up. Could be a case where the byte lane is
; bad, but we read a valid test pattern***>
;
; Input : reg A0 = ptr to spBlock
; A1 = ptr to sInfo record for card
; Output : reg D0 = status, 0=ok CCR reflects status
;
; spBlock : -> spSlot slot number
;
Export VerifySlot
With FHeaderRec
VerifySlot
MOVEM.L D1/A2,-(SP)
suba.w #fhBlockSize,sp ; alloc space for format block
MOVE.L SP,A2 ; A2 = ptr to blk for format record
; Get the byte lane from the declaration ROM. Read in the format block and check the
; test pattern. If it does not match, then the byte lane must be bad, so loop and try
; another one.
MOVE.L A2,spResult(A0) ; pass A2 = addr to put format header
moveq #3,d1 ; start with byte lane 3 <2.0>
@Loop BSR GetByteLane ; get a valid byte lane - return byte lane value in D1
BNE VerifySlotDone ; error - no valid byte lane
_sReadFHeader ; read the format header from the declaration ROM
BNE.S @EndLoop ; some error - try another byte lane <1.7>
; Verify the ByteLanes value (by checking the Test pattern) - reg A2 = ptr to format header image
CMP.L #TestPattern,fhTstPat(A2)
bne.s @EndLoop ; bad signature - try another byte lane <1.7>
; Found a valid test pattern. Now check the rest of the format block fields
; and the ROM checksum.
BSR VerifyFormat ; chk the format blk - reg A2 = ptr to format blk image
bne.s @EndLoop ; error
BSR VerifyCRC ; verify the ROM checksum
beq.s @GoodRom ; good rom - get ptr to the sRsrc directory
@EndLoop sub.l #1,siROMAddr(a1) ; decrement ROM ptr to next byte lane <1.7>
DBRA D1,@Loop
move.w #smBLFieldBad,d0 ; error - could not find a valid byte lane
BRA VerifySlotDone
; Get the pointer to the sResource directory from the declaration ROM and store
; it in the sInfo record for future use. The directory is at an offset from the
; directory offset field in the format header.
EndWith ; FHeaderRec
With XFHeaderRec
@GoodRom
VerifySlotPatch
Tst.b spSlot(A0) ; If weÕre not looking at slot 0, then
Bne @StdHeader ; just assume a standard header.
Move.l siROMAddr(A1),spsPointer(A0) ; Set ptr to top of ROM.
Move.l #-(fhXBlockSize)+1,spOffsetData(A0) ; Set offset to beginning of extended header.
Move.b siCPUByteLanes(A1),spByteLanes(A0) ; Set byte lanes field.
_sCalcsPointer ; Get pointer to extended header.
Bne @StdHeader ; If failed, just try standard header.
@SaveRegs Reg A3-A4 ; Define some work register.
Movem.l @SaveRegs,-(Sp) ; Save them.
Suba.l #XFHdrExtraSize,Sp ; Allocate space for extended part of FHeaderRec.
Move.l Sp,A3 ; Point to it.
Suba.l #seBlockSize,Sp ; Allocate space for sExec block.
Move.l Sp,A4 ; Point to it.
Move.l A3,spResult(A0) ; Point to buffer for extra part of format block.
Move.l #XFHdrExtraSize,spSize(A0) ; Number of bytes to copy.
_sReadStruct ; Read extended part of header.
Bne.s @FallBack ; If failed, just try the standard header.
Cmpi.l #TestPattern,fhXSTstPat(A3) ; If the (extended) test pattern doesnÕt exist,
Bne.s @FallBack ; just try the standard header.
Move.b fhFormat(A2),D0 ; Get the format ID of the header.
Cmp.b fhXSuperInit(A3),D0 ; If not using an appropriately IDÕd SuperInit,
Bne.s @FallBack ; just try the standard header.
Move.b spSlot(A0),seSlot(A4) ; Copy the slot number.
Move.b fhXSuperInit(A3),sesRsrcId(A4) ; Copy the sRsrc/format ID of the SuperInit.
Move.b fhXSuperInit(A3),spID(A0) ; Make sure sExec calls the right SuperInit.
Move.l A4,spsExecPBlk(A0) ; Point to the sExec param block.
_SExec ; Call SuperInit.
Bne.s @FallBack ; If failed, just try the standard header.
Tst.b seStatus(A4) ; If upper byte of seStatus is non-zero (a failure),
Bne.s @FallBack ; just try the standard header.
Move.l siROMAddr(A1),spsPointer(A0) ; Point back to the top of ROM.
Move.l fhXSDirOffset(A3),spOffsetData(A0) ; Load super directory offset.
Clr.b spOffsetData(A0) ; Strip psuedo-spID byte.
Add.l #XOffsetToDir,spOffsetData(A0) ; Negative offset.
Move.b siCPUByteLanes(A1),spByteLanes(A0) ; Set byte-lanes field.
_sCalcsPointer ; Get ptr to start of super sRsrc directory.
Bne.s @FallBack ; If failed, just try standard header.
Move.b seStatus+1(A4),spID(A0) ; Get the id of the super sRsrc directory.
_sFindStruct ; Look for it.
Bne.s @FallBack ; If failed, try standard header.
Move.l spsPointer(A0),siDirPtr(A1) ; Set ptr to sRsrc dir in sInfo record.
Adda.l #XFHdrExtraSize+seBlockSize,Sp ; Restore stack.
Movem.l (Sp)+,@SaveRegs ; Restore work registers.
Bra.s VerifySlotDone
@FallBack Adda.l #XFHdrExtraSize+seBlockSize,Sp ; Restore stack.
Movem.l (Sp)+,@SaveRegs ; Restore work registers.
@StdHeader MOVE.L siROMAddr(A1),spsPointer(A0) ; set ptr to slot declaration ROM
MOVE.L fhDirOffset(A2),spOffsetData(A0) ; get dir offset from format blk image
add.l #OffsetToDir,spOffsetData(a0) ; negative offset to directory field <2.0>
_sCalcsPointer ; calc ptr to directory
BNE.S VerifySlotDone
MOVE.L spsPointer(A0),siDirPtr(A1) ; set ptr to sRsrc dir in sInfo record
VerifySlotDone
adda.w #fhBlockSize,sp ; de-alloc space on stack
MOVE D0,siInitStatusA(A1) ; set current status
MOVEM.L (SP)+,D1/A2
RTS ; done - VerifySlot
EndWith
;_______________________________________________________________________________________
; GetByteLane - get the byte lane field
;
; Read and verify the byte lane field in the format header block of a declaration ROM.
; Start looking from the byte lane given. The byte lane value determines the address
; in the ROM to look ($FsFFFFFF - $FsFFFFFC). This routine handles the case where reading
; an unsupported bytelane field from the ROM causes a bus exception, and where it does
; not.
;
; The byte lane field in the declaration ROM is a two nibble field. The high nibble
; is the complement of the low nibble. The low nibble indicates the byte lanes
; supported (0-$F).
;
; Input : reg D1 = byte lane to start from (0-3)
; A0 = ptr to spBlock (free to use - but not used in this routine)
; A1 = ptr to sInfo record for card
; Output : reg D0 = status, 0=ok CCR reflects status
; D1 = new byte lane value
;
GetByteLane
movem.l d2/a0/a2,-(sp) ; <2.0>
MOVE.L siROMAddr(A1),A0 ; A0 = ptr to ROM
; Loop until a valid byte lane value is found
slotjsr InstallBus ; switch to 32bit mode and new bus exception <2.0>
lea @EndLoop,a2 ; addr to go if bus error occurs <2.0>
@Loop
MOVE.B (A0),D0 ; NUBUS READ - read bytelane field from ROM
moveq #$0f,d2 ; <2.0>
and.b d0,d2 ; mask d2=byte lane value <2.0>
beq.s @EndLoop ; byte lane value cannot be zero <2.0>
not.b d0 ; complement high nibble <2.0>
asr.w #4,d0 ; get high nib which should be complement of low <2.0>
CMP.B D0,D2 ; same?
BNE.S @EndLoop ; error - not the same, try again
BTST.L D1,D0 ; is this the byte lane we think we have?
BNE.S @Good ; good - found a valid byte lane
@EndLoop suba.w #1,a0 ; decrement a0 = ROM ptr to next byte lane
DBRA D1,@Loop ; dec byte lane cntr and continue
move.w #smBLFieldBad,d0 ; error - no valid byte lane field
BRA.S @Done
@Good move.b d0,siCPUByteLanes(a1) ; good - save byte lane value from ROM <2.0>
move.l a0,siROMAddr(a1) ; ptr to top of ROM with correct bytelane start <2.0>
MOVE.L A0,D0 ; get last byte of address
move.b d0,siTopOfROM(a1) ; $FsFFFFF<x> where <x> is top of rom - this field for compatibility <2.0>
moveq #noErr,d0 ; set good return
@Done slotjsr RestoreBus ; switch back mmu mode and bus exception
movem.l (sp)+,d2/a0/a2
RTS ; done - GetByteLane
;_______________________________________________________________________________________
; VerifyFormat - verify format block
;
; Given a pointer to a format header block image, verify that all the required fields
; have reasonable values. The format block is in RAM pointed to by reg A2
;
; Input : reg A0 = ptr to spBlock (free to use)
; A1 = ptr to sInfo record for card
; A2 = ptr to format block image
; Output : reg D0 = status, 0=ok CCR reflects status
;
VerifyFormat
; Check ROM format
CMP.B #AppleFormat,fhFormat(A2) ; check for an Apple format type
bne.s @Error ; not apple format - log as error
; Check revision level
CMP.B #ROMRevRange,fhROMRev(A2) ; the rev number must be less than 9<***why?***>
bhi.s @Error ; revision number out of range
; Check fhReserved for zero.
TST.B fhReserved(A2) ; reserved field must be zero
bne.s @Error ; not zero - error
; Check sResource Directory Offset (Offset must not be nil, although the reserved
; field must be nil).
MOVE.L fhDirOffset(A2),D0 ; get D0 = directory offset value
beq.s @Error ; zero offset <2.0>
rol.l #8,d0 ; d0 = xxxx xxxx xxxx <id> <2.0>
ext.w d0 ; sign extend the <id> <2.0>
beq.s @Done ; ok - id field is zero
@Error move.w #smFormatErr,D0 ; some format header error
@Done RTS ; done - VerifyFormat
;_______________________________________________________________________________________ <2.0>
; VerifyCRC - verify declaration ROM CRC
;
; Verify that a slot's declaration ROM's CRC matches the value in the format block.
; The CRC calculations are really a modified checksum. If the length field in the
; format header block is zero, then the checksum is not calculated.
;
; The algorithm used is :
; start pointer at bottom of ROM
; load sum = 0
; @1 rotate sum left by one bit
; if pointer is pointing to CRC field in format header, goto @2
; get a byte
; add byte to sum
; @2 increment pointer to next data byte
; goto @1 until done
;
; Input : reg A0 = ptr to spBlock (pre-initialized for this slot)
; A1 = ptr to sInfo record for card
; A2 = ptr to format block image
; Output : reg D0 = status, 0=ok CCR reflects status
;
VerifyCRC
movem.l d1-d4/a2-a4,-(sp)
; Calculate pointer to the bottom of the declaration data (taking into account
; the bytelane supported)
MOVEA.L A2,A4 ; A4 = ptr to format blk
move.l fhLength(a4),d2 ; d2 = length of declaration ROM data
beq.s @Done ; zero length - ignore checksum calculation
moveq #1,d1
sub.l d2,d1 ; d1 = negative offset to bottom of rom
MOVE.L siROMAddr(A1),spsPointer(A0) ; ptr to top of ROM
MOVE.L D1,spOffsetData(A0) ; D1 = negative offset to bottom
_sCalcsPointer ; calc pointer to bottom
BNE.S @Done
MOVE.L spsPointer(A0),A3 ; set A3 = ptr to bottom of declaration ROM
; Setup for calculating CRC. Since we are stepping through the ROM one byte at a
; time, we are calculating the step register (indicating which byte lanes are valid).
; The pointer increment is done by macro which uses the step register.
BSET.B #fConsecBytes,spFlags(A0) ; calc for consecutive bytes.
_sCalcStep ; calculate the step value.
BNE.S @Done
MOVE.L spResult(A0),D4 ; D4 = the quad step value
MOVEQ #0,D1 ; init D1 = crc sum
MOVEQ #0,D3 ; temp reg - bits 8-15 must be zero for sNextStep
; Loop and calculate CRC - treat the CRC field in the format header as zero (4 bytes)
; reg A3 = ptr to bottom of declaration ROM
; reg D1 = crc sum, D2 = length of ROM, D3 = temp, D4 = step register
slotjsr InstallBus ; switch to 32bit mode and new bus exception
move.w #smCRCFail,d0 ; prepare for a bad CRC error return
lea @Restore,a2 ; set addr to jmp if bus error
@Loop
ROL.L #1,D1 ; Rotate-left the crc value.
cmp.l #fhCRC+4,d2 ; are we at crc field yet?
bhi.s @Continue ; not yet - read byte from card's rom
cmp.l #fhCRC,d2 ; are we in the crc field ?
bhi.s @EndLoop ; yes - inc pass this byte
@Continue
MOVE.B (A3),D3 ; NUBUS READ - read D3 = the next byte
add.l d3,d1 ; update the CRC value.
@EndLoop
sNextStep D4,D3,A3 ; point to the next byte in ROM.
SUBQ.L #1,D2 ; dec 'bytes left' cntr
bne.s @Loop ; continue looping
; Done computing the CRC value. Compare with the value stored in the format header
CMP.L fhCRC(A4),D1 ; cmp computed CRC with format ROM's CRC
BNE.S @Restore ; error - no match
moveq #noErr,d0 ; CRC matches - set good return
@Restore slotjsr RestoreBus ; switch back mmu mode and bus exception
@Done movem.l (sp)+,d1-d4/a2-a4
RTS ; end - VerifyCRC
;_______________________________________________________________________________________ <h3> djw
; InitsRsrc - initialize the slot resource table
;
; Loop through the given slot's sRsrc directory and add all the sRsrcs to the
; SRT. The SRT is actually made up of fixed sized blocks linked together. A
; slot or id of $FF indicates the last entry in the block. An SRT block consist
; of the block, and a link block at the end indicating the end of the block and
; linking to the next block.
;
; Input : a0 = ptr to spBlock
; Output : none
;
; spBlock : -> spSlot slot number
Export InitsRsrc
with srrBlock,srtLink
InitsRsrc
@regs reg d1-d3/a1-a2
movem.l @regs,-(sp)
; Check the slot's status
_sFindsInfoRecPtr ; get ptr to sInfoRecord
bne.s @Done ; slot not valid - done
movea.l spResult(a0),a2 ; a2 = ptr to sInfoRecord
tst.w siInitStatusA(a2) ; is the slot status ok?
bmi.s @Done ; bad slot - done
; Calculate the step value for this slot so we can step through the sRsrc dir
move.l siDirPtr(a2),spsPointer(a0) ; set ptr field to get step value for
move.b siCPUByteLanes(a2),spByteLanes(a0) ; set byte lanes field
bset.b #fConsecBytes,spFlags(a0) ; set flag for step value for bytes
_sCalcStep
bne.s @Done
; Loop through the sResource directory. Check that the sResource id's are in
; acsending order. The last entry must have id = $FF.
; d1 = last id read, d2 = ptr to current dir entry, d3 = temp
move.l spResult(a0),spParamData(a0) ; set step value for reading bytes
move.l siDirPtr(a2),d2 ; set d2 = ptr to current dir entry
moveq.l #0,d1 ; zero last id read
@Loop move.l d2,spsPointer(a0) ; set spsPointer to addr of id to read in dir
slotjsr Read4Bytes ; read <id><offset> - inc spsPointer to next long
bne.s @Done ; an error - stop adding SRT entries
move.l spsPointer(a0),d3 ; get d3 = ptr to next id to read
move.l d2,spsPointer(a0) ; restore ptr to current dir entry
move.l d3,d2 ; setup d2 = ptr to next entry in sRsrc dir
; Check for acsending order in sResource directory id's
move.b spResult(a0),d3 ; get high byte to get <id> field
cmp.b #$ff,d3 ; end of list ?
beq.s @Done ; done - a good return
cmp.b d1,d3 ; is new id greater than last id ?
bls.s @Done ; id's out of order
move.b d3,d1 ; set reg d1 = last id read
; Given the sRsrc id, insert a new entry into the SRT
move.b d3,spId(a0) ; set sRsrc id to insert
clr.l spsPointer(a0) ; clear fields used by _InsertSRTRec
clr.w spIOReserved(a0)
clr.w spRefNum(a0)
clr.b spExtDev(a0)
clr.b spHwDev(a0)
clr.l spParamData(a0) ; make sure to insert sRsrc as enabled
_InsertSRTRec ; insert <slot><id> sRsrc into SRT
beq.s @Loop ; continue inserting sRsrc's
@Done
movem.l (sp)+,@regs
rts
endwith
;_______________________________________________________________________________________ <h3> djw
; InitsPRAM - initialize slot PRAM
;
; Each slot is assigned 8 bytes of PRAM: <board id><6 user bytes>. On boot,
; the <board id> is compared against the card in the slot. If they are
; different, then the PRAM is initialized. If the card has a PRAM initialization
; record in its declaration ROM, then the user bytes along with the new <board id>
; are written into PRAM. If there is no PRAM init record, or if the slot is bad,
; then the PRAM is zeroed.
;
; Input : a0 = ptr to spBlock
; Output : none
;
; spBlock : -> spSlot slot number
Export InitsPRAM
InitsPRAM
@regs reg d1-d3/a1-a2
movem.l @regs,-(sp)
suba.w #SizesPRAMRec,sp ; alloc slot PRAM buffer
movea.l sp,a1 ; a1 = ptr to PRAM buffer
clr.l (a1) ; zero pram buffer (8 bytes)
clr.l 4(a1)
; Get the state of this slot. If the slot is disabled or reserved, then DO NOT ZERO
; PRAM. If the pram has already been initialized, then do not initialize again.
_sFindsInfoRecPtr ; get ptr to sInfoRecord
bne @Done ; slot invalid - done
movea.l spResult(a0),a2 ; a2 = ptr to sInfoRecord
cmpi.b #statePRAMInit,siState(a2) ; has PRAM already been initialized ?
bge @Done ; already initialized - done
tst.w siInitStatusA(a2) ; is the slot status ok?
beq.s @readPRAM ; slot ok - read board id from pram
cmp.w #smDisabledSlot,siInitStatusA(a2) ; is slot disabled?
beq @Done ; don't touch disabled slot's pram
cmp.w #smReservedSlot,siInitStatusA(a2) ; is slot reserved?
beq @Done ; reserved is the same as disabled
cmp.w #smEmptySlot,siInitStatusA(a2) ; is slot empty?
beq @Done ; empty is the same as disabled
bra.s @writePRAM ; slot status is bad - zero pram
; Read PRAM to get the current board id.
@readPRAM
move.l a1,spResult(a0) ; pass ptr to read PRAM bytes into
_sReadPRAMRec ; return (a1).w = board id
move.w (a1),d3 ; d3 = board id from PRAM
clr.l (a1) ; zero pram buffer (8 bytes)
clr.l 4(a1)
; Read the board id from the board sRsrc in the config ROM. Compare the card board id
; with the pram board id. If they do not match, then the card in the slot has changed
; so we should either zero or initialize the pram for the new card. Slot zero is a
; special case for board sResources. The universal ROM supports multiple board sResource
; records in the declaration ROM so we can represent different CPU's. Therefore, for
; slot zero, loop through all the board sResource records found, trying to match the
; pram board id.
moveq.l #0,d1 ; sRsrc id to start looking at (incase of slot 0)
@Loop
move.b d1,spId(a0) ; pass sRsrc id to routine to begin looking from
slotjsr GetBoard ; return board sRsrc and sInfo rec ptrs
bne.s @writePRAM ; no board sRsrc - write zero PRAM
; Board sResource is found - read the board id
move.b spId(a0),d1 ; save spId incase we need to loop (for slot 0)
move.b #Boardid,spId(A0) ; read board id field from board sRsrc
_sReadWord
beq.s @doMatch ; compare with pram board id
move.w #smNoBoardId,siInitStatusA(A2) ; no board id - fatal error
bra.s @writePRAM ; slot is bad - zero PRAM
; Compare the card's board id with the pram board id. d3 = pram board id
@doMatch
move.w spResult+2(a0),d2 ; d2 = card board id
cmp.w d3,d2 ; compare board id's
beq.s @Done ; board id's match - do not initialize
; Board id's are different - if this is slot zero, then look for another board sResource
tst.b spSlot(a0) ; slot zero ?
beq.s @Loop ; yes - look for another board sResource
; Look for a pram init record on the card's config ROM. If found, use the values to
; initialize pram.
move.b #PRAMInitData,spId(a0) ; look for PRAM init in board sRsrc
_sReadPBSize ; spsPointer = ptr to board sRsrc list
bne.s @notFound ; not found - write new board id, zero the rest
subq.l #4,spSize(a0) ; sub 4 bytes for size field
move.l a1,spResult(a0) ; pass ptr to PRAM buffer
_sReadStruct ; read the PRAM init rec into (a1)
bne.s @notFound ; failed - just write board id
bset.b #fCardIsChanged,siStatusFlags(a2) ; indicate card has changed in sInfo record
@notFound
move.w d2,(a1) ; set new board id in buffer
@writePRAM
move.l a1,spsPointer(a0) ; ptr to pram data
_InitSlotPRAM ; initialize board id and user PRAM
@Done
adda.w #SizesPRAMRec,sp ; free pram data buffer
movem.l (sp)+,@regs
rts
;_______________________________________________________________________________________ <h3> djw
; InitPrimary - execute primaryInit
;
; Execute primary init code for a slot having a primaryInit record in it's board
; sResource. Primary inits are passed parameters in an seBlock.Primary inits are
; executed before patches with interrupts disabled. <in 24bit mode-removed>
;
; Input : a0 = ptr to spBlock
; Output : none
;
; spBlock : -> spSlot slot number
; -> spFlags fWarmStart - if set then a warm start (may be used by primary
; init code)
; seBlock : seSlot -> spSlot
; sesRsrcId -> BoardId
; seFlags -> spFlags
;
Export InitPrimary
InitPrimary
@regs reg d1-d3/a1-a3
movem.l @regs,-(sp)
suba.w #seBlockSize,sp
movea.l sp,a2 ; a2 = ptr to sExec param blk
move.l a2,spsExecPBlk(a0) ; set ptr in spblock to sExec blk
move.b #BoardId,sesRsrcId(a2) ; indicates exec code is from board sResource
bsr.s doPrimaryInit ; execute the primary init
adda.w #seBlockSize,sp
movem.l (sp)+,@regs
rts
;_______________________________________________________________________________________ <8>
; doPrimaryInit - find and execute primaryInit records
;
; Called by Primary_Init. For a single slot, find the board sResource and if there
; is a primary init record, execute it.
;
; Input : reg A0 = ptr to spBlock
; A2 = ptr to sExecBlk
; Output : none
;
; Torches A1/A3.
;
; spBlock : -> spSlot slot number
;
doPrimaryInit
clr.b spId(a0) ; start looking with id = 0
slotjsr GetBoard ; return board sRsrc and sInfo rec ptrs
bne @Done ; bad slot - done
movea.l spsPointer(a0),a3 ; save ptr to board srsrc
movea.l spResult(a0),a1 ; get a1 = ptr to sInfo record
tst.w siInitStatusA(a1) ; test card status
bmi.s @Done ; bad slot - skip it
cmpi.b #statePInit,siState(a1) ; have we already executed primary inits ?
bhs.s @Done ; yes - don't execute a second time
; Check if the board sResource has a primary init record
move.b #PrimaryInit,spId(a0) ; id to search for
_sFindStruct
bne.s @Done ; no primary init record - done
; Load the code and execute the primary init record.
;
Move.l A3,spsPointer(A0) ; Restore ptr to board sRsrc.
Move.b spSlot(A0),seSlot(A2) ; Set slot in sExec blk.
Move.b spFlags(A0),seFlags(A2) ; Xfer warmstart flag (if present).
_sExec ; Execute the code.
; Update the sInfo record status field - vendor status returned in sExec blk.
;
@cleanup Move.b #statePInit,siState(A1) ; Update state variable
Move.w seStatus(A2),siInitStatusV(A1) ; Update vendor status
Bpl.s @done ; Good primary init status - done
Move.w #smInitStatVErr,siInitStatusA(A1) ; Some fatal vendor status returned
@done Rts
;_______________________________________________________________________________________ <h5> djw
; StubCheckSlot - check if a slot status has changed
;
; This is a little stub routine for the real CheckSlot routine in the slot manager
; overpatch file. We need this stub because the slot manager jump table in ROM only
; has 16 bit offset and the overpatch file is out of range. We therefore vector to
; this stub routine which then jumps to the overpatch file.
;
; Input : none
; Output : none
;
export StubCheckSlot
import CheckSlot
StubCheckSlot
bra.l CheckSlot ; go to the real routine
;_______________________________________________________________________________________ <h5> djw
; StubAddCard - add a card to slot manager
;
; This is a little stub routine for the real StubAddCard routine in the slot manager
; overpatch file. We need this stub because the slot manager jump table in ROM only
; has 16 bit offset and the overpatch file is out of range. We therefore vector to
; this stub routine which then jumps to the overpatch file.
;
; Input : none
; Output : none
;
export StubAddCard
import AddCard
StubAddCard
bra.l AddCard ; go to the real routine
;_______________________________________________________________________________________ <h5> djw
; StubRemoveCard - remove a card from the slot manager
;
; This is a little stub routine for the real CheckSlots routine in the slot manager
; overpatch file. We need this stub because the slot manager jump table in ROM only
; has 16 bit offset and the overpatch file is out of range. We therefore vector to
; this stub routine which then jumps to the overpatch file.
;
; Input : none
; Output : none
;
export StubRemoveCard
import RemoveCard
StubRemoveCard
bra.l RemoveCard ; go to the real routine
;_______________________________________________________________________________________ start <LW2>
; EnableBlockXfer - find then enable cards capable of support block xfers as a Slave
;
; Input : a0 = ptr to spBlock
; Output : none
;
; spBlock : -> spSlot slot number
; -> spFlags fWarmStart - if set then a warm start (may be used by primary
EnableBlockXfer
@exit Rts
;end <LW2>
;_______________________________________________________________________________________
; Secondary_Init - secondary initialization
;
; Secondary init records are the same as primary init records, except they are run
; after patches are loaded, with interrupts enabled. If the slot's siInitStatusA field
; value is zero or positive, the secondary init is executed. If there is a fatal
; primary init status error smIntStatVErr, but the vendor status error (field
; siInitStatusV) is in the range svTempDisable (-32768) to svDisabled (-32640), then
; the secondary init will still be run. The secondary init status will replace the
; primary init status. Normally the vendor error is not Apple's concern, but a special
; error is needed to temporarily disable a card, and have the secondary init re-enable it.
;
; A special flag "fTempDisabled" has been added to the sInfo record to help the slot
; manager patch version. A temporarily disabled card will have it's siInitStatusA field
; cleared in the patch, so that the slot manager will look at it. It will have the
; "fTempDisabled" flag set to indicate this state. In this routine, if there is no
; secondary init record, and the "fTempDisabled" flag is set, then an error will be
; placed back in siInitStatusA. Card's should only be in this "temporarily enabled"
; state, within the bounds of the slot manager's execution.
;
; Input : reg A0 = ptr to spBlock
; Output : reg D0 = status, 0=ok CCR reflects status
; A0 = ptr to spBlock
;
; spBlock : -> spFlags fWarmStart - if set then a warm start (may be used by primary
; init code)
;
; seBlock : seSlot <- spSlot
; sesRsrcId <- #BoardId
; seFlags <- spFlags
;
Proc
Export Secondary_Init, SecondaryEnd
WITH spBlock,sInfoRecord,seBlock
Secondary_Init
movem.l d1-d2/a1-a3,-(sp)
suba.w #seBlockSize,sp
movea.l sp,a2 ; a2 = ptr to sExec param blk
move.l a2,spsExecPBlk(a0) ; set ptr in spblock to sExec blk
move.b #BoardId,sesRsrcId(a2) ; indicates exec code is from board sResource
; Loop through all slots and get their board sResources. See if there is a secondary init
; record associated with it.
moveq #sLastSlot,d1 ; start with slot $E <2.0>
@Loop
move.b d1,spSlot(a0)
bsr.s DoSecondaryInit ; execute slot secondaryInit code <h7> djw
@EndLoop dbra d1,@Loop ; dec slot count <2.0>
cmpi.b #sLastSlot,d1 ; done ?
bls.s @Loop ; not done yet - continue
If SeparateFile or Not forROM then ; code for 32bitQD INIT and RAM patch <8>
; Re-define the default video device in-case a temporarily disabled card was brought
; back to life by secondary inits.
move.w sr,-(sp) ; save current interrupt level
ori.w #hiIntMask,sr ; disable all interrupts again
bsr ReConfigVideo
move.w (sp)+,sr ; restore interrupts
endif ; <8>
adda.w #seBlockSize,sp
movem.l (sp)+,d1-d2/a1-a3
rts
;_______________________________________________________________________________________ <h11> djw
; DoSecondaryInit - find and execute secondaryInit records
;
; Called by Secondary_Init. For a single slot, find the board sResource and if there
; is a secondary init record, execute it.
;
; Input : reg a0 = ptr to spBlock
; a2 = ptr to sExecBlk
; Output : none
;
; trashes d0/d2-a1/a3.
;
; spBlock : -> spSlot slot number
;
Export DoSecondaryInit
DoSecondaryInit
@regs reg d0-d2/a1/a3
movem.l @regs,-(sp)
clr.b spId(a0) ; start looking with id = 0 <4>
slotjsr GetBoard ; get the sInfo and board sRsrc ptrs <4>
bne.s @Done ; bad slot
movea.l spsPointer(a0),a3 ; save ptr to board srsrc
movea.l spResult(a0),a1 ; get a1 = ptr to sInfo record
; Check the status of this slot. If "temporarily disabled", then enable the slot
cmpi.b #stateSInit,siState(a1) ; have we already executed secondary init ?
bhs.s @Done ; yes - skip this slot
move.w siInitStatusA(a1),d0 ; get card status
bpl.s @Continue ; status ok
cmpi.w #smInitStatVErr,d0 ; is card temporarily disabled ?
bne.s @Done ; no - card is really bad
cmpi.w #svDisabled,siInitStatusV(a1) ; vendor temporarily disabled code ?
bgt.s @Done ; no - a fatal vendor code
clr.w siInitStatusA(a1) ; temp disabled - clr err so FindStruct will work
bset.b #fTempEnabled,siStatusFlags(a1) ; make sure temp enabled bit is set
; Check if the board sResource has a secondary init record
@Continue move.w d0,d2 ; save status value for siInitStatusA field
move.b #SecondaryInit,spId(a0) ; id to search for
_sFindStruct
beq.s @Execute ; secondary init record found
move.w d2,siInitStatusA(a1) ; no secondary init - restore status error
bclr.b #fTempEnabled,siStatusFlags(a1) ; test and clear temp enabled bit
beq.s @Done ; was not set
move.w #smInitStatVErr,siInitStatusA(a1) ; was "temp enabled" - restore error
bra.s @Done ; continue to next slot
; Load the code and execute the secondary init record
@Execute move.l a3,spsPointer(a0) ; restore ptr to board srsrc
move.b spSlot(a0),seSlot(a2) ; set slot in sExec blk
move.b spFlags(a0),seFlags(a2) ; xfer warmstart flag (if present)
_sExec ; execute the code
; Update the sInfo record status field - vendor status returned in sExec blk
bclr.b #fTempEnabled,siStatusFlags(a1) ; clear temp enabled bit
move.b #stateSInit,siState(a1) ; update state variable
move.w seStatus(a2),siInitStatusV(a1) ; update vendor status
bpl.s @Done ; good secondary init status - continue
move.w #smInitStatVErr,siInitStatusA(a1) ; some fatal vendor status returned
@Done
movem.l (sp)+,@regs
rts
endwith
If SeparateFile or Not forROM then ; <8>
;_______________________________________________________________________________________
; ReConfigVideo - select new default video screen
;
; This routine select a new default video device if the old default was the dummy
; screen. The new default may be a video card which was temporarily disabled, but
; has been re-enabled by a SecondayInit. It deletes the dummy screen from the gDevice
; list and jumps back into ROM to the routine which selects the default video device.
;
; Input: none
; Output: none
;
ReConfigVideo
ROMFROVideo Equ $00000b58 ; hard offset only applies to Mac II rev A roms <4>
; This code deletes the dummy screen in the gDevice list (if present), and searches
; for the default video device all over again (normally done earlier in the start
; code), just in case a video card was temporarily disabled, and re-enabled by the
; secondary init.
; Determine if the main gDevice is the dummy screen. If so, then delete it from the
; gDevice list and look for the default video again (incase the default video card
; was temporarily disabled and is now enabled).
_HideCursor
MOVE.L MainDevice,A1 ; A1 = handle to gDevice from low mem
MOVE.L (A1),A0 ; A0 = ptr to gDevice
TST gdRefNum(A0) ; is ref number zero?
BNE.S @Fixup ; no - not dummy screen
CMP #32,GDRect+right(A0) ; make sure size of rect is 32x32
BNE.S @Fixup ; not dummy screen
CMP #32,GDRect+bottom(A0)
BNE.S @Fixup ; not dummy screen
MOVE.L A1,-(SP) ; push handle of dummy screen gDevice
_DisposGDevice ; get rid of the dummy screen gDevice
CLR.L DeviceList
suba.w #ioQElSize,sp
movea.l sp,a0 ; allocate an iopb into a0 for frovideo
st.b QDExist ; indicate QD environment is invalid so pallette <4>
jsr ([rombase],ROMFROVideo) ; select new default video - slimy jump to hard <4>
adda.w #ioQElSize,sp
_AllocCursor ; fixup cursor to new gdevice
_ShowCursor
; Set the lowmem 'scrnbase' to the proper base address. This should be done in
; 'RdVidParam', but on 1.0 roms, it does not know about 32bit base addresses.
;
; <1.1/DAF> The original version of this code moved dCtlDevBase into ScrnBase which isn't
; correct (it's missing two critical offsets). At this point, ScrnBase is the base address
; of the boot screen's frame buffer (by the first app launch, it will be the main screen's
; frame buffer base). If the machine has 1.0 or 1.1 ROMs (old Slot Manager) then the
; video card's SecondaryInit was responsible for updating the base address in the card's
; gdPixMap. So the fix is to always copy the boot screen gDevice's base address into
; ScrnBase. No other gDevices exist yet so we don't need to look for it. The refnum
; test prevents problems if the dummy screen is still in effect.
@Fixup MOVE.L MainDevice,A0 ; A0 = handle to gDevice from low mem
MOVE.L (A0),A0 ; A0 = ptr to gDevice
MOVE.W gdRefNum(A0),D1 ; is ref number zero?
BEQ.S @Done ; no ref num - no video devices
MOVE.L gdPMap(A0),A0 ; get handle to device pixmap <1.1>
MOVE.L (A0),A0 ; get pointer <1.1>
MOVE.L pmBaseAddr(A0),ScrnBase ; put it in lo-mem <1.1>
@Done MOVEQ #0,D0 ; only good returns
RTS ; done
endif ; <8>
SecondaryEnd
End