sys7.1-doc-wip/OS/SlotMgr/SlotMgrInit.a
2020-05-10 13:37:38 +08:00

1178 lines
42 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

;
; Hacks to match MacOS (most recent first):
;
; <Sys7.1> 8/3/92 Elliot make this change
; 9/2/94 SuperMario ROM source dump (header preserved below)
;
;_______________________________________________________________________________________
;
; 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):
;
; <17> 5/4/92 JSM The checks for isUniversal in this file should just be forROM.
; (Dean really didnt have to do all that work in <14>).
; <15> 1/7/92 RB Rolled in Terror changes.
; <14> 8/30/91 DTY Define isUniversal here since its 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'
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 SlotEmpty ; <djw>
IMPORT pGetBoard ; <3>
IMPORT SlotManager ; <3>
IMPORT p040BusException ; <4>
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 SlotEmpty ;$0F
; 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 SlotEmpty ;$1E
DispatchVector SlotEmpty ;$1F
; Advanced (SDM private routines).
DispatchVector SlotEmpty ;$20
DispatchVector SlotEmpty ;$21
DispatchVector CardChanged ;$22
DispatchVector SlotExec ;$23
DispatchVector OffsetData ;$24
DispatchVector SlotEmpty ;$25
DispatchVector ReadPBSize ;$26
DispatchVector SlotEmpty ;$27
DispatchVector CalcStep ;$28
DispatchVector SlotEmpty ;$29
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
;_______________________________________________________________________________________
; 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
;
InitSlotMgr Proc Export
with spBlock,sInfoRecord,FHeaderRec,slotGlobals,seBlock
movem.l d1/a1/a2,-(sp)
bsr Subroutine
; 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
_sFindsInfoRecPtr ; get ptr to sInfoRecord
movea.l spResult(a0),a1 ; a1 = ptr to sInfoRecord
tst.w siInitStatusA(a1) ; is the slot status ok?
bmi.s @SlotDone ; bad slot - done
bsr VerifySlot ; verify the config rom format
@SlotDone dbra d1,@Loop
movem.l (sp)+,d1/a1/a2
rts
Subroutine
@regs reg d1-d2/a0-a3
movem.l @regs,-(sp) ; save registers
; Enumerate all the slots
; d0 = number of slots found
; sp points to array of index/-1 words
move.l sp,SInfoPtr ; create a fake SlotMgr global block for InstallBus
sub.w #slotGlobalSize,sp
move.l #minorLast,a1 ; explore the standard slot space ($Fn......)
move.l #TotalSlots-1,d1
move.l #0,d0
lea @BusError,a2 ; switch to 32-bit mode, and jump to a2 on bus error
slotjsr InstallBus
@NextSlot
sub.l #2,sp
move.b (a1),d2
add.w #1,d0
move.w d0,(sp)
bra.s @NoBusError
@BusError
move.w #-1,(sp)
@NoBusError
sub.l #minorStep,a1
sub.w #1,d1
bne.s @NextSlot
slotjsr RestoreBus ; undo InstallBus
; Allocate the necessary memory as one contiguous block
mulu.w #sInfoNewSize,d0 ; size of N sInfoRecords
add.l #(slotGlobalSize \ ; size of globals
+(4*TotalSlots)+48 \ ; size of sInfor vector table ?????
),d0
_NewPtr ,sys,clear ; alloc block
adda.w #slotGlobalSize,a0 ; globals are at a negative offset from sInfo tbl
move.l a0,sInfoPtr ; set ptr to sInfo table
move.l a0,a1
; 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 #smEmptySlot, \
siInitStatusA(a0) ; set slot status to disabled
lea sInfoNewSize(a0),a0 ; inc a0 to reserved sInfoRecord
move.l #$40000,d0
sub.l #1,d0
add.l RomBase,d0
move.l d0,siROMAddr(a0)
move.w #1,siTOConst(a0)
move.l a0,(a1) ; ?????
move.w #1,d0
@Loop
movea.l a0,a2 ; save ptr to spBlock
move.w (sp)+,d1 ; pop word from
muls.w #sInfoNewSize,d1 ; size of sInfoRecord
add.l d1,a2
move.l a2,(a1,d0.w*4) ; set ptr in sInfo vector table
move.w #retryCnt,siTOConst(a2) ; set default bus error retry cnt (not used)
move.b d0,siSlot(a2) ; set slot number
not.l siROMAddr(a2) ; set ROM address ???
bfins d0,siROMAddr(a2){4,4} ; inset slot number to get $fsffffff
add.w #1,d0
cmp.w #sLastSlot,d0
ble.s @Loop
add.w #slotGlobalSize,sp ; pop fake globals
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.S GetByteLane ; get a valid byte lane - return byte lane value in D1
BNE.S 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.S VerifySlotDone
@GoodRom 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
;_______________________________________________________________________________________
; InitsRsrcTable - 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
InitsRsrcTable Proc Export
with spBlock,sInfoRecord,FHeaderRec,slotGlobals,seBlock,srrBlock,srtLink
@regs reg a1-a2
movem.l @regs,-(sp)
slotjsr AllocSRTBlk
move.l a1,SRsrcTblPtr
clr.b spSlot(a0) ; clear fields used by _InsertSRTRec
clr.w spIOReserved(a0)
clr.w spRefNum(a0)
clr.b spExtDev(a0)
clr.b spHwDev(a0)
; Check the slot's status
@NextSlot
_sFindsInfoRecPtr ; get ptr to sInfoRecord
movea.l spResult(a0),a2 ; a2 = ptr to sInfoRecord
tst.w siInitStatusA(a2) ; is the slot status ok?
bmi.s @BadSlot ; bad slot - done
bsr @InitTheResourceTable
@BadSlot
add.b #1,spSlot(a0)
cmp.b #sLastSlot,spSlot(a0)
ble.s @NextSlot
movem.l (sp)+,@regs
rts
@InitTheResourceTable
movem.l d3-d5/a3,-(sp)
; 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 @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),d4 ; set d4 = ptr to current dir entry
moveq.l #0,d3 ; zero last id read
@Loop move.l d4,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),d5 ; get d5 = ptr to next id to read
move.l d4,spsPointer(a0) ; restore ptr to current dir entry
move.l d5,d4 ; setup d4 = ptr to next entry in sRsrc dir
; Check for acsending order in sResource directory id's
move.b spResult(a0),d5 ; get high byte to get <id> field
cmp.b #$ff,d5 ; end of list ?
beq.s @Done ; done - a good return
cmp.b d3,d5 ; is new id greater than last id ?
bls.s @Done ; id's out of order
move.b d5,d3 ; set reg d3 = last id read
; Given the sRsrc id, insert a new entry into the SRT
move.b d3,spId(a0) ; set sRsrc id to insert
move.l spResult(a0),d5
and.l #$FFFFFF,d5
move.l d5,spOffsetData(a0)
_SCalcSPointer
bne.s @Done
cmp.w #-1,(a1)
bne.s @no
move.l a1,a3
slotjsr AllocSRTBlk
move.l a1,2(a3)
@no
clr.l $18(a0)
slotjsr InitEntry
bne.s @Done
add.w #1,([sInfoPtr],srtCnt)
move.l a1,([sInfoPtr],lastSRTPtr)
add.l #$18,a1
bra @Loop
@Done
movem.l (sp)+,d3-d5/a3
rts
;_______________________________________________________________________________________
; InitPramRecs - 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
InitPramRecs Proc Export
with spBlock,sInfoRecord,FHeaderRec,slotGlobals,seBlock,srrBlock,srtLink
@regs reg d1-d4/a1-a2
movem.l @regs,-(sp)
suba.w #SizesPRAMRec,sp ; alloc slot PRAM buffer
movea.l sp,a1 ; a1 = ptr to PRAM buffer
moveq #sLastSlot,d1
@NextSlot
; Read PRAM to get the current board id.
move.b d1,spSlot(a0)
clr.w (a1) ; zero board ID in pram buffer
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,d4 ; sRsrc id to start looking at (incase of slot 0)
@Loop
move.b d4,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
movea.l spResult(a0),a2 ; a2 = ptr to sInfoRecord
tst.w siInitStatusA(a2) ; is the slot status ok?
bmi.s @writePRAM ; slot status is bad - zero pram
cmpi.b #statePRAMInit,siState(a2) ; has PRAM already been initialized ?
bge.s @Done ; already initialized - done
; Board sResource is found - read the board id
move.b spId(a0),d4 ; 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 d1 ; 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
dbra d1,@NextSlot
moveq #0,d0
adda.w #SizesPRAMRec,sp ; free pram data buffer
movem.l (sp)+,@regs
rts
;_______________________________________________________________________________________
; Primary_Init - 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 Primary_Init
Primary_Init
@regs reg d1/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
moveq #0,d0 ; MMU to 32-bit mode
_SwapMMUMode
move.b d0,-(sp)
move.b #0,spSlot(a0)
bsr.s doPrimaryInit ; execute the primary init
moveq #sLastSlot,d1
@Loop
move.b d1,spSlot(a0)
bsr.s doPrimaryInit ; execute the primary init
subq #1,d1
bnz.s @Loop
move.b (sp)+,d0 ; restore MMU
_SwapMMUMode
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 D1,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
;_______________________________________________________________________________________
; 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)
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 d1,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
@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
;_______________________________________________________________________________________
; 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
SecondaryEnd
End