; ; 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): ; ; 11/19/93 chp When testing for hasEnhancedLTalk, always use ProductInfo flags. ; Remove Cyclone/Tempest boxFlag checks. ; 11/8/93 SAM Roll in from mc900ftjesus. ; 11/8/93 SAM Updated TestForEmu to correctly adjust the logical RAM size when ; an EDisk is present. ; 10/28/93 SAM Roll in from mc900ftjesus. ; 10/28/93 SAM Changed getNativeCPUType to put the PowerPC cpus in the $100 ; range. ; 10/10/93 SAM Roll in from mc900ftjesus. ; 10/10/93 SAM Added a universal check for hasEnhancedLTalk in gestaltHardware. ; 8/12/93 BG Converted references to gestaltCyclone40 to gestaltQuadra840AV. ; 8/7/93 SAM Removed temporary fix to LRAM size made in . ; 8/4/93 JDR Integrate Sound Manager 3.0 project. ; 7/20/93 SAM Added a macro for setting the assembler machine directive to the ; appropriate thing (based on the build time flag "CPU"). ; 6/29/93 SAM Removed all references to gEDiskSize cuz its not needed. The ; lram value is updated to include the Edisk at initalization (as ; it was in 7.0.1). This still doesnt cover the case of VM ; loading after gestalt (a gibbly fix for PDM is a temporary ; solution). Cyclone this is broken in your ROM. ; 6/14/93 SAM Added a test for the hasHardPower bit in Universal info so we no ; longer have to use boxflags for the shutdown dialog crap. ; 6/14/93 kc Roll in Ludwig. ; 6/3/93 SAM Updated that stupid list of boxflags in hassoftpoweroff to ; reflect the new PDM boxflags. ; 5/21/93 CSS Set bits in gestaltFontAttr to indicate settings for double byte ; support. ; 4/23/93 SAM Added the temporary PDMEvt2 boxflag to the brain-dead list of ; boxflag based cmp/bne for hassoftpoweroff. ; 4/11/93 chp Added a selector to return the HAL type for the runtime CPU. ; This just returns an encoded resource ID from ProductInfo. Also ; added the AppleTalk interrupt level selector from Cyclone. ; 4/8/93 KW changed gestaltids for cyclone/tempest products when determining ; if enhanced localtalk is present. ; 4/8/93 CSS Use gestalt global for edisk size as the boot globals get hosed ; by VM. ; 4/5/93 jb Added TestFor AwacsExists in GetSoundHardware. ; 3/30/93 CSS Add EDisk size to logical RAM size in gestaltLogicalRAMSize. ; Before SuperMario, VM was inited before Gestalt. Now this has ; changed. The Gestalt expandmem var realTop(An) used to be fixed ; by Gestalt by taking VM version of RealMemTop and adding the ; Edisk size. Because of how thing are in SuperMario, VM doesn't ; get to affect realTop(An), therefore rather than returning that ; variable, we return RealMemTop (which is the one that VM ; changed). However, for About this Macintosh… to work correctly ; (and show the RAM disk as part of the System Software), we need ; to add the RAM disk size whenever we return RealMemTop. ; 2/20/93 SAM Updated all the EMMU stuff. MMU page size, emulator present, ; sys architecture, all updated. Fixed up the Universal ROM ; check. ; 02/10/93 HY Remove change. We no longer need the gestaltNoAppleTalk bit. ; 2/5/93 SAM Added support for Emulated page size. ; 2/5/93 SAM Updated the System architecture selector to use universal info. ; 01/11/93 HY Added code into getMisc for setting gestaltNoAtlkSupport bit. ; If this bit is set then this machines DOESN'T support AppleTalk. ; 1/10/93 RC Soft Power Off now works correctly for PDM ; 12/13/92 SAM Added gestaltNativeCPUtype and gestaltSysArchitecture. Restored ; universal code in the hdwr selector. Cleaned things up. ; 12/4/92 fau Added gestaltTempest33 to soft-power off. Added all ; Cyclone-type machines to say they have enhanced localtalk -- ; this should not be box-flag based. I'll get to it soon. ; 11/13/92 mal Added MACE Ethernet to hardware attributes gestalt. ; 11/11/92 RB The Mac LC II does not have Soft Power Off. ; 11/11/92 fau Changed soundhardware to check for the 'DSPExists' feature flag. ; This means that a DSP is installed and used for sound. Made ; tempest not have a soft power off flag. ; 11/9/92 fau Made gestaltSoundHardware return 'dsp ' for a Tempest. Rolled ; back change in so the Text-to-speech guys fix it. ; 11/6/92 FU Made Cyclone/Tempest return ASC for hardware attributes -- will ; back this as soon as a name-revision is done. This will work ; around a Text-to-speech bug. ; 11/3/92 RB (Murali) Under SM, return RealMemTop instead of the cached ; realTop in the gestalt globals. Gestalt was loaded before VM ; did, and so realMemTop may have changed by VM, so always use the ; real thing. ; 10/27/92 fau Forgot to change a label to actually execute the ; enhancedlocaltalk code. ; 10/27/92 fau Added a gestaltHasEnhancedLtalk check to hardwareAttr to enable ; the bit on Cyclone and Tempest. ; 9/3/92 PN Nuke the check for IIci because this is SuperMario. ; 8/20/92 CS Fix another problem with BootGlobs changing to StartGlobals per ; roll-in from Reality. ; 8/17/92 CCH Change getHardwareAttr to not use OrwellExists bit since it was ; removed. ; 7/24/92 RLM change GetEDiskSize, now uses BootGlobs, this removes the ; requirement to have drivres installed before Gestalt ; 7/20/92 CSS Names of the sound hardware attributes have changed because they were moved ; from GestaltEqu.a to GestaltEquPriv.a by JDR. ; 7/14/92 RB Added a function to return the gestaltSoundHardware attributes. ; 7/1/92 RB Added the selectors for the gestalt script manager attributes. ; The script Mgr function for gestalt is in ScripMgrExtensions.a ; 5/19/92 CS Integrated changes from Reality: ; <42> 4/9/92 JSM #1026795,: gestaltSerialAttr should be the same for a Mac ; LC II as a Mac LC. ; 4/30/92 SES Rolled in a fix of the parity check routine from PatchIIciROM.a. ; Removed check for bootglobs - all ROMs now have bootglobs, so no ; need to check. ; 4/28/92 PN Fix OutlineFont Gestalt so that getFontMgrAtr returns the ; correct result ; 4/22/92 PN Roll in hasSoftPowerOff to hardware attribute. Add GetOSTable, ; GetToolboxTable, GetExtToolboxTable, GetFSAttr into ROM build. ; Roll in GetQDFeatures and GestaltFontMgrAttr from ; GestaltPatches.a and BassPatches.a. ; <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' PRINT ON MACRO SETMACHINE IF CPU = 020 THEN MACHINE MC68020 ELSEIF CPU = 030 THEN MACHINE MC68030 ELSEIF CPU = 040 THEN MACHINE MC68040 ELSE AERROR 'Unknown CPU type' ENDIF ENDM SETMACHINE ;;; 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 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 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> ************************************************************************ * System Architecture ************************************************************************ getSysArchitecture ; If we're running (68k code) and Emu is installed ; for now, assume Architecture is PPC. MOVE.L ExpandMem,A1 ; find out where expandMem is MOVE.L emGestalt(A1),A1 ; get global ptr TST.B Emu68k(A1) ; Do the globals say we have an emulator? BEQ.S @MC68k ; -> Nope, ol' slow boy. @PowerPC MOVEQ #gestaltPowerPC,D0 ; Emulator is running. Signal PowerPC architecture BRA stdResult ; -> Return @MC68k MOVEQ #gestalt68k,D0 ; Emu is off. Assume 68k BRA stdResult ; -> Return IsEmuInstalled TestFor has68kEmulator RTS ; On Exit z set = PowerPC, clear = 68k ************************************************************************ * Native Processor Type ************************************************************************ getNativeCPUtype MOVE.L ExpandMem,A1 ; find out where expandMem is MOVE.L emGestalt(A1),A1 ; get global ptr TST.B Emu68k(A1) ; Do the globals say we have an emulator? BEQ.S @MC68k ; -> Nope, ol' slow boy. MOVEQ.L #0,D0 ; Clear out D0 MOVE.B nativeCPU(A1),D0 ; Get the PowerPC processor type ADD.W #$100,D0 ; Bump the PowerPC CPU type into the $100 range BRA stdResult ; -> Return @MC68k MOVE.B CPUFlag,D0 ; Return CPU flag BRA stdResult ************************************************************************ * 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 IF not forROM THEN move.l ROMBase,A0 ; Get ROMBase lea universalROMs,A1 ; Point to the table of Clean/Univeral ROM Sigs move.w (A1)+,D1 ; Get a ROM id (list is null terminated) beq.s @checkMemCtrlr ; -> End of table means not universal (huh) cmp.w D1,ROMHeader.MachineNumber(A0) ; Check a table entry beq.s @userDelay ; -> Yep, set the hasBootGLobs ROM bit ENDIF bset #gestaltBootGlobals,d3 ; we have boot globals @userDelay bset #gestaltScrollingThrottle,d3 ; <17> @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 ; ; Removed ROM version compare - all ROMs now have bootglobs ************************************************************************ * 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? blo @noPages ; oh well, no page size <2.9> cmpi.b #PMMU851,MMUType ; do we have some kind of real mmu? blo.s @normalSize ; nope, use default page size Move.l ExpandMem,A0 ; find out where expandMem is Move.l emGestalt(A0),A0 ; get global ptr tst.b emu68k(A0) ; Do the globals say we have a 68k Emulator? bne.s @GetEmuPageSize ; -> Yes, get the saved page size 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! @GetEmuPageSize Move.l nativePageSize(A0),D0 ; Grab the NanoKernel's page size bra.s @saveResult ; save result and exit @normalSize Move.l #DefaultPageSize,D0 ; use default pagesize @saveResult bra stdResult ; save result and exit <2.9> SETMACHINE ; 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> IF ForRom THEN ; <22> ************************************************************************ * 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> ************************************************************************ * Quickdraw feature flags ;<14> ************************************************************************ getQuickdrawFeatures moveq #0, d0 ; <26> move.l # \ ; ;<14> (1< ;<14> (1< ;<14> (1< ;<14> (1< ;<14> , d0 ; bra stdResult ; <26> ************************************************************************ * FontManager Attribute ;<14> ************************************************************************ IF hasSplineFonts THEN getFontMgrAttr move.l #(1 << gestaltOutlineFonts) | \ (1 << gestaltPartialFonts) | \ (1 << gestaltDiskCachedFonts) \ , d0 ; CSS bra stdResult ; <26> ENDIF ENDIF ; IF ForRom <22> ************************************************************************ * 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 $077D ; SuperMario ROM 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> ************************************************************************ * Sound Hardware ************************************************************************ GetSoundHardware move.l #gestaltASCSnd,d0 ; default is Apple Sound Chip rb CSS fau TestFor AwacsExists ; Do we have an Awacs audio codec? beq @check4dsp ; nope, try DSP move.l #gestaltAwacsSnd, d0 ; yep, so return the appropriate thing bra stdResult @check4dsp TestFor DSPExists ; Are we using the DSP for sound beq stdResult ; Nope move.l #gestaltDSPSnd,d0 ; set the DSP type bra stdResult ; and exit ************************************************************************ * 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 IF 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) ; must use tables for pre Mac IIci machines blo 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> ENDIF ; 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) IF forROM THEN TestFor hasHardPowerOff ; See if this power supply is cheap, stupid and manual! bne.s @noSoftPowerOff ; -> Has a cheap power switch. ELSE ; movea.l ExpandMem,a0 ; get ptr to expandmem rec movea.l emGestalt(a0),a0 ; get gestalt global ptr cmpi.w #gestaltMacSE30,machType(a0) ; if this is an SE/30, we don’t have soft power-off beq.s @noSoftPowerOff cmpi.w #gestaltMacLC,machType(a0) ; if this is an LC, we don’t have soft power-off beq.s @noSoftPowerOff cmpi.w #gestaltMacLCII,machType(a0) ; if this is an LC II, we don’t have soft power-off rb beq.s @noSoftPowerOff cmpi.w #boxClassicII,machType(a0) ; if this is an Apollo, we don’t have soft power-off <5><22> beq.s @noSoftPowerOff ; cmpi.w #gestaltTempest25,machType(a0) ; if this is a Tempest, we don’t have soft power-off fau beq.s @noSoftPowerOff ; fau cmpi.w #gestaltTempest33,machType(a0) ; if this is a Tempest, we don’t have soft power-off fau beq.s @noSoftPowerOff ; fau ENDIF ; move.l #gestaltHasSoftPowerOff,d1 ; Get the Gestalt bit for SoftpowerOff bset d1,d0 ; Say we gots SoftPowerOff @noSoftPowerOff @IsUniversal IF not forROM THEN bsr.s IsROMUniversal ; See if this ROM is universal beq.s @checkMemCtrlr ; -> Nope, skip it ENDIF @HasUniv move.l #gestaltHasUniversalROM,d1 ; Get the Gestalt bit for Univ <6> bset d1,d0 ; Say we gots a Universal ROM! <6> @checkMemCtrlr move.l UnivInfoPtr,a0 ; Get pointer to ProductInfo record cmp.b #DecoderKinds.OrwellDecoder,DecoderKind(a0) ; Do we have an orwell? bne.s @EnhLtalk ; IF we have an Orwell THEN bset #gestaltHasOrwell,d0 ; set the corresponding Gestalt bit @EnhLtalk TestFor hasEnhancedLTalk ; Do we have CURIO LocalTalk enhancements? beq.b @checkMACE ; no, check next feature bset #gestaltHasEnhancedLtalk,d0 ; That’s a big 10-4. @checkMACE TestFor MACEExists ; do we have MACE Ethernet Controller? beq.s @hardwareExit ; no, exit bset #gestaltHasMace,d0 * bra.s @hardwareExit @hardwareExit 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 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 ************************************************************************ * Universal ROM check ************************************************************************ IsROMUniversal IF NOT forROM THEN move.l A1,-(SP) ; Save A1 move.l ROMBase,A0 ; Get ROMBase lea universalROMs,A1 ; Point to the table of Clean/Univeral ROM Sigs @UnivLupe move.w (A1)+,D1 ; Get a ROM id (list is null terminated) beq.s @done ; -> End of table means not universal (huh) cmp.w D1,ROMHeader.MachineNumber(A0) ; Check a table entry bne.s @UnivLupe ; -> Nope, keep looping ELSE moveq #1,D1 ; Yes, set D0 @Done movem.l (SP)+,A1 ; Restore A1 rts ENDIF ************************************************************************ ************************************************************************ * AppleTalk Interrupt Disable Level * - for new machines to supply AppleTalk with the appropriate * interrupt mask, so AppleTalk doesn't default to disabling Level 4 * and below interrupts ($2400). * - initially needed for Cyclone/Tempest * ************************************************************************ GetAtlkIntLevel TestFor MACEExists ; Do we have a MACE Ethernet Controller? Beq stdUnknown ; no, give an error TestFor PSCExists ; Do we have a PSC DMA/Interrupt Controller? Beq stdUnknown ; no, give an error Move.l #$2,d0 ; return interrupt mask level 2 Bra stdResult ; and exit ************************************************************************ * machine-specific selectors ************************************************************************ IF ( 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 bsr.s TestForEmu ; Test for a 68k emulator. Update globals if so. bne.s @MachineType ; -> (hasEmu) Everything is setup. 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> IF NOT forROM THEN bsr.s IsROMUniversal ; Is this a 32 bit clean ROM? beq.s @not32bitClean ; -> Nope. Use Memtop for Log & Phys <1> ENDIF 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> bmi.s @MachineType ; -> No VM <6> move.l D0,A1 ; Get VM globals Ptr <6> IF NOT forROM THEN bsr.s IsROMUniversal ; Is this a 32 bit clean ROM? bne.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 ; uses the value stored in BootGlobs record ; at bgRamDiskSize ; ; Exit: ; D0 - Size in bytes ;--------------------------------------------------- WITH StartGlobals ; RLM CSS GetEDiskSize move.l BootGlobPtr,a0 ; get ptr to boot globals at top of RAM RLM move.l sgRamDiskSize(a0), D0 ; size of ram disk, if any RLM rts ; RLM ENDWITH ; (BootGlobs) RLM ;__________________________________________________________________________________________ SAM ; TestForEmu ; ; Tests for the existence of a 68k emulator. Implies a PowerPC architecture. Get the ; CPU id from the 60x processor and save it in Gestalt's globals. Update Gestalt's ; logical and physical RAM size globals if Emu is running. ; ; Entry: ; A2 - Ptr to Gestalt's Globals ; Exit: ; D0 - Clear if no Emulator. Nothing else touched. ; Set if emulator installed, GestaltGlobals.realTop/memSize/pageSize updated ;——————————————————————————————————————————————————————————————————————————————————————————— With NKSystemInfo, ProcessorInfo TestForEmu MOVE.L Line1111,-(SP) ; Save the F-Line vector PEA @Continue ; Push the addr of our routine MOVE.L (SP)+,Line1111 ; Update the vector MOVE.L SP,D1 ; Save the Stack Ptr case we take an F-Line MOVEQ #0,D0 ; Clear the "has and emulator" flag NOP ; Sync the pipeline _RiscCoprocessorNop ; Either do nothing, or skip the next instructon MOVEQ #1,D0 ; Set the "has a 68k emulator" flag @Continue MOVE.L D1,SP ; Restore the SP (trash the exception frame if we made one) MOVE.L (SP)+,Line1111 ; Restore the Vector NOP ; See above MOVE.B D0,emu68k(A2) ; Save the Result in Gestalt's globals BEQ.S @Done ; -> No, emu. No data page. MOVE.L ProcessorInfoPtr,A3 ; Point to the NanoKernel's Processor Info record MOVE.L PageSize(A3),nativePageSize(A2) ; Save the native page size in Gestalt's globals MOVE.W ProcessorVersionReg(A3),D1 ; Get the PowerPC CPU version MOVE.B D1,nativeCPU(A2) ; Save the native CPU type MOVE.L NKSystemInfoPtr,A3 ; Point to the NanoKernel's System Info record MOVE.L PhysicalMemorySize(A3),D3 ; Get the Physical Memory Size MOVE.L D3,memSize(A2) ; Save it in Gestalt's globals TST.L VMGlobals ; Is VM on? BMI.S @noVM ; -> Nope MOVEQ #-6,D0 ; GetLogicalSize _MemoryDispatch ; Ask VM how much logical RAM we have SUB.L UsableMemorySize(A3),D3 ; Calc ram allocated by the NanoKernel ADD.L D0,D3 ; Add that to VM's logical size. @noVM MOVE.L D3,realTop(A2) ; Save the Logical RAM size @Done RTS EndWith IMPORT GESTALTSCRIPTMGR ; rb IMPORT GetSoundAttributes ; found in SndLowLevel.a ;----- ; 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 gestaltSerialHALType, getSerialHALType ; serial HAL resource ID IF ForRom THEN ; 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 gestaltQuickdrawFeatures, getQuickdrawFeatures ; return ColorQuickdrawfeatures IF hasSplineFonts THEN Selector gestaltFontMgrAttr, getFontMgrAttr ; return true if outline fonts ENDIF Selector gestaltScriptMgrVersion, GESTALTSCRIPTMGR ; Script Manager version number rb Selector gestaltScriptCount, GESTALTSCRIPTMGR ; Script Manger count of scripts rb Selector gestaltSoundAttr, GetSoundAttributes ; get the sound attributes Selector gestaltSoundHardware, GetSoundHardware ; get the sound harwdware chip type rb Selector gestaltAtlkIntLevel, GetAtlkIntLevel ; get cpu's desired appletalk interrupt mask level ENDIF ; <22> Selector gestaltSysArchitecture, getSysArchitecture ; System Architecture Selector gestaltNativeCPUtype, getNativeCPUtype ; Native Processor Type 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? Blo.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 Blo.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 st.b rpuReset(a1) ; sync up RPU serial line clr.b (a1) ; write good parity mode tst.l (a3) ; parity error if it's a parity SIMM nop ; wait for an interrupt nop 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.