;_______________________________________________________________________________________ ; ; 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): ; ; 9/12/93 pdw Removed a push,SwapMMU,pop sequence. ; 9/1/93 SKH Fixed a bug where only LastSDMSelts were being allocated in the dispatch ; table. ; 8/4/93 GMR RC: Added code to enable slave block transfers for BART machines ; (PDM,CF). ; 6/14/93 kc Roll in Ludwig. ; 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. ; 11/17/92 kc Add "IF NOT LC930 THEN" around patchPrimaryInit to facilitate ; dead code stripping for the LC930 build. ; 10/14/92 CSS Change some branch short instructions to branches. ; 09-24-92 jmp Added a pRAM-based mechanism for skipping BootBug altogether if ; it is installed. ; 08-27-92 jmp Added support for Brigent, Inc.’s BootBug card. ; 6/30/92 kc Roll in Horror, comments follow: ;                                • From SlotMgr.a ;
djw Add new selector for DoSecondaryInit. ; • From SlotMgrPatch.a ; djw Added DoSecondaryInit routine. ; 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 ;

3/18/92 djw Add new calls to support docking code - AddCard, RemoveCard, ; CheckSlot, and GetSRTEntry. ;

3/5/92 djw Replaced InitSlotMgr, InitsRsrcTable, InitPRAMRecs, and ; Primary_Init entries in the table with new routines. ; • From SlotMgrPatch.a ;

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). ;

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. ; 2/25/91 jmp Added code to check version number of the driver before doing ; PrimaryInit and GetDriver patches. ; 11/19/90 jmp Added in patches for PrimaryInit and GetDriver. ; • From SlotInfo.a ;
3/18/92 djw Add stub entry points for new docking support routines - ; StubAddCard and StubRemoveCard ;

3/6/92 SWC We thank Dave for

(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. ;

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. ;

10/29/91 jmp Added a patch to the VerifySlot routine for supporting super ; sRsrc directories in Slot $0. ; 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>). ; 2/21/92 RB delete rude code which snuck in late at night while no one was ; looking… ; 2/12/92 RM Change BRA.S to BRA.L. ; 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 ;

djw IMPORT SlotEmpty ; 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 _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 DoSecondaryInit ;$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 StubAddCard ;$1E

djw DispatchVector StubRemoveCard ;$1F

djw ; Advanced (SDM private routines). DispatchVector InitsInfo ;$20

djw DispatchVector InitPrimary ;$21

djw DispatchVector CardChanged ;$22 DispatchVector SlotExec ;$23 DispatchVector OffsetData ;$24 DispatchVector InitsPram ;$25

djw DispatchVector ReadPBSize ;$26 DispatchVector StubCheckSlot ;$27

djw DispatchVector CalcStep ;$28 DispatchVector InitsRsrc ;$29

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 ; 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

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. ;======================================================================================= ;_______________________________________________________________________________________

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 ; Initialize the Docking Manager so built-in video and docking cards can use its facilities BSR.L InitDocking ; initialize the Docking Manager

; Set up the warm/cold start flag for later. 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< 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 @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 ; ;_______________________________________________________________________________________

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 ;_______________________________________________________________________________________

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 ; 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 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 ;_______________________________________________________________________________________

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 - 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 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 sRsrc into SRT beq.s @Loop ; continue inserting sRsrc's @Done movem.l (sp)+,@regs rts endwith ;_______________________________________________________________________________________

djw ; InitsPRAM - 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 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.s @Done ; don't touch disabled slot's pram cmp.w #smReservedSlot,siInitStatusA(a2) ; is slot reserved? beq.s @Done ; reserved 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 ;_______________________________________________________________________________________

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. ; ; 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 IF NOT LC930 THEN ; Identify Apple Cards whose PrimaryInit code is faulty, and execute fixed ; versions from the CPU ROM. Bsr.s PatchPrimaryInit ; If PatchPrimaryInit returns a Tst.b D0 ; result >= 0, don’t execute Bpl.s @cleanup ; normal PrimaryInit. ENDIF ; 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 ;____________________________________________________________________________ ; ; PatchPrimaryInit and support (called from doPrimaryInit). ; ; Entry: A0 -- points to spBlock. ; A1 -- points to sInfoRecord. ; A2 -- (after restore from BigJump) points to sExec param blk. ; A3 -- points to board sResource. ; ; D1 -- contains spSlot (we use spBlock.spSlot here, though). ; ; Exit: A0-A3 -- preserved. ; D1 -- preserved. ; ; Purpose: The purpose of SlotPrimaryInitPatch is to identify Apple ; Cards whose PrimaryInit code is faulty, and execute fixed ; versions from the CPU ROM. ; ; SlotPrimaryInitPatch is executed from the (non-exported) ; routine doPrimayInit in SlotInfo.a. ;____________________________________________________________________________ IF NOT LC930 THEN With seBlock,spBlock Import GetDevIndex,JsrTbl PatchPrimaryInit @saveRegs Reg A0-A3/D1/D3 ; Define some work and scratch registers, Movem.l @saveRegs,-(Sp) ; and save them on the stack. Move.l A0,A3 ; Save the spBlockPtr for later. Bsr GetDevIndex ; Get the device/card index into D0. Move.l D0,D3 ; If the device index is negative, then Bmi.s @done ; PrimaryInit doesn’t need patching. Lea JsrTbl,A1 ; Point to base of JsrTbl. Lsl.l #2,D3 ; Adjust index. Move.l A1,A0 ; Copy base address. Add.l D3,A0 ; Point to proper entry. Add.l (A0),A1 ; Load A1 with effective address of PrimaryInit. Move.l A3,A0 ; Restore spBlockPtr. Move.b spSlot(A0),seSlot(A2) ; Set the right slot number. Move.b spFlags(A0),seFlags(A2) ; Set the flags. Move.l A2,A0 ; Set A0 to sExecBlkPtr for fake sExec call. Jsr (A1) ; Execute the PrimaryInit. Move.l D3,D0 ; Return result code. @done Movem.l (Sp)+,@saveRegs Rts Endwith ENDIF ;_______________________________________________________________________________________
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 ;_______________________________________________________________________________________
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 ;_______________________________________________________________________________________
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 ; 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 Testfor BARTExists ; are we on a ColdFusion or PDM bne.s @goodMach Testfor MUNIExists ; do we have MUNI Nubus Controller? Beq @exit ; no, leave @goodMach MoveM.l A0/D0-D2, -(SP) Clr.b spID(A0) ; Begin search with ID 0. Clr.b spExtDev(A0) ; No external device(s). Clr.b spHwDev(A0) ; No hardware device(s). Clr.b spTBMask(A0) ; No mask in search. Move.w #catBoard,spCategory(A0) ; Look for: Board sRsrc Clr.w spCType(A0) Clr.w spDrvrSW(A0) Clr.w spDrvrHW(A0) Move.l #(1< ;_______________________________________________________________________________________ ; 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 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 ;_______________________________________________________________________________________ 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