mac-rom/OS/PowerMgr/PowerMgrPatches.a
Elliot Nunn 4325cdcc78 Bring in CubeE sources
Resource forks are included only for .rsrc files. These are DeRezzed into their data fork. 'ckid' resources, from the Projector VCS, are not included.

The Tools directory, containing mostly junk, is also excluded.
2017-12-26 09:52:23 +08:00

1432 lines
50 KiB
Plaintext
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

;
; 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 itÕ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> É 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
;=================================================================================== <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µ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
;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ <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
; (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
;ÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑÑ <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