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

3807 lines
138 KiB
Plaintext

;
; File: SlotMgr.a
;
; Contains: Macintosh Interface to the Slot Manager
;
; Written by: George Norman, June 1, 1986; (rewritten) David Wong, March 12, 1989
;
; Copyright: © 1986-1993 by Apple Computer, Inc., all rights reserved.
;
; Change History (most recent first):
;
; <SM14> 11-07-93 jmp Fixed two more bugs in RemoveCard: 1) Made sure that only the
; fAll bit is set when searching for sResources to delete, and 2)
; made sure that all resouces belonging to a particular slot would
; in fact be found (and now not skipped).
; <SM13> 2/8/93 rab Sync up with Horror. Comments follow: <H14> 8/24/92 SWC Fixed a
; bug in RemoveCard: the wrong register was being used.
; <SM12> 1/20/93 PN Re-roll in PatchGetCString so that d0 get zeroed out correctly.
; <SM11> 11/18/92 kc Import GetDriverPatch to fix problem introduced by last checkin.
; <SM10> 11/17/92 kc Add "IF NOT LC930 THEN" around GetDriverPatch to facilitate dead
; code stripping for the LC930 build.
; <SM9> 10/22/92 CSS Change some branch short instructions to branches.
; <SM8> 09-24-92 jmp Fixed a bug in the GetDevIndex utility where a register was
; being trashed.
; <SM7> 6/30/92 kc Roll in Horror, comments follow:
;ÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊ ¥From SlotManagerPatch.a:
; <H12> 6/10/92 djw Modify AddCard to execute SecondaryInit's.
; <SM6> 6/20/92 PN Roll in patchIIciROM.a. Fix a bug in pInitEntry to restore the
; spID before calling _sFindDevBasse
; <SM5> 5/16/92 kc Roll in Horror. Comments follow:
; ¥From SlotManager.a:
; <H3> 3/18/92 djw Add new calls to support docking code - AddCard, RemoveCard,
; CheckSlot, and GetSRTEntry.
; <H2> 3/5/92 djw Replaced InitSlotMgr, InitsRsrcTable, InitPRAMRecs, and
; Primary_Init entries in the table with new routines.
; <T3> 11/5/90 CCH Fixed out of range error due to SlotMgrPatch.a moving to second
; half-meg.
; <T2> 9/17/90 CCH Patched Slot interrupt jump table in RAM for Eclipse.
; ¥From smspecial.a:
; <H3> 1/7/91 jmp Because of a misplaced label, the sRsrcFlag was only being read
; for Slot $0 devices.
; <H2> 12/11/90 HJR Fix a bug in special casing for slot zero: TestForRBV is not
; appropriate since not all machines that need special casing for
; slot zero have an RBV.
; ¥From smadvanced.a
; <T5> 4/23/91 jmp Cleaned up StatLoadPatch comments.
; <T4> 4/22/91 CCH Added a patch to StatLoadDrvr to flush the cache after loading
; in slot resources. Also slightly modified the way GetSlotDrvr
; was being patched.
; <T3> 3/29/91 CCH Added in a patch to SlotExec to flush the caches before
; executing code read from a NuBus card.
; <T2> 11/19/90 jmp Added in patch for GetDriver.
; ¥From SlotMgrPatches.a
; <H9> 4/24/92 HJR Added NiagraVIA2SlotInt and necessary install code for VSC video
; interrupts.
; <H8> 04/16/92 jmp Added a routine so that Slot $0 framebuffers can actually use
; the Minor/Major base address offset sResources like other slots
; can.
; <H7> 3/18/92 djw Complete CheckSlot call for DBLite docking code. Add AddCard and
; RemoveCard calls
; <H5> 02/05/92 jmp Unfortunately, I put some tables in the middle of this file
; that, in Cyclone, will get bigger. So, I moved them from the
; middle of the file into the pad space. Also, I generalized the
; routine that decides whether a DeclROMÕs PrimaryInit/Driver
; should be patched by not stopping once I found the version I was
; looking for (e.g., in case we need to patch out versions 1, 2,
; and 3 of the 8¥24 card).
; <H3> 10/29/91 jmp Added the VerifySlotPatch routine for supporting super sRsrc
; directories in Slot $0.
; <H2> 10/22/91 SAM/jmp Discontinued patching out the JMFB PrimaryInit & Driver on the
; Bungee (1.1) version of the 4¥8/8¥24 Card ROM. From Zydeco-TERROR ROM.
; ¥From SlotInfo.a
; <H5> 3/18/92 djw Add stub entry points for new docking support routines -
; StubAddCard and StubRemoveCard
; <H4> 3/6/92 SWC We thank Dave for <H3> (getting it working in under 25 triesÉ),
; and move the Docking Manager initialization to StartSDeclMgr
; just before running the primary inits so that we can decided
; whether or not to install the built-in LCD driver when DBLite
; (etc.) is inside a docking station and thus the LCD screen is
; not useable.
; <H3> 3/5/92 djw Rewrote slot manager initialization code (major routines from
; beginning of file to SecondaryInit) to facilitate new code for
; DBLite docking station. The major change was to modify the
; routines to execute their functions for a single slot instead of
; for every slot.
; <H2> 10/29/91 jmp Added a patch to the VerifySlot routine for supporting super
; sRsrc directories in Slot $0.
; <SM4> 5/5/92 JSM Roll-in changes from Reality:
; <19> 5/4/92 JSM The one check for isUniversal in this file should just be
; forROM. (Dean really didnÕt have to do all that work in <17>).
; <SM3> 3/18/92 RB Added a WITH statement to use video information record.
; <SM2> 2/20/92 RB Need to switch to 24 bit mode before calling DisposPtr for
; srtRecords in the routine DeleteSRTRec. Made a second pass on
; Terror changes. The Terror code is diferent files and so that
; makes it hard to compare sources. Changed InitSlotPRAM,
; PtrToSlot, pInitEntry, GetBoard, and added MapUnit.
; <18> 1/7/92 RB Rolled in Terror changes. Mainly cache flushing.
; <17> 8/30/91 DTY Define isUniversal here since itÕs no longer defined in
; BBSStartup. isUniversal is defined to be 0 for System builds
; because thatÕs the way it is. It should already be defined for
; the ROM build (in Build, in a {DefOverride}), but define it
; again just to be on the safe side. (ItÕs inside a check to see
; whether or not itÕs defined, so itÕs ok to define it again.)
; <16> 6/12/91 LN removed #include 'HardwareEqu.a'
; <15> 3/8/91 djw <dnf>(BRC #83516) Fix GetCString where in 32 bit mode reg d0 was
; set to 1 and caused an off-by-one count to be returned.
; <14> 12/10/90 djw Modify SlotExec to fix a problem with the 4¥8/8¥24/GC card's
; secondaryInit code. Add FixTrident routine to do the fix.
; <13> 9/19/90 BG Removed EclipseNOPs from <9>, <10>. 040s are behaving more
; reliably now.
; <12> 7/30/90 BG Removed IF CPU = 040 conditional in preparation for moving from
; Mac040 to Mac32 build.
; <11> 7/20/90 gbm get rid of slot warnings
; <10> 7/19/90 BG Added EclipseNOPs for flakey 040s.
; <9> 7/5/90 CCH Fixed aeStackFrame record for 68040. Also added EclipseNOPs for
; flakey 040s.
; <8> 6/29/90 djw Fix bug in FindDevBase and in SlotPRAM where hasRBV must be true
; or no slot zero. Deleted MapUnit routine (overkill). Modified
; FindDevBase to return a base addr for slot zero even if there is
; no internal video (addr is not mapped). Corrected conditionals
; for ROM and A/UX. Modified bus exception handler to be VM
; friendly (not pop stack frame and jump). Moved SecondaryInit
; code back to SlotMgrInit.a. Added universal support to SlotPRAM
; routines. Modified pGetBoard to accept spId as a parameter.
; <7> 4/2/90 djw Simplify the install and remove routines for bus exception
; handler
; <6> 2/20/90 BG Changed the definition of aeXFrameSize in the 040 bus exception
; handler to reflect the real size of the exception frame.
; <5> 1/21/90 BG Removed 040 AERROR from pBusException. Added routine
; p040BusException to handle 040 bus error exceptions.
; <4> 1/17/90 djw Modifications to build slot mgr with 32bit QD INIT using BBS
; sources. Added Secondary_Init and GetBoard routines from
; SlotMgrInit.a
; <3> 1/11/90 CCH Added include of ÒHardwarePrivateEqu.aÓ.
; <2> 1/3/90 BG Changing the quoting on the 040-related AERROR messages to use
; the correct quotes (single, not double). Will fix problem
; related to the AERROR shortly.
; <1.8> 9/18/89 djw Reorganized sources to combine into two source files, to allow
; system 7.0 patch to share the same sources.
; <1.7> 7/14/89 djw NEEDED FOR AURORA: removed sNewPtr. Set findbigdevbase to
; finddevbase because findbigdevbase. Update internal version
; number. macro is in mpw equate files (so just can't get rid of
; the call).
; <1.6> 6/30/89 djw removed pSlotStatus. Modified InitJmpTbl to use relative
; addressed table. Changed sdmjmptbl to use relative addresses for
; the vectors
; <1.5> 6/12/89 djw Removed findbigdevbase
; <1.4> 3/28/89 djw Cleaned up IMPORT statements. Rewrote InitJmpTbl,SlotManager.
; Added dummy routine for unimplemented selectors. Deleted old
; modification history. Added patch support, added old bsr routine
; to jmp tbl now using slotjsr macro. Rewrote slotmgr dispatcher
; <1.3> 3/12/89 djw Added InitJmpTbl from smadvanced, to make the 1.0 patch easier
; to manage. Moved things around a little. Added GetsRsrcPtr.
; <1.2> 2/20/89 djw Added sVersion, SetsRsrcState, InsertSRTRec, delete code to
; switch slotmanager 24 bit mode - make it 32 bit clean. Added
; GetsRsrc, GetTypesRsrc and FindSRTRec.
; <1.1> 11/10/88 CCH Fixed Header.
; <1.0> 11/9/88 CCH Adding to EASE.
; <1.5> 11/7/88 djw Added InitSlotPRAM
; <¥1.4> 10/24/88 djw NEW SLOTMANAGER VERSION. Deleted all register names. Rewrote to
; save mmu mode on stack - no longer need to save any registers in
; called slot manager routines. All new IMPORT routine names.
; <¥1.3> 9/23/88 CCH Got rid of inc.sum.d and empty nFiles
; <1.2> 2/15/88 BBM added inc.sum.d as a second load file
; <1.1> 2/15/88 BBM modified for mpw 3.0 equates
; <1.0> 2/10/88 BBM Adding file for the first time into EASEÉ
;
Machine MC68020
String Asis
Print Off
LOAD 'StandardEqu.d'
Include 'HardwarePrivateEqu.a'
Include 'RomEqu.a'
Include 'UniversalEqu.a'
Include 'SlotMgrEqu.a'
Include 'ComVideoEqu.a' ; <18> rb
Print On
If (&TYPE('forAUX') = 'UNDEFINED') Then ; equ indicating whether we are <8>
forAUX Equ 0 ; ... building for an A/UX patch
Endif
;_________________________________________________________________________________________ <1.4>
; SlotManager - slot manager secondary dispatch routine
;
; Vector through the secondary dispatch table for the slot manager to the requested
; routine.
;
; Input : reg D0 = routine selector (word)
;
SlotMgr Proc
Export SlotManager
; Jump to the selected slot manager routine.
DC.B 'slot version 2.3' ; slot manager internal version number <4>
SlotManager
CMP.W #LastSDMSelt,D0 ; check selector range
BHI.S SlotEmpty ; selector(unsigned) > max - error <djw>
move.l ([SDMJmpTblPtr],d0.w*4),a1 ; get vector from table <1.7>
jmp (a1) ; <1.7>
;_________________________________________________________________________________________ <1.4>
; SlotEmpty - unimplemented slot manager trap
;
Export SlotEmpty
SlotEmpty
move.w #smSelOOBErr,d0 ; error - selector out of bounds
rts
;=========================================================================================
; smPrinciple
;=========================================================================================
**********************************************************************
*
* FUNCTION ReadSlotByte : Read Byte.
* Return an 8-bit value from the list pointed to by sPointer and
* identified by Id. This value is placed in the LSB of the Result
* field.
*
* Parameter block:
* -> spsPointer - Points to the list the Byte is in.
* -> spId - The Id of the Byte.
* <- spResult - The desired byte.
*
**********************************************************************
ReadSlotByte FUNC EXPORT
;VAR
spBlkPtr$a0 EQU A0 ;Pointer to the SDM parameter block
Status$d0 EQU D0 ;Status of ReadSlotByte
;----------------------------------------------------------------------
; ReadSlotByte
;----------------------------------------------------------------------
;BEGIN
WITH spBlock
; Initialize
MOVE.L spsPointer(spBlkPtr$a0),-(SP) ;Save sPointer.
CLR.B spResult+3(spBlkPtr$a0) ;ReadSlotByte <- 0
; Read the Offset/Data field and assign the Data to ReadSlotByte.
_sOffsetData ;Read the Offset/Data field.
BNE.S End ;IF Error THEN
; GOTO End
MOVE.B spOffsetData+3(spBlkPtr$a0),spResult+3(spBlkPtr$a0) ;ReadSlotByte <- Data[4]
MOVEQ #0,Status$d0 ;Status <- NoError
; Exit
End MOVE.L (SP)+,spsPointer(spBlkPtr$a0) ;Restore sPointer.
RTS ;Return.
ENDWITH
;END ReadSlotByte
ENDF
EJECT
**********************************************************************
*
* FUNCTION ReadSlotWord : Read Word.
* Return a 16-bit value from the list pointed to by sPointer and
* identified by Id. This value is placed in the two LSB fields of
* the Result field.
*
* Parameter block:
* -> spsPointer - List pointer. Points to the list the Word is in.
* -> spId - Id. The Id of the Word in the list.
* <- spResult - The desired word.
*
**********************************************************************
ReadSlotWord FUNC EXPORT
;VAR
spBlkPtr$a0 EQU A0 ;Pointer to the SDM block
Status$d0 EQU D0 ;Status of ReadSlotWord
;----------------------------------------------------------------------
; ReadSlotWord
;----------------------------------------------------------------------
;BEGIN
WITH spBlock
; Initialize
MOVE.L spsPointer(spBlkPtr$a0),-(SP) ;Save sPointer
CLR.W spResult+2(spBlkPtr$a0) ;ReadSlotWord <- 0
; Read the Offset/Data field and Assign the Data to ReadSlotWord.
_sOffsetData ;Read the Offset/Data field.
BNE.S End ;IF Error THEN
; GOTO End
MOVE.W spOffsetData+2(spBlkPtr$a0),spResult+2(spBlkPtr$a0) ;ReadSlotWord <- Data[3..4]
MOVEQ #0,Status$d0 ;Status <- NoError
; Exit
End MOVE.L (SP)+,spsPointer(spBlkPtr$a0) ;Restore sPointer.
RTS ;Return.
ENDWITH
;END ReadSlotWord
ENDF
EJECT
**********************************************************************
*
* FUNCTION ReadSlotLong : Read Long
* Return a 32-bit value from the list pointed to by sPointer and
* identified by Id. This value is placed in the Result field.
*
* Parameter block:
* -> spsPointer - List pointer. Points to the list the Long is in.
* -> spId - Id. The Id of the Long in the list.
* <- spResult - The desired long.
*
**********************************************************************
ReadSlotLong FUNC EXPORT
;VAR
spBlkPtr$a0 EQU A0 ;Pointer to the SDM parameter block
Status$d0 EQU D0 ;Status of ReadSlotLong
;----------------------------------------------------------------------
; ReadSlotLong
;----------------------------------------------------------------------
;BEGIN
WITH spBlock
; Initialize
MOVE.L spsPointer(spBlkPtr$a0),-(SP) ;Save sPointer.
CLR.L spResult(spBlkPtr$a0) ;ReadSlotLong <- 0
; Use sReadPBSize to read the Long and move PhyBlkSize to Result.
BCLR.B #fCkReserved,spFlags(spBlkPtr$a0) ;Do not check reserved.
_sReadPBSize ;Read the long.
BNE.S End ;IF Error THEN
; GOTO End
MOVE.L spSize(spBlkPtr$a0),spResult(spBlkPtr$a0) ;ReadSlotLong <- PhyBlkSize
MOVEQ #0,Status$d0 ;Status <- NoError
; Exit
End MOVE.L (SP)+,spsPointer(spBlkPtr$a0) ;Restore sPointer.
RTS ;Return
ENDWITH
;END ReadSlotLong
ENDF
EJECT
;_______________________________________________________________________________________ <1.5>
; GetcString - get a C string
;
; Find the cString identified by the id in the given sList. Allocate a pointer
; block on the system heap and copy the string to it.
;
; Input : reg A0 = ptr to spBlock
; Output : none
;
; spBlock : -> spId id of the cString in the list
; -> spsPointer ptr to list
; <- spResult ptr to the cString in RAM
;
; Called : trap dispatcher
;
GetcString Proc Export
With spBlock
movem.l a2-a3,-(sp)
move.l spsPointer(a0),-(sp) ; save ptr to the sList
move.b spSlot(a0),-(sp) ; save the slot
_sFindStruct ; get the ptr to the string
bne @Done ; <SM9> CSS
movea.l spsPointer(a0),a3 ; a3 = ptr to the string
; Calculate the step register
bset.b #fConsecBytes,spFlags(a0) ; calc for consecutive bytes
_sCalcStep
bne @Done ; <SM9> CSS
move.l spResult(a0),d1 ; d1 = step register
; Loop and count all the chars in the string so we know how big a block to allocate.
moveq #0,d2 ; clear temp reg for NextStep macro
movea.l a3,a1 ; a1 = ptr to the string in the decl rom
lea @Done,a2 ; set address to jump to if bus error
slotjsr InstallBus ; replace sys bus excptn and 32 bit mode
moveq #0,d0 ; d0 = length cntr <SM12> PN
@Loop
addq.l #1,d0 ; inc the length
move.b (a1),d2 ; NUBUS READ - read a char
beq.s @EndLoop ; found the end of the string
sNextStep d1,d2,a1 ; inc to the next byte in the decl rom
bra.s @Loop ;Continue looping
@EndLoop move.l d0,spSize(a0) ; set size of string
slotjsr RestoreBus ; restore mmu mode and sys bus excptn
; Allocate a non-relocatable block on the current heap to copy the string to
movea.l a0,a2 ; save ptr to spBlock
_NewPtr ; allocate the memory <1.6>
bne.s @Done
move.l a0,spResult(a2) ; pass ptr to buf in result field
movea.l a2,a0 ; restore a0 = ptr to spBlock
move.l a3,spsPointer(a0) ; restore ptr to the string
_sReadStruct ; copy the string to the buffer
beq.s @Done ; a good return
move.l d0,d1 ; an error - save the error code
movea.l a0,a1 ; save ptr to spBlock
movea.l spsPointer(a1),a0 ; free the allocated pointer
_DisposPtr
movea.l a1,a0 ; restore a0 = ptr to spBlock
move.l d1,d0 ; restore the error code
@Done
move.b (sp)+,spSlot(a0) ; restore the slot
move.l (sp)+,spsPointer(a0) ; restore the ptr to the sList
movem.l (sp)+,a2-a3
rts
EJECT
;_______________________________________________________________________________________ <1.5>
; GetSlotBlock - get an sBlock on the system heap
;
; Given a pointer to an sList and the id of an sBlock, find and copy the block to
; a non-relocatable block allocated on either the system or current heap. GetSSBlock
; must allocate on the system heap, because video drivers assumes that it does. The
; old slot manager allocated on the current heap.
;
; Input : reg A0 = ptr to spBlock
; Output : none
;
; spBlock : -> spId id of the sBlock in the list
; -> spsPointer ptr to list
; <- spResult ptr to the copy block in ram
;
; Called : trap dispatcher
;
GetSlotBlock Proc Export
With spBlock
move.l spsPointer(a0),-(sp) ; save the spsPointer field
bset.b #fCkReserved,spFlags(a0) ; check the reserved byte for zero
_sReadPBSize ; read the physical block size
bne.s @Done
move.l spSize(a0),d0 ; d0 = sBlock size (including length field)
subq.l #4,d0 ; size-length field > 0 ?
bgt.s @Alloc ; positive block size <1.7>
move.w #smNilsBlockErr,d0 ; a bad block size
bra.s @Done
@Alloc
move.l d0,spSize(a0) ; set size of sBlock (minus length field)
movea.l a0,a1 ; save ptr to spBlock
_NewPtr ,Sys ; on sys heap for video dependency <1.6>
bne.s @Done
move.l a0,spResult(a1) ; pass ptr to buffer in spResult
movea.l a1,a0 ; restore a0 = ptr to spBlock
_sReadStruct ; copy the sBlock to memory
beq.s @Done ; a good return
move.l d0,d1 ; an error - save the error code
movea.l a0,a1 ; save ptr to spBlock
movea.l spsPointer(a1),a0 ; free the allocated pointer
_DisposPtr
movea.l a1,a0 ; restore a0 = ptr to spBlock
move.l d1,d0 ; restore the error code
@Done
move.l (sp)+,spsPointer(a0) ;restore ptr to the sList
rts
;_______________________________________________________________________________________ <1.5>
; FindSlotStruct - find a structure
;
; Given a pointer to an sList, find the offset field associated with the given id.
; Calculate a pointer from the offset and return the pointer.
;
; Input : reg A0 = ptr to spBlock
; Output : none
;
; spBlock : -> spId id of the sBlock in the list
; <-> spsPointer ptr to list
; returns ptr to structure
; <- spByteLanes by product of offsetdata call
;
; Called : trap dispatcher, jsr
;
FindSlotStruct Proc Export
With spBlock
_sOffsetData ; find and read the offset/data field
bne.s @Done
_sCalcsPointer ; convert offset to a pointer
@Done
rts
;_______________________________________________________________________________________ <1.5>
; ReadSlotStruct - read a structure
;
; Given a pointer to a structure, copy the structure into the given buffer,
;
; Input : reg A0 = ptr to spBlock
; Output : none
;
; spBlock : -> spsPointer ptr to list
; -> spSize number of bytes to read
; <-> spResult ptr to buffer to copy structure to
;
; Called : trap dispatcher, jsr
;
ReadSlotStruct Proc Export
With spBlock, sInfoRecord
movem.l d1-d3/a1-a3,-(sp)
move.b spSlot(a0),-(sp) ; save spSlot field
movea.l spsPointer(a0),a3 ; a3 = ptr to struct to read
move.l a3,-(sp) ; save spsPointer field
; Strip the buffer pointer to make sure it's 32 bit clean
move.l spResult(a0),d0 ; d0 = buffer ptr
_StripAddress
move.l d0,-(sp) ; save a copy of ptr to buffer
movea.l d0,a1 ; a1 = ptr to the buffer
; Convert the pointer to a slot number
_sPtrToSlot ; return a slot number
bne.s @Done
_sFindsInfoRecPtr ; given the slot, get ptr to sInfoRecord
bne.s @Done
movea.l spResult(a0),a2 ; reg a2 = ptr to sInfo record
; Calculate the step register for the slot
move.b siCPUByteLanes(a2),spByteLanes(a0) ; get byte lane field from sInfo rec
bset.b #fConsecBytes,spFlags(a0) ; calc for consecutive bytes
_sCalcStep
bne.s @Done
move.l spResult(a0),d1 ; d1 = step register
; Loop and read the struct into the buffer
; a1 = ptr to buffer, a3 = ptr to struct
slotjsr InstallBus ; 32 bit mode and swap bus exception vector
moveq #0,d3 ; clear temp register for NextStep macro
move.l spSize(a0),d2 ; d2 = number of bytes to read
subq.l #1,d2 ; adjust size for dbra loop
lea @EndLoop,a2 ; address to jump to if bus error
move.w #smUnExBusErr,d0 ; set error return (just in case)
@Loop
move.b (a3),(a1)+ ; NUBUS READ - copy a byte
sNextStep d1,d3,a3 ; inc rom ptr
dbra d2,@Loop ; continue
moveq #noErr,d0 ; completed ok - set return status
@EndLoop
slotjsr RestoreBus ; switch back to save mmu mode and bus exception
@Done
move.l (sp)+,spResult(a0) ; restore ptr to buffer
move.l (sp)+,spsPointer(a0) ; restore ptr to structure
move.b (sp)+,spSlot(a0) ; restore slot number field
movem.l (sp)+,d1-d3/a1-a3
tst.w d0 ; set ccr
rts
;=========================================================================================
; smSpecial
;=========================================================================================
**********************************************************************
*
* FUNCTION ReadInfo : Read Slot Information.
* Read the SlotInfo record identified by Slot.
*
* Parameter block:
* -> spSlot - Which slot.
* <-> spResult - Pointer to the buffer.
*
**********************************************************************
ReadSlotInfo FUNC EXPORT
;VAR
spBlkPtr$a0 EQU A0 ;Pointer to the SDM parameter block.
sInfoRec$a EQU A1 ;sInfoArray pointer.
BufferPtr$a EQU A2 ;Pointer to the buffer.
Status$d0 EQU D0 ;Status
Slot$d EQU D1 ;Slot
LoopIndex$d EQU D2 ;Loop Index.
;----------------------------------------------------------------------
; ReadSlotInfo
;----------------------------------------------------------------------
;BEGIN
WITH spBlock,sInfoRecord
; Allocate local vars.
MOVEM.L A2,-(SP) ;Save registers
MOVE.L spResult(spBlkPtr$a0),BufferPtr$a ;BuferPtr$a <- Pointer to the buffer.
MOVE.L BufferPtr$a,-(SP) ;Save spResult.
; Get a pointer to the sInfo Array for the given slot.
C10 _sFindsInfoRecPtr ;Find the pointer to the sInfo record. <C520><C726>
BNE End ;Branch if error. <C520>
MOVE.L spResult(spBlkPtr$a0),sInfoRec$a ;sInfoRec$a <- pointer to the sInfo record. <C520>
; Move the sInfo record to the block.
MOVEQ #sInfoRecSize-1,LoopIndex$d ;LoopIndex$d <- sInfoRecSize-1
;REPEAT
Repeat MOVE.B (sInfoRec$a)+,(BufferPtr$a)+ ; sInfoRec(i)+ <- sInfoArray[Slot].(i)+
Until DBF LoopIndex$d,Repeat ;UNTIL LoopIndex < 0
MOVEQ #0,Status$d0 ;Status <- NoError
; Restore locals & return
End MOVE.L (SP)+,spResult(spBlkPtr$a0) ;Restore the buffer pointer.
MOVEM.L (SP)+,A2 ;Restore registers
RTS ;Return
ENDWITH
;END ReadSlotInfo
ENDF
**********************************************************************
*
* PROCEDURE SlotDisposPtr : Dispose Pointer
* Dispose of the pointer.
*
* Parameter block:
* -> spsPointer - The pointer to be disposed.
*
**********************************************************************
SlotDisposPtr PROC EXPORT
;VAR
spBlkPtr$a0 EQU A0 ;Pointer to the SDM parameter block.
p$a0 EQU A0 ;Pointer to be disposed by Memory Manager.
Status$d0 EQU D0 ;Status
;----------------------------------------------------------------------
; SlotDisposPtr
;----------------------------------------------------------------------
;BEGIN
WITH spBlock
; Allocate local vars.
move.l a0,-(sp) ; <1.7>
; Dispose of the block.
MOVE.L spsPointer(a0),a0 ;p <- sPointer
_DisposPtr ;DisposPtr(p)
BEQ.S End ;IF Good THEN
; GOTO End
;ELSE
MOVE.L #smDisposePErr,d0 ; Status <- smDisposeHErr
; Restore spBlkPtr and Return
End movea.l (sp)+,a0 ; <1.7>
RTS
ENDWITH
;END SlotDisposPtr
ENDP
EJECT
**********************************************************************
*
* FUNCTION ReadSlotDrvrName : Read the driver name.
* Read the sResource name, Append the '.' prefix to this name,
* giving the sDriver name. The result is a pointer to a Pascal type
* string useable by iocore (_Open).
*
* Parameter block:
* -> spSlot : Slot number.
* -> spId : sResource id.
* <- spResult : Pointer to the driver name.
*
**********************************************************************
ReadSlotDrvrName FUNC EXPORT
;VAR
spBlkPtr$a0 EQU A0 ;Pointer to the SDM parameter block.
SourcePtr$a0 EQU A0 ;**Used by _BlockMove.
DestPtr$a1 EQU A1 ;**Used by _BlockMove.
sRsrcNamePtr$a EQU A2 ;Pointer to sResource name.
BufferPtr$a EQU A3 ;Pointer to the buffer.
Status$d0 EQU D0 ;Status.
ByteCnt$d0 EQU D0 ;**Used by _BlockMove.
LensRsrcName$d EQU D1 ;Length of sResource name.
IdSave$d EQU D2 ;Save the sResource Id.
;----------------------------------------------------------------------
; ReadSlotDrvrName
;----------------------------------------------------------------------
;BEGIN sGetDrvrName
WITH spBlock,sInfoRecord
; Save
MOVEM.L A2-A3,-(SP) ;Save A2-A3
MOVE.B spId(a0),d2 ;Save Id
MOVE.L spResult(a0),a3 ;BuferPtr$a <- Pointer to the buffer.
MOVE.L a3,-(SP) ;Save spResult.
; Get sResource Name
CLR.B spExtDev(A0) ; was not required for ReadDrvrName <1.4>
CLR.L spParamData(A0) ; only look at enabled guys <1.4>
_GetsRsrcPtr ; find the ptr to the sRsrc <1.4>
BNE.S Err2
MOVE.B #sRsrcName,spId(a0)
_sGetcString ;Get the name.
BNE.S Err2
MOVE.L spResult(a0),a2
MOVE.L spSize(a0),d1
SUBQ.B #1,d1 ;Adjust length to ignore the nil EOS marker.
CMP.L #254,d1 ;IF d1 > 254 THEN
BHI.S Err1
; Set prefix {Prefix = '<Len>.', where Len is the length of the string.
MOVE.B spSize+3(a0),(a3)+ ;Str -> '<Len>'
MOVE.B #'.',(a3)+ ;Str -> '<Len>.'
; Append the sResource name to the prefix, giving: '<Len>.Name'
MOVEM.L A0-A1,-(SP) ;Preserve A0-A1, destroyed by _BlockMove.
MOVE.L a2,a0
MOVE.L a3,a1
MOVE.L d1,d0
_BlockMoveData
MOVEM.L (SP)+,A0-A1 ;Restore A0-A1, destroyed by _BlockMove.
BNE.S Err1
; sDriver name build was successful. Dispose of sRsrc name string and exit.
exg.l a2,a0 ; a0 = ptr to string to dispose <1.7>
_DisposPtr ; <1.7>
movea.l a2,a0 ; restore a0 = ptr to spBlock <1.7>
MOVEQ #0,d0
BRA.S EndGetDrvrName
; Error, Dispose sRsrc name string and exit.
Err1 exg.l a2,a0 ; a0 = ptr to string to dispose <1.7>
_DisposPtr ; <1.7>
movea.l a2,a0 ; restore a0 = ptr to spBlock <1.7>
Err2 MOVE.L #smGetDrvrNamErr,d0
; Exit sGetDrvrName.
EndGetDrvrName MOVE.L (SP)+,spResult(a0) ;Restore the buffer pointer.
MOVE.B d2,spId(a0) ;Restore Id
MOVEM.L (SP)+,A2-A3 ;Restore A2-A3
RTS
;END ReadSlotDrvrName
ENDWITH
ENDF
;_______________________________________________________________________________________ <1.6>
; FindDevBase - find the slot device base address
;
; Given a slot and id, find the base address. There are 3 possible base addresses,
; each within a different address space. They are the 1Mb, 16Mb, and 256Mb spaces.
; The address returned is determined by a flag in sRsrcFlags, and by whether a
; minor or major base offset record is found. The following permutations are
; possible, and result in the address returned as indicated:
;
; minorbase majorbase address returned
; _________ _________ ________________
;
; sRsrcFlags missing x Fssxxxxx
; sRsrcFlags missing x sxxxxxxx
; 24 bit x Fssxxxxx
; 24 bit x sxxxxxxx
; 32 bit x Fsxxxxxx
; 32 bit x sxxxxxxx
;
;
; Input : reg A0 = ptr to spBlock
;
; Output : reg D0 = status, 0=ok CCR reflects status
;
; spBlock : -> spSlot
; -> spId Id in list to search for
; <- spResult base address for the given slot
;
; Called : secondary dispatch table
;
FindDevBase Proc Export
Import FindDevBaseSlot0
With spBlock,sInfoRecord
move.l a1,-(sp)
move.b spId(a0),-(sp) ; save the id of the sRsrc
move.l spParamData(a0),-(sp) ; save ParamData field
; Get the pointer to the sResource
clr.l spParamData(a0) ; clear flags field
bset.b #fOneSlot,spParamData+3(a0) ; search only one slot
slotjsr sGetsRsrc ; only look at enabled sRsrc's
bne @Done ; some error <djw>
moveq.l #0,d2
move.b spSlot(a0),d2 ; d2 = slot number
; Try to get the minor base offset
move.b #MinorBaseOS,spId(a0)
_sReadLong
bne.s @Major ; minor base offset not found
move.l spResult(a0),d1 ; d1 = minor base offset
and.l #$00ffffff,d1 ; max offset in minor slot space
tst.b spSlot(a0) ; getting base addr for slot zero ? <H2>
beq.s @SlotZero
bra.s @FormSmall ; form a 1Mb or 16Mb ptr
; No minor base - try to get the major base offset
@Major move.b #MajorBaseOS,spId(a0)
_sReadLong
bne.s @Done ; major base offset not found - error
move.l spResult(a0),d1 ; d1 = major base offset
and.l #$0fffffff,d1 ; max offset in major slot space
tst.b spSlot(a0) ; getting base addr for slot zero ? <H2>
beq.s @SlotZero
; Form a major base pointer (256Mb space) : d2 = slot number
ror.l #4,d2 ; d2 = s0000000
or.l d1,d2 ; d2 = sxxxxxxx
bra.s @RtnBase
; Form a small base pointer (1Mb or 16Mb) - get the sRsrcFlag word to determine which
; d2 = slot number
@FormSmall move.l #$f0000000,d0 ; d0 = F0000000
or.l d1,d0 ; d0 = F0xxxxxx
bfins d2,d0{4:4} ; d0 = Fsxxxxxx
bfins d2,d0{8:4} ; d0 = Fssxxxxx
move.l d0,d2 ; d2 = a 24 bit pointer
If forROM and Not forAUX then ; <8>
; If slot zero, then map the base address - only needed for minor space. Only video
; currently has a base address for slot zero. If there is no internal video, then
; do not map the base address.
tst.b spSlot(a0) ; getting base addr for slot zero ?
bne.s @NonZero
movea.l UnivInfoPtr,a1 ; point to the ProductInfo record
adda.l ProductInfo.VideoInfoPtr(a1),a1 ; point to the VideoInfo record
move.l VideoInfo.VRAMLogAddr24(a1),d2 ; 24bit dev base to alias addr for slot zero
move.l VideoInfo.VRAMLogAddr32(a1),d1 ; set d1 to 32bit offset if 32bit ptr
@NonZero
endif ; <8>
move.b #sRsrcFlags,spId(a0) ; get flags to determine whether the pointer
_sReadWord ; - should be 24 or 32 bit
bne.s @RtnBase ; no flag field - default to 24 bit space
move.w spResult+2(a0),d0 ; get sRsrc flag word <1.8>
btst.l #f32BitMode,d0 ; 32 bit mode flag set? <1.8>
beq.s @RtnBase ; not set - use 24 bit address form <1.8>
and.l #$ff000000,d2 ; d2 = Fs000000
or.l d1,d2 ; d2 = Fsxxxxxx
@RtnBase move.l d2,spResult(a0) ; return the base pointer
moveq.l #noErr,d0 ; set a good return
@Done
move.l (sp)+,spParamData(a0) ; restore spBlock fields
move.b (sp)+,spId(a0)
movea.l (sp)+,a1 ; <1.8>
rts
@SlotZero Bsr.l FindDevBaseSlot0 ; Jump to our SlotZero utility. <H2>
Bra.s @RtnBase ; And exit.
;=========================================================================================
; smAdvanced
;=========================================================================================
;_______________________________________________________________________________________ <1.6>
; CardChanged - return true if card changed
;
; Return true if a card's PRAM has been initialized (i.e. a card in the slot
; is now different from the previous one).
;
; Input : reg A0 = ptr to spBlock
;
; Output : reg D0 = status, 0=ok CCR reflects status
; A0 = ptr to spBlock
;
; spBlock : -> spSlot slot number
; <- spResult 0=false (card same), $ff if card changed
;
CardChanged Proc Export
with spBlock,sInfoRecord
clr.b spResult+3(a0) ;CardChanged <- Flags {True if > 0}
_sFindsInfoRecPtr ;Find the pointer to the sInfo record. <C520>
bne.s @Done ; <1.8>
movea.l spResult(a0),a1 ; a1 = pointer to the sInfo record.<C520>
btst.b #fCardIsChanged,siStatusFlags(a1)
sne.b spResult+3(a0) ;spResult <- True if > 0, else false.
MOVEQ #0,d0 ;Status <- NoError (No error is possible)
@Done rts ; <1.8>
Endp
EJECT
**********************************************************************
*
* PROCEDURE SlotExec : Execute
* Download the code block, from the list pointed to by sPointer
* and identified by Id, to the current heap zone, check revision
* level, check CPU field and execute the code.
*
* Parameter block:
* -> spsPointer - Struct pointer. Points to the list the code block is in.
* -> spId - The Id of the code block in the list.
* -> spsExecPBlk - Pointer to the se block.
*
**********************************************************************
SlotExec PROC EXPORT
;VAR
spBlkPtr$a0 EQU A0 ;Pointer to the SDM parameter block.
sePBlkPtr$a0 EQU A0 ;se parameter block pointer. ## warning A0 ##
Temp$a EQU A1 ;Temporary address register.
CodePtr$a EQU A2 ;Pointer to code.
CodePtrCopy$a EQU A3 ;Copy of CodePtr (use to dispose ptr).
Status$d0 EQU D0 ;Status
Revision$d EQU D1
Temp$d EQU D2 ;Temporary data register.
Slot$d EQU D3 ;Slot
TimeOut$d EQU D4 ;Time-Out value.
BRA.S BeginSlotExec ; <C783>
;====================================================================
;
; PROCEDURE Revision2 : Revision-2
; Handle a header with a revision level of 2.
;
; Vars imported from SlotExec:
; <-> a2 : Pointer to the Header of the code record.
; <-> Status$d0 : Status of this call.
; <- TimeOut$d : Time-out register.
;
;====================================================================
;BEGIN
WITH spBlock,seHeader2
; Check Revision level.
Revision2 CMP.B #sExec2,seRevision(a2) ;IF (CodePtr.seRevision = sExec2) THEN
BEQ.S @10 ; GOTO @10
MOVE.L #smCodeRevErr,d0 ;Status <- smCodeRevErr
BRA.S EndRev2
; Check CPU type
@10 CMP.B #sCPU68020,seCPUId(a2) ;IF CodePtr.seCPUId = (sCPU68000 OR sCPU68020) THEN <C807>
BLS.S @20 ; GOTO @20 {CPU type is good, Continue} <C807>
MOVE.L #smCPUErr,d0 ;Status <- smCPUErr
BRA.S EndRev2
; Get pointer to code
@20 ADDQ.L #seCodeOffset,a2 ;CodePtr <- CodePtr + CodePtr.seCodeOffset {Skip to pointer to code}
MOVE.L (a2),a1 ;Temp <- CodePtr^ {Offset to code}
ADD.L a1,a2 ;CodePtr <- CodePtr + Temp {Now points to top of code}
; Code header is good, clear status and exit.
Good2 MOVEQ #0,d0
; Return.
EndRev2 RTS ;Return
ENDWITH
;END Revision2
;----------------------------------------------------------------------
; SlotExec
;----------------------------------------------------------------------
;BEGIN
WITH spBlock
; Allocate local vars.
BeginSlotExec
MOVEM.L A2-A3/D3-D4,-(SP) ;Save registers <C783>
MOVE.L spsPointer(a0),-(SP) ;Save sPointer
; Read the sBlock from the ROM into RAM. Warning - GetsBlock now always allocates
; on the system heap.
_sGetBlock ;CodePtr <- Pointer to the code block.
BNE.S End ;IF Error THEN
; GOTO End {exit with error}
MOVE.L spResult(a0),a2
MOVE.L a2,a3 ;Save a copy for dispose ptr
; WARNING...WARNING...WARNING...
; The routine FixTrident depends on spSize being unchanged from _sGetBlock
bsr FixTrident ; kludge to fix a bug in Trident video card
; Decode the revision level of the header and retrieve the necessary data.
BSR.S Revision2 ;IF (Error in Rev-2 header) THEN
BNE.S DispCode ; GOTO DispCode {Dispose of the code and exit with error}
; Header ok, execute the code.
ExecCode MOVEM.L A0-A6/D0-D7,-(SP) ;Save registers
JSR ([jCacheFlush]) ;flush the caches <18> rb
MOVE.L spsExecPBlk(a0),a0 ;Set pointer to se parameters.
JSR (a2) ;Parameters: ->Slot,->Id, plus any extensions.
MOVEM.L (SP)+,A0-A6/D0-D7 ;Restore registers
MOVEQ #0,d0 ;SlotExec Good, now exit.
; Release memory (created by sGetBlock).
DispCode EXG.L d0,d2 ;Save the Status (May be an error) <C520>
exg.l a3,a0 ; a0 = ptr to dispose <1.7>
_DisposPtr ; dispose of the code block <1.7>
movea.l a3,a0 ; restore a0 = ptr to spBlock <1.7>
EXG.L d2,d0 ;Restore the Status <C520>
; Release memory, Clean up stack & return
End MOVE.L (SP)+,spsPointer(a0) ;Restore sPointer. <C468/25Nov86> <C783>
MOVEM.L (SP)+,A2-A3/D3-D4 ;Restore registers
RTS ;Return
;END SlotExec
;_______________________________________________________________________________________ <14>
; FixTrident - patch 8¥24 card problem
;
; This routine is called from SlotExec (_Exec) to detect a code problem in the
; Trident/4¥8/8¥24/GC video card's secondaryInit code. The Trident card's
; secondaryInit code has a call to _sNextTypesRsrc. Instead of setting "clr.b tbMask(a0)",
; the error is using "clr.b sptbMask", which clears byte $30 in low mem (fortunately benign).
; This fix looks at every sExec block being executed. If it sees a "clr.b $30" next to
; a _sNextTypesRsrc, then it changes the instruction to a "clr.b $30(a0)".
;
; Input : a2 = ptr to sExec sBlock (including an 8 byte header in this case)
; a0 = ptr to spBlock
;
; spBlock : -> spSize size of code block read in
;
TridentCodeSize Equ $18e ; size of secondaryInit sBlock
TheBadCode Equ 8+$7e ; header+code offset to bad code to patch
FixTrident
movem.l a0-a1,-(sp)
movea.l a2,a1 ; a1 = ptr to beginning of code
cmpi.l #TridentCodeSize,spSize(a0) ; same size code block?
bne.s @Done ; no - do nothing
lea.l CompareTbl,a0 ; get addr of table of values to compare
adda.l (a0)+,a1 ; add in offset to code to compare
move.w (a0)+,d0 ; get the compare count
@Loop cmp.w (a0)+,(a1)+ ; compare the code
dbne d0,@Loop ; continue comparing code
tst.w d0 ; did we finish the count?
bpl.s @Done ; nope - positive count
move.w #$4228,TheBadCode(a2) ; change "clr.b $30" to "clr.b $30(a0)"
@Done
movem.l (sp)+,a0-a1
rts
;_______________________________________________________________________________________ <14>
; Code Comparision Table For Trident Card Fix
;
CompareTbl
dc.l 8+$7e ; header+code offset into the code to start
dc.w 6-1 ; compare 6 words (adjusted for dbra)
dc.w $4238 ; "clr.b spTBMask" <--- the bad one
dc.w $0030
dc.w $4228 ; "clr.b spExtDev(a0)"
dc.w $0033
dc.w $7015 ; "moveq #15,d0"
dc.w $a06e ; "_SlotManager"
Endwith
Endp
EJECT
********************************************************************** <C225/16Oct86>
*
* PROCEDURE CalcsPointer : Calculate sPointer
* Calculate a pointer to a byte in the declaration ROM, given the
* pointer to the current byte and an offset in bytes (to the new
* byte if the memory was contiguous).
*
* Parameter block:
* <-> spsPointer - A pointer to the current byte in ROM.
* -> spOffsetData - Offset to the desired location.
* -> spByteLanes - The ByteLanes value for this slot.
*
**********************************************************************
CalcsPointer PROC EXPORT
;VAR
spBlkPtr$a0 EQU A0 ;Pointer to the SDM parameter block.
ROMPtr$a EQU A1 ;Pointer to ROM. <C783>
Status$d0 EQU D0 ;Status of sNextsRsrc.
TheByteLane$d EQU D1 ;The Byte lane you are in.
NumByteLanes$d EQU D2 ;The number of byte-lanes used.
Index$d EQU D3 ;Index
ROMOffset$d EQU D4 ;Number of bytes offset relative to ROM.
PCOffset$d EQU D5 ;Number of bytes offset relative to the CPU.
Remainder$d EQU D6 ;Number of bytes to do after the coarse calculation.
;----------------------------------------------------------------------
; CalcsPointer
;----------------------------------------------------------------------
;BEGIN
WITH spBlock,srrBlock,sInfoRecord
; Allocate and Initialize some vars.
MOVEM.L D3-D6,-(SP) ;Save registers <C438/19Nov86><C783>
MOVE.L spsPointer(spBlkPtr$a0),ROMPtr$a ;ROMPtr$a <- Pointer to the present location in ROM.
; Verify ROMPtr$a points to a valid byte-lane (This test could be deleted, but now it helps debug).
MOVEQ #0,TheByteLane$d ;TheByteLane$d <- Bits 0 and 1 of ROMPtr$a.
MOVE.W ROMPtr$a,TheByteLane$d
AND.B #$03,TheByteLane$d
BTST.B TheByteLane$d,spByteLanes(spBlkPtr$a0) ;IF (the bit in spByteLanes corresponds to the actual byte lane) THEN
BNE.S C20 ; GOTO C20 {Good}
;ELSE
MOVE.L #smBadsPtrErr,Status$d0 ; Status$d0 <- smBadsPtrErr
BRA.S End ; GOTO End {Exit with error}
; Calculate the number of byte-lanes used per long.
C20 MOVEQ #0,NumByteLanes$d
MOVEQ #3,Index$d ;FOR Index <- 3 DOWNTO 0 DO
For BTST.B Index$d,spByteLanes(spBlkPtr$a0) ; IF (There is a ROM in this byte-lane) THEN
BEQ.S EndFor
ADDQ #1,NumByteLanes$d ; NumByteLanes$d <- NumByteLanes$d + 1
EndFor DBF Index$d,For ;ENDFOR
TST.B NumByteLanes$d ;IF NumByteLanes$d = 0 THEN
BNE.S C30
MOVE.L #smByteLanesErr,Status$d0 ; Status$d0 <- smByteLanesErr
BRA.S End ; GOTO End {Exit with error}
; Calculate the offset (Coarse calculation, determines offset of ROMOffset$d >= 4 bytes).
C30 MOVE.L spOffsetData(spBlkPtr$a0),ROMOffset$d ;ROMOffset$d <- The number of ROM bytes to the desired new position.
BTST.L #23,ROMOffset$d ;ROMOffset$d <- ROMOffset$d sign extended (from 24-bits to 32).
BEQ.S C35
OR.L #$FF000000,ROMOffset$d
C35 MOVE.L ROMOffset$d,PCOffset$d ;PCOffset$d <- ROMOffset$d DIV NumByteLanes$d
TDIVS.L NumByteLanes$d,Remainder$d:PCOffset$d
LSL.L #2,PCOffset$d ;PCOffset$d <- PCOffset$d * 4
; Calculate the Offset (fine calculation, adjust offset for remainning offset of < 4 bytes)
C40 TST.B Remainder$d ;IF Remainder = 0 THEN
BEQ.S C50 ; GOTO C50 {done}
BPL.S PlRemainder ;IF Remainder < 0 THEN
; GOTO PlRemainder {Offset is positive}
; Offset is negative.
MiRemainder NEG.W Remainder$d ;Remainder$d <- poitive remainder. <C361>
SUBQ.W #1,Remainder$d ;Adjust Remainder$d for DBF <C361>
;REPEAT
Repeat_MI SUBQ.B #1,TheByteLane$d ; TheByteLane$d <- the next byte lane (Check all byte lanes 0..3) <C361><C726>
AND.B #$03,TheByteLane$d
SUBQ.L #1,PCOffset$d ; PCOffset$d <- PCOffset$d + 1
BTST.B TheByteLane$d,spByteLanes(spBlkPtr$a0) ; IF (no ROM in this byte lane) THEN
BEQ.S Repeat_MI ; GOTO Repeat_MI
Until_MI DBF Remainder$d,Repeat_MI ;UNTIL (there have been four rotates)
BRA.S C50 ;GOTO C50 {Calculation complete}
; Offset is positive.
PlRemainder SUBQ.W #1,Remainder$d ;Adjust Remainder$d for DBF <C361>
;REPEAT
Repeat_PL ADDQ.B #1,TheByteLane$d ; TheByteLane$d <- the next byte lane (Check all byte lanes 0..3) <C361><C726
AND.B #$03,TheByteLane$d ; <C726>
@10 ADDQ.L #1,PCOffset$d ; PCOffset$d <- PCOffset$d + 1
BTST.B TheByteLane$d,spByteLanes(spBlkPtr$a0) ; IF (no ROM in this byte lane) THEN
BEQ.S Repeat_PL ; GOTO Repeat_PL
Until_PL DBF Remainder$d,Repeat_PL ;UNTIL (there have been four rotates)
; Calculations complete, offset was calculated successfully, now add it to the current pointer.
C50 ADD.L PCOffset$d,spsPointer(spBlkPtr$a0) ;spsPointer <- spsPointer + PCOffset$d
MOVEQ #0,Status$d0 ;Status$d0 <- good.
; Restore globals & return
End MOVEM.L (SP)+,D3-D6 ;Restore registers <C438/19Nov86><C783>
RTS ;Return
ENDWITH
;END CalcsPointer
ENDP
EJECT
**********************************************************************
*
* FUNCTION GetSlotDrvr : Get Driver.
* Load a Mac-OS driver into a relocatable block on the system heap.
*
* Parameter block:
* -> spIOFileName - The file name (probably not useful).
* -> spSlot - The slot the driver is in.
* -> spId - Id of the sResource which contains the driver.
* -> spExtDev - Id of the external device (not useful to drivers in Decl ROM).
* -> spsExecPBlk - Pointer to any extra parameters useful to the driver
* and/or the sLoad record.
* <- spResult - Handle/Ptr to the driver.
* *** New feature, add if necessary *** see Rich C. <- spFlags - If fDRAMBased is set then is Handle to the driver.
*
**********************************************************************
GetSlotDrvr FUNC EXPORT
;VAR
ParamBlk$a0 EQU A0 ;Parameter block pointer (Used by SDM & _NewHandle) <C600>
h$a0 EQU A0 ;Pointer to the handle to be disposed of. <C600>
NewHandRes$a0 EQU A0 ;***Used by _NewHandle <C600>
spBlkPtr$a EQU A1 ;SDM parameter block. <C600>
seBlkPtr$a EQU A2 ;SDM parameter block. <C600>
DrvrHand$a EQU A3 ;Handle to the driver. <C600>
Status$d0 EQU D0 ;Status
Size$d0 EQU D0 ;***Used by _NewHandle
StripAddr$d0 EQU D0 ;Strip Address. <C887>
Temp$d EQU D1 ;Temporary data register
SavedId$d EQU D2 ;Saved Id
BRA BeginGetSlotDrvr ; <C783>
EJECT
*====================================================================
* FUNCTION DynLoadDrvr : Dynamically Load Driver.
* Execute a given block of code to load the driver. This code must
* set spResult with a handle to the driver.
*
* Vars imported from GetSlotDrvr:
* Status$d0
* Status$d0
* Temp$d
* ParamBlk$a0
*
* Parameter block:
* -> spSlot - The slot the driver is in.
* -> spId - Id of the sResource which contains the driver.
* -> spExtDev - Id of the external device (not useful to drivers in Decl ROM).
* -> spsExecPBlk - Pointer to any extra parameters useful to the driver
* and/or the sLoad record.
* <- spResult - Handle to the driver (Set by the sLoad record).
* *** New feature, add if necessary *** see Rich C. <- spFlags - If fDRAMBased is set then is Handle to the driver.
*
*====================================================================
;----------------------------------------------------------------------
; DynLoadDrvr
;----------------------------------------------------------------------
;BEGIN
WITH spBlock,FHeaderRec,seBlock
; Initialize.
DynLoadDrvr CLR.L spParamData(A0) ; only look at enabled guys <1.4>
_GetsRsrcPtr ; find the ptr to the sRsrc <1.4>
BNE.S DError ;Branch if error.
; Execute the code to load the driver.
MOVE.B #sRsrcLoadRec,spId(ParamBlk$a0) ;Load the driver.
_sExec
BNE.S DError ;IF SDM error THEN GOTO DError
MOVE.L spsExecPBlk(ParamBlk$a0),seBlkPtr$a ;seBlkPtr$a <- pointer to the seBlock <C614>
TST.W seStatus(seBlkPtr$a) ;Test the status of the sLoad code. <C614>
BNE.S DError ;Branch if error. <C614>
MOVE.L seResult(seBlkPtr$a),spResult(ParamBlk$a0) ;Return the handle to the caller.
MOVE.B seFlags(seBlkPtr$a),spFlags(ParamBlk$a0) ;Handle or Ptr? See fRAMBased.
MOVEQ #0,Status$d0
BRA.S EndDynLoad ;GOTO EndDynLoad
; Error.
DError MOVE.L #smsGetDrvrErr,Status$d0 ;Status <- smsGetDrvrErr
EndDynLoad ; <1.8>
RTS
ENDWITH
;END DynLoadDrvr
EJECT
*====================================================================
* FUNCTION StatLoadDrvr : Statically Load Driver.
* Load the driver from the driver directory.
*
* Vars imported from GetSlotDrvr:
* Status$d0
* Temp$d
* spBlkPtr$a
* ParamBlk$a0
* NewHandRes$a0
* h$a0
* DrvrHand$a
*
* spsPointer
*
* Parameter block:
* -> spSlot - The slot the driver is in.
* -> spId - Id of the sResource which contains the driver.
* <- spResult - Handle to the driver (Set by the sLoad record).
* *** New feature, add if necessary *** see Rich C. <- spFlags - If fDRAMBased is set then is Handle to the driver.
*
*====================================================================
;----------------------------------------------------------------------
; StatLoadDrvr
;----------------------------------------------------------------------
;BEGIN
WITH spBlock,FHeaderRec
; Get a pointer to the sResource list and find the driver directory.
StatLoadDrvr _sRsrcInfo ;Get a pointer to the sResource list. <C468>
BNE SError2 ; <SM9> CSS
MOVE.B #sRsrcDrvrDir,spId(ParamBlk$a0) ;Find the driver directory.
_sFindStruct
BNE.S SError2
; Load the driver into the system heap zone.
LoadDrvr MOVE.B #sMacOS68020,spId(ParamBlk$a0) ;Load a MacOS 68020 driver. <C807>
BSET.B #fCkReserved,spFlags(ParamBlk$a0) ;Check reserved byte of the PBS. <C807>
_sReadPBSize ;Read the physical block size. <C807>
BEQ.S @10 ;IF ok THEN <C807>
; GOTO @10 <C807>
MOVE.B #sMacOS68000,spId(ParamBlk$a0) ;Load a MacOS 68000 driver.
BSET.B #fCkReserved,spFlags(ParamBlk$a0) ;Check reserved byte of the PBS. <C600>
_sReadPBSize ;Read the physical block size. <C600>
BNE.S SError2 ;IF Error THEN <C600>
; GOTO End <C600>
@10 SUBQ.L #4,spSize(ParamBlk$a0) ;Size <- PhyBlkSize - 4 {By pass the physical block size}.<C600>
MOVE.L spSize(ParamBlk$a0),Size$d0
_ResrvMem ,SYS ;Compact the system heap. <C600><C783>
BNE.S SError2 ;Branch if error <C600><C783>
MOVE.L spSize(ParamBlk$a0),Size$d0 ; <C783>
_NewHandle ,SYS ;Allocate the memory on the system heap.<C600>
BNE.S SError2 ; GOTO SError2 <C600>
MOVE.L NewHandRes$a0,DrvrHand$a ;Put the result of _NewHandle into DrvrHand$a. <C600>
MOVE.L (NewHandRes$a0),StripAddr$d0 ;Dereference. <C887>
_StripAddress ;Strip the address. <C887>
MOVE.L StripAddr$d0,spResult(spBlkPtr$a) ;Put the pointer to the block into spResult. <C600><C887>
MOVE.L spBlkPtr$a,ParamBlk$a0 ;Restore the SDM parameter block pointer. <C600>
_sReadStruct ;Read the sBlock into the buffer. <C600>
BNE.S SError1 ;IF error THEN <C600>
; GOTO SError1. <C600>
MOVE.L DrvrHand$a,spResult(ParamBlk$a0) ;Put handle to the driver in spResult. <C600>
JSR ([jCacheFlush]) ; flush the caches <18> rb
BRA.S EndStatLoad ;GOTO end. <C600>
; ERRORS
; Error(1): Dispose of the sBlock and restore the zone.
SError1 MOVE.L DrvrHand$a,h$a0
_DisposHandle ;Dispose of the handle.
; Error(2): Set Status$d, spResult and exit with error.
SError2 MOVE.L spBlkPtr$a,ParamBlk$a0 ;Restore spBlkPtr
CLR.L spResult(ParamBlk$a0) ;Result <- nil
MOVE.L #smsGetDrvrErr,Status$d0 ;Status <- smsGetDrvrErr
EndStatLoad RTS
ENDWITH
;END StatLoadDrvr
EJECT
;----------------------------------------------------------------------
; GetSlotDrvr
;----------------------------------------------------------------------
WITH spBlock
; Patch out Drivers for any Apple Cards that need it.
BeginGetSlotDrvr
; This is the original entry-point. It is called by GetDevIndex
Export OrigGetSlotDrvr
OrigGetSlotDrvr
MOVEM.L A2-A3,-(SP) ;Save registers <C783>
MOVE.L ParamBlk$a0,spBlkPtr$a ;Save spBlkPtr
MOVE.B spId(ParamBlk$a0),SavedId$d ;Save Id.
; Try to load the driver by executing the code from proper sLoad list in the sRsrc_LoadDir.
BSR DynLoadDrvr ;spResult <- DynLoadDrvr(->spSlot,->spId,<-Status)
BEQ.S @Done ;Driver was successfully loaded.
; Try to load the driver from the sRsrc_DrvrDir.
MOVE.B SavedId$d,spId(ParamBlk$a0)
BSR StatLoadDrvr ;spResult <- StatLoadDrvr(->spSlot,->spId,<-Status)
; Clean up and exit
@Done MOVE.L spBlkPtr$a,ParamBlk$a0 ;Restore spBlkPtr
MOVE.B SavedId$d,spId(ParamBlk$a0) ;Restore Id.
MOVEM.L (SP)+,A2-A3 ;Restore registers <C783>
ExitGetSlotDrvr RTS
ENDWith
EJECT
;=========================================================================================
; slotinfo
;=========================================================================================
;_______________________________________________________________________________________ <v1.2>
; ReadSlotPRAM - read PRAM associated with a slot
; PutSlotPRAM - write PRAM associated with a slot
; InitSlotPRAM - write PRAM including board and record id's
;
; Read or write the parameter RAM associated with the given slot number. These
; routines handle both internal and external slot PRAM.
;
;
; Input : reg A0 = ptr to spBlock
; Output : reg D0 = status, 0=ok CCR reflects status
; A0 = ptr to spBlock
;
; For ReadSlotPRAM :
; spBlock : -> spSlot slot whose PRAM to read
; -> spResult pointer to 8 byte buffer to place PRAM data
;
; For PutSlotPRAM and InitSlotPRAM :
; spBlock : -> spSlot slot whose PRAM to read
; -> spsPointer pointer to 8 byte buffer to place PRAM data
;
SlotPRAM PROC
EXPORT ReadSlotPRAM
EXPORT PutSlotPRAM
EXPORT InitSlotPRAM
WITH spBlock,slotGlobals
ReadSlotPRAM
MOVEQ #0,D0 ; clear reg D0 to indicate a read
MOVE.L spResult(A0),spParamData(A0) ; temp set = ptr to buffer to read to
BRA.S CommonPRAM ; goto shared routine for read and write
PutSlotPRAM
MOVEQ #1,D0 ; set reg D0 to indicate a write
MOVE.L spsPointer(A0),spParamData(A0) ; temp set = ptr to bufr to write from
BRA.S CommonPRAM ; goto shared routine for read and write
InitSlotPRAM
MOVEQ #2,D0 ; set reg D0 to indicate executive write
MOVE.L spsPointer(A0),spParamData(A0) ; temp set = ptr to buf to write from
CommonPRAM
@savedregs Reg d1/d3/a0-a1 ; <8>
movem.l @savedregs,-(sp) ; save regs
CLR.W D3
MOVE.L D0,D1 ; D1 = indicates which routine executing
MOVE.B spSlot(A0),D3 ; D3 = slot number with high byte clear
BNE.S @CheckRange ; not slot zero
; <SM2> rb, Start
; Check for slot zero and convert slot number to relative slot to index into PRAM. On <1.2>
; RBV machines, slot zero steals the PRAM from one of the 9-$E slots. The slot mgr <1.2>
; is only assigned enough PRAM for 6 slots. <1.2>
WITH VideoInfo ; <SM3> rb
movea.l UnivInfoPtr,a1 ; point to the ProductInfo record <1.9>
adda.l ProductInfo.VideoInfoPtr(a1),a1 ; point to the VideoInfo record <1.9>
move.b VideoInfo.SlotNumberAlias(a1),d3; get the alias for slot zero PRAM <1.9>
@CheckRange ; not slot zero
MOVEA.L spParamData(A0),A1 ; A1 = ptr to buf to read to or write from <1.9>
; Check range for internal slots with PRAM on the motherboard
MOVE.W #smSlotOOBErr,D0 ; assume error
CMP.B #sLastSlot,D3
BHI.S @Done ; slot number out of range
CMP.B #FirstPRAMSlot,D3 ; a motherboard slot?
bge.s @InternalPRAM ; good slot - get PRAM, <SM2> rb, End
; Slot number is in the expansion chassis range. If an expansion chassis is present, <1.5>
; call a vendor routine, to handle PRAM requests.
TST.W ([sInfoPtr],expnSlot) ; is there an expansion chassis ?
BEQ.S @Done ; nope - can't handle this slot's PRAM request
; ***** Add code to look for and call PRAM handling code - use sExec ? *****
BRA.S @Done ; should never get to this point
; Setup parameters to read or write PRAM from motherboard
@InternalPRAM
SUB.B #FirstPRAMSlot,D3 ; convert slot to relative index
MULU.W #SizesPRAMRec,D3 ; index to PRAM record for slot
ADD.W #SMPRAMTop,D3 ; add offset to slot manager PRAM
MOVE.L #SizesPRAMRec<<16,D0 ; move number of bytes to read into high word
MOVE.W D3,D0 ; move offset in PRAM into low word
movea.l a1,a0 ; setup A0 = ptr to buffer or data <2.1>
TST.B D1 ; is this a read or write?
BNE.S @WritePRAM ; non-zero - must be a write
_ReadXPRAM
BRA.S @Done
@WritePRAM
subq.l #2,d1 ; regular write or executive write? <2.1>
BEQ.S @DoWrite ; executive write
ADDQ.L #2,A0 ; skip over board and record id
sub.l #$20000-2,d0 ; sub two from number of bytes to write (in high word) <2.1>
; add two to offset into PRAM, pass board and record id's
@DoWrite _WriteXPRAM
@Done movem.l (sp)+,@savedregs ; restore ptr to spBlock
RTS ; done
;_______________________________________________________________________________________ <1.5>
; FindsInfoRecPtr - find sInfo record ptr
;
; Given the slot number in an spBlock, return a pointer to the sInfo record in the
; spResult field. The pointer is retrieved from the sInfo vector table.
;
; Input : reg A0 = ptr to spBlock
; Output : reg D0 = status, 0=ok CCR reflects status
; A0 = ptr to spBlock
;
; spBlock : -> spSlot slot number
; <- spResult ptr to sInfo record
;
FindsInfoRecPtr PROC EXPORT
WITH spBlock
; Verify slot is good
moveq.l #0,d0 ; clear register <2.0>
MOVE.B spSlot(A0),D0 ; D0 = slot number
CMPI.B #sLastSlot,D0
bhi.S @Error ; error - slot number out of range
; Calculate the pointer to the desired record
MOVE.L ([sInfoPtr],d0.w*4),spResult(A0) ; get ptr to sInfo record
MOVEQ #0,D0 ; sInfo record present - return good status
BRA.S @Done
@Error MOVE.W #smSlotOOBErr,D0 ; set error return
@Done RTS ; end - FindsInfoRecPtr
ENDP
;_______________________________________________________________________________________ <1.4>
; GetsRsrcPtr - find the pointer to an sResource list
; FindsRsrcPtr - find the pointer to an enabled sResource List
;
; Given the <slot><id><extdev>, return the pointer to the sResource list. This routine
; differs from the original slot manager in that the sResource list pointer is fetched
; from the SRT instead of the sResource directory on the card. This change allows
; fetching pointers to replaced or RAM sResources.
;
; Input : reg A0 = ptr to spBlock
; Output : reg D0 = status, 0=ok CCR reflects status
; A0 = ptr to spBlock
;
; spBlock : -> spSlot slot number
; -> spId sResource id
; <- spsPointer ptr to sResource list
;
; GetsRsrcPtr Only :
; -> spExtDev external device id
; -> spParamData input flag filed
; bit 0 set = include disabled sResources in search
; clr = ignore disabled sResources
; bit 1 set = restrict search to single given slot
; clr = search all slots
; bit 2 set = search for next <slot><id><extdev>
; clr = search for given <slot><id><extdev>
;
FindsRsrcPtr PROC EXPORT
EXPORT GetsRsrcPtr
WITH spBlock,srrBlock
CLR.B spExtDev(A0) ; not required by old slot mgr
CLR.L spParamData(A0) ; clear flags field
GetsRsrcPtr
MOVE.L A1,-(SP) ; save reg
_FindSRTRec ; get ptr to SRT entry
BNE.S @Done ; not found - error
MOVEA.L spsPointer(A0),A1 ; A1 = ptr to SRT entry
MOVE.L srrsRsrcPtr(A1),spsPointer(A0) ; return ptr to sRsrc
@Done MOVEA.L (SP)+,A1
RTS
;_______________________________________________________________________________________ <2.3>
; PtrToSlot - map sPointer to slot number
;
; Given a valid pointer to a slot, map it to the slot number. Both major and minor
; NuBus address space pointers are mapped. The minor slot number must be a 32bit
; NuBus pointer. This routine map change to map into an array of valid slots to
; take into account bus expansion chassis's. A pointer within the size of
; ROMBase (assumed in ROM) is translated into slot 0.
;
; Input : reg A0 = ptr to spBlock
; Output : reg D0 = status, 0=ok CCR reflects status
; A0 = ptr to spBlock
;
; spBlock : -> spsPointer the sPointer
; <- spSlot slot number
;
PtrToSlot Proc Export
With spBlock
movem.l d1-d2,-(sp) ; <SM2> rb
; Verify a good sPointer
; <SM2> rb, Start
MOVE #smsPointerNil,D0 ; assume nil ptr - set error status
MOVE.L spsPointer(A0),D1 ; D1 = sPointer
BEQ.S @Done ; nil pointer - error
ROL.L #8,D1
MOVE.B ROMBase,D2
CMP.B D2,D1
BEQ.S @skip_older
MOVE.L spsPointer(A0),D1
; Determine the slot
clr.b d1 ; clear low byte of pointer <2.1>
ROL.L #4,D1 ; determine if major or minor space
CMP.B #$0F,D1 ; minor space?
BEQ.S @minor ; minor slot space
; Super slot space - if the high nibble is the same as ROMBase, then this is an access to
; the host ROM's declaration data (or ram). Translate it into slot 0.
MOVE.B ROMBase,D2 ; D2 = high byte of ROMBase
lsr.b #4,d2 ; shift high nib to low nibble <2.1>
CMP.B D2,D1 ; same?
BNE.S @FoundSlot ; must be other super slot space
; Pointer is to ram or rom. Translate it to slot 0.
@skip_older
MOVEQ #0,D1 ; access to host ROM - translate to slot 0
BRA.S @FoundSlot
@minor clr.b d1 ; sxxxxx0F to sxxxxx00 <2.1>
ROL.L #4,D1 ; minor space - reg D1 = xxxxx00s
@FoundSlot MOVE.W #smSlotOOBErr,D0 ; assume out of bounds
CMP.B #sLastSlot,D1 ; good slot number?
BHI.S @Done ; must be slot $0F which is bad
MOVE.B D1,spSlot(A0) ; return slot number
MOVEQ #0,D0 ; set good return
@Done TST D0 ; set condition codes
movem.l (sp)+,d1-d2
RTS ; done - PtrToSlot
ENDP ; <SM2> rb, End
;_______________________________________________________________________________________
; ReadFHeader - copy a declaration ROM's format header block
;
; Copy a declaration ROM's format header block into a buffer. The pointer to the
; buffer is an argument.
;
; Input : reg A0 = ptr to spBlock
; Output : reg D0 = status, 0=ok CCR reflects status
; A0 = ptr to spBlock
;
; spBlock : -> spSlot slot to read
; <-> spResult pointer to buffer
;
ReadFHeader PROC EXPORT
WITH spBlock,sInfoRecord,FHeaderRec
movem.l a1-a2,-(sp)
MOVE.L spResult(A0),A2 ; A2 = save ptr to buffer
_sFindsInfoRecPtr ; ret - spResult(A0) = ptr to sInfo record
BNE.S @Done ; error - bad slot
MOVE.L spResult(A0),A1 ; A1 = ptr to sInfo record
MOVE.W siInitStatusA(A1),D0 ; is there a card installed ? <1.5>
BMI.S @Done ; bad status - error <1.5>
; Offset the ROM ptr to the bottom of the format block
MOVE.L siROMAddr(A1),spsPointer(A0) ; set ptr to top of ROM
MOVE.L #-fhBlockSize+1,spOffsetData(A0) ; set offset to move ptr
MOVE.B siCPUByteLanes(A1),spByteLanes(A0) ; set byte lanes field
_sCalcsPointer
BNE.s @Done ; some error
; Copy format block into RAM
MOVE.L A2,spResult(A0) ; set buffer pointer
MOVE.L #fhBlockSize,spSize(A0) ; number of bytes to copy
_sReadStruct
@Done movem.l (sp)+,a1-a2
RTS ; done - ReadFHeader
ENDP
;_______________________________________________________________________________________ <1.4>
; CkCardStat - check a card's status
;
; Check a card's status in the sInfo array. If there is no entry for the slot, then
; the card is not installed. If the initStatusA field of the sInfo record is negative,
; then the card status is also bad.
;
; Input : reg A0 = ptr to spBlock
; Output : reg D0 = status, 0=ok CCR reflects status
; A0 = ptr to spBlock
;
; spBlock : -> spSlot slot to get status
;
CkCardStat PROC EXPORT
WITH spBlock,sInfoRecord
MOVE.L A2,-(SP)
_sFindsInfoRecPtr ; get ptr to sInfo record
BNE.S @CardBad ; error - card not installed
MOVEA.L spResult(A0),A2 ; A2 = ptr to sinfo record
TST.W siInitStatusA(A2) ; check card's status field
BMI.S @CardBad ; error - card status is bad
MOVEQ #0,D0 ; card is ok
BRA.S @Done
@CardBad MOVE.L #smCkStatusErr,D0 ; set bad card status
@Done MOVE.L (SP)+,A2
RTS ; done - CkCardStat
;_______________________________________________________________________________________ <1.3>
; SlotVersion - return slot manager version number
;
; Return the slot manager version number. The Mac II 1.0 and 1.2 ROM's are considered
; version 1. The version in the Cobra II is version 2.
;
; Input : reg A0 = ptr to spBlock
; Output : reg A0 = ptr to spBlock
;
; spBlock : <- spResult version number (long)
; <- spPointer nil (in case of future use)
;
SlotVersion PROC EXPORT
WITH spBlock
if forROM then
MOVE.L #slotVNum,spResult(A0)
else
move.l #1,spResult(A0)
endif
CLR.L spsPointer(A0)
MOVEQ #0,D0 ; set a good return
RTS
;_______________________________________________________________________________________
; GetsRsrc - get sResource by id
; NextsRsrc - get next visible sResource by id
;
; Return information on the next sResource starting from the given slot number and
; sResource id. Unused fields in the spBlock are set to zero. The difference between
; GetsRsrc and NextsRsrc, is that NextsRsrc only includes enabled (visible) entries
; in the search. GetsRsrc uses spParamData as a flags field to indicate the type of
; enabled and disabled entries in the search.
;
; Input : reg A0 = ptr to spBlock
; Output : reg D0 = status, 0=ok CCR reflects status
; A0 = ptr to spBlock
;
; spBlock : <-> spSlot slot to start looking in
; <-> spId id to start looking from
; <-> spExtDev external device identifier
; <- spsPointer pointer to sResource record
; <- spRefNum driver reference number (if applicable)
; <- spIOReserved
; <- spCategory sType fields
; <- spCType
; <- spDrvrSW
; <- spDrvrHW
; <- spHWDev hardware device id (if applicable)
;
; For GetsRsrc only :
; -> spParamData input flag filed
; bit 0 set = include disabled sResources in search
; clr = ignore disabled sResources
; bit 1 set = restrict search to single given slot
; clr = search all slots
; bit 2 set = search for next <slot><id><extdev>
; clr = search for given <slot><id><extdev>
;
; <- spParamData state of sResource: 0=enabled, 1=disabled
;
NextsRsrc PROC EXPORT
EXPORT GetsRsrc
WITH sInfoRecord,srrBlock,spBlock,SlotRsrcType,srtLink,slotGlobals
CLR.L spParamData(A0) ; clear optional flags
BSET.B #fnext,spParamData+3(A0) ; search for next SRT entry
GetsRsrc
MOVE.L A1,-(SP)
_FindSRTRec ; search table
BNE.S @Error ; some error or not found
; sResource entry found - set parameters and exit
MOVEA.L spsPointer(A0),A1 ; pass A1 = ptr to SRT entry
slotjsr SrToSpBlock ; fill in spBlock with srrBlock values
BRA.S @Done
; sResource was not found
@Error MOVE.W #smNoMoresRsrcs,D0 ; set error return
@Done MOVE.L (SP)+,A1
TST.W D0
RTS ; done - NextsRsrc
;_______________________________________________________________________________________ <1.5>
; GetTypesRsrc - get sResource by type
; NextTypesRsrc - get next visible sResource by type
;
; Search for an sResource by its type fields - <category><type><drvrSW><drvrHW>. Mask
; the type fields appropriately by the mask given in the type mask field of the spBlock.
; Return information on the next sResource starting from the given slot number and
; sResource id. Unused fields in the spBlock are set to zero. The difference between
; GetTypesRsrc and NextTypesRsrc, is that NextTypesRsrc only includes enabled (visible)
; entries in the search. GetTypesRsrc uses spParamData as a flags field to indicate the type
; of enabled and disabled entries in the search.
;
; Input : reg A0 = ptr to spBlock
; Output : reg D0 = status, 0=ok CCR reflects status
; A0 = ptr to spBlock
;
; spBlock : -> spTBMask sType mask (bit 0-3) - bit set means mask off this field
; <-> spSlot slot to start looking in
; <-> spId id to start looking from
; <-> spExtDev external device identifier
; <- spHWDev hardware device id (if applicable)
; <- spsPointer pointer sResource list (*****different than old slot manager)
; <- spRefNum driver reference number (if applicable)
; <- spIOReserved
; <- spCategory sType fields
; <- spCType
; <- spDrvrSW
; <- spDrvrHW
;
; For GetTypesRsrc only :
; -> spParamData input flag filed
; bit 0 set = include disabled sResources in search
; clr = ignore disabled sResources
; bit 1 set = restrict search to single given slot
; clr = search all slots
;
; <- spParamData state of sResource: 0=enabled, 1=disabled
;
EXPORT NextTypesRsrc,GetTypesRsrc
NextTypesRsrc
CLR.L spParamData(A0) ; clear optional flags
GetTypesRsrc
MOVEM.L D1-D6/A1,-(SP)
; Use the type mask field in the spBlock as an index into a table to get the
; bit mask for the sType fields <category><type><drvrsw><drvrhw>
MOVEQ #0,D0 ; clear for use as index
MOVE.B spTBMask(A0),D0 ; D0 = index (mask value)
LEA MaskTbl,A1 ; addr of table in reg A1
LSR.B #2,D0 ; use bits <3,2> as index
MOVE.L (A1,D0.W*4),D1 ; D1 = mask for <category><type>
MOVE.B spTBMask(A0),D0 ; D0 = index (mask value)
AND.B #3,D0 ; use low 2 bits
MOVE.L (A1,D0.W*4),D2 ; D2 = mask for <drvrsw><drvrhw>
MOVE.L spCategory(A0),D3 ; get LONG, D3 = <category><type> to match
MOVE.L spDrvrSW(A0),D4 ; get LONG, D4 = <drvrsw><drvrhw> to match
AND.L D1,D3 ; mask target <category><type>
AND.L D2,D4 ; mask target <drvrsw><drvrhw>
; Search SRT comparing the type fields of the entries to the type we are looking
; for. Mask the entry's type field before doing the compare.
; reg D1 = <cat><type> mask, D2 = <drvrsw><drvrhw> mask
; reg D3 = <cat><type> to match, D4 = <drvrsw><drvrhw> to match
@Loop BSET.B #fnext,spParamData+3(A0) ; search for next SRT entry
_FindSRTRec ; search table
BNE.S @Done ; no more good entries in the SRT - failed
MOVE.L spsPointer(A0),A1 ; get A1 = ptr to SRT entry
MOVE.L srrSlot(A1),spSlot(A0) ; update spSlot,spId,spExtDev,spHwDev
MOVE.L D1,D5 ; get D5 = copy of <category><type> mask
AND.L srrCategory(A1),D5 ; mask <cat><type> into D5
CMP.L D3,D5 ; <does <category><type> match ?
BNE.S @Loop ; does not match - get next entry
MOVE.L D2,D6 ; get D6 = copy of <drvrsw><drvrhw> mask
AND.L srrDrvrSw(A1),D6 ; mask <drvrsw><drvrhw> into D6
CMP.L D4,D6 ; does <drvrsw><drvrhw> fields match ?
BNE.S @Loop ; no match - get next entry
; Found the entry - return the sResource information
slotjsr SrToSpBlock ; fill in spBlock with srrBlock values
MOVEQ #0,D0 ; set good return
@Done MOVEM.L (SP)+,D1-D6/A1
RTS
;_______________________________________________________________________________________ <1.3>
; Mask table for NextTypesRsrc
;
; This is a table of bit masks for the <category><type><drvrSW><drvrHW> fields of
; an sResource. The table is indexed by the spTBMask field of the spBlock. Bits
; <1,0> are used as an index for the <drvrSW><drvrHW> mask. Bits <3,2> are used as
; an index for <category><type> field.
;
MaskTbl DC.W $FFFF,$FFFF ; index 00
DC.W $FFFF,$0000 ; 01
DC.W $0000,$FFFF ; 10
DC.W $0000,$0000 ; 11
;_______________________________________________________________________________________ <1.5>
; UpdateSRT - add or update an entry in the slot resource table
; InsertSRTRec - add a ROM or RAM sResource to the slot resource table
;
; UpdateSRT adds or updates an entry in the SRT based on spSlot, spId, and spExtDev. If
; the slot-id-extdev are found in the SRT, then the RefNum and IOReserved fields are
; updated. If the entry is not found, then a new record is added to the table with
; spSlot, spId, spExtDev, spRefNum, and spIOReserved. In addition to these fields,
; srrsRsrcPtr, srrType, and srrHWDev are updated by reading their values from the
; appropriate declaration ROM. Updates may be made to enabled sResources only.
;
; InsertSRTRec is similar to UpdateSRT except it uses the spsPointer field as an argument.
; If the spsPointer field is nil, then an sResource is added to the SRT if it exist
; in the sResource directory (based on slot-id-extdev) in the declaration ROM. If
; spsPointer is not nil, then assume we are adding a RAM sResource (not implemented yet).
; Also accept flags to indicate whether the sResource should be enabled or disabled.
;
; There are 5 cases to consider in the shared code :
; UpdateSRT :
; (1) Add a new sRsrc dir entry to SRT
; (5) Modify an existing SRT entry
;
; InsertSRT :
; (1) Add a new sRsrc dir entry to SRT (spsPointer == nil)
; (2) Add a new RAM sRsrc (not in sRsrc dir) to SRT (spsPointer == RAM addr)
; (3) Replace an SRT entry with a new RAM sRsrc (spsPointer == RAM addr)
; (4) Add a new RAM sRsrc (replacing one in sRsrc dir) to SRT (spsPointer == RAM addr)
;
; In case (3), when replacing an sResource, if there is a reference number
; (i.e. a driver) associated with the sResource we are replacing, then recalculate
; the dCtlDevBase field in the driver's DCE
;
;
; Input : reg A0 = ptr to spBlock
; Output : reg D0 = status, 0=ok CCR reflects status
; A0 = ptr to spBlock
;
; For UpdateSRT and InsertSRT :
; spBlock : -> spSlot slot number
; -> spId sResource id
; -> spExtDev sResource external device id
; -> spRefNum reference number of driver for sResource
; -> spIOReserved reserved field
;
; In addition for InsertSRT only :
; -> spsPointer if nil then ROM sResource, else RAM sResource
; -> spParamData (formerly spStackPtr) 1 = disable, 0 = enable sResource
;
EXPORT UpdateSRT,InsertSRT
UpdateSRT
MOVEQ #1,D0 ; reg D0 = 1 indicates UpdateSRT
CLR.L spsPointer(A0) ; nil to simulate AddSRTRec call for add-new case
CLR.L spParamData(A0) ; do not disable the sResource
BRA.S ModifySRT
InsertSRT
MOVEQ #0,D0 ; reg D0 = 0 indicates InsertSRTRec
; Begin shared code for both UpdateSRT and InsertSRTRec
ModifySRT
MOVEM.L D1-D2/A1-A2,-(SP) ; save registers
MOVE.L D0,D1 ; D1 = flag indicating Update or Insert
MOVEA.L spsPointer(A0),A2 ; save reg A2 = spsPointer (ptr to RAM sRsrc or nil)
MOVE.L spParamData(A0),D2 ; save enable/disable flag to set
; Search the SRT for the <spSlot><spId><spExtDev> to see if the sResource already exists.
CLR.L spParamData(A0) ; clear flags to FindSRTRec
BSET.B #fall,spParamData+3(A0) ; set flag to look for all sRsrc's
_FindSRTRec
BEQ.S @Found ; sRsrc found - must be an update or a replacement
; <case 3 or 5>
; At this point, the <spSlot><spId><spExtDev> is not in the SRT Add the sRsrc to the SRT.
; <case 1,2, or 4>
MOVE.L A2,spsPointer(A0) ; restore ptr to RAM sRsrc or nil
MOVE.L D2,spParamData(A0) ; restore spParamData = enable/disable flag
slotjsr NewSRTEntry
BRA.S @Done
; Doing update or replacement
@Found MOVEA.L spsPointer(A0),A1 ; A1 = ptr to SRT entry, A2 = ptr to RAM sRsrc
TST.W D1 ; are we executing Insert or Update SRT?
BEQ.S @Replace ; doing Insert - replace SRT entry with a RAM sRsrc
; Doing an update on an existing entry <case 5>. Check that the entry is enabled
MOVE.W #smNoMoresRsrcs,D0 ; set error return in case
BTST.B #srdisable,srrFlags+3(A1) ; is this an enabled or disabled entry ?
BNE.S @Done ; error - trying to update a disabled entry
MOVE.W spIOReserved(A0),srrIOReserved(A1) ; do update of existing entry <case 5>
MOVE.W spRefNum(A0),srrRefNum(A1)
MOVEQ #0,D0 ; set good return status
BRA.S @Done
; Replace an existing sRsrc entry in the SRT with a new RAM sRsrc.
; <case 3>
@Replace move.l a2,d0 ; is the ptr to the ram sRsrc nil ? <1.7>
beq.s @Done ; yes - ignore this case - leave existing entry <1.7>
MOVE.L A2,spsPointer(A0) ; pass ptr to RAM sResource
MOVE.L D2,spParamData(A0) ; restore spParamData = enable/disable flag
slotjsr InitEntry ; pass reg A1 = ptr SRT entry to replace
; BNE.S @Done ; some error
@Done MOVEM.L (SP)+,D1-D2/A1-A2
RTS
;_______________________________________________________________________________________ <1.5>
; FindSRTRec - search the slot resource table for an sResource
; SearchSRT - search the SRT for visible sResource entries
;
; Search the slot resource table (SRT) for an sResource identified by the <slot number>
; <sResource id> and <ExtDev id> fields. Optionally return a pointer either to the
; found SRT entry, or to the entry immediately following the found entry.
;
; FindSRTRec accepts a flag indicating whether the search sould include disabled
; (invisible) sResource entries in the SRT. SearchSRT is the original slot manager
; _sSearchSRT documented in Inside Mac vol 5, and it only searches visible entries.
;
; Input : reg A0 = ptr to spBlock
;
; Output : reg D0 = status, 0=ok CCR reflects status
;
; spBlock : -> spSlot slot number of sResource
; -> spId id of sResource
; -> spExtDev external device id of sResource
; -> spFlags bit 0 clear means return ptr for the given sResource
; set means return ptr for the following sResource
; <- spsPointer returns pointer to found or next entry in SRT.
;
; FindSRTRec only :
; -> spParamData input flag filed
; bit 0 set = include disabled sResources in search
; clr = ignore disabled sResources
; bit 1 set = restrict search to single given slot
; clr = search all slots
; bit 2 set = search for next <slot><id><extdev>
; clr = search for given <slot><id><extdev>
;
EXPORT SearchSRT,FindSRTRec
SearchSRT
CLR.L spParamData(A0) ; clear flag field for FindSRTRec
BTST.B #fCkForNext,spFlags(A0) ; test for next search flag
BEQ.S FindSRTRec ; not set - go to shared code
BSET.B #fnext,spParamData+3(A0) ; transfer flag to new flag field
FindSRTRec
MOVEM.L D2-D4/A1-A3,-(SP)
MOVEA.L sRsrcTblPtr,A1 ; get ptr to beginning of SRT
MOVE.L spSlot(A0),D2 ; get <slot><id><extdev><hwdev> to search for
CLR.B D2 ; zero <hwdev> - not included in search key
MOVEA.L A1,A2 ; init ptr to "found" entry
MOVEA.L A1,A3 ; init ptr to a "next" entry
MOVE.L MinusOne,D3 ; init a large "next" <slot><id><extdev> entry
; Loop and search each entry in the SRT blocks for the given <slot><id><extdev>.
; Reg A1 = ptr to current SRT entry
; A2 = ptr to "found" entry, D2 = "found" <slot><id><extdev>
; A3 = ptr to "next" SRT entry, D3 = "next" <slot><id><extdev>
@Loop BSR GetSRTEntry ; return A1 = ptr to good entry
BNE.S @NoMore ; no more good entries in the SRT - done
MOVE.L srrSlot(A1),D4 ; get <slot><id><extdev><hwdev>
CLR.B D4 ; clear <hwdev>
CMP.L D2,D4 ; are we looking for this one ?
BGT.S @ChkNext ; no match - try "next" entry
BLT.S @EndLoop ; no match and does not qualify for a "next" entry
MOVEA.L A1,A2 ; matches - set ptr to "found" entry
BTST.B #fnext,spParamData+3(A0) ; are we looking for the "next" entry ?
BEQ.S @Done ; not looking for "next" - we are done
BRA.S @EndLoop ; continue looking for the "next" one
@ChkNext CMP.L D3,D4 ; check against current "next" entry
BHI.S @EndLoop ; nope - greater than existing "next"
MOVEA.L A1,A3 ; found new "next entry - update registers
MOVE.L D4,D3
@EndLoop ADDA.W #SRTRecSize,A1 ; inc SRT entry ptr to next entry
BRA.S @Loop ; continue looking
; Did not find the entry. Reg A3 = ptr to "next" valid SRT entry in the table. If we
; are set to search for the next sResource, then we are ok.
@NoMore
TST.L D3 ; did we ever update D3 ("next" <slot><id><extdev> ?
BMI.S @Error ; nope - there is no "next" entry
MOVEQ #0,D0 ; setup a good return
MOVEA.L A3,A2 ; return ptr to "next" entry
BTST.B #fnext,spParamData+3(A0) ; check "for next" bit
BEQ.S @Error ; error - could not find specific entry
; A1 = valid ptr to NEXT entry. If the oneslot bit is set, then check if it is
; the same as the given slot number.
@CheckSlot
BTST.B #foneslot,spParamData+3(A0) ; restrict search to one slot ?
BEQ.S @Done ; no - we are done
MOVE.B spSlot(A0),D1 ; get D1 = given slot
CMP.B srrSlot(A2),D1 ; still in same slot ?
BEQ.S @Done ; yes - we are done
@Error MOVE.W #smNoMoresRsrcs,D0 ; error - could not find entry in slot
@Done MOVE.L A2,spsPointer(A0) ; return ptr to SRT entry
MOVEM.L (SP)+,D2-D4/A1-A3
TST.W D0
RTS
;_______________________________________________________________________________________ <1.6>
; DeleteSRTRec - delete a given sResource entry from the SRT
;
; Search the slot resource table (SRT) for an sResource identified by the <slot number>
; <sResource id> and <ExtDev id> fields. If found, then remove it from the table.
; This routine will delete an enabled or disabled entry from the SRT.
;
; Entries are removed by moving the last entry in the table to the deleted location.
; This keeps the SRT as a compacted (unordered) list. There is a pointer to the
; last entry stored in the slot manager globals. If after moving the last entry, the
; last block becomes free, then the block is freed. Because there is no back link
; pointer, the SRT must be travered from the beginning to the new last block, so that
; it's link pointer field may be nil-ed.
;
; Input : reg A0 = ptr to spBlock
;
; Output : reg D0 = status, 0=ok CCR reflects status
;
; spBlock : -> spSlot slot number of sResource
; -> spId id of sResource
; -> spExtDev external device id of sResource
;
EXPORT DeleteSRTRec
DeleteSRTRec
MOVEM.L A0-A2,-(SP)
; Find the sResource entry in the SRT
CLR.L spParamData(A0) ; clear flags to FindSRTRec
BSET.B #fall,spParamData+3(A0) ; set flag to look for all sRsrc's
_FindSRTRec
BNE @Error ; sRsrc not found - done
; Mark the entry as being free (just in case)
MOVEA.L spsPointer(A0),A1 ; A1 = ptr to found entry
MOVE.W #srtfree,srrSlot(A1) ; place free tag at beginning of srrblock
; Compact the SRT by copying the last entry to the free space
MOVEA.L ([sInfoPtr],lastSRTPtr),A2 ; A2 = ptr to last entry
MOVE.W #SRTRecSize-1,D0 ; entry size (adjusted for dbra)
@Loop MOVE.B (A2)+,(A1)+ ; copy last entry to freed entry
DBRA D0,@Loop
; Determine whether the last block in the SRT chain is empty and can be freed.
MOVEA.L ([sInfoPtr],lastSRTPtr),A2 ; get ptr to last entry again
MOVE.W #srtfree,srrSlot(A2) ; place free tag at beginning of srrblock
SUBQ.W #1,([sInfoPtr],srtCnt) ; dec total srt cnt
MOVE.W ([sInfoPtr],srtCnt),D0 ; get new cnt
DIVU.W #srtMaxEntries,D0 ; divide total cnt by num entries per blk
AND.L #$FFFF0000,D0 ; D0 = <remainder><quotient>, any remainder ?
BNE.S @Good ; still entries left in last blk - done
; Last SRT block is empty - free the block. Traverse SRT to end to nil the link ptr.
@Free
MOVEA.L A2,A0 ; A0 = ptr to last SRT blk
_DisposPtr ; free the block
MOVEA.L sRsrcTblPtr,A1 ; get ptr to beginning of SRT
@Loop1 ADDA.W #srtBlkSize,A1 ; inc to end of blk
CMPA.L srtNext(A1),A2 ; found end of link ?
BEQ.S @Found ; found new last blk
MOVEA.L srtNext(A1),A1 ; advance to next blk
BRA.S @Loop1 ; continue
@Found CLR.L srtNext(A1) ; nil the link field
MOVEA.L A1,A2 ; get ptr into A2 for the following shared code
@Good SUB.W #SRTRecSize,A2 ; dec ptr to previous entry
MOVE.L A2,([sInfoPtr],lastSRTPtr) ; update new last ptr
MOVEQ #0,D0 ; a good return
BRA.S @Done
@Error MOVE.W #smRecNotFnd,D0 ; same error code as old slot manager
@Done MOVEM.L (SP)+,A0-A2
RTS
;_______________________________________________________________________________________ <1.7>
; GetsRsrcInfo - get sResource information
; SlotRsrcInfo - get visible sResource information
;
; Given an sResource's <slot><id><extdev>, find the sResource's SRT entry and return
; some of the information stored in the SRT entry.
;
; Input : reg A0 = ptr to spBlock
; Output : reg D0 = status, 0=ok CCR reflects status
; A0 = ptr to spBlock
;
; spBlock : -> spSlot slot number
; -> spId sResource id
; -> spExtDev external device id
; <- spHWDev hardware device id (if applicable)
; <- spsPointer pointer sResource list (*****different than old slot manager)
; <- spRefNum driver reference number (if applicable)
; <- spIOReserved
; <- spCategory sType fields
; <- spCType
; <- spDrvrSW
; <- spDrvrHW
;
; For GetsRsrcInfo only :
; -> spParamData input flag filed
; bit 0 set = include disabled sResources in search
; clr = ignore disabled sResources
;
; <- spParamData state of sResource: 0=enabled, 1=disabled
;
EXPORT SlotRsrcInfo,GetsRsrcInfo
SlotRsrcInfo
CLR.L spParamData(A0) ; clear flag field
GetsRsrcInfo
MOVE.L A1,-(SP)
_FindSRTRec ; search for the SRT entry
BNE.S @Done ; error - sRsrc not found
MOVEA.L spsPointer(A0),A1 ; pass A1 = ptr to SRT entry
slotjsr SrToSpBlock ; fill in spBlock with srrBlock values
bra.s @Done
@Error move.w #smRecNotFnd,d0 ; set compatible error return
@Done MOVEA.L (SP)+,A1
RTS
;_______________________________________________________________________________________
; SetsRsrcState - enable or disable an sResource
;
; Search the slot resource table (SRT) for a given sResource identified by <slot number>
; <sResource id> and <ExtDev id> fields. Set the flag in the SRT record to enable or
; disable the sResource.
;
; Input : reg A0 = ptr to spBlock
;
; Output : reg D0 = status, 0=ok CCR reflects status
;
; spBlock : -> spSlot slot number of sResource
; -> spId id of sResource
; -> spExtDev external device id of sResource
; -> spParamData 0 = enable, 1 = disable
;
EXPORT SetsRsrcState ; <1.5>
SetsRsrcState
MOVEM.L D1/A1,-(SP)
MOVE.L spParamData(A0),D1 ; save enable/disable state to set
CLR.L spParamData(A0) ; clear flag field
BSET.B #fall,spParamData+3(A0) ; search all sResources
_FindSRTRec
BNE.S @Done ; sRsrc not found
MOVEA.L spsPointer(A0),A1 ; get A1 = ptr to SRT entry
BCLR.B #srDisable,srrFlags+3(A1) ; assume enabling the sResource
TST.B D1 ; enabling or disabling ?
BEQ.S @Done ; enabling - we already did, so done
BSET.B #srDisable,srrFlags+3(A1) ; disable the sResource
MOVEQ #0,D0 ; set good return
@Done MOVE.L D1,spParamData(A0) ; restore param data field
MOVEM.L (SP)+,D1/A1
TST.W D0
RTS
;_______________________________________________________________________________________ <1.5>
; pNewSRTEntry - Add a new record to the SRT
;
; Add a new record entry to the slot resource table (SRT). Insert the entry to the
; proper place in the table.
;
; Input : reg A0 = ptr to spBlock
;
; Output : reg D0 = status, 0=ok CCR reflects status
;
; spBlock : -> spsPointer ptr to RAM sRsrc, or nil
; -> spParamData enable/disable flag
;
EXPORT pNewSRTEntry
pNewSRTEntry
MOVEM.L D1/A1-A2,-(SP)
MOVE.L spsPointer(A0),D0 ; test if there is a ptr to a RAM sRsrc
BNE.S @FindFree ; yes - add the SRT entry
; Find the sResource in the ROM sResource directory, based on the <spSlot><spId><spExtDev>.
; ***** Under the old slot mgr, if the sRsrc could not be found, it was not an error.
MOVE.L spParamData(A0),D1 ; save enable/disable flags
_sFindsInfoRecPtr ; get ptr to sinfo record
BNE.S @Done
MOVEA.L spResult(A0),A1 ; A1 = ptr to sInfo record
MOVE.L siDirPtr(A1),spsPointer(A0) ; set ptr to ROM directory
_sFindStruct ; search the ROM directory
BNE.S @Done ; can't find it - error (***** different from old slot mgr)
MOVE.L D1,spParamData(A0) ; restore flag
; Find a free entry in the SRT. If there is no free space left, then allocate and
; link a new SRT block.
@FindFree MOVEA.L ([sInfoPtr],lastSRTPtr),A1 ; A1 = ptr to last entry in SRT <1.6>
@Loop CMPI.W #srtfree,srrSlot(A1) ; free block ?
BEQ.S @AddEntry ; found a free SRT entry
CMPI.W #srtend,srrSlot(A1) ; end of current block ?
BEQ.S @NewBlock ; need to alloc a new blk <1.6>
ADDA.W #SRTRecSize,A1
BRA.S @Loop
; Allocate a new SRT block and link it in
@NewBlock MOVEA.L A1,A2 ; save ptr to current blk
slotjsr AllocSRTBlk ; return A1 = ptr to new blk
BNE.S @Done ; memory error
MOVE.L A1,srtNext(A2) ; update link field
; Initialize the new SRT entry - A1 = ptr to free SRT entry
@AddEntry slotjsr InitEntry
BNE.S @Done ; some error <1.6>
ADDQ.W #1,([sInfoPtr],srtCnt) ; inc SRT count <1.6>
MOVE.L A1,([sInfoPtr],lastSRTPtr) ; save ptr to last entry in SRT <1.6>
@Done MOVEM.L (SP)+,D1/A1-A2 ; restore regs
RTS
;_______________________________________________________________________________________
; pInitEntry - init an SRT entry
;
; Initialize and fill in the fields of a slot resource table entry.
;
; Input : reg A0 = ptr to spBlock
; A1 = ptr to SRT entry to initialize
;
; Output : reg D0 = status, 0=ok CCR reflects status
;
; spBlock : -> spSlot slot number
; -> spId sResource id
; -> spExtDev external device id
; -> spRefNum reference number or nil
; -> spIOReserved reserved value, or nil
; -> spsPointer pointer to sResource
; -> spParamData enable/disable flag
;
EXPORT pInitEntry
pInitEntry
MOVEM.L D1/A2,-(SP) ; save regs
SUBA.W #SRSize,SP ; alloc size to read sRsrc sType field
MOVEA.L SP,A2 ; save A2 = ptr to buffer
; Fill in the fields of a new SRT entry
MOVE.B spSlot(A0),srrSlot(A1) ; slot number
MOVE.B spId(A0),srrId(A1) ; sRsrc id
MOVE.B spExtDev(A0),srrExtDev(A1) ; external device id
CLR.B srrHWDev(A1) ; clear hardware device id
MOVE.W spRefNum(A0),srrRefNum(A1) ; driver reference number
MOVE.W spIOReserved(A0),srrIOReserved(A1) ; IO reserved field (good for nothin?)
MOVE.L spsPointer(A0),srrsRsrcPtr(A1) ; set the ptr to the RAM or ROM sRsrc
CLR.L srrFlags(A1) ; clear flag field
MOVE.L spParamData(A0),D0 ; test state of enable/disable value
BEQ.S @ReadStuff ; zero - sRsrc is marked as enabled
BSET.B #srDisable,srrFlags+3(A1) ; set flag to indicate disabled
; Read the hardware sRsrc id
@ReadStuff MOVE.B #sRsrcHWDevId,spId(A0) ; get hardware id (if present)
_sReadByte ; no error if not present
BNE.S @Continue
MOVE.B spResult+3(A0),srrHWDev(A1) ; only a byte value
; Find and read the sRsrc type field <category><type><drvrSW><drveHW>
@Continue MOVE.B #sRsrcType,spId(A0) ; get ptr to sRsrc type
_sFindStruct
BNE.S @Error ; error - sRsrc type field is required
MOVE.L #SRSize,spSize(A0) ; set size to read
MOVE.L A2,spResult(A0) ; set buffer ptr
_sReadStruct
BNE.S @Error ; error - found but can't read ?
MOVE.L sCategory(A2),srrCategory(A1) ; copy <cat><type>
MOVE.L sDrvrSw(A2),srrDrvrSw(A1) ; copy <drvrSW><drvrHW>
; If there is a valid reference number, then find the DCE and calculate the dCtlDevBase <1.5>
MOVEQ #0,D0 ; set a good return <SM2> rb
MOVE.W spRefNum(A0),D1 ; get ref num <SM2> rb
BEQ.S @Done ; no ref num - done <SM2> rb
BSR.S MapUnit ; return reg A2 = ptr to DCE <SM2> rb
BNE.S @Error ; some error with ref num or DCE <SM2> rb
; Read a 24 or 32 bit base address from the sResource <2.0>
; Fixes a bug when calling _InsertSRTRec, inserting a ROM sRsrc with a valid
; refnum, pInitEntry is called. pInitEntry calls _sFindDevBase to calc a base
; addr to place in the DCE. The bug is _sFindDevBase is called with a bad
; sRsrc id. The fix is one line to restore the spId before calling
; _sFindDevBase.
move.b srrId(a1),spId(a0) ; set spId of sRsrc to get base addr (the fix) <SM6>
_sFindDevBase ; get base address
BNE.S @Error
MOVE.L spResult(A0),dCtlDevBase(A2) ; set the dCtlDevBase
MOVE.B srrId(A1),dCtlSlotId(A2) ; update sResource id <1.6>
MOVE.B srrExtDev(A1),dCtlExtDev(A2) ; update the external device id <1.6>
BRA.S @Done
; Some error occurred - mark the SRT entry free again
@Error MOVE.W #srtfree,srrSlot(A1)
@Done MOVE.L srrsRsrcPtr(A1),spsPointer(A0) ; restore ptr to sRsrc
ADDA.W #SRSize,SP ; free sRsrc type buffer
MOVEM.L (SP)+,D1/A2 ; restore regs
TST.W D0 ; set CCR
RTS
; <SM2> rb, from Zydeco...I give you MapUnit !
;_______________________________________________________________________________________ <1.5>
; MapUnit - map a reference number to a pointer to a DCE
;
; Given a driver reference number, get the pointer to it's DCE
;
; Input : reg D1 = reference number
;
; Output : reg A2 = ptr to DCE
; D0 = status, 0=ok CCR reflects status
;
MapUnit
MOVE.W #rfNumErr,D0 ; setup bad ref num error return
NOT.W D1 ; bitwise complement to get unitnum
BMI.S @Done
CMP.W UnitNtryCnt,D1 ; is it in range ?
BGE.S @Done ; skip if it's not
ASL.W #2,D1 ; multiply by four
MOVE.L UTableBase,A2 ; get address of unit table
MOVE.L 0(A2,D1.W),D1 ; add in the offset
BEQ.S @Done ; branch if there is no driver installed
MOVE.L D1,A2 ; DCE handle
MOVE.L (A2),D1 ; dereference handle
BEQ.S @SysErr ; DCE should never be purged - call sys error
MOVE.L D1,A2 ; pointer to Device Control Entry
MOVEQ #0,D0 ; init good return
@Done TST.W D0
RTS
@SysErr MOVEQ #dsIOCoreErr,D0 ; deep shit IOCore error
_SysError ; invoke deep shit
;_______________________________________________________________________________________ <2.0>
; pAllocSRTBlk - allocate and initialize an SRT block
;
; Allocate an SRT block. Initialize all the SRT entries to free.
;
; Input : none
;
; Output : reg A1 = ptr to new SRT block
; D0 = status, 0=ok CCR reflects status
;
EXPORT pAllocSRTBlk
pAllocSRTBlk
move.l a0,-(sp)
move.l #srtBlkSize+srtLinkSize,d0 ; d0 = size to allocate
_NewPtr ,Sys,Clear ; allocate block
bne.s @Done
movea.l a0,a1 ; save copy of ptr to SRT block for the return
move.w #srtMaxEntries-1,d0 ; number of entries in SRT (adjusted for dbra)
@Loop move.w #srtfree,srrSlot(a0) ; mark entries as free
adda.w #SRTRecSize,a0 ; inc to next entry
dbra d0,@Loop
move.w #srtend,srtMarker(a0) ; indicate link and end of block
moveq #noErr,d0 ; good return status
@Done
movea.l (sp)+,a0
rts
;_______________________________________________________________________________________
; GetSRTEntry - return a pointer to the next visible SRT entry
;
; Given a pointer to an entry in an SRT block, return that pointer if the SRT entry
; is visible. If it is not visible, or if the pointer is to the end of the SRT
; block, increment and return a pointer to the next visible SRT entry. Walk down
; the linked SRT blocks if necessary.
;
; Input : reg A0 = ptr to spBlock
; A1 = ptr to SRT entry to get or start search from
;
; Output : reg A1 = ptr to visible SRT entry
; D0 = status, 0=ok CCR reflects status
;
; spBlock : -> spParamData input flag filled
; bit 0 set = include disabled sResources in search
; clr = ignore disabled sResources
;
Export GetSRTEntry
GetSRTEntry
MOVEM.L D1-D2/A0,-(SP)
@Loop MOVE.W srrSlot(A1),D1 ; get <slot><id>
BMI.S @ChkEnd ; escape flag - check for end of block
BTST.B #fall,spParamData+3(A0) ; search includes disabled sResource entries ?
BNE.S @Good ; yes - return whatever entry we have
BTST.B #srdisable,srrFlags+3(A1) ; is this entry enabled ?
BEQ.S @Good ; yes - return ptr to good entry
BRA.S @EndLoop ; otherwise inc to next entry and continue
; Entry has escape flag (srrSlot == $FF). Check for end of block
@ChkEnd CMP.W #srtEnd,D1 ; end of list ?
BNE.S @EndLoop
TST.L srtNext(A1) ; end of block - any more srt blks ?
BEQ.S @NoMore ; end or SRT
MOVEA.L srtNext(A1),A1 ; point to top of next block
BRA.S @Loop ; continue looking
@EndLoop ADDA.W #SRTRecSize,A1 ; inc to next entry
BRA.S @Loop
@NoMore MOVE.W #smRecNotFnd,D0 ; no good entries
BRA.S @Done
@Good MOVEQ #0,D0 ; set good return
@Done MOVEM.L (SP)+,D1-D2/A0
RTS
;_______________________________________________________________________________________ <1.3>
; pSrToSpBlock - copy srBlock info to spBlock
;
;
;
; Input : reg A0 = ptr to spBlock
; A1 = ptr to srBlock
;
; Output : none
;
; spBlock : <- spSlot slot to start looking in
; <- spId id to start looking from
; <- spExtDev external device identifier
; <- spHWDev hardware device id (if applicable)
; <- spsPointer pointer sResource list
; <- spRefNum driver reference number (if applicable)
; <- spIOReserved
; <- spCategory sType fields
; <- spCType
; <- spDrvrSW
; <- spDrvrHW
; <- spParamData 1 = sRsrc is disabled, 0 = enabled (*****different from old slotmgr)
;
EXPORT pSrToSpBlock
pSrToSpBlock
MOVE.B srrSlot(A1),spSlot(A0)
MOVE.B srrId(A1),spId(A0)
MOVE.B srrExtDev(A1),spExtDev(A0)
MOVE.B srrHWDev(A1),spHWDev(A0)
MOVE.W srrRefNum(A1),spRefNum(A0)
MOVE.W srrIOReserved(A1),spIOReserved(A0)
MOVE.W srrCategory(A1),spCategory(A0)
MOVE.W srrCType(A1),spCType(A0)
MOVE.W srrDrvrSw(A1),spDrvrSW(A0)
MOVE.W srrDrvrHw(A1),spDrvrHW(A0)
MOVE.L srrsRsrcPtr(A1),spsPointer(A0) ; return ptr to sRsrc list
CLR.L spParamData(A0) ; clear return flags field
BTST.B #srdisable,srrFlags+3(A1) ; test disable flag
BEQ.S @Done ; not disabled - return zero
MOVE.L #1,spParamData(A0) ; disabled - return 1
@Done RTS
;_______________________________________________________________________________________
; CalcStep - calculate the byte lane's step register value
;
; The step register contains the value to add to a pointer to a declaration ROM, to
; increment to the next consecutive byte or id field. NuBus cards are not required to
; support all 4 byte lanes, so the address increment value between consecutive bytes
; may be greater than 1 (see Designing Cards and Driver's manual for more detail on
; bytelanes).
;
; The step register is a long, having the format of <incr 3><incr 2><incr 1><incr 0>,
; where each increment value is a byte. The increment values indicate from the first
; byte lane supported, how much to increment to the next consecutive byte or id field.
; The step register is used as a rotating shift register, so the increment values may
; repeat. For example, if only 1 byte lane where supported, then the step register
; value would be <04><04><04><04>. If all 4 byte lanes are supported, then the step
; register would be <01><01><01><01>. For 2 or 3 byte lanes, the step register value
; depends on the byte lanes supported.
;
; When used for accessing consecutive bytes, the step register the low byte is added
; to the address to get the next byte. Then the step register is rotated left on byte
; in preparation for the next byte access. When accessing consecutive id's, only the
; low byte is needed as the increment value. No rotation is needed.
;
; Input : reg A0 = ptr to spBlock
;
; Output : reg D0 = status, 0=ok CCR reflects status
;
; spBlock : -> spsPointer NuBus address to calc step value for
; -> spByteLanes byte lane for slot
; -> spFlags if bit 5 is set, then calc for consecutive bytes, else id's
; <- spResult step value
;
CalcStep PROC EXPORT
WITH spBlock
MOVEM.L D1-D3/A1,-(SP)
MOVE.W #smBadsPtrErr,D0 ; assume an error
CLR.W D1 ; clear for later
CLR.W D2 ; clear for later
MOVE.B spsPointer+3(A0),D1 ; get low byte of NuBus address
AND.L #$03,D1 ; get low 2 bits = using which byte lane
MOVE.B spByteLanes(A0),D2 ; reg D2 = byte lanes supported for card
BTST.L D1,D2 ; using a valid byte lane ?
BEQ.S @Error ; a bad pointer for this slot
MOVE.L D2,D3 ; get copy D3 = byte lanes for slot
ASL.W #2,D3 ; adjust index to long entries in table
BTST.B #fConsecBytes,spFlags(A0) ; calculating bytes or id's ?
BEQ.S @Ids ; do id's
; Do table lookup to get step register value for consecutive bytes
; reg D3 = byte lanes for slot * 4, D1 = byte lane spsPointer is occupying (used to rotate step value)
LEA ByteTable,A1 ; reg A1 = ptr to byte access table
MOVE.L 0(A1,D3.W),D2 ; reg D2 = step value
MULU.W #8,D1 ; calc which step value current byte lane is on
ROR.L D1,D2 ; D2 = step value corrected to current byte lane
MOVE.L D2,spResult(A0)
BRA.S @Done
; Do table lookup to get step register value for consecutive id's
; reg D2 = byte lanes for slot, D1 = byte lane spsPointer is occupying
@Ids LEA IdTable,A1 ; reg A1 = addr of id access table
MOVE.L 0(A1,D3.W),spResult(A0) ; return step value - no rotation needed
BPL.S @Done ; if negative, then calc for 3 byte lanes
; Card supports three byte lanes. Must index into an auxilary table. There are 4 valid
; and 1 invalid entry in the table (total of 5). Each entry has the step value for the
; slot's byte lane configuration, a different step value depending on which byte lane
; the spsPointer occupies.
LEA ThreeByteTbl,A1 ; get addr of auxilary table for 3 byte lanes
AND.B #7,D2 ; use low 3 bits for indexing into table
SUB.B #3,D2 ; adjust index for table
ASL.L #4,D2 ; multiply by 16 bytes (size of each entry)
ADDA.L D1,A1 ; add in current byte lane offset
MOVE.L 0(A1,D2.W),spResult(A0) ; get step value for 3 byte lane support
@Done CLR.W D0 ; set good result
@Error MOVEM.L (SP)+,D1-D3/A1
RTS
;_______________________________________________________________________________________
; Byte lane translation tables
;
; ByteTable, corresponds to consecutive bytes. IdTable, corresponds to consecutive
; id fields. ThreeByteTbl, corresponds to consecutive id fields on cards which support
; three byte lanes. Each entry is 4 longs. These byte lanes have their entries as -1
; in IdTable.
;
; step values byte lanes
; ----------- ----------
ByteTable DC.L $0 ; no byte lane indexed at 0
DC.L $04040404 ; 0
DC.L $04040404 ; 1
DC.L $03010301 ; 0,1
DC.L $04040404 ; 2
DC.L $02020202 ; 0,2
DC.L $03010301 ; 1,2
DC.L $00020101 ; 0,1,2
DC.L $04040404 ; 3
DC.L $01030103 ; 0,3
DC.L $02020202 ; 1,3
DC.L $00010201 ; 0,1,3
DC.L $03010301 ; 2,3
DC.L $00010102 ; 0,2,3
DC.L $00020101 ; 1,2,3
DC.L $01010101 ; 0,1,2,3
IdTable DC.L $0 ; no byte lane indexed at 0
DC.L $10101010 ; 0
DC.L $10101010 ; 1
DC.L $08080808 ; 0,1
DC.L $10101010 ; 2
DC.L $08080808 ; 0,2
DC.L $08080808 ; 1,2
DC.L $FFFFFFFF ; 0,1,2
DC.L $10101010 ; 3
DC.L $08080808 ; 0,3
DC.L $08080808 ; 1,3
DC.L $FFFFFFFF ; 0,1,3
DC.L $08080808 ; 2,3
DC.L $FFFFFFFF ; 0,2,3
DC.L $FFFFFFFF ; 1,2,3
DC.L $04040404 ; 0,1,2,3
ThreeByteTbl
DC.L $05050505 ; 0,1,3
DC.L $06060606 ;
DC.L $0 ;
DC.L $05050505 ;
DC.L $0 ; empty
DC.L $0 ;
DC.L $0 ;
DC.L $0 ;
DC.L $06060606 ; 0,2,3
DC.L $0 ;
DC.L $05050505 ;
DC.L $05050505 ;
DC.L $0 ; 1,2,3
DC.L $05050505 ;
DC.L $05050505 ;
DC.L $06060606 ;
DC.L $05050505 ; 0,1,2
DC.L $05050505 ;
DC.L $06060606 ;
DC.L $0 ;
;_______________________________________________________________________________________
; OffsetData - read an offset/data field
;
; Read the offset/data field identified by spId, in the list pointed to by spsPointer.
; The offset/data field is the 3 byte field following the id in a list entry :
; <id><offset/data>. This routine may be used for general data access of a list.
;
; Input : reg A0 = ptr to spBlock
;
; Output : reg D0 = status, 0=ok CCR reflects status
;
; spBlock : <-> spsPointer On entry is ptr to list to search, on exit is ptr
; to id in list. This can be used to calculate a new
; pointer offset by the value of the offset/data field.
; -> spId Id in list to search for
; <- spOffsetData the value of the offset data field
; <- spByteLanes byte lane for slot
;
OffsetData PROC EXPORT
WITH spBlock,sInfoRecord
MOVEM.L D1-D2/A1,-(SP)
MOVE.B spSlot(A0),-(SP) ; save slot field (if any)
MOVE.W #smBadRefId,D0 ; asume an error
CMPI.B #$FF,spId(A0) ; is id less than $FF ?
beq @Done ; no - id out of range
; Get the sInfo record for the slot. Derive the slot number from the spsPointer.
; If the spsPointer is to a RAM list, then slot number gets translated to slot 0.
_sPtrToSlot ; convert to slot number
bne @Done
_sFindsInfoRecPtr ; get ptr to sInfo record and status <1.6>
MOVE.L spResult(A0),A1 ; reg A1 = ptr to sInfo record
move.w siInitStatusA(a1),d0 ; test slot
bmi.s @Done ; bad slot - skip it
; Calculate the step value to consecutive bytes
MOVE.B siCPUByteLanes(A1),spByteLanes(A0) ; get byte lane field from sInfo rec
BSET.B #fConsecBytes,spFlags(A0) ; set flag for consecutive bytes
_sCalcStep ; calc step value for spsPointer
bne.s @Done
; Loop and read the <id><offset/data> fields (a long) from the list.
MOVE.L spResult(A0),spParamData(A0) ; step value in spParamData
MOVEQ #0,D1 ; clear for last id read
@Loop MOVE.B D1,D2 ; save D2 = last id read
MOVE.L spsPointer(A0),A1 ; save reg A1 = ptr to current id
slotjsr Read4Bytes ; read <id><offset/data>
bne.s @Done ; some error
MOVE.B spResult(A0),D1 ; reg D1 = <id>
MOVE.W #smBadsList,D0 ; assume out of order error
CMP.B D2,D1 ; check for ascending order
bcs.s @Done ; out of order
MOVE.W #smBadRefId,D0 ; assume not found
CMP.B #$FF,D1 ; end of list ?
beq.s @Done ; id not found
CMP.B spId(A0),D1 ; found id ?
BNE.S @Loop ; not found - continue
; Found id - return offset/data value
MOVE.L spResult(A0),D0 ; get <id><offset/data>
AND.L #$00FFFFFF,D0 ; mask off id
MOVE.L D0,spOffsetData(A0) ; set return offset/data field
MOVE.L A1,spsPointer(A0) ; set ptr to id in list
moveq #noErr,d0 ; set a good return
@Done MOVE.B (SP)+,spSlot(A0) ; restore save slot number
MOVEM.L (SP)+,D1-D2/A1
TST.W D0
RTS
;_______________________________________________________________________________________ <2.0>
; ReadPBSize - read the physical block size field of an sBlock
;
; Search a list pointed to by spsPointer for the id spId. Use the offset/data field
; of the id to calculate a pointer to an sBlock. Return the physical block size of
; the sBlock. Also return the pointer to the sBlock after the size field. Optionally
; return a long instead of the physical block size (PBSize is masked to 3 bytes).
;
; Input : reg A0 = ptr to spBlock
;
; Output : reg D0 = status, 0=ok CCR reflects status
;
; spBlock : <-> spsPointer On entry is ptr to list to search, on exit is ptr
; to sBlock.
; -> spId Id in list to search for
; -> spFlags bit 1 set means check high byte of size for zero
; <- spSize physical block size field of sBlock
; <- spByteLanes byte lane for slot
;
; Called : trap dispatcher, jsr
;
ReadPBSize Proc Export
With spBlock,sInfoRecord
movem.l d1/a1,-(sp)
move.b spSlot(a0),-(sp) ; save slot field (if any)
; Search the list pointed to by spsPointer for the spId. Use the offset/data
; field to calculate a pointer to the sBlock.
_sFindStruct ; return new spsPointer
bne.s @Done
; Read the PBSize field pointed to by spsPointer. Increment spsPointer to after the
; size field.
_sPtrToSlot ; get slot number
bne.s @Done
_sFindsInfoRecPtr ; get ptr to sInfo record and status <1.6>
movea.l spResult(a0),a1 ; reg a1 = ptr to sInfo record
move.w siInitStatusA(a1),d0 ; test slot
bmi.s @Done ; bad slot - skip it
; Calculate the step value to consecutive bytes
move.b siCPUByteLanes(a1),spByteLanes(a0) ; get byte lane field from sInfo rec
bset.b #fConsecBytes,spFlags(a0) ; set flag for consecutive bytes
_sCalcStep ; calc step value for spsPointer
bne.s @Done
move.l spResult(a0),spParamData(a0) ; step value in spParamData
slotjsr Read4Bytes ; read PBSize field
bne.s @Done
; Optionally check the PBSize field to make sure that the high byte (a reserved field),
; is zero.
move.l spResult(a0),spSize(a0) ; move pbsize to size field
moveq #noErr,d0 ; assume a good return
btst.b #fCkReserved,spFlags(a0) ; check reserved field ?
beq.s @Done ; no - we are done
move.b spResult(a0),d1 ; d1 = high byte of PBSize field
beq.s @Done ; it's ok
move.w #smReservedErr,d0 ; not zero - log an error
@Done
move.b (sp)+,spSlot(a0) ; restore save slot number
movem.l (sp)+,d1/a1
tst.w d0
rts
;_______________________________________________________________________________________ <2.0>
; pRead4Bytes - read 4 bytes from NuBus
;
; Utility routine to read 4 bytes from NuBus. This differs from ReadLong(), in that
; it doesn't do a lot of the endless slot manager checking.
;
; Input : reg A0 = ptr to spBlock
;
; Output : reg D0 = status, 0=ok CCR reflects status
;
; spBlock : <-> spPointer address of 4 bytes to read - on exit, ptr to next long
; -> spParamData consecutive byte step value
; -> spSlot slot number
; <- spResult 4 bytes read
;
pRead4Bytes PROC EXPORT
WITH spBlock,sInfoRecord
movem.l d1-d4/a1-a2,-(sp)
; Setup for accessing NuBus
MOVE.L spParamData(A0),D2 ; get step value
MOVEA.L spsPointer(A0),A1 ; reg A1 = ptr to read bytes from
MOVEQ #3,D3 ; D3 = loop cntr
MOVEQ #0,D4 ; clear for temp reg for macro
slotjsr InstallBus ; switch to 32bit mode and new bus exception
lea @Done,a2 ; set addr to jump to if bus error
move.w #smUnExBusErr,d0 ; assume unexpected bus error
@Loop
asl.l #8,d1 ; shift previously read value
move.b (a1),d1 ; NUBUS READ - read byte
sNextStep d2,d4,a1 ; macro to inc ptr to next byte
dbra d3,@Loop ; continue
move.l d1,spResult(a0) ; set result to 4 bytes read
MOVE.L A1,spsPointer(A0) ; update incremented ptr
MOVEQ #noErr,D0 ; done - set good return
@Done
slotjsr RestoreBus ; restore mmu mode and bus exception
movem.l (sp)+,d1-d4/a1-a2
RTS
;_______________________________________________________________________________________ <4>
; GetBoard - get ptr to board sResource
;
; Given a slot number - return a pointer to the board sResource and sInfo record
;
; Input : reg A0 = ptr to spBlock
;
; Output : reg D0 = status, 0=ok CCR reflects status
; A0 = ptr to spBlock
;
; spBlock : -> spSlot slot number
; -> spId sRsrc id to search from <8>
; <- spsPointer ptr to board sResource
; <- spResult ptr to sInfo record
;
Export pGetBoard
pGetBoard
move.l a1,-(sp)
_sFindsInfoRecPtr ; get the sInfo record ptr
movea.l spResult(a0),a1 ; save a1 = ptr to sInfo record
; Get the board sResource
move.l #((CatBoard<<16)++TypBoard),spCategory(a0) ; set category and type fields
clr.l spDrvrSW(a0) ; no drvrSW and drvrHW fields
clr.b spTBMask(a0) ; no <cat><typ><SW><HW> masking
clr.b spExtDev(a0) ; clear external device id field (not a device)
clr.l spParamData(a0) ; clear flag field
IF NOT forROM THEN ; <SM2> rb
bset.b #fall,spParamData+3(a0) ; search all sResources
bset.b #foneslot,spParamData+3(a0) ; search in only one slot
ELSE ; <SM2> rb
ori.b #(1<<fall)+(1<<foneslot),spParamData+3(a0) ; <SM2> rb search all sRsrc's in one slot <4>
ENDIF ; <SM2> rb
_GetTypesRsrc ; return ptr to sResource
beq.s @Done
move.w #smNoBoardsRsrc,d0 ; no board sResource
@Done move.l a1,spResult(a0) ; restore spResult to sInfo ptr
movea.l (sp)+,a1
tst.w d0
rts
;_______________________________________________________________________________________
; pBusException - nubus bus error exception handler
;
; This is the slot manager's replacement bus error exception handler. It is designed
; to detect faulted Nubus address data read bus cycles. It is NOT designed to handle
; data write or read-modify-write cycles, or instruction fetch faults. These exceptions
; are transfered to the old bus exception handler.
;
; Upon an exception, the stack frame type is verified for as being one this routine is
; able to handle (in this case, a long bus cycle stack frame only). The SSW is check
; for a data read cycle fault ONLY. If the fault address is a NuBus address (32 bit
; address), then the exception stack frame is pop-ed and the exception return address
; in reg a2 is jumped to.
;
; Input : reg a2 address to return from exception when a bus error occurs
; Output : ccr set to value in reg d0
;
pBusException Proc Export
Export pInstallBus,pRestoreBus
stackframe RECORD 0
savereg DS.L 1 ; saved register on stack
statusreg DS.W 1
programCnt DS.L 1
type DS.B 1 ; format frame type
fill DS.B 3 ; filler
ssw DS.W 1 ; special status register
fill2 DS.L 1 ; filler
DFAddr DS.L 1 ; data cycle fault address
remainder DS.B 72-8 ; remainder of stack frame minus the short frame
shortSR ds.w 1 ; beginning of short stack frame definition
shortPC ds.l 1 ; new pc for short frame
shortvers ds.w 1 ; version and vector offset
ENDR
WITH stackframe,slotGlobals
; Verify that this is a faulted NuBus read data cycle
move.l d0,-(sp) ; save working register
move.w ssw(sp),d0 ; get special status register
and.w #$F1C0,d0 ; mask FC FB RC RB DF RM RW
cmp.w #$0140,d0 ; DF and RW bit set only ?
bne.s @RealBusEx ; can't handle this case - pass it on
move.b type(sp),d0 ; get format of stack frame for long frame
lsr.b #4,d0 ; look at high nibble
cmp.b #$0B,d0 ; long bus exception frame ?
bne.s @RealBusEx ; transfer to real bus exception handler
; Have verified that a NuBus read data access caused the bus error. Need to modify the
; stack frame to return to the address in register a2. Accomplish this by creating a new
; short stack frame and setting a new PC. The long bus exception PC is popped off leaving
; a short exception frame. Cannot just modify the PC in the long frame to return to a new
; address (this doesn't work).
move.l (sp),d0 ; restore reg d0
move.l a2,shortPC(sp) ; set new return address in short frame
move.w statusreg(sp),shortSR(sp) ; move the SR
clr.w shortvers(sp) ; clear frame type and vector offset
adda.w #shortSR,sp ; pop long frame leaving a short frame
rte
; The bus exception was not caused by a read to NuBus - pass the exception to the
; real bus exception handler.
@RealBusEx move.l (sp)+,d0 ; restore reg D0
jmp ([sInfoPtr],sysBusExcptn) ; jump to bus exception vector
;_______________________________________________________________________________________ <7>
; pInstallBus - install the slot manager's bus exception vector
;
; Switch to 32 bit mode and replace the system bus exception handler with the slot
; manager's exception handler. Return the saved mmu state in reg D0. Installing
; the slot manager's vector is based on a use count in the slot mgr globals. If the
; count is zero, then save the system vector and install the new vector. If the count
; is not zero, then assume some embedded slot mgr routine has already replaced the
; vector. In that case, just increment the count. This routine may be called at
; interrupt level.
;
; Input : none
; Output : none
;
; Destroys: d0
;
pInstallBus
move.w sr,-(sp) ; Save current interrupt level.
ori.w #HiIntMask,sr ; disable interrupts
move.l BusErrVct,([sInfoPtr],sysBusExcptn) ; save system bus vector in globals
move.l ([SDMJmpTblPtr],BusException*4),BusErrVct ; replace with slot mgr vector
move.w (SP)+,SR ; restore interrupt state
rts
;_______________________________________________________________________________________ <7>
; pRestoreBus - restore the system bus exception vector
;
; Restore the mmu state and the system's bus exception vector. If the bus exception
; use count is incremented to zero, then there is no slot mgr routine still using
; the exception vector, so restore the system's vector (saved in the slot mgr globals).
; If the count is non-zero, then do nothing. This routine may be called at interrupt
; level.
;
; Input : none
; Output : none
;
; Preserves all registers
;
pRestoreBus
move.l d0,-(sp) ; save reg
move.w sr,-(sp) ; Save current interrupt level.
ori.w #HiIntMask,sr ; disable interrupts
move.l ([sInfoPtr],sysBusExcptn),BusErrVct ; restore system exception vector
move.w (sp)+,sr ; restore interrupt state
move.l (sp)+,d0 ; restore reg
rts
ENDWITH ; { stackframe,slotGlobals } <5>
;____________________________________________________________________________
;
; Routine: p040BusException
;
; Inputs: a2 - address to return to from exception when a bus error occurs
;
; Outputs: ccr set to value in reg d0
;
; Function: nubus bus error exception handler for 68040-based machines
;
;____________________________________________________________________________
Export p040BusException
p040BusException ;
; The 040 Special Status Word (SSW) is different than the 020/030 one. It looks like
;
; +---------------------------------------------------------------------+
; | CP | CU | CT | CM | MA | ATC | LK | RW | X | SIZE | TT | TM |
; +---------------------------------------------------------------------+
; 15 14 13 12 11 10 9 8 7 6 5 4 3 2 0
;
;
; CP = Continuation - Floating Pt. Post Exception Pending
; CU = Continuation - Unimplemented Floating Pt. Instruction Exception
; CT = Continuation - Trace Exception Pending
; CM = Continuation - MOVEM Instruction Execution Pending
; MA = Misaligned Access
; ATC = ATC Fault
; LK = Locked Transfer
; RW = Read/Write (1=Read)
; X = Undefined
; SIZE = Transfer Size
; TT = Transfer Type
; TM = Transfer Modifier
aeStackFrame RECORD 0 ; 040 Access Stack Frame
savereg DS.L 1 ; space to save working register (D0)
aeSR DS.W 1 ; status register
aePC DS.L 1 ; program counter
aeType DS.B 1 ; type of exception stack frame
less DS.B 1 ; filling (vector offset)
aeEffAddr DS.L 1 ; effective address
aeSSW DS.W 1 ; special status word
aeWBnS DS.W 3 ; WriteBack #n Status
aeFA DS.L 1 ; fault address
aeWB3Addr DS.L 1 ; WriteBack 3 Address
aeWB3Data DS.L 1 ; WriteBack 3 Data
aeWB2Addr DS.L 1 ; WriteBack 2 Address
aeWB2Data DS.L 1 ; WriteBack 2 Data
aeWB1Addr DS.L 1 ; WriteBack 1 Address
aeWB1Data DS.L 1 ; WriteBack 1 Data/Push Data LW0
aePD1 DS.L 1 ; Push Data LW 1
aePD2 DS.L 1 ; Push Data LW 2
aePD3 DS.L 1 ; Push Data LW 3
ENDR
aeXFrameSize EQU $3C ; size of an Access Error stack frame
aeXFrameType EQU $07 ; access error exception frame type
WITH aeStackFrame,slotGlobals ;
; Verify that this is a faulted NuBus read data cycle
move.l d0,-(SP) ; save working register
move.w aeSSW(SP),d0 ; retrieve SSW
andi.w #$0518,d0 ; mask off only ATC, RW, TT
cmp.w #$0100,d0 ; should be ATC=0, RW=1, TT=0
bne.s @RealBusEx ; can't handle these case - pass it on
move.b aeType(SP),d0 ; get format of stack frame
lsr.b #4,d0 ; look at high nibble
cmp.b #aeXFrameType,d0 ; access error exception frame?
bne.s @RealBusEx ; NO ... use sys. access error handler
move.b aeFA(SP),d0 ; get high byte of fault address
cmp.b #majorSpace,d0 ; in super slot space ($60-$E0)?
blo.s @RealBusEx ; not in slot address space
cmp.b #$FF,d0 ; in minor slot space range?
beq.s @RealBusEx ; not in minor slot space
cmp.b #$F0,d0 ; in minor slot space range?
beq.s @RealBusEx ; not in minor space $F1 - $FE
; Have verified that a NuBus read data access caused the bus error. Pop the exception
; stack frame and jump to the error return address in register a2.
;
; *** I don't think this will work correctly. Given that you could have other exceptions
; *** of a lesser priority pending, and could possibly have pending writebacks as well,
; *** does this code need to look to complete those writebacks, stuff A2 into aePC(SP)
; *** and do an RTE? Or can we legally/safely stuff A2 into aePC(SP)?
; move.l (sp)+,d0 ; restore reg d0
; adda.w #aeXFrameSize,sp ; pop the exception stack frame
; jmp (a2) ; take the error return address
move.l a2,aePC(SP) ; (re-)set the PC to where we want to go
move.l (sp)+,d0 ; restore reg d0
rte ; return, catching any pending exceptions
; The bus exception was not caused by a read to NuBus - pass the exception to the
; real bus exception handler.
@RealBusEx MOVE.L (SP)+,D0 ; restore reg D0
MOVE.L ([sInfoPtr],sysBusExcptn),-(SP) ; put saved bus exception vector on stack
RTS ; jump to bus exception vector
ENDWITH ; { aeStackFrame,slotGlobals }
;_______________________________________________________________________________________ <h7> djw
; AddCard - add a card to the slot manager data structures
;
; There is a stub entrypoint for this routine in the file slotInfo.a which does a long
; branch here. The stub routine is needed for the slot manager's jump table offset
; limitation.
;
; Add a card to the slot manager's data structures and run it's primaryInit. If the
; card's current status is not empty, then the slot is rejected as not valid. Memory
; is allocated, so this routine should not be run at interrupt time.
;
; Input : a0 = ptr to spBlock
; Output : none
;
; spBlock : -> spSlot slot number (slot 0 is not valid)
;
Export AddCard
with spBlock,sInfoRecord,seBlock
AddCard
@regs reg d1/a0/a2
movem.l @regs,-(sp)
; If the current slot status is not empty, then the slot may not be re-initialized
_sFindsInfoRecPtr ; get ptr to sInfoRecord
bne @Done ; slot not valid - done
movea.l spResult(a0),a2 ; a2 = ptr to sInfoRecord
move.w #smSlotOOBErr,d0 ; assume bad slot
cmp.w #smEmptySlot, \ ; check for empty slot
siInitStatusA(a2)
bne.s @Done ; only empty slots are valid
; Execute the slot manager initialization again on this slot
slotjsr initSDeclMgr ; initialize a slot's sInfoRecord
slotjsr sInitSRsrcTable ; initialize the slot resource table (SRT)
slotjsr sInitPRAMRecs ; initialize a slot's PRAM
clr.b spFlags(a0) ; clear flag bit to assume cold start
cmp.l #WmStConst,WarmStart ; check low mem for warm start value
bne.s @continue ; cold start
bset.b #fWarmStart,spFlags(a0) ; warm start
@continue
move.w sr,-(sp)
ori.w #HiIntMask,sr ; disable ints for primary init
slotjsr sPrimaryInit ; execute the primaryInit
move.w (sp)+,sr ; restore ints
; Execute the secondaryInit record <h12> thru next <h12>
lea -seBlockSize(sp),sp ; alloc seBlock
movea.l sp,a2 ; a2 = ptr to seBlock
move.l a2,spsExecPBlk(a0) ; set ptr in spblock to sExec blk
move.b #BoardId,sesRsrcId(a2) ; indicates exec code is from board sResource
slotjsr sDoSecondary ; jump thru the vector
lea seBlockSize(sp),sp ; dealloc seBlock <h12> from last <h12>
@Done
movem.l (sp)+,@regs
rts
endwith
;_______________________________________________________________________________________ <h7> djw
; RemoveCard - Remove a card from the slot manager
;
; This routine will remove a card from the system by:
;
; 1. Delete all sRsrc's from the SRT for that slot
; 2. Delete sInfoRecord and set to empty status
; 3. If there is a driver attached to the slot, attempt to close the driver
; 4. Remove any slot interrupt queue elements for the slot
;
; Input : a0 = ptr to spBlock
; Output : none
;
; spBlock : -> spSlot slot number (slot 0 is not valid)
;
Export RemoveCard
with spBlock,SlotIntQElement,slotIntGlobals,srrBlock,sInfoRecord
RemoveCard
@regs reg d1-d3/a1-a2
movem.l @regs,-(sp)
lea -ioQElSize(sp),sp ; alloc iopb
movea.l sp,a2 ; <H14><SM13>
clr.l ioCompletion(a2) ; no completion routine
moveq.l #0,d1
move.b spSlot(a0),d1 ; d1 = slot number
; Loop through SRT deleting all sResources for this slot.
@LoopAgain
movea.l sRsrcTblPtr,a1 ; get ptr to beginning of SRT
suba.w #SRTRecSize,a1 ; pre-decrement pointer
@Loop
adda.w #SRTRecSize,a1 ; inc to next srrBlock
clr.l spParamData(a0) ; ignore input flags becauseÉ
bset.b #fall,spParamData+3(a0) ; Éwe need to find both enabled and disabled sRsrc's
slotjsr sGetSRTEntry ; get next entry - rtn in ptr in a1
bne.s @noMore ; found all sRsrc's
slotjsr SrToSpBlock ; fill spBlock with srrBlock info
cmp.b spSlot(a0),d1 ; is this the slot we are looking at?
bne.s @Loop ; not right slot - continue looking
; If there is a driver associated with this slot, attempt to close it
tst.w spRefNum(a0) ; is there a valid refnum?
bpl.s @remove ; not a refnum
move.w spRefnum(a0),ioRefnum(a2) ; set refnum to close
move.l a0,-(sp) ; save ptr to spBlock
movea.l a2,a0 ; a0 = ptr to iopb
_Close ; close driver
movea.l (sp)+,a0 ; restore a0 = ptr to spBlock
; Delete the sRsrc from SRT
@remove
slotjsr sDeleteSRTRec ; delete the found sRsrc
bra.s @LoopAgain ; find and delete all sRsrc's
; Delete the sInfoRecord
@noMore
lea ([sInfoPtr],(4*TotalSlots) \
+(sInfoNewSize*2)),a1 ; get ptr to empty sInfo record
move.l a1,([sInfoPtr],d1.w*4) ; set slot to point to empty record
; Clear the slot interrupt queue for this slot
; **** WARNING **** WARNING ****
; This code is very implementation specific. If slot interrupt table structure
; changes, this code will not work. Also, this routine leaks memory because
; it does not free the slot int queue elements
lea ([SlotQDT],d1.w*4,slotIntQHeads-SQLink),a1 ; get address of queue header
clr.l SQLink(a1) ; zero queue link
; Done
@Done
lea ioQElSize(sp),sp ; de-alloc iopb
movem.l (sp)+,@regs
rts
endwith
;_______________________________________________________________________________________ <h7> djw
; CheckSlot - check if a card has changed
;
; Check whether a slot's status has changed. There are 3 slot state changes to
; consider:
;
; 1. empty --> occupied
; 2. occupied --> empty
; 3. occupied --> occupied
;
; If a slot goes from empty to occupied, or occupied to empty, return status that
; the slot's state has changed. If a slot was previously occupied and is still
; occupied, then read the board id from the card and match it to the board id in
; PRAM. If they are not the same, then the previous card was removed, and a new
; card is now in it's place.
;
; Input : a0 = ptr to spBlock
;
; Output : d0 = 0 if no change, non-zero if change
;
; spBlock : -> spSlot slot number (slot 0 is not valid)
;
Export CheckSlot
Import VerifySlot
with spBlock,sInfoRecord
CheckSlot
@regs reg d1-d4/a1-a4
movem.l @regs,-(sp)
moveq.l #0,d3 ; set d3 = change status flag
moveq.l #0,d4
; get ptr to slot's sInfoRecord so we can check its previous state
_sFindsInfoRecPtr ; get ptr to sInfoRecord
bne @Return ; slot not valid - no change
movea.l spResult(a0),a4 ; a4 = ptr to sInfoRecord
; If a slot is disabled or reserved, then it is invalid
cmp.w #smDisabledSlot, \ ; check for disabled slot
siInitStatusA(a4)
beq @Return ; disabled slots not valid
cmp.w #smReservedSlot, \ ; check for reserved slot
siInitStatusA(a4)
beq @Return ; reserved slots not valid
cmp.w #smEmptySlot, \ ; check for empty slot
siInitStatusA(a4)
bne.s @notbad ; empty slots not valid
moveq.l #-1,d4
@notbad
moveq.l #0,d1 ; zero reg
move.b spSlot(a0),d1 ; d1 = slot number
; Save the current sInfoRecord for the slot
lea -sInfoNewSize(sp),sp ; alloc temp sInfoRecord
move.w d3,siInitStatusA(sp) ; clear status field
move.b d3,siState(sp) ; clear state variable
move.w siTOConst(a4),siTOConst(sp) ; set bus error retry cnt (not used)
move.b d1,siSlot(sp) ; set slot number
move.l d3,siROMAddr(sp) ; clear ROM address
movea.l sp,a1 ; a1 = ptr to temp sInfoRecord
move.l a1,([sInfoPtr],d1.w*4) ; set new temp sInfoRecord ptr for slot
; Determine whether the slot is empty or occupied
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
move.l a3,siROMAddr(sp) ; set ROM address
bra.s @Verify ; slot is occupied - verify the decl rom
; If the slot is still empty and was previously empty, then we are done
@Empty
slotjsr RestoreBus ; get here if empty slot
move.w #smEmptySlot,siInitStatusA(a1) ; set empty status
bra.s @CheckError ; check if same as previous status
; Verify the format header - a0 = ptr to spblock, a1 = ptr to sInfoRecord
@Verify
bsr VerifySlot ; verify the config rom format
tst.w siInitStatusA(a1) ; is the slot status ok?
bne.s @CheckError ; bad or empty slot - check previous status
; Config ROM verifies ok - walk through all the sResources looking for the board sResource
tst.l d4
bne.s @Changed
bsr GetBoardID ; find the board sRsrc and board id
beq.s @Changed ; no board id - a bad card
; Compare with pram board id. If sRsrc board id is different, then there is
; a different card in the slot.
move.w d0,d2 ; d2 = board id for new card
lea -8(sp),sp ; alloc pram buffer
move.l sp,spResult(a0) ; pass ptr to pram buffer
slotjsr sReadPRAMRec ; read the current slot pram
bne.s @Changed ; something wrong - change the card
cmp.w (sp),d2 ; are board id's the same?
lea 8(sp),sp ; de-alloc buffer
beq.s @Done ; same board id's - return no change
bra.s @Changed
; Some error - if same as previously, then mark as unchanged
@CheckError
move.w siInitStatusA(a4),d0 ; get previous status
cmp.w siInitStatusA(a1),d0 ; same error?
beq.s @Done ; same board id's - no change
; The card has changed
@Changed
moveq.l #-1,d3 ; return error to indicate card changed
; Done
@Done
lea sInfoNewSize(sp),sp ; free temp sInfoRecord
move.l a4,([sInfoPtr],d1.w*4) ; restore original sInfoRecord
@Return
move.l d3,d0 ; return change status
movem.l (sp)+,@regs
rts
;_______________________________________________________________________________________ <h7> djw
; GetBoardID - Find and return board id
;
; Find the board sResource and return the board id for the given slot. This
; routine walks through the sResource data structures on the card, not using
; the SRT.
;
; Input : a0 = ptr to spBlock
; a1 = ptr to sInfoRecord
; Output : d0 = board id or zero ccr reflects status
;
; spBlock : -> spSlot slot number (slot 0 is not valid)
;
GetBoardID
@regs reg d1-d4/a1-a2
movem.l @regs,-(sp)
moveq.l #0,d4 ; d4 = board id value to return
; Calculate the step value for this slot so we can step through the sRsrc dir
move.l siDirPtr(a1),spsPointer(a0) ; set ptr field to get step value for
move.b siCPUByteLanes(a1),spByteLanes(a0) ; set byte lanes field
bset.b #fConsecBytes,spFlags(a0) ; set flag for step value for bytes
_sCalcStep
bne @Done
; For every entry in the sResource directory, read the sResource type to find the
; board sResource. Also check for ascending order for the sResources in case there
; is no $ff at the end.
move.l spResult(a0),spParamData(a0) ; set step value for reading bytes
move.l siDirPtr(a1),d2 ; set d2 = ptr to current dir entry
moveq.l #0,d1 ; zero last id read
@Loop move.l d2,spsPointer(a0) ; set spsPointer to addr of id to read in dir
slotjsr Read4Bytes ; read <id><offset> - inc spsPointer to next long
bne.s @Done ; an error - stop searching
move.l spsPointer(a0),d2 ; get d2 = ptr to next id to read
; Check for acsending order in sResource directory id's
move.b spResult(a0),d3 ; get high byte to get <id> field
cmp.b #$ff,d3 ; end of list ?
beq.s @Done ; done - board sResource is not found
cmp.b d1,d3 ; is new id greater than last id ?
bls.s @Done ; id's out of order - not found
move.b d3,d1 ; set reg d1 = last id read
; Get a pointer to the sResource id found
move.l siDirPtr(a1),spsPointer(a0) ; point to directory
move.b d1,spId(a0) ; find the sRsrc id just read from the dir
_sFindStruct
bne.s @Done ; some error
; With the spsPointer field now pointing to the sRsrc, read the type field
movea.l spsPointer(a0),a2 ; save ptr to sRsrc
move.b #sRsrcType,spId(a0) ; get ptr to type field
_sFindStruct
bne.s @Done ; error - no sRsrc type field found
lea -8(sp),sp ; alloc sRsrc_type buffer
move.l sp,spResult(a0) ; set buffer ptr
move.l #8,spSize(a0) ; set size to read
_sReadStruct
bne.s @Done ; @@@@Remember to dealloc stack@@@@can't read it - error
move.l (sp)+,d0 ; get category and type fields
move.l (sp)+,d3 ; get drvrSW and drvrHW fields
cmp.l #(catBoard<<16)+typBoard,d0 ; board type?
bne.s @Loop ; not found - continue search
tst.l d3 ; drvrSW and drvrHW fields should be zero
bne.s @Loop ; not found - continue search
; At this point, we have found the board sResource. Read the board id
move.l a2,spsPointer(a0) ; restore ptr to sRsrc
move.b #Boardid,spId(a0) ; read board id field from board sRsrc
_sReadWord
bne.s @Done ; some error - no board id
move.w spResult+2(a0),d4 ; d4 = board id for new card
; Done
@Done
move.w d4,d0 ; return board id or zero
movem.l (sp)+,@regs
rts
endwith
;____________________________________________________________________________ <H8>
;
; FindDevBaseSlot0 (called from FindDevBase).
;
; Entry: a0 points to spBlock.
; d1 is the major/minorbase offset.
;
; Exit: a0 points to spBlock.
; d2 is the DevBase.
;
; Trashes: A1/D0-D1.
;____________________________________________________________________________
Export FindDevBaseSlot0
With SpBlock
FindDevBaseSlot0
movea.l UnivInfoPtr,a1 ; point to the ProductInfo record
adda.l ProductInfo.VideoInfoPtr(a1),a1 ; point to the VideoInfo record
move.b #sRsrcFlags,spId(a0) ; get flags to determine whether the pointer
_sReadWord ; - should be 24 or 32 bit
bne.s @Do24 ; no flag field - default to 24 bit space
move.w spResult+2(a0),d0 ; get value of spFlags
btst.l #f32BitMode,D0 ; see if 32- or 24-bit base address
beq.s @Do24 ; branch if 24-bit base address
Add.l VideoInfo.VRAMLogAddr32(a1),d1 ; 32bit dev base to alias addr for slot zero
Bra.s @Done
@Do24 Add.l VideoInfo.VRAMLogAddr24(a1),d1 ; 24bit dev base to alias addr for slot zero
@Done Move.l d1,d2 ; d2 has what we want
Rts
EndWith
Endp ; must have endp for RAM builds <djw>
End