mirror of
https://github.com/elliotnunn/supermario.git
synced 2024-11-29 05:49:19 +00:00
6210 lines
234 KiB
Plaintext
6210 lines
234 KiB
Plaintext
;
|
||
; File: PowerMgr.a
|
||
;
|
||
; Contains: 680x0 Interface to the Power Manager.
|
||
;
|
||
; Written by: Mike Hanlon
|
||
; Remangled by Portable Terror Squad
|
||
;
|
||
; Copyright: © 1986-1993 by Apple Computer, Inc. All rights reserved.
|
||
;
|
||
; This file is used in these builds: ROM
|
||
;
|
||
; Change History (most recent first):
|
||
;
|
||
; <SM10> 12/13/93 PN Roll in KAOs and Horror changes to support Malcom and AJ
|
||
; machines.
|
||
; <SM9> 9/1/93 SKH Rolled in from Horror. The old supermario copy of PowerMgr was
|
||
; hopelessly out of date, this is an almost straight copy of the Horror
|
||
; version.
|
||
; <H97> 6/24/93 SWC Clear the ‘disable hard disk spindown’ flag before calling the
|
||
; spindown routine so that the hard disk really does get turned
|
||
; off.
|
||
; <H96> 6/22/93 SWC Fixed a bug that causes a crash when getting ADB packets (when a
|
||
; timeout occurred, it was jumping to the wrong label).
|
||
; <H95> 6/21/93 SWC Changed the bit ordering in the modem info selectors and munged
|
||
; the SetWakeupTimerEnable into that mess. Get/SetWakeupTimer now
|
||
; take a record containing the wakeup time and an enable flag.
|
||
; <H94> 6/16/93 SWC The polarity of the hasInternalModem bit in the modem info
|
||
; selector was backwards, mainly because the PRAM bit,
|
||
; UseIntrnlModem, is set to 1 when using an EXTERNAL modem. Added
|
||
; a ‘wakeup on ring’ bit to the modem info selector. Added a new
|
||
; selector to set/clear the ‘wakeup on ring’ bit. Changed the
|
||
; default SCSI Disk Mode address from 1 to 2 so it doesn't
|
||
; conflict with the ID of a built-in hard disk in a DuoDock.
|
||
; <H93> 6/2/93 SWC Rolled in the modem type entry in the PowerDispatch hook from
|
||
; Excelsior. Added the modem type to the modem info selector on
|
||
; the public dispatch. Copied the public dispatch vector table
|
||
; into RAM.
|
||
; <H92> 6/1/93 SWC Only run the reduced speed routines if that feature is supported
|
||
; on a particular machine. Filled in the FactoryDisp entry in the
|
||
; PowerDispatch table wth a stub so that the RAM-based table gets
|
||
; built correctly.
|
||
; <H91> 5/31/93 RLE change set/getmachineid to set/getmachineattr (this way PG&E
|
||
; won't need to be updated for each and every new machine)
|
||
; <H90> 5/28/93 SWC Moved the absolute battery voltage from private to public
|
||
; dispatch. Added several new selectors to the public dispatch.
|
||
; <H89> 5/5/93 SWC Moved RunHardDiskQueue into the hard disk spindown routine so
|
||
; that it will only be called when the hard disk will really be
|
||
; spun down. Fixed a bug in SelectIntModem: it was always
|
||
; selecting the external modem.
|
||
; <H88> 5/4/93 SWC Allocated a buffer for reading/writing PRAM since the old buffer
|
||
; (a PMgr command parameter block) isn't available anymore. Always
|
||
; clear the NTSC low-mem so we'll get square corners on the main
|
||
; screen and menu bar.
|
||
; <H87> 5/4/93 SWC Made sure HardDiskQInstall/Remove return zero if no error.
|
||
; <H86> 5/4/93 SWC Added include of PowerMgrDispatchEqu.a. Added code to
|
||
; SetProcessorSpeed to allow for dynamically switching the
|
||
; processor speed on machines that support this feature.
|
||
; <H85> 4/23/93 SWC Moved the new PowerDispatch selectors down one in the table
|
||
; because #12 was used by the factory and patched in on disk.
|
||
; <H84> 4/22/93 RLE for SetMachineID/GetMachineID, force the count to be sent as
|
||
; part of the message packet
|
||
; <H83> 4/21/93 SWC Changed all routines that reference the primitives tables to
|
||
; assume that they exist instead of checking for a nil pointer.
|
||
; The initialization code will now hang if a table hasn't been set
|
||
; up. Added some more info to the modem info selector, and two new
|
||
; selectors to deal with disabling hard disk spindown. Added a new
|
||
; selector to _PowerDispatch to return a bitmap of private Power
|
||
; Manager features.
|
||
; <H82> 4/19/93 SWC Changed the primitives table initialization since there's now a
|
||
; vector to it in the ProductInfo table. Added new
|
||
; _PowerMgrDispatch selectors. Moved DoSpinDown here from
|
||
; SCSIMiscPatch.a.
|
||
; <H81> 4/16/93 SWC Pass the pointer to the queue element into the hdProc in
|
||
; RunHardDiskQueue
|
||
; <H80> 4/15/93 SWC Added in support for the public Power Manager interface trap,
|
||
; PowerMgrDisp ($A09E).
|
||
; <H79> 4/14/93 RLE add commands to set and get cutoff voltage
|
||
; <H78> 3/29/93 RLE add SetMachineID/GetMachineID commands to provide a mechanism to
|
||
; inform microcontroller what machine it might be running on; do
|
||
; SetMachine command as part of InitPmgrVars, but move part of the
|
||
; routine into MorePmgrInit to fit within the patch space
|
||
; <H77> 03-11-93 jmp Rolled back to the <H74> rev because we now handle the turning
|
||
; on/off the CSC in the CSCPrimaryInit.
|
||
; <H76> 3/9/93 RLE in the Power1Control call, add a 50 msec delay after powering up
|
||
; the CSC's PNLPWR output to allow it to fully charge
|
||
; <H75> 3/5/93 RLE add Power1Cntl and Power1Read to list of pmgr commands not
|
||
; entirely supported by PG&E microcontroller
|
||
; <H74> 3/3/93 RLE toss <H73> and prepare to do the LCD screen save/restore in the
|
||
; driver instead of in the power manager
|
||
; <H73> 2/24/93 RLE change InitPmgrPrimitives to support multiple table entries for
|
||
; a given decoder type
|
||
; <H72> 8/10/92 ag Fixed (aX,aY.w) addressing problem in serial power. aY being
|
||
; only size word does not allow for large movement of the
|
||
; primitives record (such as into ram).
|
||
; <H71> 8/4/92 ag Fixed (aX,aY.w) addressing problem. aY being only size word does
|
||
; not allow for large movement of the primitives record (such as
|
||
; into ram).
|
||
; <H70> 8/3/92 SWC ag/IdleMind wasn't using a long table offset. This causes a
|
||
; problem if the table is moved to RAM for patching.
|
||
; <H69> 7/31/92 SWC Backed out <H68> and instead just set D0=0 on exit of Wakeup.
|
||
; <H68> 7/30/92 SWC Added D0 to the list of SleepRegs so that the original sleep
|
||
; type will be returned on exit.
|
||
; <H67> 7/29/92 SWC Added a new call in the wakeup code to make sure we have the
|
||
; appropriate AppleTalk connection selected. This mostly applies
|
||
; to a docking environment where available SCC ports may change
|
||
; during sleep.
|
||
; <H66> 7/16/92 HJR In WakeUp move the SetSupervisorMode to the very end so that we
|
||
; can run on the UserStack. Since the interrupt stack is smaller,
|
||
; this fixes a problem where PaintBehind overflows the stack doing
|
||
; region calls.
|
||
; <H65> 7/14/92 ag Initialize the shorted battery alert delay if the charger is
|
||
; installed at powerup.
|
||
; <H64> 7/13/92 SWC In Wakeup, added a call to SCSIDiskWakeAlert to put up a
|
||
; DeepShit alert if the user has a SCSI Disk Mode cable plugged in
|
||
; when we wake up from sleep.
|
||
; <H63> 7/13/92 HJR Cleaned-up PowerMgrHook a little bit.
|
||
; <H62> 7/13/92 ag Rewrote the battery interrupt handler. Added new subhandlers to
|
||
; handle the battery shorted interrupt and the changer state
|
||
; change interrupt. Added new constants to the primitive
|
||
; infotable for delay of shorted battery dialog and delta battery
|
||
; warn level when using an external monitor.
|
||
; <H61> 7/11/92 ag Changed SecondaryInitDisp to PowerMgrHookDisp. The selector is
|
||
; now a general purpose selector with data passed in the upper
|
||
; word of d0. Added 3rd level dispatch table for PowerMgrHookDisp.
|
||
; Added scsi disk mode handler, and external monitor on handler.
|
||
; <H60> 7/11/92 HJR Changed the name of WakeScrnPtr to ScreenRedrawPtr and slightly
|
||
; modified the RestoreScreen routine.
|
||
; <H59> 7/10/92 ag Added softpower vector support. Created modem primitives, so
|
||
; moved all the serial overpatch stuff and part of the serial
|
||
; power stuff to PowerMgrPrimitives.a. With the new space in the
|
||
; serial power section moved the modem sound int stuff back to
|
||
; it's original location.
|
||
; <H58> 7/1/92 ag Add new modem commands to the dartexception table. ($71,$79).
|
||
; Commented command ($5D) as a general purpose modem command which
|
||
; is modem dependent.
|
||
; <H57> 7/1/92 SWC Disable level 3 modem interrupts as well as level 1 PMGR
|
||
; interrupts on DBLite. Put a line back into InitPMgrVars to clear
|
||
; the PMGR interrupt bit in the IFR (this seems to have been lost
|
||
; in the course of changes).
|
||
; <H56> 6/30/92 HJR Moved ADBReInit earlier in WakeUp so that user will have cursor
|
||
; feedback in wake.
|
||
; <H55> 6/29/92 GMR Updated a couple of the PMGROp modem cmd/reply counts in the
|
||
; tables.
|
||
; <H54> 6/26/92 GMR Added another modem command (SetDAAID) to the PmgrOp command
|
||
; table.
|
||
; <H53> 6/25/92 djw Fixed a bug in SerPowerOff (found by Steve Christensen) where
|
||
; the data length was not being set calling the _PmgrOp. The
|
||
; result was 5v was not being turned off to the modem.
|
||
; <H52> 6/18/92 SWC Setup PMgrOp to use vectors to make patching easier. These are
|
||
; now initialized in InitPMgrVars. Also in PMgrOp, don't point to
|
||
; the SCC if no PollProc is installed to avoid overflowing the
|
||
; stack when AppleTalk is running on port A (lotsa bytes stashed).
|
||
; Added a low power warning flag to IdleMind so we can tell that's
|
||
; why we're going to sleep.
|
||
; <H51> 6/11/92 djw Removed code to post a video warning message from PSecondaryInit
|
||
; because it did not take into account video waking from sleep
|
||
; case.
|
||
; <H50> 6/4/92 SWC Temporarily changed the reply count for the battery info command
|
||
; ($6D) until the PG&E code is updated to fix a bug.
|
||
; <H49> 6/2/92 SWC Fixed a bug I introduced in <H46>.
|
||
; <H48> 6/1/92 HJR Initialized PmgrRec.Charger in InitPmgrVars. Provided support in
|
||
; PSecondaryInit for external video warning if no charger
|
||
; installed.
|
||
; <H47> 5/29/92 SWC When waking up, check if a docking bar was attached that's not
|
||
; supposed to be attached during sleep, and if so, put the machine
|
||
; back to sleep.
|
||
; <H46> 5/28/92 SWC In NewPMgrTrap, A0 was trashed when we checked if we needed to
|
||
; delay for a power control command. It isn't anymore.
|
||
; <H45> 5/27/92 SWC Converted changes in <H44> into overpatches cuz as written they
|
||
; caused code to move (ROMBind problems in system disk patches).
|
||
; <H44> 5/20/92 ag Added DartSPI flag code to enable and disable the SPI interface
|
||
; depending on the modem connected.
|
||
; <H43> 5/19/92 HJR Added new selector, PDimScreens, to PowerDispatch Trap and added
|
||
; accompanying routine which powers down video. Changed
|
||
; HdDSpinDown to RunIdleRoutines, a more generalized routine.
|
||
; <H42> 5/15/92 SWC Added PMGR diagnostics (selector-based) command ($ED) entry to
|
||
; send and receive tables. Moved SndWatch, SndWatchPonti to
|
||
; PowerManagerPrimitives as yet another primitive, and fixed
|
||
; InitPMgrVars to look up the addresses from the primitives table.
|
||
; Sound VBLs are no longer installed by secondary init dispatch,
|
||
; since the sound VBLs check to make sure that patches are
|
||
; installed before calling the sound input primitives. Changed the
|
||
; way the PMgrOp exception table is set up to make the search
|
||
; faster.
|
||
; <H41> 5/12/92 ag Added secondary init dispatch routine for code execution at
|
||
; secondary init time. Removed sound primitives check for sound
|
||
; vbl code, vbl now installed at secondary init time. All patches
|
||
; should be in by then. Added Dart exception table for SPI. Moved
|
||
; init of softshutdown vars to secondary init code.
|
||
; <H40> 5/8/92 ag Fixed SoundPonti to check expand mem vector before using the
|
||
; vector.
|
||
; <H39> 5/8/92 ag Added dartanian busy check to NewPmgrTrap.
|
||
; <H38> 5/8/92 HJR Added new primitive for refreshing the screen from wake.
|
||
; <H37> 5/7/92 ag Added soft shutdown for Dartanian. Rolled in Modem sound
|
||
; patches. Added busy check in power manager protocal.
|
||
; <H36> 5/7/92 SWC Added a check in IdleMind to bail on sleeping if sleep is not
|
||
; allowed because of the kind of bar that's attached (avoids a
|
||
; dialog). Moved the beginning and end parts of NewPMgrTrap around
|
||
; a bit so I could add SCC polling to the delay loop for power
|
||
; control commands. Added a new selector to PowerDispatch to
|
||
; return a scaled battery level.
|
||
; <H35> 4/27/92 ag Added new sound watch to use registers in Ponti to control sound
|
||
; power.
|
||
; <H34> 4/24/92 HJR Fix some alignment problems.
|
||
; <H33> 4/24/92 HJR Added new SndWatchPtch to handle DFAC activity. Changed
|
||
; CheckForNewPMgr so the Niagra uses new PMgrTrap. Fixed
|
||
; Handle_Element bug where a QueueProc element returning error
|
||
; would still cause the machine to sleep.
|
||
; <H32> 4/22/92 SWC In GoToSleep, changed the BTST to a BSET to block re-entry into
|
||
; the sleep code earlier on in the process, and removed the BSET
|
||
; in DreamAway (duplication). Added a call to DockingSleepDenied
|
||
; (DockingMgr.a) if someone tries to put the system to sleep when
|
||
; connected to a bar that doesn't want that to happen.
|
||
; <H31> 4/17/92 SWC Fixed bugs in the power control/status emulation routines that
|
||
; sometimes cause the wrong information to be returned.
|
||
; <H30> 4/13/92 SWC Changed the table entry for "send DFAC command" to 2 bytes since
|
||
; we need to pass a byte for the input source as well so the PMGR
|
||
; can switch the MUX. Changed the readBattery command emulation to
|
||
; return a scaled battery level instead of maximum since we now
|
||
; check for the existance of a battery in the battery monitoring
|
||
; routine. Fixed a bug in InitPmgrPrimitives (hysteresis was
|
||
; being copied into a byte instead of a word).
|
||
; <H29> 3/11/92 SWC In InitPmgrVars, get the address of the power cycle register
|
||
; from the primitives table instead of a chain of TestFors.
|
||
; Installed a VBL task (for machines that support it) to monitor a
|
||
; clamshell switch so we can put the machine to sleep or shut it
|
||
; down. In Wakeup, always do an ADBReInit since new cursor stuff
|
||
; needs this to handle adding devices across sleep. Renamed
|
||
; JawsPwrCycReg to PowerCycleReg since non-Jaws machines use it
|
||
; too.
|
||
; <H28> 3/9/92 SWC Fixed the receive count for the PMGR soft reset command.
|
||
; <H27> 3/3/92 SWC Exported GetLevel for use in the SCSI DiskMode code.
|
||
; <H26> 2/26/92 SWC In NewPMgrTrap, fixed register usage and saving relating to
|
||
; polling the SCC since some registers aren't setup right, and
|
||
; others are getting trashed by the PollProc. Added a 125usec
|
||
; delay to the end of NewPMgrTrap on powerCntl calls to give the
|
||
; power planes a chance to stabilize.
|
||
; <H25> 2/21/92 HJR Cleaned up InitPmgrVars a bit. Fixed Batwatch to utilize to 3
|
||
; battery levels instead of 4. Also added sleep hysteresis to
|
||
; batwatch. Fixed reentrancy problem with sleep.
|
||
; <H24> 2/19/92 SWC Fixed the Wakeup padding (off by 2 bytes).
|
||
; <H23> 2/17/92 SWC Added docking checks to see if power cycling and/or sleep are
|
||
; allowed when we're connected to certain bars on DBLite.
|
||
; <H22> 2/14/92 SWC Added docking support to power control/status emulation on
|
||
; DBLite.
|
||
; <H21> 2/13/92 SWC Moved an emulated command in the table. Fixed a typo.
|
||
; <H20> 2/13/92 SWC Fixed a patch that the assembler had optimized to make 2 bytes
|
||
; shorter (I specified BSR.W, I got BSR.S).
|
||
; <H19> 2/10/92 SWC Added a new PowerDispatch selector to return the base Power
|
||
; Manager PRAM address so our clients won't have to go looking
|
||
; thru our globals.
|
||
; <H18> 2/7/92 SWC Write out default low/dead battery warning levels if the values
|
||
; read aren't valid. Default values now come from the ever popular
|
||
; primitives info table.
|
||
; <H17> 2/7/92 SWC Modified other places that reference Power Manager PRAM bytes to
|
||
; use the base address in the globals. Removed old HcMac code cuz
|
||
; it's confusing and more than likely won't be used again.
|
||
; <H16> 2/5/92 SWC Fixed a cut and paste boo-boo in <H15>.
|
||
; <H15> 2/5/92 SWC Moved a couple of the PMGR battery commands down in the tables
|
||
; since they were stomping on a pre-existing command. Changed how
|
||
; we get the low battery warning and dead battery levels from
|
||
; reading them from PRAM to using a specific command (available
|
||
; from the TIM days and carried on by DBLite).
|
||
; <H14> 2/4/92 SWC Adjusted padding since some stuff has moved a bit (wreaks havoc
|
||
; with patches). Re-wrote the sleep and wakeup code to use
|
||
; primitives tables to determine what needs to be done.
|
||
; <H13> 2/3/92 HJR Added support for PowerManagerPrimitives. Use PmgrPrim for
|
||
; default PRAM base, new IdleMind, and new CPUSpeed. Fixed
|
||
; HandleElement improperly aborting when encountering non-zero
|
||
; sleep queue return in DemandSleep.
|
||
; <H12> 1/28/92 SWC Did a bit of re-ordering in InitPMgrPatch2 to reduce the
|
||
; possibility of a race condition in clearing any unexpected PMGR
|
||
; interrupts.
|
||
; <H11> 1/27/92 SWC Updated NewPMgrTrap's transfer tables for new commands.
|
||
; <H10> 1/24/92 SWC Fixed the code to save/restore GSC registers over sleep. The new
|
||
; PMgrOp code (for DBLite) now uses only a 32ms timeout instead of
|
||
; having both long and short timeouts, so that when PG&E gets
|
||
; multiple interrupts we won't time out while waiting for it to
|
||
; respond.
|
||
; <H9> 1/9/92 SWC Rolled in changes for final chips: removed special case checks
|
||
; for PMGR interrupts on CA2 (now on CB1), extend DB-Lite's CPU
|
||
; speed code to support 25MHz/33MHz versions plus econo-mode.
|
||
; Added _PMgrOp emulation for SCSI and SCC clock control/status to
|
||
; the power control/status commands since these functions are now
|
||
; handled by the MSC. Save and restore GSC registers in the sleep
|
||
; code for DB-Lite.
|
||
; <H8> 10/29/91 SWC Cleared the interrupt flag before doing a blind interrupt read
|
||
; in InitPMgrPatch to make sure it isn't left in a weird state.
|
||
; Did miscellaneous cleanup in NewPMgrTrap. Turn on/off the
|
||
; serial driver chips as well as the SCC in SerialPower.
|
||
; <H7> 10/22/91 SWC Changed SCC polling in NewPMgrTrap to look at the SCC directly
|
||
; instead of using the VIA bit. Changed references to NoVRAMVidRam
|
||
; to point to the end of the record since the offsets are
|
||
; negative.
|
||
; <H6> 9/10/91 SWC Set battery voltage for ReadBattery emulation at maximum for
|
||
; now. Fixed the returned byte counts for the set/read sound
|
||
; emulated routines.
|
||
; <H5> 8/27/91 SWC Fixed the [temporary] jump to OneSecInt so that it instead jumps
|
||
; 6 bytes into the routine so the VIA's IFR is not cleared a
|
||
; second time. Depending on when one-second and ADB interrupts
|
||
; came along, it was possible to lose an ADB interrupt if it
|
||
; occurred just before the IFR bit was cleared in OneSecInt.
|
||
; <H4> 8/26/91 SWC Added Set Screen Brightness command ($41) to the command tables.
|
||
; <H3> 8/22/91 SWC Added in a call to the one-second interrupt handler from the
|
||
; PMgrInt. Vectored the send and receive count tables for
|
||
; NewPMgrTrap so we can make changes and additions without having
|
||
; to roll the ROM.
|
||
; <H2> 8/8/91 SWC Added universal PMgrOp code which will run on any Power
|
||
; Manager-based system. Universalized PMGR interrupt setup.
|
||
; Fixed sleep/wakeup sound chip register saving so Batman-specific
|
||
; registers are only saved if we've got a Batman. Added an MSC
|
||
; entry to the CPUSpeed routine. Added DB-Lite support to the
|
||
; sleep code. Fixed an unpatchable bug in InitPMgrVars that was
|
||
; found after TERROR was frozen (it just requires moving an
|
||
; instruction down).
|
||
; ———————————————————————————————————————————————————————————————————————————————————————
|
||
; Pre-HORROR ROM comments begin here.
|
||
; ———————————————————————————————————————————————————————————————————————————————————————
|
||
; <40> 7/11/91 HJR Call HDSpinDown in sleep if HDSpindownflag is not clear and on
|
||
; wakeup move KdbReset before interrupts are enabled. Also added
|
||
; SleepHook and WakeUpHook to sleep code, and vectorized ModemSnd
|
||
; Routines in PMgrGlobals.
|
||
; <39> 7/9/91 HJR Added CPUSpeed to PowerDispatch Trap and set SaveSpeedo to
|
||
; appropriate speed in InitPMgrVars.
|
||
; <38> 7/7/91 HJR Add some more reset for the progressive power cycling.
|
||
; <37> 7/3/91 HJR Fix VM powercycling problem by restoring the VBR if we decide to
|
||
; skip power cycling due to character pending on SCC.
|
||
; <36> 6/25/91 HJR Updated IdleMind to reset progressive power cycling
|
||
; appropriately. Fixed bug in PowerCycling030 and PowerCycling020
|
||
; to set AutoInt7 appropriately.
|
||
; <35> 6/25/91 ag added hysteresis low power value to power manager globals.
|
||
; <34> 6/25/91 HJR Set cursor to a watchcursor when going to sleep and fix a bug in
|
||
; IdleDelay where a BGE should have been a BLE.
|
||
; <33> 6/24/91 HJR Individually test SlpTimeOut and HDTimeOut for zero in
|
||
; InitPmgrVars. Determine whether running on '020 or '030 at
|
||
; InitPmgrVar and load appropriate power cycling code. Added
|
||
; IdleRead, IdleEnable, and IdleDisable to the list of
|
||
; PowerDispatchVectors and rewrote IdleState to use these new
|
||
; routines.
|
||
; <32> 6/24/91 djw Moved init code for notification mgr record from InstallMsg to
|
||
; InitPmgr. Added code to install and remove message in case of a
|
||
; bad battery condition interrupt from power mgr. Removed modem
|
||
; sound int handler from InitPmgr. Add support to disable posting
|
||
; notification messages for low power. Fixed bug in SerPowerOff
|
||
; and external ports. Added code to call LAPMgr for status of
|
||
; port B.
|
||
; <31> 6/12/91 ag changed the default of the network check to sleep.
|
||
; <30> 6/12/91 ag added network warning override bit in PmgrFlags.
|
||
; <29> 6/11/91 HJR Parameterized progressive power cycling with PwrCycProgGrow and
|
||
; PwrCycProgMax in PMgrRec. Fixed bug in Installmsg where stack
|
||
; was corrupted if message string was null.
|
||
; <28> 6/11/91 djw Fix modem sound support using VIA interrupt handlers.
|
||
; <27> 6/9/91 HJR Used new Default equates in InitPMgrVar for Power Cycling. Fixed
|
||
; bug in checking whether there has been enough elapsed time
|
||
; before power cycling. Added IdleDelay to PowerDispatch in order
|
||
; to improve IO performance. Modified the Batman saving and
|
||
; restoring from sleep so that the registers are written out in
|
||
; appropriate order. Cleared the Sound Latch after restoring from
|
||
; sleep to hopefully kill the buzzing sound while waking up.
|
||
; <26> 5/31/91 djw Add modem sound interrupt routines and install them in
|
||
; _SerialPower
|
||
; <25> 5/23/91 HJR Returned to a more universal power cycling scheme. Added include
|
||
; for PowerPrivEqu.a. Removed WaitStates sleep queue element since
|
||
; problem is now solved in hardware, HOPEFULLY!
|
||
; <24> 5/10/91 HJR Removed references of ResetSP since it is now saved in
|
||
; PMgrGlobalsRec. Changed PMgrTrap to call PollProc before
|
||
; interrupts re-enbled. Correct problem VM/NMI bug by setting and
|
||
; restoring NMIvector to the restore code during power cycling.
|
||
; <23> 4/29/91 HJR Added semaphor for power-up conditions in power cycling. Made
|
||
; sleep more universal by calculating the video-ram space from
|
||
; universal instead of using hard-coded addresses.
|
||
; <22> 4/23/91 ag switch back to supervisor mode on exit of sleep.
|
||
; <21> 4/23/91 ag alerts must be run in user mode! so we moved the restore to
|
||
; user mode earlier.
|
||
; <20> 4/22/91 ag Fixed missing dereference in data structure.
|
||
; <19> 4/16/91 HJR Somebody forgot to add a semicolon to the comment part of their
|
||
; line!
|
||
; <18> 4/15/91 ag added sound vbl code to turn off power to the sound circuits if
|
||
; not in use.
|
||
; <17> 4/12/91 ag changed the location of "insleep" flag in the power manager
|
||
; locals. Changed name of pram flags to avoid conflict with
|
||
; reality sources.
|
||
; <16> 4/4/91 ag slight correction to test for null proc.
|
||
; <15> 4/4/91 ag fixed bug with sleep queue execution. added check for null proc
|
||
; pointer.
|
||
; <14> 4/3/91 HJR Restore DFAC state on sleep wakeup
|
||
; <13> 4/1/91 HJR Modified the switching from User Mode to Supervisor Mode so that
|
||
; interrupts may be enable prior to running the queue out of
|
||
; wakeup since .MPP needs them enabled. Save all necessary Batman
|
||
; sound registers.
|
||
; <12> 3/29/91 ag Removed power manager bus contention check. the protocal has
|
||
; been changed to just check for busy and retry. Also changed
|
||
; timeout to take the new retry protocal into account (extended
|
||
; timeouts).
|
||
; <11> 3/19/91 jmp Oops, sombody forgot to put a semicolon in front of a comment.
|
||
; <10> 3/19/91 HJR Restore SP during wakeup since JumpintoRom sets it. Changed
|
||
; register useage in InitPMgrVars since GetRealProc trashes
|
||
; d1/a1-a2.
|
||
; <9> 3/18/91 HJR Rolled in sleep changes from Reality. Moved sleep to Ram based
|
||
; instead of video for performance improvement. Made sure that
|
||
; all access to the Video storage is done when the MMU is off
|
||
; because of
|
||
; MMU wrap.
|
||
; <8> 2/18/91 HJR Added DebugUtil call in IdleMind and GotoSleep to set the
|
||
; machine into Supervisor mode so that VM will be happy.
|
||
; <7> 1/30/91 HJR Changed PwrCycleCount to be part of PwrMgrVars and initialized
|
||
; in InitPwrMgrVars.
|
||
; <6> 1/24/91 HJR Cleared the bus prior to entering into power cycling by writing
|
||
; a zero to rom space. Also changed the write to the Jaws
|
||
; register to a Move.l and hit the waitstate register coming out
|
||
; of powercycle.
|
||
; <5> 1/24/91 HJR Moved IdleMind from PwrControlPatches.a. Also rewrote
|
||
; PowerCycling code for speed improvements and MMU bug fixes.
|
||
; <4> 1/22/91 djw Replace SerPowerOn and SerPowerOff in SerialPower trap code to
|
||
; work with TIM and the TIM modem.
|
||
; <3> 1/15/91 HJR Add WaitSSleepTask and install code to InitPMgrVars
|
||
; <2> 12/11/90 HJR Updated to the latest PowerMgr interface.
|
||
; <2.2> 6/10/89 SWC Moved InitPmgrVars here from StartInit.a.
|
||
; <2.1> 4/13/89 MSH Removed level 3 low power warning.
|
||
; <2.0> 4/7/89 MSH Gave battery and environment interrupts new names. PmgrInt now
|
||
; uses vectors to dispatch to handlers. Clearing low battery bit
|
||
; removes any low power message. CloseATalk saves D2.
|
||
; <1.9> 3/31/89 MSH Power off turns off the modem, then the rest of power, then
|
||
; calls sleep. CloseATalk rewritten. DOQueue now knows about
|
||
; sleepnow. If more than two ADB devices in use then ADBReInit
|
||
; called at wake up. A sleepnow hides the cursor. Batterymon
|
||
; replaced with SndWatch and made a vbl task.
|
||
; <1.8> 3/14/89 MSH CloseAtalk needed to close MPP. Mild warning didn't close XPP.
|
||
; At WakeUp restart timers the right way. ReInit Normandy test
|
||
; register after sleep. Ignore ENV interrupt.
|
||
; <1.7> 3/10/89 MSH PowerOff does a SleepNow
|
||
; <1.6> 3/9/89 MSH Forgot to check for any mounted file servers when sleep time
|
||
; out.
|
||
; <1.5> 3/2/89 MSH Reset keymap when sleep called. Spin down and sleep time outs
|
||
; reduced to one value each. Low power warning resources are
|
||
; loaded into local memory at init. No low power warning may occur
|
||
; before system task gets called once. Some local storage use got
|
||
; proper equ names.
|
||
; <1.4> 2/8/89 MSH Added high temperature warning support, moved all hard disk and
|
||
; sleep time out to systemtask, low power warnings are now four in
|
||
; number. The last warning goes to sleep in ten seconds. Sleep now
|
||
; has request, demand, and now, the last is for low power
|
||
; condition. Before calling the sleep queue a check is made of the
|
||
; AppleTalk world and if any servers or other activity is present.
|
||
; If so the user is warned and given the option to undo sleep. A7
|
||
; is now saved in undisplayed video ram rather than in SERegs
|
||
; where it interfered with Macsbug. Make use of charger status
|
||
; bits to determine if charger connection state has changed.
|
||
; <1.3> 12/14/88 MSH Save and restore RAM wait state register, power off uses jump to
|
||
; startboot instead of RESET, kick on timer 1 after sleep.
|
||
; <1.2> 11/30/88 MSH Fixed the sound control stuff. Gave time out flags legit name.
|
||
; Save and restore speed from stack.
|
||
; <1.1> 11/10/88 CCH Fixed Header.
|
||
; <1.0> 11/9/88 CCH Adding to EASE.
|
||
; <2.2> 11/1/88 MSH Added a whole bunch of stuff. First, the sound watchdog is in
|
||
; and running. If no one hits on the ASC for ten seconds then the
|
||
; amplifier power is turned off. Also save and restore the ASC
|
||
; control registers at sleep. Second, the battery monitor and low
|
||
; power interrupt handler are in place. The user is alerted via
|
||
; the background notification manager of entering reserve power
|
||
; use, half reserve left, and a quarter of reserve power left. One
|
||
; SICN and three STR resources required on system disk. Last, the
|
||
; power off code called from the shutdown manager is found here.
|
||
; <2.1> 9/29/88 MSH Moved the reading of the charger state and time outs from the
|
||
; one second stuff to an interrupt routine. BatteryAlrt handles
|
||
; the charger connected state change interrupt from the power
|
||
; manager. BatteryMon checks the dirty time out data flag to see
|
||
; if it is necessary to update the time outs due to a change to
|
||
; them from the battery desk accessory.
|
||
; <1.9> 9/12/88 MSH Fixed bug in stack framse usage. One second interrupt now points
|
||
; to BatteryMon. BatteryMon first calls the one second interrupt
|
||
; then checks the state of the battery charger and the time outs.
|
||
; Screen saving no longer allocates memory.
|
||
; <1.8> 8/5/88 MSH Made WakeUp vectored. Added sleep q calling code.
|
||
; <1.7> 7/19/88 MSH Fixed potential stack error in PMGRInt. Save the state of the
|
||
; PMGR interrupt bit from VIA at entry and restore on exit. Also
|
||
; do more VIA save and restore at wake up.
|
||
; <1.6> 6/24/88 MSH Many revisions: Use pmgr local vars to save clock speed. Check
|
||
; for valid pmgr vars pointer before using it. Went back to
|
||
; original busy test of pmgr chip. Sleep command now has signature
|
||
; word sent with command. Removed InitIWM call, didn't actually do
|
||
; anything anyway. Temporarily removed call to ADBreInit and added
|
||
; kludge to keep old power managers auto polling after sleep.
|
||
; <1.5> 6/15/88 MSH Removed one too many SWAPs from PmgrDone. Also changed the test
|
||
; for pmgr ready to only use the upper half of the port.
|
||
; <1.4> 5/23/88 MSH Trashing speed code saved in upper half of D3 with a MOVEQ.
|
||
; <1.3> 5/19/88 BBM Changed two MOVEQs to MOVE.Ls as they were out of range
|
||
; <1.2> 4/21/88 MSH Fixed reset vector getting trashed when saving screen.
|
||
; <1.1> 3/28/88 BBM Made sure that this code runs at 16M. Blank screen before sleep.
|
||
; <1.0> 2/10/88 BBM Adding file for the first time into EASE…
|
||
; <C988> 12/21/87 MSH Exported GoToSleep for use by toolevents.
|
||
; <C984> 12/16/87 MSH Made start of handshake more tolerant of interrupts.
|
||
; <C937> 11/6/87 MSH Mask out PMGR interrupts while in PmgrOp.
|
||
; <C930> 11/5/87 MSH Rewrote PmgrInt to use new interrupt interface to PMGR.
|
||
; <C916> 10/21/87 MSH More of the same.
|
||
; <C915> 10/20/87 MSH Fixed some bugs, turned off interrupts while waiting for pmgr
|
||
; ack, and preserved sound bits that may be in VIA port A.
|
||
; 9/21/87 MSH New today.
|
||
;
|
||
|
||
BLANKS ON
|
||
STRING ASIS
|
||
|
||
PRINT OFF
|
||
LOAD 'StandardEqu.d'
|
||
INCLUDE 'HardwarePrivateEqu.a'
|
||
INCLUDE 'UniversalEqu.a'
|
||
INCLUDE 'PowerPrivEqu.a'
|
||
INCLUDE 'PowerMgrDispatchEqu.a'
|
||
INCLUDE 'Appletalk.a'
|
||
INCLUDE 'LAPEqu.a'
|
||
INCLUDE 'Notification.a'
|
||
INCLUDE 'IopEqu.a'
|
||
INCLUDE 'Egretequ.a'
|
||
INCLUDE 'AppleDeskBusPriv.a'
|
||
INCLUDE 'MMUEqu.a'
|
||
INCLUDE 'IOPrimitiveEqu.a'
|
||
INCLUDE 'DockingEqu.a'
|
||
INCLUDE 'GestaltEqu.a'
|
||
|
||
INCLUDE 'ROMEqu.a'
|
||
INCLUDE 'Slots.a'
|
||
PRINT ON
|
||
|
||
MACHINE MC68030
|
||
MC68881
|
||
|
||
|
||
Unimplement EQU $A89F ; _Unimplemented trap
|
||
|
||
|
||
|
||
PowerMngr PROC EXPORT
|
||
|
||
EXPORT InitPmgrVars
|
||
|
||
IF hasPwrControls THEN
|
||
EXPORT BatInt
|
||
EXPORT BatWatch
|
||
EXPORT GoToSleep
|
||
EXPORT PmgrInt
|
||
EXPORT PmgrOp
|
||
EXPORT PortableCheck
|
||
EXPORT PowerDispatch
|
||
EXPORT PowerDownAll
|
||
EXPORT SetSupervisorMode
|
||
EXPORT WakeUp
|
||
EXPORT PmgrTrap
|
||
EXPORT IdleUpdate
|
||
EXPORT IdleUpdateTrap
|
||
EXPORT IdleDelay
|
||
EXPORT IdleMind
|
||
EXPORT IdleRead
|
||
EXPORT IdleEnable
|
||
EXPORT IdleDisable
|
||
EXPORT IdleState
|
||
EXPORT CPUSpeed
|
||
EXPORT BasePRAM
|
||
EXPORT ScaledBattery
|
||
EXPORT PowerMgrHook
|
||
EXPORT PDimScreens
|
||
EXPORT PMGRrecv
|
||
EXPORT PMGRsend
|
||
EXPORT PrivateFeatures
|
||
EXPORT SecondaryInitproc
|
||
EXPORT SerialPower
|
||
EXPORT ScsiDiskModeproc
|
||
EXPORT ExternaVideoOnproc
|
||
EXPORT ModemTypeProc
|
||
EXPORT PowerMgrDispatch
|
||
EXPORT ModemStatusRT
|
||
EXPORT LCDScreenChk
|
||
EXPORT GetButtonValues
|
||
EXPORT SetHDState
|
||
|
||
IMPORT CacheFlush ; Dispatch.a
|
||
IMPORT DelayNMsec ; PowerMgrPrimitives.a
|
||
IMPORT DockingSleepDenied ; DockingMgr.a
|
||
IMPORT DockingWakeupDenied ; DockingMgr.a
|
||
IMPORT GetHardwareInfo ; Universal.a
|
||
IMPORT GetRealProc ; GetReal.a
|
||
IMPORT GracefulShutdown ; DockingMgr.a
|
||
IMPORT InitQueue ; Queue.a
|
||
IMPORT InitSCSIHW ; SCSIMgrInit.a
|
||
IMPORT InitWallyWorld ; WallyWorld.a
|
||
IMPORT RdXByte ; USTPram.a
|
||
IMPORT RSetKMap ; ADBMgr.a
|
||
IMPORT SCSIDiskWakeAlert ; SCSIDiskMode.a
|
||
IMPORT SetupTimeK ; StartInit.a
|
||
IMPORT USTPMgrSendByte ; USTStartUp.a
|
||
IMPORT USTPMGRSendCommand ; USTStartUp.a
|
||
|
||
WITH NMRec,PmgrRec,ADBVars,ADBDeviceEntry
|
||
WITH DecoderInfo,DecoderKinds,ProductInfo,VideoInfo,SpBlock
|
||
WITH pmCommandRec,SleepqRec,PowerCycleRec,PowerDispRec,PmgrPramRec
|
||
WITH PmgrPrimitivesRec,PmgrRoutineRec,PrimInfoTbleRec
|
||
WITH IdleMindTblRec,ModemTblRec,HDQueueElement
|
||
ENDIF
|
||
|
||
;••••••••••••••••••••••••••••••••••• Initialization •••••••••••••••••••••••••••••••••••••
|
||
;
|
||
; Contains:
|
||
;
|
||
; InitPMgrVars
|
||
; SetUpPmgrBase
|
||
; SizeTables
|
||
; BuildTables
|
||
; InitPmgrGlobals
|
||
; InitPMgrOp
|
||
; DoPmgrCommands
|
||
; GetPmgrPRAM
|
||
; InstallVBLs
|
||
;________________________________________________________________________________________
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: InitPMgrVars
|
||
;
|
||
; Inputs: none
|
||
;
|
||
; Outputs: none
|
||
;
|
||
; Trashes: none
|
||
;
|
||
; Function: allocates and initialized system heap space for the Power Manager's variables,
|
||
; installs VBL tasks, etc.
|
||
;________________________________________________________________________________________
|
||
|
||
InitPmgrVars
|
||
IF hasPwrControls THEN
|
||
TestFor hwCbPwrMgr
|
||
BNE.S @DoPMgrInit ; IF pmgr exists THEN intall pmgr stuff
|
||
ENDIF ; {hasPwrControls}
|
||
|
||
LEA @Traps,A1 ; ELSE remove the PmgrOp and Sleep traps
|
||
MOVE.W (A1)+,D0 ; Get the Unimplimented trap location
|
||
_GetTrapAddress ,newTool ;
|
||
@TrapLoop ; WHILE !EndOfList DO {
|
||
MOVE.W (A1)+,D0 ; Get the next trap to remove
|
||
BEQ.S @exit ;
|
||
_SetTrapAddress ,newOS ; Replace the trap with the Unimplimented
|
||
BRA.S @TrapLoop ; } LOOP
|
||
@exit ;
|
||
RTS ; EndELSE
|
||
|
||
@Traps _Unimplemented
|
||
_PmgrOp
|
||
_PowerDispatch
|
||
_Sleep
|
||
DC.W 0
|
||
|
||
IF hasPwrControls THEN
|
||
|
||
@DoPMgrInit
|
||
@WorkingSet REG D0-D3/A0-A3
|
||
MOVEM.L @WorkingSet,-(SP) ; save them regs
|
||
|
||
BSR SetUpPmgrBase ; set up the PMgr Globas A3 = PmgrGlobals
|
||
BSR InitPmgrGlobals ; Initialize our primitives table
|
||
BSR InitPMgrOp ; Initialize variables used by PMgrOp
|
||
BSR DoPmgrCommands ; Initialize variables through the PMgrOp Call
|
||
|
||
BSR DoDynamicSpeedChange ; Initialize timing constants for full/reduced speed
|
||
BSR GetPmgrPRAM ; Initialize variables through PRam
|
||
|
||
LEA SleepQHdr(A3),A1 ; init sleep queue
|
||
BSR.L InitQueue ; go do it
|
||
|
||
BSR InstallVBLs ; Install our VBLs
|
||
; BSR.L HandleChargeTime ; setup for bulk charge extension
|
||
|
||
LEA PMGRInt,A0 ; get addr of PMGR interrupt handler
|
||
MOVE.L A0,Lvl1DT+(4*ifCB1) ; install as PMGR interrupt receiver
|
||
|
||
BSR ResetPMGRInts ; clear any pending PMGR interrupts
|
||
MOVEM.L (SP)+,@WorkingSet ; restore them regs
|
||
RTS
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: SetUpPmgrBase
|
||
;
|
||
; Inputs: none
|
||
;
|
||
; Outputs: A3 - Ptr to PmgrGlobals
|
||
;
|
||
; Trashes: none
|
||
;
|
||
; Function: Determines the appropriate size of the PmgrGlobals section. It takes as a base
|
||
; the PmgrVarSize and walks through the primitives table and sums up there sizes.
|
||
;________________________________________________________________________________________
|
||
SetUpPmgrBase
|
||
@WorkingSet REG D0/A0-A2
|
||
MOVEM.L @WorkingSet,-(SP) ; Save them regs
|
||
MOVEA.L UnivInfoPtr,A1 ; point to the ProductInfo table
|
||
ADDA.L PowerManagerPtr(A1),A1 ; then to the Power Manager's primitives
|
||
MOVE.L #PmgrVarSize,D0 ; Start with the Vars Size
|
||
BSR SizeTables ; Size the table for new ptr
|
||
_NewPtr ,SYS,CLEAR ; allocate space on heap and clear
|
||
MOVE.L A0,PmgrBase ; save ptr to it
|
||
LEA PmgrVarSize+8(A0),A2 ; get the vPrimitives pointer
|
||
MOVE.L A2,vPMgrPrimitives(A0) ; set the vPMgrPrimitives vector
|
||
MOVEA.L A2,A0 ; set pointer to beginning of our memory chunk
|
||
BSR BuildTable ; build table
|
||
BSR.L CacheFlush ; flush caches to be safe
|
||
MOVE.L PmgrBase,A3 ; A3 = Ptr to PmgrGlobals
|
||
|
||
MOVEQ #4/4,D0 ; get the size of the public dispatch table
|
||
ADD.W PwrMgrDispVects-2,D0 ;
|
||
ASL.L #2,D0 ;
|
||
_NewPtr ,SYS ; and allocate space for it in the system heap
|
||
BNE.S @GetOut ; -> errors aren't allowed
|
||
|
||
LEA PwrMgrDispVects-4,A1 ;
|
||
MOVE.L (A1)+,D0 ; get the flags and routine count
|
||
MOVE.L D0,(A0)+ ; and copy them to RAM
|
||
MOVE.L A0,vPublicDispatch(A3) ; save the pointer to the start of the table
|
||
MOVE.L A1,D1 ; remember where the table starts in ROM
|
||
SUBQ.W #1,D0 ; adjust the count for the DBRA
|
||
@CopyPublic MOVE.L (A1)+,(A0) ; copy the routine offset into RAM
|
||
ADD.L D1,(A0)+ ; and convert it into an address
|
||
DBRA D0,@CopyPublic ; next entry
|
||
@GetOut
|
||
MOVEM.L (SP)+,@WorkingSet ; Restore them regs
|
||
RTS
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: SizeTables
|
||
;
|
||
; Inputs: A1 - Pointer to top of table
|
||
; D0 - Initial size of to be incremented
|
||
;
|
||
; Outputs: D0 - Incremented Size of Table
|
||
;
|
||
; Trashes: none
|
||
;
|
||
; Function: Determines the appropriate size of the tables.
|
||
;________________________________________________________________________________________
|
||
SizeTables
|
||
@WorkingSet REG D1-D3/A1-A2
|
||
|
||
MOVEM.L @WorkingSet,-(SP) ; save them registers
|
||
|
||
MOVE.L -8(A1),D1 ; get the flags
|
||
ANDI.L #PrimsTypeMask,D1 ; mask out all but last two bits
|
||
MOVE.W @EntryType(D1.W*2),D1 ; get the offset to that routine
|
||
JMP @EntryType(D1) ; go to that routine
|
||
|
||
@Table ; Size a Table of Tables
|
||
MOVE.L -4(A1),D1 ; setup dbra counter
|
||
LSR.L #2,D1 ; arrange it as long word entries
|
||
MOVEA.L A1,A2 ; A2 = Beginning rom base of table
|
||
ADD.L -4(A1),D0 ; increment for size of table
|
||
ADDQ #8,D0 ; account for the size byte and the flags
|
||
MOVEQ #0,D2 ; clear the register
|
||
@TblLoop ; FOR 0 to MaxNum DO
|
||
MOVE.L (A2,D2.L*4),D3 ; get the offset of the first routine
|
||
BEQ.S @NilValue ; if offset = 0 then bail
|
||
LEA (A2,D3.L),A1 ; get pointer to table
|
||
BSR SizeTables ; build the table
|
||
@NilValue ADDQ.L #1,D2 ; increment index
|
||
CMP.L D1,D2 ; .
|
||
BLT.S @TblLoop ; LOOP
|
||
BRA.S @Done
|
||
@PmgrEx
|
||
@Ptr
|
||
@Info
|
||
ADD.L -4(A1),D0 ; increment the size
|
||
ADDI.L #8,D0 ; add in flags and size field
|
||
@Done
|
||
MOVEM.L (SP)+,@WorkingSet ; restore them registers
|
||
RTS
|
||
|
||
@EntryType
|
||
DC.W @Table-@EntryType ; Table of Tables
|
||
DC.W @Ptr-@EntryType ; Table of pointers
|
||
DC.W @Info-@EntryType ; Table of info
|
||
DC.W @PmgrEx-@EntryType ; Table of Power Manager Op Exceptions
|
||
DC.W 0 ; Expansion
|
||
DC.W 0 ; Expansion
|
||
DC.W 0 ; Expansion
|
||
DC.W 0 ; Expansion
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: BuildTables
|
||
;
|
||
; Inputs: A0 - Ptr to location where table is to be built
|
||
; A1 - Ptr to ROM table
|
||
;
|
||
; Outputs: none
|
||
;
|
||
; Trashes: none
|
||
;
|
||
; Function: Build all the tables into ram and convert all offsets into pointers for easier
|
||
; patching.
|
||
;________________________________________________________________________________________
|
||
BuildTable
|
||
@WorkingSet REG D0-D3/A0-A3
|
||
|
||
MOVEM.L @WorkingSet,-(SP) ; save them registers
|
||
LEA -8(A1),A1 ; get pointer to flags
|
||
MOVE.L (A1)+,D0 ; get a copy of the flags
|
||
MOVE.L (A1)+,D1 ; get a copy of the size
|
||
|
||
MOVE.L D0,-8(A0) ; copy out the flags
|
||
MOVE.L D1,-4(A0) ; copy out the size
|
||
|
||
LSR.L #2,D1 ; arrange it as long word entries
|
||
ANDI.L #PrimsTypeMask,D0 ; mask out all but last two bits
|
||
MOVE.W @EntryType(D0.W*2),D0 ; get the offset to that routine
|
||
JMP @EntryType(D0) ; go to that routine
|
||
|
||
@EntryType
|
||
DC.W @Table-@EntryType ; Table of Tables
|
||
DC.W @Ptr-@EntryType ; Table of pointers
|
||
DC.W @Info-@EntryType ; Table of info
|
||
DC.W @PmgrExLoop-@EntryType ; Table of Power Manager Op Exceptions
|
||
DC.W 0 ; Expansion
|
||
DC.W 0 ; Expansion
|
||
DC.W 0 ; Expansion
|
||
DC.W 0 ; Expansion
|
||
|
||
@Table ; Build a Table of Tables
|
||
MOVEA.L A0,A3 ; A3 = Beginning ram base of table
|
||
MOVEA.L A1,A2 ; A2 = Pointer to rom base of table
|
||
MOVEQ #0,D2 ; clear the register
|
||
@TblLoop ; FOR 0 to MaxNum DO
|
||
ADD.L -4(A1),A0 ; increment ram pointer for size of table
|
||
ADDQ.W #8,A0 ; account for the size byte and the flags
|
||
@Cont MOVE.L (A2,D2.L*4),D3 ; get the offset of the first routine
|
||
BEQ.S @NullVal ; IF offset != 0 THEN
|
||
MOVE.L A0,(A3,D2.L*4) ; save pointer to table in table
|
||
LEA (A2,D3.L),A1 ; make it a pointer
|
||
BSR.S BuildTable ; build the table
|
||
ADDQ.L #1,D2 ; increment index
|
||
CMP.L D1,D2 ; .
|
||
BLT.S @TblLoop ; LOOP
|
||
BRA.S @Done
|
||
|
||
@NullVal ADDQ.L #1,D2 ; increment index
|
||
CMP.L D1,D2 ; .
|
||
BLT.S @Cont ; LOOP
|
||
BRA.S @Done ; and continue on
|
||
|
||
@Ptr ; Build a Table of Pointers
|
||
MOVEQ #0,D2 ; clear the register
|
||
@PtrLoop ; FOR 0 to MaxNum DO
|
||
MOVE.L (A1,D2.L*4),D3 ; get the offset of the first routine
|
||
BEQ.S @NullValue ; IF offset != 0 THEN
|
||
ADD.L A1,D3 ; add the offset
|
||
@NullValue MOVE.L D3,(A0)+ ; save it in the table
|
||
ADDQ.L #1,D2 ; increment index
|
||
CMP.L D1,D2 ; .
|
||
BLT.S @PtrLoop ; LOOP
|
||
BRA.S @Done
|
||
@Info ; Build a Table of Info
|
||
SUBQ.W #1,D1 ; help out dbra god
|
||
@InfoLoop ; FOR 0 to MaxNum DO
|
||
MOVE.L (A1)+,(A0)+ ; copy info directly
|
||
DBRA D1,@InfoLoop ; LOOP
|
||
BRA.S @Done
|
||
|
||
@PmgrExLoop ; WHILE notDone DO { <K12>
|
||
MOVE.W (A1)+,D0 ; get the mask & Exception |
|
||
MOVE.W D0,(A0)+ ; copy them directly into Ram Tables v
|
||
BEQ.S @Done ; IF mask & Exception == NULL THEN notDone = FALSE
|
||
MOVE.L A1,D0 ; get pointer to entry
|
||
ADD.L (A1)+,D0 ; calculate the handler's address
|
||
MOVE.L D0,(A0)+ ; stuff address in the Ram Tables
|
||
BRA.S @PmgrExLoop ; } <K12>
|
||
@Done
|
||
MOVEM.L (SP)+,@WorkingSet ; restore them registers
|
||
RTS
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: InitPmgrGlobals
|
||
;
|
||
; Inputs: A3 -- Pointer to PmgrVars
|
||
;
|
||
; Outputs: none.
|
||
;
|
||
; Trashes: D0/A0-A2
|
||
;
|
||
; Function: Determines the appropriate size of the tables.
|
||
;
|
||
;________________________________________________________________________________________
|
||
|
||
InitPmgrGlobals
|
||
|
||
; Initialize using InfoTbl
|
||
LoadTbl PrimInfoTblPtr,A3,A2
|
||
MOVE.B PrimPRAMBase(A2),\
|
||
PRAMbase(A3) ; Save value in globals for future reference
|
||
MOVEQ #0,D0 ; clear D0
|
||
MOVE.B PrimDefHyst(A2),D0 ; get a byte from primitives
|
||
MOVE.W D0,Hysteresis(A3) ; set default hysteresis value <H30>
|
||
MOVE.W PrimLowWarn(A2),\
|
||
LowWarn(A3) ; set default low/dead battery warning levels
|
||
MOVE.W PrimPRAMBase(A2),D0 ; get PrimWakeLvl:PrimBatWarnCt in d0 <H62>
|
||
EXT.W D0 ; extend the byte value to word (value should be < 127) <H62>
|
||
MOVE.W D0,BatteryWarnDly(A3) ; load the dialog delay count for shorted battery int's <H62>
|
||
MOVE.W D0,BatteryWarnCnt(A3) ; init battery warning count for shorted battery int's
|
||
MOVE.L PowerCycRegAddr(A2),\
|
||
PowerCycleReg(A3) ; get the address of the power cycle register
|
||
MOVE.B PrimCycRegValue(A2),\
|
||
PwrCycRegValue(A3) ; get the value for the power cycle register <K20>
|
||
|
||
; Initialize using RoutinesTbl
|
||
LoadTbl PmgrRoutineTbl,A3,A2
|
||
MOVE.L PowerCycPtr(A2),D0
|
||
MOVE.L D0,PwrCycProc(A3) ; Save pointer in Globals <H24>
|
||
|
||
MOVE.L PowerCycResPtr(A2),D0
|
||
MOVE.L D0,PwrCycRestore(A3) ; Save pointer in Globals <H24>
|
||
|
||
MOVE.W #PwrCycWaitTmDef,\
|
||
PwrCycWaitTime(A3) ; Set PwrCycWaitTime
|
||
MOVE.W #PwrCycSynCntDef,\
|
||
PwrCycSyncCount(A3) ; Set number of SyncIdles <27> HJR
|
||
MOVE.W #PwrCycleDef,\
|
||
PwrCycCounter(A3) ; Set number of power cycle loops. <7> HJR
|
||
MOVE.W #PwrCycDelayDef,\
|
||
PwrCycDelay(A3) ; Set default delay <27> HJR
|
||
MOVE.W #PwrCycProgGrowDef,\
|
||
PwrCycProgGrow(A3) ; Set growth increment for power cycling <29> HJR
|
||
MOVE.W #PwrCycProgMaxDef,\
|
||
PwrCycProgMax(A3) ; Set maximum size for power cycling <29> HJR
|
||
MOVE.L #$0FFFFFFF,\
|
||
DimmingWaitTime(A3) ; Set Time till we start dimming
|
||
|
||
|
||
MOVE.L EnvIntPtr(A2),D0
|
||
MOVE.L D0,vEnvInt(A3) ; save the handler address (or nil if none)
|
||
|
||
; Initialize the rest
|
||
|
||
MOVEQ #1,D0
|
||
MOVE.L D0,LastAct(A3) ; Init last activity and disk counters <v3.7>
|
||
MOVE.L D0,LastHd(A3)
|
||
|
||
ADDQ.W #nmType,BNmQEntry+qType(A3) ; initialize some notification record fields <H52>
|
||
MOVEQ #-1,D0
|
||
MOVE.L D0,BNmQEntry+nmSound(A3); Use default sound <H52>
|
||
|
||
LEA BatInt,A1 ; Set up int handlers <v4.9>
|
||
MOVE.L A1,vBatInt(A3)
|
||
|
||
LEA WakeUp,A1 ; Get Address of WakeUp Routine
|
||
MOVE.L A1,WakeVector(A3) ; Save in the Globals
|
||
|
||
MOVE.L A3,A0 ; Param A0 = Ptr to Pmgr Globals
|
||
IF NOT forRomulator THEN ; <SM4>
|
||
BSR.L GetRealProc ; Get the physical address of PMgrVars--Warning Destroys Regs D1/A1-A2
|
||
ENDIF
|
||
MOVE.L A0,PmgrVarPhysPtr(A3) ; Save it off in PwrMgr Globals
|
||
|
||
MOVE.W #CPUSpeedDisp,D0 ; Find out what speed we are running <39> HJR
|
||
_PowerDispatch ; <39> HJR
|
||
MOVE.B D0,SaveSpeedo(A3) ; Set saveSpeedo to current speed <39> HJR
|
||
|
||
LEA DoSpinDown,A1 ; initialize the hard disk spindown vector <H82>
|
||
MOVE.L A1,HDvector(A3) ; <H82>
|
||
|
||
LEA DoHDSpinUP,A1 ; initialize the hard disk spinup vector <H82>
|
||
MOVE.L A1,HDSpinUpVector(A3) ; <H82>
|
||
|
||
BigLEA GracefulShutdown,A1 ; issue shutdown command (AppleEvent) <H59>
|
||
MOVE.L A1,vSoftShutdown(A3) ; <H59>
|
||
|
||
LEA ModemSndOnInt,A1 ; get addr of modem sound interrupt handler <t28> djw
|
||
MOVE.L A1,MdmSndVect(A3) ; install PmgrGlobal <40> HJR
|
||
|
||
ST TOdirtyFlag(A3) ; set time outs to be dirty
|
||
|
||
BSET.B #ClamshellClosed,\
|
||
PmgrFlags(A3) ; initialize the value to be closed <K26>
|
||
RTS
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: InitPMgrOp
|
||
;
|
||
; Inputs: A3 -- pointer to Power Manager's variables
|
||
;
|
||
; Outputs: none
|
||
;
|
||
; Trashes: D1/A0-A2
|
||
;
|
||
; Function: initializes all the variables required by PMgrOp
|
||
;________________________________________________________________________________________
|
||
|
||
InitPMgrOp LEA cmdCounts,A0 ; save pointers to the PMgrOp send/receive count tables <H52>
|
||
MOVE.L A0,vSendCountTbl(A3) ; <H52>
|
||
LEA replyCounts,A0 ; <H52>
|
||
MOVE.L A0,vRecvCountTbl(A3) ; <H52>
|
||
BSR.S SetupPMgrOpInterface ; get the PMgrOp exception table <H52>
|
||
MOVE.L A1,pmgrOpExceptions(A3) ; and save it <H52>
|
||
RTS ; <H52>
|
||
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: SetupPMgrOpInterface
|
||
;
|
||
; Inputs: none
|
||
;
|
||
; Outputs: D1 -- communications protocol (0=parallel, 2=serial, ...)
|
||
; D2 -- 0 = Rom Exception Tables <K15>
|
||
; A1 -- pointer to the start of an exception table
|
||
;
|
||
; Function: returns the protocol type, and a pointer to an exception table for
|
||
; handling commands that are either partially or not handled by the
|
||
; PMGR microcontroller due to differences in hardware implementations.
|
||
;
|
||
; Each entry consists of a byte for the "don't care bits" mask,
|
||
; a byte for the command number, and a long word for a relative
|
||
; offset from the current location to the special handler.
|
||
;________________________________________________________________________________________
|
||
|
||
SetupPMgrOpInterface
|
||
MOVE.L PmgrBase,A3 ; get pointer to PmgrBase
|
||
MOVEQ #0,D1 ; clear register
|
||
MOVE.L A3,D2 ;
|
||
|
||
ADDQ.L #1,D2 ; IF Power Manager vars valid THEN
|
||
BEQ.S @UseROMExceptions ;
|
||
|
||
LoadTbl PrimInfoTblPtr,A3,A1 ; A0 = Power Managers Info table (RAM)
|
||
MOVE.B PrimPMgrCommType(A1),D1 ; D1 = communications protocol type (RAM)
|
||
LoadTbl PMgrOpExcepTbl,A3,A1 ; A1 = Power Managers Exception Table (RAM)
|
||
RTS ; ELSE
|
||
|
||
@UseROMExceptions ;
|
||
MOVEA.L UnivInfoPtr,A1 ; A1 = ProductInfo table (ROM)
|
||
ADDA.L PowerManagerPtr(A1),A1 ; A1 = ROM Power Manager's primitives (ROM)
|
||
MOVEA.L A1,A2 ; A2 = A1
|
||
ADDA.L PrimInfoTblPtr(A2),A2 ; A2 = Power Managers Info table (ROM)
|
||
|
||
MOVE.B PrimPMgrCommType(A2),D1 ; D1 = communications protocol type (ROM)
|
||
ADDA.L PMgrOpExcepTbl(A1),A1 ; A1 = Power Managers Exception Table (ROM)
|
||
RTS ;
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: DoPmgrCommands
|
||
;
|
||
; Inputs: A3 -- Pointer to PmgrVars
|
||
;
|
||
; Outputs: none.
|
||
;
|
||
; Trashes: D0/A0-A1
|
||
;
|
||
; Function: Determines the appropriate size of the tables.
|
||
;
|
||
;________________________________________________________________________________________
|
||
|
||
DoPmgrCommands
|
||
CLR.L -(SP) ; zero the buffer <H18>
|
||
MOVE.L SP,-(SP) ; pmRBuffer <H18>
|
||
MOVE.L (SP),-(SP) ; pmSBuffer <H18>
|
||
CLR.W -(SP) ; pmLength = 0 <H18>
|
||
MOVE.W #PmgrADBoff,-(SP) ; pmCommand = turn off ADB auto poll <H18>
|
||
MOVEA.L SP,A0 ; point to the parameter block <H18>
|
||
_PMgrOp ; send the command <H18>
|
||
|
||
LoadTbl PrimInfoTblPtr,A3,A1 ; get pointer to info table
|
||
TST.B PrimChargerAttr(A1) ; IF charger attributes THEN
|
||
BEQ.S @noChargerAttribs
|
||
MOVE.B #ChargerOn,pmData(A0) ; ensure charger turned on <H43>
|
||
MOVE.W #1,pmLength(A0) ; pmLength = 1 <H43>
|
||
MOVE.W #power1Cntl,pmCommand(A0) ; pmCommand = power 1 control <H43>
|
||
_PMgrOp ; send the command <H43>
|
||
|
||
LoadTbl PrimInfoTblPtr,A3,A1 ; get pointer to info table
|
||
MOVE.B PrimChargerAttr(A1),\ ;
|
||
pmData(A0) ; stuff the attr <H42>
|
||
MOVE.W #1,pmLength(A0) ; pmLength = 1
|
||
MOVE.W #setMachineAttr,\ ;
|
||
pmCommand(A0) ; pmCommand = send cpu attributes to microcontroller
|
||
_PMgrOp ; send the command
|
||
|
||
@noChargerAttribs
|
||
MOVE.W LowWarn(A3),D0 ; get the low warning
|
||
MOVE.W D0,pmData(A0) ; stuff the default Pmgr low warning and cutoff <H18>
|
||
BEQ.S @NoDefWarnings ; -> no defaults, so trust the PMGR to be right <H30>
|
||
MOVE.W #2,pmLength(A0) ; pmLength = 2 <H18>
|
||
MOVE.W #setBattWarning,\
|
||
pmCommand(A0) ; pmCommand = set low/dead battery levels <H18>
|
||
_PMgrOp ; send the command <H18>
|
||
@NoDefWarnings
|
||
|
||
CLR.W pmLength(A0) ; pmLength = 0 <H48>
|
||
MOVE.W #batteryRead,pmCommand(A0) ; pmCommand = read Battery State <H48>
|
||
_PMgrOp ; send the command <H48>
|
||
MOVEA.L pmRBuffer(A0),A0 ; get pointer to receive buffer <H48>
|
||
MOVE.B (A0),Charger(A3) ; Initialize charger state <H48>
|
||
|
||
BTST.B #HasCharger,Charger(A3) ; is the charger inserted <H65>
|
||
BEQ.S @exitChrgStateInt ; if not, do nothing <H65>
|
||
MOVE.W BatteryWarnDly(A3),\
|
||
BatteryWarnCnt(A3) ; load battery warn counter <H65>
|
||
@exitChrgStateInt
|
||
LEA pmBlkSize(SP),SP ; Remove stack frame <H2>
|
||
RTS
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: DoDynamicSpeedChange
|
||
;
|
||
; Inputs: A3 -- Pointer to PmgrVars
|
||
;
|
||
; Outputs: none.
|
||
;
|
||
; Trashes: D0/A0-A1
|
||
;
|
||
; Function: setup timing constants for full/reduced speed
|
||
;
|
||
;________________________________________________________________________________________
|
||
|
||
DoDynamicSpeedChange
|
||
LoadTbl PrimInfoTblPtr,A3,A0 ; point to the info table for this machine
|
||
MOVEQ #1<<dynamicSpeedChange,\;
|
||
D0 ; does this machine support dynamic speed changes?
|
||
AND.L PrimPubFeatures(A0),D0 ;
|
||
BEQ.S @NotDynamic ; -> no
|
||
|
||
_FullProcessorSpeed ; find out if we're running at full or reduced speed
|
||
EORI.W #1,D0 ; 1=reduced, 0=full
|
||
IF EconoBit THEN
|
||
LSL.W #EconoBit,D0 ; shift it into the correct position
|
||
ENDIF
|
||
MOVE.W D0,D3 ; and save it for later
|
||
|
||
BSR.S @SetProcessorSpeed ; save current timing constants and flip to the opposite speed mode
|
||
|
||
MOVEA.L VIA,A0 ; save the VIA1 registers,
|
||
MOVE.B vIER(A0),-(SP)
|
||
MOVE.B vACR(A0),-(SP)
|
||
MOVEA.L VIA2,A0 ; save the VIA2 interrupt enables
|
||
MOVE.B Rv2IER(A0),-(SP)
|
||
BSET #7,(SP)
|
||
MOVE.B Rv2SEnb(A0),-(SP)
|
||
BSET #7,(SP)
|
||
MOVEQ #$7F,D0
|
||
MOVE.B D0,Rv2IER(A0) ; and disable the interrupts
|
||
MOVE.B D0,Rv2SEnb(A0)
|
||
MOVE.L A3,-(SP) ; save A3
|
||
|
||
BSR.L SetupTimeK ; go calculate the timing constants
|
||
|
||
MOVEA.L (SP)+,A3 ; restore A3,
|
||
MOVEA.L VIA2,A0 ; the VIA2 interrupt enables,
|
||
MOVE.B (SP)+,Rv2SEnb(A0)
|
||
MOVE.B (SP)+,Rv2IER(A0)
|
||
MOVEA.L VIA,A0 ; and the VIA registers
|
||
MOVE.B (SP)+,vACR(A0)
|
||
MOVE.B (SP)+,vIER(A0)
|
||
|
||
BSR.S @SetProcessorSpeed ; save the constants for the opposite speed mode, and restore the speed
|
||
|
||
LEA fullSpeedDBRAs(A3),A1 ; assume we're running at full speed
|
||
TST.W D3 ; are we?
|
||
BEQ.S @RestoreDBRAs ; -> yep
|
||
ADDQ.W #lowSpeedDBRAs-fullSpeedDBRAs,A1
|
||
@RestoreDBRAs
|
||
MOVE.W (A1)+,TimeDBRA ; restore the original timing constants
|
||
MOVE.W (A1)+,TimeSCCDB
|
||
MOVE.W (A1)+,TimeSCSIDB
|
||
MOVE.W (A1)+,TimeVIADB
|
||
@NotDynamic
|
||
RTS
|
||
|
||
|
||
@SetProcessorSpeed
|
||
LEA fullSpeedDBRAs(A3),A1 ; assume we're running at full speed
|
||
TST.W D3 ; are we?
|
||
BEQ.S @CopyDBRAs ; -> yep
|
||
ADDQ.W #lowSpeedDBRAs-fullSpeedDBRAs,A1
|
||
@CopyDBRAs MOVE.W TimeDBRA,(A1)+ ; copy the timing constants from low mem
|
||
MOVE.W TimeSCCDB,(A1)+
|
||
MOVE.W TimeSCSIDB,(A1)+
|
||
MOVE.W TimeVIADB,(A1)+
|
||
|
||
MOVEQ #1<<EconoBit,D1 ; toggle the full/reduced state
|
||
EOR.W D1,D3
|
||
MOVE.W D3,D1
|
||
JmpRoutine SpeedChangePtr,A3,A0; and go do the switch
|
||
|
||
;________________________________________________________________________________________
|
||
; Routine: GetPmgrPRAM
|
||
;
|
||
; Inputs: A3 -- Pointer to PmgrVars
|
||
;
|
||
; Outputs: none.
|
||
;
|
||
; Trashes: D0/A0
|
||
;
|
||
; Function: Determines the appropriate size of the tables.
|
||
;
|
||
;________________________________________________________________________________________
|
||
|
||
GetPmgrPRAM
|
||
LEA -PmgrPramSize(SP),SP ; get a param block
|
||
MOVEA.L SP,A0
|
||
|
||
MOVEQ #PmgrPramSize,D0 ; hi-word = number of PRAM bytes to read <H14>
|
||
SWAP D0 ; <H14>
|
||
MOVE.B PRAMbase(A3),D0 ; lo-word = base address <H13>
|
||
_ReadXPRam ; read in the PMGR PRAM settings
|
||
|
||
CLR.B NTSC ; clear the NTSC flag (square corners)
|
||
|
||
TST.W SlpTimeOut(A0) ; are sleep and hard disk timeouts valid? <H14>
|
||
BNE.S @skipwrite ; -> yes
|
||
|
||
MOVE.B #DfltSlpTime,\
|
||
SlpTimeOut(A0) ; Init default time outs <v5.6>
|
||
MOVE.B #DfltHDTime,HDTimeOut(A0)
|
||
MOVEQ #2,D0 ; hi-word = number of PRAM bytes to write <H14>
|
||
SWAP D0 ; <H14>
|
||
MOVE.B PRAMbase(A3),D0 ; lo-word = base address <H13>
|
||
_WriteXPRam ; write out the default sleep and hard disk timeouts
|
||
|
||
@skipwrite MOVE.B SlpTimeOut(A0),\
|
||
SleepTime(A3) ; Init default time outs for sleep <v5.6>
|
||
MOVE.B HDTimeOut(A0),HDTime(A3); for hard disk
|
||
LEA PmgrPramSize(SP),SP ; kill param block
|
||
RTS
|
||
|
||
;________________________________________________________________________________________
|
||
|
||
; Routine: InstallVBLs
|
||
;
|
||
; Inputs: A3 -- Pointer to PmgrVars
|
||
;
|
||
; Outputs: none.
|
||
;
|
||
; Trashes: none
|
||
;
|
||
; Function: Determines the appropriate size of the tables.
|
||
;
|
||
;________________________________________________________________________________________
|
||
|
||
InstallVBLs
|
||
LoadTbl PmgrRoutineTbl,A3,A1 ; get pointer to Routine Table
|
||
|
||
; install the battery monitoring VBL task...
|
||
|
||
MOVE.L BatteryVBLPtr(A1),D0 ; does this machine monitor the battery level? <H42>
|
||
BEQ.S @NoBatteryVBL ; -> no, don't install the VBL task <H42>
|
||
LEA BatVBLTask+vblCount(A3),\
|
||
A0 ; point to the end of the VBL task record <H42>
|
||
MOVE.W #BatFreq,(A0) ; vblCount <H42>
|
||
MOVE.L D0,-(A0) ; vblAddr <H42>
|
||
ADDQ.W #vType,-(A0) ; vblType = vType <H42>
|
||
SUBQ.W #vblType-vblink,A0 ; point to the beginning of the record <H42>
|
||
_VInstall ; install the task <H42>
|
||
@NoBatteryVBL
|
||
|
||
; install the sound usage monitoring VBL task...
|
||
|
||
MOVE.L SoundVBLPtr(A1),D0 ; does this machine monitor sound usage? <H42>
|
||
BEQ.S @NoSoundVBL ; -> no, don't install the VBL task <H42>
|
||
LEA SwVBLTask+vblCount(A3),\
|
||
A0 ; point to the end of the VBL task record <H42>
|
||
MOVE.W #SndWFreq,(A0) ; vblCount <H42>
|
||
MOVE.L D0,-(A0) ; vblAddr <H42>
|
||
ADDQ.W #vType,-(A0) ; vblType = vType <H42>
|
||
SUBQ.W #vblType-vblink,A0 ; point to the beginning of the record <H42>
|
||
_VInstall ; install the task <H42>
|
||
@NoSoundVBL
|
||
|
||
RTS
|
||
;•••••••••••••••••••••••••••• End Of Initialization •••••••••••••••••••••••••••••••••••••
|
||
|
||
|
||
;••••••••••••••••••••••••••••• VBL's & Interrupts •••••••••••••••••••••••••••••••••••••••
|
||
;
|
||
; Contains:
|
||
;
|
||
; BatWatch
|
||
; RemoveMsg
|
||
; InstallMsg
|
||
; PMGRInt
|
||
; BatInt
|
||
;________________________________________________________________________________________
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: BatWatch
|
||
;
|
||
; Inputs: A1 - pointer to VIA1 base
|
||
;
|
||
; Outputs: none
|
||
;
|
||
; Trashes: none (D0-D3, A0-A3 are preserved by the interrupt dispatcher)
|
||
;
|
||
; Function: Monitors the battery for low power conditions, and then alerts the user via
|
||
; the Notification Manager. Also updates dirty sleep and hard disk timeouts.
|
||
;________________________________________________________________________________________
|
||
|
||
BatWatch
|
||
MOVE.L PmgrBase,A2
|
||
LEA BatVBLTask(A2),A0 ; Get pointer to vbl task
|
||
MOVE.W #BatFreq,vblCount(A0) ; Do it again
|
||
TST.B SysTaskFlag(A2)
|
||
BEQ @exit
|
||
|
||
@didsystask
|
||
JsrRoutine GetLevelPtr,A2,A0 ; Read, average, and convert battery level
|
||
BNE.S @valid ; into level -1 - 4, branch if data not ready
|
||
|
||
MOVE.B #-1,LastLevel(A2) ; Reset last level
|
||
BRA.S @BatWatchOut
|
||
|
||
@valid TST.B D0 ; Test for negative current level
|
||
BPL.S @positive
|
||
|
||
@negative BSR RemoveMsg ; Remove old message (if any)
|
||
MOVE.B D0,LastLevel(A2) ; Save level
|
||
BRA.S @BatWatchOut
|
||
|
||
@positive BEQ.S @lesser ; Level 0, do nothing
|
||
|
||
CMP.B #2,D0 ; Level 2, remap to level 1 (last dialog level) <H25>
|
||
BNE.S @lpowermode ; <2> … continue with low power stuff <H25>
|
||
MOVEQ #1,D0 ; <2> … remap level 2 to level 1 <H25>
|
||
|
||
@lpowermode TST.B LastLevel(A2) ; If LasLevel was -1 then new message
|
||
BMI.S @newmsg
|
||
|
||
CMP.B LastLevel(A2),D0 ; If NewLevel<=LastLevel then branch
|
||
BLS.S @lesser
|
||
|
||
@newmsg BSR RemoveMsg ; Remove previous level message
|
||
BSR InstallMsg ; Install this level message
|
||
CLR.B Level4Cnt(A2) ; Clear level 4 count down timer
|
||
MOVE.B D0,LastLevel(A2) ; Save level
|
||
BRA.S @BatWatchOut
|
||
|
||
@lesser CMP.B #4,LastLevel(A2) ; If level 4 then inc timer
|
||
BNE.S @BatWatchOut
|
||
|
||
ADD.B #1,Level4Cnt(A2)
|
||
|
||
@BatWatchOut
|
||
LEA BatVBLTask(A2),A0 ; Get pointer to vbl task
|
||
MOVE.W #BatFreq,vblCount(A0) ; Do it again
|
||
LoadTbl PrimInfoTblPtr,A2,A0 ; Get pointer to info table
|
||
TST.B LastLevel(A2) ; Is the level -1? <H25>
|
||
BPL.S @Next ; No, try next check <H25>
|
||
BCLR #PmgrWakeLvlSet,PmgrFlags(A2) ; Is the semaphor set? <H25>
|
||
BEQ.S @FinishUp ; Nope. Then skip and go on <H25>
|
||
|
||
MOVE.W PrimLowWarn(A0),D0 ; Get low power values <H25>
|
||
BRA.S @SetPmgrLvl ; Set level and get on with life <H30>
|
||
|
||
@Next CMP.B #4,LastLevel(A2) ; Check if we are in level 4 <H25>
|
||
BNE.S @FinishUp ; If not, go on <H25>
|
||
|
||
TST.B Level4Cnt(A2) ; Is it the first time through? <H25>
|
||
BNE.S @FinishUp ; If not, go On <H25>
|
||
|
||
BSET #PmgrWakeLvlSet,PmgrFlags(A2) ; Set the semaphor <H25>
|
||
MOVE.W PrimLowWarn(A0),D0 ; Get low power values <H25>
|
||
MOVE.B PrimWakeLvl(A0),D0 ; Get wake level values <H25>
|
||
@setPmgrLvl
|
||
TST.W D0 ; are there valid levels? <H30>
|
||
BEQ.S @FinishUp ; -> no, figure the PMGR knows what to do <H30>
|
||
SWAP D0 ; set the values in the top of buffer
|
||
MOVE.L D0,-(SP) ; Set the parameter in the buffer
|
||
MOVE.L SP,-(SP) ; pmRBuffer
|
||
MOVE.L (SP),-(SP) ; pmSBuffer
|
||
MOVE.W #2,-(SP) ; pmLength = 0
|
||
MOVE.W #setBattWarning,-(SP) ; pmCommand = set Battery warning level
|
||
MOVEA.L SP,A0 ; point to the parameter block
|
||
_PMgrOp ; send the command
|
||
LEA pmBlkSize(SP),SP ; Remove stack frame
|
||
|
||
@FinishUp TST.B TOdirtyFlag(A2) ; Check for new timeouts <H25>
|
||
BEQ.S @exit
|
||
|
||
CLR.B TOdirtyFlag(A2) ; Clear the dirty flag <H25>
|
||
SUB.W #8,SP ; allocate some stack space <H25>
|
||
MOVE.L SP,A0 ; set param block <H25>
|
||
MOVEQ #PmgrPramSize,D0 ; hi-word = number of PRAM bytes to read <H25>
|
||
SWAP D0 ; <H25>
|
||
MOVE.B PRAMbase(A2),D0 ; lo-word = base address <H25>
|
||
_ReadXPRam
|
||
|
||
MOVE.B PmgrStatusFlags(A0),SleepFlags(A2) ; Get the sleep flags <H25>
|
||
MOVE.W SlpTimeOut(A0),SleepTime(A2) ; Get latest timeouts <H25>
|
||
ADD.W #8,SP ; free the buffer <H25>
|
||
_IdleUpdateDispatch ;
|
||
@exit RTS
|
||
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: RemoveMsg
|
||
;
|
||
; Inputs: A2 - pointer to Power Manager's variables
|
||
;
|
||
; Outputs: none
|
||
;
|
||
; Trashes: A0
|
||
;
|
||
; Function: removes any pending low power warning messages
|
||
;________________________________________________________________________________________
|
||
|
||
RemoveMsg
|
||
BTST.B #AvoidLowPMsg,PmgrFlags(A2) ; are low power messages enabled? <t32> djw
|
||
BNE.S nomsg ; no - don't do anything <t32> djw
|
||
BatIntRemoveMsg
|
||
TST.B lpMSGvalid(A2) ; If no messages pending then nothing to remove
|
||
beq.s nomsg ; Yes. remove low power message
|
||
|
||
MOVE.L D0,-(SP)
|
||
LEA BNmQEntry(A2),A0
|
||
_NMRemove ; Remove low power warning message
|
||
MOVE.L (SP)+,D0
|
||
CLR.B lpMSGvalid(A2) ; No messages pending
|
||
nomsg RTS
|
||
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: InstallMsg
|
||
;
|
||
; Inputs: A2 - pointer to Power Manager's variables
|
||
;
|
||
; Outputs: none
|
||
;
|
||
; Trashes: A0
|
||
;
|
||
; Function: installs a low power warning message if they're allowed
|
||
;________________________________________________________________________________________
|
||
|
||
InstallMsg
|
||
BTST.B #AvoidLowPMsg,PmgrFlags(A2) ; are low power messages enabled? <t32> djw
|
||
BNE.S @nmproc ; don't post any message <t32> djw
|
||
MOVE.L D0,-(SP)
|
||
LEA BNmQEntry(A2),A0 ; Create notification entry
|
||
LEA @nmproc,A1
|
||
MOVE.L A1,nmResp(A0) ; Use empty response routine below
|
||
MOVE.L lpSICNHndl(A2),nmIcon(A0) ; Use the icon
|
||
|
||
MOVE.W D0,D2 ; Copy level into D2
|
||
SUBQ.W #1,D2 ; Adjust for range 0 - 3
|
||
LSL.W #2,D2 ; Convert to offset
|
||
MOVE.L lpSTR0Ptr(A2,D2.W),nmStr(A0) ; Index into messages strings
|
||
TST.L nmStr(A0) ; Do we have a string?
|
||
BEQ.S @nonminst ; Nope. Get out...
|
||
_NMInstall ; Notify user of low power condition
|
||
ST lpMSGvalid(A2) ; Message pending <29> HJR
|
||
@nonminst MOVE.L (SP)+,D0 ; <29> HJR
|
||
|
||
@nmproc RTS ; No notification proc now
|
||
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: PMGRInt
|
||
;
|
||
; Inputs: A1 - pointer to VIA1 base
|
||
;
|
||
; Outputs: none
|
||
;
|
||
; Trashes: none (D0-D3 and A0-A3 are preserved by the interrupt dispatcher)
|
||
;
|
||
; Function: This is the Power Manager interrupt handler. It dispatches to the right
|
||
; interrupt handler for the type of interrupt received.
|
||
;________________________________________________________________________________________
|
||
|
||
PMGRInt
|
||
MOVE.B #(1<<ifIRQ)+(1<<ifCB1),vIFR(A1) ; clear PMGR interrupt
|
||
LEA -12(SP),SP ; Create stack frame
|
||
MOVE.L SP,A0
|
||
ADDQ.L #2,A0 ; point 2 bytes into buffer
|
||
MOVEQ #ReadINT,D0 ; PMGR command, get interrupt flags
|
||
BSR PMGRrecv
|
||
TST.W D0
|
||
BNE.S @exit
|
||
|
||
MOVE.B (A0),D0 ; Flag byte [int/adb]
|
||
LSR.B #4,D0 ; interrupt bits were in upper half
|
||
|
||
MOVE.W @intPriority(D0.W*2),D0 ; get the offset to that routine
|
||
JMP @intPriority(D0) ; jump to that routine
|
||
|
||
@intPriority
|
||
DC.W @exit-@intPriority ; 0 0 0 0
|
||
DC.W @isADBint-@intPriority ; 0 0 0 1
|
||
DC.W @isBATint-@intPriority ; 0 0 1 0
|
||
DC.W @isADBint-@intPriority ; 0 0 1 1
|
||
DC.W @isEnvInt-@intPriority ; 0 1 0 0
|
||
DC.W @isADBint-@intPriority ; 0 1 0 1
|
||
DC.W @isBATint-@intPriority ; 0 1 1 0
|
||
DC.W @isADBint-@intPriority ; 0 1 1 1
|
||
IF BlackBirdDebug THEN ; goes away when BB handles one sec ints for real
|
||
DC.W @exit-@intPriority ; 1 0 0 0
|
||
ELSE
|
||
DC.W @oneSecInt-@intPriority ; 1 0 0 0
|
||
ENDIF
|
||
DC.W @isADBint-@intPriority ; 1 0 0 1
|
||
DC.W @isBATint-@intPriority ; 1 0 1 0
|
||
DC.W @isADBint-@intPriority ; 1 0 1 1
|
||
IF BlackBirdDebug THEN ; goes away when BB handles one sec ints for real
|
||
DC.W @exit-@intPriority ; 1 1 0 0
|
||
ELSE
|
||
DC.W @oneSecInt-@intPriority ; 1 1 0 0
|
||
ENDIF
|
||
DC.W @isADBint-@intPriority ; 1 1 0 1
|
||
DC.W @isBATint-@intPriority ; 1 1 1 0
|
||
DC.W @isADBint-@intPriority ; 1 1 1 1
|
||
|
||
|
||
@oneSecInt LEA 12(SP),SP ; clean up PB on stack
|
||
MOVEA.L VIA,A1 ; OneSecInt expects pointer to VIA in A1 <H3>
|
||
MOVEA.L Lvl1DT+(4*ifCA2),A0 ; get the address of the one-second interrupt handler <H3>
|
||
JMP (A0) ; and call it <H3>
|
||
|
||
@isEnvInt MOVE.L PMgrBase,A2
|
||
MOVE.L vENVInt(A2),D0 ; Check for valid vector
|
||
BRA.S @callHandler
|
||
|
||
@isBATint MOVE.L PMgrBase,A2
|
||
MOVE.L vBatInt(A2),D0 ; Check for valid vector
|
||
bra.s @callHandler
|
||
|
||
@isADBint andi.b #$0F,(a0) ; mask off interrupt status bits
|
||
move.b 1(a0),-(a0) ; [cmd] [stat] [cmd]
|
||
subq.b #2,d1 ; actual count
|
||
move.b d1,2(a0) ; [cmd] [stat] [len]
|
||
move.l Lvl1DT+8,d0 ; Check for valid vector
|
||
|
||
@callHandler
|
||
beq.s @exit ; no handler, exit
|
||
move.l d0,a1
|
||
jsr (a1) ; call handler
|
||
@exit lea 12(sp),SP ; Done with stack frame
|
||
rts
|
||
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: BatInt
|
||
;
|
||
; Inputs: A0 - pointer to PMGR interrupt data: [flags][battery][gas][therm]
|
||
; A1 - pointer to VIA1 base
|
||
; A2 - pointer to Power Manager's variables
|
||
;
|
||
; Outputs: none
|
||
;
|
||
; Trashes: none (D0-D3 and A0-A3 are preserved by the interrupt dispatcher)
|
||
;
|
||
; Function: Handles PMGR interrupts that occur because of a change in charger connection
|
||
; state, or a shorted battery condition is detected.
|
||
;________________________________________________________________________________________
|
||
|
||
BatInt
|
||
moveq.l #0,d2 ; clear reg
|
||
move.b 1(a0),d2 ; get battery flags
|
||
move.b d2,Charger(a2) ; save charger state
|
||
|
||
; Charger Change interrupt
|
||
btst.l #ChrgState,d2 ; was there a charger int
|
||
beq.s @exitChargeState ; procede to next test
|
||
btst.l #HasCharger,d2 ; is the charger inserted
|
||
beq.s @exitChargeState ; if not, do nothing
|
||
move.w BatteryWarnDly(a2),BatteryWarnCnt(a2); load battery warn counter
|
||
@exitChargeState
|
||
|
||
; batter shorted interrupt
|
||
btst.l #ShortedBat,d2 ; is there a shorted battery?
|
||
beq.s @shortTestexit ; not this time
|
||
tst.w BatteryWarnCnt(a2) ; if counter
|
||
ble.s @postShortedBatt ; if less than or equal, post message
|
||
|
||
subq.w #1,BatteryWarnCnt(a2) ; update counter
|
||
bra.s @shortTestexit ; exit handler
|
||
|
||
; Shorted battery condition detected - post notification message
|
||
; Remove any pending low power messages and prevent any more from showing up so they
|
||
; don't try to remove the bad battery message.
|
||
@postShortedBatt
|
||
bsr BatIntRemoveMsg ; remove any old message
|
||
bset.b #AvoidLowPMsg,PmgrFlags(a2) ; avoid confict with low power messages
|
||
|
||
lea bbSTR0Ptr(a2),a1 ; get first vectored string
|
||
bset.b #BadBatDet,PmgrFlags(a2) ; is this the first bad message?
|
||
beq.s @continue
|
||
addq.l #4,a1 ; index to second harsher message
|
||
bclr.b #BadBatDet,PmgrFlags(a2) ; reset bad battery level for next time
|
||
@continue
|
||
tst.l (a1) ; does the string exist?
|
||
beq.s @shortTestexit ; no string - do not post message
|
||
lea BNmQEntry(a2),a0 ; a0 = ptr to notification mgr record
|
||
move.l (a1),nmStr(a0) ; set string message
|
||
lea @BatResp,a1 ; address of response routine
|
||
move.l a1,nmResp(a0) ; set response routine
|
||
move.l lpSICNHndl(a2),nmIcon(a0) ; Use the icon
|
||
_NMInstall ; notify user of defective battery condition
|
||
|
||
subq.l #4,sp
|
||
movea.l sp,a0 ; a0 = pmgr pkt data buffer
|
||
move.b #writePmgrRAM,d0 ; pmgr command
|
||
moveq.l #3,d1 ; 3 bytes to send
|
||
move.w #$0021,(a0) ; set addr to write to
|
||
andi.l #~((1<<ShortedBat)+\
|
||
(1<<hasCharger)),d2 ; clear short and charger condition
|
||
move.b d2,2(a0) ; set data byte
|
||
bsr PmgrSend ; tell pmgr to clear the interrupt
|
||
addq.l #4,sp ; free buffer
|
||
@shortTestexit
|
||
rts ; exit interrupt handler
|
||
|
||
@BatResp movea.l (sp)+,a1 ; save return addr
|
||
movea.l (sp)+,a0 ; get ptr to BNmQEntry
|
||
_NMRemove ; remove the bad battery notification
|
||
movea.l PmgrBase,a0 ; get ptr to pmgr globals |
|
||
bclr.b #AvoidLowPMsg,PmgrFlags(a0) ; allow low power messages again V
|
||
jmp (a1) ; return to caller <H62>
|
||
|
||
;•••••••••••••••••••••••••••• End of VBL's & Ints •••••••••••••••••••••••••••••••••••••••
|
||
|
||
;••••••••••••••••••••••••••••••••••• Traps ••••••••••••••••••••••••••••••••••••••••••••••
|
||
;
|
||
; Contains:
|
||
;
|
||
; PowerDispatch
|
||
; IdleUpdate (Selector #1)
|
||
; IdleDelay (Selector #2)
|
||
; IdleMind (Selector #3)
|
||
; IdleRead (Selector #4)
|
||
; IdleEnable (Selector #5)
|
||
; IdleDisable (Selector #6)
|
||
; CPUSpeed (Selector #7)
|
||
; BasePRAM (Selector #8)
|
||
; ScaledBattery (Selector #9)
|
||
; PowerMgrHook (Selector #10)
|
||
; SecondaryInitproc
|
||
; ScsiDiskModeproc
|
||
; ExternaVideoOnproc
|
||
; ModemTypeProc
|
||
; PDimScreens (Selector #11)
|
||
; PrivateFeatures (Selector #13)
|
||
; GetButtonValues (Selector #15)
|
||
; SetHDState (Selector #16)
|
||
;
|
||
; PmgrOp
|
||
; IdleUpdate
|
||
; IdleState
|
||
; SerialPower
|
||
; Sleep
|
||
; SlpQInstall
|
||
; SlpQRemove
|
||
;________________________________________________________________________________________
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: PowerDispatch (trap $A09F)
|
||
;
|
||
; Inputs: D0 - selector
|
||
;
|
||
; Outputs: D0 - selector result, or error code if bad selector
|
||
;
|
||
; Trashes: varies by selector
|
||
;
|
||
; Function: This is the Power Manager's private dispatch trap, and provides a variety of
|
||
; miscellaneous functions.
|
||
;________________________________________________________________________________________
|
||
|
||
PowerDispatch
|
||
WITH PwrDispatchRec
|
||
MOVE.L PmgrBase,A0 ; Get pointer to globals
|
||
LoadTbl PwrDispatchTbl,A0,A0 ; Get pointer to Table
|
||
MOVEQ #0,D1 ; Clear D1
|
||
MOVE.W D0,D1 ; Get selector in D1
|
||
LSL.W #2,D1 ; Convert selector to bytes
|
||
CMP.L PwrDispCount(A0),D1 ; IF Dispatch Out of Range THEN
|
||
BHI.S @Error ; Get Out Of Here
|
||
TST.L ([A0,D1.L]) ; ELSE Dispatch Non Existent THEN
|
||
BEQ.S @Error ; Get Out of Here
|
||
JMP ([A0,D1.L]) ; Go do that routine
|
||
|
||
@Error
|
||
MOVEQ #paramErr,D0 ; Abort and return error
|
||
RTS
|
||
ENDWITH
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: IdleUpdate ($A285) (PowerDispatch selector #1)
|
||
;
|
||
; Inputs: none
|
||
;
|
||
; Outputs: D0 - time of last activity, in ticks
|
||
;
|
||
; Trashes: A1
|
||
;
|
||
; Function: resets the idle compare time to Ticks unless the idle compare time is
|
||
; already pushed out beyond Ticks.
|
||
;________________________________________________________________________________________
|
||
|
||
IdleUpdateTbl
|
||
DC.W Exit-IdleUpdateTbl ; $00 => OverallAct <K20>
|
||
DC.W UsrAct-IdleUpdateTbl ; $01 => UsrActivity |
|
||
DC.W NetAct-IdleUpdateTbl ; $02 => NetActivity v
|
||
DC.W HDAct-IdleUpdateTbl ; $03 => HardDriveActivity
|
||
TblEnd DC.W 0 ; $04 => padding for now
|
||
|
||
IdleUpdateTrap
|
||
MOVEQ #0,D0 ; clear selector
|
||
|
||
IdleUpdate
|
||
SWAP D0 ; Get our selector
|
||
MOVE.W D0,D1 ; Get a copy of the selector
|
||
MOVE.W SR,-(SP) ; No ints at this time
|
||
OR.W #HiIntMask,SR
|
||
MOVE.L PmgrBase,A1 ; get pmgr local
|
||
MOVE.L LastAct(A1),D0 ; If LastAct > Ticks then branch
|
||
CMP.L Ticks,D0
|
||
BHI.S @noLastActupdate
|
||
MOVE.L Ticks,LastAct(A1) ; reset sleep/idle time
|
||
@noLastActupdate
|
||
|
||
CMP.W #(TblEnd-IdleUpdateTbl)/2,D1 ; IF entry outofbounds THEN
|
||
BHI.S Exit ; exit
|
||
|
||
MOVE.W IdleUpdateTbl(D1.W*2),D1 ; Get the relative offset to the routine.
|
||
JMP IdleUpdateTbl(D1.W) ; GOTO the proper routine.
|
||
|
||
UsrAct MOVE.L LastUsrAct(A1),D0 ; IF LastUsrAct > Ticks THEN
|
||
CMP.L Ticks,D0 ; Exit
|
||
BHI.S Exit ; ELSE
|
||
MOVE.L Ticks,LastUsrAct(A1) ; Update user activity
|
||
BRA.S Exit
|
||
|
||
NetAct MOVE.L LastNetAct(A1),D0 ; IF LastUsrAct > Ticks THEN
|
||
CMP.L Ticks,D0 ; Exit
|
||
BHI.S Exit ; ELSE
|
||
MOVE.L Ticks,LastNetAct(A1) ; Update user activity
|
||
BRA.S Exit
|
||
|
||
HDAct MOVE.L Ticks,LastHd(A1) ; Update user activity
|
||
|
||
Exit MOVE.L LastAct(A1),D0 ;
|
||
MOVE.W (SP)+,SR ; <K20>
|
||
RTS
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: IdleDelay (PowerDispatch selector #2)
|
||
;
|
||
; Inputs: none
|
||
;
|
||
; Outputs: none
|
||
;
|
||
; Trashes: D0,A1
|
||
;
|
||
; Function: This routine will delay Idling (Power Cycling) by setting LastAct to some
|
||
; future time. This is in particular useful in Reads, and Writes where the
|
||
; PwrCycWaitTime might not be enough time for them to function properly.
|
||
;________________________________________________________________________________________
|
||
|
||
IdleDelay MOVE.W SR,-(SP) ; Save the status register
|
||
ORI.W #HiIntMask,SR ; Turn off those interrupts
|
||
MOVE.L PMgrBase,A1 ; Get the Globals
|
||
MOVEQ #0,D0 ; Clear the register
|
||
MOVE.W PwrCycDelay(A1),D0 ; Get the time delay used
|
||
ADD.L Ticks,D0 ; update it with Ticks
|
||
CMP.L LastAct(A1),D0 ; IF LastAct > New One THEN
|
||
BLE.S @Done ; Get Out! <34> HJR
|
||
MOVE.L D0,LastAct(A1) ; ELSE set new LastAct
|
||
@Done MOVE.W (SP)+,SR ; Restore status register
|
||
RTS
|
||
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: IdleMind (PowerDispatch selector #3)
|
||
;
|
||
; Inputs: none
|
||
;
|
||
; Outputs: none
|
||
;
|
||
; Trashes: none
|
||
;
|
||
; Function: Checks for hard disk time out, sleep time out, idle time out, and low power
|
||
; sleep. The first check is for a low power condition, if so then sleep is
|
||
; immediately called. The next check is for hard disk spin down time out and
|
||
; sleep time out. These time outs may be disabled when on the battery if a
|
||
; special bit is set. The last check is for idle time out.
|
||
;________________________________________________________________________________________
|
||
|
||
IdleMind
|
||
@savedRegs REG D0-D2/A0-A2
|
||
MOVEM.L @savedRegs,-(SP) ; Save some registers
|
||
|
||
MOVE.L PmgrBase,A2 ; Get pmgr locals
|
||
MOVE.W PwrCycSyncCount(A2),D0 ; Get the number of syncIdle before IdleMind
|
||
ADDI.W #1,PMgrScratch.SyncCounter(A2) ; Increment scratch counter
|
||
CMP.W PMgrScratch.SyncCounter(A2),D0 ; Have we done enough SyncIdles
|
||
BLT @CommonOut
|
||
|
||
CLR.W PMgrScratch.SyncCounter(A2) ; reset counter
|
||
LoadTbl IdleMindTblPtr,A2,A1 ; Get pointer to IdleMindTble
|
||
|
||
ST SysTaskFlag(A2) ; Flag that systemtask has been called
|
||
JsrPrimTbl CountDownTimer,A1 ; Check if we are in countdown condition
|
||
BNE.S @ForceSleep ; IF CountDownTimer THEN sleep
|
||
|
||
JsrPrimTbl RunIdleRoutines,A1 ; Get pointer to Check for spin down HD <H43>
|
||
|
||
MOVE.L LastAct(A2),D0 ; Get LastAct
|
||
CMP.L Ticks,D0 ; IF LastAct > Ticks THEN
|
||
BGT.S @CommonOut ; exit
|
||
|
||
JsrPrimTbl SleepTimeOut,A1 ; Get pointer to Check for going to sleep
|
||
BNE.S @RequestSlp ; IF SleepTimeOut THEN sleep
|
||
|
||
JsrPrimTbl CheckIdle,A1 ; Get pointer to Check for going to power cycle
|
||
BEQ.S @ClrOut ; IF activity THEN clearout
|
||
JsrPrimTbl CalcProgPwrCyc,A1 ; Else calculate progressive count
|
||
JsrPrimTbl CyclePower,A1 ; Get pointer to Go Power Cycling
|
||
BRA.S @CommonOut ; That's All Folks
|
||
|
||
@RequestSlp
|
||
MOVEQ #SleepRequest,D0 ; Set a sleep request
|
||
BRA.S @DoSleep ; Go ajourn
|
||
@ForceSleep
|
||
MOVEQ #SleepNow,D0 ; Set to force sleep
|
||
@DoSleep BTST #dockNoSleep,dockFlags(A2) ; is sleeping allowed (if we're connected to a bar) <H36>
|
||
BNE.S @SleepDeny ; -> no, avoid putting up a dialog <H36>
|
||
_Sleep ; Go to sleep
|
||
@SleepDeny BCLR #LowPowerSleep,PMgrFlags2(A2) ; clear the low power sleep flag <H52>
|
||
MOVE.L Ticks,LastAct(A2) ; Waking updates last activity <H36>
|
||
@ClrOut
|
||
CLR.L PMgrScratch.ProgLastAct(A2) ; Reset progressive power cycling
|
||
@CommonOut
|
||
MOVEM.L (SP)+,@savedRegs ; Restore registers
|
||
RTS
|
||
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: IdleRead (PowerDispatch selector #4)
|
||
;
|
||
; Inputs: none
|
||
;
|
||
; Outputs: D0 - current CPU speed, in MHz
|
||
;
|
||
; Trashes: A0
|
||
;
|
||
; Function: returns the current CPU speed
|
||
;________________________________________________________________________________________
|
||
|
||
IdleRead
|
||
MOVE.W SR,-(SP) ; Save the status register
|
||
ORI.W #HiIntMask,SR ; Kill those vicious interrupts
|
||
MOVE.L PMgrBase,A0 ; Get pmgr locals
|
||
MOVEQ #0,D0 ; Clear the register
|
||
MOVE.B saveSpeedo(A0),D0 ; return current speed
|
||
MOVE.W (SP)+,SR ; restore the status register
|
||
RTS
|
||
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: IdleEnable (PowerDispatch selector #5)
|
||
;
|
||
; Inputs: none
|
||
;
|
||
; Outputs: D0 - idle disable count
|
||
;
|
||
; Trashes: A0
|
||
;
|
||
; Function: returns the idle disable flag count
|
||
;________________________________________________________________________________________
|
||
|
||
IdleEnable
|
||
MOVE.W SR,-(SP) ; Save the status register
|
||
ORI.W #HiIntMask,SR ; Kill those vicious interrupts
|
||
MOVEQ #0,D0 ; Clear the register
|
||
MOVE.L PMgrBase,A0 ; Get pmgr locals
|
||
SUBQ.B #1,IdleFlagCnt(A0) ; pop a level
|
||
BPL.S @DontClr ; IF IdleFlagCnt < 0 THEN
|
||
CLR.B IdleFlagCnt(A0) ; IdleFlagCnt = 0
|
||
@DontClr MOVE.B IdleFlagCnt(A0),D0 ; return idle disable count
|
||
MOVE.W (SP)+,SR ; restore the status register
|
||
RTS
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: IdleDisable (PowerDispatch selector #6)
|
||
;
|
||
; Inputs: none
|
||
;
|
||
; Outputs: D0 - idle disable count
|
||
;
|
||
; Trashes: A0
|
||
;
|
||
; Function: returns the idle disable flag count
|
||
;________________________________________________________________________________________
|
||
|
||
IdleDisable
|
||
MOVE.W SR,-(SP) ; Save the status register
|
||
ORI.W #HiIntMask,SR ; Kill those vicious interrupts
|
||
MOVEQ #0,D0 ; Clear the register
|
||
MOVE.L PMgrBase,A0 ; Get pgmr locals
|
||
ADD.B #1,IdleFlagCnt(A0) ; push a level
|
||
MOVE.B IdleFlagCnt(A0),D0 ; return idle disable count
|
||
MOVE.W (SP)+,SR ; restore the status register
|
||
NoPrimRTS RTS
|
||
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: CPUSpeed (PowerDispatch selector #7)
|
||
;
|
||
; Inputs: none
|
||
;
|
||
; Outputs: D0 - [maximum CPU speed (high word)][current CPU speed (low word)]
|
||
;
|
||
; Trashes: A0,A1
|
||
;
|
||
; Function: returns the maximum and current CPU speeds, in MHz
|
||
;________________________________________________________________________________________
|
||
|
||
CPUSpeed
|
||
MOVEA.L PMgrBase,A2 ; get pointer to Power Manager globals
|
||
MOVEQ #0,D0 ; assume no speed
|
||
JmpRoutine CPUSpeedPtr,A2,A0 ; go do that routine
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: BasePRAM (PowerDispatch selector #8)
|
||
;
|
||
; Inputs: none
|
||
;
|
||
; Outputs: D0 - base PRAM address used by the Power Manager
|
||
;
|
||
; Trashes: A0,A1
|
||
;
|
||
; Function: returns the base PRAM address that the Power Manager uses for keeping its
|
||
; permanent state information
|
||
;________________________________________________________________________________________
|
||
|
||
BasePRAM
|
||
MOVEA.L PMgrBase,A2 ; get pointer to Power Manager globals
|
||
MOVEQ #0,D0
|
||
MOVE.B PRAMbase(A2),D0 ; stuff in the base PRAM address we use
|
||
RTS
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: ScaledBattery (PowerDispatch selector #9)
|
||
;
|
||
; Inputs: none
|
||
;
|
||
; Outputs: D0 - battery information:
|
||
; bits 31: 1=battery installed
|
||
; 30: 1=battery is charging
|
||
; 29: 1=charger connected
|
||
; 23-16: warning level (0-255)
|
||
; 7- 0: battery level (0-255)
|
||
;
|
||
; Trashes: D1-D2, A0-A2
|
||
;
|
||
; Function: returns battery and warning levels scaled into the range 0-255
|
||
;________________________________________________________________________________________
|
||
|
||
ScaledBattery
|
||
MOVEA.L PMgrBase,A2 ; get pointer to Power Manager globals
|
||
MOVEQ #0,D0 ; assume no battery info
|
||
JmpRoutine ScaledBattPtr,A2,A0 ; go do that routine
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: PowerMgrHook (PowerDispatch selector #10)
|
||
;
|
||
; Inputs: D0 - [hook selector (high word)][PowerDispatch selector=10 (low word)]
|
||
;
|
||
; Outputs: varies with selector
|
||
;
|
||
; Trashes: D1-D2, A0-A2
|
||
;
|
||
; Function: secondary dispatch selector for various functions
|
||
;________________________________________________________________________________________
|
||
|
||
PowerMgrHook
|
||
WITH PMgrHookRec
|
||
MOVE.L PmgrBase,A2 ; Get pointer to globals
|
||
LoadTbl PmgrHookTbl,A2,A0 ; Get pointer to Table
|
||
MOVEQ #0,D1 ; Clear D1
|
||
SWAP D0 ; Get selector
|
||
MOVE.W D0,D1 ; Get selector in D1
|
||
LSL.W #2,D1 ; Convert selector to bytes
|
||
CMP.L PmgrHookCount(A0),D1 ; IF Dispatch Out of Range THEN
|
||
BHI.S @OutOfRange ; Get Out Of Here
|
||
JMP ([A0,D1.L]) ; Go do that routine
|
||
|
||
@OutOfRange
|
||
MOVEQ #paramErr,D0 ; Abort and return error
|
||
RTS
|
||
ENDWITH
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: SecondaryInitproc (PowerMgrHook selector #0)
|
||
;
|
||
; Inputs: none
|
||
;
|
||
; Outputs: none
|
||
;
|
||
; Trashes: none
|
||
;
|
||
; Function: code to execute at secondary init time
|
||
;________________________________________________________________________________________
|
||
|
||
SecondaryInitproc
|
||
BCLR #PmgrShutdownReq,PmgrFlags1(A2) ; clear any pending shutdown requests
|
||
BSET #PmgrShutdownEnb,PmgrFlags1(A2) ; enable shutdown requests
|
||
MOVEQ #noErr,D0
|
||
RTS
|
||
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: ScsiDiskModeproc (PowerMgrHook selector #1)
|
||
;
|
||
; Inputs: none
|
||
;
|
||
; Outputs: none
|
||
;
|
||
; Trashes: none
|
||
;
|
||
; Function: code to execute if SCSI Disk Mode was entered
|
||
;________________________________________________________________________________________
|
||
|
||
ScsiDiskModeproc
|
||
BSET #7,PmgrFlags(A2)
|
||
MOVEQ #noErr,D0
|
||
RTS
|
||
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: ExternaVideoOnproc (PowerMgrHook selector #2)
|
||
;
|
||
; Inputs: none
|
||
;
|
||
; Outputs: none
|
||
;
|
||
; Trashes: none
|
||
;
|
||
; Function: code to execute if external video is running
|
||
;________________________________________________________________________________________
|
||
|
||
ExternaVideoOnproc
|
||
LoadTbl PrimInfoTblPtr,A2,A1 ; Get pointer to primitives table
|
||
MOVE.B PrimExtVidCor(A1),D0 ; Get Delta Threshold
|
||
ADD.B D0,LowWarn(A2) ; add delta threshold to LowWarn
|
||
BSR SetPwrLvlTask ; update the power manager micro
|
||
MOVEQ #noErr,D0 ; Indicate no problems
|
||
RTS ;
|
||
|
||
;________________________________________________________________________________________ <K9>
|
||
;
|
||
; Routine: ModemTypeProc (PowerMgrHook selector #3)
|
||
;
|
||
; Inputs: none
|
||
;
|
||
; Outputs: d0.l -- modem type
|
||
;
|
||
; Trashes: a0
|
||
;
|
||
; Function: returns modem type constant
|
||
;________________________________________________________________________________________
|
||
ModemTypeProc
|
||
WITH ModemTblRec
|
||
|
||
bsr.l ModemStatusRT ; d0 has the modem status
|
||
btst.l #ModemInstalled,d0 ; is the modem physically installed
|
||
beq.s @noModem ; if not set, no modem, exit
|
||
|
||
move.l PmgrBase,a0 ; Get pointer to globals
|
||
moveq.l #ModemTypeUnk,d0 ; assume modem installed of unknown type
|
||
LoadTbl ModemTblPtr,a0,a0 ; load the Modem table pointer
|
||
beq.s @exit ; yes
|
||
JsrPrimTbl GetModemType,A0 ; get modem type
|
||
rts
|
||
|
||
@noModem moveq.l #ModemTypeNone,d0 ; no modem
|
||
@exit rts
|
||
ENDWITH
|
||
|
||
;———————————————————————————————————————————————————————————————————————————————————————— <K9>
|
||
; Routine: ModemStatus
|
||
;
|
||
; Inputs: none
|
||
; Outputs: d0.b - modem status byte
|
||
; Trashes: none
|
||
;
|
||
; Called by: ModemTypeProc
|
||
; Calls: PMgrOp
|
||
; Function: return the modem status byte in d0
|
||
;————————————————————————————————————————————————————————————————————————————————————————
|
||
ModemStatusRT
|
||
@workingset reg a0
|
||
|
||
movem.l @workingset,-(sp)
|
||
;
|
||
; read power manager's modem bit
|
||
;
|
||
MOVEQ.L #0,D0 ; clear the result register
|
||
CLR.L -(SP) ; allocate a buffer for the result
|
||
MOVE.L SP,-(SP) ; pmRBuffer
|
||
MOVE.L (SP),-(SP) ; pmSBuffer
|
||
CLR.W -(SP) ; pmLength
|
||
MOVE.W #modemRead,-(SP) ; pmCommand
|
||
MOVEA.L SP,A0 ; point to the parameter block
|
||
_PMgrOp ; get the modem info
|
||
MOVE.B pmData(SP),D0 ; return the status byte
|
||
ADDA.L #pmBlkSize, sp ; pop buffer
|
||
|
||
MOVEA.L (SP)+,A0 ; <K28>
|
||
RTS
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: PDimScreens (PowerDispatch selector #11)
|
||
;
|
||
; Inputs: D0 - high word: 0=power up, 1=power down
|
||
;
|
||
; Outputs: none
|
||
;
|
||
; Trashes: A0
|
||
;
|
||
; Function: sets a flag so that IdleMind handles changing state of screens
|
||
;________________________________________________________________________________________
|
||
|
||
PDimScreens
|
||
MOVEA.L PmgrBase,A0 ; get pointer to globals
|
||
MOVE SR,D0 ; save the sr
|
||
SWAP D0 ; Let get the parameter
|
||
ORI #HiIntMask,SR ; Mask Interrupts
|
||
BSET #PmgrDimReq,PmgrFlags1(A0) ; set the request
|
||
BSET #PmgrDimState,PmgrFlags1(A0) ; assume Power Down state
|
||
TST.W D0 ; IF Powering Up THEN
|
||
BNE.S @Done ;
|
||
BCLR #PmgrDimState,PmgrFlags1(A0) ; set Power Up State
|
||
@Done
|
||
SWAP D0 ; get saved sr
|
||
MOVE D0,SR ; restore sr
|
||
MOVEQ #0,D0 ; noErr
|
||
RTS ; goodbye
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: PrivateFeatures (PowerDispatch selector #13)
|
||
;
|
||
; Inputs: none
|
||
;
|
||
; Outputs: D0: bits 0: 1=extended battery status call is supported by PMGR
|
||
; 1: 1=battery ID call is supported by PMGR
|
||
; 2: 1=switch AC power on/off call is supported by PMGR
|
||
;
|
||
; Trashes: A0
|
||
;
|
||
; Function: Returns a bitmap of private Power Manager features.
|
||
;________________________________________________________________________________________
|
||
|
||
PrivateFeatures
|
||
MOVEA.L PMgrBase,A2 ; get pointer to Power Manager globals
|
||
LoadTbl PrimInfoTblPtr,A2,A0 ; get pointer to Info
|
||
MOVE.L PrimPrivFeatures(A0),D0 ; return the bitmap
|
||
RTS
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: GetButtonValues (PowerDispatch selector #15)
|
||
;
|
||
; Inputs: D0 - high word: 0=Brightness Button, 1=Contrass Button
|
||
;
|
||
; Outputs: D0 - Normalized value from 0-31
|
||
;
|
||
; Trashes: A0
|
||
;
|
||
; Function: Return the current state of the appropriate button
|
||
;________________________________________________________________________________________
|
||
|
||
GetButtonValues
|
||
SWAP D0 ; Let get the parameter
|
||
MOVE.B D0,-(SP) ; data to send = Brightness or Contrass
|
||
MOVE.L SP,-(SP) ; pmRBuffer
|
||
MOVE.L (SP),-(SP) ; pmSBuffer
|
||
MOVE.W #1,-(SP) ; pmLength
|
||
MOVE.W #readButton,-(SP) ; pmCommand
|
||
MOVEA.L SP,A0 ; point to the parameter block
|
||
_PMgrOp ; turn off the hard disk
|
||
LEA pmRBuffer+4(SP),SP ; clean up the stack
|
||
MOVEQ #0,D0 ; clear the register
|
||
MOVE.B (SP)+,D0 ; get the result value and clean off the stack
|
||
RTS
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: SetHDState (PowerDispatch selector #16)
|
||
;
|
||
; Inputs: D0 - high word: 0=Spin down HD, 1=Spin Up HD
|
||
;
|
||
; Outputs: none
|
||
;
|
||
; Trashes: A0
|
||
;
|
||
; Function: Return the current state of the appropriate button
|
||
;________________________________________________________________________________________
|
||
|
||
SetHDState
|
||
SWAP D0 ; Let get the parameter
|
||
MOVEA.L PMgrBase,A0 ; Get pointer to the globas
|
||
TST.W D0 ;
|
||
BEQ.S @DoSpinDown
|
||
|
||
@DoHDSpinUp
|
||
MOVE.L HDSpinUpVector(A0),D0 ; is there a spin up routine?
|
||
BEQ.S @Done ; -> no, just exit
|
||
MOVEA.L D0,A0 ; yes, call the spinup down routine
|
||
JSR (A0)
|
||
BRA.S @Done
|
||
|
||
@DoSpinDown
|
||
MOVE.L LastHD(A0),D0 ; is the hard disk spinning?
|
||
BEQ.S @Done ; -> no, just exit
|
||
MOVE.L HDvector(A0),D0 ; is there a spindown routine?
|
||
BEQ.S @Done ; -> no, just exit
|
||
MOVEA.L D0,A0 ; yes, call the spindown routine
|
||
JSR (A0)
|
||
|
||
@Done MOVEQ #noErr,D0 ; return no error
|
||
RTS ; going home
|
||
|
||
|
||
;________________________________________________________________________________________ <K16>
|
||
; |
|
||
; Routine: PmgrOp v
|
||
;
|
||
; Inputs: D1 - trap word
|
||
;
|
||
; Outputs: D0 - selector result, or error code if bad selector
|
||
;
|
||
; Trashes: varies by selector
|
||
;
|
||
; Function: This is the PmgrOp trap, and provides which provide for
|
||
; PmgrTrap ($A085)
|
||
; IdleUpdate ($A285)
|
||
; IdleState ($A485)
|
||
; SerialPower ($A685)
|
||
;________________________________________________________________________________________
|
||
|
||
PmgrOp
|
||
WITH PMgrOpTblRec
|
||
ANDI.L #$00000F00,D1 ; Clear all but the trap modifier bits
|
||
LSR.W #7,D1 ; Convert selector to bytes
|
||
|
||
MOVE.L PmgrBase,A1 ; Get pointer to globals
|
||
CMPA.L #-1,A1 ; IF Power Manager Var valid THEN
|
||
BEQ.S @UseROMTable ; .
|
||
LoadTbl PMgrOpTblPtr,A1,A1 ; Get pointer to Table
|
||
CMP.L PMgrOpTblCount(A1),D1 ; IF Trap Out of Range THEN
|
||
BHI.S @OutOfRange ; Get Out Of Here
|
||
JMP ([A1,D1.L]) ; Do the TRAP
|
||
@UseROMTable ; ELSE
|
||
MOVEA.L UnivInfoPtr,A1 ; A0 = ProductInfo table (ROM)
|
||
ADDA.L PowerManagerPtr(A1),A1 ; A0 = ROM Power Manager's primitives (ROM)
|
||
ADDA.L PMgrOpTblPtr(A1),A1 ; A0 = Power Managers PMgrOpTblPtr (ROM)
|
||
CMP.L PMgrOpTblCount(A1),D1 ; IF Trap Out of Range THEN
|
||
BHI.S @OutOfRange ; Get Out Of Here
|
||
MOVE.L (A1,D1.L),D1 ; get offset to the trap
|
||
JMP (A1,D1.L) ; Do the TRAP
|
||
|
||
@OutOfRange
|
||
MOVEQ #paramErr,D0 ; Abort and return error
|
||
RTS ; <K16>
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: PmgrTrap
|
||
;
|
||
; Inputs: A0 -- pointer to Power Manager parameter block
|
||
; [word] command/reply
|
||
; [word] number of bytes to send/receive
|
||
; [long] pointer to send buffer
|
||
; [long] pointer to receive buffer
|
||
;
|
||
; Outputs: D0 -- result code: 0 if successful, else error code
|
||
; (all other registers are preserved)
|
||
;
|
||
; Uses: D1 -- byte to send/byte received
|
||
; D2 -- timeout value for handshaking
|
||
; D3 -- loop counter / miscellaneous
|
||
; D4 -- saved copy of parameter block pointer
|
||
; D5 -- timeout value
|
||
; D6 -- [saved SR][interface model: 0=parallel, 2=serial, ...]
|
||
; D7 -- pointer to top of SCC poll stack
|
||
; A1 -- pointer to VIA1 base
|
||
; A2 -- pointer to VIA2 base
|
||
; A3 -- send or receive buffer pointer
|
||
; A4 -- saved return addresses (Wait4AckLo, Wait4AckHi)
|
||
; A5 -- saved return addresses (SendByte, ReceiveByte)
|
||
; A6 -- pointer to SCC channel A data register
|
||
;
|
||
; Function: This is the Power Manager interface trap ($A085).
|
||
;________________________________________________________________________________________
|
||
|
||
|
||
PMack EQU v2PMack
|
||
PMreq EQU v2PMreq
|
||
PMbuf EQU vBufAH
|
||
PMbufDir EQU vDirA
|
||
|
||
|
||
PMgrTrap
|
||
pmgrPollRegs REG D3/D4/D5/D6/A0/A1/A2/A4
|
||
@numPollRegs EQU 4+4
|
||
@savedRegs REG D1-D7/A0-A6
|
||
|
||
MOVEM.L @savedRegs,-(SP) ; save working registers
|
||
|
||
BSR SetupPMgrOpInterface ; get the setup information
|
||
MOVE.W SR,D6 ; save the entry SR in the upper half of D6
|
||
SWAP D6
|
||
MOVE.W D1,D6 ; and the interface model in the lower half
|
||
MOVEA.L A1,A3 ; save the table pointer
|
||
|
||
; remember the current PMGR interrupt setting, and then disable PMGR interrupts...
|
||
|
||
MOVEA.L VIA,A1 ; point to VIA1
|
||
MOVEA.L VIA2,A2 ; point to the VIA with the handshake lines
|
||
|
||
MOVEQ #(1<<ifCB1),D1 ; uses CB1 for IRQ
|
||
AND.B vIER(A1),D1 ; mask off the PMGR interrupt enable bit(s)
|
||
MOVE.B D1,vIER(A1) ; and disable any that are enabled
|
||
BEQ.S @NoPMGRInt ; -> interrupts are currently disabled
|
||
BSET #ifIRQ,D1 ; be sure to re-enable them on exit
|
||
@NoPMGRInt MOVE.B D1,-(SP)
|
||
|
||
; set up for SCC polling...
|
||
|
||
LEA -4*@numPollRegs(SP),SP ; allocate space for registers saved if we call PollProc
|
||
MOVE.L SP,D7 ; point to the stack top for our SCC poll stack
|
||
|
||
MOVEA.L SccRd,A6 ; point to the SCC channel A's data register <H26>
|
||
ADDQ.W #aData,A6 ; <H26>
|
||
TST.L PollProc ; is a poll proc installed? <H52>
|
||
BNE.S @WillPoll ; -> yes <H52>
|
||
LEA @NoPollSCC+sccData,A6 ; no, avoid collecting bytes no one will use <H52>
|
||
@WillPoll
|
||
|
||
; run thru the exception table for this machine to see if this command is emulated...
|
||
|
||
MOVE.L A0,D4 ; save the pointer to the parameter block
|
||
MOVE.W pmCommand(A0),D0 ; get the command
|
||
TST.L A3 ; IF Exception pointer <> NULL THEN
|
||
BEQ.S @NoExceptions ;
|
||
LEA -4(A3),A3 ; subtract 4 bytes for the loop
|
||
@NextException ; WHILE notDone DO {
|
||
ADDQ.W #4,A3 ; skip over the offset to the previous handler
|
||
MOVE.B (A3)+,D1 ; get the mask
|
||
BEQ.S @NoExceptions ; IF mask = NULL THEN end of list
|
||
AND.B D0,D1 ; mask off the bits we care about
|
||
CMP.B (A3)+,D1 ; IF this command emulated THEN
|
||
BNE.S @NextException ;
|
||
MOVEM.L A0-A2,-(SP) ; save state
|
||
ORI #HiIntMask,SR ; mask interrupts
|
||
TST.L D2 ; IF rom tables THEN <K15>
|
||
BNE.S @RamTables ; .
|
||
ADDA.L (A3),A3 ; calculate the handler's address
|
||
JSR (A3) ; and call the handler
|
||
BRA.S @ExceptDone ;
|
||
@RamTables
|
||
JSR ([A3]) ; call the handler
|
||
@ExceptDone
|
||
MOVEM.L (SP)+,A0-A2 ; restore state
|
||
BEQ @PMgrOpExit ; and exit
|
||
@NoExceptions ; }
|
||
|
||
MOVE.W TimeVIAdb,D5 ; calculate a 32ms timeout value
|
||
LSL.W #5,D5
|
||
|
||
MOVE.W #8*64-1,D3 ; initialize the retry count (8 ms)
|
||
MOVE.W (A0)+,D1 ; get the command byte
|
||
|
||
; wait for /ack to go away in case the PMGR is busy...
|
||
|
||
@CmdRetry MOVE.W #pmBusyErr,D0 ; assume a timeout
|
||
MOVE.W timeVIAdb,D2 ; use a 4 ms timeout value
|
||
LSL.W #2,D2
|
||
BSR Wait4AckHi ; wait for /ack to go high if it's currently low
|
||
BEQ @PMgrOpExit ; -> timed out waiting for initial conditions
|
||
|
||
IF hasNiagra THEN ; <H39>
|
||
IF isUniversal THEN ; <H39>
|
||
TestFor NiagraExistsBit ; <H39>
|
||
beq @pmgrFree ; call old routine <H39>
|
||
ENDIF ; <H39>
|
||
@BusyCheck
|
||
MOVE.W timeVIAdb,D2 ; Get 1ms timeout value <H39>
|
||
LSL.W #4,D2 ; multiply by 16 <H39>
|
||
MOVE.B #0,PMBufDir(A2) ; set Port A is input <H39>
|
||
@pmgrbusy
|
||
CMP.B #$07,PMbuf(A2) ; Get port status <H39>
|
||
DBNE D2,@pmgrbusy ; Wait pmgr not busy <H39>
|
||
BNE.S @pmgrFree ; if not busy status, continue <H39>
|
||
MOVE.L #pmBusyErr,D0 ; Timeout, flag error <H39>
|
||
BRA @PMgrOpExit ; Timed out waiting for initial conditions <H39>
|
||
@pmgrFree
|
||
ENDIF ; <H39>
|
||
|
||
; send the command byte...
|
||
|
||
ORI #HiIntMask,SR ; no interrupts while sending the command bytes
|
||
BSR SendByte ; send the command byte
|
||
BEQ.S @SendCount ; -> success
|
||
|
||
BSR UnloadPollstack ; unload any SCC data stashed while trying to send the command byte
|
||
|
||
MOVE.W D5,D2 ; wait for the handshake to abort
|
||
SWAP D6
|
||
@spin MOVE.W D6,SR ; restore the interrupt level
|
||
DBRA D2,@spin
|
||
SWAP D6
|
||
|
||
DBRA D3,@CmdRetry ; try again
|
||
BRA @PMgrOpExit ; -> enough retries: just abort
|
||
|
||
; send the byte count...
|
||
;
|
||
; As an optimization, commands with fixed length data do not have their
|
||
; count byte sent to the PMGR since both sides know what the count is.
|
||
|
||
@SendCount MOVE.W (A0)+,D3 ; get the byte count
|
||
TestFor PMgrNewIntf ; new PMGR?
|
||
BEQ.S @SendTheCnt ; -> no, it still sends the count anyway
|
||
LEA cmdCounts,A3
|
||
MOVEA.L PMgrBase,A4 ; point to the Power Manager's variables <H3>
|
||
CMPA.W #-1,A4 ; are they valid yet (-1 if not initialized)? <H3>
|
||
BEQ.S @NoSendTbl ; -> no, use the default table <H3>
|
||
MOVEA.L vSendCountTbl(A4),A3 ; yes, use the vectored send table <H52>
|
||
@NoSendTbl TST.B 0(A3,D1) ; do we need to send the count? <H3>
|
||
BPL.S @NoSendCnt ; -> no, both sides know what it is
|
||
@SendTheCnt MOVE.W D3,D1 ; use the count passed in
|
||
BSR SendByte ; send the byte count to the PMGR
|
||
BNE.S @PMgrOpExit ; -> error
|
||
|
||
; send the command's data bytes to the PMGR...
|
||
|
||
@NoSendCnt MOVEA.L (A0),A3 ; get the pointer to the command's data bytes
|
||
MOVEQ #0,D1 ; (set CCR for BEQ so DBNE below won't fall thru)
|
||
BRA.S @StartSend
|
||
|
||
@SendData MOVE.B (A3)+,D1 ; get the next data byte
|
||
BSR SendByte ; and send it
|
||
@StartSend DBNE D3,@SendData ; -> more bytes to send
|
||
BNE.S @PMgrOpExit ; -> error
|
||
|
||
; the command has been sent, so check if we need to wait for a reply...
|
||
|
||
SUBQ.W #pmSBuffer-pmCommand,A0 ; point to the start of the parameter block
|
||
MOVE.W (A0),D1 ; get the command byte before it gets trashed
|
||
LEA replyCounts,A3
|
||
MOVEA.L PMgrBase,A4 ; point to the Power Manager's variables <H3>
|
||
CMPA.W #-1,A4 ; are they valid yet (-1 if not initialized)? <H3>
|
||
BEQ.S @NoRecvTbl ; -> no, use the default table <H3>
|
||
MOVEA.L vRecvCountTbl(A4),A3 ; yes, use the vectored receive table <H52>
|
||
@NoRecvTbl MOVE.B 0(A3,D1),D3 ; get the reply byte count <H3>
|
||
EXT.W D3
|
||
MOVE.W D3,pmLength(A0) ; stuff the count in case there's no reply <H31>
|
||
BEQ.S @PMgrOpExit ; -> no reply, so we're done
|
||
|
||
; read in the reply byte...
|
||
;
|
||
; We don't expect a reply byte except for specific commands.
|
||
|
||
TestFor PMgrNewIntf ; new PMGR?
|
||
BEQ.S @ReadReply ; -> no, it still wants the reply byte anyway
|
||
SUBQ.W #1,D3 ; do we need to get a reply byte?
|
||
BNE.S @NoReply ; -> nope
|
||
@ReadReply BSR ReceiveByte ; get the reply byte
|
||
BNE.S @ReplyTO ; -> error
|
||
|
||
@NoReply MOVE.W D1,(A0)+ ; save the reply byte in the parameter block
|
||
|
||
; read in the reply byte count...
|
||
;
|
||
; As an optimization, replies with fixed length data do not have their
|
||
; count byte sent by the PMGR since both sides know what the count is.
|
||
|
||
TestFor PMgrNewIntf ; new PMGR?
|
||
BEQ.S @ReadCount ; -> no, it still wants the count anyway
|
||
TST.W D3 ; is the PMGR sending us a byte count?
|
||
BPL.S @NoReplyCnt ; -> no, we both know what it is
|
||
|
||
@ReadCount BSR ReceiveByte ; get the count byte
|
||
BNE.S @PMgrOpExit ; -> error
|
||
MOVE.W D1,D3 ; update the reply data byte count
|
||
|
||
@NoReplyCnt MOVE.W D3,(A0)+ ; save the byte count in the parameter block
|
||
|
||
; get the reply's data bytes from the PMGR...
|
||
|
||
ADDQ.W #pmRBuffer-pmSBuffer,A0
|
||
MOVEA.L (A0)+,A3 ; get the pointer to where the reply bytes will go
|
||
BRA.S @StartReply
|
||
|
||
@ReplyData BSR ReceiveByte ; get the next reply data byte
|
||
BNE.S @PMgrOpExit ; -> error
|
||
MOVE.B D1,(A3)+ ; save the byte in the reply data buffer
|
||
@StartReply DBRA D3,@ReplyData ; -> more bytes to get
|
||
|
||
; special-case the power control command, and add a delay if anything was turned on...
|
||
|
||
@PMgrOpExit MOVEA.L VIA,A1
|
||
MOVEA.L D4,A0 ; restore the pointer to the parameter block <H49>
|
||
|
||
MOVE.W D0,D4 ; save the result code
|
||
BNE.S @NotPC ; -> no point in delaying if the command failed <H46>
|
||
|
||
CMPI.W #powerCntl,pmCommand(A0); was this a power control command? <H26>
|
||
BNE.S @NotPC ; -> nope, really all done <H26>
|
||
MOVEA.L pmSBuffer(A0),A2 ; point to the send buffer <H36>
|
||
CMPI.B #(1<<pTurnOn),(A2) ; was something being turned on? <H36>
|
||
BLS.S @NotPC ; -> nope, no need to wait <H36>
|
||
MOVE.W TimeVIAdb,D2 ; wait 125usec for the power planes to stabilize <H36>
|
||
LSR.W #3,D2 ; <H36>
|
||
@Wait125us TST.B (A1) ; (throttle execution speed with a VIA access) <H36>
|
||
BTST #RxCA,-sccData(A6) ; SCC data available? <H36>
|
||
BEQ.S @NoSCCData ; <H36>
|
||
MOVE.B (A6),-(SP) ; yes, push it on the stack <H36>
|
||
@NoSCCData DBRA D2,@Wait125us ; -> keep looping if not <H36>
|
||
|
||
; check if any SCC bytes were collected so we can send them to the serial driver...
|
||
|
||
@NotPC BSR UnloadPollstack ; unload any SCC data stashed while interrupts were disabled
|
||
LEA 4*@numPollRegs(SP),SP ; de-allocate PollProc saved register frame
|
||
|
||
; clean everything up...
|
||
|
||
MOVE.B (SP)+,vIER(A1) ; restore the PMGR interrupt state
|
||
SWAP D6
|
||
MOVE.W D6,SR
|
||
MOVE.W D4,D0 ; restore the result
|
||
EXT.L D0 ; set condition codes
|
||
MOVEM.L (SP)+,@savedRegs ; restore working registers
|
||
RTS
|
||
|
||
@ReplyTO MOVE.W #pmReplyTOErr,D0 ; timed out waiting for the reply
|
||
BRA.S @PMgrOpExit
|
||
|
||
@NoPollSCC DC.W 0 ; A6 points here if no PollProc to avoid stack overflow <H52>
|
||
|
||
|
||
;________________________________________________________________________________________
|
||
|
||
;
|
||
; Routine: Wait4AckLo
|
||
;
|
||
; Inputs: D2 -- timeout count
|
||
; A1 -- pointer to VIA1 base
|
||
; A2 -- pointer to VIA2 base
|
||
; A6 -- pointer to SCC channel A data register
|
||
;
|
||
; Outputs: CCR-- BEQ: /ack has gone low, BNE: timed out
|
||
;
|
||
; Trashes: D2,A4
|
||
;
|
||
; Function: waits for the /ack handshake line to go low (may time out)
|
||
;________________________________________________________________________________________
|
||
|
||
|
||
Wait4AckLo MOVEA.L (SP)+,A4 ; save the return address
|
||
BRA.S @WaitLoop
|
||
|
||
@CheckSCC TST.B (A1) ; (throttle execution speed with a VIA access)
|
||
BTST #RxCA,-sccData(A6) ; SCC data available? <H26>
|
||
BEQ.S @WaitLoop ; <H7>
|
||
MOVE.B (A6),-(SP) ; yes, push it on the stack <H26>
|
||
@WaitLoop BTST.B #PMack,(A2) ; has /ack gone low yet?
|
||
DBEQ D2,@CheckSCC ; -> keep looping if not
|
||
JMP (A4)
|
||
|
||
|
||
;________________________________________________________________________________________
|
||
|
||
;
|
||
; Routine: Wait4AckHi
|
||
;
|
||
; Inputs: D2 -- timeout count
|
||
; A1 -- pointer to VIA1 base
|
||
; A2 -- pointer to VIA2 base
|
||
; A6 -- pointer to SCC channel A data register
|
||
;
|
||
; Outputs: CCR-- BNE: /ack has gone high, BEQ: timed out
|
||
;
|
||
; Trashes: D2,A4
|
||
;
|
||
; Function: waits for the /ack handshake line to go high (may time out)
|
||
;________________________________________________________________________________________
|
||
|
||
|
||
Wait4AckHi MOVEA.L (SP)+,A4 ; save the return address
|
||
BRA.S @WaitLoop
|
||
|
||
@CheckSCC TST.B (A1) ; (throttle execution speed with a VIA access)
|
||
BTST #RxCA,-sccData(A6) ; SCC data available? <H26>
|
||
BEQ.S @WaitLoop ; <H7>
|
||
MOVE.B (A6),-(SP) ; yes, push it on the stack <H26>
|
||
@WaitLoop BTST.B #PMack,(A2) ; has /ack gone high yet?
|
||
DBNE D2,@CheckSCC ; -> keep looping if not
|
||
JMP (A4)
|
||
|
||
|
||
;________________________________________________________________________________________
|
||
|
||
;
|
||
; Routine: ReceiveByte
|
||
;
|
||
; Inputs: D6 -- interface type
|
||
; 0=parallel
|
||
; 2=serial
|
||
; A1 -- pointer to VIA1 base
|
||
; A2 -- pointer to VIA2 base
|
||
; A6 -- pointer to SCC channel A data register
|
||
;
|
||
; Outputs: D0 -- result code (0 if successful)
|
||
; D1 -- byte received
|
||
;
|
||
; Trashes: D2,A4,A5
|
||
;
|
||
; Function: handshakes a byte from the PMGR micro
|
||
;________________________________________________________________________________________
|
||
|
||
|
||
ReceiveByte MOVE.W D5,D2 ; use the standard timeout value
|
||
MOVE.W #pmRecvStartErr,D0 ; assume we'll time out
|
||
MOVEA.L (SP)+,A5 ; save the return address <H7>
|
||
JMP @ReadByte(D6.W) ; go read a byte
|
||
|
||
@ReadByte BRA.S @RecvParallel
|
||
; BRA.S @RecvSerial
|
||
|
||
|
||
@RecvSerial
|
||
ORI.B #%00001100,vACR(A1) ; ***for BlackBird_EVT0 HJR***
|
||
BCLR #4,vACR(A1) ; set shift register to shift in under external clock
|
||
TST.B vSR(A1) ; read a byte to reset the shifter
|
||
|
||
BCLR #PMreq,(A2) ; assert /req to start the handshake
|
||
|
||
BSR.S Wait4AckLo ; wait for /ack to go low
|
||
BNE.S SendRcvDone ; -> timed out
|
||
|
||
BSET #PMreq,(A2) ; de-assert /req since we've seen /ack asserted
|
||
|
||
MOVE.W #pmRecvEndErr,D0 ; assume we'll time out
|
||
MOVE.W D5,D2
|
||
BSR.S Wait4AckHi ; wait for /ack to go high
|
||
BEQ.S SendRcvDone ; -> timed out
|
||
|
||
MOVE.B vSR(A1),D1 ; read in the byte
|
||
|
||
MOVEQ #NoErr,D0 ; success!
|
||
BRA.S SendRcvDone
|
||
|
||
|
||
@RecvParallel
|
||
MOVE.B #$00,PMBufDir(A2) ; make the data port an input
|
||
|
||
BSR.S Wait4AckLo ; wait for /ack to go low
|
||
BNE.S SendRcvDone ; -> timed out
|
||
|
||
BCLR #PMreq,(A2) ; assert the /req line
|
||
|
||
MOVE.B PMbuf(A2),D1 ; read in the byte
|
||
|
||
MOVE.W #pmRecvEndErr,D0 ; assume we'll time out
|
||
FinishHshk MOVE.W D5,D2
|
||
BSR.S Wait4AckHi ; wait for /ack to go high
|
||
BEQ.S SendRcvDone ; -> timed out
|
||
|
||
MOVEQ #NoErr,D0 ; success!
|
||
|
||
SendRcvDone BSET #PMreq,(A2) ; be sure /req is not asserted
|
||
JSR DisableBuf(D6.W) ; turn off the data buffer
|
||
TST.W D0 ; set the condition codes
|
||
JMP (A5) ; <H7>
|
||
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: SendByte
|
||
;
|
||
; Inputs: D1 -- byte to send
|
||
; D2 -- timeout count
|
||
; D6 -- interface type
|
||
; 0=parallel
|
||
; 2=serial
|
||
; A1 -- pointer to VIA1 base
|
||
; A2 -- pointer to VIA2 base
|
||
; A6 -- pointer to SCC channel A data register
|
||
;
|
||
; Outputs: D0 -- result code (0 if successful)
|
||
;
|
||
; Trashes: D2,A4,A5
|
||
;
|
||
; Function: handshakes a byte to the PMGR micro
|
||
;________________________________________________________________________________________
|
||
|
||
SendByte MOVE.L D5,D2 ; use the standard timeout value
|
||
MOVEA.L (SP)+,A5 ; save the return address <H7>
|
||
|
||
JSR @SendByte(D6.W) ; send the byte
|
||
|
||
BCLR #PMreq,(A2) ; assert the /req line
|
||
|
||
MOVE.W #pmSendStartErr,D0 ; assume we'll time out
|
||
BSR Wait4AckLo ; wait for /ack to go low
|
||
BNE.S SendRcvDone ; -> timed out
|
||
|
||
BSET #PMreq,(A2) ; de-assert the /req line
|
||
|
||
MOVE.W #pmSendEndErr,D0 ; assume we'll time out
|
||
BRA.S FinishHshk ; wait for /ack to go high
|
||
|
||
|
||
@SendByte BRA.S @SendParallel ; [0] parallel interface
|
||
; BRA.S @SendSerial ; [2] serial interface
|
||
|
||
@SendSerial
|
||
ORI.B #%00011100,vACR(A1) ; ***for BlackBird_EVT0 HJR***
|
||
; BSET #4,vACR(A1) ; set shift register to shift out under external clock
|
||
MOVE.B D1,vSR(A1) ; write out the byte to the shift register
|
||
RTS
|
||
|
||
@SendParallel
|
||
MOVE.B #$FF,PMBufDir(A2) ; make the data port an output
|
||
MOVE.B D1,PMBuf(A2) ; and write out the byte
|
||
RTS
|
||
|
||
|
||
DisableBuf BRA.S @Buf2Input ; [0] parallel interface
|
||
; BRA.S @DisableSR ; [2] serial interface
|
||
|
||
@DisableSR
|
||
ORI.B #%00011100,vACR(A1) ; ***for BlackBird_EVT0 HJR***
|
||
; BSET #4,vACR(A1) ; make the shift register shift out
|
||
RTS
|
||
|
||
@Buf2Input MOVE.B #0,PMBufDir(A2) ; switch the data port back to an input
|
||
RTS
|
||
|
||
|
||
;________________________________________________________________________________________
|
||
|
||
;
|
||
; Routine: UnloadPollstack
|
||
;
|
||
; Inputs: D7 -- pointer to top of poll stack
|
||
; A1 -- pointer to VIA1 base
|
||
; A6 -- pointer to SCC channel A data register
|
||
; SP -- pointer to bottom of poll stack
|
||
;
|
||
; Outputs: D7 -- pointer to top of poll stack
|
||
; A1 -- pointer to VIA1 base
|
||
; A6 -- pointer to SCC channel A data register
|
||
; SP -- pointer to top of poll stack
|
||
;
|
||
; Trashes: D0,D1,D2,A3,A4,A5
|
||
;
|
||
; Function: calls the poll proc to unload any bytes stashed from SCC
|
||
; port A while interrupts were disabled
|
||
;________________________________________________________________________________________
|
||
|
||
|
||
UnloadPollstack
|
||
MOVEA.L (SP)+,A4 ; pop the return address
|
||
CMPA.L D7,SP ; is there any poll data?
|
||
BEQ.S @NoSCCData ; -> no
|
||
MOVE.L PollProc,D0 ; is there a poll proc?
|
||
BEQ.S @NoPollProc ; -> no
|
||
MOVE.L D7,PollStack ; stuff the PollStack
|
||
|
||
MOVEA.L D7,A3
|
||
MOVEM.L pmgrPollRegs,(A3) ; save regs while calling poll proc W/O USING STACK
|
||
|
||
LEA vBufA(A1),A5 ; point to the register with the SCC WR/REQ bit in VIA 1<H26>
|
||
|
||
MOVEA.L D0,A3
|
||
JSR (A3) ; run the poll proc
|
||
|
||
MOVEA.L D7,A3
|
||
MOVEM.L (A3),pmgrPollRegs ; restore our registers
|
||
@NoPollProc MOVEA.L D7,SP ; toss any bytes left on the pollstack <H26>
|
||
@NoSCCData JMP (A4)
|
||
|
||
|
||
;_______________________________________________________________________________________
|
||
;
|
||
; This table is used to determine if the 680x0 needs to send a count byte to the PMGR.
|
||
; A positive value means that the count is known by both sides, and so it is not sent.
|
||
; A negative value means that the command can send variable amounts of data, so the
|
||
; count byte needs to be sent.
|
||
;
|
||
; Unused commands will be marked as expecting the count to be sent so that commands
|
||
; may be added without having to change the ROM.
|
||
|
||
cmdCounts DC.B -1 ; [$00] -
|
||
DC.B -1 ; [$01] -
|
||
DC.B -1 ; [$02] -
|
||
DC.B -1 ; [$03] -
|
||
DC.B -1 ; [$04] -
|
||
DC.B -1 ; [$05] -
|
||
DC.B -1 ; [$06] -
|
||
DC.B -1 ; [$07] -
|
||
DC.B -1 ; [$08] -
|
||
DC.B -1 ; [$09] -
|
||
DC.B -1 ; [$0A] -
|
||
DC.B -1 ; [$0B] -
|
||
DC.B -1 ; [$0C] -
|
||
DC.B -1 ; [$0D] -
|
||
DC.B -1 ; [$0E] -
|
||
DC.B -1 ; [$0F] -
|
||
|
||
DC.B 1 ; [$10] Subsystem Power/Clock Control
|
||
DC.B 1 ; [$11] Subsystem Power/Clock Control (yet more)
|
||
DC.B -1 ; [$12] -
|
||
DC.B -1 ; [$13] -
|
||
DC.B -1 ; [$14] -
|
||
DC.B -1 ; [$15] -
|
||
DC.B -1 ; [$16] -
|
||
DC.B -1 ; [$17] -
|
||
DC.B 0 ; [$18] Read Power/Clock Status
|
||
DC.B 0 ; [$19] Read Power/Clock Status (yet more)
|
||
DC.B -1 ; [$1A] -
|
||
DC.B -1 ; [$1B] -
|
||
DC.B -1 ; [$1C] -
|
||
DC.B -1 ; [$1D] -
|
||
DC.B -1 ; [$1E] -
|
||
DC.B 0 ; [$1F] RESERVED FOR MSC/PG&E EMULATION
|
||
|
||
DC.B -1 ; [$20] Set New Apple Desktop Bus Command
|
||
DC.B 0 ; [$21] ADB Autopoll Abort
|
||
DC.B 2 ; [$22] ADB Set Keyboard Addresses
|
||
DC.B 1 ; [$23] ADB Set Hang Threshold
|
||
DC.B 1 ; [$24] ADB Enable/Disable Programmers Key
|
||
DC.B -1 ; [$25] -
|
||
DC.B -1 ; [$26] -
|
||
DC.B -1 ; [$27] -
|
||
DC.B 0 ; [$28] ADB Transaction Read
|
||
DC.B -1 ; [$29] -
|
||
DC.B -1 ; [$2A] -
|
||
DC.B -1 ; [$2B] -
|
||
DC.B -1 ; [$2C] -
|
||
DC.B -1 ; [$2D] -
|
||
DC.B -1 ; [$2E] -
|
||
DC.B -1 ; [$2F] -
|
||
|
||
DC.B 4 ; [$30] Set Realtime Clock.
|
||
DC.B 20 ; [$31] Write Parameter RAM
|
||
DC.B -1 ; [$32] Write Extended Parameter RAM.
|
||
DC.B -1 ; [$33] -
|
||
DC.B -1 ; [$34] -
|
||
DC.B -1 ; [$35] -
|
||
DC.B -1 ; [$36] -
|
||
DC.B -1 ; [$37] -
|
||
DC.B 0 ; [$38] Read Realtime Clock.
|
||
DC.B 0 ; [$39] Read Parameter RAM
|
||
DC.B 2 ; [$3A] Read Extended Parameter RAM.
|
||
DC.B -1 ; [$3B] -
|
||
DC.B -1 ; [$3C] -
|
||
DC.B -1 ; [$3D] -
|
||
DC.B -1 ; [$3E] -
|
||
DC.B -1 ; [$3F] -
|
||
|
||
DC.B 1 ; [$40] Set Screen Contrast
|
||
DC.B 1 ; [$41] Set Screen Brightness <H4>
|
||
DC.B -1 ; [$42] -
|
||
DC.B -1 ; [$43] -
|
||
DC.B -1 ; [$44] -
|
||
DC.B -1 ; [$45] -
|
||
DC.B -1 ; [$46] -
|
||
DC.B -1 ; [$47] -
|
||
DC.B 0 ; [$48] Read Screen Contrast
|
||
DC.B 0 ; [$49] Read Screen Brightness
|
||
DC.B -1 ; [$4A] -
|
||
DC.B -1 ; [$4B] -
|
||
DC.B -1 ; [$4C] -
|
||
DC.B -1 ; [$4D] -
|
||
DC.B -1 ; [$4E] -
|
||
DC.B -1 ; [$4F] -
|
||
|
||
DC.B 1 ; [$50] Set Internal Modem Control Bits
|
||
DC.B 0 ; [$51] Clear FIFOs
|
||
DC.B 2 ; [$52] Set FIFO Interrupt Marks
|
||
DC.B 2 ; [$53] Set FIFO Sizes
|
||
DC.B -1 ; [$54] Write Data to Modem
|
||
DC.B 1 ; [$55] Set Data Mode
|
||
DC.B 3 ; [$56] Set Flow Control Mode <H55>
|
||
DC.B 1 ; [$57] Set DAA control lines <H54>
|
||
DC.B 0 ; [$58] Read Internal Modem Status
|
||
DC.B 1 ; [$59] Get DAA Identification <H55>
|
||
DC.B 0 ; [$5A] Get FIFO Counts
|
||
DC.B 0 ; [$5B] Get Maximum FIFO Sizes
|
||
DC.B 0 ; [$5C] Read Data From Modem
|
||
DC.B -1 ; [$5D] General Purpose modem command (modem dependent) <H58>
|
||
DC.B -1 ; [$5E] -
|
||
DC.B -1 ; [$5F] -
|
||
|
||
DC.B 2 ; [$60] Set low power warning and cutoff levels
|
||
DC.B -1 ; [$61] -
|
||
DC.B -1 ; [$62] -
|
||
DC.B -1 ; [$63] -
|
||
DC.B -1 ; [$64]
|
||
DC.B -1 ; [$65] -
|
||
DC.B -1 ; [$66] -
|
||
DC.B -1 ; [$67] -
|
||
DC.B 0 ; [$68] Read Charger State, Battery Voltage, Temperature
|
||
DC.B 0 ; [$69] Read Instantaneous Charger, Battery, Temperature
|
||
DC.B 0 ; [$6A] Read low power warning and cutoff levels
|
||
DC.B 0 ; [$6B] Read Extended Battery Status
|
||
DC.B 0 ; [$6C] Read Battery ID
|
||
DC.B 0 ; [$6D] Battery Parameters
|
||
DC.B -1 ; [$6E] -
|
||
DC.B -1 ; [$6F] -
|
||
|
||
DC.B 1 ; [$70] Set One-Second Interrupt
|
||
DC.B 1 ; [$71] Modem Interrupt Control
|
||
DC.B 1 ; [$72] Set Modem Interrupt
|
||
DC.B -1 ; [$73] -
|
||
DC.B -1 ; [$74] -
|
||
DC.B -1 ; [$75] -
|
||
DC.B -1 ; [$76] -
|
||
DC.B -1 ; [$77] -
|
||
DC.B 0 ; [$78] Read Interrupt Flag Register.
|
||
DC.B 0 ; [$79] Read Modem Interrupt Data
|
||
DC.B -1 ; [$7A] -
|
||
DC.B -1 ; [$7B] -
|
||
DC.B -1 ; [$7C] -
|
||
DC.B -1 ; [$7D] -
|
||
DC.B 4 ; [$7E] Enter Shutdown Mode
|
||
DC.B 4 ; [$7F] Enter Sleep Mode
|
||
|
||
DC.B 4 ; [$80] Set Wakeup Timer
|
||
DC.B -1 ; [$81] -
|
||
DC.B 0 ; [$82] Disable Wakeup Timer
|
||
DC.B -1 ; [$83] -
|
||
DC.B -1 ; [$84] -
|
||
DC.B -1 ; [$85] -
|
||
DC.B -1 ; [$86] -
|
||
DC.B -1 ; [$87] -
|
||
DC.B 0 ; [$88] Read Wakeup Timer
|
||
DC.B -1 ; [$89] -
|
||
DC.B -1 ; [$8A] -
|
||
DC.B -1 ; [$8B] -
|
||
DC.B -1 ; [$8C] -
|
||
DC.B -1 ; [$8D] -
|
||
DC.B -1 ; [$8E] -
|
||
DC.B -1 ; [$8F] -
|
||
|
||
DC.B 1 ; [$90] Set Sound Control Bits
|
||
DC.B 2 ; [$91] Set DFAC Control Register
|
||
DC.B -1 ; [$92] -
|
||
DC.B -1 ; [$93] -
|
||
DC.B -1 ; [$94] -
|
||
DC.B -1 ; [$95] -
|
||
DC.B -1 ; [$96] -
|
||
DC.B -1 ; [$97] -
|
||
DC.B 0 ; [$98] Read Sound Control Status
|
||
DC.B 0 ; [$99] Read DFAC Control Register
|
||
DC.B -1 ; [$9A] -
|
||
DC.B -1 ; [$9B] -
|
||
DC.B -1 ; [$9C] -
|
||
DC.B -1 ; [$9D] -
|
||
DC.B -1 ; [$9E] -
|
||
DC.B -1 ; [$9F] -
|
||
|
||
DC.B 2 ; [$A0] Write Modem Register
|
||
DC.B 2 ; [$A1] Clear Modem Register Bits
|
||
DC.B 2 ; [$A2] Set Modem Register Bits
|
||
DC.B 4 ; [$A3] Write DSP RAM
|
||
DC.B -1 ; [$A4] Set Filter Coefficients
|
||
DC.B 0 ; [$A5] Reset Modem
|
||
DC.B -1 ; [$A6] -
|
||
DC.B -1 ; [$A7] -
|
||
DC.B 1 ; [$A8] Read Modem Register
|
||
DC.B 1 ; [$A9] Send Break
|
||
DC.B 3 ; [$AA] Dial Digit
|
||
DC.B 2 ; [$AB] Read DSP RAM
|
||
DC.B -1 ; [$AC] -
|
||
DC.B -1 ; [$AD] -
|
||
DC.B -1 ; [$AE] -
|
||
DC.B -1 ; [$AF] -
|
||
|
||
DC.B -1 ; [$B0] -
|
||
DC.B -1 ; [$B1] -
|
||
DC.B -1 ; [$B2] -
|
||
DC.B -1 ; [$B3] -
|
||
DC.B -1 ; [$B4] -
|
||
DC.B -1 ; [$B5] -
|
||
DC.B -1 ; [$B6] -
|
||
DC.B -1 ; [$B7] -
|
||
DC.B -1 ; [$B8] -
|
||
DC.B -1 ; [$B9] -
|
||
DC.B -1 ; [$BA] -
|
||
DC.B -1 ; [$BB] -
|
||
DC.B -1 ; [$BC] -
|
||
DC.B -1 ; [$BD] -
|
||
DC.B -1 ; [$BE] -
|
||
DC.B -1 ; [$BF] -
|
||
|
||
DC.B -1 ; [$C0] -
|
||
DC.B -1 ; [$C1] -
|
||
DC.B -1 ; [$C2] -
|
||
DC.B -1 ; [$C3] -
|
||
DC.B -1 ; [$C4] -
|
||
DC.B -1 ; [$C5] -
|
||
DC.B -1 ; [$C6] -
|
||
DC.B -1 ; [$C7] -
|
||
DC.B -1 ; [$C8] -
|
||
DC.B -1 ; [$C9] -
|
||
DC.B -1 ; [$CA] -
|
||
DC.B -1 ; [$CB] -
|
||
DC.B -1 ; [$CC] -
|
||
DC.B -1 ; [$CD] -
|
||
DC.B -1 ; [$CE] -
|
||
DC.B -1 ; [$CF] -
|
||
|
||
DC.B 0 ; [$D0] Reset CPU
|
||
DC.B -1 ; [$D1] -
|
||
DC.B -1 ; [$D2] -
|
||
DC.B -1 ; [$D3] -
|
||
DC.B -1 ; [$D4] -
|
||
DC.B -1 ; [$D5] -
|
||
DC.B -1 ; [$D6] -
|
||
DC.B -1 ; [$D7] -
|
||
DC.B 1 ; [$D8] Read A/D Status
|
||
DC.B 1 ; [$D9] Read User Input
|
||
DC.B -1 ; [$DA] -
|
||
DC.B -1 ; [$DB] -
|
||
DC.B 0 ; [$DC] read external switches
|
||
DC.B 0 ; [$DD] -
|
||
DC.B -1 ; [$DE] -
|
||
DC.B -1 ; [$DF] -
|
||
|
||
DC.B -1 ; [$E0] Write to internal PMGR memory
|
||
DC.B 4 ; [$E1] Download Flash EEPROM Code
|
||
DC.B 0 ; [$E2] Get Flash EEPROM Status
|
||
DC.B -1 ; [$E3] -
|
||
DC.B -1 ; [$E4] -
|
||
DC.B -1 ; [$E5] -
|
||
DC.B -1 ; [$E6] -
|
||
DC.B -1 ; [$E7] -
|
||
DC.B 3 ; [$E8] Read PMGR internal memory
|
||
DC.B -1 ; [$E9] -
|
||
DC.B 0 ; [$EA] Read PMGR firmware version number
|
||
DC.B -1 ; [$EB] -
|
||
DC.B 0 ; [$EC] Execute self test
|
||
DC.B -1 ; [$ED] PMGR diagnostics (selector-based)
|
||
DC.B -1 ; [$EE] -
|
||
DC.B 0 ; [$EF] PMGR soft reset
|
||
|
||
DC.B -1 ; [$F0] -
|
||
DC.B -1 ; [$F1] -
|
||
DC.B -1 ; [$F2] -
|
||
DC.B -1 ; [$F3] -
|
||
DC.B -1 ; [$F4] -
|
||
DC.B -1 ; [$F5] -
|
||
DC.B -1 ; [$F6] -
|
||
DC.B -1 ; [$F7] -
|
||
DC.B -1 ; [$F8] -
|
||
DC.B -1 ; [$F9] -
|
||
DC.B -1 ; [$FA] -
|
||
DC.B -1 ; [$FB] -
|
||
DC.B -1 ; [$FC] -
|
||
DC.B -1 ; [$FD] -
|
||
DC.B -1 ; [$FE] -
|
||
DC.B -1 ; [$FF] -
|
||
|
||
|
||
; This table is used to determine how the 680x0 needs to handle the reply:
|
||
;
|
||
; =0: no reply should be expected.
|
||
; =1: only a reply byte will be sent (this is a special case for a couple of commands)
|
||
; <0: a reply is expected and the PMGR will send a count byte.
|
||
; >1: a reply is expected and the PMGR will not send a count byte,
|
||
; but the count will be (value-1).
|
||
;
|
||
; Unused commands in the range $x8 to $xF will be marked as expecting a reply (with count)
|
||
; so that commands may be added without having to change the ROM.
|
||
|
||
replyCounts DC.B 0 ; [$00] -
|
||
DC.B 0 ; [$01] -
|
||
DC.B 0 ; [$02] -
|
||
DC.B 0 ; [$03] -
|
||
DC.B 0 ; [$04] -
|
||
DC.B 0 ; [$05] -
|
||
DC.B 0 ; [$06] -
|
||
DC.B 0 ; [$07] -
|
||
DC.B -1 ; [$08] -
|
||
DC.B -1 ; [$09] -
|
||
DC.B -1 ; [$0A] -
|
||
DC.B -1 ; [$0B] -
|
||
DC.B -1 ; [$0C] -
|
||
DC.B -1 ; [$0D] -
|
||
DC.B -1 ; [$0E] -
|
||
DC.B -1 ; [$0F] -
|
||
|
||
DC.B 0 ; [$10] Subsystem Power/Clock Control
|
||
DC.B 0 ; [$11] Subsystem Power/Clock Control (yet more)
|
||
DC.B 0 ; [$12] -
|
||
DC.B 0 ; [$13] -
|
||
DC.B 0 ; [$14] -
|
||
DC.B 0 ; [$15] -
|
||
DC.B 0 ; [$16] -
|
||
DC.B 0 ; [$17] -
|
||
DC.B 1+1 ; [$18] Read Power/Clock Status
|
||
DC.B 1+1 ; [$19] Read Power/Clock Status (yet more)
|
||
DC.B -1 ; [$1A] -
|
||
DC.B -1 ; [$1B] -
|
||
DC.B -1 ; [$1C] -
|
||
DC.B -1 ; [$1D] -
|
||
DC.B -1 ; [$1E] -
|
||
DC.B 0 ; [$1F] RESERVED FOR MSC/PG&E EMULATION
|
||
|
||
DC.B 0 ; [$20] Set New Apple Desktop Bus Command
|
||
DC.B 0 ; [$21] ADB Autopoll Abort
|
||
DC.B 0 ; [$22] ADB Set Keyboard Addresses
|
||
DC.B 0 ; [$23] ADB Set Hang Threshold
|
||
DC.B 0 ; [$24] ADB Enable/Disable Programmers Key
|
||
DC.B 0 ; [$25] -
|
||
DC.B 0 ; [$26] -
|
||
DC.B 0 ; [$27] -
|
||
DC.B -1 ; [$28] ADB Transaction Read
|
||
DC.B -1 ; [$29] -
|
||
DC.B -1 ; [$2A] -
|
||
DC.B -1 ; [$2B] -
|
||
DC.B -1 ; [$2C] -
|
||
DC.B -1 ; [$2D] -
|
||
DC.B -1 ; [$2E] -
|
||
DC.B -1 ; [$2F] -
|
||
|
||
DC.B 0 ; [$30] Set Realtime Clock.
|
||
DC.B 0 ; [$31] Write Parameter RAM
|
||
DC.B 0 ; [$32] Write Extended Parameter RAM.
|
||
DC.B 0 ; [$33] -
|
||
DC.B 0 ; [$34] -
|
||
DC.B 0 ; [$35] -
|
||
DC.B 0 ; [$36] -
|
||
DC.B 0 ; [$37] -
|
||
DC.B 4+1 ; [$38] Read Realtime Clock.
|
||
DC.B 20+1 ; [$39] Read Parameter RAM
|
||
DC.B -1 ; [$3A] Read Extended Parameter RAM.
|
||
DC.B -1 ; [$3B] -
|
||
DC.B -1 ; [$3C] -
|
||
DC.B -1 ; [$3D] -
|
||
DC.B -1 ; [$3E] -
|
||
DC.B -1 ; [$3F] -
|
||
|
||
DC.B 0 ; [$40] Set Screen Contrast
|
||
DC.B 0 ; [$41] Set Screen Brightness <H4>
|
||
DC.B 0 ; [$42] -
|
||
DC.B 0 ; [$43] -
|
||
DC.B 0 ; [$44] -
|
||
DC.B 0 ; [$45] -
|
||
DC.B 0 ; [$46] -
|
||
DC.B 0 ; [$47] -
|
||
DC.B 1+1 ; [$48] Read Screen Contrast
|
||
DC.B 1+1 ; [$49] Read Screen Brightness
|
||
DC.B -1 ; [$4A] -
|
||
DC.B -1 ; [$4B] -
|
||
DC.B -1 ; [$4C] -
|
||
DC.B -1 ; [$4D] -
|
||
DC.B -1 ; [$4E] -
|
||
DC.B -1 ; [$4F] -
|
||
|
||
DC.B 0 ; [$50] Set Internal Modem Control Bits
|
||
DC.B 0 ; [$51] Clear FIFOs
|
||
DC.B 0 ; [$52] Set FIFO Interrupt Marks
|
||
DC.B 0 ; [$53] Set FIFO Sizes
|
||
DC.B 0 ; [$54] Write Data to Modem
|
||
DC.B 0 ; [$55] Set Data Mode
|
||
DC.B 0 ; [$56] Set Flow Control Mode
|
||
DC.B 0 ; [$57] Set DAA control lines <H54>
|
||
DC.B 1+1 ; [$58] Read Internal Modem Status
|
||
DC.B 0 ; [$59] Get DAA Identification <H55>
|
||
DC.B 2+1 ; [$5A] Get FIFO Counts
|
||
DC.B 2+1 ; [$5B] Get Maximum FIFO Sizes
|
||
DC.B -1 ; [$5C] Read Data From Modem
|
||
DC.B -1 ; [$5D] General Purpose modem command (modem dependent) <H58>
|
||
DC.B -1 ; [$5E] -
|
||
DC.B -1 ; [$5F] -
|
||
|
||
DC.B 0 ; [$60] Set low power warning and cutoff levels
|
||
DC.B 0 ; [$61] -
|
||
DC.B 0 ; [$62] -
|
||
DC.B 0 ; [$63] -
|
||
DC.B 0 ; [$64] -
|
||
DC.B 0 ; [$65] -
|
||
DC.B 0 ; [$66] -
|
||
DC.B 0 ; [$67] -
|
||
DC.B 3+1 ; [$68] Read Charger State, Battery Voltage, Temperature
|
||
DC.B 3+1 ; [$69] Read Instantaneous Charger, Battery, Temperature
|
||
DC.B 2+1 ; [$6A] Read low power warning and cutoff levels
|
||
DC.B 8+1 ; [$6B] Read Extended Battery Status
|
||
DC.B -1 ; [$6C] Read Battery ID
|
||
DC.B -1 ;10+1 ; [$6D] Battery Parameters
|
||
DC.B -1 ; [$6E] -
|
||
DC.B -1 ; [$6F] -
|
||
|
||
DC.B 0 ; [$70] Set One-Second Interrupt
|
||
DC.B 0 ; [$71] Modem Interrupt Control
|
||
DC.B 0 ; [$72] Set Modem Interrupt
|
||
DC.B 0 ; [$73] -
|
||
DC.B 0 ; [$74] -
|
||
DC.B 0 ; [$75] -
|
||
DC.B 0 ; [$76] -
|
||
DC.B 0 ; [$77] -
|
||
DC.B -1 ; [$78] Read Interrupt Flag Register.
|
||
DC.B -1 ; [$79] Read Modem Interrupt Data
|
||
DC.B -1 ; [$7A] -
|
||
DC.B -1 ; [$7B] -
|
||
DC.B -1 ; [$7C] -
|
||
DC.B -1 ; [$7D] -
|
||
DC.B 0+1 ; [$7E] Enter Shutdown Mode
|
||
DC.B 0+1 ; [$7F] Enter Sleep Mode
|
||
|
||
DC.B 0 ; [$80] Set Wakeup Timer
|
||
DC.B 0 ; [$81] -
|
||
DC.B 0 ; [$82] Disable Wakeup Timer
|
||
DC.B 0 ; [$83] -
|
||
DC.B 0 ; [$84] -
|
||
DC.B 0 ; [$85] -
|
||
DC.B 0 ; [$86] -
|
||
DC.B 0 ; [$87] -
|
||
DC.B 5+1 ; [$88] Read Wakeup Timer
|
||
DC.B -1 ; [$89] -
|
||
DC.B -1 ; [$8A] -
|
||
DC.B -1 ; [$8B] -
|
||
DC.B -1 ; [$8C] -
|
||
DC.B -1 ; [$8D] -
|
||
DC.B -1 ; [$8E] -
|
||
DC.B -1 ; [$8F] -
|
||
|
||
DC.B 0 ; [$90] Set Sound Control Bits
|
||
DC.B 0 ; [$91] Set DFAC Control Register
|
||
DC.B 0 ; [$92] -
|
||
DC.B 0 ; [$93] -
|
||
DC.B 0 ; [$94] -
|
||
DC.B 0 ; [$95] -
|
||
DC.B 0 ; [$96] -
|
||
DC.B 0 ; [$97] -
|
||
DC.B 1+1 ; [$98] Read Sound Control Status
|
||
DC.B 1+1 ; [$99] Read DFAC Control Register
|
||
DC.B -1 ; [$9A] -
|
||
DC.B -1 ; [$9B] -
|
||
DC.B -1 ; [$9C] -
|
||
DC.B -1 ; [$9D] -
|
||
DC.B -1 ; [$9E] -
|
||
DC.B -1 ; [$9F] -
|
||
|
||
DC.B 0 ; [$A0] Write Modem Register
|
||
DC.B 0 ; [$A1] Clear Modem Register Bits
|
||
DC.B 0 ; [$A2] Set Modem Register Bits
|
||
DC.B 0 ; [$A3] Write DSP RAM
|
||
DC.B 0 ; [$A4] Set Filter Coefficients
|
||
DC.B 0 ; [$A5] Reset Modem
|
||
DC.B 0 ; [$A6] -
|
||
DC.B 0 ; [$A7] -
|
||
DC.B 1+1 ; [$A8] Read Modem Register
|
||
DC.B 0 ; [$A9] Send Break
|
||
DC.B 0 ; [$AA] Dial Digit
|
||
DC.B 0 ; [$AB] Read DSP RAM
|
||
DC.B -1 ; [$AC] -
|
||
DC.B -1 ; [$AD] -
|
||
DC.B -1 ; [$AE] -
|
||
DC.B -1 ; [$AF] -
|
||
|
||
DC.B 0 ; [$B0] -
|
||
DC.B 0 ; [$B1] -
|
||
DC.B 0 ; [$B2] -
|
||
DC.B 0 ; [$B3] -
|
||
DC.B 0 ; [$B4] -
|
||
DC.B 0 ; [$B5] -
|
||
DC.B 0 ; [$B6] -
|
||
DC.B 0 ; [$B7] -
|
||
DC.B -1 ; [$B8] -
|
||
DC.B -1 ; [$B9] -
|
||
DC.B -1 ; [$BA] -
|
||
DC.B -1 ; [$BB] -
|
||
DC.B -1 ; [$BC] -
|
||
DC.B -1 ; [$BD] -
|
||
DC.B -1 ; [$BE] -
|
||
DC.B -1 ; [$BF] -
|
||
|
||
DC.B 0 ; [$C0] -
|
||
DC.B 0 ; [$C1] -
|
||
DC.B 0 ; [$C2] -
|
||
DC.B 0 ; [$C3] -
|
||
DC.B 0 ; [$C4] -
|
||
DC.B 0 ; [$C5] -
|
||
DC.B 0 ; [$C6] -
|
||
DC.B 0 ; [$C7] -
|
||
DC.B -1 ; [$C8] -
|
||
DC.B -1 ; [$C9] -
|
||
DC.B -1 ; [$CA] -
|
||
DC.B -1 ; [$CB] -
|
||
DC.B -1 ; [$CC] -
|
||
DC.B -1 ; [$CD] -
|
||
DC.B -1 ; [$CE] -
|
||
DC.B -1 ; [$CF] -
|
||
|
||
DC.B 0 ; [$D0] Reset CPU
|
||
DC.B 0 ; [$D1] -
|
||
DC.B 0 ; [$D2] -
|
||
DC.B 0 ; [$D3] -
|
||
DC.B 0 ; [$D4] -
|
||
DC.B 0 ; [$D5] -
|
||
DC.B 0 ; [$D6] -
|
||
DC.B 0 ; [$D7] -
|
||
DC.B 1+1 ; [$D8] Read A/D Status
|
||
DC.B 1+1 ; [$D9] Read User Input
|
||
DC.B -1 ; [$DA] -
|
||
DC.B -1 ; [$DB] -
|
||
DC.B 1+1 ; [$DC] read external switches
|
||
DC.B -1 ; [$DD] -
|
||
DC.B -1 ; [$DE] -
|
||
DC.B -1 ; [$DF] -
|
||
|
||
DC.B 0 ; [$E0] Write to internal PMGR memory
|
||
DC.B 0 ; [$E1] Download Flash EEPROM Code
|
||
DC.B 0+1 ; [$E2] Get Flash EEPROM Status
|
||
DC.B 0 ; [$E3] -
|
||
DC.B 0 ; [$E4] -
|
||
DC.B 0 ; [$E5] -
|
||
DC.B 0 ; [$E6] -
|
||
DC.B 0 ; [$E7] -
|
||
DC.B -1 ; [$E8] Read PMGR internal memory
|
||
DC.B -1 ; [$E9] -
|
||
DC.B 1+1 ; [$EA] Read PMGR firmware version number
|
||
DC.B -1 ; [$EB] -
|
||
DC.B -1 ; [$EC] Execute self test
|
||
DC.B -1 ; [$ED] PMGR diagnostics (selector-based)
|
||
DC.B -1 ; [$EE] -
|
||
DC.B 0 ; [$EF] PMGR soft reset
|
||
|
||
DC.B 0 ; [$F0] -
|
||
DC.B 0 ; [$F1] -
|
||
DC.B 0 ; [$F2] -
|
||
DC.B 0 ; [$F3] -
|
||
DC.B 0 ; [$F4] -
|
||
DC.B 0 ; [$F5] -
|
||
DC.B 0 ; [$F6] -
|
||
DC.B 0 ; [$F7] -
|
||
DC.B -1 ; [$F8] -
|
||
DC.B -1 ; [$F9] -
|
||
DC.B -1 ; [$FA] -
|
||
DC.B -1 ; [$FB] -
|
||
DC.B -1 ; [$FC] -
|
||
DC.B -1 ; [$FD] -
|
||
DC.B -1 ; [$FE] -
|
||
DC.B -1 ; [$FF] -
|
||
|
||
;________________________________________________________________________________________ <K11>
|
||
;
|
||
; _CommsPower - Communications' port power control
|
||
; _SerialPower ($A685) - Serial port power control
|
||
;
|
||
; Enter with: D0 = bit pattern
|
||
; BIT INDICATION
|
||
; 0 1 = ignore internal modem
|
||
; 1 not used
|
||
; 2-6 0000 = Do something to port B serial
|
||
; 0001 = Do something to port A serial/modem
|
||
; 0010 = Do something to port C modem
|
||
; 0011 = Do something to Ethernet Port
|
||
; 0100 thru 1111 are not used (yet)
|
||
; 7 1 = power port OFF
|
||
; 0 = power port ON
|
||
; Enter with: D1 - trap word
|
||
;
|
||
; Implementation:
|
||
; The SerialPower (now also CommsPower) code now resides in the CommsPowerTables of the
|
||
; Power Manager Primitives.
|
||
;
|
||
; History:
|
||
; The TIM internal (serial) modem is multiplexed thru port A. So bit 0 controls
|
||
; the use of the internal modem. When port C was created (for Dart), the used of it
|
||
; was backpatched to TIM. Now if you power ON port A and a serial modem is installed,
|
||
; as in TIM, the 'power A ON' code calls 'power C ON', which turns the modem on.
|
||
;
|
||
; On Dart, the internal modem is not multiplexed thru serial port A. To Power on the
|
||
; modem, call 'power C ON' directly.
|
||
;
|
||
; On Blackbird, the internal modem is not multiplexed thru serial port A. To Power on the
|
||
; modem, call 'power C ON' directly. Onboard Ethernet is treated like another port; Call
|
||
; 'Power Enet ON' directly.
|
||
;
|
||
; To power the SONIC LP:
|
||
; Turn on power to the SONIC (assert Whitney signal ENET_RESET_L)
|
||
; Wait for crystal to stabilize (50 ms, a LONG time)
|
||
; Deassert SLEEP line (deassert Whitney signal ENET_RESET_L)
|
||
;
|
||
; -------------------
|
||
; For Posterity, the TIM Algorithm:
|
||
; Determine what needs to be powered on for the SCC port that is being opened. There
|
||
; are two SCC ports (A/B) which may be connected to the external ports (the modem and
|
||
; printer ports), or the internal modem (for port B only).
|
||
;
|
||
; The following is a summary of the devices and which power manager commands to use
|
||
; to control them.
|
||
;
|
||
; device Pmgr cmd port0 bit signal name
|
||
; ----- --------- ------- -----------
|
||
; SCC powerCntl P01/sccOn *SCC_CNTL
|
||
; external port powerCntl P04/serOn *SERIAL_POWER
|
||
; internal modem powerCntl P03/ModemOn MODEM_PWR
|
||
; modemSet P06 *MODEM_PWROUT
|
||
;
|
||
; Additionally for the internal modem, MODEM_RESET (a Orca/via2 signal) must be
|
||
; manipulated by changing it from an input to and output to de-assert reset.
|
||
;
|
||
; Powering on the SCC and the external ports only involves sending the correct power
|
||
; manager commands. Powering on the internal modem involves some timing delays and a
|
||
; specific sequence of commands.
|
||
;
|
||
; To power the SCC and external ports:
|
||
; turn on SCC
|
||
; turn on external line drivers
|
||
;
|
||
; To power the internal modem:
|
||
; make MODEM_RESET an input (to assert reset) - signal will float up
|
||
; turn on +5V and -5V to modem (MODEM_PWROUT)
|
||
; wait >2ms to allow +5V and -5V to settle
|
||
; enable the modem (*MODEM_PWR)
|
||
; turn on SCC
|
||
; wait >5ms to allow reset time
|
||
; make MODEM_RESET an output
|
||
; write a zero to MODEM_RESET to de-assert reset - drive it low
|
||
;
|
||
;________________________________________________________________________________________
|
||
CommsPower
|
||
SerialPower
|
||
with PrimInfoTbleRec,PmgrRec,PmgrPramRec,PmgrPrimitivesRec,ModemTblRec,CommsPwrTblRec
|
||
@workregs REG d1-d2/a0 ; <K19>
|
||
movem.l @workregs,-(sp) ; save our regs <K19>
|
||
|
||
move.l PMgrBase, a0 ; point to Power Manager globals <K14>
|
||
LoadTbl PmgrCommTblPtr,a0,a0 ; get pointer to Comms Power primitive table <K14>
|
||
beq @OutOfRange ; sorry no table
|
||
|
||
clr.l d1 ; clear work register
|
||
move.w d0,d1 ; get a copy of d0 to work on
|
||
asr.w #2,d1 ; right justify selector field
|
||
andi.w #$1f,d1 ; mask only selector field
|
||
|
||
move.l CommsPwrCount(a0), d2 ; length of table
|
||
asr.l #2, d2 ; number of entries in table
|
||
asr.l #1, d2 ; half as many valid selectors as entries
|
||
cmp.l d2, d1 ; are we in range?
|
||
bhs.s @OutOfRange ; no, so punt
|
||
|
||
btst #7,d0 ; is it on or off
|
||
beq.s @on ; on, so look at first half of table
|
||
|
||
add.l d2, d1 ; off, so look at second half of table
|
||
@on
|
||
tst.l ([a0, d1.l*4]) ; is there a routine?
|
||
beq.s @done ; zero offset means no rtn
|
||
jsr ([a0, d1.l*4]) ; go execute routine <K19>
|
||
moveq #noErr, d0 ; everything just dandy <K19>
|
||
bra.s @done ; <K19>
|
||
|
||
@OutOfRange
|
||
MOVE.W #paramErr,D0 ; Abort and return error
|
||
@done movem.l (sp)+,@workregs ; restore our regs <K19>
|
||
RTS
|
||
|
||
|
||
;——————————————————————————————————————————————————————————————————————————————————————— <t28> djw
|
||
; Modem Sound Interrupt Handlers
|
||
;
|
||
; Modem sound on Tim is implemented through DFAC's aux channel. The modem demands
|
||
; and releases the sound path through the MODEM_SND_ENABLE signal (on VIA1 CB2). The
|
||
; system monitors that bit to determine whether it should enable or disable the modem
|
||
; sound path.
|
||
;
|
||
; When the modem is powered, a CB2 interrupt handler is installed. When the modem
|
||
; demands sound, we immediately enable the sound path. The interrupt handler then
|
||
; re-configures the VIA CB2 interrupt to trigger on the falling edge. A new interrupt
|
||
; handler is installed which disables the sound path. The interrupt handlers ping-pongs
|
||
; back a
|
||
;
|
||
; Input: none
|
||
; Output: none
|
||
;
|
||
|
||
ModemSndOnInt
|
||
move.b #(1<<ifCB2),([VIA],vIFR) ; clear interrupt flag reg
|
||
move.b SDVolume,d0 ; get current volume <H37>
|
||
jsrTBL sndPlayThruVol ; set volume for playthrough <H37>
|
||
moveq.l #sndAuxiliary,d0 ; <H37>
|
||
jsrTbl sndInputSelect ; select aux source <H37>
|
||
|
||
bclr.b #6,([VIA],vPCR) ; change from pos to neg edge int
|
||
lea ModemSndOffInt,a0 ; disable sound routine
|
||
move.l a0,jModemSnd ; install in Level 1 VIA1 dispatch table
|
||
|
||
rts
|
||
|
||
;——————————————————————————————————————————————————————————————————————————————————————— <H59>
|
||
; Modem Sound Interrupt Handlers |
|
||
; V
|
||
; Modem sound on Tim is implemented through DFAC's aux channel. The modem demands
|
||
; and releases the sound path through the MODEM_SND_ENABLE signal (on VIA1 CB2). The
|
||
; system monitors that bit to determine whether it should enable or disable the modem
|
||
; sound path.
|
||
;
|
||
; When the modem is powered, a CB2 interrupt handler is installed. When the modem
|
||
; demands sound, we immediately enable the sound path. The interrupt handler then
|
||
; re-configures the VIA CB2 interrupt to trigger on the falling edge. A new interrupt
|
||
; handler is installed which disables the sound path. The interrupt handlers ping-pongs
|
||
; back a
|
||
;
|
||
; Input: none
|
||
; Output: none
|
||
;
|
||
ModemSndOffInt
|
||
move.b #(1<<ifCB2),([VIA],vIFR) ; clear interrupt flag reg
|
||
moveq.l #0,d0 ; disable playthrough
|
||
jsrTBL sndPlayThruVol ;
|
||
moveq.l #sndInputOff,d0
|
||
jsrTbl sndInputSelect ; disable aux source
|
||
|
||
bset.b #6,([VIA],vPCR) ; change from neg to pos edge int
|
||
lea ModemSndOnInt,a0 ; enable sound routine
|
||
move.l a0,jModemSnd ; install in Level 1 VIA1 dis≈ table
|
||
|
||
rts
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; IdleState ($A485) - Increments/decrements the idle enable flag count and returns
|
||
; the current speed.
|
||
;
|
||
; Enter with: D0 < 0, read speed
|
||
; Exit with: D0 = current speed
|
||
;
|
||
; Enter with: D0 = 0, enable idle
|
||
; Exit with: D0 = idle disable count
|
||
;
|
||
; Enter with: D0 > 0, disable idle
|
||
; Exit with: D0 = idle disable count
|
||
;________________________________________________________________________________________
|
||
IdleState
|
||
TST.L D0 ; What selector do we have
|
||
BGT IdleDisable ; D0 > 0
|
||
BEQ IdleEnable ; D0 = 0
|
||
BMI IdleRead ; D0 < 0
|
||
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; GoToSleep, WakeUp, SleepQInstall, SleepQRemove
|
||
;
|
||
; Enter : D1 = trap word
|
||
; D0 = Sleep type
|
||
;
|
||
; Exit : All regs unchanged
|
||
;
|
||
; SlpQInstall adds a sleep queue entry into the sleep queue.
|
||
;
|
||
; SlpQRemove deletes a sleep queue entry from the sleep queue.
|
||
;
|
||
; GoToSleep is called by the event manager when it determines that
|
||
; there is no work being done. Drivers are called to save their state,
|
||
; then the PMGR is ordered to put the system to sleep. When a waking
|
||
; event occurs, the PMGR powers up the system. The reset code jumps to
|
||
; WakeUp if the sleep flag is set. WakeUp restores the system hardware
|
||
; state, reloads the 68000 regs, and returns to the calling routine.
|
||
;________________________________________________________________________________________
|
||
|
||
GoToSleep BTST #9,D1 ; $A28A
|
||
BNE SlpQInstall
|
||
BTST #10,D1 ; $A48A
|
||
BNE SlpQRemove
|
||
*** BRA @Sleep ; $A08A
|
||
@Sleep
|
||
MOVE.L PMgrBase,A0 ; Get Power Manager Base Pointer
|
||
BSET #InSleep,PmgrFlags(A0) ; test and set sleep semaphore
|
||
BNE.S @Exit ; if in sleep, exit! don't re-enter
|
||
|
||
MOVE.L D0,D1 ; Save the sleep type
|
||
BSR.W SetSupervisorMode ; Set the machine to supervisor mode
|
||
MOVE.W D0,SaveCPUState.\
|
||
CPUSRsave(A0) ; Save the store away the status register
|
||
MOVE.W D0,PwrCycSave.\
|
||
PCRSRsave(A0) ; Save this stupid value for historical purposes
|
||
MOVE.L D1,D0 ; restore the sleep type
|
||
BSR.S TakeASnooze ; Take a snooze
|
||
MOVE.W SaveCPUState.\
|
||
CPUSRsave(A0),SR ; Restore the Status Register to the proper world
|
||
@Exit
|
||
RTS
|
||
|
||
;________________________________________________________________________________________
|
||
;________________________________________________________________________________________
|
||
|
||
TakeASnooze
|
||
SleepRegs REG A0-A6/D1-D7
|
||
MOVEM.L SleepRegs,-(SP) ; Save registers
|
||
MOVE.L D0,D2 ; Save a sleep type in D2
|
||
|
||
@checkinprogress
|
||
BTST #dockNoSleep,\
|
||
dockFlags(A0) ; is sleeping allowed (if we're connected to a bar)
|
||
BEQ.S @checkAuto ; -> yes, onward!
|
||
BSR.L DockingSleepDenied ; have the Docking Manager put up a notification
|
||
BRA AbortSleep ; then abort!
|
||
|
||
@checkAuto CMP.B #SleepRequest,D0 ; auto sleep request
|
||
BEQ.S @validselector
|
||
|
||
@checkDnd CMP.B #SleepDemand,D0 ; User sleep, from finder or command key
|
||
BEQ.S @validselector
|
||
|
||
@checkNow CMP.B #SleepNow,D0 ; Critical low power sleep
|
||
BNE AbortSleep
|
||
|
||
@validselector
|
||
MOVE.W SaveCPUState.\
|
||
CPUSRsave(A0),SR ; Restore the SR so that when VM is on the queue is run in User Mode
|
||
|
||
BCLR #AvoidNetDiag,\
|
||
PmgrFlags(A0) ; tst/clear the avoid bit
|
||
BNE.S @traverse ; if bit was set, skip dialog
|
||
|
||
MOVE.L SleepNetHook(A0),D1 ; IF SleepNetHook present THEN
|
||
BEQ.S @nextHook ;
|
||
MOVEA.L D1,A1 ; Get pointer
|
||
JSR (A1) ; Call Hook
|
||
BNE AbortSleep ; IF Bad Close THEN exit
|
||
@nextHook ; ELSE
|
||
MOVE.L SleepHook(A0),D1 ; IF SleepNetHook present THEN
|
||
BEQ.S @closeAT ;
|
||
MOVEA.L D1,A1 ; Get pointer
|
||
JSR (A1) ; Call Hook
|
||
@closeAT ; ENDIF
|
||
BSR.W CheckAppleTalk ; Close AppleTalk
|
||
BNE AbortSleep ; Branch if close denied
|
||
|
||
@traverse MOVE.W D2,D0 ; Restore D0
|
||
CMP.W #SleepNow,D0 ; If passing sleepnow to sleepq then change it
|
||
BNE.S @doQ ; to a sleep demand
|
||
MOVEQ #SleepDemand,D0 ; sleepNow -> sleepDemand
|
||
|
||
@doQ BSR.W DoQueueStack ; Walk the queue
|
||
MOVE.L D0,D1 ; Save a copy of DoQueueStack result
|
||
BSR.W SetSupervisorMode ; Return to supervisor mode so that we may continue
|
||
TST.L D1 ; DoQueueStack == Ok to goto sleep ?
|
||
BNE.W AbortSleep ; Nope. Get out!
|
||
BSR.W CloseAppleTalk ; Else shut down atalk
|
||
BCLR #InSleep,PmgrFlags(A0) ; clr the sleep indicator
|
||
|
||
BCLR #PmgrShutdownEnb,\
|
||
PmgrFlags1(A0) ; disable shutdown across sleep
|
||
|
||
MOVEA.L A0,A2 ; A2 = Power Manager Vars
|
||
BSR.W SaveSetCrsr ; Save and Set cursor to a watch cursor
|
||
|
||
; run thru the table of machine-specific operations to perform for going to sleep...
|
||
ORI.W #HiIntMask,SR ; Disable interrupts
|
||
BackToSleep
|
||
LoadTbl SleepTblPtr,A2,A0 ; get pointer to the SleepTable
|
||
LEA @Resume,A1 ; set up return address in A1
|
||
BRA.S @Resume ; WHILE tableItem != NIL DO {
|
||
@SaveLoop MOVEA.L D0,A2 ; get address of calling routine
|
||
JMP (A2) ; do the routine
|
||
@Resume MOVE.L (A0)+,D0 ; increment to the next table item
|
||
BNE.S @SaveLoop ; }
|
||
|
||
BRA.S * ; wait for sleep (yawn...)
|
||
|
||
AbortSleep BSR.W SetSupervisorMode ; Set the machine to supervisor mode
|
||
BCLR #InSleep,PmgrFlags(A0) ; Clear the sleep indicator
|
||
MOVE.W D2,D0 ; Restore sleep type to D0
|
||
MOVEM.L (SP)+,SleepRegs
|
||
RTS ; Return to caller
|
||
|
||
;________________________________________________________________________________________
|
||
; WakeUp is reached from the reset (power up) code if the sleep flag is set.
|
||
;
|
||
; Enter : A2 = Pointer to Pmgr Globals
|
||
; Exit : All regs unchanged
|
||
;________________________________________________________________________________________
|
||
WakeUp
|
||
ORI.W #HiIntMask,SR ; no more interrupts
|
||
MOVEA.L PmgrBase,A0 ; make sure that we have pointer to PmgrBase
|
||
LoadTbl WakeTblPtr,A0,A0 ; get pointer to the WakeTable
|
||
LEA @Resume,A1 ; set up return address in A1
|
||
BRA.S @Resume ; WHILE tableItem != NIL DO {
|
||
@RestoreLp MOVEA.L D0,A2 ; get address of calling routine
|
||
JMP (A2) ; do the routine
|
||
@Resume MOVE.L (A0)+,D0 ; increment to the next table item
|
||
BNE.S @RestoreLp ; }
|
||
|
||
MOVEA.L PmgrBase,A2 ; point to the Power Manager globals <H47>
|
||
BTST #dockNoWakeup,\ ; <H47>
|
||
dockFlags(A2) ; can we wakeup with this bar attached? <H47>
|
||
BEQ.S @CanWakeup ; -> yes, continue waking up <H47>
|
||
MOVEM.L (SP),SleepRegs ; restore the registers but don't touch the stack <H47>
|
||
MOVEA.L PmgrBase,A2 ; point to the Power Manager globals again <H47>
|
||
BSR.L DockingWakeupDenied ; setup the notification message <H47>
|
||
BRA BackToSleep ; then go put the machine back to sleep <H47>
|
||
@CanWakeup ; <H47>
|
||
MOVEM.L (SP),SleepRegs ; Restore the registers but don't touch the stack
|
||
|
||
BSR.L SCSIDiskWakeAlert ; check if a disk mode cable is plugged in <H64>
|
||
BSR.L InitSCSIHW ; Init the SCSI chip
|
||
|
||
LEA Time,A0 ; load parameter for ReadDateTime
|
||
_ReadDateTime
|
||
|
||
BSR KbdReset ; clear the keyboard maps
|
||
|
||
MOVEA.L PmgrBase,A2 ; Get Power Manager globals base
|
||
TST.L WakeUpHook(A2) ; Do we have a sleep hook?
|
||
BEQ.S @noHook ; Nope... go on
|
||
MOVE.L WakeUpHook(A2),A0 ; Get the sleep hook
|
||
JSR (A0) ; Go do it...
|
||
@noHook
|
||
MOVE.W SaveCPUState.\
|
||
CPUSRsave(A2),SR ; Restore the SR so that when VM is on the queue is run in User Mode
|
||
_ADBReInit ; Init the ADB devices <H56>
|
||
_ShowCursor ; Alive now tell the user it's OK <H56>
|
||
|
||
BSR.W MPPOpen ; Open the driver since elements in the queue might need some MPP services
|
||
MOVEQ #SleepWakeUp,D0 ; Go through wake queue
|
||
BSR.W DoQueue ; Run through the queue in proper order
|
||
|
||
MOVEA.L PmgrBase,A2 ; Get Power Manager globals base
|
||
BSR.W RemoveMsg
|
||
CLR.B Level4Cnt(A2) ; Clear level 4 count down timer
|
||
MOVE.B #-1,LastLevel(A2) ; Reset battery level <v2.8>
|
||
CLR.L BatQ(A2) ; Clear queue
|
||
CLR.L BatQ+4(A2)
|
||
MOVE.B #8,BatQIndex(A2) ; Reset index
|
||
|
||
BCLR #PmgrShutdownReq,\
|
||
PmgrFlags1(A2) ; clear any shutdown request <H37>
|
||
BSET #PmgrShutdownEnb,\
|
||
PmgrFlags1(A2) ; enable shutdown <H37>
|
||
|
||
BSR.W RestoreScreen ; Restore cursor and screen and back into the world.
|
||
BSR.W SetSupervisorMode ; Return to supervisor mode <H66>
|
||
MOVEM.L (SP)+,SleepRegs ; Now really restore the world
|
||
MOVEQ #0,D0 ; and return a zero result <H69>
|
||
RTS
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; CheckAppleTalk - checks AppleTalk drivers depending on the sleep
|
||
; level, what is open, and what the user OK's.
|
||
;
|
||
;________________________________________________________________________________________
|
||
|
||
STRING PASCAL
|
||
CheckAppleTalk
|
||
MOVEM.L A0-A3/D1-D2,-(SP) ; Try to close AppleTalk and warn user of this <v1.4>
|
||
SUB.W #ioQElSize,SP ; Allocate IO stack frame
|
||
MOVE.L SP,A3 ; Save this place
|
||
|
||
MOVE.L PmgrBase,A2 ;
|
||
MOVEQ #$0F,D1 ; Lower nibble indicates ATalk in use
|
||
AND.B PortBUse,D1
|
||
CMP.B #1,D1
|
||
BNE @okexit ; Do exit if no Atalk
|
||
|
||
MOVE.W D0,D1 ; Case on request, demand, and now sleeps
|
||
CMP.B #SleepRequest,D0 ; Request case
|
||
BNE.S @dmndcase
|
||
|
||
|
||
;________________________________________________________________________________________
|
||
; Request sleep (time out) case. If plugged in or chooser bit set or server mounted then sleep
|
||
; denied, else ok.
|
||
;________________________________________________________________________________________
|
||
|
||
@reqcase BTST #noATChg,ChooserBits ; If magic chooser bit set then no sleep
|
||
BEQ @done
|
||
|
||
BTST #HasCharger,Charger(A2) ; If plugged in then no sleep
|
||
BNE @done
|
||
|
||
BTST #XPPLoadedBit,PortBUse ; Test for XPP in use
|
||
BNE.S @reqcase1 ; Branch if so
|
||
|
||
MOVE.B #ClosedMPP,WakeWarn(A2) ; Set flag for wake up warning (MPP closed)
|
||
BRA @okexit ; Bye now
|
||
|
||
@reqcase1 BSR XPPCheck ; Try to close XPP
|
||
BNE @done ; Branch if not
|
||
|
||
MOVE.B #ClosedXPP,WakeWarn(A2) ; Set flag for wake up warning (XPP closed)
|
||
BRA @okexit
|
||
|
||
;________________________________________________________________________________________
|
||
; Demand sleep (Finder - Battery DA) case. User warned of different conditions and given the choice
|
||
; to sleep or not.
|
||
;________________________________________________________________________________________
|
||
|
||
@dmndcase CMP.B #SleepDemand,D0 ; Demand case
|
||
BNE.S @nowcase
|
||
|
||
BTST #noATChg,ChooserBits ; If no magic chooser bit then branch
|
||
BNE.S @dmndcase1
|
||
|
||
; Magic chooser bit is set so give the user the big bad warning.
|
||
|
||
BSR.W HarshWarn ; Warn user of impending doom
|
||
BNE @done ; No sleep if user is scared off
|
||
|
||
MOVE.B #ClearedChsr,WakeWarn(A2) ; Set flag for wake up warning (magic bit cleared)
|
||
BSET #noATChg,ChooserBits ; Clear magic chooser bit
|
||
BRA @okexit
|
||
|
||
; Only MPP is open so give the user the wimpy warning.
|
||
|
||
@dmndcase1 BTST #XPPLoadedBit,PortBUse ; Test for XPP in use
|
||
BNZ.S @dmndcase2 ; Branch if so
|
||
|
||
BSR.W WimpyWarn ; Warn user of possible problems
|
||
BNE.S @done ; Branch if chickened out
|
||
|
||
MOVE.B #ClosedMPP,WakeWarn(A2) ; Set flag for wake up warning (MPP closed)
|
||
BRA.S @okexit ; We're cool
|
||
|
||
; XPP is open and a server may be mounted. If no server then give the wimpy warning, else
|
||
; give a stronger one.
|
||
|
||
@dmndcase2 BSR XPPCheck ; Try to close XPP
|
||
BNE.S @dmndcase3 ; Branch if not able
|
||
|
||
BSR.W WimpyWarn ; Warn user of possible problems
|
||
BNE.S @done ; Branch if chickened out
|
||
|
||
MOVE.B #ClosedXPP,WakeWarn(A2) ; Set flag for wake up warning (XPP closed)
|
||
BRA.S @okexit ; We're cool
|
||
|
||
; Server is mounted so give the strong warning.
|
||
|
||
@dmndcase3 BSR.W StrongWarn ; Be firm but gentle
|
||
BNE.S @done ; Talked him out of it
|
||
|
||
MOVE.B #ClosedSvr,WakeWarn(A2) ; Set flag for wake up warning (server lost)
|
||
BRA.S @okexit ; It was rough but we're fine
|
||
|
||
;________________________________________________________________________________________
|
||
; Now sleep (Low power) case. Close any and all but select the right wake up warning.
|
||
;________________________________________________________________________________________
|
||
|
||
@nowcase MOVE.B #ClearedChsr,WakeWarn(A2) ; Set flag for wake up warning (magic bit cleared)
|
||
BSET #noATChg,ChooserBits ; Clear magic chooser bit
|
||
BEQ.S @nowcase4 ; Branch if bit was active
|
||
|
||
MOVE.B #ClosedMPP,WakeWarn(A2) ; Set flag for wake up warning (MPP closed)
|
||
BTST #XPPLoadedBit,PortBUse ; Test for XPP in use
|
||
BNZ.S @nowcase4 ; Branch if so
|
||
|
||
MOVE.B #ClosedXPP,WakeWarn(A2) ; Set flag for wake up warning (XPP closed)
|
||
BSR XPPCheck ; Try to close XPP
|
||
BEQ.S @nowcase4 ; Branch if did
|
||
|
||
MOVE.B #ClosedSvr,WakeWarn(A2) ; Set flag for wake up warning (server lost)
|
||
|
||
@nowcase4
|
||
@okexit MOVEQ #0,D0
|
||
|
||
@done ADD.W #ioQElSize,SP ; Release stack frame
|
||
MOVEM.L (SP)+,A0-A3/D1-D2
|
||
TST.W D0
|
||
RTS
|
||
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; 91/02/13 - AG
|
||
;
|
||
; Close appletalk drivers if necessary
|
||
;
|
||
;________________________________________________________________________________________
|
||
CloseAppleTalk
|
||
MOVEM.L A0-A3/D1-D2,-(SP) ; Try to close AppleTalk and warn user of this <v1.4>
|
||
SUB.W #ioQElSize,SP ; Allocate IO stack frame
|
||
MOVE.L SP,A3 ; Save this place
|
||
|
||
MOVE.L PmgrBase,A2 ;
|
||
MOVEQ #$0F,D1 ; Lower nibble indicates ATalk in use
|
||
AND.B PortBUse,D1
|
||
CMP.B #1,D1
|
||
BNE @Closedone ; Do exit if no Atalk
|
||
BSR.W AllClose ; Shutdown everything
|
||
|
||
@Closedone ADD.W #ioQElSize,SP ; Release stack frame
|
||
MOVEM.L (SP)+,A0-A3/D1-D2
|
||
TST.W D0
|
||
RTS
|
||
|
||
;———————————————————————————————————————————————————————————————————————
|
||
; CloseATalk support routines.
|
||
;———————————————————————————————————————————————————————————————————————
|
||
|
||
StrongWarn MOVE.W #-16386,D0
|
||
BRA.S Warn
|
||
|
||
WimpyWarn MOVE.W #-16387,D0
|
||
BRA.S Warn
|
||
|
||
HarshWarn MOVE.W #-16388,D0
|
||
|
||
Warn CLR.W -(SP) ; Send the warning
|
||
MOVE.W D0,-(SP)
|
||
CLR.L -(SP)
|
||
_Alert
|
||
MOVE.W (SP)+,D0 ; D0 non-zero if canceled
|
||
SUBQ.W #1,D0 ; <t31> 1 is sleep button
|
||
RTS
|
||
|
||
MPPClose MOVE.L A3,A0 ; Get stack frame pointer
|
||
MOVE #~MPPUnitNum,ioRefNum(A0) ; Close MPP
|
||
_Close
|
||
TST.W D0
|
||
RTS ; Sucess returned in status
|
||
|
||
XPPClose MOVE.L A3,A0 ; Get stack frame pointer
|
||
LEA #'.XPP',A1 ; Get XPP refnum
|
||
MOVE.L A1,ioVNPtr(A0)
|
||
MOVE.B #fsCurPerm,ioPermssn(A0)
|
||
_Open
|
||
_Close ; Close XPP
|
||
TST.W D0
|
||
RTS ; Sucess returned in status
|
||
|
||
AllClose MOVE.L A3,A0 ; Get stack frame pointer
|
||
LEA #'.XPP',A1 ; Get XPP refnum
|
||
MOVE.L A1,ioVNPtr(A0)
|
||
MOVE.B #fsCurPerm,ioPermssn(A0)
|
||
_Open
|
||
MOVE #CloseAll,csCode(A0) ; Close everything
|
||
_Control
|
||
_Close
|
||
MOVE #~MPPUnitNum,ioRefNum(A0); Close MPP
|
||
_Close
|
||
TST.W D0
|
||
RTS ; Sucess returned in status
|
||
|
||
|
||
;———————————————————————————————————————————————————————————————————————
|
||
;
|
||
; MPPOpen - routine to open the MPP driver. If the driver is not necessary, the open
|
||
; will fail, so just try to open the driver blindly
|
||
;
|
||
; input
|
||
; none
|
||
;
|
||
; output
|
||
; none
|
||
;
|
||
; usage
|
||
; a0 - pointer to iopb
|
||
; a1 - pointer to driver name
|
||
;
|
||
;———————————————————————————————————————————————————————————————————————
|
||
|
||
MPPOpen MOVEM.L A0-A3/D1-D2,-(SP)
|
||
;•••••••••••••••• <K14>
|
||
; temporarily don't even call this!
|
||
; so we stop switching from ethertalk to localtalk across sleep
|
||
IF BlackBirdDebug THEN
|
||
TestFor PrattExists
|
||
bne.s @skipit
|
||
BSR SelectAtlkPort ; make sure AppleTalk knows which port to use <H67>
|
||
@skipit
|
||
ENDIF
|
||
;•••••••••••••••• <K14>
|
||
LEA -ioQElSize(SP),SP ; Allocate IO stack frame
|
||
MOVEA.L SP,A0 ; Save this place
|
||
|
||
LEA #'.MPP',A1 ; Get MPP refnum
|
||
MOVE.L A1,ioVNPtr(A0)
|
||
MOVE.B #fsCurPerm,ioPermssn(A0)
|
||
_Open
|
||
|
||
LEA ioQElSize(SP),SP ; Release stack frame
|
||
MOVEM.L (SP)+,A0-A3/D1-D2
|
||
RTS
|
||
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: SelectAtlkPort
|
||
;
|
||
; Inputs: none
|
||
;
|
||
; Outputs: none
|
||
;
|
||
; Trashes: D0-D1/A0-A1
|
||
;
|
||
; Function: Calls the lmgr to see if the AppleTalk connection in use
|
||
; before going to sleep is still available. If it isn't, it
|
||
; switches to the preferred connection (usually SCC port B).
|
||
;________________________________________________________________________________________
|
||
|
||
SelectAtlkPort ; <H67>
|
||
MOVE.W #mapTrue,RomMapInsert ; map the ROM into the resource chain
|
||
SUBQ.W #4,SP
|
||
PEA 'lmgr' ; theType
|
||
CLR.W -(SP) ; theID
|
||
_GetResource ; try to load the ‘lmgr’
|
||
MOVE.L (SP)+,D0 ; did we get it
|
||
BEQ.S @NoLmgr ; -> no, just exit
|
||
MOVEA.L D0,A0 ; get the handle to the ‘lmgr’
|
||
MOVE.L A0,-(SP) ; and push a copy for ReleaseResource
|
||
|
||
CLR.L -(SP) ; param1 (none)
|
||
CLR.L -(SP) ; param2 (none)
|
||
PEA 6 ; selector
|
||
MOVEA.L (A0),A0
|
||
JSR 2(A0) ; call the ‘lmgr’ to switch the ‘atlk’ if necessary
|
||
LEA 12(SP),SP ; (toss parameters, C style)
|
||
|
||
_ReleaseResource ; all done, so unload the resource
|
||
@NoLmgr RTS
|
||
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; 91/02/13 - AG
|
||
;
|
||
; DoQueueStack - this routine is called to traverse the sleep queue. if
|
||
; the sleep type is "now", "demand", or "WakeUp", the queue will only
|
||
; be run once. otherwise, the queue will be run twice. once to check if
|
||
; its ok to sleep, if ok, the sleep type is changed to "demand" and the
|
||
; queue is rerun. if not ok, then the sleep type is change to "Unlock"
|
||
; and the queue is rerun, Each proc is passed its queue entry in A0.
|
||
;
|
||
; input
|
||
; d0 sleep type
|
||
; a0 ptr to pmgrglobals
|
||
;
|
||
; output
|
||
; d0
|
||
; == 0 ok to sleep
|
||
; != 0 queue rejected auto sleep
|
||
;
|
||
; usage
|
||
; d d0 sleep type/result
|
||
; a0 pointer to first element/ ptr to pmgrglobals
|
||
;
|
||
;———————————————————————————————————————————————————————————————————————
|
||
|
||
DoQueueStack
|
||
MOVEM.L A0/D1,-(SP) ; save pmgrglobals ptr
|
||
MOVE.L SlpQHead(A0),A0 ; Get ptr to first element
|
||
|
||
CMP.W #SleepRequest,D0 ; is it auto sleep ?
|
||
BNE.S @runTheQueue ; if no, just run the queue
|
||
|
||
@testTheQueue
|
||
BSR.s Handle_Element ; ask queue about auto sleep
|
||
BNE.s @undosleepreq ; if error returned, undo sleep
|
||
MOVEQ #SleepDemand,D0 ; ... else set to sleep demand
|
||
|
||
@runTheQueue
|
||
BSR.S Handle_Element ; handle element
|
||
CLR.L D0 ; return no error
|
||
|
||
@exit MOVEM.L (SP)+,A0/D1 ; restore pmgrglobals ptr
|
||
RTS
|
||
|
||
@undosleepreq
|
||
MOVEQ #SleepUnlock,D0 ; Since sleep denied, set to unsleep
|
||
BSR.S Handle_Element ; handle element
|
||
MOVEQ #SleepUnlock,D0 ; return non zero result
|
||
BRA.S @exit
|
||
|
||
|
||
;———————————————————————————————————————————————————————————————————————
|
||
;
|
||
; Handle Element - this is a routine which is used to execute a queue element. if the
|
||
; element pointer is null, the routine exits and returns 0 in d0. if the element
|
||
; pointer is not null, then the routine will do two thing:
|
||
; 1) handle the next element recursively
|
||
; 2) execute the current element's sleep proc
|
||
; the queue will essentially be traversed in post fixed order
|
||
;
|
||
; input
|
||
; a0 pointer to queue element
|
||
; d0 sleep type
|
||
;
|
||
; output
|
||
; d0 result
|
||
; == 0 ok to sleep
|
||
; != 0 sleep rejected
|
||
;
|
||
; Usage
|
||
; a0 pointer to element
|
||
; d a1 pointer to sleep proc
|
||
; d d0 sleep type/result
|
||
; d d1 saved sleep type/ condition code check
|
||
;
|
||
;———————————————————————————————————————————————————————————————————————
|
||
ProcRegs REG a0-a6/d1-d7
|
||
|
||
Handle_Element
|
||
MOVE.L a0,d1 ; test element pointer
|
||
BEQ.S @noelement ; if invalid element ptr, exit with d0 clear
|
||
MOVE.L d0,d1 ; save a copy of type in d1
|
||
|
||
@validelement
|
||
MOVEM.L a0/d1,-(sp) ; save element pointer and type
|
||
MOVE.L SleepqLink(a0),a0 ; pass in pointer to next element
|
||
BSR.S Handle_Element ; handle the next element in queue
|
||
MOVEM.L (sp)+,a0/d1 ; restore pointer and type
|
||
BNE.S @exit ; if result != zero, exit
|
||
|
||
@callproc
|
||
MOVE.L SleepqProc(a0),D0 ; get a pointer to the proc <H33>
|
||
BEQ.S @noelement ; if no pointer, exit; flags set by move <H33>
|
||
MOVEA.L d0,a1 ; load pointer in address register for execution <H33>
|
||
|
||
MOVE.L d1,d0 ; restore type to d0
|
||
MOVEM.L ProcRegs,-(sp) ; save the world before calling proc <15> ag
|
||
JSR (a1) ; call sleep proc
|
||
MOVEM.L (sp)+,ProcRegs ; restore the world
|
||
|
||
CMP.W #SleepRequest,D1 ; is this request or demand? <H13>
|
||
BNE.S @noelement ; IF NOT Request THEN clear result & exit <H13>
|
||
TST.L d0 ; ELSE set condition codes on result <H13>
|
||
RTS ; <H13>
|
||
|
||
@noelement moveq #0,d0 ; clear result
|
||
@exit RTS ; exit
|
||
|
||
|
||
;———————————————————————————————————————————————————————————————————————
|
||
;
|
||
; XPPCheck - this is a routine checks to see if any servers are mounted.
|
||
; D0 will return the error from the close. if no error, no servers!
|
||
; to restore the world, reopen the driver after.
|
||
;
|
||
; input
|
||
; a3 pointer to pb
|
||
;
|
||
; output
|
||
; d0 result
|
||
; == 0 no servers mounted
|
||
; != 0 servers mounted
|
||
;
|
||
; Usage
|
||
; a0 pointer to pb
|
||
; a1 pointer to driver name
|
||
; a3 pointer to pb
|
||
;
|
||
;———————————————————————————————————————————————————————————————————————
|
||
XPPCheck MOVE.L a3,a0 ; Get pb pointer
|
||
|
||
MOVE.W #~xppUnitNum,ioRefNum(A0) ;
|
||
_Close ; Close XPP
|
||
|
||
MOVE.L d0,-(sp) ; save result
|
||
LEA #'.XPP',a1 ; Get XPP refnum
|
||
MOVE.L a1,ioVNPtr(a0) ; load pointer to driver
|
||
MOVE.B #fsCurPerm,ioPermssn(a0) ; set permission
|
||
_Open ; get refnum
|
||
MOVE.L (sp)+,d0 ; restore result
|
||
|
||
TST.W d0 ; test close result
|
||
RTS ; Sucess returned in status
|
||
|
||
|
||
;———————————————————————————————————————————————————————————————————————
|
||
;
|
||
; DoQueue - Call each procedure in the sleep/wake queue with the parameter passed
|
||
; in D0. Each proc is passed its queue entry in A0.
|
||
;———————————————————————————————————————————————————————————————————————
|
||
|
||
DoQueue CMP.W #SleepNow,D0 ; Sleep now
|
||
BEQ.S @mustsleep
|
||
CMP.W #SleepDemand,D0 ; Sleep demand
|
||
BEQ.S @mustsleep
|
||
CMP.W #SleepWakeUp,D0 ; or wake calls are not denied
|
||
BEQ.S @mustsleep
|
||
|
||
@startreq MOVE.L D0,D7 ; Save call type
|
||
MOVE.L PmgrBase,A1
|
||
|
||
MOVE.L SlpQHead(A1),A0 ; Get head pointer to sleep queue entries
|
||
MOVE.L A0,D2
|
||
BEQ @noentries ; Skip rest if no entries
|
||
|
||
@getreq MOVE.L SleepqProc(A0),A2 ; Get sleep proc
|
||
MOVE.L A2,D2
|
||
BEQ.S @nextreq ; Go to next if no proc
|
||
MOVE.W D7,D0
|
||
MOVEM.L A0-A1,-(SP)
|
||
JSR (A2) ; Execute proc
|
||
MOVEM.L (SP)+,A0-A1
|
||
TST.L D0
|
||
BEQ.S @nextreq ; Request ok
|
||
|
||
CMP.W #SleepUnlock,D7 ; If unlocking then continue
|
||
BEQ.S @nextreq
|
||
|
||
MOVEQ #SleepUnlock,D0 ; Since sleep denied
|
||
MOVE.L D0,D7
|
||
BRA.S @startreq ; unlock everything
|
||
|
||
@nextreq CMP.L SlpQTail(A1),A0 ; Check for more entries
|
||
BEQ.S @checkreq ; Branch if no more
|
||
|
||
MOVE.L SleepqLink(A0),A0 ; Get next queue entry
|
||
BRA.S @getreq
|
||
|
||
@checkreq MOVEQ #SleepDemand,D0 ; Queue says sleep is ok
|
||
CMP.W #SleepUnlock,D7 ; If we were unlocking then we are done now
|
||
BNE.S @mustsleep
|
||
|
||
MOVEQ #SleepDeny,D0 ; Sleep request failed
|
||
RTS
|
||
|
||
; Sleep demand case
|
||
|
||
@mustsleep MOVE.W D0,D7 ; Save command
|
||
MOVE.L PmgrBase,A1
|
||
|
||
MOVE.L SlpQHead(A1),A0 ; Get head pointer to sleep queue entries
|
||
MOVE.L A0,D2
|
||
BEQ.S @noentries ; Skip rest if no entries
|
||
|
||
@getdemand MOVE.L SleepqProc(A0),A2 ; Get sleep proc
|
||
MOVE.L A2,D2
|
||
BEQ.S @nextdemand ; Go to next if no proc
|
||
MOVE.W D7,D0
|
||
MOVEM.L A0-A1,-(SP)
|
||
JSR (A2) ; Execute proc
|
||
MOVEM.L (SP)+,A0-A1
|
||
|
||
@nextdemand CMP.L SlpQTail(A1),A0 ; Check for more entries
|
||
BEQ.S @noentries ; Branch if no more
|
||
|
||
MOVE.L SleepqLink(A0),A0 ; Get next queue entry
|
||
BRA.S @getdemand
|
||
|
||
@noentries CLR.L D0
|
||
RTS
|
||
|
||
|
||
;———————————————————————————————————————————————————————————————————————
|
||
; KbdReset - Clears all keymaps
|
||
;———————————————————————————————————————————————————————————————————————
|
||
|
||
KbdReset BigJSR RSetKMap,A1 ; Reset global keymap <v2.9>
|
||
|
||
MOVEQ #numFDBAdr, D1 ; Number of table entries
|
||
MOVE.L ADBBase, A1 ; Put Base in A1
|
||
BRA.S @10 ; Skip past record increment
|
||
|
||
@loop ADD #FRecSize, A1 ; Get to next record
|
||
|
||
@10 MOVEQ #2, D0 ; We're looking for keyboards
|
||
CMP.B FDBOAddr(A1), D0 ; Is this one?
|
||
BNE.S @notkbd ; Nope, skip around
|
||
|
||
MOVE.L FDBOpData(A1),A0 ; Retrieve pointer to kbd data
|
||
LEA 4(A0),A0 ; Get address of keybits
|
||
|
||
MOVEQ #0,D0
|
||
MOVE.L D0,(A0)+ ; Clear the key bits
|
||
MOVE.L D0,(A0)+
|
||
MOVE.L D0,(A0)+
|
||
MOVE.L D0,(A0)+
|
||
|
||
@notkbd DBRA D1, @loop ; Loop until no more
|
||
RTS
|
||
|
||
|
||
STRING ASIS
|
||
;———————————————————————————————————————————————————————————————————————
|
||
;
|
||
; SlpQInstall/SlpQRemove - Installs/Removes entries in the sleep queue.
|
||
;
|
||
; Enrty: A0 = SlpQRec (pointer)
|
||
;
|
||
; Exit: D0 = Result code (word)
|
||
;———————————————————————————————————————————————————————————————————————
|
||
|
||
SlpQInstall
|
||
CMP.W #slpQType,SleepqType(A0)
|
||
BNE.S SlpQErr
|
||
|
||
MOVE.L PmgrBase,A1
|
||
LEA SleepQHdr(A1),A1
|
||
_Enqueue
|
||
RTS
|
||
|
||
SlpQErr MOVEQ #SlpTypeErr,D0
|
||
RTS
|
||
|
||
SlpQRemove CMP.W #slpQType,SleepqType(A0)
|
||
BNE.S SlpQErr
|
||
|
||
MOVE.L PmgrBase,A1
|
||
LEA SleepQHdr(A1),A1
|
||
_Dequeue
|
||
RTS
|
||
;•••••••••••••••••••••••••••••••• End of Traps ••••••••••••••••••••••••••••••••••••••••••
|
||
|
||
;••••••••••••••••••••••••••••••••••• Misc •••••••••••••••••••••••••••••••••••••••••••••••
|
||
;
|
||
; Contains:
|
||
;
|
||
; ResetPMGRInts
|
||
; SaveSetCrsr
|
||
; RestoreScreen
|
||
; SetSupervisorMode
|
||
; PMGRsend/recv
|
||
; SetPwrLvlTask
|
||
; DoSpinDown
|
||
; DoHDSpinUP
|
||
; PowerDownAll
|
||
; PortableCheck
|
||
;
|
||
;________________________________________________________________________________________
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: ResetPMGRInts
|
||
;
|
||
; Inputs: A1 - VIA1 base address
|
||
;
|
||
; Outputs: A1 - VIA1 base address
|
||
;
|
||
; Trashes: D0, D1, A0
|
||
;
|
||
; Function: clears any pending PMGR interupts and disables modem interrupts
|
||
;________________________________________________________________________________________
|
||
ResetPMGRInts ; clear any pending PMGR interrupts
|
||
MOVE.L VIA,A1 ; get VIA base address
|
||
MOVE.B #(1<<ifIRQ)+(1<<ifCB1),\
|
||
vIFR(A1) ; clear PMGR interrupts in the VIA
|
||
; read any pending PMGR interrupt data from PG&E so we don't hang in InitADB...
|
||
|
||
LEA -12(SP),SP ; allocate a buffer for interrupt data <H8>
|
||
MOVE.L SP,A0 ; and point to it <H8>
|
||
ADDQ.L #2,A0 ; (why do we have to do this?) <H8>
|
||
MOVEQ #ReadINT,D0 ; PMGR command = get interrupt data <H8>
|
||
BSR PMGRrecv ; go get the interrupt data (we'll just toss it) <H8>
|
||
|
||
; disable all modem interrupt sources so we won't get spurious level 3 interrupts from PG&E...
|
||
|
||
CLR.B (A0) ; data to send = disable all modem interrupt sources <H57>
|
||
MOVEQ #1,D1 ; 1 bytes to send <H57>
|
||
MOVEQ #SetModemInts,D0 ; command = set modem interrupt sources <H57>
|
||
BSR PMGRsend ; tell PG&E to turn them all off <H57>
|
||
LEA 12(SP),SP ; toss the buffer <H8>
|
||
|
||
MOVE.B #(1<<ifIRQ)+(1<<ifCB1),\
|
||
vIER(A1) ; enable PMGR interrupts in the VIA
|
||
RTS ; <H57>
|
||
|
||
|
||
;————————————————————————————————————————————————————————————————————————————————————————
|
||
; Routine: SaveSetCrsr
|
||
;
|
||
; Inputs: A2 - pointer to Power Manager variables
|
||
; A5 - Quickdraw globals
|
||
;
|
||
; Outputs: none
|
||
;
|
||
; Trashes: A0 - A1
|
||
;
|
||
; Function: Save current state of cursor and set cursor to a watch cursor.
|
||
;————————————————————————————————————————————————————————————————————————————————————————
|
||
SaveSetCrsr
|
||
MOVE.L (A5),A0 ; point to QuickDraw globals
|
||
LEA Arrow(A0),A0 ; Get pointer to current cursor
|
||
MOVE.L A0,SleepSaveCrsr(A2) ; save the address of cursor in our little storage
|
||
SUBA.L #4,SP ; Get some stack space <34> HJR
|
||
MOVE.W #watchCursor,-(SP) ; Get the watch cursor
|
||
_GetCursor
|
||
MOVE.L (SP)+,A0 ; Get handle to cursor
|
||
MOVE.L (A0),A0 ; Dereference once
|
||
MOVE.L A0,-(SP) ; push parameter on stack
|
||
_SetCursor
|
||
_HideCursor ; <H56>
|
||
RTS
|
||
|
||
;————————————————————————————————————————————————————————————————————————————————————————
|
||
; Routine: RestoreScreen
|
||
;
|
||
; Inputs: A2 - pointer to Power Manager variables
|
||
; A5 - Quickdraw globals
|
||
;
|
||
; Outputs: none
|
||
;
|
||
; Trashes: A0
|
||
;
|
||
; Function: Restores the cursor to its previous state and updates the screen (but not
|
||
; in that order :-)
|
||
;————————————————————————————————————————————————————————————————————————————————————————
|
||
RestoreScreen
|
||
JsrRoutine ScreenRedrawPtr,A2,A0 ; (Calls RedrawScrn from the Primitives.)
|
||
MOVE.L SleepSaveCrsr(A2),-(SP) ; Get ptr to saved crsr
|
||
_SetCursor ; Set the cursor
|
||
_ShowCursor ; Show it to the world
|
||
RTS
|
||
|
||
|
||
;________________________________________________________________________________________
|
||
; SetSupervisorMode
|
||
;
|
||
; Input: None
|
||
;
|
||
; Destroys: D0/A1
|
||
;
|
||
; Called by: BSR from DreamAway & Wakeup.
|
||
;
|
||
; Function: When VM is running we must switch to supervisor mode so
|
||
; that we may run necessary priviledged instructions. Yes
|
||
; we are the operatorating system and that is acceptable!!!
|
||
;________________________________________________________________________________________
|
||
SetSupervisorMode
|
||
MOVE.L (SP)+,A1 ; Save a copy of return address since we might switch stacks
|
||
MOVEQ #8,D0 ; Set selector to Set Supervisor Mode for VM
|
||
_DebugUtil ;
|
||
CMPI.W #paramErr,D0 ; IF VM is on THEN D0 = Status Register
|
||
BNE.S @Cont ; ELSE
|
||
MOVE.W SR,D0 ; Save the current Status Register
|
||
@Cont ANDI.W #$EFFF,SR ; Make sure that we are in the interrupt stack
|
||
JMP (A1) ; Get out of here
|
||
|
||
;————————————————————————————————————————————————————————————————————————————————————————
|
||
; Routine: PMGRsend/recv
|
||
;
|
||
; Inputs: A0 - data buffer
|
||
; D0 - command
|
||
; D1 - length
|
||
;
|
||
; Outputs: A0 - data buffer
|
||
; D0 - result code
|
||
;
|
||
; Trashes: A0 - A1
|
||
;
|
||
; Function: Handy PmgrOp calling routines.
|
||
;————————————————————————————————————————————————————————————————————————————————————————
|
||
PMGRrecv MOVEQ #0,D1 ; Get data from pmgr <v2.4>
|
||
|
||
PMGRsend MOVE.L A0,-(SP) ; pmRBuffer
|
||
MOVE.L A0,-(SP) ; pmSBuffer
|
||
MOVE.W D1,-(SP) ; pmLength
|
||
MOVE.W D0,-(SP) ; pmCommand
|
||
MOVE.L SP,A0
|
||
_PmgrOp
|
||
MOVE.W pmLength(sp),d1 ; return count <gmr>
|
||
LEA pmRBuffer(SP),SP ; Release stack frame
|
||
MOVE.L (SP)+,A0 ; pmRBuffer
|
||
RTS
|
||
|
||
|
||
;————————————————————————————————————————————————————————————————————————————————————————
|
||
; Routine: SetPwrLvlTask
|
||
;
|
||
; Inputs: A2 - PMgrBase
|
||
;
|
||
; Outputs: none
|
||
;
|
||
; Trashes: A0
|
||
;
|
||
; Function: set the power manager micro levels to match those set in the 680x0 pmgr globals
|
||
;————————————————————————————————————————————————————————————————————————————————————————
|
||
SetPwrLvlTask
|
||
@SetPwrLvlRegs REG A0-A1/D0-D1
|
||
|
||
MOVEM.L @SetPwrLvlRegs,-(SP) ; working registers
|
||
MOVE.W #$4201,-(SP) ; pushpram byte 0x42 + one byte of data
|
||
MOVE.W LowWarn(A2),-(SP) ; move the current 68K pmgr setting into buffer for set
|
||
MOVEA.L SP,A0 ; set up data buffer
|
||
MOVEQ #xPramWrite,D0 ; command to send
|
||
MOVEQ #3,D1 ; number of data bytes
|
||
BSR.S PMGRsend ; send command
|
||
CLR.L (SP)+ ; clean up buffer
|
||
MOVEM.L (SP)+,@SetPwrLvlRegs ; Restore working registers
|
||
RTS
|
||
|
||
;________________________________________________________________________________________ <H82>
|
||
;
|
||
; Routine: DoSpinDown
|
||
;
|
||
; Inputs: none
|
||
;
|
||
; Outputs: none
|
||
;
|
||
; Trashes: D0, A0
|
||
;
|
||
; Function: kills power to the internal hard disk, unless spindown is disabled
|
||
;________________________________________________________________________________________
|
||
|
||
DoSpinDown
|
||
MOVEM.L A0-A1,-(SP) ; save some registers
|
||
MOVEA.L PMgrBase,A1 ; point to the Power Manager's globals <H83>
|
||
BTST.B #QuickHDSpinDwn,PmgrFlags2(A1) ; quick spin down enabled? <H83>
|
||
BNE.S @MustSpindown ; -> yes, have to spin down even if disabled<H83>
|
||
IF HDSpinDownDisable=7 THEN
|
||
TST.B PmgrFlags2(A1) ; is spindown allowed? <H83>
|
||
BMI.S @Done ; -> no, ignore it <H83>
|
||
ELSE
|
||
BTST #HDSpinDownDisable,PmgrFlags2(A1) ; is spindown allowed? <H83>
|
||
BNE.S @Done ; -> no, ignore it <H83>
|
||
ENDIF
|
||
@MustSpindown ; <H83>
|
||
BCLR #HDPowerOn,PMgrFlags(A1); clear the flag, indicating that the drive is now spun down <K36>
|
||
|
||
; call each of the routines in the hard disk queue to notify anyone who cares
|
||
; that the hard disk is about to be spun down
|
||
|
||
MOVEM.L D1-D2/A1-A2,-(SP)
|
||
LEA hdQHead(A1),A2 ; point to the start of the hard disk queue
|
||
BRA.S @NoProc
|
||
@NextElement
|
||
MOVEA.L D0,A2 ; point to the next queue element
|
||
MOVE.L hdProc(A2),D0 ; get the pointer to the routine
|
||
BEQ.S @NoProc ; -> there isn't one
|
||
MOVE.L A2,-(SP) ; push a pointer to the queue element <H81>
|
||
MOVEA.L D0,A0 ; point to the routine
|
||
JSR (A0) ; and call it
|
||
@NoProc MOVE.L hdQLink(A2),D0 ; end of the queue?
|
||
BNE.S @NextElement ; -> no, keep running (huff! puff!)
|
||
MOVEM.L (SP)+,D1-D2/A1-A2
|
||
|
||
; finally, spin down the internal hard disk
|
||
|
||
MOVE.B #hdOff,-(SP) ; data to send = turn off hard disk power plane
|
||
MOVE.L SP,-(SP) ; pmRBuffer (not used)
|
||
MOVE.L (SP),-(SP) ; pmSBuffer
|
||
MOVE.W #1,-(SP) ; pmLength
|
||
MOVE.W #powerCntl,-(SP) ; pmCommand
|
||
MOVEA.L SP,A0 ; point to the parameter block
|
||
_PMgrOp ; turn off the hard disk
|
||
LEA pmRBuffer+4+2(SP),SP ; clean up the stack
|
||
BNE.S @Done ; -> an error occurred
|
||
|
||
CLR.L LastHD(A1) ; stop calling - disk is spun down
|
||
BCLR #HDPowerOn,PMgrFlags(A1); clear the flag, indicating that the drive is now spun down
|
||
MOVEM.L (SP)+,A0-A1 ; restore some registers
|
||
@Done RTS
|
||
|
||
;________________________________________________________________________________________ <H82>
|
||
;
|
||
; Routine: DoHDSpinUp
|
||
;
|
||
; Inputs: none
|
||
;
|
||
; Outputs: none
|
||
;
|
||
; Trashes: D0, A0
|
||
;
|
||
; Function: restores power to the internal hard disk
|
||
;________________________________________________________________________________________
|
||
|
||
DoHDSpinUp
|
||
|
||
; This portion of code freezes the "Spin Down" timer for the hard disk, preventing
|
||
; the Power Mgr from cutting hard disk power during ANY SCSI transaction.
|
||
|
||
MOVEM.L A0-A1/D0,-(SP) ; save them regs
|
||
|
||
MOVEA.L PmgrBase,A1 ; point to Pmgr locals
|
||
MOVE.L #0,LastHd(A1) ; always freeze the spin down timer
|
||
BTST.B #HDPowerOn,PmgrFlags(A1) ; set flag indicating drive is now spun up <t11> djw
|
||
BNE.S @Done ; drive already spun up - skip PmgrOp call <t11> djw
|
||
|
||
MOVE.B #hdOn,-(SP) ; data to send = turn off hard disk power plane
|
||
MOVE.L SP,-(SP) ; pmRBuffer (not used)
|
||
MOVE.L (SP),-(SP) ; pmSBuffer
|
||
MOVE.W #1,-(SP) ; pmLength
|
||
MOVE.W #powerCntl,-(SP) ; pmCommand
|
||
MOVEA.L SP,A0 ; point to the parameter block
|
||
_PMgrOp ; turn off the hard disk
|
||
LEA pmRBuffer+4+2(SP),SP ; clean up the stack
|
||
BNE.S @Done ; -> an error occurred
|
||
|
||
MOVE.L #250,D0 ; wait 250 Miliseconds
|
||
BigJsr DelayNMsec,A0 ; … Spin are wheels
|
||
|
||
BSET.B #HDPowerOn,PmgrFlags(A1) ; set flag indicating drive is now spun up <t11> djw
|
||
|
||
@Done MOVEM.L (SP)+,A0-A1/D0 ; restore them registers
|
||
RTS ; return to SCSIGet
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: PowerDownAll
|
||
;
|
||
; Inputs: none
|
||
;
|
||
; Outputs: none
|
||
;
|
||
; Trashes: D0, A0
|
||
;
|
||
; Function: called by StartInit to power down all peripheral subsystems
|
||
;________________________________________________________________________________________
|
||
|
||
PowerDownAll
|
||
TestFor hwCbPwrMgr ; is there Power Mgr in this Mac ?
|
||
BEQ.S @NoPMGR ; -> no, skip
|
||
MOVE.B #allOff,-(SP) ; buffer contains "turn off unused devices"
|
||
IF forRomulator THEN
|
||
ANDI.B #~((1<<pSCC)|(1<<pSerDrvr)|(1<<pMinus5V)),(SP) ; don't kill the nub! <SM69>
|
||
ENDIF
|
||
MOVE.L SP,-(SP) ; point to receive buffer
|
||
MOVE.L (SP),-(SP) ; point to transmit buffer
|
||
MOVE.W #1,-(SP) ; one byte of transmit data
|
||
MOVE.W #PowerCntl,-(SP) ; PMGR command: power control
|
||
MOVE.L SP,A0 ; A0 gets pointer to parameter block
|
||
_PmgrOp
|
||
LEA pmRBuffer+4+2(SP),SP ; Remove stack frame
|
||
MOVEA.L PmgrBase,A0 ; get addr of globals <t25>
|
||
BCLR.B #HDPowerOn,PmgrFlags(A0) ; clear HD powered on flag <t25>
|
||
@NoPMGR RTS
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: PortableCheck
|
||
;
|
||
; Inputs: D2 - Bits 31..16, hwCfgFlags info (possibly unknown)
|
||
; D2 - Bits 7..0, Address Decoder Kind (zero if unknown)
|
||
; A1 - Productinfo
|
||
;
|
||
; Outputs: none
|
||
;
|
||
; Trashes: D0-D1, A0-A6
|
||
;
|
||
; Function: Called by a BSR6 from StartInit to check if we're booting
|
||
; or waking up. Since we've just called JumpIntoROM, D2
|
||
; has the decoder kind.
|
||
;________________________________________________________________________________________
|
||
|
||
|
||
beok EQU 27 ;a BusError is expected and is OK (copied from STEqu.a to avoid duplicate label if included)
|
||
|
||
PortableCheck
|
||
IF isUniversal THEN
|
||
BTST.L #(hwCbPwrMgr+16),D2 ; Are we running on Pmgr System
|
||
BEQ.W NonPwrMgr ; NOPE. Branch...
|
||
ENDIF
|
||
|
||
MOVEA.L A6,A5 ; save return addr <H34>
|
||
LEA @NoRAM,A6 ; load return addr in case of bus error <H34>
|
||
|
||
MOVE.L PmgrBase,A2 ; get the addr of PMgrVars <H34>
|
||
CMP.L #SleepConst,SleepSaveFlag(A2) ; are we waking from sleep?
|
||
BNE.S @noRAM ; branch if not <H34>
|
||
|
||
CLR.L SleepSaveFlag(A2) ; clear the sleep flag
|
||
MOVE.L WakeVector(A2),A0 ; Go restore ourself
|
||
JMP (A0) ; .
|
||
|
||
NOP ; keep everything aligned <H34>
|
||
|
||
@NoRAM MOVEA.L A5,A6 ; restore return addr <H34>
|
||
|
||
;————————————————————————————————————————————————————————————————————————————————
|
||
; Routine: CheckEconoMode
|
||
;
|
||
; Input: D2 - Bits 31..16, hwCfgFlags info (possibly unknown)
|
||
; D2 - Bits 7..0, Address Decoder Kind (zero if unknown)
|
||
;
|
||
; Destroys: A0-A7,D0-D6
|
||
;
|
||
; Called by: BSR6 from StartInit.
|
||
;
|
||
; Function: checks to see if a portable needs to be switched into econo-mode
|
||
;————————————————————————————————————————————————————————————————————————————————
|
||
|
||
CheckEconoMode
|
||
; do we have a Pratt?
|
||
btst #(PrattExists//8),(ProductInfo.BasesValid1+3-(PrattExists/8))(a1)
|
||
bne NonPwrMgr ; yes don't do anything
|
||
MOVEA.L A6,A7 ; save the return address <H18>
|
||
|
||
BigBSR6 InitWallyWorld,A1 ; download code into the PMGR, if necessary <H18>
|
||
|
||
MOVEQ #0,D2 ; <H18>
|
||
BigBSR6 GetHardwareInfo,A0 ; figure out what we're running on
|
||
|
||
MOVE.L D2,D4 ; save the decoder type around the PRAM calls <H18>
|
||
MOVEQ #$10,D1 ; read the PRAM validation byte <H18>
|
||
MOVEA.L DecoderInfo.VIA1Addr(A0),A2 ; point to base of VIA1 <H19>
|
||
BigBSR6 RdXByte,A0 ; <H18>
|
||
MOVEQ #$A8-256,D0 ; compare what was read against expected value <H18>
|
||
SUB.B D1,D0 ; <H18>
|
||
MOVEQ #0,D1 ; (assume PRAM's invalid) <H18>
|
||
TST.B D0 ; is PRAM OK? <H18>
|
||
BNE.S @BadPRAM ; -> no, run at full speed for now <H18>
|
||
|
||
MOVEQ #PmgrPramBase+PmgrPramRec.PmgrOtherFlags,D1 ; default to standard PRAM location <H7>
|
||
MOVE.L PowerManagerPtr(A1),D0 ; does this box have a PMgr primitives table? <H36><H37>
|
||
|
||
IF 0 THEN
|
||
BEQ.S @UseDefPRAM ; -> no, use the default location <H36>
|
||
MOVEA.L A1,A2 ; <H36><H37>
|
||
ADDA.L D0,A2 ; point to the primitives table for this box <H36>
|
||
ADDA.L PmgrPrimsRec.PrimInfoPtr(A2),A2 ; and then to the primitives info table <H7>
|
||
MOVE.B PrimInfoTbleRec.PrimPRAMBase(A2),D1 ; get the base Power Manager PRAM byte <H7>
|
||
ADDQ.B #PmgrPramRec.PmgrOtherFlags,D1 ; and adjust for the byte we want <H7>
|
||
ENDIF
|
||
|
||
@UseDefPRAM MOVEA.L A1,A0 ; point back to the DecoderInfo table <H37>
|
||
ADDA.L DecoderInfoPtr(A0),A0 ; <H37>
|
||
MOVEA.L DecoderInfo.VIA1Addr(A0),A2 ; point to the base of VIA1
|
||
BigBSR6 RdXByte,A0 ; read the desired econo-mode setting from PRAM
|
||
ANDI.B #(1<<EconoBit),D1 ; and mask off the econo-mode bit
|
||
@BadPRAM MOVE.L D4,D2 ; restore the decoder type
|
||
|
||
|
||
MOVEA.L A1,A0 ; point back to the DecoderInfo table <H37>
|
||
ADDA.L DecoderInfoPtr(A0),A0 ; one last time <H37>
|
||
|
||
; at this point:
|
||
; A0 - pointer to DecoderInfo table
|
||
; A1 - pointer to ProductInfo table
|
||
; D2 - decoder type
|
||
|
||
|
||
IF hasJAWS | hasNiagra THEN
|
||
;•••••••••••••••••••••••••••••••••••••••••••••• JAWS ••••••••••••••••••••••••••••••••••••••••••••••
|
||
SPIN_WAIT equ $40000 ; delay for power manager to hit reset <H23>
|
||
SPEED25MHZBIT equ 0 ; 1 = running at 25mhz
|
||
|
||
IF isUniversal THEN
|
||
cmp.b #Decoderkinds.NiagraDecoder,D2 ; Do we have a Niagra decoder? <H14>
|
||
beq.s @DoNiagra ; -> yes, go do it.. <H14>
|
||
cmp.b #Decoderkinds.JAWSDecoder,D2 ; Do we have a JAWS decoder ?
|
||
bne.s NotJaws ; -> no, do next one
|
||
ENDIF
|
||
|
||
IF hasJAWS THEN
|
||
@DoJaws MOVEA.L DecoderInfo.JAWSAddr(A0),A1 ; A1 = pointer to the base of the JAWS decoder <H19>
|
||
MOVE.L #JAWSGetCPUClock,D0 ; get the offset to the CPU clock frequency register
|
||
BTST #SPEED25MHZBIT,0(A1,D0.L) ; are we running at 25MHz?
|
||
BEQ.S @JAWSDone ; -> no, done
|
||
ENDIF
|
||
|
||
@DoNiagra MOVEA.L DecoderInfo.JAWSAddr(A0),A1 ; A1 = pointer to the base of the JAWS decoder <H19>
|
||
MOVEQ #(1<<EconoBit),D2 ; mask off the econo bit in the econo-mode register
|
||
AND.B JAWSEconoMode(A1),D2
|
||
CMP.B D1,D2 ; are we currently in the right mode?
|
||
BEQ.S @JAWSDone ; -> yes, done
|
||
MOVE.B D1,JAWSEconoMode(A1) ; stuff the new mode into the econo register
|
||
|
||
MOVE.W #(0<<8)+(resetCPU<<0),D3 ; data length=0, command=reset PMGR
|
||
BigBSR6 USTPMGRSendCommand,A2 ; reset the system
|
||
|
||
MOVE.L #SPIN_WAIT,D3 ; wait awhile for the PMGR to reset the system
|
||
@spin SUBQ.L #1,D3
|
||
BNE.S @spin
|
||
|
||
@JAWSDone ; <H23>
|
||
bra ExitEconoMode ; <H23>
|
||
NotJaws
|
||
ENDIF
|
||
|
||
|
||
IF hasMSC THEN
|
||
;•••••••••••••••••••••••••••••••••••••••••••••• MSC •••••••••••••••••••••••••••••••••••••••••••••••
|
||
IF isUniversal THEN
|
||
CMPI.B #DecoderKinds.MSCDecoder,D2 ; do we have a MSC decoder?
|
||
BNE NotMSC ; -> nope, bail
|
||
ENDIF
|
||
ORI.B #MSCDefConfig,D1 ; this sets 25Mhz mode by default
|
||
|
||
; <H45> D2 now has the value of the Econo Mode bit in PRAM. Yeager needs
|
||
; to make sure that this bit is never set, or it will break!
|
||
|
||
MOVEQ #$1F,D2 ; mask off the CPU ID
|
||
AND.W CPUIDValue(A1),D2 ;
|
||
BEQ.S @MSC33MHz ; is it a new Yeager MBT 040
|
||
CMP.W #16,D2 ; is it a Yeager (040)?
|
||
BEQ.S @MSC33MHz ; -> yes, do setup
|
||
AND.W #7,D2 ; mask off the CPU ID
|
||
CMP.W #5,D2 ; is it a 33MHz system (DB Lite)? <H38>
|
||
BEQ.S @MSC33MHz ; -> yes, do setup <H38>
|
||
CMP.W #2,D2 ; maybe it's a 33MHz Escher? <H38>
|
||
BEQ.S @MSC33MHz ; -> yes, do setup <H38>
|
||
|
||
BTST #EconoBit,D1 ; are we in going to run in econo-mode? <H15>
|
||
BNE.S @NotMSC33MHz ; -> yes, we'll be running at 16MHz regardless <H15>
|
||
|
||
@MSC33MHz BCLR #MSC25MHz,D1 ; setup the state machines to run at 33MHz <H10>
|
||
@NotMSC33MHz
|
||
MOVEA.L DecoderInfo.RBVAddr(A0),A1 ; point to the base of the MSC decoder
|
||
MOVEQ #(%11111000)-256,D2 ; mask off the RAM size information <H15>
|
||
AND.B MSCConfig(A1),D2 ; <H15>
|
||
OR.B D2,D1 ; and add it to the base configuration <H15>
|
||
MOVE.B D1,MSCConfig(A1) ; stuff the configuration into the register <H6>
|
||
|
||
MOVE.L #(0<<16)|(1<<8)|(SetModemInts<<0),D3 ; <H30>
|
||
BigBSR6 USTPmgrSendCommand,A2 ; turn off modem interrupts <H30>
|
||
|
||
;◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊ <H31>
|
||
;
|
||
; This is the nasty hack. When a DBLite is docked to a Gemini or DeskBar with an external SCSI
|
||
; hard disk connected and powered up, the SCC gets charged up a little bit and ends up in a weird
|
||
; state, usually generating level 4 interrupts. Normally we initialize the SCC later, but since
|
||
; the Docking Manager isn't initialized soon enough, as soon as interrupts are opened up, we get
|
||
; stuck in the level 4 interrupt handler (which is hopefully set up). This hack will talk to the
|
||
; Gemini/DeskBar hardware directly and reset the external SCC.
|
||
|
||
ROMSigAddr EQU $FEFFFFE4 ; where to find the ROM signature
|
||
ROMSigLo EQU 'Russ' ; and what it is
|
||
ROMSigHi EQU 'SWC!'
|
||
|
||
vscClockPwr EQU $FEE00021 ; VSC power control register
|
||
vscSCCclock EQU 1 ; 1=turn on SCC clock
|
||
vscSCCAddr EQU $FEE08000 ; SCC base address
|
||
NastyHack
|
||
If Not ForRomulator Then
|
||
MOVEA.L SP,A5 ; save the return address
|
||
BSET #beok,D7 ; allow bus errors
|
||
BSR6 @WhackSCC ; go whack the SCC (bad SCC! bad SCC! blah blah)
|
||
BCLR #beok,D7 ; disallow bus errors
|
||
Endif
|
||
BRA.S ExitEconoMode
|
||
|
||
@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
|
||
|
||
@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
|
||
|
||
@WhackSCC CMPI.L #ROMSigLo,ROMSigAddr ; is the signature in the config ROM?
|
||
BNE.S @NotGemini ; -> no, not the ROM we're looking for
|
||
CMPI.L #ROMSigHi,ROMSigAddr+4 ; ditto with the other part of the signature
|
||
BNE.S @NotGemini ; -> no, not the ROM we're looking for
|
||
|
||
BSET #vscSCCclock,vscClockPwr ; turn on clocks to the SCC
|
||
|
||
LEA vscSCCAddr,A0
|
||
LEA @InitBData,A2 ; point to channel B init data
|
||
MOVEQ #@InitAData-@InitBData,D1
|
||
LEA @ResumeB,A1
|
||
BRA.S @WriteSCC
|
||
@ResumeB ADDQ.W #ACtl,A0 ; point to channel A
|
||
MOVEQ #@WhackSCC-@InitAData,D1
|
||
LEA @ResumeA,A1
|
||
@WriteSCC MOVE.B (A0),D2 ; read to make sure the 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
|
||
JMP (A1)
|
||
|
||
@ResumeA BCLR #vscSCCclock,vscClockPwr ; turn off clocks to the SCC
|
||
@NotGemini RTS6
|
||
|
||
;◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊ <H31>
|
||
|
||
NotMSC
|
||
ENDIF
|
||
|
||
ExitEconoMode
|
||
MOVEA.L A7,A6 ; restore the return address <H23>
|
||
|
||
;________________________________________________________________________________________
|
||
; Routine: InitAndBlankScreen |
|
||
; V
|
||
; Input: a6 - return address
|
||
;
|
||
; Destroys: A0-A7,D0-D6
|
||
;
|
||
; Called by: BSR6 from StartInit.
|
||
;
|
||
; Function: initialize and blank the screen to meet timing requirements
|
||
;________________________________________________________________________________________
|
||
|
||
InitAndBlankScreen
|
||
IF hasNiagra | hasMSC THEN
|
||
movea.l a6,a7 ; save original return address
|
||
MOVEQ #0,D2 ;
|
||
BigBSR6 GetHardwareInfo,A0 ; figure out what we're running on
|
||
cmp.b #Decoderkinds.NiagraDecoder,D2 ; Do we have a Niagra decoder?
|
||
beq.s @BlankNiagra ; -> yes
|
||
cmpi.b #DecoderKinds.MSCDecoder,D2 ; do we have a MSC decoder?
|
||
bne @ExitInitAndBlank ; -> no, continue
|
||
|
||
IF hasMSC THEN ; <H29>
|
||
MOVEA.L DecoderInfo.RBVAddr(A0),A2 ; point to the base of the MSC <H29>
|
||
BSET #MSCLCDReset,MSCClkCntl(A2) ; turn on clocks to the GSC so we can program it<H29>
|
||
BRA.S @TestForGSC ; <H29>
|
||
ENDIF ; <H29>
|
||
|
||
IF hasNiagra THEN
|
||
; send command to power manager to blank the screen and delay before talking to the gsc
|
||
; D3- [data2] [data1] [length] [command]
|
||
; A0- pointer to DecoderInfo
|
||
; A6- return address
|
||
|
||
@BlankNiagra
|
||
MOVE.l #($E0<<0) | \ ; Write Pmgr Ram
|
||
(03<<8) | \ ; count 3, 2 address + 1 data
|
||
(00<<16) | \ ; addrH - $00xxH
|
||
($EA<<24),D3 ; addrL - $xxEA
|
||
BigBSR6 USTPMGRSendCommand,A2 ; reset the system
|
||
|
||
move.b #$0A,D3 ; port 4: d[2] = 0 (blank), d[0] = 1 adb inactive
|
||
BigBSR5 USTPMgrSendByte,A4 ; and send it
|
||
* bra.s @TestForGSC ; <H29>
|
||
ENDIF
|
||
|
||
; test for gsc chip
|
||
@TestForGSC MOVEA.L DecoderInfo.VDACAddr(A0),A0 ; point to base of gsc
|
||
movea.l a7,a5 ; save return address in case of bus error <H26>
|
||
bset.l #beok,d7 ; allow bus errors
|
||
bsr6 @checkforGSC ; check for gsc chip
|
||
bra @ExitInitAndBlank ; if not zero, buserror, no gsc, exit
|
||
; bne @ExitInitAndBlank ; if not zero, buserror, no gsc, exit
|
||
|
||
; initialize GSC early to meet hardware timing spec
|
||
@loadSetup
|
||
moveq.l #7,D0 ; mask off the display ID
|
||
And.b GSCPanelID(A0),D0 ; get the display id
|
||
|
||
MULU #(GSCPanelSkew-GSCPanelSetup+1)+(GSCDiag2-GSCDiag0+1),D0 ;
|
||
LEA @GSCInitTable,A2 ; point to the entry for this display
|
||
ADDA.L D0,A2
|
||
|
||
ADDQ.W #GSCPanelSetup,A0 ; point to the first register to blast <H25>
|
||
MOVE.L (A2)+,(A0)+ ; initialize the main display registers <H25>
|
||
MOVE.L (A2)+,(A0)+ ; <H25>
|
||
LEA GSCDiag0-GSCPanelSkew-1(A0),A0 ; point to the diagnostic registers <H25>
|
||
MOVE.B (A2)+,(A0)+ ; and initialize them too <H25>
|
||
MOVE.W (A2)+,(A0)+ ; <H25>
|
||
bra.s @ExitInitAndBlank ; done
|
||
|
||
@checkforGSC
|
||
move.b GSCPanelID(A0),D0 ; try reading a register
|
||
moveq #0,d0 ; set CC to Equal, buserr will return not Equal <H26>
|
||
rts6
|
||
|
||
|
||
; GSC initialization table. Each entry is based on the LCD panel ID.
|
||
;
|
||
; panel gray poly panel ACD refresh blank panel
|
||
; setup scale adjust adjust clock rate shade skew diag0 diag1 diag2
|
||
@GSCInitTable
|
||
DC.B $10, $00, $64, $00, $80, $02, $00, $A0, $00, $00, $03 ; ID=0 TFT1Bit <H27>
|
||
DC.B $12, $00, $64, $00, $80, $02, $00, $FF, $00, $00, $03 ; ID=1 TFT3Bit <H27>
|
||
DC.B $10, $00, $64, $00, $80, $02, $00, $FF, $00, $00, $03 ; ID=2 TFT4Bit <H27>
|
||
DC.B $10, $00, $64, $00, $80, $02, $00, $A0, $00, $00, $03 ; ID=3 NotAssignedTFT <H27>
|
||
DC.B $10, $00, $64, $00, $80, $05, $00, $A0, $00, $00, $03 ; ID=4 NotAssignedSTN <H27>
|
||
DC.B $10, $00, $64, $00, $80, $05, $00, $A0, $00, $00, $03 ; ID=5 TimSTN <H27>
|
||
DC.B $10, $00, $63, $00, $80, $05, $00, $9C, $00, $00, $03 ; ID=6 DBLiteSTN <H29>
|
||
DC.B $10, $00, $64, $00, $80, $05, $00, $A0, $00, $00, $03 ; ID=7 No Display <H27>
|
||
|
||
|
||
@ExitInitAndBlank
|
||
bclr.l #beok,d7 ; disallow bus errors
|
||
movea.l a7,a6 ; restore original return address
|
||
|
||
ENDIF ; {hasNiagra | hasMSC}
|
||
|
||
;________________________________________________________________________________________
|
||
; Routine: Exit
|
||
;________________________________________________________________________________________ ; V
|
||
NonPwrMgr RTS6 ; return to start init <H23> ; All done
|
||
|
||
|
||
;•••••••••••••••••••••••••••••••••••• End of Misc. •••••••••••••••••••••••••••••••••••••••••••••••••
|
||
|
||
|
||
;•••••••••••••••••••••••••••••••• Public Power Manager •••••••••••••••••••••••••••••••••••••••••••••
|
||
;
|
||
; Contains:
|
||
;
|
||
;________________________________________________________________________________________
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: PowerMgrDispatch (trap $A09E)
|
||
;
|
||
; Inputs: D0 - selector
|
||
;
|
||
; Outputs: D0 - selector result, or error code if bad selector
|
||
;
|
||
; Trashes: varies by selector
|
||
;
|
||
; Function: This is the Power Manager's public dispatch trap, which provides a variety of
|
||
; miscellaneous functions to the public, hackers, etc.
|
||
;
|
||
; NOTE: The offset-based dispatch table is copied into RAM and converted to
|
||
; absolute addresses by InitPMgrVars.
|
||
;________________________________________________________________________________________
|
||
|
||
PowerMgrDispatch
|
||
MOVEA.L PMgrBase,A2 ; point to the Power Manager's globals
|
||
MOVE.L vPublicDispatch(A2),A1 ; and then to the public dispatch table
|
||
CMP.W -2(A1),D0 ; is the selector in range?
|
||
BHS.S @OutOfRange ; -> no, bail with an error
|
||
MOVEA.L 0(A1,D0.W*4),A1 ; point to the routine <H93>
|
||
JMP (A1) ; and call it
|
||
|
||
@OutOfRange MOVEQ #paramErr,D0 ; abort and return error
|
||
RTS
|
||
|
||
|
||
ALIGN 4
|
||
|
||
DC.W 0 ; flags
|
||
DC.W (PwrMgrDispEnd-PwrMgrDispVects)/4 ; number of table entries
|
||
PwrMgrDispVects
|
||
DC.L PMSelectorCount-PwrMgrDispVects ; [ 0] return the number of selectors supported
|
||
DC.L PMFeatures-PwrMgrDispVects ; [ 1] return bitmap of Power Manager features
|
||
DC.L GetSleepTimeout-PwrMgrDispVects ; [ 2] get the sleep timeout
|
||
DC.L SetSleepTimeout-PwrMgrDispVects ; [ 3] set the sleep timeout
|
||
DC.L GetHardDiskTimeout-PwrMgrDispVects ; [ 4] get the hard disk spindown timeout
|
||
DC.L SetHardDiskTimeout-PwrMgrDispVects ; [ 5] set the hard disk spindown timeout
|
||
DC.L HardDiskPowered-PwrMgrDispVects ; [ 6] returns true if hard disk is powered up
|
||
DC.L SpinDownHardDisk-PwrMgrDispVects ; [ 7] spin down the hard disk
|
||
DC.L IsSpindownDisabled-PwrMgrDispVects ; [ 8] returns whether or not spindown is disabled
|
||
DC.L SetSpindownDisable-PwrMgrDispVects ; [ 9] enables/disables hard disk spindown
|
||
DC.L HardDiskQInstall-PwrMgrDispVects ; [10] add element to HD queue
|
||
DC.L HardDiskQRemove-PwrMgrDispVects ; [11] remove element from HD queue
|
||
DC.L ScaledBattery-PwrMgrDispVects ; [12] return the scaled battery level
|
||
DC.L AutoSleepControl-PwrMgrDispVects ; [13] enables/disables auto sleep
|
||
DC.L GetIntModemInfo-PwrMgrDispVects ; [14] return information about an internal modem
|
||
DC.L SetIntModemState-PwrMgrDispVects ; [15] sets the state of the internal modem
|
||
DC.L MaximumProcessorSpeed-PwrMgrDispVects ; [16] return maximum processor speed
|
||
DC.L CurrentProcessorSpeed-PwrMgrDispVects ; [17] return current processor speed
|
||
DC.L FullProcessorSpeed-PwrMgrDispVects ; [18] returns true if processor running at full speed
|
||
DC.L SetProcessorSpeed-PwrMgrDispVects ; [19] set full/reduced processor speed
|
||
DC.L GetSCSIDiskModeAddress-PwrMgrDispVects ; [20] get SCSI Disk Mode HD address
|
||
DC.L SetSCSIDiskModeAddress-PwrMgrDispVects ; [21] set SCSI Disk Mode HD address
|
||
DC.L GetWakeupTimer-PwrMgrDispVects ; [22] get wakeup time
|
||
DC.L SetWakeupTimer-PwrMgrDispVects ; [23] set wakeup time
|
||
DC.L GetProcessorCycling-PwrMgrDispVects ; [24] get processor cycling state
|
||
DC.L SetProcessorCycling-PwrMgrDispVects ; [25] set processor cycling state
|
||
DC.L BatteryCount-PwrMgrDispVects ; [26] returns number of internal batteries
|
||
DC.L GetBatteryVoltage-PwrMgrDispVects ; [27] return absolute battery voltage
|
||
DC.L GetBatteryTimes-PwrMgrDispVects ; [28] returns information about battery times
|
||
DC.L GetDimTimeout-PwrMgrDispVects ; [29] get the dimming timeout
|
||
DC.L SetDimTimeout-PwrMgrDispVects ; [30] set the dimming timeout
|
||
DC.L DimControl-PwrMgrDispVects ; [31] enables/disables dimming
|
||
DC.L IsDimmingDisabled-PwrMgrDispVects ; [32] returns whether or not dimming is disabled
|
||
DC.L IsAutoSlpDisabled-PwrMgrDispVects ; [33] returns whether or not autosleep is disabled
|
||
PwrMgrDispEnd
|
||
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: PMSelectorCount (PowerMgrDispatch selector #0)
|
||
;
|
||
; Inputs: A2 - pointer to Power Manager globals
|
||
;
|
||
; Outputs: D0 - number of selectors
|
||
;
|
||
; Trashes: A0
|
||
;
|
||
; Function: returns the number of selectors so users can determine what selectors are
|
||
; supported
|
||
;________________________________________________________________________________________
|
||
|
||
PMSelectorCount
|
||
MOVEQ #0,D0
|
||
MOVE.L vPublicDispatch(A2),A0 ; point to the public dispatch table
|
||
MOVE.W -(A0),D0 ; and get the number of selectors
|
||
RTS
|
||
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: PMFeatures (PowerMgrDispatch selector #1)
|
||
;
|
||
; Inputs: A2 - pointer to Power Manager globals
|
||
;
|
||
; Outputs: D0 - bitmap of supported features
|
||
;
|
||
; Trashes: none
|
||
;
|
||
; Function: returns a bitmap containing bits describing which software/hardware
|
||
; features are supported on this machine
|
||
;________________________________________________________________________________________
|
||
|
||
PMFeatures
|
||
LoadTbl PrimInfoTblPtr,A2,A0 ; get pointer to Info
|
||
MOVE.L PrimPubFeatures(A0),D0 ; get the features bits
|
||
RTS
|
||
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: GetSleepTimeout (PowerMgrDispatch selector #2)
|
||
;
|
||
; Inputs: A2 - pointer to Power Manager globals
|
||
;
|
||
; Outputs: D0 - sleep timeout (number of 15 second intervals)
|
||
;
|
||
; Trashes: A0
|
||
;
|
||
; Function: returns the current sleep timeout time
|
||
;________________________________________________________________________________________
|
||
|
||
GetSleepTimeout
|
||
MOVEQ #SlpTimeOut,D0 ; which byte to read
|
||
BRA.S ReadPMgrPRAM ; go read and return the value
|
||
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: SetSleepTimeout (PowerMgrDispatch selector #3)
|
||
;
|
||
; Inputs: A2 - pointer to Power Manager globals
|
||
; D0 - high word: sleep time to set (number of 15 second intervals)
|
||
;
|
||
; Outputs: D0 - result code (always zero)
|
||
;
|
||
; Trashes: D1, A0
|
||
;
|
||
; Function: sets the current sleep timeout
|
||
;________________________________________________________________________________________
|
||
|
||
SetSleepTimeout
|
||
SWAP D0 ; get the new value
|
||
TST.B D0 ; is it zero?
|
||
BNE.S @NotZero ; -> no
|
||
MOVEQ #DfltSlpTime,D0 ; yes, set it to the default
|
||
@NotZero
|
||
MOVE.B D0,SleepTime(A2) ; save it
|
||
MOVE.B D0,D1
|
||
MOVEQ #SlpTimeOut,D0 ; where to put it
|
||
BRA.S WritePMgrPRAM ; go write it out
|
||
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: GetHardDiskTimeout (PowerMgrDispatch selector #4)
|
||
;
|
||
; Inputs: A2 - pointer to Power Manager globals
|
||
;
|
||
; Outputs: D0 - hard disk time (number of 15 second intervals)
|
||
;
|
||
; Trashes: A0
|
||
;
|
||
; Function: returns the amount of time the system will wait after the last hard disk
|
||
; access before shutting down power to the hard disk
|
||
;________________________________________________________________________________________
|
||
|
||
GetHardDiskTimeout
|
||
MOVEQ #HDTimeOut,D0 ; which byte to read
|
||
|
||
; Inputs: D0 - PRAM address (upper word must be zero)
|
||
;
|
||
; Outputs: D0 - byte read from PRAM
|
||
;
|
||
; Trashes: D0
|
||
|
||
ReadPMgrPRAM
|
||
ADD.B PRAMBase(A2),D0 ; get the absolute PRAM address
|
||
SWAP D0
|
||
ADDQ.W #1,D0 ; one byte
|
||
SWAP D0
|
||
CLR.W -(SP) ; make space for a buffer on the stack
|
||
MOVEA.L SP,A0 ; and point to it
|
||
_ReadXPRAM ; read the byte
|
||
MOVEQ #0,D0
|
||
MOVE.B (SP)+,D0 ; and return it in D0
|
||
RTS
|
||
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: SetHardDiskTimeout (PowerMgrDispatch selector #5)
|
||
;
|
||
; Inputs: A2 - pointer to Power Manager globals
|
||
; D0 - high word: hard disk time to set (number of 15 second intervals)
|
||
;
|
||
; Outputs: D0 - result code (always zero)
|
||
;
|
||
; Trashes: D1, A0
|
||
;
|
||
; Function: sets the amount of time the system will wait after the last hard disk
|
||
; access before shutting down power to the hard disk
|
||
;________________________________________________________________________________________
|
||
|
||
SetHardDiskTimeout
|
||
SWAP D0 ; get the new value
|
||
TST.B D0 ; is it zero?
|
||
BNE.S @NotZero ; -> no
|
||
MOVEQ #DfltHDTime,D0 ; yes, set it to the default
|
||
@NotZero
|
||
MOVE.B D0,HDTime(A2) ; save it
|
||
MOVE.B D0,D1
|
||
MOVEQ #HDTimeOut,D0 ; where to put it
|
||
|
||
; Inputs: D0 - PRAM address (upper word must be zero)
|
||
; D1 - byte to write
|
||
;
|
||
; Outputs: D0 - none
|
||
;
|
||
; Trashes: D0
|
||
|
||
WritePMgrPRAM
|
||
MOVE.B D1,-(SP) ; push the byte to write
|
||
MOVEA.L SP,A0 ; and point to it
|
||
ADD.B PRAMBase(A2),D0 ; get the absolute PRAM address
|
||
SWAP D0
|
||
ADDQ.W #1,D0 ; one byte
|
||
SWAP D0
|
||
_WriteXPRAM ; write the byte
|
||
ADDQ.W #2,SP
|
||
ST TODirtyFlag(A2) ; force an update of the new values
|
||
RTS
|
||
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: HardDiskPowered (PowerMgrDispatch selector #6)
|
||
;
|
||
; Inputs: A2 - pointer to Power Manager globals
|
||
;
|
||
; Outputs: D0 - 1=hard disk spinning, 0=hard disk powered down
|
||
;
|
||
; Trashes: A2
|
||
;
|
||
; Function: spins down the internal hard disk immediately
|
||
;________________________________________________________________________________________
|
||
|
||
HardDiskPowered
|
||
MOVEQ #0,D0 ; zero-extend the result
|
||
TST.L LastHd(A2) ; is the hard disk powered up?
|
||
SNE D0 ; $FF if so, $00 if not
|
||
NEG.B D0 ; 1 if so, 0 if not
|
||
RTS
|
||
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: SpinDownHardDisk (PowerMgrDispatch selector #7)
|
||
;
|
||
; Inputs: A2 - pointer to Power Manager globals
|
||
;
|
||
; Outputs: D0 - result code (always zero)
|
||
;
|
||
; Trashes: A0
|
||
;
|
||
; Function: spins down the internal hard disk immediately
|
||
;________________________________________________________________________________________
|
||
|
||
SpinDownHardDisk
|
||
_SpinDownHardDrive
|
||
MOVEQ #0,D0
|
||
@Done RTS
|
||
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: IsSpindownDisabled (PowerMgrDispatch selector #8)
|
||
;
|
||
; Inputs: A2 - pointer to Power Manager globals
|
||
;
|
||
; Outputs: D0 - boolean: 1=disabled, 0=enabled
|
||
;
|
||
; Trashes: none
|
||
;
|
||
; Function: returns a boolean telling whether hard disk spindown is enabled or disabled
|
||
;________________________________________________________________________________________
|
||
|
||
IsSpindownDisabled
|
||
MOVEQ #0,D0
|
||
IF HDSpinDownDisable=7 THEN
|
||
TST.B PmgrFlags2(A2)
|
||
SMI D0
|
||
ELSE
|
||
BTST #HDSpinDownDisable,PmgrFlags2(A2)
|
||
SNE D0
|
||
ENDIF
|
||
NEG.B D0
|
||
RTS
|
||
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: SetSpindownDisable (PowerMgrDispatch selector #9)
|
||
;
|
||
; Inputs: A2 - pointer to Power Manager globals
|
||
; D0 - high word: 1=disable, 0=enable
|
||
;
|
||
; Outputs: D0 - result code (always zero)
|
||
;
|
||
; Trashes: none
|
||
;
|
||
; Function: enables or disables hard disk spindown
|
||
;________________________________________________________________________________________
|
||
|
||
SetSpindownDisable
|
||
SWAP D0
|
||
TST.B D0 ; is it to be disabled?
|
||
BNE.S @disable ; -> yes
|
||
BCLR #HDSpinDownDisable,PmgrFlags2(A2)
|
||
BRA.S @Done ; no, enable it
|
||
|
||
@disable BSET #HDSpinDownDisable,PmgrFlags2(A2)
|
||
@Done MOVEQ #0,D0
|
||
RTS
|
||
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: HardDiskQInstall (PowerMgrDispatch selector #10)
|
||
;
|
||
; Inputs: A0 - pointer to queue element
|
||
; A2 - pointer to Power Manager globals
|
||
;
|
||
; Outputs: D0 - result code (always zero)
|
||
;
|
||
; Trashes: A0, A1, D0
|
||
;
|
||
; Function: adds an element to the hard disk spindown notification queue
|
||
;________________________________________________________________________________________
|
||
|
||
HardDiskQInstall
|
||
MOVEQ #slpTypeErr,D0 ; assume bad queue type
|
||
CMP.W #HDPwrQType,hdQType(A0) ; is it?
|
||
BNE.S @Done ; -> yes, bail
|
||
|
||
LEA HardDiskQHdr(A2),A1 ; point to the hard disk queue
|
||
_Enqueue ; and add the element to the queue
|
||
MOVEQ #0,D0 ; <H87>
|
||
@Done RTS
|
||
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: HardDiskQRemove (PowerMgrDispatch selector #11)
|
||
;
|
||
; Inputs: A0 - pointer to queue element
|
||
; A2 - pointer to Power Manager globals
|
||
;
|
||
; Outputs: D0 - result code
|
||
;
|
||
; Trashes: A0, A1, D0
|
||
;
|
||
; Function: removes an element from the hard disk spindown notification queue
|
||
;________________________________________________________________________________________
|
||
|
||
HardDiskQRemove
|
||
MOVEQ #slpTypeErr,D0 ; assume bad queue type
|
||
CMP.W #HDPwrQType,hdQType(A0) ; is it?
|
||
BNE.S @Done ; -> yes, bail
|
||
|
||
LEA HardDiskQHdr(A2),A1 ; point to the hard disk queue
|
||
_Dequeue ; and remove the element from the queue
|
||
MOVEQ #0,D0 ; <H87>
|
||
@Done RTS
|
||
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: AutoSleepControl (PowerMgrDispatch selector #13)
|
||
;
|
||
; Inputs: A2 - pointer to Power Manager globals
|
||
; D0 - high word: 0=disable sleep, 1=enable sleep
|
||
;
|
||
; Outputs: D0 - result code (always zero)
|
||
;
|
||
; Trashes: A0
|
||
;
|
||
; Function: Disables or enables auto sleep by incrementing or decrementing the auto sleep
|
||
; semaphone. Note that since the semaphore supports multiple ‘levels’, if it's
|
||
; been disabled n times in a row, it needs to be enabled n times before auto
|
||
; sleep will really be enabled.
|
||
;________________________________________________________________________________________
|
||
|
||
AutoSleepControl
|
||
SWAP D0 ; get the flag <H85>
|
||
TST.W D0 ; enable or disable? <H85>
|
||
BEQ.S @disable ; -> disable <H85>
|
||
SUBQ.B #1,AutoSlpDisable(A2) ; ‘pop’ a level towards sleep enabled <H85>
|
||
BGE.S @done ; -> haven't rolled over <H85>
|
||
CLR.B AutoSlpDisable(A2) ; pin the semaphore a zero <H85>
|
||
BRA.S @done ; <H85>
|
||
|
||
@disable ADDQ.B #1,AutoSlpDisable(A2) ; set the semaphore to >0 (‘push’ a level) <H85>
|
||
BHI.S @done ; -> we're done if it's still >0 <H85>
|
||
SUBQ.B #1,AutoSlpDisable(A2) ; it rolled over, so make it >0 again <H85>
|
||
@done MOVEQ #0,D0 ; <H85>
|
||
RTS ; <H85>
|
||
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: GetIntModemInfo (PowerMgrDispatch selector #14)
|
||
;
|
||
; Inputs: A2 - pointer to Power Manager globals
|
||
;
|
||
; Outputs: D0 - bitmap of internal modem info:
|
||
; 0: 1=modem installed
|
||
; 1: 1=modem ring detected
|
||
; 2: 1=modem off hook
|
||
; 3: 1=wakeup on ring is enabled
|
||
; 4: 1=external modem selected
|
||
; 15-3: 0=reserved
|
||
; 31-16: modem type
|
||
; -1 = modem installed but type unknown
|
||
; 0 = no modem installed
|
||
; 1 = original serial modem
|
||
; 2 = Rockwell data pump modem (RC144DPL)
|
||
; 3 = Rockwell data pump modem (RC144DPL) + 6805 controller
|
||
;
|
||
; Trashes: A0
|
||
;
|
||
; Function: returns a bitmap of information about the internal modem, if any
|
||
;________________________________________________________________________________________
|
||
|
||
GetIntModemInfo
|
||
CLR.W -(SP) ; allocate a buffer for the result
|
||
MOVE.L SP,-(SP) ; pmRBuffer
|
||
MOVE.L (SP),-(SP) ; pmSBuffer
|
||
CLR.W -(SP) ; pmLength
|
||
MOVE.W #modemRead,-(SP) ; pmCommand
|
||
MOVEA.L SP,A0 ; point to the parameter block
|
||
_PMgrOp ; get the modem info
|
||
LEA pmRBuffer+4(SP),SP ; toss the parameter block
|
||
|
||
MOVEQ #PmgrStatusFlags,D0 ; read the byte containing modem status <H83>
|
||
BSR ReadPMgrPRAM ; <H83>
|
||
MOVEQ #1<<UseIntrnlModem,D1 ; mask off the bit, <H83>
|
||
AND.B D0,D1 ; <H83>
|
||
LSL.B #extModemSelected-UseIntrnlModem,D1 ; and shift it into position <H95>
|
||
MOVEQ #(1<<RingWakeEnable)|(1<<ModemInstalled)|(1<<RingDetect)|(1<<ModemHook),D0 ; <H95>
|
||
AND.B (SP)+,D0 ; mask off the bits we want, <H83>
|
||
ROR.B #ModemInstalled-hasInternalModem,D0 ; <H94>
|
||
; and shift them into position <H83>
|
||
BCLR #8-(ModemInstalled-hasInternalModem)+RingWakeEnable,D0 ; <H94>
|
||
BEQ.S @NoWake ; -> the ‘wakeup on ring’ bit isn't set <H94>
|
||
ADDQ.B #1<<intModemRingWakeEnb,D0 ; set the bit in the output <H94>
|
||
@NoWake OR.B D1,D0 ; combine all the bits so far <H83>
|
||
|
||
BTST #hasInternalModem,D0 ; is an internal modem installed? <H93>
|
||
BEQ.S @Done ; -> no, we're done <H93>
|
||
MOVE.L D0,-(SP) ; save the rest of the information <H93>
|
||
BSR ModemTypeProc ; find out what kind of modem is installed <H93>
|
||
SWAP D0 ; and move it into bits 16-31 <H93>
|
||
CLR.W D0 ; (make sure we don't have any stray bits) <H93>
|
||
OR.L (SP)+,D0 ; then OR in the rest of the info <H93>
|
||
@Done RTS
|
||
|
||
|
||
;________________________________________________________________________________________ <H95>
|
||
;
|
||
; Routine: SetIntModemState (PowerMgrDispatch selector #15)
|
||
;
|
||
; Inputs: A2 - pointer to Power Manager globals
|
||
; D0 - high word: bitmap of bits to set or clear
|
||
; 18: 1=wakeup on ring is enabled if bit 31=1, or disabled if bit 31=0
|
||
; 19: 1=external modem selected if bit 31=1, or external if bit 31=0
|
||
; 31: 1=set all other 1-bits, 0=clear all other 1-bits
|
||
;
|
||
;
|
||
; Outputs: D0 - result code (always zero)
|
||
;
|
||
; Trashes: A0
|
||
;
|
||
; Function: Configures some of the state information for the internal modem.
|
||
;________________________________________________________________________________________
|
||
|
||
SetIntModemState
|
||
SWAP D0 ; get the flags
|
||
BTST #intModemRingWakeEnb,D0 ; do we need to update ‘wakeup on ring’?
|
||
BEQ.S @NoWake ; -> nope
|
||
LoadTbl PrimInfoTblPtr,A2,A0
|
||
MOVE.L PrimPubFeatures(A0),D1 ; does this machine support ‘wakeup on ring’?
|
||
BTST #canWakeupOnRing,D1
|
||
BEQ.S @NoWake ; -> no, skip it
|
||
|
||
MOVE.W D0,-(SP) ; save the flags
|
||
SMI D0 ; $FF=enabled, $00=disabled
|
||
MOVEQ #1<<RingWakeEnable,D1 ; mask off the ‘wakeup on ring’ bit
|
||
AND.L D0,D1
|
||
|
||
CLR.W -(SP) ; allocate a buffer for the result
|
||
MOVE.L SP,-(SP) ; pmRBuffer
|
||
MOVE.L (SP),-(SP) ; pmSBuffer
|
||
CLR.W -(SP) ; pmLength
|
||
MOVE.W #modemRead,-(SP) ; pmCommand
|
||
MOVEA.L SP,A0 ; point to the parameter block
|
||
_PMgrOp ; get the modem info
|
||
|
||
ANDI.B #~(1<<RingWakeEnable),pmRBuffer+4(SP) ; mask out the ‘wakeup on ring’ bit
|
||
OR.B D1,pmRBuffer+4(SP) ; and OR in the new value
|
||
MOVE.W #modemSet,pmCommand(SP)
|
||
_PMgrOp ; write it back out
|
||
LEA pmRBuffer+4(SP),SP ; toss the parameter block
|
||
|
||
MOVE.W (SP)+,D0 ; get the flags back
|
||
|
||
@NoWake BTST #extModemSelected,D0 ; do we need to update internal/external modem?
|
||
BEQ.S @Done ; -> nope, all done
|
||
|
||
TST.W D0 ; test for zero/non-zero
|
||
SMI -(SP) ; push $00=internal/$FF=external on stack
|
||
|
||
MOVEQ #PmgrStatusFlags,D0 ; read the byte containing modem status
|
||
BSR ReadPMgrPRAM
|
||
|
||
MOVEQ #~(1<<UseIntrnlModem),D1 ; mask off everything but the modem bit
|
||
AND.B D0,D1
|
||
MOVEQ #1<<UseIntrnlModem,D0 ; mask off the passed in flag
|
||
AND.B (SP)+,D0
|
||
OR.B D0,D1 ; and OR it in with the other bits
|
||
|
||
MOVE.B D1,SleepFlags(A2) ; save it
|
||
MOVEQ #PmgrStatusFlags,D0 ; write the byte containing modem status back out
|
||
BRA WritePMgrPRAM
|
||
|
||
@Done RTS
|
||
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: MaximumProcessorSpeed (PowerMgrDispatch selector #16)
|
||
;
|
||
; Inputs: A2 - pointer to Power Manager globals
|
||
;
|
||
; Outputs: D0 - processor speed
|
||
;
|
||
; Trashes: D1, A0
|
||
;
|
||
; Function: returns the maximum processor speed, in MHz
|
||
;________________________________________________________________________________________
|
||
|
||
MaximumProcessorSpeed
|
||
MOVEQ #CPUSpeedDisp,D0 ; get the current/max CPU speed
|
||
_PowerDispatch
|
||
CLR.W D0 ; clear the current speed
|
||
SWAP D0 ; and move the max speed into the lower word
|
||
RTS
|
||
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: CurrentProcessorSpeed (PowerMgrDispatch selector #17)
|
||
;
|
||
; Inputs: A2 - pointer to Power Manager globals
|
||
;
|
||
; Outputs: D0 - processor speed
|
||
;
|
||
; Trashes: D1, A0
|
||
;
|
||
; Function: returns the current processor speed, in MHz
|
||
;________________________________________________________________________________________
|
||
|
||
CurrentProcessorSpeed
|
||
MOVEQ #CPUSpeedDisp,D0 ; get the current/max CPU speed
|
||
_PowerDispatch
|
||
EXT.L D0 ; clear the maximum speed speed
|
||
RTS
|
||
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: FullProcessorSpeed (PowerMgrDispatch selector #18)
|
||
;
|
||
; Inputs: A2 - pointer to Power Manager globals
|
||
;
|
||
; Outputs: D0 - boolean: 1=full speed, 0=reduced speed
|
||
;
|
||
; Trashes: D1, A0
|
||
;
|
||
; Function: returns a boolean indicating whether the CPU will start up at full or
|
||
; reduced speed
|
||
;________________________________________________________________________________________
|
||
|
||
FullProcessorSpeed
|
||
MOVEQ #1,D0 ; assume full speed <H92>
|
||
LoadTbl PrimInfoTblPtr,A2,A0
|
||
MOVEQ #1<<hasReducedSpeed,D1 ; is reduced speed supported? <H92>
|
||
AND.L PrimPubFeatures(A0),D1 ; <H92>
|
||
BEQ.S @Done ; -> no, we're done <H92>
|
||
|
||
MOVEQ #PmgrOtherFlags,D0 ; read the byte containing the CPU speed bit
|
||
BSR.S ReadPMgrPRAM
|
||
IF EconoBit≠0 THEN
|
||
LSR.B #EconoBit,D0 ; shift the bit into bit zero
|
||
ENDIF
|
||
MOVEQ #1,D1
|
||
EOR.B D1,D0 ; invert the bit so true=full speed
|
||
AND.B D1,D0 ; and mask off the bit
|
||
@Done RTS
|
||
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: SetProcessorSpeed (PowerMgrDispatch selector #19)
|
||
;
|
||
; Inputs: A2 - pointer to Power Manager globals
|
||
; D0 - high word: 1=full speed, 0=half speed
|
||
;
|
||
; Outputs: D0 - boolean: true=speed was changed, false=only PRAM was changed
|
||
;
|
||
; Trashes: D1, D2, A0, A1, A2
|
||
;
|
||
; Function: Updates PRAM to reflect the desired CPU speed on the next restart. If the
|
||
; machine supports dynamic speed switching, the hardware will be whacked to
|
||
; change the speed, the low-mem timing constants (TimeDBRA, etc.) will be
|
||
; updated, and the AppleTalk Transition Queue will be run to notify anyone
|
||
; who cares that they need to recalculate their timing parameters.
|
||
;________________________________________________________________________________________
|
||
|
||
ATQEntry RECORD 0,INCREMENT
|
||
qLink DS.L 1 ; pointer to next queue entry
|
||
qType DS.W 1 ; queue type
|
||
CallAddr DS.L 1 ; pointer to routine to be called
|
||
ENDR
|
||
|
||
ATTransSpeedChange EQU 'sped' ; event = speed change
|
||
|
||
SetProcessorSpeed
|
||
SWAP D0 ; get the boolean,
|
||
MOVEQ #1,D1
|
||
EOR.B D1,D0 ; invert it so true=reduced speed,
|
||
AND.B D0,D1 ; mask it off to a single bit,
|
||
IF EconoBit=1 THEN
|
||
ADD.B D1,D1 ; and then shift it into the correct bit position
|
||
ELSEIF EconoBit>1
|
||
LSL.B #EconoBit,D1 ; and then shift it into the correct bit position
|
||
ENDIF
|
||
|
||
MOVEQ #1,D0 ; assume full speed <H92>
|
||
LoadTbl PrimInfoTblPtr,A2,A0
|
||
MOVEQ #1<<hasReducedSpeed,D2 ; is reduced speed supported? <H92>
|
||
AND.L PrimPubFeatures(A0),D2 ; <H92>
|
||
BEQ @Done ; -> no, we're done <H92>
|
||
|
||
; update the setting in PRAM
|
||
|
||
MOVEQ #PmgrOtherFlags,D0 ; read the byte containing the CPU speed bit
|
||
BSR.S ReadPMgrPRAM
|
||
MOVE.B D0,D2
|
||
ANDI.B #~(1<<EconoBit),D0 ; mask out the econo-mode bit
|
||
OR.B D0,D1 ; and insert the new value into the byte
|
||
MOVEQ #0,D0
|
||
CMP.B D2,D1 ; will the speed change?
|
||
BEQ @Done ; -> no, just exit
|
||
MOVEQ #PmgrOtherFlags,D0 ; yes, write the PRAM byte back out
|
||
BSR.S WritePMgrPRAM
|
||
|
||
MOVEQ #1<<EconoBit,D0 ; mask off the econo-mode bit
|
||
AND.W D0,D1
|
||
|
||
; change the speed if it can be done dynamically
|
||
|
||
LoadTbl PrimInfoTblPtr,A2,A0
|
||
MOVEQ #1<<dynamicSpeedChange,D0 ; is dynamic speed change supported? <H90>
|
||
AND.L PrimPubFeatures(A0),D0 ; <H90>
|
||
BEQ.S @Done ; -> no, we're done <H90>
|
||
|
||
MOVE.W D1,-(SP) ; (save D1 across the call)
|
||
JsrRoutine SpeedChangePtr,A2,A0 ; and go do the switch
|
||
MOVE.W (SP)+,D1 ; (restore D1)
|
||
TST.W D0 ; did we do the speed switch?
|
||
BEQ.S @Done ; -> no, we're done
|
||
|
||
MOVEQ #CPUSpeedDisp,D0 ; get the current CPU speed
|
||
_PowerDispatch
|
||
MOVE.B D0,saveSpeedo(A0) ; and update speedo for people using IdleRead
|
||
|
||
; setup new timing constants for the TimeDBRA low-mems
|
||
|
||
LSL.W #3-EconoBit,D1 ; convert D1 to an index (0 or 8)
|
||
LEA fullSpeedDBRAs(A2),A1 ; point to the correct table
|
||
ADDA.W D1,A1
|
||
MOVE.W (A1)+,TimeDBRA ; copy the timing constants to low mem
|
||
MOVE.W (A1)+,TimeSCCDB
|
||
MOVE.W (A1)+,TimeSCSIDB
|
||
MOVE.W (A1)+,TimeVIADB
|
||
|
||
; run the AppleTalk transition queue
|
||
|
||
MOVE.L #gestaltAppleTalkVersion,D0 ; get the version of AppleTalk
|
||
_Gestalt
|
||
BNE.S @NoATalk ; -> error means it's not installed
|
||
MOVE.L A0,D0 ; get the AppleTalk version
|
||
BEQ.S @NoATalk ; -> zero means AppleTalk is turned off
|
||
|
||
MOVEQ #25,D0 ; get a pointer to the transition queue
|
||
MOVEA.L AtalkHk2,A0
|
||
JSR LapMgrCall(A0)
|
||
LEA qHead(A1),A2 ; point to the head of the queue
|
||
BRA.S @StartQueue
|
||
|
||
@NextQueue MOVE.L D0,A2 ; point to the queue element
|
||
|
||
MOVEM.L D3-D7/A2-A6,-(SP) ; save registers cuz apparently some procs do trash them
|
||
|
||
CLR.L -(SP) ; no routine-specific parameters
|
||
MOVE.L A2,-(SP) ; *ATQEntry
|
||
PEA ATTransSpeedChange ; selector = speed change
|
||
MOVEA.L ATQEntry.CallAddr(A2),A0 ; call the transition queue element's routine
|
||
JSR (A0)
|
||
LEA 4+4+4(SP),SP ; toss the parameters
|
||
|
||
MOVEM.L (SP)+,D3-D7/A2-A6
|
||
|
||
@StartQueue MOVE.L qLink(A2),D0 ; point to the next queue element; end of the queue?
|
||
BNE.S @NextQueue ; -> no, keep looping
|
||
@NoATalk MOVEQ #1,D0
|
||
|
||
@Done RTS
|
||
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: GetSCSIDiskModeAddress (PowerMgrDispatch selector #20)
|
||
;
|
||
; Inputs: A2 - pointer to Power Manager globals
|
||
;
|
||
; Outputs: D0 - SCSI bus addresse internal hard disk (1-6)
|
||
;
|
||
; Trashes: D1, A0
|
||
;
|
||
; Function: returns the SCSI Disk Mode address of the internal hard disk
|
||
;________________________________________________________________________________________
|
||
|
||
GetSCSIDiskModeAddress
|
||
LoadTbl PrimInfoTblPtr,A2,A0
|
||
MOVEQ #1<<hasSCSIDiskMode,D0 ; is SCSI Disk Mode supported on this machine?
|
||
AND.L PrimPubFeatures(A0),D0
|
||
BEQ.S @Done
|
||
|
||
MOVEQ #PmgrOtherFlags,D0 ; read the byte containing the address
|
||
BSR.S ReadPMgrPRAM
|
||
IF DiskModeAddr≠0 THEN
|
||
LSR.B #DiskModeAddr,D0 ; and shift it down to bit zero
|
||
ENDIF
|
||
IF DiskModeAddr<5 THEN
|
||
ANDI.B #%111,D0 ; mask to just the 3 lsb's
|
||
ENDIF
|
||
MOVE.B mapSCSIAddr(D0),D0 ; make sure we return a valid address
|
||
@Done RTS
|
||
|
||
mapSCSIAddr DC.B 2,1,2,3,4,5,6,2 ; <H94>
|
||
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: SetSCSIDiskModeAddress (PowerMgrDispatch selector #21)
|
||
;
|
||
; Inputs: A2 - pointer to Power Manager globals
|
||
; D0 - high word: SCSI bus address of the internal hard disk (1-6)
|
||
;
|
||
; Outputs: D0 - result code (always zero)
|
||
;
|
||
; Trashes: D0, D1, A0
|
||
;
|
||
; Function: updates PRAM with the SCSI Disk Mode address for the internal hard disk
|
||
;________________________________________________________________________________________
|
||
|
||
SetSCSIDiskModeAddress
|
||
LoadTbl PrimInfoTblPtr,A2,A0
|
||
MOVEQ #1<<hasSCSIDiskMode,D1 ; is SCSI Disk Mode supported on this machine?
|
||
AND.L PrimPubFeatures(A0),D1
|
||
BEQ.S @Done
|
||
|
||
SWAP D0 ; get the ID
|
||
CMPI.W #7,D0 ; is it in range?
|
||
BLS.S @MapID ; -> yes
|
||
MOVEQ #7,D0 ; no, pin it
|
||
@MapID MOVE.B mapSCSIAddr(D0),D0 ; make sure the address is valid,
|
||
IF DiskModeAddr≠0 THEN
|
||
LSL.B #DiskModeAddr,D0 ; and then shift it into the correct bit position
|
||
ENDIF
|
||
MOVE.B D0,D1 ; save it for the write
|
||
MOVEQ #PmgrOtherFlags,D0 ; read the byte containing the CPU speed bit
|
||
BSR ReadPMgrPRAM
|
||
ANDI.W #~(%111<<DiskModeAddr),D0 ; mask out the disk mode address bits
|
||
OR.B D0,D1 ; and insert the new value into the byte
|
||
MOVEQ #PmgrOtherFlags,D0 ; then write the PRAM byte back out
|
||
BRA WritePMgrPRAM
|
||
|
||
@Done MOVEQ #0,D0
|
||
RTS
|
||
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: GetWakeupTimer (PowerMgrDispatch selector #22)
|
||
;
|
||
; Inputs: A0 - pointer to buffer to hold wakeup time and enable/disable flag byte
|
||
; A2 - pointer to Power Manager globals
|
||
;
|
||
; Outputs: D0 - none
|
||
;
|
||
; Trashes: A0,A1
|
||
;
|
||
; Function: returns the time when the PowerBook will wake up
|
||
;________________________________________________________________________________________
|
||
|
||
GetWakeupTimer
|
||
LoadTbl PrimInfoTblPtr,A2,A1
|
||
MOVEQ #1<<hasWakeupTimer,D0 ; does this machine have a wakeup timer?
|
||
AND.L PrimPubFeatures(A1),D0
|
||
BEQ.S @NoTimer ; -> no, we're done
|
||
|
||
MOVE.L A0,-(SP) ; pmRBuffer <H95>
|
||
CLR.L -(SP) ; pmSBuffer
|
||
CLR.W -(SP) ; pmLength
|
||
MOVE.W #timerRead,-(SP) ; pmCommand
|
||
MOVEA.L SP,A0 ; point to the parameter block
|
||
_PMgrOp ; read the wakeup time
|
||
LEA pmRBuffer+4(SP),SP ; toss the parameter block
|
||
RTS
|
||
|
||
@NoTimer CLR.L (A0)+ ; zero out all the fields <H95>
|
||
CLR.B (A0)+ ; <H95>
|
||
RTS ; <H95>
|
||
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: SetWakeupTimer (PowerMgrDispatch selector #23)
|
||
;
|
||
; Inputs: A0 - pointer to buffer that contains the wakeup time and enable/disable flag byte
|
||
; A2 - pointer to Power Manager globals
|
||
;
|
||
; Outputs: D0 - none
|
||
;
|
||
; Trashes: D0,A0,A1
|
||
;
|
||
; Function: sets the time when the PowerBook will wake up
|
||
;________________________________________________________________________________________
|
||
|
||
SetWakeupTimer
|
||
LoadTbl PrimInfoTblPtr,A2,A1
|
||
MOVEQ #1<<hasWakeupTimer,D0 ; does this machine have a wakeup timer?
|
||
AND.L PrimPubFeatures(A1),D0
|
||
BEQ.S @NoTimer ; -> no, we're done
|
||
|
||
MOVEA.L A0,A1 ; save a copy of the buffer pointer
|
||
|
||
CLR.L -(SP) ; pmRBuffer <H95>
|
||
MOVE.L A0,-(SP) ; pmSBuffer <H95>
|
||
MOVE.W #4,-(SP) ; pmLength
|
||
MOVE.W #timerSet,-(SP) ; pmCommand
|
||
MOVEA.L SP,A0 ; point to the parameter block
|
||
_PMgrOp ; set the timer
|
||
|
||
TST.B 4(A1) ; is the timer to be disabled? <H95>
|
||
BNE.S @Done ; -> nope, all done
|
||
|
||
MOVE.W #$82,pmCommand(A0) ; send a ‘disable wakeup timer’ command <H95>
|
||
CLR.W pmLength(A0) ; <H95>
|
||
_PMgrOp ; <H95>
|
||
|
||
@Done LEA pmRBuffer+4(SP),SP ; clean up the stack
|
||
@NoTimer RTS
|
||
|
||
|
||
;________________________________________________________________________________________ <H90>
|
||
;
|
||
; Routine: GetProcessorCycling (PowerMgrDispatch selector #24)
|
||
;
|
||
; Inputs: A2 - pointer to Power Manager globals
|
||
;
|
||
; Outputs: D0 - boolean: 1=cycling is enabled, 0=cycling is disabled
|
||
;
|
||
; Trashes: A0
|
||
;
|
||
; Function: returns whether or not processor cycling is enabled
|
||
;________________________________________________________________________________________
|
||
|
||
GetProcessorCycling
|
||
MOVEQ #PmgrStatusFlags,D0 ; read the byte containing modem status <H85>
|
||
BSR ReadPMgrPRAM ; <H85>
|
||
BTST #IdleBit,D0 ; 1=disabled, 0=enabled
|
||
SEQ D0
|
||
NEG.B D0 ; 1=enabled, 0=disabled
|
||
RTS
|
||
|
||
|
||
;________________________________________________________________________________________ <H90>
|
||
;
|
||
; Routine: SetProcessorCycling (PowerMgrDispatch selector #25)
|
||
;
|
||
; Inputs: A2 - pointer to Power Manager globals
|
||
; D0 - boolean: 1=enable cycling, 0=disable cycling
|
||
;
|
||
; Outputs: none
|
||
;
|
||
; Trashes: A0
|
||
;
|
||
; Function: enables/disables processor cycling
|
||
;________________________________________________________________________________________
|
||
|
||
SetProcessorCycling
|
||
SWAP D0 ; get the boolean
|
||
TST.W D0 ; enable or disable?
|
||
BNE.S @enable
|
||
|
||
BSET #IdleBit,SleepFlags(A2) ; disable idle
|
||
BRA.S @common
|
||
|
||
@enable BCLR #IdleBit,SleepFlags(A2) ; enable idle
|
||
|
||
@common MOVEQ #PmgrStatusFlags,D0 ; write the byte containing idle status
|
||
MOVE.B SleepFlags(A2),D1
|
||
BRA WritePMgrPRAM
|
||
|
||
|
||
;________________________________________________________________________________________ <H90>
|
||
;
|
||
; Routine: BatteryCount (PowerMgrDispatch selector #26)
|
||
;
|
||
; Inputs: A2 - pointer to Power Manager globals
|
||
;
|
||
; Outputs: D0 - number of internal batteries we can have
|
||
;
|
||
; Trashes: A0
|
||
;
|
||
; Function: returns the number of internal batteries we can have
|
||
;________________________________________________________________________________________
|
||
|
||
BatteryCount
|
||
MOVEA.L PMgrBase,A2 ; get pointer to Power manager globals
|
||
LoadTbl PrimInfoTblPtr,A2,A0
|
||
MOVEQ #0,D0 ; get the number of internal batteries we can have
|
||
MOVE.W PrimBatteryCount(A0),D0
|
||
RTS
|
||
|
||
|
||
;________________________________________________________________________________________ <H83>
|
||
;
|
||
; Routine: GetBatteryVoltage (PowerMgrDispatch selector #27)
|
||
;
|
||
; Inputs: A2 - pointer to Power Manager globals
|
||
; D0 - high word: battery number (0-n)
|
||
;
|
||
; Outputs: D0 - battery voltage
|
||
;
|
||
; Trashes: A0-A1, D1-D2
|
||
;
|
||
; Function: returns the battery voltage as a fixed-point number so that nobody external
|
||
; to the Power Manager needs to do the calculation anymore.
|
||
;________________________________________________________________________________________
|
||
|
||
GetBatteryVoltage
|
||
MOVEA.L PMgrBase,A2 ; get pointer to Power manager globals
|
||
LoadTbl PrimInfoTblPtr,A2,A0
|
||
SWAP D0 ; get the battery number <H90>
|
||
CMP.W PrimBatteryCount(A0),D0 ; do we support this many batteries? <H90>
|
||
BHS.S @NoBattery ; -> no, return zero <H90>
|
||
|
||
JmpRoutine AbsoluteBattPtr,A2,A0; run the routine
|
||
|
||
@NoBattery MOVEQ #0,D0 ; return zero volts <H90>
|
||
RTS ; <H90>
|
||
|
||
|
||
;________________________________________________________________________________________ <H90>
|
||
;
|
||
; Routine: GetBatteryTimes (PowerMgrDispatch selector #28)
|
||
;
|
||
; Inputs: A2 - pointer to Power Manager globals
|
||
; A0 - pointer to BatteryTimeRec record:
|
||
; expectedBatteryTime DS.L 1 ; estimated battery time remaining
|
||
; minimumBatteryTime DS.L 1 ; minimum battery time remaining
|
||
; maximumBatteryTime DS.L 1 ; maximum battery time remaining
|
||
; timeUntilCharged DS.L 1 ; time remaining until the battery is fully charged
|
||
; D0 - high word: system total (0) - battery number (1-n)
|
||
;
|
||
; Outputs: none
|
||
;
|
||
; Trashes: A0-A1, D0-D2
|
||
;
|
||
; Function: fills in a record containing fields that describe battery times.
|
||
;________________________________________________________________________________________
|
||
|
||
GetBatteryTimes
|
||
MOVEA.L PMgrBase,A2 ; get pointer to Power manager globals
|
||
LoadTbl PrimInfoTblPtr,A2,A1
|
||
SWAP D0 ; get the battery number
|
||
CMP.W PrimBatteryCount(A1),D0 ; do we support this many batteries?
|
||
BHS.S @NoBattery ; -> no, return zero
|
||
|
||
JmpRoutine BatteryTimePtr,A2,A1 ; run the routine (D0.W contains battery number or system)
|
||
|
||
@NoBattery CLR.L (A0)+ ; zero out the fields
|
||
CLR.L (A0)+
|
||
CLR.L (A0)+
|
||
CLR.L (A0)+
|
||
MOVEQ #0,D0
|
||
RTS
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: LCDScreenChk
|
||
;
|
||
; Inputs: none
|
||
;
|
||
; Outputs: CCR - BNE if LCD screen
|
||
;
|
||
; Trashes: D0, A0, A1
|
||
;
|
||
; Function: For Color QuickDraw machines, check if a flag in the video attributes sRsrc
|
||
; says we have an LCD screen for built-in video. If the sRsrc doesn't exist,
|
||
; or the flag isn't set, we assume a CRT.
|
||
;________________________________________________________________________________________
|
||
|
||
LCDScreenChk
|
||
WITH SpBlock
|
||
|
||
Cmp.w #$3FFF,ROM85 ; If Color QuickDraw is not around,
|
||
Bne.s @NoCQD ; then just leave.
|
||
Tst.l DeviceList ; If the DeviceList is empty,
|
||
Beq.s @NoDevices ; then just leave.
|
||
Move.l MainDevice,D0 ; If there isn’t a MainDevice,
|
||
Beq.s @NoDevices ; then just leave.
|
||
|
||
Move.l D0,A0 ; Get the Handle to the MainDevice.
|
||
Move.l (A0),A0 ; Make it a pointer.
|
||
Moveq #0,D0 ; Prepare D0 for unsigned .w references.
|
||
Move.w gdRefNum(A0),D0 ; If there’s no driver, then
|
||
Beq.s @NoDevices ; we can’t do anything here.
|
||
|
||
Not.w D0 ; Convert the refNum into…
|
||
Lsl.w #2,D0 ; …a UTable index.
|
||
Add.l UTableBase,D0 ; Get a ptr to the AuxDCEHandle.
|
||
Move.l D0,A1 ; Get it into A1.
|
||
Move.l (A1),A1 ; Get the AuxDCEHandle.
|
||
Move.l (A1),A1 ; Get the AuxDCEPtr.
|
||
|
||
Lea -spBlockSize(sp),Sp ; Put a slot parameter block on the stack.
|
||
Move.l Sp,A0 ; Point to it with A0.
|
||
Move.b dCtlSlot(A1),spSlot(A0) ; Get the slot number.
|
||
Move.b dCtlSlotID(A1),spID(A0) ; Get the spID of the video sRsrc.
|
||
Clr.b spExtDev(A0) ; Don’t ask why, just clear this guy.
|
||
_sRsrcInfo ; Get the spsPointer.
|
||
Bne.s @AssumeCRT ; If failed, just quit.
|
||
|
||
Move.b #sVidAttributes,spID(A0); Say to get the video sRsrc attributes.
|
||
_sReadWord ; Get ’em.
|
||
Bne.s @AssumeCRT ; If failed, just quit.
|
||
|
||
Moveq #1<<fLCDScreen,D0 ; Mask off the LCD bit in the sRsrc attributes.
|
||
And.w spResult+2(A0),D0
|
||
|
||
@Done Lea spBlockSize(sp),Sp ; Clean up the stack.
|
||
@NoDevices Rts ; Return to caller.
|
||
|
||
@AssumeCRT Moveq #0,D0 ; Set CCR appropriately.
|
||
Bra.s @Done
|
||
|
||
@NoCQD Moveq #0,D0 ; Set CCR appropriately.
|
||
Rts ; Return to caller.
|
||
|
||
|
||
;________________________________________________________________________________________ <K12>
|
||
; |
|
||
; Routine: GetDimTimeout (PowerMgrDispatch selector #29) v
|
||
;
|
||
; Inputs: A2 - pointer to Power Manager globals
|
||
;
|
||
; Outputs: D0 - sleep timeout (number of 15 second intervals)
|
||
;
|
||
; Trashes: A0
|
||
;
|
||
; Function: returns the current sleep timeout time
|
||
;________________________________________________________________________________________
|
||
GetDimTimeout
|
||
MOVEQ #0,D0 ; assume the result is zero
|
||
MOVE.L DimmingWaitTime(A2),D1 ; get value from globals
|
||
BEQ.S @Done
|
||
DIVU.L #pram2ticks,D1 ; convert from ticks value to 15 sec intervals
|
||
MOVE.B D1,D0 ; return result
|
||
@Done RTS
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: SetDimTimeout (PowerMgrDispatch selector #30)
|
||
;
|
||
; Inputs: A2 - pointer to Power Manager globals
|
||
; D0 - high word: sleep time to set (number of 15 second intervals)
|
||
;
|
||
; Outputs: D0 - result code (always zero)
|
||
;
|
||
; Trashes: D1, A0
|
||
;
|
||
; Function: sets the current sleep timeout
|
||
;________________________________________________________________________________________
|
||
SetDimTimeout
|
||
SWAP D0 ; get the new value
|
||
MOVEQ #0,D1 ; clear reg
|
||
MOVE.B D0,D1 ; get the new value
|
||
MULU.W #pram2ticks,D1 ; set ticks value
|
||
MOVE.L D1,DimmingWaitTime(A2) ; save value in globals
|
||
_UsrIdleUpdate
|
||
MOVEQ #0,D0 ; return noErr
|
||
RTS
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: DimControl (PowerMgrDispatch selector #31)
|
||
;
|
||
; Inputs: A2 - pointer to Power Manager globals
|
||
; D0 - high word: 0=disable sleep, 1=enable sleep
|
||
;
|
||
; Outputs: D0 - result code (always zero)
|
||
;
|
||
; Trashes: A0
|
||
;
|
||
; Function: Disables or enables auto sleep by incrementing or decrementing the auto sleep
|
||
; semaphone. Note that since the semaphore supports multiple ‘levels’, if it's
|
||
; been disabled n times in a row, it needs to be enabled n times before auto
|
||
; sleep will really be enabled.
|
||
;________________________________________________________________________________________
|
||
DimControl
|
||
SWAP D0 ; get the flag
|
||
TST.W D0 ; enable or disable?
|
||
BEQ.S @disable ; -> disable
|
||
SUBQ.B #1,DimmingDisable(A2) ; ‘pop’ a level towards sleep enabled
|
||
BGE.S @done ; -> haven't rolled over
|
||
CLR.B DimmingDisable(A2) ; pin the semaphore a zero
|
||
BRA.S @done ;
|
||
|
||
@disable ADDQ.B #1,DimmingDisable(A2) ; set the semaphore to >0 (‘push’ a level)
|
||
BHI.S @done ; -> we're done if it's still >0
|
||
SUBQ.B #1,DimmingDisable(A2) ; it rolled over, so make it >0 again
|
||
@done MOVEQ #0,D0 ;
|
||
RTS ; <K12>
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: IsDimmingDisabled (PowerMgrDispatch selector #32)
|
||
;
|
||
; Inputs: A2 - pointer to Power Manager globals
|
||
;
|
||
; Outputs: D0 - boolean: 1=disabled, 0=enabled
|
||
;
|
||
; Trashes: none
|
||
;
|
||
; Function: returns a boolean telling whether dimming is enabled or disabled
|
||
;________________________________________________________________________________________
|
||
|
||
IsDimmingDisabled
|
||
MOVEQ #0,D0 ; assume enabled
|
||
TST.B DimmingDisable(A2) ; IF counting semaphor not nil THEN
|
||
BEQ.S @Done ;
|
||
MOVEQ #1,D0 ; tell the world it's disabled
|
||
@Done RTS ; that's all folks
|
||
|
||
;________________________________________________________________________________________
|
||
;
|
||
; Routine: IsAutoSlpDisabled (PowerMgrDispatch selector #33)
|
||
;
|
||
; Inputs: A2 - pointer to Power Manager globals
|
||
;
|
||
; Outputs: D0 - boolean: 1=disabled, 0=enabled
|
||
;
|
||
; Trashes: none
|
||
;
|
||
; Function: returns a boolean telling whether autosleep is enabled or disabled
|
||
;________________________________________________________________________________________
|
||
|
||
IsAutoSlpDisabled
|
||
MOVEQ #0,D0 ; assume enabled
|
||
TST.B AutoSlpDisable(A2) ; IF counting semaphor not nil THEN
|
||
BEQ.S @Done ;
|
||
MOVEQ #1,D0 ; tell the world it's disabled
|
||
@Done RTS ; that's all folks
|
||
RTS
|
||
|
||
ENDIF ; {hasPwrControls}
|
||
END |