; ; File: ShutDownMgr.a ; ; Contains: This file contains the core routines pertaining to the ShutDown trap ; for both the ROM and the System. ; ; ShutDown takes a command parameter and either: ; ; sdInit: 0) initialize the ShutDown queue ; sdPowerOff: 1) turn the power off (or give a dialog on machines without soft power-down) ; sdRestart: 2) restart the machine ; sdInstall: 3) install a ShutDown task in the list ; sdRemove: 4) remove a ShutDown task ; sdUserChoice: 5) notify the user that the machine is going to power off, then turn power off ; sdSoftOff: 6) notify the user that the machine can be ShutDown, or return to Finder ; ; Written by: Donn Denman 8/22/86 ; ; Copyright: © 1992-1993 by Apple Computer, Inc. All rights reserved. ; ; Change History (most recent first): ; ; 11/6/93 SAM Roll from mc900ftjesus. ; 11/6/93 SAM Now handle the restart from the "..safe to switch off..." case ; correctly (ie restore the nanok warmstart). ; 11/6/93 SAM Roll from mc900ftjesus. ; 11/6/93 SAM Changed ClearWarmStart to check for a V0 style emulator and if ; present to clear the emu warmstart flag. ; 10/29/93 CCH Modified KillEDisk to deal with EDisks that don't use checksums. ; 10/11/93 CCH Modified KillEDisk to use new HwPriv parms on PowerPC. ; 9/27/93 SAM Added ClearWarmstart too. ; 9/27/93 SAM Added exports of DoRAMDiskAlert, KillEDisk, FindEDisk, ; ShutRestart, and ShutPower for vectorization. ; 9/25/93 SAM Completely cleaned up this file. Removed tons of shit, bogus ; and sloppy code. Looking more and more like it was in Terror... ; 8/12/93 BG Converted references to gestaltCyclone40 to gestaltQuadra840AV. ; 7/20/93 SAM Removed the Scruffy code from ShutRestart. (we will never be a ; Mac II). ; 7/13/93 RB For the third time, removed checks for 67C ROM. ; 6/14/93 kc Roll in Ludwig. ; 5/27/93 KW Added code in the Shutdown Continue Proc from the ; ShutDownMgrPatches.a from the gibbly to remove the Chassis Sw ; TimeMgr Task if you are running on a Cyclone CPU. The Chassis Ss ; TimeMgr Task is piggybacked onto the emKeyTmTaskPtr ; 5/14/93 KW After calling "DoRAMDiskAlert", if user hit cancel remove the ; tickletimer and send cuda and EnDisPDM command with PDMContinue. ; Fixes some radar bug ; 4/8/93 SAM Added some Supports24bit conds around swapmmu code in ; ClearWarmStart and KillEDisk. ; 3/9/93 jmp Cleaned up the ShutDown/Restart blank-the-screen code so that it ; now works more consistently across all CPUs (i.e., due to the ; fact that various CPUs these days don't tie reset to I/O, the ; desktop could sometimes persist thru bootbeep). ; 01-18-93 jmp Added a TimeMgr-based timeout task that forces the wait-eject ; code to terminate (if it isn’t already done) after 2 seconds. ; This prevents things like stuck disks, etc…, from hanging the ; restart/shutdown sequence. ; 12-17-92 jmp Removed the Wait500ms routine in favor of “wait for floppy ; eject” described in . ; 12-16-92 jmp Added some code that waits until the drive queue has noticed ; that all floppies have been ejected (in DoUnmount) before ; shutting down or restarting. ; 12/9/92 RB Remove (AGAIN) the check for Terror ROMs regarding EDisk. This ; ain't Terror, Also save and restore A5 in BlankScreen so that ; the cursor is not trashed on Macs that don't support soft ; shutdown. ; 11/20/92 FU Removed another tickle cuda call. ; 11/20/92 RB Removed the call to TickleCuda. ; 11/20/92 GS (bg) Updated ShutPower to include the chks for Sonic to issue a ; reset to the Sonic Chip before executing the Shutdown. Removed ; the EnablePDMsgs from ShutInit. Now found in Boot3.a. Added ; the CloseLCDVideo, DockInitSCC routines for the portables. ; 11/3/92 SWC Changed ShutdownEqu.a->Shutdown.a and SlotEqu.a->Slots.a. ; 10/8/92 GS Added a 500ms delay before pulling the power plug in the ; ShutPower routine to help with the async call by New Age to ; eject the floppy. ; 9/28/92 RB Fix the Soft Power Shutdown on the Quadra 900 and 950. ••• WHEN ; UPDATING FROM REALITY OR HORROR, DO NOT MESS WITH SHUTINIT, make ; sure that it still calls EnablePDMsgs, AND that EnablePDMsgs has ; a ble, not bne !!!!! ; 9/3/92 PN Nuke the check for IIci because this is SuperMario. ; 8/19/92 CSS Update from Reality: ; <52> 8/18/92 DTY Change the name of BootGlobs to StartGlobals to avoid confusion ; with BootGlobals, which is used by the boot code in Boot[1-3].a. ; 7/28/92 MR Restart crashes under VM because a switch ; to supervisor mode is done only if ROM is IIci. Now checks for ; SuperMario ; 7/7/92 CSS Update from Reality: ; <51> 6/2/92 JSM #1031451 : Like we do on the PowerBook 140 and 170, close ; the video driver at shutdown or restart for the PowerBook 145. ; <50> 4/9/92 JSM #1026795,: Set CLUT to 50% gray on restart for the LC II as ; well as the LC. ; 7/1/92 RB Do the EDisk check at Shutdown without checking the ROM version ; of Terror, since SuperMArio also has Edisk. Do not call Cuda on ; machines without it. ; 6/26/92 GS ReIncluded ROMBind, InstallProc, and PatchProc Linked Patch ; Macro calls to support CubeE builds. ; 6/23/92 GS Having a problem with the latest set of check-ins. The Header ; format could not be found. Cleaning up header... ; 6/23/92 GS Was a Bad Dog!!!! Re Including the LinkedPatchMacros.a for ; support of Non-SuperMario ROM based machines. ; H/W specific chks in place for Egret chip with Cuda FW. ; Rolled in changes for the Soft Power off support with code from ; Cyclone version of Regatta. This includes chks in the sdSoftOff ; code to chk for Cuda FW in the Egret chip. Removed Linked patch ; macro support. ; 5/16/92 kc Roll in Horror Changes. Include PowerPrivEqu instead of ; ROMPrivateEqu. ; 4/1/92 JSM Roll-in changes from Reality: ; <49> 4/1/92 JSM #1025166,: Roll-in code formerly in the file ; ShutDownRAMDiskPatchINIT.a that puts up a warning dialog if a ; user tries to shutdown with a RAM disk, and make it work for ROM ; builds, too. ; <48> 2/11/92 JSM Moved this file to ShutDownMgr folder, keeping all the old ; revisions; cleanup header. ; <47> 12/4/91 csd #1016450: Added support for Scruffy. If Scruffy is running, we ; turn off the MMU before jumping to the ROM code which does a ; RESET. Otherwise, the RAM-based MMU tables get lost when the ; RESET causes the ROM to overlay RAM. ; <46> 12/2/91 SAM Using official boxflag equates now. ; <45> 10/29/91 SAM Fix comment header. ; <44> 10/29/91 SAM Special case the Macintosh Portable in the Restart code to not ; execute the RESET instruction. ; <43> 10/28/91 SAM/KSM Rolled in Regatta changes. Fixed up the Restart sequence. ; Mike saves my butt. (JMP) Changed the branch case after the ; call to FindEDisk and explicitly set D0 if an EDisk was found. ; Added code to "_Shutdown" poweroff to look for an EDisk and if ; found to clear its checksum data - effectively invalidating the ; disk (no matter how much the RAM persists after a shutdown!) ; Changed register usage of last change from A1 to A0. It was causing ; non Jaws machines to hang at restart ; (HJR) Added new restart sequence for Tim because of some hardware ; limitations. (BG) Universalized the code that decides whether to ; enable PowerDownMsgs. ; (jmp) Added an include for 'InternalOnlyEqu.a' for BoxFlags. ; Modified the DoDrivers routine to not “kiss” the TIM, TIM-LC, ; Spike, and Eclipse video drivers goodbye. Modified the ; ShutRestart & ShutPower routines to turnoff TIM and TIM-LC video ; after all restart procs have been run. ; All $67C machines that are running VM will get switched into ; supervisor mode before jumping to the ROM restart vector. Non ; $67C's never switch to supervisor mode. (bg) Enable Egret ; PowerDown messages on Eclipse. ; <42> 7/10/91 dba end of the forPost70 conditional; we are past 7.0 for good ; <41> 6/12/91 LN added #include 'ROMPrivateEqu.a' ; <40> 6/12/91 LN removed #include 'HardwareEqu.a' ; <39> 6/11/91 gbm dba, dty: change Gestalt call for post-7.0 to check ; hasSoftPowerOff instead of SE/30 machine type; also use new ; “needs RESET” selector; and nuke Regatta conditionals ; <38> 4/2/91 dba use the real _EnterSupervisorMode from Traps.a, instead of ; defining a local constant here ; <37> 4/2/91 SAM Changed the Restart code to put the machine back in Supervisor ; mode (if VM is on) before restarting (in the Regatta build). ; <36> 3/13/91 bbm &dty; I almost got it right last time. I need to make sure that ; the shutdown tasks get executed on machines that have no soft ; poweroff. ; <35> 3/11/91 bbm &CCH; <#31191bbm>; Userchoice automatically did the poweroff ; routines even though we may be doing a restart. This meant we ; did a cold start even though we wanted a warm start. ; <34> 3/4/91 dba dty: get rid of SysVers conditionals ; <33> 1/15/91 stb & dba; fix ROM build by changing JSRROM to JSRROM.FAR ; <32> 1/14/91 stb & PKE; Fix lack-of-port bug in BlankScreen ; <31> 1/8/91 SAM Changed all occurrences of gestaltXO to GestaltMacClassic ; <30> 1/8/91 gbm (dba) use peaResident to avoid losing modules ; <29> 9/25/90 SAM Changed boxElsie/boxErickson to boxMacLC/boxMacIIsi. ; <28> 9/13/90 BG Removed <24>. 040s are behaving more reliably now. ; <27> 8/31/90 CV Moved the code to gray the Elsie screen on shutdown to occur ; after shutdown tasks are executed. ; <26> 8/24/90 SAM Added StripAddress to InitShutDown to lose the HiBits in the ; proc ptr so the CPU doesnt puke on an RTS in 32 bit mode. ; <25> 8/23/90 GMR NEEDED FOR SIXPACK!! Fixed task which clears warmstart to make a ; runtime check on HwCfgFlags before calling SwapMMUMode. ; <24> 7/16/90 BG Added EclipseNOPs for flakey 040s. ; <23> 6/25/90 CCH Added EXPORT of ShutDownDisp. ; <22> 6/22/90 DTY Fixed includes so ROM builds don’t break. ; <21> 6/21/90 DTY Moved ShutDownMgrINIT.a InstallProc to end of this file. Moved ; _SDInit code into InstallProc. System versions of ShutDown ; Manager will not have _SDInit as a selector. _SDInit selector ; still available in ROM builds. Check gestaltMisc for ; gestaltSquareMenus to determine background colour in BlankScreen ; instead of looking at machine type. ; <20> 6/21/90 DTY Shutdown Manager now loaded as lpch on all systems. Removed all ; references to asINIT. Changed entry point of _Shutdown to ; ShutDownDispatch. _SDInit code comes after dispatch routine, ; and now called from ShutDownMgrINIT.a. ; <19> 6/20/90 DTY Made Shutdown Manager a linked patch under 7.0 ; <18> 6/18/90 DDG NEEDED FOR SIXPACK: Fixed use of RESET instruction, so that we ; RESET on an XO. ; <17> 6/18/90 DDG NEEDED FOR SIXPACK: fixed the graying of the elsie screen (we ; need to use ioRefNum instead of ioVRefNum). ; <16> 6/12/90 DAF Added CLUT-based screen graying on restart for Elsie only. ; <15> 6/11/90 DTY Pass Shutdown constants from ShutDownEqu.a instead of sdBit ; constants to RemoveOtherType to get proper bit alignment for the ; compare. ; <14> 6/11/90 DDG NEEDED FOR SIXPACK: Put back some obsolete code that checks for ; the presence of switcher and calls _ExitToShell instead of ; shutting down. This fixes a bug in OnCue. ; <13> 6/8/90 DTY Added RemoveOtherType routine to remove sdOnRestart procedures ; when calling ShutDwnPower, and to remove sdOnPowerOff procedures ; when calling ShutDwnRestart, so that CallRoutines can ; differentiate between the two, and provide more specific times ; to call shutdown routines. ; <12> 5/29/90 DDG NEEDED FOR SIXPACK: Changed all the sixpack conditionals from ; six-point-oh-seven to six-point-oh-six. ; <11> 5/16/90 DDG NEEDED FOR SIXPACK: The ClearWarmStart routine now checks for the ; machine being a Mac Plus, and if that is the case, then ; WarmStart is NOT cleared (it doesn't exist on the MacPlus) ; <10> 5/2/90 CV Adding include of 'GestaltPrivateEqu.a'. ; <9> 3/22/90 GA Removing the code which stops Egret ADB autopoll and ; Egret one second interrupts. These functions are now ; done by diagnostics calling a routine in EgretMgr.a ; <9> 3/22/90 GA Removing the code which stops Egret ADB autopoll and Egret one ; second interrupts. These functions are now done by diagnostics ; calling a routine in EgretMgr.a ; <8> 2/28/90 GA Changed the System Restart code supporting Egret to conform with ; the new Egret Manager Parameter block Model. ; <7> 2/15/90 GA Changed the Conditional if hasEgret to If ForRom AND HasEgret to ; fix a broken BigBang Build. ; <6> 2/14/90 GA Added support to the Restart code to issue a stop autopoll and ; stop 1 sec. irq to Egret before restarting the system. ; <5> 1/12/90 SES NEEDED FOR 6.0.5: Added shut down task to clear warm start flag ; on a power off. This means that the machine will do a cold start ; if the user selects 'Shut Down', but will still do a warm start ; if the user selects 'Restart'. ; <4> 1/11/90 CCH Added include of “HardwarePrivateEqu.a”. ; <3> 1/3/90 CCH Changed Gestalt equate filename back to GestaltEqu.a. ; <2> 1/2/90 CCH Changed the name of the Gestalt equate file. ; <3.0> 11/2/89 dba exported ShutInit ; <2.9> 10/31/89 dba changed to load as a patch instead of an INIT ; <•2.9> 10/31/89 dba forced submission (Reality was full) ; <2.8> 10/11/89 dba added sdUserChoice selector; added comments; made some more ; subroutines; got rid of some code to handle Switcher and 128K ; Macs; got rid of equates which are already in ShutDownEqu.a; ; changed rules for white border, soft power-off, and RESET (these ; will use new Gestalt selectors before 7.0 ships) ; <2.7> 7/12/89 GGD NEEDED FOR AURORA, once again, changed which machines do a RESET ; inst in the Restart code. Added comments explaining why some ; machines need it, and why some others must not use it. ; <2.6> 6/26/89 PKE NEEDED FOR 6.0.4 (and 7.0): Fixed definition of DHTrapNumber. ; <2.5> 6/20/89 CCH Put RESET back in for all but HcMac. ; <2.4> 6/20/89 CCH Modified to assemble for System file. ; <2.3> 6/15/89 CSL Took out the temporary quick and dirty fix in shut down with ; parity RAM. ; <2.2> 5/30/89 CSL Temporary quick and dirty fix for shut down with parity RAM, ; zero out WarmStart during power off to ensure a real cold boot ; next time. ; <2.1> 5/23/89 DAF Hid cursor on powerdown for Aurora ; <2.0> 5/10/89 CCH Removed RESET instruction, since either we’re powering down or ; jumping to ROM, which will do a RESET anyway. ; <1.9> 4/27/89 CCH Doesn’t execute a RESET on restart if running out of RAM. ; <1.8> 3/6/89 GGD Changed ReStart again, jump to restart routine at ROMBase+$0A, ; instead of fetching the reset PC from the ROM, to allow for the ; case where the reset PC may not point into read ROM space (may ; use zero based space). Added support for RAM based ROM onMacPP, ; to not execute a reset instruction on restart. Included ; HardwareEqu.a for rom header equate. ; <1.7> 2/21/89 rwh fix restart - can’t assume RAM present after a reset. ; <1.6> 2/8/89 MSH Don’t use the RESET intruction on the portable ; <1.5> 11/21/88 CCH Changed ForRam equates to ForRom. ; <1.4> 11/18/88 DHD Cased out the portable during shutdown we always call _PowerOff ; <1.3> 11/16/88 CCH Took out include of “nTraps.a” ; <1.2> 11/16/88 DAF Updated restart for Mac II machines ; <1.1> 11/10/88 CCH Fixed Header. ; <1.0> 11/9/88 CCH Adding to EASE. ; <1.6> 10/11/88 DHD Updated screen clearing code to work on any CPU ; <1.5> 10/11/88 DHD removed code specific to the portable Mac. ; <•1.4> 9/23/88 CCH Got rid of inc.sum.d and empty nFiles ; <1.3> 9/9/88 MSH Removed hardware equate use for clearing screen before sleep. ; Use lomem values instead. ; <1.2> 9/6/88 MSH Added screen clear and delay for disk eject before sleep. ; <1.1> 7/21/88 MSH Add Sleep and reset to HcMac shutdown. ; <1.0> 2/11/88 BBM Adding file for the first time into EASE… ; 9/15/87 DHD Donn Hilsinger Denman that is - Changed the UnMountVol to the HFS ; flavor or UnMount. This really does an UnMountVol regardless of ; whether or not there are open files. Since the disk will be shut ; down, it seems like the right thing... ; 8/25/87 EKH Ed Heyl that is - Added '_ShutDown' equate so that it would build ; under MPW 1.0 - remember Don that is what everybody else uses. I ; copied the equate from MPW 2.0s AIncludes:Traps.a. ; 4/6/87 DLD Now clear the resume proc before putting up the shutdown alert, so ; the resume button won’t show. ; 11/19/86 DLD Fixed a bug in ShutInstall. Was pushing the return address twice. ; Removed push just before RTS. ; 9/5/86 DLD changes ForROM ; 8/22/86 DLD New today. ; LOAD 'StandardEqu.d' include 'LinkedPatchMacros.a' Include 'InternalOnlyEqu.a' ; <4> jmp include 'MMUEqu.a' include 'BootEqu.a' include 'HardwarePrivateEqu.a' include 'PowerPrivEqu.a' include 'GestaltEqu.a' include 'GestaltPrivateEqu.a' include 'UniversalEqu.a' include 'ShutDown.a' include 'Slots.a' include 'ROMEqu.a' include 'EgretEqu.a' include 'EDiskEqu.a' include 'DialogsPriv.a' ; <49> for _SetDialogDefaultItem, etc MACRO ; SAM 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 UnimplementedTrapNumber EQU $A89F ; _UnImplemented VMGlobals EQU $0B78 ; private selectors (public selectors are in ShutDownEqu.a) sdInit equ 0 ; initialize the ShutDown Mgr sdUserChoice equ 5 ; turn power off, but let the user know sdSoftOff equ 6 ; SoftPower Off, ShutDownMgr ; SDInstall takes a flags word in D1: bits in the flag word are: sdBitPowerOff EQU 0 ; Call routine just before PowerOff. sdBitReStart EQU 1 ; Call routine just before a Reboot. sdBitUnMount EQU 2 ; Call routine before UnMounting Vols. sdBitDrivers EQU 3 ; before Driver Goodbye Kiss. ; local equates QSDProcPtr EQU QType+2 QSDRecSize EQU QSDProcPtr+4 SDHeader EQU $BBC ; low mem for ROM version ;_______________________________________________________________________ ; ; ShutDownINIT ; Install default shutdown procedures in the shutdown queue. ; Will not stick around in System builds, but will be there for ROMs. ;_______________________________________________________________________ ShutInit PROC Export moveq #10,D0 ; SD Queue Header is pointed to by low memory in ROM _NewPtr sys,clear move.l A0,SDHeader pea DoDrivers ; the default routine to unload move.w #SDOnUnMount,-(SP) ; all drivers with a goodbye jsr ShutInstall ; install it in the queue pea DoUnmount ; the default routine to unmount volumes move.w #sdRestartOrPower,-(SP) ; do before power-off or restart jsr ShutInstall pea ClearWarmStart move.w #sdOnPowerOff,-(SP) ; only on 'shut down' <26> jsr ShutInstall ; install it in the queue <26> Rts ;_______________________________________________________________________ ; ; Routine: ShutDown ; ; Arguments: A0 (input) : address of a ShutDown routine ; D0 (input) : command word (SDInit, SDPowerOff ...) ; D1 (input) : for an SDInstall operation, the flags word. ; ; Function: This routine dispatches to one of several functions: SDInit ; initializes the ShutDown Queue and sets up a default ; shutdown routine to eject disks. SDPowerOff calls the ; power down routines, and then turns power off (or waits ; for the user to do so). SDRestart calls the restart routines ; and then does a re-boot. SDInstall installs a power ; off or restart proc. SDRemove removes a proc. ; ; ShutDown(OpWord) ; ;_______________________________________________________________________ EXPORT Shutdown ShutDown move.l (SP)+,D2 ; save return move.w (SP)+,D0 ; get opcode word move.l D2,-(SP) ; restore the return subq #SDPowerOff,D0 bcs.w ShutInit ; if d0=0, _SDInit a selector in ROM versions beq ShutPower ; if d0=1, Shutdown subq #SDInstall-SDPowerOff,D0 bcs ShutRestart ; if d0=2, carry set, bra to restart beq.s ShutInstall ; if d0=3, Install subq.w #sdUserChoice-sdInstall,d0 bmi.s ShutRemove ;if d0=4, Remove beq UserChoice ; if d0=5, User Choice @unknownSelector rts ; unknown selector (do nothing, assume no parameters) ;_______________________________________________________________________ ; ; ShutInstall - Installs a shutDown procedure in the SD Queue. ; Entry On Stack: Long - Proc pointer, to install in Queue, call later. ; Word - Flags word, with low bits defining when to call proc. ; ; ShutDown(Proc, WhenFlags, 3) ;_______________________________________________________________________ EXPORT ShutInstall ShutInstall move.l (SP)+,D2 move.w (SP)+,D1 ; get flags word move.l (SP)+,a1 ; and ProcPointer move.l D2,-(SP) moveq #QSDRecSize,D0 ; create the queue element. _NewPtr sys move.w D1,QType(A0) ; stuff in the flags and proc. move.l A1,QSDProcPtr(A0) move.l SDHeader,A1 ; get address of queue _Enqueue ; install it in the queue Rts ;_______________________________________________________________________ ; ; ShutRemove - Removes a shutDown procedure in the SD Queue. ; Entry: TOS - Proc pointer, to remove from the Queue. ; Exit: D0 - Error Code. ; ; ShutDown(Proc, 4) ;_______________________________________________________________________ Export ShutRemove ShutRemove move.l (SP)+,D2 move.l (SP)+,A0 ; get proc pointer from NOS move.l D2,-(SP) move.l A2,-(SP) move.l SDHeader,A1 ; get address of queue AddQ #QHead,A1 ; point to the head move.l (A1)+,A2 move.l (A1),D0 ; remember the tail beq.s @NotFound ; are there any entries? ; Search for the matching entry. @ScanLoop cmp.l QSDProcPtr(A2),A0 ; is this the one? beq.s @Found move.l QLink(A2),A1 ; get the link to the next. cmp.l A2,D0 ; did we do the end? move.l A1,A2 Bne.S @ScanLoop @NotFound moveq #qErr,D0 ; return error - not found. Bra.S @Terminate @Found move.l SDHeader,A1 ; get the SD Queue Header A1. move.l A2,A0 _Dequeue ; remove it from the linked list. move.l A2,A0 _DisposPtr ; de-allocate the memory for the pt @Terminate move.l (SP)+,A2 ; restore work registers Rts ;_______________________________________________________________________ ; ; ShutRestart - do a shut-down and restart the system ; ; Entry: no parameters ; Exit: never does. ; ; ShutDown(2) ;_______________________________________________________________________ ; ; Some history for all you young'ns: ; ; Some things to be aware of about the RESET instruction on various Macintosh Products <2.7> ; ; 1) This code is in ROM on Aurora, Esprit, F19, and all new CPUs. It is in RAM, from ; the System Disk on the Mac Plus, SE, II, IIx, IIcx, SE30. ; ; 2) StartInit contains a RESET instruction in ROM on the 68020/030 CPU ROMs. ; ; 3) On the Mac Plus and Mac SE, a RESET will cause the 68000 to get a Reset, and it ; will switch into overlay mode, and Re-Boot through the reset vector. ; ; 4) When running a ROM image out of RAM, we do not want to do a RESET, because it will ; cause a switch into overlay mode, and the RAM base code cannot be fetched. ; ; 5) On 68030 based machines, if the translation tables are in RAM (AURORA/F19, VM or Romulator), ; you should not do a RESET when the MMU is enabled, even if you are executing in ROM. ; If there is a miss in the ATC, it will attempt to fetch descriptors from RAM, but overlay ; is now enabled, and data from ROM will be used instead, causing lots of problems. ; ; 6) Esprit has some problem when RESET is executed, and RESET should NEVER be used. ; ; 7) This all means that RESET is only needed on a MacPlus and MacSE. ; It might not be a problem on machines based on the MacII/IIx ROMs, ; since they have the MMU tables in ROM, but it is not reccommended. ; All other situations should not do a RESET in Shutdown. ; export ShutRestart ShutRestart with ROMHeader moveq #sdOnPowerOff,d5 ; Remove poweroff routines from the queue <13> bsr RemoveOtherRoutines moveq #SDBitRestart,D0 ; remember that we will reboot. bsr CallRoutines ; do the shutDown cleanup. moveq #1,D5 ; Go ahead and hide cursor/close LCDs. bsr BlankDesktop ; Go blank the desktop. move.l ROMBase,A2 ; point to the ROM lea ROMHeader.Restart(A2),A2 ; point to the restart routine move.l #emuWarmStartConst,D0 ; Does the upper long match? move.l #WmStConst,D1 ; Does the upper long match? bsr UpdateEmuWarmstart ; Write the warmstart (We may have come from a shutdown...) tst.l VMGlobals ; Is VM running? bmi.s @noVM ; -> No. Assume we're in Supervisor Mode _EnterSupervisorMode ; Enter supervisor mode (don’t worry about munging the stack...) @noVM bsr DockInitSCC ; reset the SCC (if we have Power controls) <3> TestFor JawsExists ; are we running on a Tim machine with JAWS <5> HJR beq.s @noJAWS ; -> No JAWS, jump to RESTART now. <43> with PmgrRec, pmCommandRec @JawsRestartSeq ; -- Special Case for JAWS -- <5> HJR move.l PMgrBase,a0 ; get pointer to the power manager globals move.l HDVector(a0),a0 ; get pointer to hard disk power down jsr (a0) ; kill the hard disk lea -pmBlkSize(sp),sp ; Create stack frame lea pmData(sp),a0 ; Get pointer to a xmit buffer move.l a0,pmRBuffer(sp) ; Load pointer to receive buffer move.l a0,pmSBuffer(sp) ; Load pointer to xmit buffer clr.l (a0) ; No data clr.w pmLength(sp) ; No data move.w #$21,pmCommand(sp) ; ADB autopoll disable move.l sp,a0 ; a0 get pointer to paramter block _PmgrOp ; go kill the machine clr.l pmData(a0) ; clear data clr.w pmLength(a0) ; clear length move.w #$d0,pmCommand(sp) ; reset CPU command move.w Timedbra,d1 ; set-up our counter lsl.w #2,d1 ; give ourselves 4 milliseconds _PmgrOp ; go kill the machine @waitloop dbra d1,@waitloop ; stick around for 4 milliseconds ; Fall into the JMP to Restart <43> ; Finally! Restart the machine by Jumping through the Restart vector in the ROM header @noJAWS JMP (A2) ; exit thru the restart routine ;________________________________________________________________________________________________ ;_______________________________________________________________________ ; ; ShutPower - Do a shutDown and power off the system if possible. If it’s ; and older system (no power off ability) then put up an ; alert that the system can go down now. ; ; Entry: no parameters ; Exit: never does. ; ; ShutDown(1) ;_______________________________________________________________________ export ShutPower ShutPower bsr DoRAMDiskAlert ; Check for RAM disk. Should we kill the power? beq @continuePowerOff ; -> Yes. Pull the plug! rts ; Cancel the Shutdown. @continuePowerOff moveq #sdOnRestart,D5 ; Remove all restart procedures from the queue <13> bsr.w RemoveOtherRoutines ; Go remove these procedures from the queue <13> moveq #SDBitPowerOff,D0 ; pass parameter: power off. bsr.w CallRoutines ; do cleanup and check if new mac. moveq #1,D5 ; Go ahead and hide cursor/close LCDs. bsr BlankDesktop ; Clear the whole desktop. bsr FindEDisk ; Do we have an EDisk in the drive Q? beq.s @noEDisk ; -> Nope, continue w/power off bsr KillEDisk ; Clear the EDisk's checksum data (invalidate the disk) @noEDisk ; Send Sonic a soft reset <16> thru next <16> TestFor SonicExists ; Does this machine have a SONIC ENet chip? beq.s @noSONIC ; IF hasSONIC THEN With DecoderInfo movea.l UnivInfoPtr,a0 ; get address of universal product info adda.l ProductInfo.DecoderInfoPtr(a0),a0; and point to table of base addresses moveq #SonicExists,d0 ; get offset to Sonic base address movea.l (a0,d0.w*4),a0 ; grab Sonic base address tst.l a0 ; check address just in case its bogus (?) beq.s @noSONIC ; dont do anything if address is zero bset #7,(a0) ; bit 7 of SonicAddr+0 causes a SW reset EndWith @noSONIC ; ENDIF <16> bsr CheckForSoftPowerOff ; does this machine have software power-off? bz.s @noSoftPowerOff ; no, don’t even try it _PowerOff ; turn power off ; it’s nice that we fall through if PowerOff does nothing @noSoftPowerOff _InitCursor moveq #shutDownAlert,D0 ;_______________________________________________________________________ ; ; DoSysErrDialog ; ; Put up a dialog (done by the system error handler). ; The system error ID must be in D0. ; ;_______________________________________________________________________ DoSysErrDialog clr.l ResumeProc ; don’t show resume button _SysError ; will never return ;_______________________________________________________________________ ; ; UserChoice ; ; Start off as a power-off. If the machine supports soft power-off, ; we give the user a choice between Restart and Shut Down (some of the ; code to handle this is in system error tables). If the machine ; does not support soft power-off, Shut Down and Restart are equivalent, ; so we put up an alert with a single Restart button (the text reflects ; the fact that the computer made the choice). ; ;_______________________________________________________________________ UserChoice moveq #0,D5 ; Don’t hide cursor/close LCDs. bsr BlankDesktop ; Clear the entire desktop for consistency. bsr CheckForSoftPowerOff ; does this machine have software power-off? bz.s @noSoftPowerOff ; no! move.w #dsShutDownOrRestart,d0 ; yes, let the user choose Shut Down or Restart bra.s DoSysErrDialog @noSoftPowerOff moveq #sdBitPowerOff,d0 ; notify just as we would for PowerOff bsr.s CallRoutines ; go do the notification move.w #dsSwitchOffOrRestart,d0 ; no, let the user switch off or Restart bra.s DoSysErrDialog ;_______________________________________________________________________ ; ; CallRoutines ; Entry: D0 - Bit number to test (shutdown type). ; Exit: regs saved. ;_______________________________________________________________________ CallRoutines movem.l A1-A3/D0-D5,-(SP) move.w D0,D4 ; Call Cleanup for Drivers, and Custom cleanup Procs. moveq #SDBitDrivers,D5 ; do Pre-Driver cleanUp bsr.s CallCleanUp ; Call Cleanup to unmount volumes, and then custom PowerOff/Restart. moveq #SDBitUnMount,D5 ; do Vol UnMounts bsr.s CallCleanUp move.w D4,D5 ; do PowerOff or ReStart cleanup bsr.s CallCleanUp ; set up the flags for the caller. movem.l (SP)+,A1-A3/D0-D5 Rts ;_______________________________________________________________________ ; ; RemoveOtherRoutines - Remove all occurences of the passed in shutdown procedure type from the shutdown queue. <13> ; This differentiates routines that wish to be executed before drivers on restart, but not at all on poweroff ; (as an example). Before, there was no differentiation between restart and poweroff for routines that were ; to run before drivers close, or before volumes are unmounted. There are cases when such differentiation ; is desired, but was previously impossible. By removing routines of the “other” type (other being restart on ; a poweroff, and vice versa), the only routines left in the queue are those that should be executed. Routines ; that execute on both poweroff and restart are left in the queue. On a final note, the routines aren’t actually ; removed from the queue, since the machine will either be powered off or restarted in a few seconds, so it really ; doesn’t matter what gets left lying around in memory. This way, a call to _SDRemove is saved. ; ; Entry: D5 - Bit number of shutdown type to remove from queue ; Exit: ;_______________________________________________________________________ RemoveOtherRoutines move.l SDHeader,A1 ; get header into A1. Lea QHead(A1),A3 ; point to the head move.l (A3)+,A2 move.l (A3),D3 ; remember the tail beq.s @NotFound ; are there any entries? ; Find entry that matches the type to remove @ScanLoop move.l QLink(A2),A3 ; get the link to the next move.w QType(A2),D0 ; get the shutdown flags andi.w #3,d0 ; We’re only interested in the poweroff and restart bits cmp.w d0,d5 ; Is this a type that should be removed? bne.S @DontRemove ; don’t remove this entry ; now remove the proc from the queue. ; Since the whole state of the machine is going into la-la land very shortly, there’s no point ; in actually removing the procedure. Just zapping the shutdown flags to zero to prevent this ; routine from being found again is good enough. <13> clr.w QType(a2) ; QType holds the shutdown flags @DontRemove cmp.l A2,D3 ; at the end? move.l A3,A2 Bne.S @ScanLoop @NotFound Rts ;_______________________________________________________________________ ; ; CallCleanUp ; Entry: D5 - Bit number to test (shutdown type). ; Exit: ;_______________________________________________________________________ CallCleanUp move.l SDHeader,A1 ; get header into A1. Lea QHead(A1),A3 ; point to the head move.l (A3)+,A2 move.l (A3),D3 ; remember the tail beq.s @NotFound ; are there any entries? ; Search for an entry that wants a call now. @ScanLoop move.l QLink(A2),A3 ; get the link to the next move.w QType(A2),D0 ; get the shutdown flags BTst D5,D0 ; want call now? beq.s @DontCallUs ; don’t call for this kind ; call the proc, with bit number in D0, in case it cares. move.l QSDProcPtr(A2),A0 ; call the shutdown routine move.w D5,D0 ; pass bit number in D0 Jsr (A0) ; now remove the proc from the queue. ; Since the whole state of the machine is going into la-la land very shortly, there’s no point ; in actually removing the procedure. Just zapping the shutdown flags to zero to prevent this ; routine from being found again is good enough. <13> clr.w QType(a2) ; QType holds the shutdown flags @DontCallUs cmp.l A2,D3 ; at the end? move.l A3,A2 Bne.S @ScanLoop @NotFound Rts ;_______________________________________________________________________ ; ; DoDrivers - The Default shutdown routine to kiss all of the drivers ; goodbye. ; Entry: No paramters. ; ;_______________________________________________________________________ export DoDrivers DoDrivers ; first, send a doGoodBye call to all drivers that want one MOVEM.L D0-D1/D4-D7/A0-A1,-(SP) ; save registers <4> jmp SUB #IOQElSize,SP ; allocate pBlock MOVE #-1,CSCode(SP) ; set up control code MOVE.L UTableBase,A1 ; point to unit table MOVE.W UnitNtryCnt,D1 ; get # entries in unit table @loop MOVE.L (A1)+,D0 ; get the DCE handle BEQ.S @next ; if NIL, try next one MOVE.L D0,A0 ; get the DCE handle MOVE.L (A0),A0 ; get the DCE pointer ;------------------------------------------------------------------------ <4> jmp Btst #dRamBased,DCtlFlags+1(A0) ; If we’ve got a pointer, then just skip Beq.s @skipVidChk ; this code (our drivers are RamBased). Move.l A0,D7 ; Save pointer to DCE. Move.l A1,D6 ; Save UTable pointer. Move.l dCtlDriver(A0),A0 ; Get handle to driver. Move.l (A0),A0 ; Get pointer to driver. Lea drvrName(A0),A0 ; Point to driver name. Move.l A0,D5 ; Save it for later. moveq #0,D0 ; Prepare D0. Move.b (A0),D0 ; Get the length of the driver name. Move.w D0,D4 ; Make a copy. Addq #2,D4 ; Adjust offset to version field (len + 1) Bclr #0,D4 ; Adjust offset for word alignment. Move.w (A0,D4.w),D4 ; Get the version number. Bne.s @endVidChk ; If non-zero, then just leave. Swap D0 ; Get 1st string length into hi-word. Addq #1,A0 ; Point to text of driver name. Lea TimVidTitle,A1 ; Point to TIM/TIM-LC’s video driver name. Move.b (A1)+,D0 ; Get 2nd string length into lo-word. _CmpString ; Compare drvrName with TimVidTitle. Tst.b D0 ; If this is the TIM/TIM-LC driver, Beq.s @fixFlags ; then don’t kiss it goodbye. Move.l D5,A0 ; Restore pointer to driver name. moveq #0,D0 ; Re-prepare D0. Move.b (A0)+,D0 ; Get length of 1st string… Swap D0 ; …into the hi-word. Lea DAFBVidTitle,A1 ; Point to Spike/Eclipse video driver name. Move.b (A1)+,D0 ; Get 2nd string length into lo-word. _CmpString ; Compare drvrName with DAFVidTitle. Tst.b D0 ; If this is the DAFB (Spike/Eclipse) driver, Beq.s @fixFlags ; then don’t kiss it goodbye. Bra.s @endVidChk ; Otherise, just leave. @fixFlags Move.l D7,A0 ; Restore pointer to DCE. Bclr #DNeedGoodbye,DCtlFlags(A0) ; Reset the good-bye kiss flag. @endVidChk Move.l D7,A0 ; Restore pointer to DCE. Move.l D6,A1 ; Restore pointer to UTable. @skipVidChk ;------------------------------------------------------------------------ <4> jmp BTST #DNeedGoodbye,DCtlFlags(A0) ; need a goodbye kiss? BEQ.S @next ; not tonight dear ; we found one that needs a goodbye call so issue the control call MOVE.W DCtlRefNum(A0),IORefNum(SP) ; set up the refNum MOVE.L SP,A0 ; point to the DCE _Control ; kiss it goodbye... @next SUBQ #1,D1 ; check next entry BNE.S @loop ; if so, loop ; done, return ADD #IOQElSize,SP ; deallocate pBlock MOVEM.L (SP)+,D0-D1/D4-D7/A0-A1 ; restore registers <4> jmp RTS ;------------------------------------------------------------------------ <4> jmp String Pascal TIMVidTitle DC.W '.Display_Video_Apple_TIM' ; Name of TIM/TIM-LC Video Driver. DAFBVidTitle DC.W '.Display_Video_Apple_DAFB' ; Name of Spike/Eclipse Video Driver. ;------------------------------------------------------------------------ <4> jmp ;_______________________________________________________________________ ; ; DoUnmount - Unmount all of the volumes on line, so the disks will be updated before our power off. ; ; Entry: No parameters. ; ;_______________________________________________________________________ export DoUnmount DoUnmount sub #IOQElSize,SP ; allocate pBlock ; Go through the VCB Queue to Flush and eject all volumes. move.l SP,A0 ; point to the parameter block clr.L ioVNPtr(A0) clr.W ioRefNum(A0) move.l VCBQHdr+QHead,A1 ; get the queue header move.l VCBQHdr+QTail,D2 ; get the tail too beq.s @AllFlushed bsr ZapVCBQueue ; wipe out the whole queue @AllFlushed add.W #IOQElSize,SP ; deallocate pBlock ; Wait for all floppy drives that have diskettes inserted to eject, or for 2 seconds, ; whichever comes first. (Note: This should now be “universal,” even ; for CPUs that don’t have auto-eject floppy mechanisms.) taskActive equ 7 ; High bit of qType word is active flag. moveq.l #(tmXQSize/2)-1,D0 ; Set up the init-loop counter. @clrTask clr.w -(Sp) ; Allocate and clear a TMTask record. dbra D0,@clrTask ; Do it one word at a time. move.l Sp,A0 ; Point to the TMTask record. _InsXTime ; Install it. move.l #2*1000*1000,D0 ; We need ~1.5sec, but we’ll say 2sec for safety. neg.l D0 ; (Negate for µsec timer.) _PrimeTime ; Start the TMTask. move.l DrvQHdr+QHead,D0 ; Now, get a pointer to the first drvQElem. @Repeat move.l D0,A1 ; Copy the drvQElem pointer into A1. cmpi.w #-5,dqRefNum(A1) ; If this isn’t a floppy (.Sony) driver drive, bne.s @Until ; then just go on. @WaitEject btst.b #taskActive,qType(A0) ; If the TMTask has completed, beq.s @TimedOut ; then we can now exit this loop. move.l -4(A1),D0 ; Otherwise, get the drvQElem flags. andi.l #$00FF0000,D0 ; If the media is still in the mechanism, bne.s @WaitEject ; then just wait. @Until move.l qLink(A1),D0 ; Otherwise, get the next entry in the queue. bne.s @Repeat ; Loop until done. @TimedOut _RmvTime ; Remove TMTask. adda.w #tmXQSize,Sp ; Reclaim the stack space. rts ;_______________________________________________________________________ <5> ; ; ClearWarmStart - Shutdown task to clear warm start variable if user ; chooses 'Shut Down' from the Finder. ; ;_______________________________________________________________________ <5> export ClearWarmStart ClearWarmStart movea.l BootGlobPtr,A0 ; point to bootGlobals clr.l StartGlobals.sgWarmStart(A0) ; clear warm start flag clr.l WarmStart ; write warm start constant to indicate warm start moveq #0,D0 ; hi long moveq #0,D1 ; lo long bsr.l UpdateEmuWarmstart ; Clear the warmstart rts ;_______________________________________________________________________ SAM ; ; UpdateEmuWarmstart - ; ; The emulator warmstart flag lives in the writeprotected diagnostic info block in the Nanokernel's ; data page. We need to "map" the diag page to a normally mapped page of RAM, write the warmstart ; constant, and remap the memory back the way it was. Oh, I'm using logical page number 1 ; (i.e. $1000 - 4k pages). Oh, yeah, the RAM at $1000 never actually gets modified... ; ; Entry - D0.l warmstart low ; D1.1 warmstart high ; ;_______________________________________________________________________ Export UpdateEmuWarmstart UpdateEmuWarmstart With nkDiagInfo testFor has68kEmulator ; Does this machine have a V0 style emulator? beq @Done ; -> Nope, we're done. Exit. move SR,-(SP) ; Save SR ori.w #hiIntMask,SR ; Disable interrupts movem.l D2-D7,-(SP) ; Save some D regs move.l D0,D6 move.l D1,D7 move.w #12,D2 ; Shift Count (12 bits in 4k) lea 1,A0 ; Logical page #1 ($1000) _nkGetPTEntryGivenPage ; Get its Pte move.l D0,D3 ; Save the Pte in D3 move.l (nkDiagInfoPtr),D0 ; Get the DiagPage Logical Address move.l D0,D5 ; Make a copy and.l #4096-1,D5 ; Get the offset into the page lsr.l D2,D0 ; Make it a page number move.l D0,A0 ; Page into A0 _nkGetPTEntryGivenPage ; Get the Diag Pte move.l D0,D4 ; Save it lea 1,A0 ; Get the buffer page number in A0 lea 1,A1 ; Say page is inited (#1) _nkMMUMarkBacking ; Mark this page as outta here lea 1,A0 ; Logical Page number of the buffer move.l D4,D0 ; Get the Diag Pte lsr.l D2,D0 ; Get its Physical Page number move.l D0,A1 ; Set Physical Page _nkMMUMarkResidentGlue ; Map the diag's physical address to the buffer's logical addr lea $1000,A0 ; Get our logical starting point add.l D5,A0 ; Add in the offset from the start of the diag page move.l D6,DiagWarmStartLow(A0) move.l D7,DiagWarmStartHigh(A0) lea 1,A0 ; Get the lo Page number in A0 lea 1,A1 ; Say page is inited (#1) _nkMMUMarkBacking ; Mark this page as outta here lea 1,A0 ; Get the lo Page number in A0 move.l D3,D0 ; Get the LoPage's Pte lsr.l D2,D0 ; Get its Physical Page number move.l D0,A1 ; Set Physical Page _nkMMUMarkResidentGlue ; Move the HiPage to the loPage's logical addr movem.l (SP)+,D2-D7 ; Save some D regs move (SP)+,SR ; Restore IRQ enable state @Done rts ; all done EndWith ;_______________________________________________________________________ <5> ; ZapVCBQueue - This routine goes through the VCB Queue, and calls HUnmountVol for each entry. ; ; Entry: A0 - IOParam Block ; A1 - Pointer to current Entry ; D2 - Tail entry Pointer. ; Exit: A1 - Pointer to next Entry. ; D1 - Preserved. ;_______________________________________________________________________ <5> ZapVCBQueue move.w D1,-(SP) ; save for re-entrancy. move.w vcbVRefNum(A1),D1 ; get a VRefNum move.l QLink(A1),-(SP) ; go on to the next VCB cmp.l D2,A1 move.l (SP)+,A1 beq.s @FlushTime ; have we reached the end? bsr.s ZapVCBQueue ; not yet, save the VRefNum, call self. @FlushTime move.w D1,ioVRefNum(A0) ; set up the refNum in the PBlock. _Eject _HUnMountVol ; shut the volume down. move.w (SP)+,D1 ; restore crucial VRefNum Rts ; for reentrancy. ;_______________________________________________________________________ ; ; BlankDesktop ; ; Blank the whole deskstop. This fills the entire desktop with black. ; It used to be the case that we wanted the screen to go white on ; portables, but that causes a really ugly white flash, and it’s ; not necessary since portables always (famouse last words) have ; soft power. Note that this routine is now also called by restart ; instead of only during shutdown. The reason for this is that ; many newer CPUs don’t pass the reset instruction thru the CPU ; to the I/O devices. As a result, the desktop can persist on many ; displays thru BootBeep until PrimaryInit, which looks bad. ; ; Note that it also hides the cursor, for a more tidy look. ; ;_______________________________________________________________________ IMPORT AllocFakeRgns ; BlankDesktop MOVE.L A5,-(Sp) ; Save A5-world. Why? ; Somewhat stolen from StartAlert.a TST.B D5 ; If we’re not supposed to hide the cursor, BEQ.S @SkipHide ; then just go on. _HideCursor ; Otherwise, hide it. @SkipHide LEA -4(SP),A5 ; start A5 here SUB.W #GrafSize+140,SP ; allocate global, port space MOVE.L SP,A6 ; remember start of port PEA -4(A5) ; point to QD global space MOVE.B QDExist,D3 ; preserve state of QDExist flag (don't let us affect it) _InitGraf ; initialize QuickDraw MOVE.B D3,QDExist ; allocate a grafPort using the stack and initialize it BigJsr AllocFakeRgns,A1 ; init dummy vis and clip to wide-open MOVE.L A6,-(SP) ; push address of grafPort _InitPort ; initialize the port. This particular case ; doesn’t move memory, even when it calls COPYRGN! MOVE.L clipRgn(sp),-(sp) ; region for FillRgn MOVE.L GrafGlobals(A5),A1 ; get QuickDraw globals PEA black(A1) ; get black _FillRgn ; fill, wide region, with wide clip in wide bounded port ; i.e. fill all screens with the appropriate color. ; doesn’t move memory. ADD.W #GrafSize+140,SP ; dispose of the port TST.B D5 ; If we’re not supposed to close LCDs, BEQ.S @SkipClose ; then just go on. BSR CloseLCDVideo ; Otherwise, close ’em. @SkipClose MOVE.L (Sp)+,A5 ; Restore A5-world. RTS ;_______________________________________________________________________ ; ; CheckForSoftPowerOff ; ; Check to see if this machine has a working PowerOff trap. ; ; Note that this must be accurate for machines like the SE/30, since ; it is sometimes used to decide whether the user has choice between ; Shut Down and Restart. ; ; Returns: Z if there is no soft power-off, NZ if there is ; ;_______________________________________________________________________ CheckForSoftPowerOff move.l #gestaltHardwareAttr,d0 ; check for soft power-off hardware <39> _Gestalt ; Gestalt <39> move.l a0,d0 ; It’s not just a good idea. <39> btst #gestaltHasSoftPowerOff,d0 ; It’s the law. <39> rts ;———————————————————————————————————————————————————————————————————————————————————————— <4> HJR ; Routine: CloseLCDVideo | ; v ; Inputs: none ; ; Outputs: none ; ; Trashes: D0 ; ; Function: Run through the slot manager record looking for apple video. Afterward check ; if the video is of type LCD. If so, then close the video driver. ;———————————————————————————————————————————————————————————————————————————————————————— CloseLCDFrame RECORD 0, DECR CloseLCDCntBlk DS.B IOVQElSize ; control call parm block CloseLCDSpBlk DS.B spBlock.spBlockSize ; Slot Manager param block. CloseLCDFrameSize EQU * ; size of frame ENDR CloseLCDVideo CloseLCDVideoRegs REG D1/A0-A1 WITH CloseLCDFrame,spBlock LINK A6,#CloseLCDFrameSize ; allocate variable space MOVEM.L CloseLCDVideoRegs,-(SP) ; Save them regs LEA CloseLCDSpBlk(A6),A1 ; Get pointer to spBlock MOVEA.L A1,A0 ; Set pointer to A0 CLR.B spSlot(A0) ; Set slot number MOVEQ #0,D1 ; set spId to 0 CLR.B spExtDev(A0) ; No external devices MOVE.W #CatDisplay,spCategory(A0) ; Look for this slot's card MOVE.W #TypVideo,spCType(A0) ; Make sure it is video MOVE.W #DrSwApple,spDrvrSW(A0) ; Make sure it is from Apple MOVE.B #1,spTBMask(A0) ; mark spDrvrHw field as don’t care @sNextLoop MOVEA.L A1,A0 ; Get pointer to spBlock MOVE.B D1,spId(A0) ; Set spID _sNextTypesRsrc ; get the spsPointer BNE.S @Done MOVE.B spId(A0),D1 ; Save spId for later use MOVE.B #sVidAttributes,spId(A0) ; read flag field in sRsrc _sReadWord ; ...pointed to by spsPointer BNE.S @sNextLoop ; no flags - find next sRsrc MOVEQ.L #1< HJR ENDWITH ;__________________________________________________________________________________ <7> SAM ; ; FindEDisk - Find the EDisk DriveQ entry, the Drive num, and the Driver refNum. ; Compares the Driver names of each drive in the drive queue to ".EDisk" ; ; Entry: ; Exit: ; D0 - Clear if EDisk was NOT found <8> jmp ; D2 - Drive Number ; D3 - Driver RefNum ; A0 - Drive Queue Element Ptr ;__________________________________________________________________________________ <7> SAM EXPORT FindEDisk FindEDisk ; Look through the Drive Queue to find each drive's Driver MOVE.L A2,-(SP) ; Save A2 @Ok LEA DrvQHdr+2,A0 ; Start of drive queue. @DriveLoop MOVE.L (A0),D0 ; Get a drive entry BEQ.S @NoRAMDisk ; -> No more drives. No Edisk, bail out MOVE.L D0,A0 ; Pointer to queue element. MOVE.W dQDrive(A0),D2 ; Get the drive num in D2 for later. MOVE.W dQRefNum(A0),D0 ; Get the Driver reference number. MOVE.W D0,D3 ; Put the Driver RefNum in D3 ADDQ.W #1,D0 ; Calc the UnitTable entry NEG.W D0 ; ASL.W #2,D0 ; (-1 * RefNum) * 4 ; Found a drive & its RefNum. Look for the driver in the UnitTable MOVE.L UTableBase,A1 ; Get the UnitTable base address MOVE.L (A1,D0.W),A1 ; Get the DCE handle MOVE.L (A1),A1 ; Get the DCE ptr BTST.B #dRAMBased,dCtlFlags+1(A1) ; Is the driver RAM based? BEQ.S @GotPtr ; -> No. Its a pointer. Dont Dereference it. MOVE.L dCtlDriver(A1),A1 ; Dereference the DCE handle @GotPtr MOVE.L (A1),A1 ; Point to the driver LEA drvrName(A1),A1 ; Pointer to driver name ; Found the Driver, see if the drvrName = .EDisk LEA EDiskName,A2 ; Pointer to RAM disk driver name. MOVEQ #0,D0 ; Init length of driver name. MOVE.B (A2),D0 ; Get the Name string length byte @CharLupe CMP.B (A2)+,(A1)+ ; Does this char match? BNE.S @DriveLoop ; -> No. Try another Drive. DBRA D0,@CharLupe ; Keep looping till we run out 'o chars MOVEQ #1,D0 ; Force D0 to be non-zero (we found the '.EDisk'). <8> jmp @NoRAMDisk MOVEM.L (SP)+,A2 ; Restore A2. RTS ; No disk. Bail out. EDiskName DC.W '.EDisk' ; EDisk driver name ;__________________________________________________________________________________ <7> SAM ; ; KillEDisk - Given a Ptr to the EDisk's DriveQElem, get the logical start of ; the EDisk checksum data, Write enable the EDisk RAM, and whack ; the checksums data so the volume will not be mounted next time ; no matter how much the RAM persists after a power down! ; ; Entry: ; A0 - EDiskDrive Queue Element Ptr ;__________________________________________________________________________________ <7> SAM hwEDiskProt EQU 8 ; _hwPriv Write protect EDisk selector BytesToKill EQU $8000 ; Number of bytes to erase from base of EDisk data area EXPORT KillEDisk KillEDisk WITH EDiskDriveInfo MOVE.L DataStartPtr(A0),A2 ; Get Ptr to the start of the data area CMP.B #EMMU1,MMUType ; Check for PowerPC MMU emulation BNE.S @noEMMU ; IF we have an EMMU THEN MOVE.L A2,A0 ; get ptr to start of data area MOVE.L #BytesToKill,A1 ; get number of bytes to erase MOVE.L #(0<<16)|hwEDiskProt,D0 ; _HwPriv EDisk write protect selector and "unprotect" parm BRA.S @unProtect ; ELSE @noEMMU MOVE.L CheckSumPtr(A0),A0 ; Get Ptr to the start of the checksum area, if it exists TST.L A0 ; Check if RAM Disk is using checksums BNE.S @cksumOn ; IF checksumming is off THEN MOVE.L A2,A0 ; base address of RAM disk is same as DataStartPtr @cksumOn ; ENDIF SUB.L A1,A1 ; Protect flag. Zero = Unprotect MOVEQ #hwEDiskProt,D0 ; _HwPriv EDisk write protect selector @unProtect ; ENDIF _HwPriv ; Write Enable the EDisk RAM CMPI.W #paramErr,D0 ; Does not clear D0 on success, Check for failure BEQ.S @Done ; -> enable failed. Bail out now or Bus Error! MOVE.W #BytesToKill/4-1,D2 ; number of bytes to erase @whackLupe ; LOOP (to erase bytes in data area) CLR.L (A2)+ ; clear a longword DBRA D2,@whackLupe ; UNTIL (we've erased all bytes) @Done RTS ENDWITH ;———————————————————————————————————————————————————————————————————————————————————————————————————— ; DoRAMDiskAlert <49> ; ; If a RAM disk exists, and we're powering off as opposed to restarting, we want to display an alert ; warning that the contents of the RAM disk will be lost and give the user a chance to cancel the ; shutdown. This code is called from a patch in System builds, and from ShutPower directly for ; ROM builds. ; ; Entry: no parameters ; Exit: d0 is false and Z flag set if we should continue the shutdown ; d0 is true and Z flag not set if we should abort the shutdown ; ; if the option key is held down, return false ; if no RAM disk exists, return false ; if there are no visible files on the RAM disk, return false ; otherwise, put up an alert asking if the shutdown should continue ; return false if OK is hit, true if cancel is hit ; Export DoRAMDiskAlert DoRAMDiskAlert move.l a2,-(sp) ; save a2 CheckForOptionKey btst.b #2,KeyMap+7 ; don’t do anything if option key is held down bne exitFalse CheckIfRAMDiskExists movem.l d2-d3,-(sp) ; save registers munged by FindEDisk bsr FindEDisk ; is there a RAM disk? move.w d3,d1 ; save driver refNum in d1 movem.l (sp)+,d2-d3 ; restore registers tst.w d0 beq exitFalse ; no RAM disk ; get VCB pointer in a2 lea VCBQHdr+2,a2 ; start of volume queue @volumeLoop move.l (a2),d0 ; is there another volume? beq exitFalse ; no? then RAM disk is not mounted move.l d0,a2 ; pointer to VCB cmp.w vcbDRefNum(a2),d1 ; same driver? bne.s @volumeLoop ; no? then check next volume CheckForVisibleFiles link a6,#-108 lea -108(a6),a0 ; paramater block clr.l ioNamePtr(a0) ; don't care about name move.w vcbVRefNum(a2),ioVRefNum(a0); volume reference number clr.w ioFDirIndex(a0) ; init index @fileLoop move.l #fsRtDirID,ioDirID(a0) ; only check root addq.w #1,ioFDirIndex(a0) ; next index _GetCatInfo ; get info for file cmp.w #fnfErr,d0 ; are we done? beq.s @exitCheck ; yes? then leave btst #4,ioFlAttrib(a0) ; folder? beq.s @checkInvis ; no? then see if it's a desktop file tst.l ioFlUsrWds(a0) ; Finder 7.0 folder? bne.s @exitCheck ; no? then warn user tst.l ioFlUsrWds+4(a0) ; Finder 7.0? bne.s @exitCheck ; no? then warn user tst.w ioFlUsrWds+20(a0) ; any files in folder? beq.s @fileLoop ; no? then check next file bra.s @exitCheck ; yes? then warn user @checkInvis btst #14,HFileParam.ioFlFndrInfo+fdFlags(a0) ; is the file Invisible? bne.s @fileLoop ; -> yes, ignore this file @checkDesktop cmp.l #'FNDR',ioFlUsrWds(a0) ; old Desktop type? bne.s @checkNewDesktop ; no? then check to see if new type cmp.l #'ERIK',ioFlUsrWds+4(a0) ; correct file type? beq.s @fileLoop ; yes? then check next file bra.s @exitCheck ; no? then warn user @checkNewDesktop cmp.l #'DMGR',ioFlUsrWds+4(a0) ; correct creator type for new Desktop? beq.s @checkType ; yes? then check type cmp.l #'pds ',ioFlUsrWds+4(a0) ; correct creator type for file sharing? bne.s @exitCheck ; no? then warn user @checkType cmp.l #'BTFL',ioFlUsrWds(a0) ; correct file type? beq.s @fileLoop ; yes? then check next file cmp.l #'DTFL',ioFlUsrWds(a0) ; no? then check other possible type beq.s @fileLoop ; yes? then check next file @exitCheck unlk a6 ; get rid of parameter block beq.s exitFalse ; if no files that we care about, continue shutdown DoTheDialog ShutDownDLOGID EQU -16535 ; ID of DLOG in System file ShutDownOKButton EQU 1 ; dialog item of OK button ShutDownCancelButton EQU 2 ; dialog item of Cancel button pea vcbVN(a2) ; put volume name in warning message clr.l -(sp) ; nil clr.l -(sp) ; nil clr.l -(sp) ; nil _ParamText ; set dialog parameters subq #4,sp ; room for DialogPtr move.w #ShutDownDLOGID,-(sp) ; resource ID clr.l -(sp) ; use heap storage move.l #-1,-(sp) ; put it in front _GetNewDialog move.l (sp),a2 ; save dialog in a2 tst.l (sp)+ ; did we get a dialog? beq.s exitFalse ; no, bail ; let the Dialog Mgr outline the OK button and handle processing ; of both it and the Cancel button subq #2,sp ; room for OSErr result move.l a2,-(sp) ; dialogPtr move.w #ShutDownOKButton,-(sp) ; default item _SetDialogDefaultItem ; ignore error and let _SetDialogCancelItem use it move.l a2,-(sp) ; dialogPtr move.w #ShutDownCancelButton,-(sp) ; cancel item _SetDialogCancelItem addq #2,sp ; ignore error ; do the dialog subq #2,sp ; space for returned item clr.l -(sp) ; use standard filter proc pea 4(sp) ; VAR item. _ModalDialog ; wait for OK or Cancel move.l a2,-(sp) _DisposeDialog ; kill dialog. cmpi.w #ShutDownCancelButton,(sp)+ ; hit cancel button? bne.s exitFalse ; no, hit OK, so continue shutdown exitTrue move.w #true,d0 ; don’t continue shutdown bra.s justExit exitFalse move.w #false,d0 ; allow shutdown to continue justExit move.l (sp)+,a2 ; restore a2 rts ;________________________________ ; ; Docking Dispatch Trap ; DockInitSCC MOVEM.L D0-D2/A0-A2,-(SP) ; <3> MOVE.W #UnimplementedTrapNumber,D0 ; does the _DockingDispatch trap exist? _GetTrapAddress ,NEWTOOL MOVEA.L A0,A1 MOVE.W #$AA57,D0 _GetTrapAddress ,NEWTOOL CMPA.L A0,A1 BEQ.S @Done ; -> no, skip it MOVEQ #sccOn-256,D0 ; turn SCC power on BSR.S @SCCPower BSR.S InitSCC ; reset the SCC so it doesn't cause us trouble MOVEQ #sccOff,D0 ; turn SCC power off BSR.S @SCCPower @Done MOVEM.L (SP)+,D0-D2/A0-A2 RTS @SCCPower TestFor hwCbPwrMgr ; does this machine have a Power Manager? BEQ.S @NoPMGR ; -> nope, skip MOVE.B D0,-(SP) MOVE.L SP,-(SP) ; pmRBuffer MOVE.L (SP),-(SP) ; pmSBuffer MOVE.W #1,-(SP) ; pmLength = 1 byte to send MOVE.W #powerCntl,-(SP) ; pmCommand = power control MOVEA.L SP,A0 ; point to the parameter block _PMgrOp ; turn SCC power on or off LEA pmRBuffer+4+2(SP),SP ; toss the parameter block and buffer @NoPMGR RTS InitBData DC.B 9,$C0 ; do a hard reset DC.B 9,$40 ; reset the channel DC.B 4,$4C ; set async mode (magic?) DC.B 2,$00 ; zero interrupt vector for dispatcher DC.B 3,$C0 ; DCD not an auto-enable DC.B 15,$00 ; no interrupts DC.B 0,$10 ; reset ext/sts interrupts twice DC.B 0,$10 DC.B 1,$00 ; no interrupts InitBLth EQU *-InitBData InitAData DC.B 9,$80 ; reset the channel DC.B 4,$4C ; set async mode (magic?) DC.B 3,$C0 ; DCD not an auto-enable DC.B 15,$00 ; no interrupts DC.B 0,$10 ; reset ext/sts interrupts twice DC.B 0,$10 DC.B 1,$00 ; no interrupts InitALth EQU *-InitAData InitSCC TestFor SCCIOPExists ; see if we have a SCC IOP bne.s @hasIOP ; if so, don't try to initialize it MOVEA.L SCCWr,A0 ; point to SCC base write address (chan B) MOVEA.L SCCRd,A1 ; point to SCC base read address (chan B) LEA InitBData,A2 ; point to channel B init data MOVEQ #InitBLth,D1 ; and set up the length BSR.S @WriteSCC ; then init channel B ADDQ.W #ACtl,A0 ; adjust SCC addresses for channel A ADDQ.W #ACtl,A1 ; A2 points to channel A's init data MOVEQ #InitALth,D1 ; init data length @WriteSCC MOVE.B (A1),D2 ; read to make sure SCC is sync'ed up BRA.S @2 ; delay for timing, too @1 MOVE.L (SP),(SP) ; delay long for reset MOVE.L (SP),(SP) MOVE.B (A2)+,(A0) @2 DBRA D1,@1 @hasIOP RTS endwith ENDP END