sys7.1-doc-wip/OS/Gestalt/GestaltFunction.a
2020-05-10 13:37:38 +08:00

1697 lines
66 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

;
; Hacks to match MacOS (most recent first):
;
; <Sys7.1> 8/3/92 Elliot make this change
; 9/2/94 SuperMario ROM source dump (header preserved below)
;
;
; File: GestaltFunction.a
;
; Contains: Entry point for Gestalt trap, and pre-defined Gestalt functions.
;
; Written by: Carl C. Hewitt
;
; Copyright: © 1989-1993 by Apple Computer, Inc., all rights reserved.
;
; Change History (most recent first):
;
; <SM5> 5/19/92 CS Integrated changes from Reality:
; <42> 4/9/92 JSM #1026795,<DTY>: gestaltSerialAttr should be the same for a Mac
; <41> 12/4/91 csd #1016451: Added support for Scruffy. If Scruffy is running, we
; need to set 32-bit capable flag for the
; gestaltAddressingModeAttr selector.
; <40> 12/2/91 SAM Using official boxflag equates now.
; <39> 10/28/91 SAM/KSM Rolled in Regatta Changes. Removed sound selector code from this
; file cuz its in SoundMgrLowLevel.a
;
; Regatta Change History:
;
; <11> 8/28/91 SAM The logical RAM size is now gotten from RealMemTop on IIci
; machines.
; <10> 7/18/91 SAM Using the new MemoryDispatch calls to get the logical & physical
; RAM sizes when VM is on.
; <9> 7/9/91 SAM Removing the gestaltSoundAttr selector. It will get installed by
; the SoundMgr patch.
; <8> 7/2/91 SAM Extended the keyBdTable to include entries for Tim & Asahi.
; <7> 7/1/91 SAM Correcting logical RAM size while VM is running to assure the
; correct value in the case where a 24-bit system is used with
; more than 8mb of VM (in this case VM sets memtop to the wrong
; value!)
; <5> 6/15/91 SAM The size of the EDisk is added to the Logical RAM size that gets
; returned from Gestalt. This is so the RAM disk size shows up in
; the About the Finder dialog. The functionality of the "Is the
; New/ReplaceGestalt Proc Ptr zero?" linked patch has been Added
; to this file (and the patch removed).
; <4> 5/23/91 SAM This time for real (tough typo!)
; <3> 5/23/91 SAM Typo fix.
; <2> 5/23/91 SAM ORR, Added selectors for Jaws, Sonic, SCSC961, SCSI962 and DAFB
; to the Harware attribute table.
; <1> 5/15/91 SAM Split off from 7.0 GM sources. Changed the internal setup of
; MemSize (physical RAM size) and RealTop (logical RAM size) so
; that MemSize is obtained from RealMemTop (the low mem) on
; IIciROM machines and MemTop (the low mem) on all other machines.
;
; 7.0 Change History:
;
; <38> 9/30/91 JSM Dont use is32BitClean conditional in getAddrMode, all future
; ROMs will be.
; <37> 9/10/91 JSM Cleanup header.
; <36> 8/30/91 DTY Change the QuickDraw selector code so that it doesnt depend on
; the hasCQD conditional. Remove isUniversal check in parity
; selector since we make only universal ROMs now.
; <35> 7/10/91 dba end of the forPost70 conditional; we are past 7.0 for good
; <34> 6/12/91 LN removed #include 'HardwareEqu.a'
; <33> 6/11/91 gbm dba: add new Gestalt bit to indicate that the hardware requires
; a RESET when resetting the machine
; <32> 3/7/91 dnf dty,#DNF-009:Move the latest version of the function for 'fs '
; into here.
; <31> 2/20/91 KON smc BRC #83172: Gestalt should call the QDOffscreen version trap
; to get the 'qd ' version if 32-bit QD is present.
; <30> 2/6/91 KON smc: BRC# Gang of 5: Remove GestaltOriginalQD1 and change to
; GestaltOriginalQD as per Gang Of 5 discussion.
; <29> 1/23/91 KON bbm: no BRC #, Make Gestalt on B&W machines return version 1.
; <28> 1/8/91 SAM Changed all occurrences of gestaltXO to GestaltMacClassic
; <27> 10/22/90 JJ Rex V8: Change VISAChipBit to V8ChipBit.
; <26> 9/22/90 dnf add gestaltFSAttrs for file system attributes
; <25> 9/14/90 MSH Added additional feature based conditionals for inclusion of
; power manager stuff.
; <24> 9/12/90 SAM Changing GestaltElsie to GestaltMacLC.
; <23> 8/13/90 JWK NEEDED FOR SIXPACK: Added NuBus and Serial Gestalt selectors.
; <22> 8/13/90 gbm add selectors for trap table bases
; <21> 7/24/90 gbm Get rid of useless branch
; <20> 7/18/90 CCH Moved machine icon selector to linked patch version in
; GestaltPatches.a.
; <19> 6/20/90 CCH Modified FPU routine to support 68040's when not running in ROM.
; <18> 6/1/90 CCH Added 68040 support to page size selector.
; <17> 5/1/90 CCH Added specific entry for XO (to indicate that it doesn't have a
; PDS slot.) Also added SquareMenuBar response to misc selector.
; <16> 4/11/90 dba add selector that gets the resource ID of the model icon
; <15> 3/26/90 CCH Added check for VISA and renamed gestalt Headphone selector.
; <14> 3/1/90 GMR Fixed bug in parity check for Zone-5, where longword was not
; being written back with good parity after each SIMM check.
; <13> 2/14/90 CCH Made sure external cache on Zone 5 does not interfere with the
; check to see if parity RAM is installed.
; <12> 1/30/90 CCH NEEDED FOR 6.0.5: - Modified gestaltHardwareAttr to set
; gestaltHasSCC bit in result if in IOP bypass mode. - Also
; modified hardware selector to check for 32-bit cleanliness on
; any machine running a/ux.
; <11> 1/25/90 CCH Added values for Elmer keyboards.
; <10> 1/22/90 CCH Added in machine-specific slot information for pre-universal
; ROMs.
; <9> 1/22/90 CCH Added gestaltNotificationMgrAttr selector.
; <8> 1/17/90 CCH NEEDED FOR 6.0.5: moved restoration of cache register in parity
; check routine.
; <7> 1/16/90 CCH turn off cache when checking RPU for parity.
; <6> 1/11/90 CCH Added include of “HardwarePrivateEqu.a”.
; <5> 1/10/90 CCH Don't check for parity on XO.
; <4> 1/8/90 CCH Added gestaltMisc selector.
; <3> 1/5/90 CCH Changes: (NEEDED FOR 6.0.5) - Added slot selectors back in
; temporarily. - Added RPU and Orwell bits to hardware selector. -
; Added Zone 5 parity support - Reorganized some code to determine
; FPU and MMU types only at startup. - Also removed those
; selectors that only returned SCC, VIA or RBV base addresses.
; <2> 1/3/90 CCH Changed Gestalt equate filename.
; <1> 1/2/90 CCH Changed name from Gestalt.a. Also removed slot-related
; selectors.
; <3.3> 12/15/89 CCH Changes: (NEEDED FOR 6.0.5)
; - Modified gestaltROMSize selector to work with XO
; - GestaltSCCReadAddr and gestaltSCCWriteAddr return
; an error when not in bypass mode on Zone 5.
; - Modified to return machine-specific info for XO.
; <3.2> 11/1/89 CCH Changed gestaltVMInstalled to gestaltVMExists.
; <3.1> 9/29/89 CCH Added gestalt32BitCapable bit to gestaltAddressingModeAttr.
; <3.0> 8/9/89 CCH Changes: (NEEDED FOR 6.0.4)
; - Changed gestaltQuickdrawType to gestaltQuickdrawVersion
; and made it return two-byte versions.
; - Fixed bug in gestaltVersion selector
; <2.9> 7/16/89 CCH Changes: (NEEDED FOR AURORA AND 6.0.4)
; - Started using common exit code for Gestalt functions.
; - Got rid of unecessary HLocks and HUnlocks
; <2.8> 7/10/89 CCH Changes: (NEEDED FOR AURORA)
; - Removed gestaltFirstSlotNumber selector.
; <2.7> 6/30/89 CCH Changes:
; - Added gestaltLowMemSize selector.
; - Fixed bug that caused gestaltLogicalPageSize to write to
; ROM.
; - gestaltAUXVersion now returns an unknown error if a/ux
; is not installed.
; <2.6> 6/26/89 CCH Changes:
; - Added gestaltLogicalPageSize and gestaltFirstSlotNumber
; selectors
; - Rewrote built-in selector
; installation routine
; <2.5> 6/9/89 CCH Changes:
; - Added gestaltAddressingModeAttr, gestaltAUXVersion,
; gestaltSlotAttr, gestaltSoundAttr, gestaltTimeMgrVersion,
; GestaltRBVAddr, gestaltHardwareAttr, gestaltNuBusSlotCount
; selectors.
; - Fixed gestaltLogicalRAMSize to take video RAM into
; account on IIci.
; <2.4> 5/25/89 CCH Changes:
; - Took out concept of internal-only codes, added internal
; gestalt function
; - added NewGestalt, ReplaceGestalt calls
; <2.3> 5/23/89 CCH Changes:
; - Added VIA,SCC,ROM version,VM info, and power mgr selectors
; - changed gestalt function interface to use pascal
; conventions so they can be written in high-level languages
; - save registers before calling gestalt functions
; <2.2> 5/18/89 CCH Several changes:
; - wrote getGestalt in assembly, and moved from Gestalt.c
; - started using new error codes
; - changed interface to use A0 to return results
; - get ROM size routine now uses size word in new ROMs
; - removed code to return system vrefnum, moved to SysEnvirons
; - changed trap number to $A1AD
; <2.1> 4/20/89 CCH Added equate for virtual RAM size.
; <2.0> 4/16/89 CCH Took out a debugger statement.
; <1.9> 4/16/89 CCH Wrote initialization routine in assembly, merged patch
; initialization code into this file, and changed Gestalt equates
; to new naming convention.
; <1.8> 4/3/89 CCH Added international keyboards to keyboard info.
; <1.7> 3/30/89 CCH Took out all functionality except for basic _Gestalt function.
; <1.6> 3/24/89 CCH Now pushes 4 bytes on the stack for shorts when calling C
; functions.
; <1.5> 3/16/89 CCH Re-did selector dispatcher. Thanks, Gary!
; <1.4> 3/16/89 CCH Moved global data in from GestaltEqu.a.
; <1.3> 3/6/89 CCH Uppercased GestaltTrap and changed MMU code to use new equates.
; <1.2> 3/3/89 CCH Added assembly versions of Atalk driver code, and sys refnum
; code.
; <1.1> 2/22/89 CCH Started using global ptr in ExpandMem.
; <1.0> 2/21/89 CCH Adding to EASE for the first time.
; 2/14/89 CCH New Today.
;
TITLE 'Gestalt'
CASE OBJ
PRINT OFF
LOAD 'StandardEqu.d'
INCLUDE 'HardwarePrivateEqu.a'
INCLUDE 'UniversalEqu.a'
INCLUDE 'SANEMacs881.a'
INCLUDE 'MMUEqu.a'
INCLUDE 'GestaltEqu.a'
INCLUDE 'GestaltPrivateEqu.a'
include 'InternalOnlyEqu.a'
INCLUDE 'EDiskEqu.a'
INCLUDE 'BootEqu.a'
INCLUDE 'Devices.a'
PRINT ON
;;; Gestalt private equates
GestaltTrapID EQU $A1AD ; Gestalt trap number
NewGestaltTrapID EQU $A3AD ; newGestalt trap number
ReplaceGestaltTrapID EQU $A5AD ; ReplaceGestalt trap number
HighestProc EQU $7fffffff
LongEntrySz EQU 8 ; size of an entry in table
RomVersionOffset EQU 8 ; offset from base of ROM to ROM version word
AUXVersion EQU $110 ; version 1.1 is default
addFlag EQU 0 ; flag to add a code
replaceFlag EQU 1 ; flag to replace a code
VIA2Base EQU $50f02000 ; via 2 base on all pre-universal ROM machines <2.9>
UnimplementedTrap EQU $A89F ; unimplemented trap
PMgrOpTrap EQU $A085 ; power manager trap
UserDelayTrap EQU $A84C ; user delay trap <17>
VMGlobals EQU $B78 ; Pointer to VM's globals <5>
************************************************************************
* purpose: entry point for the Gestalt function
*
* on entry: d0 = selector
* a0 = gestalt function (add,replace)
* on exit: a0 = result (gestalt)
* a0 = old gestalt function (replace)
* d0 = error code
*
************************************************************************
GESTALTTRAP FUNC EXPORT
IMPORT newGestalt
EXPORT INITGESTALT
cmp.w #GestaltTrapID,d1 ; Gestalt?
beq.s @getGestalt ; yup
move.l a0,-(sp) ; space for oldProc (preserves a0 otherwise)
move.l sp,-(sp) ; put address of scratch space on stack
move.l a0,-(sp) ; put gestalt function ptr on stack
move.l d0,-(sp) ; put selector on stack
tst.l 12(SP) ; Is the Proc/Var ptr nil? <5>
beq.s @err ; -> Yes, bail out <5>
cmp.w #NewGestaltTrapID,d1 ; NewGestalt?
beq.s @newGestalt ; yup
cmp.w #ReplaceGestaltTrapID,d1 ; ReplaceGestalt?
bne.s @err ; nope, oh oh
move.l #replaceFlag,-(sp) ; push replace flag
bra.s @callNew
@newGestalt move.l #addFlag,-(sp) ; push add flag
@callNew jsr newGestalt ; call newGestalt
add.l #16,sp ; clean up stack
move.l (sp)+,a0 ; return oldProc or original a0
bra.s @takeOff
@getGestalt movem.l a2-a4/d3-d7,-(sp) ; save registers
Jsr getGestalt ; go get an entry
movem.l (sp)+,a2-a4/d3-d7 ; restore regs
Bra.s @takeOff ; branch
@err add.l #16,sp ; clean up stack
Move.l #paramErr,D0
@takeOff Rts
************************************************************************
*
* function: getGestalt( selector, result )
* long selector;
* long *result;
*
* entry: d0.l = function code
*
* exit: a0.l = result
* d0.w = error code
*
* destroys: d0-d3/a0-a1
*
************************************************************************
getGestalt
WITH GestaltGlobals, ExpandMemRec
IMPORT findLong
move.l d0,d3 ; save selector
subq.l #4,sp ; clear space for index
move.l sp,-(sp) ; put ptr to it on stack
move.l d0,-(sp) ; put code to find on stack
jsr findLong ; try to find it
addq.l #8,sp ; get rid of parameters
move.l (sp)+,d2 ; get index into d2
tst.w d0 ; did we find the code?
beq.s undefErr ; nope, exit
move.l ExpandMem,a0 ; get expandmem ptr
move.l emGestalt(a0),a1 ; get gestalt global ptr
move.l TableH(a1),a0 ; get table handle
move.l (a0),a1 ; get ptr to table
lsl.l #3,d2 ; turn index into offset
move.l 4(a1,d2.l),a1 ; get proc ptr
; call the gestalt function to determine the result
clr.l -(sp) ; space for result to be stored
clr.w -(sp) ; space for error code
move.l d3,-(sp) ; selector
pea 6(sp) ; address of space to store result
jsr (a1) ; call the function
move.w (sp)+,d0 ; get error code into d0
move.l (sp)+,a0 ; return result in a0
bra.s exit ; see ya..
undefErr move.l #gestaltUndefSelectorErr,d0 ; fall through
exit rts
************************************************************************
*
* Built-in codes
*
* Gestalt Function Description:
*
* pascal OSErr GestaltProc( longint selector, var longint result )
*
************************************************************************
GestaltProcParms RECORD 0,INCREMENT
returnAddr DS.L 1
resultPtr DS.L 1
selector DS.L 1
error DS.W 1
ENDR
WITH GestaltProcParms, ExpandMemRec, GestaltGlobals, ProductInfo
************************************************************************
* System Version
************************************************************************
getSysVersion move.l 4(sp),a0
clr.l d0 ; clear result register <2.9>
Move.w SysVersion,d0 ; save system version in lsw of result
bra stdResult ; save result and exit <2.9>
************************************************************************
* ROM Version
************************************************************************
getRomVersion move.l 4(sp),a0
Move.l RomBase,A1 ; get base of ROM
clr.l d0 ; clear result register <2.9>
move.w RomVersionOffset(a1),d0 ; put version in lsw of result
bra stdResult ; save result and exit <2.9>
************************************************************************
* A/UX Version
************************************************************************
getAuxVersion Btst #hwCbAUX-8,HWCfgFlags ; check for A/UX -- if bit set, A/UX is running (-8 because
; equates for HwCfgFlags are based on 16-bit word)
Beq stdUnknown ; if not running, give an error <2.9>
clr.l d0 ; clear result register <2.9>
move.w #AUXVersion,d0 ; blob in default a/ux version (no better way, yet)
bra stdResult ; save result and exit <2.9>
************************************************************************
* Machine Type
************************************************************************
getMachineType Move.l ExpandMem,A1 ; find out where expandMem is
Move.l emGestalt(A1),A1 ; get global ptr
clr.l d0 ; clear result register <2.9>
Move.w machType(A1),d0 ; put machineType in lsw of result
bra stdResult ; save result and exit <2.9>
************************************************************************
* Processor Type
************************************************************************
getProcessor moveq.l #0,d0 ; clear d0
Move.b CPUFlag,D0 ; get processor type
Addq #1,D0 ; adjust to make it the correct result #
bra stdResult ; save result and exit <2.9>
************************************************************************
* Keyboard Type
* Note: To add new keyboards, simply add types to table before EOT.
************************************************************************
getKeyboard Move.b KbdType,D0 ; get keyboard type
Lea keyBdTable,A0 ; get table into A0
move.l a0,a1 ; save a copy
keyBdLoop Move.b (A0)+,D1 ; get an entry from table
Beq stdUnknown ; if we get to the end, unknown keyboard <2.9>
Cmp.b D0,D1 ; does our keyboard match this entry?
Bne.s keyBdLoop ; yep, we found it
keyBdFound Sub.l A1,A0 ; get the index into the table
Move.l A0,D0 ; get ready to store the result
keyBdDone bra stdResult ; save result and exit <2.9>
keyBdTable DC.B $03 ; Macintosh Keyboard
DC.B $13 ; Macintosh keyboard & keypad
DC.B $0B ; Mac Plus Keyboard
DC.B $02 ; Apple Extended Keyboard
DC.B $01 ; Standard Apple Keyboard
DC.B $06 ; Standard Portable ADB Keyboard
DC.B $07 ; Portable ISO ADB Keyboard
DC.B $04 ; Standard ISO ADB Keyboard
DC.B $05 ; Extended ISO ADB Keyboard
DC.B $08 ; Elmer ADB Keyboard
DC.B $09 ; Elmer ISO ADB Keyboard
DC.B $0C ; Tim/Asahi ADB Keyboard
DC.B $0D ; Tim/Asahi ISO ADB Keyboard
DC.B $00 ; EOT
************************************************************************
* FPU Type
************************************************************************
getFPUType Move.l ExpandMem,A1 ; find out where expandMem is
Move.l emGestalt(A1),A1 ; get global ptr
clr.l d0 ; clear result register
Move.b fpu(A1),d0 ; put fpu type in lsb of result
bra stdResult ; save result and exit
************************************************************************
* MMU Type
************************************************************************
getMMUType Move.l ExpandMem,A1 ; find out where expandMem is
Move.l emGestalt(A1),A1 ; get global ptr
clr.l d0 ; clear result register
Move.b mmu(A1),d0 ; put mmu type in lsb of result
bra stdResult ; save result and exit
************************************************************************
* parity attributes
************************************************************************
getParityStatus Move.l ExpandMem,A1 ; find out where expandMem is
Move.l emGestalt(A1),A1 ; get global ptr
Move.l parityStatus(A1),d0 ; put parity status into result
bra stdResult ; save result and exit
************************************************************************
* miscellaneous attributes
************************************************************************
getMisc clr.l d3 ; clear result
move.l ROMBase,A0 ; Get ROMBase
move.w ROMHeader.MachineNumber(A0),D1
lea bootGlobROMs,A0 ; Point to the table of bootGlobbed ROM Sigs
@cleanROMloop cmp.w (a0)+,d1
beq.s @hasBootGlobs
tst.w (a0)
bne.s @cleanROMloop
bra.s @noBootGlobs
@hasBootGlobs bset #gestaltBootGlobals,d3 ; we have boot globals
@noBootGlobs
move.w #UnimplementedTrap,d0
_GetTrapAddress ,newTool
move.l a0,d2
move.l #UserDelayTrap,d0
_GetTrapAddress ,newTool
cmp.l a0,d2
beq.s @noUserDelay
@userDelay bset #gestaltScrollingThrottle,d3
@noUserDelay
@squareMenus move.b NTSC,d0 ; get a copy of the NTSC byte <17>
andi.b #$0F,d0 ; only look at bottom nibble <17>
bne.s @next ; if it's non-zero, menus aren't square <17>
bset #gestaltSquareMenuBar,d3 ; otherwise, it is! <17>
@next move.l d3,d0 ; put result into d0 <17>
bra stdResult ; save result and exit
; ROMs that have bootglobs
bootGlobROMs
dc.w $067C ; IIci ROM
dc.w 0 ; eot
************************************************************************
* Logical Page Size
************************************************************************
DefaultPageSize EQU $8000 ; default page size = 32k
EmulatorPageSize EQU $1000 ; emulator page size = 4k
getPageSize
IF hasMMU or (not ForRom) THEN ; <2.9>
clr.l d0 ; clear result <18>
cmpi.b #cpu68040,CPUFlag ; are we on an 040? <18>
bne.s @1 ; IF we are on an 040 <18>
MACHINE MC68040 ; <18>
movec tc,d1 ; get tc <18>
btst #14,d1 ; are we in 8k page mode? <18>
bne.s @0 ; if so, skip this <18>
bset #12,d0 ; if not, set page size to 4k <18>
bra.s @saveResult ; take off <18>
@0
bset #13,d0 ; set page size to 8k <18>
bra.s @saveResult ; <18>
MACHINE MC68030
@1
cmpi.b #2,CPUFlag ; are we on at least an 020?
blt @noPages ; oh well, no page size <2.9>
cmpi.b #PMMU851,MMUType ; do we have some kind of real mmu?
blt.s @normalSize ; nope, use default page size
Move.l ExpandMem,A0 ; find out where expandMem is
Move.l emGestalt(A0),A0 ; get global ptr
lea myScratch(A0),a0 ; get address of scratch area
pmove tc,(a0) ; get a copy of the TC
bfextu (a0){8,4},d1 ; get # addr bits for pageSize <2.8>
bset d1,d0 ; get our pagesize <2.8>
bra.s @saveResult ; done!
@normalSize Move.l #DefaultPageSize,D0 ; use default pagesize
@saveResult bra stdResult ; save result and exit <2.9>
ENDIF ; <2.9>
@noPages
bra stdUnknown ; there are no pages to have sizes <2.9>
************************************************************************
* Low Memory Size
************************************************************************
getLowMemSize move.l SysZone,d0 ; system zone starts at top of low-mem
bra stdResult ; save result and exit <2.9>
************************************************************************
* RAM Size
************************************************************************
getRAMSize
Move.l ExpandMem,A1 ; find out where expandMem is
Move.l emGestalt(A1),A1 ; get global ptr
cmp.l #gestaltLogicalRAMSize,selector(sp) ; asking for logical size?
bne.s @physicalSize ; nope, physical size
Move.l realTop(A1),d0 ; store adjusted amount of RAM in d0 <2.9>
bra.s @gotMemSize ; go store the info
@physicalSize Move.l memSize(A1),d0 ; store amount of RAM in d0
@gotMemSize bra stdResult ; save result and exit <2.9>
************************************************************************
* ROM Size
************************************************************************
MachCount EQU 14
getROMSize move.l RomBase,a0 ; get base of ROM <3.3>
IF not ForRom THEN ; <2.9>
cmp.b #3,ROMHeader.MachineNumber(a0) ; >= 3 knows size <3.3>
bcc.s romKnows ; size is in header, use that for response <3.3>
Move.l ExpandMem,A0 ; otherwise, get expandMem pointer
Move.l emGestalt(A0),A0 ; get global ptr
Move.w machType(A0),D1 ; get machineType
cmp.w #gestaltMacSE,d1 ; SE or later? <3.3>
bcs.s smallROM ; nope, has to be 128k <3.3>
move.l #$40000,d0 ; otherwise, 256k if no size in ROM header <3.3>
bra.s machExit ; return result <3.3>
smallROM move.l #$20000,d0 ; for Mac Plus and 512ke (puny) <3.3>
bra.s machExit ; return result <3.3>
ENDIF ; <2.9>
romKnows move.l ROMHeader.RomSize(a0),d0 ; get size of the ROM <3.3>
machExit bra stdResult ; save result and exit <2.9>
************************************************************************
* OS trap table base
************************************************************************
getOSTable ; <22>
move.l #$00000400, d0 ; this is the same on all machines <22>
bra stdResult ; <22>
************************************************************************
* Toolbox trap table base
************************************************************************
getToolboxTable ; <22>
move.l RomBase, a0 ; get base of the rom... duh... <22>
cmp.w #$0075, ROMHeader.MachineNumber(a0) ; are we on a MacPlus? <22>
bne.s @notPlus ; <22>
move.l #$00000C00, d0 ; this is only different on MacPlus <22>
bra stdResult ; <22>
@notPlus ; <22>
move.l #$00000E00, d0 ; this is where it goes on everything else <22>
bra stdResult ; <22>
************************************************************************
* Extended Toolbox trap table base
************************************************************************
getExtToolboxTable ; <22>
move.l RomBase, a0 ; get base of the rom... duh... <22>
cmp.w #$0075, ROMHeader.MachineNumber(a0) ; are we on a MacPlus? <22>
beq.s @plusOrSE ; yes, return the table base address <22>
cmp.w #$0276, ROMHeader.MachineNumber(a0) ; are we on an SE? <22>
bne stdUnknown ; not MacPlus or SE, we take the fifth <22>
@plusOrSE ; <22>
move.l XToolTable, d0 ; get the table base from the vector... <22>
bra stdResult ; <22>
************************************************************************
* Extended File System dispatching flags
************************************************************************
getFSAttr ; <26>
moveq #0, d0 ; <26>
move.w # \ ; <32>
(1<<gestaltFullExtFSDispatching) | \ ; <32>
(1<<gestaltHasFSSpecCalls) | \ ; <32>
(0<<gestaltHasFileSystemManager) \ ; <32>
, d0 ; <32>
bra stdResult ; <26>
; <26>
************************************************************************
* QD Version
************************************************************************
qdVersion
IF not ForRom THEN ; <2.9>
cmp.w #$3fff,Rom85 ; do we have color quickdraw?
bgt.s @noCQD ; nope..
Move.w #UnimplementedTrap,D0 ; get loc of unimplemented trap
_GetTrapAddress ,newTool ; get the address into A0
Move.l A0,D2 ; save it for a sec
Move.l #$AB03,D0 ; trap ID to check for 32-bit QD
_GetTrapAddress ,newTool ; get the address of it
Move.l #gestalt8BitQD,D0 ; assume 8-bit CQD
Cmp.l A0,D2 ; is it unimplemented?
Bne.s @fullCQD ; Yep..
bra.s qdDone
ENDIF ; <2.9>
;
; We dont make ROMs without Color QuickDraw any more, so we dont need the <36>
; second part of this conditional. (And this code is always here for the <36>
; RAM version of the selector.) <36>
;
IF (not ForRom) THEN ; <2.9>
@noCQD move.l #gestaltOriginalQD,d0 ; original qd, fall through
bra.s qdDone
ENDIF ; <2.9>
@fullCQD
subq #4,sp ; leave room for result <31>
_OffScreenVersion ; use offscreen version + $100 <31>
move.l (sp)+,d0 ; <31>
add.w #$100, d0
qdDone bra stdResult ; save result and exit <2.9>
************************************************************************
* AppleTalk Driver Version Number
************************************************************************
getATalkVersion
;Is the B serial port in use?
Clr.l D0 ; assume it's not installed
Tst.b PortBUse ; if so, this will be positive.
Bmi.s ATalkVersDone ; oops - not in use, I thought so, return 0
;Port B is in use. Is it in use by AppleTalk?
Move.b SPConfig,D1 ; get port configuration info
And.b #$0F,D1 ; mask off to Port B info only
Cmp.b #useATalk,D1 ; is it AppleTalk?
Bne.s ATalkVersDone ; nope, return 0
;Port B is in use by AppleTalk. Get the DCE pointer
Move.l ABusDCE,A0 ; get .MPP's DCE pointer
Move.b DCtlQueue+1(A0),D0 ; put version number in D0
ATalkVersDone bra stdResult ; save result and exit <2.9>
************************************************************************
* Power Manager
************************************************************************
noPMgrMask EQU (0<<gestaltPMgrExists)|\ ; power manager doesn't exist
(0<<gestaltPMgrCPUIdle)|\ ; can't put SCC into idle mode
(0<<gestaltPMgrSCC)|\ ; can't put CPU into idle mode
(0<<gestaltPMgrSound) ; can't put ADB into idle mode
portablePMgrMask EQU (1<<gestaltPMgrExists)|\ ; power manager exists
(1<<gestaltPMgrCPUIdle)|\ ; can put SCC into idle mode
(1<<gestaltPMgrSCC)|\ ; can put CPU into idle mode
(1<<gestaltPMgrSound) ; can idle sound hardware
PowerMgr
IF hasPwrControls|PwrMgrADB|hasPwrMgrClock OR (not ForRom) THEN ; <2.9>
Move.l ExpandMem,A0 ; find out where expandMem is
Move.l emGestalt(A0),A0 ; get global ptr
cmp.w #gestaltPortable,machType(A0) ; must be portable or later to have pmgr
blt.s @noPmgr ; save time..
Move.w #UnimplementedTrap,D0 ; get loc of unimplemented trap
_GetTrapAddress ,newTool ; get the address into A0
Move.l A0,D2 ; save addr
Move.l #PMgrOpTrap,D0 ; trap ID to check for power manager
_GetTrapAddress ,newOS ; get the address of it
Cmp.l A0,D2 ; is it unimplemented?
Beq.s @noPmgr ; Yep..
Move.l #portablePMgrMask,d0 ; the mask for the current power mgr
bra.s pMgrDone
ENDIF ; <2.9>
@noPmgr Move.l #noPMgrMask,D0 ; assume non-existent
pMgrDone bra stdResult ; save the result and exit <2.9>
************************************************************************
* Addressing mode attributes
************************************************************************
getAddrMode clr.l d0 ; clear result <3.1>
IF NOT ForROM THEN ; <3.1>
btst #hwCbAUX-8,HWCfgFlags ; check for A/UX <12>
bne.s cleanROM ; a/ux uses IIci memory manager <12>
move.l RomBase,a0 ; get ptr to base of ROM <3.1>
move.w 8(a0),d1 ; get ROM version <3.1>
lea cleanROMs,a0 ; point to table of 32-bit clean ROMs <3.1>
cleanROMloop cmp.w (a0)+,d1 ; is this a clean ROM? <3.1>
beq.s cleanROM ; "ajax was here" <3.1>
tst.w (a0) ; any more to check? <3.1>
bne.s cleanROMloop ; if so, go check <3.1>
cmp.w #$0178, D1 ; Mac-II class machine? <41>
bne stdResult ; if not, Scruffy cant be here <41>
cmp.l #$00002000, SysZone ; is Scruffy running? <41>
beq.s cleanROM ; if so, were now 32-bit clean <41>
bra stdResult ; what a dirty old ROM <3.1>
ENDIF ; <3.1>
cleanROM move.b SystemInfo,d0 ; get status byte into d1 <2.9>
not.b d0 ; invert status bits so we can use them
and.l #3,d0 ; only want bit 0 and bit 1
bset #gestalt32BitCapable,d0 ; return that machine is 32-bit clean <3.1>
bra stdResult ; save result and exit <2.9>
universalROMs
cleanROMs dc.w $067C ; IIci ROM <PN>
dc.w 0 ; eot <3.1>
************************************************************************
* Time Manager type (stolen from Gary's ERS)
************************************************************************
getTimeMgrType suba.w #tmQSize,sp ; allocate a TMTask
movea.l sp,a0 ; pointer to task for time manager traps
clr.l TMCount(a0) ; avoid bug in standard time mgr
move.w #$ffff,QType(a0) ; set all bits of QType
_InsTime ; install the task
moveq.l #1,d1 ; assume version is standard version
move.b QType(a0),d0 ; should be unchanged for std time mgr
bmi.s @remove ; if still negative, must be std time mgr
addq.l #1,d1 ; assume version is revised version
add.b d0,d0 ; next highest bit unchanged
bmi.s @remove ; will be cleared on extended version
addq.l #1,d1 ; version must be extended version
@remove _RmvTime ; didn't even have to start the timer!
adda.w #tmQSize,sp ; restore stack pointer
move.l d1,d0 ; put result into d0 <2.9>
bra stdResult ; save result and exit <2.9>
************************************************************************
* VM Info
************************************************************************
VMInfo clr.l d0 ; VM installs itself, otherwise off <3.3>
bra stdResult ; save result and exit <2.9>
************************************************************************
* Notification Manager <9>
************************************************************************
notification clr.l d0 ; clear result
bset #gestaltNotificationPresent,d0 ; Notification Manager now always exists
@noNMgr bra stdResult ; save result and exit
************************************************************************
* Serial attributes <23>
************************************************************************
getSerialAttr
movea.l ExpandMem,a0 ; get ptr to expandmem rec
movea.l emGestalt(a0),a0 ; get gestalt global ptr
moveq.l #0,d0 ; assume no GPI connections
cmpi.w #gestaltMacPlus,machType(a0)
beq.s @toStdResult
cmpi.w #gestaltMacClassic,machType(a0)
beq.s @toStdResult
cmpi.w #gestaltMacLC,machType(a0) ; <24>
beq.s @toStdResult
cmpi.w #gestaltMacLCII,machType(a0) ; <SM5> CSS <42>
beq.s @toStdResult ; <SM5> CSS <42>
; all other machines have GPI connected
moveq.l #(1<<gestaltHasGPIaToDCDa)|\ ; GPIa connected to DCDa
(1<<gestaltHasGPIaToRTxCa)|\ ; GPIa connected to RTxCa clock input)
(1<<gestaltHasGPIbToDCDb),d0 ; GPIb connected to DCDb
@toStdResult bra stdResult
************************************************************************
* get slot info <2.9>
************************************************************************
getSlotInfo
IF not ForRom THEN ;
movea.l ExpandMem,a0 ; get ptr to expandmem rec
movea.l emGestalt(a0),a0 ; get gestalt global ptr
cmpi.w #gestaltMacIIci,machType(a0) ; Mac IIci is first universal ROM
blt getMachSpecific ; if so, don't use this routine
cmpi.w #gestaltMacClassic,machType(a0) ; no universal tables on XO either
beq getMachSpecific ;
cmpi.w #gestaltPowerBook100,machType(a0) ; no universal tables on Asahi either <40>
beq getMachSpecific ;
ENDIF ;
IF hasSlotMgr or (not ForRom) THEN ;
WITH NuBusInfo
movea.l UnivInfoPtr,a0 ; get universal info ptr
adda.l NuBusInfoPtr(a0),a0 ; add in offset to NuBus info
clr.l d0 ; clear index
clr.l d1 ; clear bitmap of NuBus connectors <23>
@slotLoop btst #hasConnector,(a0,d0.w) ; does this slot have a connector?
beq.s @next ; if not, go look at next slot
bset.l d0,d1 ; note that this slot has a NuBus connector <23>
@next addq #1,d0 ; bump up to next slot
cmpi.l #gestaltMaxNuBusSlots,d0 ; have we gone through all slots? <LW6>
bne.s @slotLoop ; if not, keep going
move.l d1,d0 ; return the bitmap of NuBus connectors <23>
bra stdResult ; return the info
ENDWITH
ELSE
bra stdUnknown ; by here, there are no slots with connectors
ENDIF
*************************************************************************
* hardware attributes ••• This code assumes a universal ROM!!! •••
* ••• It cannot be used in the System file!! •••
*************************************************************************
getHardwareAttr
movea.l ExpandMem,a0 ; get ptr to expandmem rec
movea.l emGestalt(a0),a0 ; get gestalt global ptr
cmpi.w #gestaltMacIIci,machType(a0) ; must use tables for pre Mac IIci machines
blt getMachSpecific ; if so, don't use this routine
cmpi.w #gestaltMacClassic,machType(a0) ; no universal tables on XO either <3.3>
beq getMachSpecific ; <3.3>
cmpi.w #gestaltPowerBook100,machType(a0); no universal tables on Asahi either <6><40>
beq getMachSpecific ; <6>
clr.l d0 ; clear result
lea AttrTable,a0 ; get gestalt->universal mapping table
move.l AddrMapFlags,d1 ; get universal info attributes
@attrLoop move.b (a0)+,d2 ; get gestalt attribute bit number
bmi @loopDone ; if negative, we're done
move.b (a0)+,d3 ; get universal attribute bit number
btst d3,d1 ; is attribute set for this machine?
beq.s @attrLoop ; if not, check next bit
bset d2,d0 ; set bit is gestalt result
bra.s @attrLoop ; check next bit
@loopDone move.l UnivROMFlags,d1 ; get external feature bits
btst #PGCInstalled,d1 ; check if a parity chip exists
beq.s @PGCDone ; if not, return d0 as is
bset #gestaltHasPGC,d0 ; otherwise, set PGC exists bit
@PGCDone
btst #v8ChipBit,d1 ; check if a VISA chip exists <27>
beq.s @visaDone ; if not, return d0 as is
bset #gestaltHasVisa,d0 ; otherwise, set Visa exists bit
@visaDone
move.l #gestaltHasSCCIOP,d1 ; bit number to test for SCC IOP <12>
btst d1,d0 ; do we have one? <12>
beq.s @HasSoftPowerOff ; if not, don't check for bypass mode <12>
btst #0,SCCIOPFlag ; are we in bypass mode? <12>
beq.s @HasSoftPowerOff ; IF in Bypass Mode <12>
move.l #gestaltHasSCC,d1 ; get SCC exists bit <12>
bset d1,d0 ; set SCC exists bit in result <12>
; ENDIF <12>
;Roll in NewGestaltSelectors from GestaltPatches.a <SM2> <PN>
@HasSoftPowerOff
; Check for HardPower/SoftPower supplies (please dont use boxflag) <SM39>
move.l RomBase,a0
cmp.w #$67C,ROMHeader.MachineNumber(a0)
bne.s @noSoftPowerOff
move.l #gestaltHasUniversalROM,d1 ; Get the Gestalt bit for SoftpowerOff
bset d1,d0 ; Say we gots SoftPowerOff
@noSoftPowerOff
bra stdResult ; return the result in d0
WITH DecoderInfo
AttrTable dc.b gestaltHasVIA1,VIA1Exists
dc.b gestaltHasSCC,SCCRdExists
dc.b gestaltHasIWM,IWMExists
dc.b gestaltHasPWM,PWMExists
dc.b gestaltHasSoundBuffer,SoundExists
dc.b gestaltHasSCSI,SCSIExists
dc.b gestaltHasVIA2,VIA2Exists
dc.b gestaltHasASC,ASCExists
dc.b gestaltHasRBV,RBVExists
dc.b gestaltHasVDAC,VDACExists
dc.b gestaltHasSCSIDMA,SCSIDMAExists
dc.b gestaltHasSWIMIOP,SWIMIOPExists
dc.b gestaltHasSCCIOP,SCCIOPExists
dc.b gestaltHasOSS,OSSExists
dc.b gestaltHasFMC,FMCExists
dc.b gestaltHasRPU,RPUExists
dc.b gestaltHasOrwell,OrwellExists
dc.b gestaltHasJaws,JAWSExists ;<2>
dc.b gestaltHasSonic,SonicExists ;<2>
dc.b gestaltHasSCSI961,SCSI96_1Exists ;<2>
dc.b gestaltHasSCSI962,SCSI96_2Exists ;<2>
dc.b gestaltHasDAFB,DAFBExists ;<2>
dc.b -1,-1
ENDWITH
************************************************************************
* machine-specific selectors
************************************************************************
IF (1 OR ForRom) THEN ; <2.9>
getMachSpecific lea Selectors,a0 ; get address of selector table
clr.l d1 ; use d1 as second index
@selectLoop move.l (a0,d1.l),d0 ; selector to check against
cmp.l selector(sp),d0 ; is it for this selector?
beq.s @foundIt ; yep
tst.l d0 ; is it the end?
beq stdUnknown ; oh,oh.. <2.9>
addq.l #4,d1 ; bump up index
bra.s @selectLoop ; selector loop
@foundIt Move.l ExpandMem,A0 ; find out where expandMem is
Move.l emGestalt(A0),A0 ; get global ptr
Move.w machType(A0),D0 ; get machineType
cmp.w InfoMax,d0 ; greater than max?
bls.s @inTable ; nope, it's in the table <3.3>
cmp.w #gestaltMacClassic,d0 ; is it an XO? <3.3>
bne.s @nextSpecial ; no, maybe an Asahi <2.9><6>
lea MacXO,a0 ; an XO is a special case <17>
bra.s @skipIndex ; because it's boxflag is so high <17>
@nextSpecial cmp.w #gestaltPowerBook100,d0 ; is it an Asahi? <6><40>
bne stdUnknown ; whoops <6>
lea MacAsahi,a0 ; an Asahi is also a special case <6>
bra.s @skipIndex ; because it's boxflag is so high <6>
@inTable subq.l #1,d0 ; machines start at 1, table at 0
lsl.w #2,d0 ; we're indexing into longs
mulu.w SelectorMax,d0 ; times number of longs per machine
lea InfoTable,a0 ; get base of table
adda.w d0,a0 ; point at info for this machine
@skipIndex move.l (a0,d1.l),d0 ; get result <17>
cmp.l #-1,d0 ; a -1 means unknown <2.9>
beq stdUnknown ; return an error <2.9>
bra stdResult ; save it and exit <2.9>
;------
; selectors in table
;------
SelectorMax dc.w (SelEnd-Selectors)/4
Selectors
dc.l gestaltHardwareAttr ; hardware attributes <10>
dc.l gestaltNuBusConnectors ; bitmap of NuBus connectors <23>
SelEnd dc.l 0 ; EOT
SelectorCount EQU (SelEnd-Selectors)/4 ; number of selectors
;------
; table by machine
;
; NOTE: An entry of -1 will cause a gestaltUnknownErr to be returned.
;------
InfoMax dc.w ((InfoEnd-InfoTable)/4)/(SelectorCount) ; max number of machines
InfoTable ; <10>
Old128 dc.l \ ; gestaltHardwareAttr
(1<<gestaltHasVIA1)|\ ; has a via 1
(1<<gestaltHasSCC)|\ ; has an scc
(1<<gestaltHasPWM)|\ ; has a PWM buffer <2.9>
(1<<gestaltHasSoundBuffer)|\ ; has a sound buffer in RAM <2.9>
(1<<gestaltNeedsRESET) ; needs a hard RESET <33>
dc.l 0 ; gestaltNuBusConnectors (no slots) <23>
MacXL dc.l \ ; gestaltHardwareAttr
(1<<gestaltHasVIA1)|\ ; has a via 1
(1<<gestaltHasSCC)|\ ; has an scc
(1<<gestaltNeedsRESET) ; needs a hard RESET <33>
dc.l 0 ; gestaltNuBusConnectors (no slots) <23>
Ke512 dc.l \ ; gestaltHardwareAttr
(1<<gestaltHasVIA1)|\ ; has a via 1
(1<<gestaltHasSCC)|\ ; has an scc
(1<<gestaltNeedsRESET) ; needs a hard RESET <33>
dc.l 0 ; gestaltNuBusConnectors (no slots) <23>
MacPlus dc.l \ ; gestaltHardwareAttr
(1<<gestaltHasVIA1)|\ ; has a via 1
(1<<gestaltHasSCC)|\ ; has an scc
(1<<gestaltHasIWM)|\ ; has an IWM chip <2.9>
(1<<gestaltHasPWM)|\ ; has a PWM buffer <2.9>
(1<<gestaltHasSoundBuffer)|\ ; has a sound buffer in RAM <2.9>
(1<<gestaltHasSCSI)|\ ; has SCSI <2.9>
(1<<gestaltNeedsRESET) ; needs a hard RESET <33>
dc.l 0 ; gestaltNuBusConnectors (no slots) <23>
MacSE dc.l \ ; gestaltHardwareAttr
(1<<gestaltHasVIA1)|\ ; has a via 1
(1<<gestaltHasSCC)|\ ; has an scc
(1<<gestaltHasIWM)|\ ; has an IWM chip <2.9>
(1<<gestaltHasPWM)|\ ; has a PWM buffer <2.9>
(1<<gestaltHasSoundBuffer)|\ ; has a sound buffer in RAM <2.9>
(1<<gestaltHasSCSI)|\ ; has SCSI <2.9>
(1<<gestaltNeedsRESET) ; needs a hard RESET <33>
dc.l 0 ; gestaltNuBusConnectors (no slots) <23>
MacII dc.l \ ; gestaltHardwareAttr
(1<<gestaltHasVIA1)|\ ; has a via 1
(1<<gestaltHasVIA2)|\ ; has a via 2
(1<<gestaltHasASC)|\ ; has an asc
(1<<gestaltHasSCC)|\ ; has an scc
(1<<gestaltHasIWM)|\ ; has an IWM chip <2.9>
(1<<gestaltHasSCSI) ; has SCSI <2.9>
dc.l $00007E00 ; gestaltNuBusConnectors (9-E) <23>
MacIIx dc.l \ ; gestaltHardwareAttr
(1<<gestaltHasVIA1)|\ ; has a via 1
(1<<gestaltHasVIA2)|\ ; has a via 2
(1<<gestaltHasASC)|\ ; has an asc
(1<<gestaltHasSCC)|\ ; has an scc
(1<<gestaltHasIWM)|\ ; has an IWM chip <2.9>
(1<<gestaltHasSCSI) ; has SCSI <2.9>
dc.l $00007E00 ; gestaltNuBusConnectors (9-E) <23>
MacIIcx dc.l \ ; gestaltHardwareAttr
(1<<gestaltHasVIA1)|\ ; has a via 1
(1<<gestaltHasVIA2)|\ ; has a via 2
(1<<gestaltHasASC)|\ ; has an asc
(1<<gestaltHasSCC)|\ ; has an scc
(1<<gestaltHasIWM)|\ ; has an IWM chip <2.9>
(1<<gestaltHasSCSI) ; has SCSI <2.9>
dc.l $00000E00 ; gestaltNuBusConnectors (9-B) <23>
MacSE30 dc.l \ ; gestaltHardwareAttr
(1<<gestaltHasVIA1)|\ ; has a via 1
(1<<gestaltHasVIA2)|\ ; has a via 2
(1<<gestaltHasASC)|\ ; has an asc
(1<<gestaltHasSCC)|\ ; has an scc
(1<<gestaltHasIWM)|\ ; has an IWM chip <2.9>
(1<<gestaltHasSCSI) ; has SCSI <2.9>
dc.l 0 ; gestaltNuBusConnectors (no slots) <23>
Portable dc.l \ ; gestaltHardwareAttr
(1<<gestaltHasVIA1)|\ ; has a via 1
(1<<gestaltHasASC)|\ ; has an asc
(1<<gestaltHasSCC)|\ ; has an scc
(1<<gestaltHasIWM)|\ ; has an IWM chip <2.9>
(1<<gestaltHasSCSI) ; has SCSI <2.9>
dc.l 0 ; gestaltNuBusConnectors (no slots) <23>
InfoEnd
MacXO dc.l \ ; gestaltHardwareAttr <17>
(1<<gestaltHasVIA1)|\ ; has a via 1
(1<<gestaltHasSCC)|\ ; has an scc
(1<<gestaltHasIWM)|\ ; has an IWM chip
(1<<gestaltHasPWM)|\ ; has a PWM buffer
(1<<gestaltHasSoundBuffer)|\ ; has a sound buffer in RAM
(1<<gestaltHasSCSI)|\ ; has SCSI
(1<<gestaltNeedsRESET) ; needs a hard RESET <33>
dc.l 0 ; gestaltNuBusConnectors (no slots) <23>
MacAsahi dc.l \ ; gestaltHardwareAttr <6>
(1<<gestaltHasVIA1)|\ ; has a via 1 <6>
(1<<gestaltHasASC)|\ ; has an asc <6>
(1<<gestaltHasSCC)|\ ; has an scc <6>
(1<<gestaltHasIWM)|\ ; has an IWM chip <6>
(1<<gestaltHasSCSI) ; has SCSI <6>
dc.l 0 ; gestaltNuBusConnectors (no slots) <6>
ENDIF ; <2.9>
************************************************************************
* Internal
************************************************************************
Internal move.l selector(sp),d0 ; get selector into d0
cmp.l #gestaltVersion,d0 ; return gestalt version
beq.s @version
cmp.l #gestaltLongHandle,d0 ; return table handle
beq.s @tableHdl
cmp.l #13,d0
beq.s @bbm
cmp.l #7,d0
bne.s stdUnknown ; undefined code
move.l #'carl',d0 ; signature
bra.s stdResult ; <3.0>
@bbm move.l #'bbmc',d0 ; signature
bra.s stdResult ; <3.0>
@version move.l #gestaltVers,d0 ; return version number
bra.s stdResult ; <3.0>
@tableHdl move.l ExpandMem,a0 ; get expandmem ptr
move.l emGestalt(a0),a1 ; get gestalt global ptr
move.l TableH(a1),d0 ; get table handle
bra.s stdResult ; save result and exit
************************************************************************
* Common Gestalt Function Return Code <2.9>
************************************************************************
stdUnknown move.w #gestaltUnknownErr,error(sp) ; return gestaltUnknownErr
bra.s stdExit
stdResult move.l resultPtr(sp),a0 ; get ptr to place result
move.l d0,(a0) ; return value in d0
noError move.w #noErr,error(sp) ; return noErr
stdExit move.l (sp)+,a0 ; get return address off stack
addq.l #8,sp ; clean up stack
jmp (a0) ; return
ENDWITH
; ***************************************************************************
; ***************************************************************************
; *** END OF GESTALT FUNCTIONS
; ***************************************************************************
; ***************************************************************************
IF (NOT ForRom) THEN
; **************************** EntryTable Macro ****************************
Macro
EntryTable &entryPt, &trapID
If (&entryPt <> '0') Then
Import Start
DC.L &entryPt-Start
DC.W &trapID
Else
DC.L 0
EndIf
EndM
; ***************************************************************************
; *** CUT-BACK POINT
; ***************************************************************************
CutBackPt EntryTable GESTALTTRAP,GestaltTrapID
EntryTable 0 ; <=== Last table entry
; ***************************************************************************
; *** INITIALIZATION CODE FOR PATCH
; ***************************************************************************
EXPORT BootInit
BootInit
BSR INITGESTALT ; Initialize Gestalt
Lea CutBackPt,A0 ; <=== Keep these two lines…
Rts ; <=== in any case
ENDIF ; if (NOT ForROM)
;---------------------------------------------------------
; Gestalt initialization routine
;
; Initializes Gestalt. Allocates space for globals and for proc ptr
; table in system heap. Also initializes proc ptrs for built-in
; functions.
;---------------------------------------------------------
MACRO
Selector &code, &addr
dc.l &code ; gestalt selector
dc.l &addr-SelectorTable ; offset of routine
ENDM
INITGESTALT
WITH GestaltGlobals,ExpandMemRec
move.l #GestaltRecSize,d0 ; size of globals
_NewPtr Sys,Clear ; get some space
move.l a0,d0 ; did we get the space?
beq memError ; whoops...
move.l ExpandMem,a1 ; get ptr to expandmem area
move.l a0,emGestalt(a1) ; save our global ptr
move.l a0,a2 ; keep it in a2
moveq #LongEntrySz,d0 ; size of long entry
_NewHandle Sys ; get block for proc ptr table
move.l a0,TableH(a2) ; did we get it?
beq memError ; whoops..
move.l (a0),a1 ; dereference the handle
move.l #HighestProc,(a1) ; the highest function code
move.l #$12345678,4(a1) ; a neat number for debugging
move.l #1,slotsUsed(a2) ; there's one entry in the table
;------
; Add predefined selectors
;------
lea SelectorTable,a3 ; get address of selector table
moveq #0,d3 ; clear counter
addLoop tst.l (a3,d3) ; end of table?
beq.s initGlobals ; yup, see ya..
move.l 4(a3,d3),d0 ; get offset of routine
add.l a3,d0 ; convert to an address
move.l d0,-(sp) ; push address of gestalt function
move.l (a3,d3),-(sp) ; push selector of gestalt function
move.l #addFlag,-(sp) ; specify that we are _adding_ a code
jsr newGestalt ; add it.
lea 12(sp),sp ; get rid of stack parameters
addq.l #8,d3 ; bump to next entry in table
bra.s addLoop ; do it again...
;------
; Put Gestalt into the trap table
; We assume that no interrupt routines will call Gestalt to get any of
;------
;------
; Initialize gestalt global values
;------
initGlobals move.l MemTop,D2 ; Get the current Logical RAM size <5>
bsr.s GetEDiskSize ; Get the EDisk size in bytes in D0 <5>
add.l D0,D2 ; add it to the LRAM size. <5>
@SaveLRAM move.l D2,realTop(a2) ; Save Logical RAM size <2.9>
move.l RomBase,A0 ; Check the ROM
cmp.w #$67C,8(A0) ; Is this a 32 bit clean (i.e. IIci) ROM?
bne.s @not32bitClean ; -> Nope. Use Memtop for Log & Phys
move.l RealMemTop,D2 ; On IIci ROM get Logical from RealMem <11>
add.l D0,D2 ; Add in size of RAM disk to logical <11>
move.l D2,realTop(a2) ; Save the adjusted Logical size <11>
move.l PhysMemTop,memSize(A2) ; Get Physical RAM size <1>
bra.s @CheckForVM ; -> See if we need to redo these #s <1>
@not32bitClean move.l MemTop,memSize(a2) ; save Physical memory size
@CheckForVM move.l VMGlobals,D0 ; Get the Ptr to VM's globals <6>
beq.s @MachineType ; -> No VM <6>
bmi.s @MachineType ; -> No VM <6>
move.l D0,A1 ; Get VM globals Ptr <6>
IF NOT forROM THEN
move.l RomBase,A0 ; Check the ROM
cmp.w #$67C,8(A0) ; Is this a 32 bit clean (i.e. IIci) ROM?
beq.s @GetLogical ; -> Yes The Phys size is already correct <6>
moveq #-5,D0 ; GetPhysicalBytes
_MemoryDispatch ; Ask VM how much Physical RAM is in the machine
move.l D0,memSize(A2) ; Store the result
ENDIF
@GetLogical moveq #-6,D0 ; GetLogicalSize
_MemoryDispatch ; Ask VM how much logical RAM we have
move.l D0,D2 ; Save the reuslt in D2
bsr.s GetEDiskSize ; Get the EDisk size in bytes in D0 <6>
add.l D2,D0 ; Add in the size of the EDisk (if any) <6>
move.l D0,realTop(A2) ; Save Logical size in Gestalt's GLobs <6>
@MachineType jsr findMachType ; what kind of machine is this?
move.w d0,machType(a2) ; save it, since it won't change
jsr findFPUType ; what kind of FPU do we have?
move.b d0,fpu(a2)
jsr findMMUType ; what kind of MMU do we have?
move.b d0,mmu(a2)
jsr findParityStatus ; do we have parity, and is it on?
move.l d0,parityStatus(a2)
bra done
;---------------------------------------------------
; GetEDiskSize
;
; Exit:
; D0 - Size in bytes
;---------------------------------------------------
GetEDiskSize
movem.l a1/a2/d2,-(sp)
move.l RomBase,a0
cmp.w #$37A,ROMHeader.MachineNumber(a0) ; Portable
beq.s @returnZero
lea DrvQHdr+QHead-QLink,a0
@dqloop move.l (a0),d0
beq.s @returnZero
move.l d0,a0
move.w dQDrive(a0),d1
move.w dQRefNum(a0),d0
move.w d0,d2
add.w #1,d0
neg.w d0
asl.w #2,d0
move.l UTableBase,a1
move.l (a1,d0),a1
move.l (a1),a1
btst #dRAMBased,dCtlFlags+1(a1)
beq.s @romBased
move.l (a1),a1
@romBased move.l (a1),a1
lea drvrName(a1),a1
lea @dotEDisk,a2
clr.l d0
move.b (a2),d0
@cmploop cmp.b (a2)+,(a1)+
bne.s @dqloop
dbra d0,@cmploop
lea -CntrlParam.size(sp),sp
move.l sp,a0
clr.l CntrlParam.ioCompletion(a0)
clr.w CntrlParam.ioVRefNum(a0)
move.w d2,CntrlParam.ioCRefNum(a0)
move.w d1,CntrlParam.ioVRefNum(a0)
move.w #drvSizeCode,CntrlParam.csCode(a0)
_Status ,immed
move.l CntrlParam.csParam(a0),d0
lea CntrlParam.size(sp),sp
bra.s @return
@returnZero clr.l d0
@return movem.l (sp)+,a1/a2/d2
rts
STRING AsIs
@dotEDisk dc.b 6, '.EDisk', 0
;-----
; Table of built-in Gestalt selectors
;
; Selector Routine Description
; -------- ------- -----------
;-----
SelectorTable Selector gestaltMachineType, getMachineType ; machine type
Selector gestaltSystemVersion, getSysVersion ; system version
Selector gestaltProcessorType, getProcessor ; processor type
Selector gestaltKeyboardType, getKeyboard ; keyboard type
Selector gestaltAppleTalkVersion, getATalkVersion ; atalk driver
Selector gestaltFPUType, getFPUType ; fpu type
Selector gestaltMMUType, getMMUType ; mmu type
Selector gestaltPhysicalRAMSize, getRAMSize ; physical ram size
Selector gestaltLogicalRAMSize, getRAMSize ; virtual ram size
Selector gestaltQuickdrawVersion, qdVersion ; qd version
Selector gestaltROMSize, getROMSize ; ROM size
Selector gestaltVMAttr, VMInfo ; return VM Info
Selector gestaltPowerMgrAttr, PowerMgr ; power mgr attrs
Selector gestaltROMVersion, getRomVersion ; get ROM version
Selector gestaltVersion, Internal ; version of gestalt
Selector gestaltLongHandle, Internal ; handle to table of longs
Selector gestaltHardwareAttr, getHardwareAttr ; hardware attributes
Selector gestaltNuBusConnectors, getSlotInfo ; NuBus connector bitmap <23>
Selector gestaltTimeMgrVersion, getTimeMgrType ; time mgr version
Selector gestaltAddressingModeAttr, getAddrMode ; addressing mode
Selector gestaltAUXVersion, getAuxVersion ; a/ux version
Selector gestaltLogicalPageSize, getPageSize ; logical page size
Selector gestaltLowMemorySize, getLowMemSize ; low-mem size
Selector gestaltParityAttr, getParityStatus ; parity attributes
Selector gestaltMiscAttr, getMisc ; misc attributes
Selector gestaltNotificationMgrAttr, notification ; nmgr attributes
Selector gestaltSerialAttr, getSerialAttr ; serial attributes
Selector gestaltOSTable, getOSTable ; base of the OS trap table
Selector gestaltToolboxTable, getToolboxTable ; base of the toolbox trap table
Selector gestaltExtToolboxTable, getExtToolboxTable ; base of the ext. toolbox trap table
Selector gestaltFSAttr, getFSAttr ; return file system attributes
Selector 13, Internal ; special
Selector 7, Internal ; special
Selector 0, 0 ; EOT
done move.w #noErr,D0 ; return noErr
initExit rts
memError move.w #memFullErr,d0 ; tell caller what went wrong
bra.s initExit
;---------------------------------------------------------
; findMachType
;
; Determines machine type.
;
; Entry: nothing
;
; Exit: d0.l = machine type
;
; Trashes d0,a0
;---------------------------------------------------------
findMachType
move.l RomBase,a0 ; get ptr to base of ROM
move.b 8(a0),d0 ; get ROM's 'machine ID'
bgt.s @noClass ; IF its a 'classic' (machine ID = 0)
move.l #gestaltMac512KE,d0 ; assume its a 512ke
tst.w HwCfgFlags ; check if SCSI present (high bit 1?)
bpl.s @doneVers ; IF it has SCSI
move.l #gestaltMacPlus,d0 ; its a MacPlus
bra.s @doneVers ; ENDIF
@noClass ; ELSE
moveq #0,d0 ; clear a register
move.b BoxFlag,d0 ; get our RAM based machine ID
addq.b #6,d0 ; make it Gestalt based (must use '.b' so that $FF
; .becomes $000, not $100!)
@doneVers ; ENDIF
rts ; seeee ya...
;---------------------------------------------------------
; findFPUType
;
; Figures out what type of FPU is installed, if any
;
; Entry: nothing
;
; Exit: d0.l = fpu type
;
; Trashes d0,a0
;---------------------------------------------------------
findFPUType
IF (CPU >= 20) or (not ForRom) THEN ; <19>
Btst #hwCbFPU-8,HWCfgFlags ; check for FPU -- if bit set, we have FPU (-8 'cuz
; equates for HwCfgFlags are based on 16-bit word)
Beq.s @noFPU ; we have one, now figure out which one
cmp.b #cpu68040,CPUFlag ; are we on a 68040? <19>
bne.s @notAn040 ; IF we are on an 040 THEN <19>
move.l #gestalt68040FPU,d0 ; we know what kind of FPU it has <19>
bra.s @fpuExit ; ENDIF <19>
@notAn040 Move.l SP,A0 ; get base of (soon to be) FPU state frame
FNop ; synchronize FPU with us
FSave -(SP) ; get an "idle" state frame
Move.w (SP),D0 ; get format word for this state frame
Move.l A0,SP ; restore stack pointer
Cmp.w #$1f18,D0 ; an 881?
Beq.s @M68881
Cmp.w #$3f18,D0 ; this also indicates an 881
Beq.s @M68881
Cmp.w #$3f38,D0 ; how 'bout an 882?
Beq.s @M68882
Cmp.w #$1f38,D0 ; this is also an 882
Beq.s @M68882
move.l #0,d0 ; assume no FPU <3>
bra.s @fpuExit
@M68881 Move.l #gestalt68881,D0 ; we have an 881
Bra.s @fpuExit
@M68882 Move.l #gestalt68882,D0 ; we have an 882
Bra.s @fpuExit
ENDIF ;
@noFPU Move.l #gestaltNoFPU,D0 ; no FPU installed
@fpuExit rts ; return
;---------------------------------------------------------
; findMMUType
;
; Figures out what type of MMU is present, if any
;
; Entry: nothing
;
; Exit: d0.l = mmu type
;
; Trashes d0,a0
;---------------------------------------------------------
findMMUType
IF not ForRom THEN ;
Move.l ExpandMem,A0 ; find out where expandMem is
Move.l emGestalt(A0),A0 ; get global ptr
Cmp.w #gestaltMacSE,machType(A0) ; should we bother to find out?
Blt.s @noMMU ; nothing before SE can have one (yes)
ENDIF
IF hasMMU or (not ForRom) THEN ;
Moveq #0,D0 ; start clean
Move.b MMUType,D0 ; get MMU
cmp.b #HMMU,d0 ; is it an AMU?
beq.s @MMUDone ; then we're done
cmp.b #PMMU851,d0 ; then make sure there is one at all
Blt.s @noMMU ; no mmu
Subq #1,D0 ; convert to right format
Bra.s @MMUDone ; go return result
ENDIF ;
@noMMU Move.l #gestaltNoMMU,D0 ; tell the user we don't have one
@MMUDone rts ; exit
;---------------------------------------------------------
; findParityStatus
;
; Figures out if there is a parity chip on board, and
; if so, if there is parity RAM installed.
;
; Entry: nothing
;
; Exit: d0.l = parity status
;
; Trashes a0/a1/a3/a4/d0-d4
;---------------------------------------------------------
WITH DecoderInfo, ProductInfo
MACHINE MC68030
findParityStatus
IF (not ForRom) THEN ; <36> We only build universal ROMs now.
clr.l d0 ; clear result
movea.l ExpandMem,a0 ; get ptr to expandmem rec
movea.l emGestalt(a0),a0 ; get gestalt global ptr
cmpi.w #gestaltMacIIci,machType(a0) ; Mac IIci is first parity machine
blt @parityExit ; if before ci, definitely no parity
cmpi.w #gestaltMacClassic,machType(a0) ; XO's machine number screws everything up
beq @parityExit ; if on XO, definitely no parity
cmpi.w #gestaltPowerBook100,machType(a0) ; Asahi's machine number screws everything up <40>
beq @parityExit ; if on Asahi, definitely no parity
move.l UnivROMFlags,d1 ; get external feature bits
btst #PGCInstalled,d1 ; check if a parity chip exists
bne.s @checkPGC ; yep, go see if parity is enabled
move.l AddrMapFlags,d1 ; get universal info attributes
btst #RPUExists,d1 ; do we have an RPU chip?
bne.s @checkRPU ; then go check RPU
bra @parityExit ; if not, return zero as result
; checkPGC - check the parity VIA bit to see if it is enabled.
@checkPGC move.l VIA,a0 ; load up Via base address
btst #6,VBufB(a0) ; check if parity enabled
beq @parityOn ; if clear, parity is enabled
bra @parityOff ; otherwise, it's off
; checkRPU - First set RPU to generate bad parity, then access all four SIMMs in
; both banks by accessing location 0 and the last longword in memory.
; Parity is only fully active if all four SIMMs generate a parity interrupt.
; trashes a0/a1/a3/a4/d1-d4
@checkRPU movec cacr,d3 ; get contents of cache
move.l d3,-(sp) ; save them
move.l #$1111,d3 ; enable caches with bursting <13>
movec d3,cacr ; write into cache register <13>
move.l RomBase,a0 ; point to base of rom <13>
move.l #$2000,d3 ; cache size/long = 32k/4 = 8k <13>
@fillLoop tst.l (a0)+ ; load a long <13>
dbra d3,@fillLoop ; keep doing it for 8k <13>
move.l #$0808,d3 ; clear data and inst cache
movec d3,cacr ; write into cache register
move.l UnivInfoPtr,a0 ; get pointer to universal information
add.l (a0),a0 ; point to decoderInfo record
move.l RPUAddr(a0),a1 ; get RPU base address
move.l sp,d3 ; save our stack pointer
move.l AutoInt7,d4 ; save NMI vector
lea @parityInt,a4 ; address to return to from parity intrpt
lea @nmiHandler,a0 ; get address of our NMI handler
move #$2700,sr ; turn all interrupts off
move.l a0,AutoInt7 ; point vector to our handler
moveq #0,a3 ; check first bank (0 is in first bank)
@checkBank moveq #4-1,d2 ; check all four SIMMs
move.l (a3),d1 ; get contents of longword
@nextByte clr.l (a3) ; write a long with correct parity <14>
st.b rpuReset(a1) ; reset serial ptr
st.b (a1) ; write wrong parity mode
clr.b (a3,d2.w) ; write one SIMM with bad parity
tst.l (a3) ; parity error if it's a parity SIMM
nop ; wait for an interrupt
nop
st.b rpuReset(a1) ; sync up RPU serial line
clr.b (a1) ; write good parity mode
move.l d1,(a3) ; restore contents of longword
move #$2000,sr ; turn interrupts back on
move.l d4,AutoInt7 ; restore NMI vector
move.l (sp)+,d3 ; get original state of cache <8>
movec d3,cacr ; restore original state of cache <8>
bra.s @parityOff ; if we get here, it's a non-parity SIMM
@parityInt st.b rpuReset(a1) ; sync up RPU serial line
clr.b (a1) ; write good parity mode
dbra d2,@nextByte ; go check next SIMM
@allParityBank move.l d1,(a3) ; restore contents of longword
move.l a3,d1 ; did we just check location 0?
bne.s @restoreNMI ; if not, we're done and parity is on
movea.l ExpandMem,a0 ; get ptr to expandmem rec
movea.l emGestalt(a0),a0 ; get gestalt global ptr
movea.l memSize(a0),a3 ; total amount of memory
subq #4,a3 ; point to last longword in memory
bra.s @checkBank ; go check bank B
@restoreNMI move #$2000,sr ; turn interrupts back on
move.l d4,AutoInt7 ; restore NMI vector
move.l (sp)+,d3 ; get original state of cache <8>
movec d3,cacr ; restore original state of cache <8>
bra.s @parityOn ; go return that parity is on
; Interrupt handler for checkRPU routine. It is assumed that the NMI button is
; not pressed during this routine.
; d3 = stack pointer of routine
; a1 = RPU base address
; a4 = return address
@nmiHandler st.b rpuReset(a1) ; reset serial ptr
clr.b (a1) ; write good parity mode
st.b (a1) ; clear the parity error
move.l d3,sp ; restore the stack pointer
jmp (a4) ; return to the checkRPU routine
@parityOn bset #gestaltParityEnabled,d0 ; by here it is
@parityOff bset #gestaltHasParityCapability,d0 ; set parity capability bit
ELSE ; (not ForRom) OR isUniversal
@parityUnknown clr.l d0 ; set everything to zero
ENDIF
@parityExit rts
ENDWITH
END.