sys7.1-doc-wip/OS/PowerMgr/PowerMgrPatches.a

2749 lines
85 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

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

;
; Hacks to match MacOS (most recent first):
;
; <Sys7.1> 8/3/92 Elliot make this change
; 9/2/94 SuperMario ROM source dump (header preserved below)
;
;
; File: PowerMgrPatches.a
;
; Contains: patches for the power manager
;
; Copyright: © 1990-1992 by Apple Computer, Inc., all rights reserved.
;
; Change History (most recent first):
;
; <SM3> 9/1/93 SKH Rolling in from Horror. These patches will get removed and rolled into PowerMgr
; when Kaos has stopped changing.
;
; <16> 5/5/92 DTY #1026866: fixed a bug where the code was testing the pointer to
; the buffer not the buffer. "pmSBuffer" is a pointer, not the
; buffer.
; <15> 4/21/92 DTY #1026866: rolled in fixes for powerbooks. bugs fixed includes
; the following ... 1) aborting sleep queue if result was non zero
; in in all sleep case (routines were shuffled around to allow
; reuse by second patch) 2) serial speed problems due to 100us
; delay when powering off the floppy 3) floppy eject problem when
; HD inserted and waking up.
;
; <14> 2/17/92 DTY Add hasTerror conditional to PowerMiscPatches InstallProc so
; that it only loads on Terror ROM machines.
; <13> 2/12/92 JSM Moved this file to PowerMgr folder, keeping all the old
; revisions; cleanup header.
; <12> 12/31/91 RB Removed some definitions that are now in Traps.a and
; PowerPrivEqu.a
; <11> 12/30/91 RB Added a few WITH's needed for this file because the PowerMgr
; interfaces changed and were moved to PowerPrivEqu.a.
; <10> 10/28/91 SAM/KSM Rolled in Regatta file:
; (HJR) Fix bug where system crashes when a new a low power dialog
; comes in after the shorted battery dialog is set. This is done
; by patching the BatInt to handle remove messages appropriately.
; (ag) don't patch sound watch on asahi. allow rom code to turn
; off sound power when not in use.
; (eva) fixed bug that was causing 976 to crash by saving out and
; restoring d7 at beginning and end of the PMgrTrapII routine.
; oops.
; (djw) Fix modem sound feedback problem by disabling playthrough
; on modem sound off routine.
; (HJR) removed default _IdleDelay time patch. Fixed bug in
; _PmgrOp delay patch. Added wake task routine to set power
; warning level back to 5.90V. Patch BatWatch VBL task to change
; power warning level to 6.09V on first occurrence 10sec warning.
; Fixed ROM problem on invalid PRAM, sleep and HD times were not
; set to defaults. Fixed bug in Portable BatWatch code using low
; mem scratch area (GetParam) instead of stack at interrupt time.
; (djw) Changed default _IdleDelay time from 15 to 6 secs.
; Patched out SerialPowerOn to power on SCC before releasing modem
; reset (as per request from Paris guys).
; (HJR) Changed the SetCursor patch to look in the right place on
; the stack for the cursor
; (djw) Rearranged Terror power manager patches to use a single
; InstallProc instead of many separate ones. Lowered the max
; number of power cycling iterations. Patch _Sleep to fix
; reentrancy problem. Install general sleep queue element for
; all system type sleep queue bug fixes. Patch _SetCursor to
; disable powercycling on watch cursor and to detect activity.
; Replace SndWatch VBL task to take DFAC activity into account
; before powering off Batman. Patch _PmgrOp to add a 100µs delay
; to avoid a race condition between 68K and pmgr micro. Add
; sleep queue task on wake to turn on Batman if DFAC enabled.
; Replace ModemSound interrupt handlers to route sound thru
; attenuator. On Portable, do a KdbReset earlier in wake routine.
; (ag) Changed low power warning level in power manager micro to
; increase wake hysteresis.
; (HJR) Added InstallProc for new sleepqueue element to save and
; restore cursor appropriately before and after sleep.
; (MSH) Changed the SCCWakeFix to not wake up the modem while
; servicing the Serial wake up IRQ.
; (ag) Installed "bad battery" strings into power manager globals.
; Changed threshold level to 5.60 volts cutoff.
; added bypass of network sleep dialog. added ashai to backlight
; test in patches. changed network warning dialog to default to
; sleep
; (ag) added ashai to backlight test in patches. (HJR) Added
; "with PMgrRec" everywhere.
; Split off from 7.0 GM sources. Added low power and SCSI Link
; warnings.
; <9> 8/30/91 DTY Define onHcMac here, since its not an available feature in
; BBSStartup any more.
; <8> 4/10/91 ag HJR: changed the location of the insleep semaphore. the old
; location was being overwritten by other parts of the power
; manager. moved an installproc to the head of the file in insure
; it is executed BEFORE the patchproc which uses variables it
; initializes.
; <7> 2/22/91 ag MSH: Added aruba support to the powermgr install code, new low
; power string, and patched vbls.
; <6> 2/15/91 ag MSH: #BRC 80886 - Changed sleep code and wake code to allow
; sleep queue elements to use network services. This included
; moving the close of appletalk until after the sleep queue is run
; on sleep, and opening appletalk before running the sleep queue
; on wake. the running the sleep queue on sleep, the queue is run
; in reverse order to allow service consumers to be run before
; service producers. finally, a change was added to avoid
; re-entering the sleep code (this would be very bad!!!).
; <5> 2/1/91 eh (hjr) Fixed bug that was causing serial data bytes to
; occassionally be transposed. Now all code paths call PollProc
; BEFORE re-enabling interrupts.
; <4> 12/19/90 ag As it turns out, elements of the sleep queue need interrupt on
; (the old bug kept it working!). Therefore, the wake code must be
; patched to handle restoring context and interrupts BEFORE waking
; the sleep queue. Also removed changes made in <3> since the
; change in wakeup removes the necessity of avoiding the Delay
; trap.(reviewed by MSH).
; <3> 12/14/90 ag changed delay trap calls to dbra loops. this avoids turning on
; interrupts. added patch to serial power off to allow patching
; delay call in power off trap. (reviewed by DJW)
; <2> 9/21/90 VL Removed unnecessary include files.
; <1> 9/21/90 VL Moved the PowerMgr patches from PatchPortableROM.a. All the
; patches in this file are linked patches. The whole exodus was
; prompted by the need to load the Notification Manager patches
; before anything else (including the PowerMgr patches).
;
if (&type('onHcMac') = 'UNDEFINED') then
onHcMac: equ 1
endif
load 'StandardEqu.d'
include 'LinkedPatchMacros.a'
include 'HardwarePrivateEqu.a'
include 'ATalkEqu.a'
include 'UniversalEqu.a'
include 'IOPrimitiveEqu.a'
include 'PowerPrivEqu.a'
AllClose ROMBind (Portable,$4946)
BatIntCont ROMBind (IIci,$88660)
CloseAppleTalk ROMBind (IIci,$8957E)
didqueue ROMBind (IIci,$89194)
DoQueue ROMBind (Portable,$4776)
DreamAway ROMBind (IIci,$8911C)
GetLevel ROMBind (Portable,$4176),(IIci,$887B2)
InitSCSI ROMBind (Portable,$0732)
InstallMsg ROMBind (Portable,$413A),(IIci,$8877A)
KbdReset ROMBind (Portable,$496c)
PMGRrecv ROMBind (Portable,$4014),(IIci,$885d2)
PMGRsend ROMBind (Portable,$4016),(IIci,$885d4)
RemoveMsg ROMBind (Portable,$4124),(IIci,$8875C)
ROMCheckAppleTalk ROMBind (IIci,$89488)
ROMPmgrOp ROMBind (IIci,$888ec)
SlpQInstall ROMBind (IIci,$8976C)
SlpQRemove ROMBind (IIci,$89784)
SetSupervisorMode ROMBind (IIci,$89474)
SomeSleepProc ROMBind (Portable,$4628)
Burninate InstallProc (Portable)
WITH PmgrRec,pmCommandRec,SleepqRec
leaResident WakeQRec,A0
leaResident SCCWakeFix,A1
MOVE.L A1,SleepqProc(A0)
MOVE.W #slpQType,SleepqType(A0)
CLR.W SleepqFlags(A0)
_SlpQInstall
LEA -20(SP),SP
MOVE.L SP,A0
MOVE.L #$10077,D0 ; Portable: SleepFlags
_ReadXPRam
MOVE.B (A0),D1
AND.B #(1<<RingWakeup)|(1<<TimerWakeup),D1
BEQ @neitherWakeup
; Set up a PMgr record for rewriting an identical timer value
LEA pmData(SP),A1
MOVE.L A1,pmRBuffer(SP)
MOVE.L A1,pmSBuffer(SP)
BTST #TimerWakeup,D1
BEQ.S @noTimerWakeup
MOVE.W #0,pmLength(SP)
MOVE.W #timerRead,pmCommand(SP)
MOVE.L SP,A0
_PmgrOp
MOVE.W #4,pmLength(SP)
MOVE.W #timerSet,pmCommand(SP)
MOVE.L SP,A0
_PmgrOp
@noTimerWakeup
BTST #RingWakeup,D1
BEQ.S @noRingWakeup
MOVE.W #0,pmLength(SP)
MOVE.W #modemRead,pmCommand(SP)
MOVE.L SP,A0
_PmgrOp
AND.B #(1<<ModemPwr)|(1<<ModemAorB)|(1<<RingWakeEnable),(A1)
OR.B #1<<RingWakeEnable,(A1)
MOVE.W #1,pmLength(SP)
MOVE.W #modemSet,pmCommand(SP)
MOVE.L SP,A0
_PmgrOp
@noRingWakeup
@neitherWakeup
LEA 20(SP),SP
movea.l PmgrBase,a2 ; get power mgr globals
;PatchBatWatchVBL
lea BatVBLTask(a2),a0 ; get pointer to vbl queue element
_VRemove ; remove it from the queue
leaResident BatWatch,a1
move.l a1,vblAddr(a0)
move.w #1,vblCount(a0) ; enable vbl element
_Vinstall
MOVE.L #AccessBase,A0
CMP.B #$AD,(A0)
BEQ.S @noDo
;PatchSndVBL
lea SwVBLTask(a2),a0 ; a0 = ptr to SndWatch VBL queue blk
_VRemove ; remove it from the queue
leaResident SndWatch,a1 ; a1 = addr of SndWatch resident code
move.l a1,vblAddr(a0)
move.w #1,vblCount(a0) ; enable vbl element
_Vinstall
@noDo
; The Power Mgr can compare the current cursor to the watch
CLR.L -(SP)
MOVE.L #'CURS',-(SP)
MOVE.W #4,-(SP)
_GetResource
MOVE.L (SP)+,A0
MOVE.L (A0),D0
_StripAddress
MOVE.L D0,RAMwatchPtr(A2)
CLR.L -(SP)
MOVE.L #'CURS',-(SP)
MOVE.W #4,-(SP)
MOVE.W #MapTrue,ROMMapInsert
_GetResource
MOVE.L (SP)+,A0
MOVE.L (A0),D0
_StripAddress
MOVE.L D0,ROMwatchPtr(A2)
RTS
portaPmgrOp PatchProc _PmgrOp,(Portable)
WITH PmgrRec,pmCommandRec,SleepqRec
AND.W #$600,D1 ; extra bits as below...
BEQ.S PmgrOpTrap
MOVEM.L D3/D4,-(SP)
CMP.W #$400,D1
BEQ.S @jsrOld ; IdleUpdate/IdleState
BLO.S @jsrOld
; what remains is _SerialPower
BTST #7,D0 ; test bOff bit
BEQ SerialPowerTrap
@jsrOld
jsrOld
MOVEM.L (SP)+,D3/D4
RTS
PmgrOpTrap
CMP.W #pMgrADB,pmCommand(A0)
BNE DoPmgrOp
CMP.W #9,pmLength(A0)
BLS DoPmgrOp
MOVE.W #pMgrADBoff,pmCommand(A0)
MOVE.W #0,pmLength(A0)
BSR DoPmgrOp
LEA pmRBuffer(A0),A1
MOVE.L A1,pmSBuffer(A0)
MOVE.B 5(A1),D0
OR.B #2,D0
MOVE.B D0,5(A1)
MOVE.B 6(A1),D0
MOVE.B D0,2(A1)
SUB.W #1,D0
MOVE.W D0,D3
@rloop MOVE.B 7(A1,D3),-(SP)
DBRA D3,@rloop
ADD.W #7,A1
@wloop MOVE.B (SP)+,(A1,D0)
DBRA D0,@wloop
LEA pmRBuffer(A0),A1
MOVE.L 10(A1),D3
MOVE.W #15,12(A1)
LEA 12(A1),A1
MOVE.L A1,pmSBuffer(A0)
MOVE.W #writePmgrRAM,pmCommand(A0)
MOVE.W #3,pmLength(A0)
BSR DoPmgrOp
LEA pmRBuffer(A0),A1
MOVE.L D3,10(A1)
MOVE.L 4(A1),D3
MOVE.W #9,6(A1)
LEA 6(A1),A1
MOVE.L A1,pmSBuffer(A0)
MOVE.W #writePmgrRAM,pmCommand(A0)
MOVE.W #8,pmLength(A0)
BSR DoPmgrOp
LEA pmRBuffer(A0),A1
MOVE.L D3,4(A1)
MOVE.W #3,(A1)
MOVE.L A1,pmSBuffer(A0)
MOVE.W #writePmgrRAM,pmCommand(A0)
MOVE.W #8,pmLength(A0)
BSR DoPmgrOp
RTS
SerialPowerTrap
MOVE.W D0,D1
CLR.L D2
CLR.L D3
CLR.L D4
LEA -pmBlkSize(SP),SP
LEA pmData(SP),A0
MOVE.L A0,pmRBuffer(SP)
MOVE.L A0,pmSBuffer(SP)
BCLR #0,D1
BNE.S @bail
MOVE.W #modemRead,pmCommand(SP)
MOVE.W #0,pmLength(SP)
MOVE.L SP,A0
BSR.S DoPmgrOp
MOVE.B pmData(A0),D3
BTST #3,D3
BEQ.S @bail
MOVE.L #$10077,D0
_ReadXPRam
BTST #UseIntrnlModem,(A0)
BNE.S @bail
MOVE.B D3,D0
AND.B #2,D0
LSL.B #1,D0
CMP.B D0,D1
BEQ.S @othercase
@bail
OR.B #$90,D2
MOVEQ #0,D3
@othercase
MOVE.W #powerCntl,pmCommand(SP)
MOVE.W #1,pmLength(SP)
MOVE.B #$C0,pmData(SP)
MOVE.L SP,A0
BSR.S DoPmgrOp
MOVEQ #8,D0
MOVE.L D0,A0
_Delay
OR.B #$82,D2
MOVE.W #powerCntl,pmCommand(SP)
MOVE.W #1,2(SP)
MOVE.B D2,pmData(SP)
MOVE.L SP,A0
BSR.S DoPmgrOp
TST.B D3
BEQ.S @bail2
MOVE.B #$88,pmData(SP)
MOVE.W #1,pmLength(SP)
MOVE.W #powerCntl,pmCommand(SP)
MOVE.L SP,A0
BSR.S DoPmgrOp
@bail2
LEA pmBlkSize(SP),SP
MOVEM.L (SP)+,D3/D4
MOVEQ #0,D0
RTS
DoPmgrOp
MOVEM.L A0-A6/D1-D7,-(SP)
MOVE.W SR,D5
MOVE.L VIA,A1
MOVE.B vIER(A1),D4
MOVE.B D4,-(SP)
AND.B #1<<ifCB1,D4
MOVE.B #1<<ifCB1,vIER(A1)
SUB.L #2,SP
MOVE.L PmgrBase,A2
CMP.W #$FFFF,A2
BEQ.S @noGlobals
MOVE.B SaveSpeedo(A2),D3
MOVE.W D3,(SP)
MOVE.B #$10,SaveSpeedo(A2)
@noGlobals
TST.W Clock16M
SUB #48,SP
MOVE.L SP,A3
MOVE.L SCCRd,A6
ADD.L #6,A6
LEA (A1),A5
MOVE.B #$FF,vDIRA(A1) ; all to inputs?
MOVE.B vBufA(A1),D2
SWAP D2
MOVEQ #7,D3
@bigloop
CLR.B vDIRA(A1)
MOVE.W TimeVIADB,D2
LSL.W #2,D2
@timeloop
BTST #1,vBufB(A1)
BEQ.S @bitNotSet
MOVE.B vBufA(A1),D0
CMP.B #$FF,D0
BEQ.S @exitloop
@bitNotSet
DBRA D2,@timeloop
MOVE.L #pmBusyErr,D0
BRA @beatIt
@exitloop
OR.W #$700,SR
TST.W Clock16M
MOVE.B vBufB(A1),D6
SWAP D6
MOVE.B vDIRB(A1),D6
BCLR #7,vDIRB(A1)
LEA 1(A0),A2
MOVEQ #$40,D2
BSR pmSend
BEQ @notsure
MOVE.L A3,PollStack
CMP.L PollStack,SP
BEQ.S @equalsPollStack
MOVE.L A3,D7
MOVEM.L A0-A4/D0-D6,(A3)
MOVE.L PollProc,D2
BEQ.S @noPollProc
NOP
NOP
PEA @noPollProc
MOVE.L D2,-(SP)
RTS
@noPollProc
MOVE.L D7,A3
MOVEM.L (A3),A0-A4/D0-D6
@equalsPollStack
MOVE.B D6,vDIRB(A1)
SWAP D6
MOVE.B D6,vBufB(A1)
MOVEQ #$40,D2
MOVE.W D5,SR
DBRA D2,*
DBRA D3,@bigloop
BRA.S @beatIt
@notsure
MOVEQ #0,D1
LEA 3(A0),A2
MOVE.B (A2),D1
BSR pmOther
BNE.S @beatIt
SUB.W #1,D1
BMI.S @mi
MOVE.L 4(A0),A2
@loop2
BSR pmOther
BNE.S @beatIt
DBRA D1,@loop2
@mi
MOVE.B 1(A0),D0
BTST #3,D0
BEQ.S @noFail
MOVE.L A0,A2
ADD.L #1,A2
MOVE.W TimeVIADB,D2
@timeloop2
BTST #1,(A1)
BEQ.S @testresult
MOVE.B (A5),(A5)
BMI.S @withinloop
NOP
MOVE.B (A6),-(SP)
@withinloop
DBRA D2,@timeloop2
MOVE.L #pmReplyTOErr,D0
BRA.S @beatIt
@testresult
CLR.L (A0)
BSR pmUnsure
BNE.S @beatIt
ADD.L #1,A2
BSR.W pmUnsure
BNE.S @beatIt
MOVE.W 2(A0),D1
MOVE.L 8(A0),A2
SUB.W #1,D1
BMI.S @noFail
@loop3
BSR pmUnsure
BNE.S @beatIt
DBRA D1,@loop3
@noFail
MOVEQ #0,D0
@beatIt
MOVE.B #$FF,vDIRA(A1)
SWAP D2
MOVE.B D2,vBufA(A1)
CLR.B vDIRA(A1)
MOVE.L D0,D4
MOVE.L A3,PollStack
CMP.L PollStack,SP
BEQ.S @dontReturn
MOVE.L PollProc,D2
BEQ.S @dontReturn
NOP
NOP
PEA @dontReturn
MOVE.L D2,-(SP)
RTS
@dontReturn
MOVE.L PollStack,SP
ADD.L #$30,SP
MOVE.L D4,D0
MOVE.L VIA,A1
MOVE.B D6,vDIRB(A1)
SWAP D6
MOVE.B D6,vBufB(A1)
MOVE.L PmgrBase,A2
CMP.W #$FFFF,A2
BEQ.S @noPmgrGlobs
MOVE.W (SP),D3
MOVE.B D3,SaveSpeedo(A2)
CMP.B #$10,D3
BEQ.S @noPmgrGlobs
TST.W Clock1M
@noPmgrGlobs
ADD.L #2,SP
MOVE.B (SP)+,D4
MOVE.B D4,vIER(A1)
MOVE.W D5,SR
MOVEM.L (SP)+,A0-A6/D1-D7
TST.W D0
RTS
pmOther
MOVE.W #$400,D2
pmSend
MOVEQ #0,D0
MOVE.L (SP)+,A4
MOVE.B #$FF,vDIRA(A1)
MOVE.B (A2)+,vBufA(A1)
BCLR #0,vBufB(A1)
@someloop
BTST #1,vBufB(A1)
BEQ.S @trySomethingElse
MOVE.B (A5),(A5)
BMI.S @mi
NOP
MOVE.B (A6),-(SP)
@mi
DBRA D2,@someloop
MOVE.L #pmSendStartErr,D0
BRA.S pmCommonReturn
@trySomethingElse
MOVEQ #$40,D2
BSET #0,vBufB(A1)
@otherloop
BTST #1,vBufB(A1)
BNE.S pmCommonReturn
MOVE.B (A5),(A5)
BMI.S @mi2
NOP
MOVE.B (A6),-(SP)
@mi2
DBRA D2,@otherloop
MOVE.L #pmSendEndErr,D0
pmCommonReturn
BSET #0,vBufB(A1)
CLR.B vDIRA(A1)
TST.L D0
JMP (A4)
pmUnsure
MOVEQ #0,D0
MOVE.L (SP)+,A4
MOVE.B #0,vDIRA(A1)
MOVEQ #$40,D2
@someloop
BTST #1,vBufB(A1)
BEQ.S @trySomethingElse
MOVE.B (A5),(A5)
BMI.S @mi
NOP
MOVE.B (A6),-(SP)
@mi
DBRA D2,@someloop
MOVE.L #pmRecvStartErr,D0
BRA.S pmCommonReturn
@trySomethingElse
MOVEQ #$40,D2
BCLR #0,vBufB(A1)
MOVE.B vBufA(A1),(A2)+
@otherloop
BTST #1,vBufB(A1)
BNE.S pmCommonReturn
MOVE.B (A5),(A5)
BMI.S @mi2
NOP
MOVE.B (A6),-(SP)
@mi2
DBRA D2,@otherloop
MOVE.L #pmRecvEndErr,D0
BRA.S pmCommonReturn
portaSleep PatchProc _Sleep,(Portable)
WITH PmgrRec,pmCommandRec,SleepqRec
IMPORT DoQueueStack
;________________________________________________________________________________________
;
; 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.W SR,-(SP)
MOVEM.L A0-A6/D1-D7,-(SP)
MOVE.W D0,D2
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
@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.S AbortSleep
@validselector
BCLR #AvoidNetDiag,\
PmgrFlags(A0) ; tst/clear the avoid bit
BNE.S @traverse ; if bit was set, skip dialog
MOVE.L SleepNetHook(A0),D3 ; IF SleepNetHook present THEN
BEQ.S @closeAT ;
MOVEA.L D3,A1 ; Get pointer
JSR (A1) ; Call Hook
BNE.S AbortSleep
BRA.S @traverse
@closeAT ; ENDIF
BSR.W CheckAppleTalk ; Close AppleTalk
BNE.S 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
BNE.S AbortSleep ; Ok to goto sleep ? Nope. Get out!
BSR.W CloseAppleTalk ; Else shut down atalk
BCLR #InSleep,PmgrFlags(A0) ; clr the sleep indicator
jmpROM SomeSleepProc
AbortSleep BCLR #InSleep,PmgrFlags(A0) ; Clear the sleep indicator
Exit MOVE.W D2,D0 ; Restore sleep type to D0
MOVEM.L (SP)+,A0-A6/D1-D7
MOVE.W (SP)+,SR
RTS ; Return to caller
;———————————————————————————————————————————————————————————————————————
;
; 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
;________________________________________________________________________________________
;
; 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
jsrROM 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
;———————————————————————————————————————————————————————————————————————
;
; 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
portaSysTask PatchProc _SystemTask,(Portable)
WITH PmgrRec
jsrOld
MOVE.L PmgrBase,A1
TST.B MBState
BNE.S @clicked
@idleUpdate
_IdleUpdate
RTS
@clicked
TST.B watchCrsr(A1)
BNE.S @idleUpdate
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 PROC EXPORT
WITH PmgrRec,pmCommandRec,SleepqRec
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
CMP.W #1,D1
BNE.S @callproc
TST.W D0
BNE.S @exit ; if result != zero, exit
@callproc
MOVE.L d1,d0 ; restore type to d0
MOVEM.L ProcRegs,-(sp) ; save the world before calling proc <15> ag
MOVE.L SleepqProc(a0),a1 ; get a pointer to the proc
JSR (a1) ; call sleep proc
MOVEM.L (sp)+,ProcRegs ; restore the world
TST.L d0 ; set condition codes on result
RTS
@noelement moveq #0,d0 ; clear result
@exit RTS ; exit
portaPowerOff PatchProc _PowerOff,(Portable)
MOVE.W #60,A0
_Delay
SUB #4,SP ; clear pmData
MOVE.L SP,A0
CLR.L (A0)
MOVEQ #0,D1
MOVEQ #pMgrADBoff,D0
MOVE.L A0,-(SP) ; pmRBuffer -> pmData
MOVE.L A0,-(SP) ; pmSBuffer -> pmData
MOVE.W D1,-(SP) ; pmLength = 0
MOVE.W D0,-(SP) ; pmCommand = pMgrADBoff
MOVE.L SP,A0
_PmgrOp
LEA 8(SP),SP ; fix the stack, preserving A0 (why?)
MOVE.L (SP)+,A0
ADD #4,SP
_HideCursor
CLR.L WarmStart
MOVE.W #SleepNow,D0
_Sleep
RTS
pollProcRegs reg d0-d6/a0-a4
;-----------------------------------------------------------------------------------------
;
; 1/29/90 MSH SCCWakeFix - Can you beleive another hardware problem with the serial <8>
; ports? This one concerns external modems connected while the SCC is turned
; off. The machine will lock up after going to sleep and waking a few times
; because the external device somehow makes the SCC generate an interrupt.
; The fix is an entry in the sleep queue that resets the SCC when no drivers
; are using it.
;
;-----------------------------------------------------------------------------------------
SCCWakeFix PROC EXPORT
EXPORT WakeQRec
CMP.W #SleepWakeUp,D0 ; Execute only during wake up
BNE.S @boogie
MOVE.B PortAUse,D0 ; And only if the serial ports are free
AND.B PortBUse,D0
BPL.S @boogie
MOVE.B #1,D0 ; Power up a channel (no modem) <6> MSH
_SerialPower
MOVE.L SCCWr,A0 ; Reset the SCC
MOVE.B #9,actl(A0)
MOVE.B #$C0,actl(A0)
MOVE.B #$81,D0 ; Power off the channel (no modem) <6> MSH
_SerialPower
@boogie MOVEQ #0,D0
RTS
WakeQRec DC.L 0
DC.L 0
DC.L 0
ENDPROC
;_______________________________________________________________________
;
; SndWatch - A vbl task called once every ten seconds. Checks the sound
; latch for ASC new use. If so then sound power is turned on. If power is
; already on then then the latch is cleared. Leave power on to the sound
; circuit on backlighted units, noise problems.
;_______________________________________________________________________
SndWatch PROC
WITH PmgrRec
MOVE.L PmgrBase,A2
LEA SwVBLTask(A2),A0 ; Get pointer to vbl task
MOVE.W #SndWFreq,vblCount(A0) ; Do it again
SUB.W #4,SP ; Create stack frame
MOVE.L SP,A0
MOVE.W #SoundRead,D0 ; PMGR command, get sound state
jsrROM PMGRrecv
MOVE.B (A0),D2 ; Get sound state
BTST #1,D2
BEQ.S @Clearlatch ; Branch if latch is set
_IdleUpdate ; update activity indicator
@Clearlatch MOVE.B #sndOnclrLtch,(A0) ; Turn on sound power and clear the latch
MOVEQ #1,D1 ; One byte to send
MOVE.W #SoundSet,D0 ; PMGR command, set sound state
jsrROM PMGRsend
@noSound
ADD.W #4,SP ; Release stack frame
RTS
endproc
;_______________________________________________________________________
;
; BatWatch - Battery monitoring for low power conditions. If so,
; the user is alerted via the notification manager. Dirty sleep and
; hard disk time outs are updated too.
;
; Upon entry: A1 - VIA base
;
;
; A0-A3, D0-D3 are preserved by the interrupt dispatcher.
;
;_______________________________________________________________________
BatWatch PROC
WITH PmgrRec
WITH SleepQRec,pmCommandRec ; <11> rb
MOVE.L PmgrBase,A2 ;
TST.B SysTaskFlag(A2) ; is it ok to use notification manager
BNE.S @didsystask ; ... if yes, check battery
LEA BatVBLTask(A2),A0 ; Get pointer to vbl task
MOVE.W #BatFreq,vblCount(A0) ; Do it again
RTS
@didsystask jsrRom GetLevel ; 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 jsrRom 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)
BNE.S @lpowermode ; <2> … continue with low power stuff
MOVEQ #1,D0 ; <2> … remap level 2 to level 1
@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 jsrRom RemoveMsg ; Remove previous level message
jsrRom 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
MOVE.L Rombase,A1 ; Check for version of PRAM <12> HJR
CMP.W #$67C,8(A1) ; Are we running a Terror Machine <12> HJR
BEQ.S @TerrorMachines ; Branch not portable or asahi. <12> HJR
TST.B TOdirtyFlag(A2) ; Check for new timeouts
BEQ.S @exit
CLR.B TOdirtyFlag(A2) ; Clear the dirty flag
SUB.W #8,SP ; allocate buffer <12> HJR
MOVE.L SP,A0 ; Set buffer pointer <12> HJR
MOVE.L #$080070,D0 ; Read our parameters
_ReadXPRam
MOVE.B 7(A0),SleepFlags(A2) ; Portable & Asahi use PRAM 77 as SleepFlags <12> to next <12> HJR
MOVE.W (A0),SleepTime(A2) ; Get latest timeouts
ADD.W #8,SP ; Free buffer
_IdleUpdate
BRA.S @exit
@TerrorMachines
TST.B LastLevel(A2) ; Is the level -1
BPL.S @Next ; Not try next check
BCLR #PmgrWakeLvlSet,PmgrFlags(A2) ; Is the semaphor set
BEQ.S @FinishUp ; Nope. Then skip and go on
MOVE.B #(PMGRWARNLEVEL-STDOFFSET),D0 ; Otherwise, set warning level to 5.90 V
BSR.S @SetPmgrLevl ; go do it...
BRA.S @FinishUp ; and get on with life
@Next CMP.B #4,LastLevel(A2) ; Check if we are in level 4
BNE.S @FinishUp ; If not, go on
TST.B Level4Cnt(A2) ; Is it the first time through
BNE.S @FinishUp ; If not, go On
MOVE.B #(PGMRWAKELEVEL-STDOFFSET),D0 ; Set hysteresis to 6.09
BSET #PmgrWakeLvlSet,PmgrFlags(A2) ; Set the semaphor
BSR.S @SetPmgrLevl ; go do it...
@FinishUp TST.B TOdirtyFlag(A2) ; Check for new timeouts
BEQ.S @exit
CLR.B TOdirtyFlag(A2) ; Clear the dirty flag
SUB.W #8,SP ; allocate some stack space
MOVE.L SP,A0 ; set param block
MOVE.L #$080070,D0 ; Read our parameters
_ReadXPRam
MOVE.B 2(A0),SleepFlags(A2) ; Terror use Pram 72 as SleepFlags <r9> HJR
MOVE.W (A0),SleepTime(A2) ; Get latest timeouts
ADD.W #8,SP ; free the buffer
_IdleUpdate
@exit RTS
@SetPmgrLevl
LEA -(PmBlkSize+4)(SP),SP ; Get a little storage
LEA @SetLvlParm,A0 ; point to the packet
MOVE.B D0,2(A0) ; set the appropriate level
MOVE.L A0,pmSBuffer(SP) ; point to the packet
MOVE.W #3,pmLength(SP) ; send 3 bytes
MOVE.W #xPramWrite,pmCommand(SP); write to x pram
MOVE.L SP,A0 ; set pointer
_PmgrOp
LEA (PmBlkSize+4)(SP),SP ; Release stack frame
RTS
@SetLvlParm
DC.B ($42) ; pram byte 0x42
DC.B 1 ; one bytes of data
DC.B 0 ; warn level to set on pmgr <12> from last <12> HJR
ENDPROC
portaInstallWake InstallProc (Portable)
MOVE.L PmgrBase,A1
leaResident portaWakeUp,A2
MOVE.L A2,PmgrRec.WakeVector(A1)
RTS
portaWakeUp PROC EXPORT
WITH PmgrRec
MOVE.L #wmStConst,WarmStart
MOVE.L SndBase-4,SP
MOVE.W #6,RAMconfigBase
MOVE.L PmgrBase,A2
CLR.B Level4Cnt(A2)
MOVE.B #$FF,LastLevel(A2)
CLR.L BatQ(A2)
CLR.L BatQ+4(A2)
MOVE.B #8,BatQIndex(A2)
MOVE.L ASCBase,A0
LEA $808(A0),A0 ; unknown offset?!
MOVEQ #6,D0
@ascResLoop MOVE.B (SP)+,-(A0)
DBRA D0,@ascResLoop
TST.B ascFifoInt(A0)
MOVE.L VIA,A0
MOVEM.W (SP)+,D0-D5
MOVE.B D0,vBufB(A0)
MOVE.B D1,vDIRB(A0)
MOVE.B D2,vBufA(A0)
MOVE.B D3,vIER(A0)
MOVE.B D4,vACR(A0)
MOVE.B D5,vPCR(A0)
MOVE.B vT2CH(A0),vT2CH(A0)
MOVE.B vT1CH(A0),vT1CH(A0)
MOVE.L (SP)+,ResetPC
jsrROM InitSCSI ; Init the SCSI chip
LEA Time,A0 ; Restore Time
MOVEQ #timeRead,D0
jsrROM PMGRrecv
jsrROM KbdReset ; clear the keyboard maps
MOVEM.L (SP)+,D1-D7/A0-A6
SUB #56,SP
MOVE.W 56(SP),SR
BSR SCSIDiskWakeAlert ; check if a disk mode cable is plugged in
BSR.S MPPOpen ; Open the driver since elements in the queue might need some MPP services
MOVEQ #SleepWakeUp,D0 ; Go through wake queue
jsrROM DoQueue ; Run through the queue in proper order
_CountADBs
CMP.B #2,D0
BLE.S @noReInit
_ADBReInit
@noReInit
MOVEQ #0,D0
MOVEM.L (SP)+,D1-D7/A0-A6
ADD.L #2,SP
RTS
;———————————————————————————————————————————————————————————————————————
;
; 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)
SUB.L #ioQElSize,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
;———————————————————————————————————————————————————————————————————————
;
; SCSIDiskWakeAlert - Checks if the SCSI Disk Mode cable is plugged in when
; we wake up. If it is, put up a DeepShit window with a message.
;
;———————————————————————————————————————————————————————————————————————
SCSIDiskWakeAlert
MOVE.L SP,D3
MOVE.L ROMBase,A0
CMP.B #$11,ROMHeader.ROMRelease(A0)
BNE.W @return
BSR TestForDiskMode
BNE @return
; save the pixels that will be clobbered by the DS alert
CLR.L D4
CLR.L D5
TST.B QDExist
BNZ.S @savedErrBoxPixels
MOVE.L GrafGlobals(A5),A0
MOVE.L thePort(A0),D4
MOVE.L #bitmapRec+448*126/8,D0 ; bitmap rec + 8bit data
_NewPtr
TST.W D0
BNE.S @savedErrBoxPixels
MOVE.L A0,D5 ; this is the dest bitmap, saved...
PEA bitmapRec(A0) ; set baseAddr to the guts of the buffer
MOVE.L (SP)+,(A0)+
MOVE.W #56,(A0)+ ; set rowBytes
MOVE.L #$00000000,(A0)+ ; topLeft
MOVE.L #$007E01C0,(A0)+ ; botRight
SUBA #$74,SP
MOVE.L SP,A6
jsrROM AllocFakeRgns
MOVE.L SP,-(SP)
_InitPort
MOVE.L GrafGlobals(A5),A0
MOVE.L A6,thePort(A0)
PEA screenBits(A0) ; srcBits = the screen
MOVE.L D5,-(SP) ; dstBits = our new allocated bitmap
BCLR #7,DSAlertRect ; SECRETFLAG = 0
PEA DSAlertRect ; srcRect = rect where error box goes
MOVE.L D5,A0
PEA bounds(A0) ; dstRect = our entire allocated bitmap
CLR.W -(SP) ; mode = 0
CLR.L -(SP) ; maskRgn = nil
_CopyBits
BSET #7,DSAlertRect ; SECRETFLAG = 1
@savedErrBoxPixels
; put the alert on the screen and wait until the cable is removed...
MOVE.W #dsSCSIWarn,D0 ; put up the DeepShit alert
_SysError
@NotGone MOVEA.L VIA,A0
MOVEQ #3,D1
@OuterLoop MOVE.W #$7FFF,D0
@InnerLoop TST.B (A0) ; throttle the loop with a VIA access
DBRA D0,@InnerLoop
DBRA D1,@OuterLoop
BSR TestForDiskMode ; is the disk mode cable still attached?
BEQ.S @NotGone ; -> yep, keep waiting
; they finally removed the cable, so clean everything up...
TST.L D5
BEQ.S @useGNE
MOVE.L D5,-(SP) ; srcBits = our bitmap
MOVE.L GrafGlobals(A5),A0
MOVE.L A6,thePort(A0)
PEA screenBits(A0) ; dstBits = the screen
MOVE.L D5,A0
PEA bounds(A0) ; srcRect = our entire allocated bitmap
BCLR #7,DSAlertRect ; SECRETFLAG = 0
PEA DSAlertRect ; dstRect = rect where error box goes
CLR.W -(SP) ; mode = 0
CLR.L -(SP) ; maskRgn = nil
_CopyBits
BSET #7,DSAlertRect ; SECRETFLAG = 1
MOVE.L D5,A0
_DisposePtr
ADDA #$74,SP
BRA.S @reSetPort
@useGNE
CLR.B DSWndUpdate ; flag GNE to remove the alert
TST.L D4
BEQ.S @return
@reSetPort
MOVE.L D4,-(SP)
_SetPort
@return
RTS
;———————————————————————————————————————————————————————————————————————
;
; TestForDiskMode - checks if we're setup for SCSI Disk Mode
;
; input
; none
;
; output
; CCR - BEQ if the SCSI DiskMode cable is attached
;
;———————————————————————————————————————————————————————————————————————
TestForDiskMode
MOVE.L #$00EE01<<8,-(SP) ; populate pmData
MOVE.L SP,-(SP) ; pmRBuffer -> pmData
MOVE.L (SP),-(SP) ; pmSBuffer -> pmData
MOVE.W #3,-(SP) ; pmLength
MOVE.W #readPmgrRAM,-(SP) ; pmCommand
MOVE.L SP,A0
_PmgrOp
MOVE.L pmCommandRec.pmData(SP),D0
BTST #29,D0
LEA pmCommandRec.pmBlkSize(SP),SP
RTS
portaInitializeStrings InstallProc (Portable)
;___________________________________________________________________________________
; Routine: InitializeStrings
;
; Inputs: none
;
; Outputs: none
;
; Destroys: d0-d3,a0-a2
;
;___________________________________________________________________________________
InitializeStrings
SignatureReg equ $FC0200 ; address of backlight signature
SignatureAruba equ $A5 ; signature for aruba backlight
SignatureUpgrd equ $A3 ; signature for upgrade backlight
SignatureAsahi equ $AD ; signature for asahi backlight
LPsicnNum EQU -16386 ; Small battery icon
LPstr0Num EQU -16386 ; no backlight
LPstr0NumBL EQU -16511
LPstr1NumBL EQU -16512
LPstr2NumBL EQU -16516 ; Added new one for Andy <r9> HJR
LPstr3NumBL EQU -16513
BatstrWarn0 EQU -16514 ; <t5> new bad battery strings
BatstrWarn1 EQU -16515
WITH PmgrRec
MOVE.L PmgrBase,A2
MOVE.L #'SICN',D1
MOVE.W #LPsicnNum,D2
BSR GetDetachRes ; Get the battery icon
BEQ.S @getstrings
MOVE.L A1,lpSICNHndl(A2) ; Save the handle locally
@getstrings MOVE.L #SignatureReg,A0
CMP.B #SignatureAruba,(A0)
BEQ.S @dimmable
CMP.B #SignatureUpgrd,(A0)
BEQ.S @dimmable
CMP.B #SignatureAsahi,(A0)
BEQ.S @dimmable
MOVEQ #3,D4 ; strings for non-backlit screen
MOVE.W #LPstr0Num,D2
MOVEQ #lpSTR0Ptr,D3
@loop BSR LoadString
SUB.W #1,D2
ADD.L #4,D3
DBRA D4,@loop
BRA @return
@dimmable
move.w #LPstr0NumBL,D2 ; get first warning string
move.l #lpSTR0Ptr,D3
bsr LoadString
move.w #LPstr1NumBL,D2 ; get 25% warning string
move.l #lpSTR2Ptr,D3
bsr LoadString
move.w #LPstr3NumBL,D2 ; get 10 second warning
move.l #lpSTR3Ptr,D3
bsr.s LoadString
@return rts
;------------------------------------------------------------------------------------------
;
; LoadString - used to load a low power string into the power manager globals
;
; input
; a2 - pointer to powermgr
; d2 - string resource id
; d3 - offset of string pointer in powermanager
;
; output
; none
;
; usage
; d d1 - resource type
; d2 - string resource id
; d3 - offset of string pointer in powermanager
; d a1 - handle to string
; a2 - pointer to powermgr
;------------------------------------------------------------------------------------------
LoadString move.l #'STR ',d1 ; set to string resource type
bsr.s GetDetachRes ; get and detach string resource
beq.s @exit ; if no string, exit
move.l (a1),(a2,d3) ; else install pointer in pmgr globals
@exit rts ; done
; Gets and detaches a resource.
; Parameters:
; D1 Resource Type
; D2 Resource ID
; Returns:
; A1 Handle to resource
; Registers:
; D0/A0 destroyed
GetDetachRes
SUBQ.L #4, SP ; For return address
MOVE.L D1, -(SP) ; Resource type
MOVE.W D2, -(SP) ; Resource ID
_GetResource
MOVE.L (SP), A1 ; Get resource handle to return
_DetachResource
MOVE.L A1,D0 ; Set result code
RTS
;=================================================================================== <r9> thru next <r9> djw
; PowerMiscPatches - collection of all the Terror patches
;
; This routine calls all the different Terror ROM specific patches.
;
;===================================================================================
machine mc68030
InstallPowerMgrPatches InstallProc (IIci,hasTerror,hasPwrMgr)
bsr ResetSoftwareCutoff ; reset the power mgr's shutdown level
bsr InitializeStrings ; init all warning and alert strings
bsr InstallSleepTask ; install sleep queue task to do general patches
bsr PatchSetCursor ; patch _SetCursor to check for activity
bsr PatchSndVBL ; install a new SndWatch VBL
bsr PatchBatInt ; install a new BatInt handler <r16> HJR
bsr PatchBatWatchVBL ; install a new BatWatch VBL <r9> HJR
bsr PatchPmgrOp ; patch _PmgrOp
rts ; <r9> from last <r9> djw
;___________________________________________________________________________________
; Routine: ResetSoftwareCutoff
;
; Inputs: none
;
; Outputs: none
;
; Destroys: a1
;
;___________________________________________________________________________________
ResetSoftwareCutoff
WITH PmgrRec,PmgrPramRec ; <12> HJR
WITH SleepQRec,pmCommandRec ; <11> rb
; set 68k cutoff voltage in pmgr globals
move.l PmgrBase,A1
lea -(PmBlkSize+4)(SP),SP ; Get a little storage
; set pmgr cutoff voltage
lea @PRAM_PACKET,a0 ; point to the packet
move.l a0,pmSBuffer(sp) ; point to the packet
move.w #4,pmLength(SP) ; <12> HJR
move.w #xPramWrite,pmCommand(SP) ; write to x pram
move.l SP,A0
_PmgrOp
BCLR #PmgrWakeLvlSet,PmgrFlags(A1) ; Clear Hysterosis semaphor <12> to next <12> HJR
move.b #(NEWCUTOFF-STDOFFSET),Cutoff(a1) ; set the new cutoff threshold to 5.75
MOVE.B #(PMGRWARNLEVEL-STDOFFSET),LowWarn(a1) ; set the new low warning threshold
MOVE.L #((PmgrPramSize<<16)+\
PmgrPramBase),D0 ; Read all PMGR/Esprit data
_ReadXPRam
TST.B SlpTimeOut(A0) ; Check for zeroed Sleep time out
BEQ.S @dowrite
TST.B HDTimeOut(A0) ; Check for zeroed time outs and warning levels
BNE.S @skipwrite
@dowrite MOVE.B #DfltSlpTime,(A0) ; Init default time outs
MOVE.B #DfltHDTime,1(A0)
MOVE.L #((2<<16)+PmgrPramBase\
+SlpTimeOut),D0 ; Write
_WriteXPRam ; Set them
MOVE.W #((DfltSlpTime << 8) +\
DfltHDTime),SleepTime(A1) ; Writeout values to globals
@skipwrite lea (PmBlkSize+4)(SP),SP ; Release stack frame
move.w #$c0,PwrCycProgMax(a1) ; set max powercycle level lower <12> from last <12> HJR
rts
@PRAM_PACKET dc.b ($42) ; pram byte 0x42
dc.b 2 ; <8> two bytes of data
dc.b (PMGRWARNLEVEL-STDOFFSET) ; <8> warn level to set on pmgr
dc.b (NEWCUTOFF-STDOFFSET) ; cutoff to set tono pmgr
align 4 ; <r9> djw
;___________________________________________________________________________________
; Routine: InitializeStrings
;
; Inputs: none
;
; Outputs: none
;
; Destroys: d0-d3,a0-a2
;
;___________________________________________________________________________________
InitializeStrings
LPsicnNum EQU -16386 ; Small battery icon
LPstr0NumBL EQU -16511
LPstr2NumBL EQU -16516 ; Added new one for Andy <r9> HJR
LPstr3NumBL EQU -16513
BatstrWarn0 EQU -16514 ; <t5> new bad battery strings
BatstrWarn1 EQU -16515
WITH PmgrRec
MOVE.L PmgrBase,A2
MOVE.L #'SICN',D1
MOVE.W #LPsicnNum,D2
BSR GetDetachRes ; Get the battery icon
BEQ.S @getstrings
MOVE.L A1,lpSICNHndl(A2) ; Save the handle locally
@getstrings move.w #LPstr0NumBL,D2 ; get first warning string
move.l #lpSTR0Ptr,D3
bsr LoadString
move.w #LPstr2NumBL,D2 ; get 25% warning string
move.l #lpSTR2Ptr,D3
bsr.s LoadString
move.w #LPstr3NumBL,D2 ; get 10 second warning
move.l #lpSTR3Ptr,D3
bsr.s LoadString
@batterywarn move.w #BatstrWarn0,D2 ; <t5> get 1st battery warning
move.l #BBSTR0Ptr,D3
bsr.s LoadString
move.w #BatstrWarn1,D2 ; <t5> get 2nd battery warning
move.l #BBSTR1Ptr,D3
bsr.s LoadString
rts
;------------------------------------------------------------------------------------------
;
; LoadString - used to load a low power string into the power manager globals
;
; input
; a2 - pointer to powermgr
; d2 - string resource id
; d3 - offset of string pointer in powermanager
;
; output
; none
;
; usage
; d d1 - resource type
; d2 - string resource id
; d3 - offset of string pointer in powermanager
; d a1 - handle to string
; a2 - pointer to powermgr
;------------------------------------------------------------------------------------------
LoadString move.l #'STR ',d1 ; set to string resource type
bsr.s GetDetachRes ; get and detach string resource
beq.s @exit ; if no string, exit
move.l (a1),(a2,d3) ; else install pointer in pmgr globals
@exit rts ; done
; Gets and detaches a resource.
; Parameters:
; D1 Resource Type
; D2 Resource ID
; Returns:
; A1 Handle to resource
; Registers:
; D0/A0 destroyed
GetDetachRes
SUBQ.L #4, SP ; For return address
MOVE.L D1, -(SP) ; Resource type
MOVE.W D2, -(SP) ; Resource ID
_GetResource
MOVE.L (SP), A1 ; Get resource handle to return
_DetachResource
MOVE.L A1,D0 ; Set result code
RTS
;___________________________________________________________________________________ <r9> thru next <r9> djw
; Routine: InstallSleepTask
;
; Install a new sleep queue element to handle miscellaneous system sleep patches.
; These include saving the state of the cursor before going to sleep and restore
; it after waking up. On wakeup, check the state of DFAC (sound input). If a
; source is selected, then power on Batman, otherwise do nothing (the ROM already
; powered Batman off).
;
; Also patch out the Sleep trap to fix a re-entrancy problem.
;
; Inputs: none
; Outputs: none
;___________________________________________________________________________________
InstallSleepTask
MOVE.L A1,-(SP) ; Save Register
LeaResident SleepPtch,A0 ; Get address of sleep code
MOVE.W #$A08A,D0 ; Set the trap
_SetTrapAddress ,newOS ; Install the trap
MOVE.L #SleepqSize+12,D0 ; Size pf Sleep Queue element plus some extra
_NewPtr ,SYS,CLEAR
LeaResident SleepMiscTask,A1 ; Get pointer to Sleep Queue element
MOVE.L A1,SleepqProc(A0) ; Set the Proc Pointer to our handle
MOVE.W #slpQType,SleepqType(A0) ; Set the proper type
_SlpQInstall ;
MOVE.L (SP)+,A1 ; Restore Register
RTS
;_________________________________________________________________________________________
; PatchSetCursor - head patch setcursor
;
; Head patch setcursor to check for activity.
;_________________________________________________________________________________________
PatchSetCursor
move.w #$a851,d0 ; trap number for _SetCursor
_GetTrapAddress ,NewTool ; get addr of _SetCursor
leaResident OldSetCursor,a1
move.l a0,(a1) ; save the old address to chain to
move.w #$a851,d0 ; trap number for _SetCursor
leaResident SetCursorPatch,a0 ; address of head patch
_SetTrapAddress ,NewTool ; install head patch
rts
;_________________________________________________________________________________________
; PatchSndVBL - install SndWatch VBL
;
; Replace the ROM SndWatch VBL because it does not take DFAC activity into
; consideration before it clears the sound latch. This will correct a problem where
; on waking from sleep, if recording was on before sleep, it is now off.
;_________________________________________________________________________________________
PatchSndVBL
movea.l PmgrBase,a2 ; get power mgr globals
lea SwVBLTask(a2),a0 ; a0 = ptr to SndWatch VBL queue blk
_VRemove ; remove it from the queue
leaResident NewSndWatch,a1 ; a1 = addr of new SndWatch resident code
move.l a1,vblAddr(a0)
move.w #1,vblCount(a0) ; enable vbl element
_Vinstall
leaResident ModemSndOnInt,a0 ; patch out modem sound int handler
move.l PmgrBase,a1 ; get pointer to globals
move.l a0,MdmSndVect(a1) ; set new modem sound handler
rts
;_________________________________________________________________________________________
; PatchBatInt - install the new BatInt <r16> HJR
;
; Fix bug where system crashes when a new a low power dialog comes in after the shorted
; battery dialog is set.
;_________________________________________________________________________________________
PatchBatInt
movea.l PmgrBase,a2 ; get power mgr globals
leaResident NewBatInt,a1 ; a1 = ptr to NewBatInt handler
move.l a1,vBatInt(a2) ; save the vector
rts
;_________________________________________________________________________________________
; PatchBatWatchVBL - install BatWatch VBL <r9> HJR
;
; Replace the ROM Batwatch VBL because it does not work.
;_________________________________________________________________________________________
PatchBatWatchVBL
movea.l PmgrBase,a2 ; get power mgr globals
lea BatVBLTask(a2),a0 ; get pointer to vbl queue element
_VRemove ; remove it from the queue
leaResident BatWatch,a1
move.l a1,vblAddr(a0)
move.w #1,vblCount(a0) ; enable vbl element
_Vinstall
rts
;_________________________________________________________________________________________
; PatchPmgrOp - patch _PmgrOp
;
; Install a patch to _PmgrOp to delay 100µs after a power on/off command before
; returning to the caller. This is a preventative measure to take into account that
; the pmgr micro may not have actually executed the command request when it acknowledges.
; A race condition exist where the caller may assume the power on something is on or off
; when it actually is not.
;_________________________________________________________________________________________
PatchPmgrOp
move.w #$a085,d0 ; trap number for _PmgrOp
leaResident PmgrOpPatches,a0 ; address of patch
_SetTrapAddress ,NewOS ; install patch
rts
endp ; end installproc
;=========================================================================================
;=========================================================================================
; ABOVE THIS POINT IS INSTALL CODE FOR TERROR PATCHES. BELOW THIS POINT IS RESIDENT
; PATCH CODE.
;=========================================================================================
;=========================================================================================
;_________________________________________________________________________________________
; SleepPatch
;
; This is a patch to the sleep trap so to fix a reentracy bug.
; Sleep Selector (only valid selectors)
; d0 - 1 - SleepRequest
; 2 - SleepDemand
; 6 - SleepNow
;
; input
; d0 sleep type
; d1 trapword
;
; output
; none
;
; usage
; d0 sleep type
; d1 trap word
; d2 copy of sleep type
; d3 condition code test register
;
; a0 pointer to first element/ ptr to pmgrglobals
; a1 pointer to network hook
;_________________________________________________________________________________________
SleepPtch PROC
IMPORT DoQueueStack
WITH PmgrRec
BTST #9,D1 ; $A28A
BEQ.S @TryNext ; Check if condition code is set
JmpROM SlpQInstall
@TryNext
BTST #10,D1 ; $A48A
BEQ.S @Sleep ; Check if condition code is set
JmpROM SlpQRemove
@Sleep ; $A08A
MOVE.L PMgrBase,A0 ; Get Power Manager Base Pointer
BTST #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
JsrROM SetSupervisorMode ; Set the machine to supervisor mode
MOVE.W D0,PwrCycSave.PCRSRsave(A0) ; Save the store away the status register
MOVE.L D1,D0 ; restore the sleep type
bsr.s DreamAway ; <15> Take a snooze the new way
MOVE.W PwrCycSave.PCRSRsave(A0),SR ; Restore the Status Register to the proper world
@Exit
RTS
;——————————————————————————————————————————————————————————————————————— <8> HJR
; <15> Sleep queue fix.
DreamAway ; <15>
SleepRegs REG A0-A6/D1-D7
MOVEM.L SleepRegs,-(SP) ; Save registers
MOVE.L D0,D2 ; Save a sleep type in D2
@checkinprogress
BSET #InSleep,PmgrFlags(A0) ; test and set sleep semaphore <17> ag
BNE.S @exitsleep ; if in sleep, exit! don't re-enter
@checkAuto
CMP.B #SleepRequest,D0 ; auto sleep request
BEQ.S @validselector
@checkDemand
CMP.B #SleepDemand,D0 ; User sleep, from finder or command key
BEQ.S @validselector
@checkNow
CMP.B #SleepNow,D0 ; Critical low power sleep <v1.4>
BNE.S @abortsleep
@validselector
MOVE.W PwrCycSave.PCRSRsave(A0),SR ; Restore the SR so that when VM is on the queue is run in User Mode
BCLR #AvoidNetDiag,PmgrFlags(A0) ; <t3> tst/clear the avoid bit
BNE.S @traverse ; <t30> if bit was set, skip dialog
MOVE.L SleepNetHook(A0),D1 ; Test for presence of valid hook
BEQ.S @closeAT ; Nope. Branch
MOVEA.L D1,A1
JSR (A1) ; Hook
BNE.S @abortsleep ; IF Bad Close THEN branch
BRA.S @traverse ; ELSE run the queue
@closeAT jsrRom ROMCheckAppleTalk ; Close AppleTalk <v1.4>
BNE.S @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 DoQueueStack ; Walk the queue
MOVE.L D0,D1 ; Save a copy of DoQueueStack result
jsrRom SetSupervisorMode ; Return to supervisor mode so that we may continue
TST.L D1 ; DoQueueStack == Ok to goto sleep ?
BNE.S @abortsleep ; Nope. Get out!
jsrRom CloseAppleTalk ; Else shut down atalk
BCLR #InSleep,PmgrFlags(A0) ; clr the sleep indicator <17> ag
jmpRom didqueue ; Do the sleep shutdown
@abortsleep jsrRom SetSupervisorMode ; Set the machine to supervisor mode <22> ag
BCLR #InSleep,PmgrFlags(A0) ; Clear the sleep indicator <17> ag
@exitsleep MOVE.W D2,D0 ; Restore sleep type to D0
MOVEM.L (SP)+,SleepRegs
RTS
ENDPROC ; SleepPtch
;_________________________________________________________________________________________
; SleepMiscTask
;
; This sleep task is run for both sleep and wakeup. It executes all the miscellaneous
; system patches which can fit in a sleep queue task.
;
; Cursor state across sleep:
; Save the state of the cursor in extra space of the sleep queue element on sleep, and
; restore the state of the cursor on wakeup.
;
; Batman power state on wakeup:
; If sound input is active (i.e. there is an input source selected on DFAC), then power
; on Batman.
;
; Input: A0 = Ptr to sleep queue element
; D0 = sleep command
;
; Output: D0 - Result code.
;_________________________________________________________________________________________
Proc
Export SleepMiscTask
WITH PMgrRec ; <12> HJR
WITH SleepQRec,pmCommandRec ; <11> rb
SleepMiscTask
BRA.S @HandleCommand ; Handle Sleep Queue Demand
@SlpQueueDisp ; Table of offset to selector routines
DC.W @SlpRequest-@SlpQueueDisp ; SleepRequest = 1
DC.W @SlpDemand-@SlpQueueDisp ; SleepDemand = 2
DC.W @SlpWakeUp-@SlpQueueDisp ; SleepWakeUp = 3
DC.W @SlpUnlock-@SlpQueueDisp ; SleepUnlock = 4
DC.W @SlpDeny-@SlpQueueDisp ; SleepDeny = 5
@LastVect DC.W @SlpNow-@SlpQueueDisp ; SleepNow = 6
@HandleCommand
SUBQ.W #1,D0 ; Convert commands to zero base
CMP.W #(@LastVect-@SlpQueueDisp)/2,D0; check if in range
BHI.S @OutOfRange ; Nope. Out of here folks
MOVE.W @SlpQueueDisp(D0.W*2),D0 ; get the offset to that routine
JMP @SlpQueueDisp(D0) ; Jump to that routine
@OutOfRange
MOVE.W #paramErr,D0 ; Abort and return error
RTS
@SlpRequest BRA.S @Done ; Bye folks
@SlpDemand BSR.S SaveCursor ; Time to save the cursor
moveq #SleepDemand,d0 ; tell blocksonyvbl what kind of queue event<15> ag
BSR BlockSonyVBL ; <15> ag
BRA.S @Done
@SlpWakeUp BSR.S RestoreCursor ; Restore Cursor
BSR.S BatmanPower ; decide whether to power on sound
BSR.S SetPwrLvlTask ; Set PowerMgr power level <12> HJR
moveq #SleepWakeUp,d0 ; tell blocksonyvbl what kind of queue event<15> ag
BSR BlockSonyVBL ; <15> ag
BRA.S @Done
@SlpUnlock
@SlpDeny BRA.S @Done ; Bye folks
@SlpNow BSR.S SaveCursor ; Time to save the cursor
** BRA.S @Done ; (fall thru)
@Done MOVEQ #0,D0 ; Return noErr
RTS
;_________________________________________________________________________________________
; SaveCursor - misc sleep queue task
;
; This routine will save the current cursor in some extra space allocated in the
; sleep queue element.
;
; Enter: A0 - Ptr to sleep queue element
;
; Exit: none
;_________________________________________________________________________________________
SaveCursor
MOVE.L A1,-(SP) ; Save register
MOVE.L (A5),A1 ; point to QuickDraw globals
LEA Arrow(A1),A1 ; Get pointer to current cursor
MOVE.L A1,SleepqSize(A0) ; save the address of cursor in our little storage
MOVE.L (SP)+,A1 ; Restore register
RTS ; Goodbye
;_________________________________________________________________________________________
; RestoreCursor - misc sleep queue task
;
; This routine will restore the state of the cursor after wake-up with the cursor stored
; in the queue element.
;
; Enter: A0 - Ptr to sleep queue element
;
; Exit: none
;_________________________________________________________________________________________
RestoreCursor
MOVE.L SleepqSize(A0),-(SP) ; Get ptr to saved crsr in slpqueue element
_SetCursor ; Set the cursor
_ShowCursor ; Show it to the world
RTS ; Goodbye
;_________________________________________________________________________________________
; BatmanPower - misc sleep queue task
;
; The ROM on waking from sleep has powered off Batman. Because we forgot to do this
; in the ROM, we must now check the state of DFAC. If a sound input source has been
; selected, then power Batman back on so sound input will work.
;
; Input: a0 = ptr to sleep queue element
;
; Output: none
;_________________________________________________________________________________________
BatmanPower
jsrTbl sndInputSource ; get current DFAC input source
tst.b d0 ; anything selected?
beq.s @Done ; nothing selected
move.l a0,-(sp) ; save reg
suba.w #4,sp
movea.l sp,a0 ; a0 = ptr to data buf
move.b #sndOnclrLtch,(a0) ; Turn on sound power and clear the latch
moveq.l #1,d1 ; One byte to send
move.w #SoundSet,d0 ; PMGR command, set sound state
jsrROM PMGRsend
adda.w #4,sp ; restore stack
movea.l (sp)+,a0 ; restore reg
@Done
rts
;_________________________________________________________________________________________ <12> HJR
; SetPwrLvlTask -
;
; This routine on wakeup set the power manager power levels to appropriate wakeup
; values since it might have changed due to the 10 second level 4 count down.
;
; Input: None
;
; Output: None
;_________________________________________________________________________________________
SetPwrLvlTask
MOVE.L A0,-(SP) ; Save this guy
MOVE.L PMgrBase,A0 ; Get our globals
BCLR #PmgrWakeLvlSet,PmgrFlags(A0) ; Clear Hysteresis semaphore
LEA -(PmBlkSize+4)(SP),SP ; Get a little storage
LEA @PramPak,A0 ; point to the packet
MOVE.L A0,pmSBuffer(SP) ; point to the packet
MOVE.W #3,pmLength(SP)
MOVE.W #xPramWrite,pmCommand(SP); write to x pram
MOVE.L SP,A0
_PmgrOp
LEA (PmBlkSize+4)(SP),SP ; Release stack frame
MOVE.L (SP)+,A0 ; Restore this guy
RTS
@PramPak
DC.B ($42) ; pram byte 0x42
DC.B 1 ; one bytes of data
DC.B (PMGRWARNLEVEL-STDOFFSET); warn level to set on pmgr
@pad dc.b 0 ; pad
;________________________________________________________________________________________
;
; Routine: BlockSonyVBL <15> ag
;
; Inputs: D0 - sleep flag
;
; Outputs: D0 - result code (always zero)
;
; Trashes: none
;
; Function: disables the Sony driver's VBL task before going to sleep, and then enables it
; after waking up so the VBL task can't run before the SWIM chip is re-initialized
;________________________________________________________________________________________
BlockSonyVBL
active EQU 25 ; ≠0: .Sony driver is busy
MOVE.L A1,-(SP)
MOVEA.L SonyVars,A1 ; point to the Sony driver's variables
SUBQ.W #SleepWakeUp,D0 ; are we going to sleep or waking up?
SNE active(A1) ; $00=wakeup, $FF=sleep
MOVEA.L (SP)+,A1
MOVEQ #0,D0 ; always return zero
RTS
ENDPROC
;_________________________________________________________________________________________
; SetCursorPatch - check for activity
;
; Head patch SetCursor to check for activity. If SetCursor is called and the cursor
; is different from the current cursor, then we use this to indicate some level of
; program activity. Also, check specifically for the system watch cursor, and if set,
; then disable idle. If the cursor is just changing, then do an _IdleUpdate to give
; back some time.
;
; Input: 4(sp) = ptr to cursor record
;
; Output: none
;
;_________________________________________________________________________________________
Proc
Export SetCursorPatch
Export OldSetCursor
SetCursorPatch
with PowerDispRec,PmgrRec
; Check if we are updating to a different cursor from the last time
move.l a2,-(sp) ; save reg
movea.l PmgrBase,a2 ; a2 = ptr to power mgr globals
move.l 4+4(sp),d0 ; get current addr of curRec (skipping past the saved A2)
_StripAddress ; make it clean
cmp.l RAMwatchPtr(a2),d0 ; are we updating the same cursor?
beq.s @Done ; same one - do nothing
move.l d0,RAMwatchPtr(a2) ; different - update to latest addr of curRec
; Check the new cursor mask to see if it is the watch cursor
lea @WatchMask,a0 ; get mask of watch cursor
movea.l d0,a1 ; a1 = ptr to cursRec
adda.w #mask,a1 ; a1 = ptr to mask of new cursor
moveq.l #8-1,d0 ; compare 8 longs (adjusted for dbra)
@Loop
cmpm.l (a0)+,(a1)+
dbne d0,@Loop ; loop until not equal
tst.b d0 ; did we finish loop?
bpl.s @notWatch ; not the watch cursor
; Watch cursor found - disable power cycling
bset.b #0,watchCrsr(a2) ; test and set watch cursor flag
bne.s @Done ; watch already detected
moveq.l #IdleDisableDisp,d0
_PowerDispatch ; disable power cycling
bra.s @Done
; Not the watch cursor - do an _IdleUpdate
@notWatch
_IdleUpdate ; give time back to system
bclr.b #0,watchCrsr(a2) ; test and clr watch cursor flag
beq.s @Done ; not changing from the watch cursor
moveq.l #IdleEnableDisp,d0
_PowerDispatch ; enable power cycling
; Continue with the _SetCursor
@Done
movea.l (sp)+,a2 ; restore reg
movea.l OldSetCursor(pc),a0 ; chain to old code
jmp (a0)
; Watch cursor mask data
@WatchMask
dc.w $3f00
dc.w $3f00
dc.w $3f00
dc.w $3f00
dc.w $7f80
dc.w $ffc0
dc.w $ffc0
dc.w $ffc0
dc.w $ffc0
dc.w $ffc0
dc.w $ffc0
dc.w $7f80
dc.w $3f00
dc.w $3f00
dc.w $3f00
dc.w $3f00
align 4
OldSetCursor dc.l 0 ; location of old setcursor address
;_________________________________________________________________________________________
; NewSndWatch - patch to SndWatch VBL task
;
; This routine replaces the SndWatch VBL task in ROM. The ROM routine does not check
; whether DFAC (sound input) is active when it decides to clear the sound latch.
;
; Input: a0 = ptr to VBL queue block
;
;_________________________________________________________________________________________
Proc
Export NewSndWatch
NewSndWatch
move.w #SndWFreq,vblCount(a0) ; reset vbl count
suba.w #4,sp ; Create stack frame
movea.l sp,a0
move.w #SoundRead,d0 ; PMGR command, get sound state
jsrROM PMGRrecv
move.b (a0),d2 ; Get sound state
beq.s @noSound ; branch if no sound activity
btst.l #1,d2
bne.s @sndActive ; the latch is set
jsrTBL sndInputSource ; does DFAC have a source selected?
tst.b d0
bne.s @noSound ; sound input is active - do not power off sound
move.b #soundoff,(a0) ; Turn off sound power
moveq.l #1,d1 ; One byte to send
move.w #SoundSet,d0 ; PMGR command, set sound state
jsrROM PMGRsend
bra.s @noSound
@sndActive
move.b #sndOnclrLtch,(a0) ; Turn on sound power and clear the latch
moveq.l #1,d1 ; One byte to send
move.w #SoundSet,d0 ; PMGR command, set sound state
jsrROM PMGRsend
_IdleUpdate ; update activity indicator
@noSound
adda.w #4,sp ; Release stack frame
rts
endproc
;——————————————————————————————————————————————————————————————————————— <r16> HJR to next <r16>
;
; NewBatInt -
;
; This is a bug fix where the BatInt in rom does not handle remove message
; properly. Remove message first checks whether the message to be removed
; is a low power dialog or not. Since the shorted battery dialog is not
; a low power dialog it disregards the remove. Thus, when a low dialog
; comes in, the system crashes. The fix is to aviod the check for low power
; dialog in remove message.
;
; Upon entry: A0 - Ptr to power manager data: [flags] [battery] [Gas] [Therm]
; A1 - VIA base
; A2 - Ptr to power manager globals
;
;
; A0-A3, D0-D3 are preserved by the interrupt dispatcher.
;
;———————————————————————————————————————————————————————————————————————
Proc
Export NewBatInt
With PmgrRec
NewBatInt
moveq.l #0,d2 ; clear reg
move.b 1(a0),d2 ; get battery flags
move.b d2,Charger(a2) ; save charger state
btst.l #ShortedBat,d2 ; is there a shorted battery?
beq.s @Done ; not this time
; 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.
bsr.s @MyRmvMsg ; Remove any pending messages
st lpMSGvalid(A2) ; Yes, then set the flag in order to remove msg
JmpRom BatIntCont ; Go back into the rom code
@Done rts ;
@MyRmvMsg 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
endproc ; NewBatInt <r16> HJR
;_________________________________________________________________________________________
; PmgrOpPatches - _PmgrOp patch
;
; This patch is around _PmgrOp. It notes the command to _PmgrOp, and if it is "set
; power control", then call _PmgrOp but delay returning to the caller for 100µs to
; give the power manager time to actually execute the command. This avoids a race
; condition of code trying to access some hardware before it is actually turned on.
;
; Input: a0 = ptr to pmgr command pkt
; d1 = trap word
; Output: none
;_________________________________________________________________________________________
Proc
Export PmgrOpPatches
WITH PMgrRec ; <12> HJR
WITH SleepQRec,pmCommandRec ; <11> rb
PmgrOpPatches
; Head patch to PmgrOp to add a 100µs delay after power control commands
cmp.w #powerCntl,pmCommand(a0) ; power control command ?
bne.s @NewPmgrOp ; no - jmp to power mgr
@powerCommand ; <15> <ag>
movea.l pmSBuffer(a0),a1 ; load pointer to buffer in a1 <16> <ag>
btst.b #7,(a1) ; test the power on bit <16> <ag>
beq.s @NewPmgrOp ; if off command, skip delay <15> <ag>
jsr @NewPmgrOp ; jsr _PmgrOp
move.w TimeDBRA,d1 ; <12> HJR
divu #10,d1 ; divide down to 100µs <12> HJR
@Loop dbra d1,@Loop ; delay 100µs
tst.w d0 ; set condition codes
rts ; we are done
; Patch to PmgrOp to patch SerPowerOn
@NewPmgrOp
and.w #$0600,d1 ; extract bits 9 and 10 from trap word
cmp.w #$0600,d1 ; is it $a685 - SerialPower?
beq.s @NewSerialPower
jmpROM ROMPmgrOp ; execute PmgrOp in ROM
; New SerialPower patch. On SerPowerOn, assert DTR before modem reset.
; The code is the same as ROM except for DTR and reset ordering.
@NewSerialPower
btst.l #SerialOff,d0 ; power on or off
beq.s @SerPowerOn ; do new serial power on
jmpROM ROMPmgrOp ; start from beginning in ROM
;———————————————————————————————————————————————————————————————————————
; SerPowerOn - determine power on for serial port
;
; 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
;
; Input : d0 = bit 0: 0 = use internal modem, 1 = ignore internal modem
; bit 2: 0 = port B, 1 = port A
;
@SerPowerOn
@savedregs reg d0-d1/a0-a1
movem.l @savedregs,-(sp)
suba.w #pmBlkSize,sp ; alloc pmgr command pkt
lea pmData(sp),a0 ; get addr of buffer
move.l a0,pmRBuffer(sp) ; set ptr to rcv buffer
move.l a0,pmSBuffer(sp) ; set same ptr to xmit buffer (it's expected or error)
movea.l sp,a0 ; a0 = ptr to pmgr command pkt
; Check whether we should bypass the modem check
bclr.l #BypassModem,d0 ; set = ignore modem
bne @externalPort ; use the external ports
; Determine which port we are powering on - if port A then check for modem.
; The modem may only be connected to port A.
tst.b d0 ; d0 = port indicator
beq @externalPort ; 1 = port A, 0 = port B
; On port A - read the modem status. If the modem is not installed power the
; external port.
move.w #modemRead,pmCommand(a0); read the modem's status
clr.w pmLength(a0) ; clear the count field
_PmgrOp ; get the modem status
move.b pmData(a0),d1 ; d1 = modem status bits
btst.l #ModemInstalled,d1 ; check the modem installed bit
beq @externalPort ; modem not installed - use the port
; Modem is installed - read extended PRAM to see if modem should be powered on
move.l #((1<<16)+PmgrPramBase\
+PmgrPramRec.PmgrStatusFlags),d0; read Power Manager Flag byte
_ReadXPRAM ; a0 = ptr to buf (writing over cmd word in pkt)
btst.b #UseIntrnlModem,(a0) ; check cdev bit for modem
bne @externalPort ; set - don't power modem
; Power on the modem
bclr.b #7,([VIA2],vDIRB) ; set MODEM_RESET by making it an input
and.b #7,d1 ; mask only <ring wakeup><port select><modem power>
bset.l #ModemPwr,d1 ; set bit in saved modem status bits
move.b d1,pmData(a0) ; turn on +5V and -5V to modem bit
move.w #1,pmLength(a0) ; xmit one byte
move.w #modemSet,pmCommand(a0) ; modem set command
_PmgrOp ; turn on +5V and -5V to modem
move.w TimeDBRA,d0
asl.w #1,d0 ; calc 2ms delay
@Delay dbra d0,@Delay ; wait for +5v and -5V to ramp
move.b #(sccOn),pmData(a0) ; set bits to power on SCC
move.w #1,pmLength(a0) ; xmit one byte
move.w #powerCntl,pmCommand(a0); power control command
_PmgrOp ; call the power manager
move.b #(ModemOn),pmData(a0) ; enable modem - sense of bit is reversed
move.w #1,pmLength(a0) ; xmit one byte
move.w #powerCntl,pmCommand(a0); power control command
_PmgrOp ; call the power manager
move.w TimeDBRA,d0
asl.w #3,d0 ; calc 8ms delay
@Delay2 dbra d0,@Delay2 ; wait for reset time
move.l PmgrBase,a1 ; get pointer to globals
move.l MdmSndVect(a1),jModemSnd; install in Level 1 VIA1 dispatch table
move.b #((1<<ifIRQ)+\
(1<<ifCB2)),([VIA],vIER) ; enable modem sound interrupt
bset.b #7,([VIA2],vDIRB) ; clear MODEM_RESET by making it an output
bclr.b #7,([VIA2],vBufB) ; drive MODEM_RESET low to disable reset
bra.s @Done
; Power on the SCC for the external port
@externalPort
move.b #(sccOn),pmData(a0) ; set bits to power on SCC
move.w #1,pmLength(a0) ; xmit one byte
move.w #powerCntl,pmCommand(a0); power control command
_PmgrOp ; call the power manager
@Done
adda.w #pmBlkSize,sp ; pop power mgr pkt
movem.l (sp)+,@savedregs
rts ; <r11> from last <r11> djw
;———————————————————————————————————————————————————————————————————————————————————————
; Modem Sound Interrupt Handlers
;
; Modem sound in ROM is implemented through DFAC's aux channel. The aux channel is
; routed through the by-pass path which does not allow any volume control. People
; complained, so this patch routes modem sound through the attenuator which allows
; volume control. The problem is this path is shared with sound input. This patch
; does not implement any priority to the users of the patch. The last person to
; set the input source gets it.
;
; 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
;
Proc
Export ModemSndOnInt
ModemSndOnInt
move.b #(1<<ifCB2),([VIA],vIFR) ; clear interrupt flag reg
move.b SDVolume,d0 ; get current volume
jsrTBL sndPlayThruVol ; set volume for playthrough
moveq.l #sndAuxiliary,d0
jsrTbl sndInputSelect ; select aux source
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
ModemSndOffInt
move.b #(1<<ifCB2),([VIA],vIFR) ; clear interrupt flag reg
moveq.l #0,d0 ; disable playthrough <r13> djw
jsrTBL sndPlayThruVol ; <r13> djw
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
endp ; <r9> from last <r9> djw
End