mirror of
https://github.com/elliotnunn/supermario.git
synced 2024-11-26 16:49:18 +00:00
4045 lines
148 KiB
Plaintext
4045 lines
148 KiB
Plaintext
;
|
||
; File: SlotMgr.a
|
||
;
|
||
; Contains: Macintosh Interface to the Slot Manager
|
||
;
|
||
; Written by: George Norman, June 1, 1986; (rewritten) David Wong, March 12, 1989
|
||
;
|
||
; Copyright: © 1986-1993 by Apple Computer, Inc., all rights reserved.
|
||
;
|
||
; Change History (most recent first):
|
||
;
|
||
; <SM14> 11-07-93 jmp Fixed two more bugs in RemoveCard: 1) Made sure that only the
|
||
; fAll bit is set when searching for sResources to delete, and 2)
|
||
; made sure that all resouces belonging to a particular slot would
|
||
; in fact be found (and now not skipped).
|
||
; <SM13> 2/8/93 rab Sync up with Horror. Comments follow: <H14> 8/24/92 SWC Fixed a
|
||
; bug in RemoveCard: the wrong register was being used.
|
||
; <SM12> 1/20/93 PN Re-roll in PatchGetCString so that d0 get zeroed out correctly.
|
||
; <SM11> 11/18/92 kc Import GetDriverPatch to fix problem introduced by last checkin.
|
||
; <SM10> 11/17/92 kc Add "IF NOT LC930 THEN" around GetDriverPatch to facilitate dead
|
||
; code stripping for the LC930 build.
|
||
; <SM9> 10/22/92 CSS Change some branch short instructions to branches.
|
||
; <SM8> 09-24-92 jmp Fixed a bug in the GetDevIndex utility where a register was
|
||
; being trashed.
|
||
; <SM7> 6/30/92 kc Roll in Horror, comments follow:
|
||
; •From SlotManagerPatch.a:
|
||
; <H12> 6/10/92 djw Modify AddCard to execute SecondaryInit's.
|
||
; <SM6> 6/20/92 PN Roll in patchIIciROM.a. Fix a bug in pInitEntry to restore the
|
||
; spID before calling _sFindDevBasse
|
||
; <SM5> 5/16/92 kc Roll in Horror. Comments follow:
|
||
; •From SlotManager.a:
|
||
; <H3> 3/18/92 djw Add new calls to support docking code - AddCard, RemoveCard,
|
||
; CheckSlot, and GetSRTEntry.
|
||
; <H2> 3/5/92 djw Replaced InitSlotMgr, InitsRsrcTable, InitPRAMRecs, and
|
||
; Primary_Init entries in the table with new routines.
|
||
; <T3> 11/5/90 CCH Fixed out of range error due to SlotMgrPatch.a moving to second
|
||
; half-meg.
|
||
; <T2> 9/17/90 CCH Patched Slot interrupt jump table in RAM for Eclipse.
|
||
; •From smspecial.a:
|
||
; <H3> 1/7/91 jmp Because of a misplaced label, the sRsrcFlag was only being read
|
||
; for Slot $0 devices.
|
||
; <H2> 12/11/90 HJR Fix a bug in special casing for slot zero: TestForRBV is not
|
||
; appropriate since not all machines that need special casing for
|
||
; slot zero have an RBV.
|
||
; •From smadvanced.a
|
||
; <T5> 4/23/91 jmp Cleaned up StatLoadPatch comments.
|
||
; <T4> 4/22/91 CCH Added a patch to StatLoadDrvr to flush the cache after loading
|
||
; in slot resources. Also slightly modified the way GetSlotDrvr
|
||
; was being patched.
|
||
; <T3> 3/29/91 CCH Added in a patch to SlotExec to flush the caches before
|
||
; executing code read from a NuBus card.
|
||
; <T2> 11/19/90 jmp Added in patch for GetDriver.
|
||
; •From SlotMgrPatches.a
|
||
; <H9> 4/24/92 HJR Added NiagraVIA2SlotInt and necessary install code for VSC video
|
||
; interrupts.
|
||
; <H8> 04/16/92 jmp Added a routine so that Slot $0 framebuffers can actually use
|
||
; the Minor/Major base address offset sResources like other slots
|
||
; can.
|
||
; <H7> 3/18/92 djw Complete CheckSlot call for DBLite docking code. Add AddCard and
|
||
; RemoveCard calls
|
||
; <H5> 02/05/92 jmp Unfortunately, I put some tables in the middle of this file
|
||
; that, in Cyclone, will get bigger. So, I moved them from the
|
||
; middle of the file into the pad space. Also, I generalized the
|
||
; routine that decides whether a DeclROM’s PrimaryInit/Driver
|
||
; should be patched by not stopping once I found the version I was
|
||
; looking for (e.g., in case we need to patch out versions 1, 2,
|
||
; and 3 of the 8•24 card).
|
||
; <H3> 10/29/91 jmp Added the VerifySlotPatch routine for supporting super sRsrc
|
||
; directories in Slot $0.
|
||
; <H2> 10/22/91 SAM/jmp Discontinued patching out the JMFB PrimaryInit & Driver on the
|
||
; Bungee (1.1) version of the 4•8/8•24 Card ROM. From Zydeco-TERROR ROM.
|
||
; •From SlotInfo.a
|
||
; <H5> 3/18/92 djw Add stub entry points for new docking support routines -
|
||
; StubAddCard and StubRemoveCard
|
||
; <H4> 3/6/92 SWC We thank Dave for <H3> (getting it working in under 25 tries…),
|
||
; and move the Docking Manager initialization to StartSDeclMgr
|
||
; just before running the primary inits so that we can decided
|
||
; whether or not to install the built-in LCD driver when DBLite
|
||
; (etc.) is inside a docking station and thus the LCD screen is
|
||
; not useable.
|
||
; <H3> 3/5/92 djw Rewrote slot manager initialization code (major routines from
|
||
; beginning of file to SecondaryInit) to facilitate new code for
|
||
; DBLite docking station. The major change was to modify the
|
||
; routines to execute their functions for a single slot instead of
|
||
; for every slot.
|
||
; <H2> 10/29/91 jmp Added a patch to the VerifySlot routine for supporting super
|
||
; sRsrc directories in Slot $0.
|
||
; <SM4> 5/5/92 JSM Roll-in changes from Reality:
|
||
; <19> 5/4/92 JSM The one check for isUniversal in this file should just be
|
||
; forROM. (Dean really didn’t have to do all that work in <17>).
|
||
; <SM3> 3/18/92 RB Added a WITH statement to use video information record.
|
||
; <SM2> 2/20/92 RB Need to switch to 24 bit mode before calling DisposPtr for
|
||
; srtRecords in the routine DeleteSRTRec. Made a second pass on
|
||
; Terror changes. The Terror code is diferent files and so that
|
||
; makes it hard to compare sources. Changed InitSlotPRAM,
|
||
; PtrToSlot, pInitEntry, GetBoard, and added MapUnit.
|
||
; <18> 1/7/92 RB Rolled in Terror changes. Mainly cache flushing.
|
||
; <17> 8/30/91 DTY Define isUniversal here since it’s no longer defined in
|
||
; BBSStartup. isUniversal is defined to be 0 for System builds
|
||
; because that’s the way it is. It should already be defined for
|
||
; the ROM build (in Build, in a {DefOverride}), but define it
|
||
; again just to be on the safe side. (It’s inside a check to see
|
||
; whether or not it’s defined, so it’s ok to define it again.)
|
||
; <16> 6/12/91 LN removed #include 'HardwareEqu.a'
|
||
; <15> 3/8/91 djw <dnf>(BRC #83516) Fix GetCString where in 32 bit mode reg d0 was
|
||
; set to 1 and caused an off-by-one count to be returned.
|
||
; <14> 12/10/90 djw Modify SlotExec to fix a problem with the 4•8/8•24/GC card's
|
||
; secondaryInit code. Add FixTrident routine to do the fix.
|
||
; <13> 9/19/90 BG Removed EclipseNOPs from <9>, <10>. 040s are behaving more
|
||
; reliably now.
|
||
; <12> 7/30/90 BG Removed IF CPU = 040 conditional in preparation for moving from
|
||
; Mac040 to Mac32 build.
|
||
; <11> 7/20/90 gbm get rid of slot warnings
|
||
; <10> 7/19/90 BG Added EclipseNOPs for flakey 040s.
|
||
; <9> 7/5/90 CCH Fixed aeStackFrame record for 68040. Also added EclipseNOPs for
|
||
; flakey 040s.
|
||
; <8> 6/29/90 djw Fix bug in FindDevBase and in SlotPRAM where hasRBV must be true
|
||
; or no slot zero. Deleted MapUnit routine (overkill). Modified
|
||
; FindDevBase to return a base addr for slot zero even if there is
|
||
; no internal video (addr is not mapped). Corrected conditionals
|
||
; for ROM and A/UX. Modified bus exception handler to be VM
|
||
; friendly (not pop stack frame and jump). Moved SecondaryInit
|
||
; code back to SlotMgrInit.a. Added universal support to SlotPRAM
|
||
; routines. Modified pGetBoard to accept spId as a parameter.
|
||
; <7> 4/2/90 djw Simplify the install and remove routines for bus exception
|
||
; handler
|
||
; <6> 2/20/90 BG Changed the definition of aeXFrameSize in the 040 bus exception
|
||
; handler to reflect the real size of the exception frame.
|
||
; <5> 1/21/90 BG Removed 040 AERROR from pBusException. Added routine
|
||
; p040BusException to handle 040 bus error exceptions.
|
||
; <4> 1/17/90 djw Modifications to build slot mgr with 32bit QD INIT using BBS
|
||
; sources. Added Secondary_Init and GetBoard routines from
|
||
; SlotMgrInit.a
|
||
; <3> 1/11/90 CCH Added include of “HardwarePrivateEqu.a”.
|
||
; <2> 1/3/90 BG Changing the quoting on the 040-related AERROR messages to use
|
||
; the correct quotes (single, not double). Will fix problem
|
||
; related to the AERROR shortly.
|
||
; <1.8> 9/18/89 djw Reorganized sources to combine into two source files, to allow
|
||
; system 7.0 patch to share the same sources.
|
||
; <1.7> 7/14/89 djw NEEDED FOR AURORA: removed sNewPtr. Set findbigdevbase to
|
||
; finddevbase because findbigdevbase. Update internal version
|
||
; number. macro is in mpw equate files (so just can't get rid of
|
||
; the call).
|
||
; <1.6> 6/30/89 djw removed pSlotStatus. Modified InitJmpTbl to use relative
|
||
; addressed table. Changed sdmjmptbl to use relative addresses for
|
||
; the vectors
|
||
; <1.5> 6/12/89 djw Removed findbigdevbase
|
||
; <1.4> 3/28/89 djw Cleaned up IMPORT statements. Rewrote InitJmpTbl,SlotManager.
|
||
; Added dummy routine for unimplemented selectors. Deleted old
|
||
; modification history. Added patch support, added old bsr routine
|
||
; to jmp tbl now using slotjsr macro. Rewrote slotmgr dispatcher
|
||
; <1.3> 3/12/89 djw Added InitJmpTbl from smadvanced, to make the 1.0 patch easier
|
||
; to manage. Moved things around a little. Added GetsRsrcPtr.
|
||
; <1.2> 2/20/89 djw Added sVersion, SetsRsrcState, InsertSRTRec, delete code to
|
||
; switch slotmanager 24 bit mode - make it 32 bit clean. Added
|
||
; GetsRsrc, GetTypesRsrc and FindSRTRec.
|
||
; <1.1> 11/10/88 CCH Fixed Header.
|
||
; <1.0> 11/9/88 CCH Adding to EASE.
|
||
; <1.5> 11/7/88 djw Added InitSlotPRAM
|
||
; <•1.4> 10/24/88 djw NEW SLOTMANAGER VERSION. Deleted all register names. Rewrote to
|
||
; save mmu mode on stack - no longer need to save any registers in
|
||
; called slot manager routines. All new IMPORT routine names.
|
||
; <•1.3> 9/23/88 CCH Got rid of inc.sum.d and empty nFiles
|
||
; <1.2> 2/15/88 BBM added inc.sum.d as a second load file
|
||
; <1.1> 2/15/88 BBM modified for mpw 3.0 equates
|
||
; <1.0> 2/10/88 BBM Adding file for the first time into EASE…
|
||
;
|
||
|
||
Machine MC68020
|
||
String Asis
|
||
Print Off
|
||
LOAD 'StandardEqu.d'
|
||
Include 'HardwarePrivateEqu.a'
|
||
Include 'RomEqu.a'
|
||
Include 'UniversalEqu.a'
|
||
Include 'SlotMgrEqu.a'
|
||
Include 'ComVideoEqu.a' ; <18> rb
|
||
Print On
|
||
|
||
If (&TYPE('forAUX') = 'UNDEFINED') Then ; equ indicating whether we are <8>
|
||
forAUX Equ 0 ; ... building for an A/UX patch
|
||
Endif
|
||
|
||
;_________________________________________________________________________________________ <1.4>
|
||
; SlotManager - slot manager secondary dispatch routine
|
||
;
|
||
; Vector through the secondary dispatch table for the slot manager to the requested
|
||
; routine.
|
||
;
|
||
; Input : reg D0 = routine selector (word)
|
||
;
|
||
|
||
SlotMgr Proc
|
||
Export SlotManager
|
||
|
||
; Jump to the selected slot manager routine.
|
||
|
||
DC.B 'slot version 2.3' ; slot manager internal version number <4>
|
||
SlotManager
|
||
CMP.W #LastSDMSelt,D0 ; check selector range
|
||
BHI.S SlotEmpty ; selector(unsigned) > max - error <djw>
|
||
move.l ([SDMJmpTblPtr],d0.w*4),a1 ; get vector from table <1.7>
|
||
jmp (a1) ; <1.7>
|
||
|
||
|
||
;_________________________________________________________________________________________ <1.4>
|
||
; SlotEmpty - unimplemented slot manager trap
|
||
;
|
||
Export SlotEmpty
|
||
|
||
SlotEmpty
|
||
move.w #smSelOOBErr,d0 ; error - selector out of bounds
|
||
rts
|
||
|
||
|
||
;=========================================================================================
|
||
; smPrinciple
|
||
;=========================================================================================
|
||
|
||
**********************************************************************
|
||
*
|
||
* FUNCTION ReadSlotByte : Read Byte.
|
||
* Return an 8-bit value from the list pointed to by sPointer and
|
||
* identified by Id. This value is placed in the LSB of the Result
|
||
* field.
|
||
*
|
||
* Parameter block:
|
||
* -> spsPointer - Points to the list the Byte is in.
|
||
* -> spId - The Id of the Byte.
|
||
* <- spResult - The desired byte.
|
||
*
|
||
**********************************************************************
|
||
ReadSlotByte FUNC EXPORT
|
||
|
||
;VAR
|
||
spBlkPtr$a0 EQU A0 ;Pointer to the SDM parameter block
|
||
Status$d0 EQU D0 ;Status of ReadSlotByte
|
||
|
||
;----------------------------------------------------------------------
|
||
; ReadSlotByte
|
||
;----------------------------------------------------------------------
|
||
;BEGIN
|
||
WITH spBlock
|
||
|
||
; Initialize
|
||
MOVE.L spsPointer(spBlkPtr$a0),-(SP) ;Save sPointer.
|
||
CLR.B spResult+3(spBlkPtr$a0) ;ReadSlotByte <- 0
|
||
|
||
|
||
; Read the Offset/Data field and assign the Data to ReadSlotByte.
|
||
_sOffsetData ;Read the Offset/Data field.
|
||
BNE.S End ;IF Error THEN
|
||
; GOTO End
|
||
|
||
MOVE.B spOffsetData+3(spBlkPtr$a0),spResult+3(spBlkPtr$a0) ;ReadSlotByte <- Data[4]
|
||
MOVEQ #0,Status$d0 ;Status <- NoError
|
||
|
||
|
||
; Exit
|
||
End MOVE.L (SP)+,spsPointer(spBlkPtr$a0) ;Restore sPointer.
|
||
RTS ;Return.
|
||
|
||
|
||
ENDWITH
|
||
;END ReadSlotByte
|
||
ENDF
|
||
|
||
|
||
EJECT
|
||
**********************************************************************
|
||
*
|
||
* FUNCTION ReadSlotWord : Read Word.
|
||
* Return a 16-bit value from the list pointed to by sPointer and
|
||
* identified by Id. This value is placed in the two LSB fields of
|
||
* the Result field.
|
||
*
|
||
* Parameter block:
|
||
* -> spsPointer - List pointer. Points to the list the Word is in.
|
||
* -> spId - Id. The Id of the Word in the list.
|
||
* <- spResult - The desired word.
|
||
*
|
||
**********************************************************************
|
||
ReadSlotWord FUNC EXPORT
|
||
|
||
;VAR
|
||
spBlkPtr$a0 EQU A0 ;Pointer to the SDM block
|
||
Status$d0 EQU D0 ;Status of ReadSlotWord
|
||
|
||
;----------------------------------------------------------------------
|
||
; ReadSlotWord
|
||
;----------------------------------------------------------------------
|
||
;BEGIN
|
||
WITH spBlock
|
||
|
||
; Initialize
|
||
MOVE.L spsPointer(spBlkPtr$a0),-(SP) ;Save sPointer
|
||
CLR.W spResult+2(spBlkPtr$a0) ;ReadSlotWord <- 0
|
||
|
||
|
||
; Read the Offset/Data field and Assign the Data to ReadSlotWord.
|
||
_sOffsetData ;Read the Offset/Data field.
|
||
BNE.S End ;IF Error THEN
|
||
; GOTO End
|
||
|
||
MOVE.W spOffsetData+2(spBlkPtr$a0),spResult+2(spBlkPtr$a0) ;ReadSlotWord <- Data[3..4]
|
||
MOVEQ #0,Status$d0 ;Status <- NoError
|
||
|
||
|
||
; Exit
|
||
End MOVE.L (SP)+,spsPointer(spBlkPtr$a0) ;Restore sPointer.
|
||
RTS ;Return.
|
||
|
||
|
||
ENDWITH
|
||
;END ReadSlotWord
|
||
ENDF
|
||
|
||
|
||
EJECT
|
||
**********************************************************************
|
||
*
|
||
* FUNCTION ReadSlotLong : Read Long
|
||
* Return a 32-bit value from the list pointed to by sPointer and
|
||
* identified by Id. This value is placed in the Result field.
|
||
*
|
||
* Parameter block:
|
||
* -> spsPointer - List pointer. Points to the list the Long is in.
|
||
* -> spId - Id. The Id of the Long in the list.
|
||
* <- spResult - The desired long.
|
||
*
|
||
**********************************************************************
|
||
ReadSlotLong FUNC EXPORT
|
||
|
||
;VAR
|
||
spBlkPtr$a0 EQU A0 ;Pointer to the SDM parameter block
|
||
Status$d0 EQU D0 ;Status of ReadSlotLong
|
||
|
||
;----------------------------------------------------------------------
|
||
; ReadSlotLong
|
||
;----------------------------------------------------------------------
|
||
;BEGIN
|
||
WITH spBlock
|
||
|
||
; Initialize
|
||
MOVE.L spsPointer(spBlkPtr$a0),-(SP) ;Save sPointer.
|
||
CLR.L spResult(spBlkPtr$a0) ;ReadSlotLong <- 0
|
||
|
||
|
||
; Use sReadPBSize to read the Long and move PhyBlkSize to Result.
|
||
BCLR.B #fCkReserved,spFlags(spBlkPtr$a0) ;Do not check reserved.
|
||
_sReadPBSize ;Read the long.
|
||
BNE.S End ;IF Error THEN
|
||
; GOTO End
|
||
|
||
MOVE.L spSize(spBlkPtr$a0),spResult(spBlkPtr$a0) ;ReadSlotLong <- PhyBlkSize
|
||
MOVEQ #0,Status$d0 ;Status <- NoError
|
||
|
||
|
||
; Exit
|
||
End MOVE.L (SP)+,spsPointer(spBlkPtr$a0) ;Restore sPointer.
|
||
RTS ;Return
|
||
|
||
|
||
ENDWITH
|
||
;END ReadSlotLong
|
||
ENDF
|
||
|
||
|
||
EJECT
|
||
;_______________________________________________________________________________________ <1.5>
|
||
; GetcString - get a C string
|
||
;
|
||
; Find the cString identified by the id in the given sList. Allocate a pointer
|
||
; block on the system heap and copy the string to it.
|
||
;
|
||
; Input : reg A0 = ptr to spBlock
|
||
; Output : none
|
||
;
|
||
; spBlock : -> spId id of the cString in the list
|
||
; -> spsPointer ptr to list
|
||
; <- spResult ptr to the cString in RAM
|
||
;
|
||
; Called : trap dispatcher
|
||
;
|
||
|
||
GetcString Proc Export
|
||
With spBlock
|
||
|
||
movem.l a2-a3,-(sp)
|
||
move.l spsPointer(a0),-(sp) ; save ptr to the sList
|
||
move.b spSlot(a0),-(sp) ; save the slot
|
||
|
||
_sFindStruct ; get the ptr to the string
|
||
bne @Done ; <SM9> CSS
|
||
movea.l spsPointer(a0),a3 ; a3 = ptr to the string
|
||
|
||
; Calculate the step register
|
||
|
||
bset.b #fConsecBytes,spFlags(a0) ; calc for consecutive bytes
|
||
_sCalcStep
|
||
bne @Done ; <SM9> CSS
|
||
move.l spResult(a0),d1 ; d1 = step register
|
||
|
||
; Loop and count all the chars in the string so we know how big a block to allocate.
|
||
|
||
moveq #0,d2 ; clear temp reg for NextStep macro
|
||
movea.l a3,a1 ; a1 = ptr to the string in the decl rom
|
||
lea @Done,a2 ; set address to jump to if bus error
|
||
slotjsr InstallBus ; replace sys bus excptn and 32 bit mode
|
||
moveq #0,d0 ; d0 = length cntr <SM12> PN
|
||
@Loop
|
||
addq.l #1,d0 ; inc the length
|
||
move.b (a1),d2 ; NUBUS READ - read a char
|
||
beq.s @EndLoop ; found the end of the string
|
||
sNextStep d1,d2,a1 ; inc to the next byte in the decl rom
|
||
bra.s @Loop ;Continue looping
|
||
|
||
@EndLoop move.l d0,spSize(a0) ; set size of string
|
||
slotjsr RestoreBus ; restore mmu mode and sys bus excptn
|
||
|
||
; Allocate a non-relocatable block on the current heap to copy the string to
|
||
|
||
movea.l a0,a2 ; save ptr to spBlock
|
||
_NewPtr ; allocate the memory <1.6>
|
||
bne.s @Done
|
||
|
||
move.l a0,spResult(a2) ; pass ptr to buf in result field
|
||
movea.l a2,a0 ; restore a0 = ptr to spBlock
|
||
move.l a3,spsPointer(a0) ; restore ptr to the string
|
||
_sReadStruct ; copy the string to the buffer
|
||
beq.s @Done ; a good return
|
||
move.l d0,d1 ; an error - save the error code
|
||
movea.l a0,a1 ; save ptr to spBlock
|
||
movea.l spsPointer(a1),a0 ; free the allocated pointer
|
||
_DisposPtr
|
||
movea.l a1,a0 ; restore a0 = ptr to spBlock
|
||
move.l d1,d0 ; restore the error code
|
||
|
||
@Done
|
||
move.b (sp)+,spSlot(a0) ; restore the slot
|
||
move.l (sp)+,spsPointer(a0) ; restore the ptr to the sList
|
||
movem.l (sp)+,a2-a3
|
||
rts
|
||
|
||
|
||
EJECT
|
||
;_______________________________________________________________________________________ <1.5>
|
||
; GetSlotBlock - get an sBlock on the system heap
|
||
;
|
||
; Given a pointer to an sList and the id of an sBlock, find and copy the block to
|
||
; a non-relocatable block allocated on either the system or current heap. GetSSBlock
|
||
; must allocate on the system heap, because video drivers assumes that it does. The
|
||
; old slot manager allocated on the current heap.
|
||
;
|
||
; Input : reg A0 = ptr to spBlock
|
||
; Output : none
|
||
;
|
||
; spBlock : -> spId id of the sBlock in the list
|
||
; -> spsPointer ptr to list
|
||
; <- spResult ptr to the copy block in ram
|
||
;
|
||
; Called : trap dispatcher
|
||
;
|
||
|
||
GetSlotBlock Proc Export
|
||
With spBlock
|
||
|
||
move.l spsPointer(a0),-(sp) ; save the spsPointer field
|
||
|
||
bset.b #fCkReserved,spFlags(a0) ; check the reserved byte for zero
|
||
_sReadPBSize ; read the physical block size
|
||
bne.s @Done
|
||
move.l spSize(a0),d0 ; d0 = sBlock size (including length field)
|
||
subq.l #4,d0 ; size-length field > 0 ?
|
||
bgt.s @Alloc ; positive block size <1.7>
|
||
move.w #smNilsBlockErr,d0 ; a bad block size
|
||
bra.s @Done
|
||
|
||
@Alloc
|
||
move.l d0,spSize(a0) ; set size of sBlock (minus length field)
|
||
movea.l a0,a1 ; save ptr to spBlock
|
||
_NewPtr ,Sys ; on sys heap for video dependency <1.6>
|
||
bne.s @Done
|
||
move.l a0,spResult(a1) ; pass ptr to buffer in spResult
|
||
|
||
movea.l a1,a0 ; restore a0 = ptr to spBlock
|
||
_sReadStruct ; copy the sBlock to memory
|
||
beq.s @Done ; a good return
|
||
move.l d0,d1 ; an error - save the error code
|
||
movea.l a0,a1 ; save ptr to spBlock
|
||
movea.l spsPointer(a1),a0 ; free the allocated pointer
|
||
_DisposPtr
|
||
movea.l a1,a0 ; restore a0 = ptr to spBlock
|
||
move.l d1,d0 ; restore the error code
|
||
|
||
@Done
|
||
move.l (sp)+,spsPointer(a0) ;restore ptr to the sList
|
||
rts
|
||
|
||
|
||
;_______________________________________________________________________________________ <1.5>
|
||
; FindSlotStruct - find a structure
|
||
;
|
||
; Given a pointer to an sList, find the offset field associated with the given id.
|
||
; Calculate a pointer from the offset and return the pointer.
|
||
;
|
||
; Input : reg A0 = ptr to spBlock
|
||
; Output : none
|
||
;
|
||
; spBlock : -> spId id of the sBlock in the list
|
||
; <-> spsPointer ptr to list
|
||
; returns ptr to structure
|
||
; <- spByteLanes by product of offsetdata call
|
||
;
|
||
; Called : trap dispatcher, jsr
|
||
;
|
||
|
||
FindSlotStruct Proc Export
|
||
With spBlock
|
||
|
||
_sOffsetData ; find and read the offset/data field
|
||
bne.s @Done
|
||
|
||
_sCalcsPointer ; convert offset to a pointer
|
||
@Done
|
||
rts
|
||
|
||
|
||
;_______________________________________________________________________________________ <1.5>
|
||
; ReadSlotStruct - read a structure
|
||
;
|
||
; Given a pointer to a structure, copy the structure into the given buffer,
|
||
;
|
||
; Input : reg A0 = ptr to spBlock
|
||
; Output : none
|
||
;
|
||
; spBlock : -> spsPointer ptr to list
|
||
; -> spSize number of bytes to read
|
||
; <-> spResult ptr to buffer to copy structure to
|
||
;
|
||
; Called : trap dispatcher, jsr
|
||
;
|
||
|
||
ReadSlotStruct Proc Export
|
||
With spBlock, sInfoRecord
|
||
|
||
movem.l d1-d3/a1-a3,-(sp)
|
||
move.b spSlot(a0),-(sp) ; save spSlot field
|
||
movea.l spsPointer(a0),a3 ; a3 = ptr to struct to read
|
||
move.l a3,-(sp) ; save spsPointer field
|
||
|
||
; Strip the buffer pointer to make sure it's 32 bit clean
|
||
|
||
move.l spResult(a0),d0 ; d0 = buffer ptr
|
||
_StripAddress
|
||
move.l d0,-(sp) ; save a copy of ptr to buffer
|
||
movea.l d0,a1 ; a1 = ptr to the buffer
|
||
|
||
; Convert the pointer to a slot number
|
||
|
||
_sPtrToSlot ; return a slot number
|
||
bne.s @Done
|
||
_sFindsInfoRecPtr ; given the slot, get ptr to sInfoRecord
|
||
bne.s @Done
|
||
movea.l spResult(a0),a2 ; reg a2 = ptr to sInfo record
|
||
|
||
; Calculate the step register for the slot
|
||
|
||
|
||
move.b siCPUByteLanes(a2),spByteLanes(a0) ; get byte lane field from sInfo rec
|
||
bset.b #fConsecBytes,spFlags(a0) ; calc for consecutive bytes
|
||
_sCalcStep
|
||
bne.s @Done
|
||
move.l spResult(a0),d1 ; d1 = step register
|
||
|
||
; Loop and read the struct into the buffer
|
||
; a1 = ptr to buffer, a3 = ptr to struct
|
||
|
||
slotjsr InstallBus ; 32 bit mode and swap bus exception vector
|
||
moveq #0,d3 ; clear temp register for NextStep macro
|
||
move.l spSize(a0),d2 ; d2 = number of bytes to read
|
||
subq.l #1,d2 ; adjust size for dbra loop
|
||
lea @EndLoop,a2 ; address to jump to if bus error
|
||
move.w #smUnExBusErr,d0 ; set error return (just in case)
|
||
|
||
@Loop
|
||
move.b (a3),(a1)+ ; NUBUS READ - copy a byte
|
||
sNextStep d1,d3,a3 ; inc rom ptr
|
||
dbra d2,@Loop ; continue
|
||
moveq #noErr,d0 ; completed ok - set return status
|
||
@EndLoop
|
||
slotjsr RestoreBus ; switch back to save mmu mode and bus exception
|
||
|
||
@Done
|
||
move.l (sp)+,spResult(a0) ; restore ptr to buffer
|
||
move.l (sp)+,spsPointer(a0) ; restore ptr to structure
|
||
move.b (sp)+,spSlot(a0) ; restore slot number field
|
||
movem.l (sp)+,d1-d3/a1-a3
|
||
tst.w d0 ; set ccr
|
||
rts
|
||
|
||
;=========================================================================================
|
||
; smSpecial
|
||
;=========================================================================================
|
||
|
||
|
||
**********************************************************************
|
||
*
|
||
* FUNCTION ReadInfo : Read Slot Information.
|
||
* Read the SlotInfo record identified by Slot.
|
||
*
|
||
* Parameter block:
|
||
* -> spSlot - Which slot.
|
||
* <-> spResult - Pointer to the buffer.
|
||
*
|
||
**********************************************************************
|
||
ReadSlotInfo FUNC EXPORT
|
||
|
||
;VAR
|
||
spBlkPtr$a0 EQU A0 ;Pointer to the SDM parameter block.
|
||
sInfoRec$a EQU A1 ;sInfoArray pointer.
|
||
BufferPtr$a EQU A2 ;Pointer to the buffer.
|
||
|
||
Status$d0 EQU D0 ;Status
|
||
Slot$d EQU D1 ;Slot
|
||
LoopIndex$d EQU D2 ;Loop Index.
|
||
|
||
|
||
;----------------------------------------------------------------------
|
||
; ReadSlotInfo
|
||
;----------------------------------------------------------------------
|
||
;BEGIN
|
||
WITH spBlock,sInfoRecord
|
||
|
||
; Allocate local vars.
|
||
MOVEM.L A2,-(SP) ;Save registers
|
||
MOVE.L spResult(spBlkPtr$a0),BufferPtr$a ;BuferPtr$a <- Pointer to the buffer.
|
||
MOVE.L BufferPtr$a,-(SP) ;Save spResult.
|
||
|
||
|
||
; Get a pointer to the sInfo Array for the given slot.
|
||
C10 _sFindsInfoRecPtr ;Find the pointer to the sInfo record. <C520><C726>
|
||
BNE End ;Branch if error. <C520>
|
||
|
||
MOVE.L spResult(spBlkPtr$a0),sInfoRec$a ;sInfoRec$a <- pointer to the sInfo record. <C520>
|
||
|
||
|
||
; Move the sInfo record to the block.
|
||
MOVEQ #sInfoRecSize-1,LoopIndex$d ;LoopIndex$d <- sInfoRecSize-1
|
||
;REPEAT
|
||
Repeat MOVE.B (sInfoRec$a)+,(BufferPtr$a)+ ; sInfoRec(i)+ <- sInfoArray[Slot].(i)+
|
||
Until DBF LoopIndex$d,Repeat ;UNTIL LoopIndex < 0
|
||
MOVEQ #0,Status$d0 ;Status <- NoError
|
||
|
||
|
||
; Restore locals & return
|
||
End MOVE.L (SP)+,spResult(spBlkPtr$a0) ;Restore the buffer pointer.
|
||
MOVEM.L (SP)+,A2 ;Restore registers
|
||
RTS ;Return
|
||
|
||
ENDWITH
|
||
;END ReadSlotInfo
|
||
ENDF
|
||
|
||
|
||
|
||
**********************************************************************
|
||
*
|
||
* PROCEDURE SlotDisposPtr : Dispose Pointer
|
||
* Dispose of the pointer.
|
||
*
|
||
* Parameter block:
|
||
* -> spsPointer - The pointer to be disposed.
|
||
*
|
||
**********************************************************************
|
||
SlotDisposPtr PROC EXPORT
|
||
|
||
;VAR
|
||
spBlkPtr$a0 EQU A0 ;Pointer to the SDM parameter block.
|
||
p$a0 EQU A0 ;Pointer to be disposed by Memory Manager.
|
||
|
||
Status$d0 EQU D0 ;Status
|
||
|
||
|
||
;----------------------------------------------------------------------
|
||
; SlotDisposPtr
|
||
;----------------------------------------------------------------------
|
||
;BEGIN
|
||
WITH spBlock
|
||
|
||
; Allocate local vars.
|
||
move.l a0,-(sp) ; <1.7>
|
||
|
||
; Dispose of the block.
|
||
MOVE.L spsPointer(a0),a0 ;p <- sPointer
|
||
_DisposPtr ;DisposPtr(p)
|
||
BEQ.S End ;IF Good THEN
|
||
; GOTO End
|
||
;ELSE
|
||
MOVE.L #smDisposePErr,d0 ; Status <- smDisposeHErr
|
||
|
||
; Restore spBlkPtr and Return
|
||
End movea.l (sp)+,a0 ; <1.7>
|
||
RTS
|
||
|
||
ENDWITH
|
||
;END SlotDisposPtr
|
||
ENDP
|
||
|
||
|
||
EJECT
|
||
**********************************************************************
|
||
*
|
||
* FUNCTION ReadSlotDrvrName : Read the driver name.
|
||
* Read the sResource name, Append the '.' prefix to this name,
|
||
* giving the sDriver name. The result is a pointer to a Pascal type
|
||
* string useable by iocore (_Open).
|
||
*
|
||
* Parameter block:
|
||
* -> spSlot : Slot number.
|
||
* -> spId : sResource id.
|
||
* <- spResult : Pointer to the driver name.
|
||
*
|
||
**********************************************************************
|
||
ReadSlotDrvrName FUNC EXPORT
|
||
|
||
;VAR
|
||
spBlkPtr$a0 EQU A0 ;Pointer to the SDM parameter block.
|
||
SourcePtr$a0 EQU A0 ;**Used by _BlockMove.
|
||
DestPtr$a1 EQU A1 ;**Used by _BlockMove.
|
||
sRsrcNamePtr$a EQU A2 ;Pointer to sResource name.
|
||
BufferPtr$a EQU A3 ;Pointer to the buffer.
|
||
|
||
Status$d0 EQU D0 ;Status.
|
||
ByteCnt$d0 EQU D0 ;**Used by _BlockMove.
|
||
LensRsrcName$d EQU D1 ;Length of sResource name.
|
||
IdSave$d EQU D2 ;Save the sResource Id.
|
||
|
||
;----------------------------------------------------------------------
|
||
; ReadSlotDrvrName
|
||
;----------------------------------------------------------------------
|
||
;BEGIN sGetDrvrName
|
||
WITH spBlock,sInfoRecord
|
||
|
||
; Save
|
||
MOVEM.L A2-A3,-(SP) ;Save A2-A3
|
||
MOVE.B spId(a0),d2 ;Save Id
|
||
MOVE.L spResult(a0),a3 ;BuferPtr$a <- Pointer to the buffer.
|
||
MOVE.L a3,-(SP) ;Save spResult.
|
||
|
||
|
||
; Get sResource Name
|
||
CLR.B spExtDev(A0) ; was not required for ReadDrvrName <1.4>
|
||
CLR.L spParamData(A0) ; only look at enabled guys <1.4>
|
||
_GetsRsrcPtr ; find the ptr to the sRsrc <1.4>
|
||
BNE.S Err2
|
||
MOVE.B #sRsrcName,spId(a0)
|
||
_sGetcString ;Get the name.
|
||
BNE.S Err2
|
||
MOVE.L spResult(a0),a2
|
||
MOVE.L spSize(a0),d1
|
||
SUBQ.B #1,d1 ;Adjust length to ignore the nil EOS marker.
|
||
CMP.L #254,d1 ;IF d1 > 254 THEN
|
||
BHI.S Err1
|
||
|
||
|
||
; Set prefix {Prefix = '<Len>.', where Len is the length of the string.
|
||
MOVE.B spSize+3(a0),(a3)+ ;Str -> '<Len>'
|
||
MOVE.B #'.',(a3)+ ;Str -> '<Len>.'
|
||
|
||
|
||
; Append the sResource name to the prefix, giving: '<Len>.Name'
|
||
MOVEM.L A0-A1,-(SP) ;Preserve A0-A1, destroyed by _BlockMove.
|
||
MOVE.L a2,a0
|
||
MOVE.L a3,a1
|
||
MOVE.L d1,d0
|
||
_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
|
||
|