; ; Hacks to match MacOS (most recent first): ; ; 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 didn’t 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 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' 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 ; 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 _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 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 ; 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 where 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 <2.0> ext.w d0 ; sign extend the <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 - 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 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: <6 user bytes>. On boot, ; the 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 ; 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. ; ; 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