; ; Hacks to match MacOS (most recent first): ; ; 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): ; ; 5/19/92 CS Integrated changes from Reality: ; <42> 4/9/92 JSM #1026795,: 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 Don’t 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 doesn’t 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< (1< (0< , 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 don’t make ROMs without Color QuickDraw any more, so we don’t 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< 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 can’t be here <41> cmp.l #$00002000, SysZone ; is Scruffy running? <41> beq.s cleanROM ; if so, we’re 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 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) ; CSS <42> beq.s @toStdResult ; CSS <42> ; all other machines have GPI connected moveq.l #(1< ************************************************************************ 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? 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 @HasSoftPowerOff ; Check for HardPower/SoftPower supplies (please dont use boxflag) 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< (1< (1< dc.l 0 ; gestaltNuBusConnectors (no slots) <23> MacXL dc.l \ ; gestaltHardwareAttr (1< dc.l 0 ; gestaltNuBusConnectors (no slots) <23> Ke512 dc.l \ ; gestaltHardwareAttr (1< dc.l 0 ; gestaltNuBusConnectors (no slots) <23> MacPlus dc.l \ ; gestaltHardwareAttr (1< (1< (1< (1< (1< dc.l 0 ; gestaltNuBusConnectors (no slots) <23> MacSE dc.l \ ; gestaltHardwareAttr (1< (1< (1< (1< (1< dc.l 0 ; gestaltNuBusConnectors (no slots) <23> MacII dc.l \ ; gestaltHardwareAttr (1< (1< dc.l $00007E00 ; gestaltNuBusConnectors (9-E) <23> MacIIx dc.l \ ; gestaltHardwareAttr (1< (1< dc.l $00007E00 ; gestaltNuBusConnectors (9-E) <23> MacIIcx dc.l \ ; gestaltHardwareAttr (1< (1< dc.l $00000E00 ; gestaltNuBusConnectors (9-B) <23> MacSE30 dc.l \ ; gestaltHardwareAttr (1< (1< dc.l 0 ; gestaltNuBusConnectors (no slots) <23> Portable dc.l \ ; gestaltHardwareAttr (1< (1< dc.l 0 ; gestaltNuBusConnectors (no slots) <23> InfoEnd MacXO dc.l \ ; gestaltHardwareAttr <17> (1< dc.l 0 ; gestaltNuBusConnectors (no slots) <23> MacAsahi dc.l \ ; gestaltHardwareAttr <6> (1< (1< (1< (1< (1< 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.