mac-rom/OS/SlotMgr/SlotMgr.a
Elliot Nunn 0ba83392d4 Bring in CubeE sources
Resource forks are included only for .rsrc files. These are DeRezzed into their data fork. 'ckid' resources, from the Projector VCS, are not included.

The Tools directory, containing mostly junk, is also excluded.
2017-09-20 18:04:16 +08:00

4045 lines
148 KiB
Plaintext
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

;
; 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
_BlockMove
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
IF NOT LC930 THEN
Import GetDriverPatch
Bsr GetDriverPatch ; If GetDriverPatch returns a
Tst.b D0 ; result >= 0, donÕt execute
Bge.s ExitGetSlotDrvr ; Patched, so just return.
ENDIF
; 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
;____________________________________________________________________________
;
; GetDriverPatch and support (called from _SGetDriver).
;
; Entry/Exit: A0 points to spBlock.
;
; Purpose: The purpose of GetDriverPatch is to identify Apple
; Cards whose Driver code is faulty, and execute fixed
; versions from the CPU ROM. ItÕs job is to
; call GetDevIndex to determine whether the card/device
; pointed to by the incoming spBlock is one that needs
; patching. If so, it attempts to allocate enough space
; for the driver in the system heap, copy it there, and
; then return a handle to the driver in spBlock.spResult.
; If the driver canÕt be loaded (e.g., not enough memory),
; the appropriate Slot Manager error is returned.
;____________________________________________________________________________
GetDriverPatch Proc Export
With spBlock,LoadTblRec
@saveRegs Reg A0/A3-A5/D3-D4 ; Define registers for work/saving, and
Movem.l @saveRegs,-(Sp) ; store them on the stack.
Link A6,#-spBlockSize ; Get a stack frame.
Move.l A0,A3 ; Save spBlockPtr.
; First, look to see if we even need to be attempting to patch the driver on this
; card/device.
;
Bsr GetDevIndex ; Get the card/device index into D0.
Move.l D0,D3 ; If the device index is negative, then
Bmi @done ; driver doesnÕt need patching.<SM9> CSS
; Next, check to see that weÕre pointing to the sResource that has the driver or
; driver loader in it (i.e., we donÕt want to be opening the driver multiple
; times).
;
Lea LoadTbl,A1 ; Point to base of LoadTbl.
Mulu #LTEntrySize,D3 ; Adjust index.
Move.l A1,A0 ; Point to base of LoadTbl.
Move.b ltSpID(A0,D3),D0 ; Get spID.
Move.b ltSpExtDev(A0,D3),D1 ; Get spExtDev.
Moveq #0,D4 ; Clear value holder.
Move.b D0,D4 ; Save spID
Swap D4 ; and
Move.b D1,D4 ; Save spExtDev.
Move.l Sp,A0 ; Point to local spBlock.
Move.b spSlot(A3),spSlot(A0) ; Get pointer to right sResource list:
Move.b spID(A3),spID(A0) ; Need spSlot, spID, and
Move.b D4,spExtDev(A0) ; spExtDev.
_SRsrcInfo
Bne.s @errRtn
Swap D4 ; Get spID.
Move.b D4,spID(A0) ; Make sure this sResource is the one
_SFindStruct ; with the driver in it.
Bne.s @errRtn
; Finally, now that we know that we on the right card/device and are looking at the right
; sResource, allocate relocatable space in the System heap and tell the caller where that
; space is.
;
Move.l A1,A4 ; Point to base of LoadTbl.
Add.l ltAddrOff(A1,D3),A4 ; Add offset to driver and save pointer.
Move.l A1,A0 ; Point to base of LoadTbl.
Add.l ltSizeOff(A1,D3),A0 ; Add offset to driver size and get pointer.
Move.l (A0),D3 ; Save driver size.
Move.l D3,D0 ; Compact/Reserve some space for ourselves
_ResrvMem ,SYS ; in the System heap.
Bne.s @errRtn ; Get out if we couldnÕt reserve the space.
Move.l D3,D0 ; Attempt to allocate some space in the
_NewHandle ,SYS ; System heap.
Bne.s @errRtn ; Get out if we couldnÕt get the space.
Move.l A0,A5 ; Remember allocated handle, and prevent it
_HNoPurge ; from being removed.
Move.l A4,A0 ; Get address of driver code.
Move.l (A5),A1 ; Get address of allocated space.
Move.l D3,D0 ; Get size.
_BlockMove ; Move driver into allocated space.
Move.l A3,A0 ; Restore spBlockPtr.
Move.l A5,spResult(A0) ; Return driver handle in spResult.
Moveq #0,D0 ; Return noErr.
Bra.s @done
@errRtn Move.l #smsGetDrvrErr,D0 ; CouldnÕt load driver error.
@done Unlk A6 ; Restore stack frame.
Movem.l (Sp)+,@saveRegs ; Restore registers.
Rts
;____________________________________________________________________________
;
; GetDevIndex
;
; Entry: A0 -- points to spBlock.
;
; Exit: D0 -- contains index (0..n-1) or error value (<0).
;
; Purpose: The purpose of GetDevIndex is to cycle through a table of
; card/device identifiers. If the card/device passed in
; is in the device table, itÕs entry is returned. Otherwise,
; a negative number (-1) is returned. This is a utility routine
; called by SlotGetDriverPatch and SlotPrimaryInitPatch.
;
; Note: This routine JsrÕs (Bsr.lÕs) to GetSlotDrvr directly due to
; the fact that we might be coming from our patched out version
; of GetSlotDrvr! We need to do this so that we can compare
; the version of the driver on the card with the one we know
; about. This is so that we donÕt patch out newer (and
; presumably compatible) versions of the PrimaryInit and Driver.
;
;____________________________________________________________________________
Macro ; Macro for jumping directly int
_GetSlotDriver ; GetSlotDrvr (acting like trap dispatcher).
Movem.l A1/D1-D2,-(Sp) ; Save registers (A0 i/o, D0 is result).
Bsr.l OrigGetSlotDrvr ; Make call. <T8>
Tst.w D0 ; Act like Slot Manager for result.
Movem.l (Sp)+,A1/D1-D2 ; Restore registers.
EndMacro ;
With DevTblRec,spBlock,seBlock
Export GetDevIndex
GetDevIndex
@saveRegs Reg A3-A5/D3-D4 ; Define registers for work/saving, and
Movem.l @saveRegs,-(Sp) ; store them on the stack.
Link A6,#-spBlockSize ; Get a stack frame.
Move.l A0,A3 ; Save current spBlock to simulate sExec.
Move.l Sp,A0 ; Point to stack spBlock.
Lea DevTbl,A4 ; Point to table of device identifiers.
Moveq #0,D3 ; Set entry index to 0.
@repeat Move.b spSlot(A3),spSlot(A0) ; Reset spSlot to the one we want.
Clr.w spID(A0) ; Start search from top, no external devices. <11>
Clr.b spTBMask(A0) ; No mask (i.e., specific search).
Move.w category(A4),spCategory(A0) ; Look for: Category,
Move.w cType(A4),spCType(A0) ; CType,
Move.w drvrSW(A4),spDrvrSW(A0) ; DrvrSW,
Move.w drvrHW(A4),spDrvrHW(A0) ; DrvrHW.
Clr.l spParamData(A0) ; Look only for enabled sRsrcs. <11>
Bset #foneslot,spParamData+3(A0) ; Limit search to this slot only by
_GetTypeSRsrc ; using the new & improved routine.
Bne.s @until ; If this isnÕt the device were looking for,
; then keep going.
_GetSlotDriver ; Otherwise, attempt to load driver (for version #).
Bne.s @dontPatch ; If it couldnÕt be loaded, punt.
Move.l spResult(A0),A5 ; Save driver handle (to dispose).
Move.l (A5),A0 ; Get driver pointer.
Lea drvrName(A0),A0 ; Get driver name.
Clr.w D0 ; Clear D0.w (for use as index).
Move.b (A0),D0 ; Get the length of the driver name.
Addq #2,D0 ; Adjust offset to version field.
Bclr #0,D0 ; Adjust offset for word alignment.
Move.w (A0,D0.w),D4 ; Save the version number.
Move.l A5,A0 ; Get driver handle, and
_DisposHandle ; dispose of it.
Cmp.w drvrVers(A4),D4 ; If the cardÕs version ­ to ours, <11>
Bne.s @until ; then keep going. <11><H5>
Move.l D3,D0 ; Otherwise, copy the index into D0,
Bra.s @done ; and return.
@until Adda #DTEntrySize,A4 ; Point to next entry in table, and
Addq #1,D3 ; increment entry index.
Tst.w (A4) ; If this isnÕt the final entry, then
Bne.s @repeat ; keep checking.
@dontPatch Moveq #-1,D0 ; Flag that we donÕt want to patch.
@done Unlk A6 ; Put stack frame back.
Movem.l (Sp)+,@saveRegs ; Restore registers.
Rts
EndWith
;____________________________________________________________________________
;
; Tables for PrimaryInit & GetDriver patches.
;
; Note: Keep these here and donÕt export these labels!
;____________________________________________________________________________
Import TFBDrvr,TFBDrvrSize
Import JMFBDrvr,JMFBDrvrSize
Import TFBPrimaryInit
Import JMFBPrimaryInit
Export JsrTbl
DevTbl Dc.w CatDisplay,TypVideo,DrSwApple,DrHwTFB,0 ; TFB Entry <11>
Dc.w CatDisplay,TypVideo,DrSwApple,DrHwJMFB,0 ; JMFB Entry <11>
Dc.w 0
Align 4
LoadTbl Dc.l TFBDrvr-LoadTbl ; Start of TFB driver code.
Dc.l TFBDrvrSize-LoadTbl ; Length.
Dc.b sRsrcDrvrDir ; TFBÕs have an sRsrcDrvrDir.
Dc.b 0 ; TFBÕs are singly deviced.
Dc.b 0,0 ; Padding. <11>
Dc.l JMFBDrvr-LoadTbl ; Start of 4¥8/8¥24 driver code.
Dc.l JMFBDrvrSize-LoadTbl ; Length.
Dc.b sRsrcDrvrDir ; 4¥8/8¥24Õs have an sRsrcDrvrDir.
Dc.b 0 ; 4¥8/8¥24Õs are singly deviced.
Dc.b 0,0 ; Padding.
Align 4
JsrTbl Dc.l TFBPrimaryInit-JsrTbl ; TFBPrimaryInit
Dc.l JMFBPrimaryInit-JsrTbl ; 4¥8/8¥24 PrimaryInit
;=========================================================================================
; 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
; 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?
BHI.S @FoundSlot ; must be other super slot space
; Pointer is to ram or rom. Translate it to slot 0.
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 MOVE.B mmu32Bit,-(SP) ; save current mmu state <SM2> rb
MOVE.B #false32b,D0 ; <SM2> rb
_SwapMMUMode ; switch to 24 bit mode <SM2> rb
MOVEA.L A2,A0 ; A0 = ptr to last SRT blk
_DisposPtr ; free the block
MOVE.B (SP)+,D0 ; recover status <SM2> rb
_SwapMMUMode ; restore mmu state <SM2> rb
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
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
move.b DFAddr(sp),d0 ; get high byte of data fault cycle 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. 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
moveq #True32B,d0
_SwapMMUMode ; change to 32 bit mode
move.b d0,([sInfoPtr],entryMMUMode) ; save old mmu state
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.b ([sInfoPtr],entryMMUMode),d0 ; get saved mmu mode
_SwapMMUMode ; restore mmu mode
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-d3/a1-a4
movem.l @regs,-(sp)
moveq.l #0,d3 ; set d3 = change status flag
; 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
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.l 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
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