boot3/OS/PowerMgr/PowerMgrPatches.a

1432 lines
50 KiB
Plaintext
Raw Permalink Normal View History

;
; File: PowerMgrPatches.a
;
; Contains: patches for the power manager
;
; Copyright: <09> 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<30>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 it<69>s 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)
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
; (SKH) BEQ.S @Clearlatch ; Branch if latch is set
bra.s @noSound
_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> <20> continue with low power stuff
MOVEQ #1,D0 ; <2> <20> 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
;=================================================================================== <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 PROC EXPORT
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<30>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
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
;<3B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <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 ; <20>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
; (SKH) beq.s @noSound ; branch if no sound activity
bra.s @noSound ; SKH - Never power down sound.
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
;<3B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <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.
;
;<3B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
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<30>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<30>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<30>s <12> HJR
@Loop dbra d1,@Loop ; delay 100<30>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
;<3B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
; 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
;<3B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
; 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<69> table
rts
endp ; <r9> from last <r9> djw
End