supermario/base/SuperMarioProj.1994-02-09/OS/PowerMgr/PwrControlsPatches.a
2019-06-29 23:17:50 +08:00

932 lines
41 KiB
Plaintext

;
; File: PwrControlsPatches.a
;
; Contains: Patches for new features dealing with PowerControls.
;
; Written by: Helder J. Ramalho
;
; Copyright: © 1990-1993 by Apple Computer, Inc. All rights reserved.
;
; This file is used in these builds: ROM
;
; Change History (most recent first):
;
; <SM2> 12/13/93 PN Roll in KAOs and Horror changes to support Malcom and AJ
; machines.
; <SM1> 9/1/93 SKH Rolled into SuperMario for the first time. After Kaos stops changing
; this will be rolled into PowerMgr.a
;
; <H43> 6/24/93 RLE ensure charger turned on as part of pmgrinit
; <H42> 5/31/93 RLE change setMachineID command to setMachineAttr
; <H41> 05-12-93 jmp For reanimator builds, quit whacking the SCC.
; <H40> 5/7/93 RLE disable dynamic speed switching for Escher's ROM
; <H39> 5/4/93 SWC Calculate full/reduced speed timing constants (TimeDBRA, etc.)
; for machines that support dynamic speed changes.
; <H38> 4/30/93 RLE update MSC initialization to configure 33MHz Escher correctly
; <H37> 4/20/93 SWC Fixed a bug that was causing us to hang. It looks like this one
; has been around for awhile, too.
; <H36> 4/19/93 SWC Modified CheckEconoMode to look for the pointer to the Power
; Manager primitives directly in a box's ProductInfo, instead of
; using the PmgrPrimLookUp table (which is now gone).
; <H35> 3/29/93 RLE include new patch for InitPmgrVars since it's grown too big to
; fit in the original file
; <H34> 3/19/93 RLE fix a narly problem with PortableCheck using uninitialized ram
; <H33> 3/3/93 RLE toss <H32> in preparation for doing the LCD screen save/restore
; in the driver instead of in the power manager
; <H32> 2/25/93 RLE modify PmgrPrimLookUp calls to support multiple table entries
; for a given memory decoder
; <H31> 8/21/92 SWC Added a nasty hack to fix an SCC initialization problem on
; Gemini and DeskBar. This will eventually be fixed in their
; hardware, but we need this to be working correctly now.
; <H30> 8/10/92 SWC Disable PG&E modem interrupts so we don't get hit before the
; Power Manager gets set up.
; <H29> 7/27/92 SWC Blank the GSC-based LCD screen on DBLite as well as Niagra.
; <H28> 7/21/92 ag Change the GSC initialization values, the screen should not
; blank with active pixels, this will highlight bad pixels. The
; new values will blank with inactive pixels avoiding this
; problem.
; <H27> 7/15/92 ag Changed the initial setting for GSC to blank the screen.
; <H26> 7/15/92 ag Moved a7 to a5 for storage before testing for bus error. The
; bus error handler will move a5 to a7. Set the condition codes
; in bus error check. Set the condition codes before returning in
; the spi timeout code.
; <H25> 7/14/92 ag Fixed trashed register problem in gsc blank routine.
; <H24> 7/14/92 ag Added timeouts to the spi code to avoid infinite loops.
; <H23> 7/14/92 ag Added initialization and blanking of the display for niagra. the
; timing spec would be violated if initialization is done later.
; Changed the spin wait loop constant for economode to reduce
; possible extended delay.
; <H22> 7/10/92 ag fixed dart exception processing for $5x commands, $50 should
; still go to the power manager.
; <H21> 6/18/92 SWC Modified the Dart SPI routines to use the vectors for the
; command send/receive count tables to make patching easier.
; <H20> 6/12/92 ag Changing the spi receive protocal. on receive, data should be
; read on the RISING edge of ack. this protocal sucks!
; <H19> 6/10/92 HJR Fixed some bugs to allow Econo-Mode to work.
; <H18> 5/19/92 SWC Moved InitWallyWorld to CheckEconoMode from USTStartup.a since
; we read PRAM and thus need the PMGR initialized.
; <H17> 5/12/92 ag Set the condition codes before leaving the exception handling
; routine. This tells the code down stream that the exception
; handler handled the call.
; <H16> 5/7/92 ag Added Dartanian SPI code.
; <H15> 5/7/92 SWC Preserve the RAM size info when configuring the MSC. Also, leave
; the MSC25MHz bit set when running in econo-mode regardless of
; the maximum CPU speed so the state machines will be better
; optimized.
; <H14> 4/24/92 HJR Provided Econo-Mode support for Niagra.
; <H13> 4/3/92 SWC Moved all the ADB and DebugUtil routines to ADBPrimitives.a.
; Moved EnableSCSIIntsPatch to InterruptHandlers.a (where it
; should go).
; <H12> 3/19/92 HJR for GMR - Fixed bug in below change on TIM- moved fDBExpActive
; check earlier in StartRequestPMGR rtn.
; <H11> 3/19/92 HJR for GMR - Added fDBExpActive flag in StartReqPMGR,ReqDonePMGR to
; prevent the same explicit command from going out twice if
; autopoll data came in at the same time.
; <H10> 3/16/92 SWC Added support for 33MHz MSC systems to CheckEconoMode.
; <H9> 2/21/92 HJR Modified check sleep to use new ram locations instead of
; obsolete VRam space.
; <H8> 2/10/92 HJR Fix a bug where we are returning from a BSR6 without setting the
; return address in A6.
; <H7> 2/7/92 SWC Modified the CheckEconoMode code to lookup the correct base
; Power Manager PRAM address from the primitives tables.
; <H6> 1/24/92 SWC In CheckEconoMode, do both econo-mode setup and chip
; configuration for the MSC case.
; <H5> 1/9/92 SWC Rolled in changes for final chips: removed special case checks
; for PMGR interrupts on CA2 (now on CB1). Re-wrote CheckEconoMode
; as part of adding support for DB-Lite and to simplify it.
; <H4> 10/29/91 SWC Added the signature to the shutdown command in PMgrPowerOffPatch
; so the PMGR will actually turn us off (I don't know why it
; wasn't there before, cuz it's specifically required).
; <H3> 10/22/91 SWC PortableCheck: changed references to NoVRAMVidRam to point to
; the end of the record since the offsets are negative.
; <H2> 8/8/91 SWC Added import of USTPMGRSendCommand and modified the econo mode
; code to use it instead of sending the bytes discretely.
; Universalized the ADB code so that it supports interrupts on CA2
; and PMGR auto-polling for DB-Lite. Fixed PortableCheck so it
; handles the case when VRAM doesn't retain power across sleep
; (state saved in PMgrGlobals). Added EnableSCSIIntsPatch so we
; won't enable SCSI interrupts on DB-Lite.
; ———————————————————————————————————————————————————————————————————————————————————————
; Pre-HORROR ROM comments begin here.
; ———————————————————————————————————————————————————————————————————————————————————————
; <17> 7/9/91 HJR Added more overpatch space
; <16> 6/24/91 HJR Sleepq and pmCommand are now record, so the appropriate With
; statements were added.
; <15> 5/23/91 HJR Added include for PowerPrivEqu.a.
; <14> 5/10/91 HJR Removed NMIExcpPatch for a much cleaner implementation in
; PowerMgr.a. Removed BigBSR5 macros since it is now in private.a.
; <13> 4/29/91 HJR Added NMIExcpPatch in order to hit NMI while power-cycling and
; modified checkwakeup to use physical video location from
; universal instead of using hard-coded addresses.
; <12> 4/22/91 ag added check and code for economode.
; <11> 3/5/91 ag added install code for backlight driver.
; <10> 3/5/91 HJR Removed TaskDonePatch since IdleMind is now called from
; SynIdlePatch.
; <9> 2/26/91 HJR Added PmgrPowerOffPatch: an overpatch of the PowerOff trap in
; InterruptHandlers.a.
; <8> 2/22/91 HJR Fix bug in CheckWakeUp to prevent BusErr on non JAWSDecoder
; machines.
; <7> 1/24/91 HJR Moved IdleMind and powercycling code to PowerMgr.a.
; <6> 1/15/91 HJR Changed IdleMind so that it uses SleepTime off of PwrMgrVar
; instead of hardcoded constant.
; <5> 12/18/90 HJR Added DeskMgr.a overpatch, i.e. TaskDonePatch and IdleMind.
; <4> 12/11/90 HJR Fix bug.
; <3> 12/11/90 HJR Added Overpatching from StartInit.a, InterruptHandles.a and
; KbdADB.a.
; <2> 11/15/90 HJR Fixing comments.
; <1> 11/15/90 HJR first checked in
;
PRINT OFF
LOAD 'StandardEqu.d'
INCLUDE 'HardwarePrivateEqu.a'
INCLUDE 'UniversalEqu.a'
INCLUDE 'PowerPrivEqu.a'
INCLUDE 'PowerMgrDispatchEqu.a'
INCLUDE 'IopEqu.a'
INCLUDE 'EgretEqu.a'
INCLUDE 'AppleDeskBusPriv.a'
INCLUDE 'MMUEqu.a'
INCLUDE 'Appletalk.a'
INCLUDE 'LAPEqu.a'
PRINT ON
BLANKS ON
STRING ASIS
MACHINE MC68030
IMPORT GetHardwareInfo
IMPORT RdXByte
IMPORT USTPMGRSendCommand ; <H2>
IMPORT USTPMgrSendByte
IMPORT InitWallyWorld ; <H18>
IMPORT SetupTimeK ; <H39>
PwrCntrlPatch PROC
beok EQU 27 ;a BusError is expected and is OK <H23>
;••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
; PATCHES TO StartInit.a
;--------------------------------------------------------------------------------
IF hasPwrControls THEN
;————————————————————————————————————————————————————————————————————————————————
; Routine: PortableCheck
;
; Input: D2 - Bits 31..16, hwCfgFlags info (possibly unknown)
; D2 - Bits 7..0, Address Decoder Kind (zero if unknown)
; A1 - Productinfo
;
; Destroys: A0
;
; Called by: BSR6 from StartInit.
;
; Function: Since we've just called JumpIntoROM, D2 has the decoder kind.
; We check to see if the wakeup flag is set. If it is, take wakeup
; code path, otherwise, continue with the bootup process.
;————————————————————————————————————————————————————————————————————————————————
WITH DecoderInfo,DecoderKinds,ProductInfo, ProductInfo, VideoInfo, PmgrRec, pmCommandRec
PortableCheck
CheckWakeUp
IF isUniversal THEN
TestFor hwCbPwrMgr
BEQ.W NonPwrMgr ; NOPE. Branch...
ENDIF
MOVEA.L A6,A5 ; save return addr <H34>
LEA @NoRAM,A6 ; load return addr in case of bus error <H34>
MOVE.L PmgrBase,A2 ; get the addr of PMgrVars <H34>
CMP.L #SleepConst,SleepSaveFlag(A2) ; are we waking from sleep?
BNE.S @noRAM ; branch if not <H34>
CLR.L SleepSaveFlag(A2) ; clear the sleep flag
MOVE.L WakeVector(A2),A0 ; Go restore ourself
JMP (A0) ; .
NOP ; keep everything aligned <H34>
@NoRAM MOVEA.L A5,A6 ; restore return addr <H34>
IF 0 THEN
;————————————————————————————————————————————————————————————————————————————————
; Routine: CheckEconoMode
;
; Input: D2 - Bits 31..16, hwCfgFlags info (possibly unknown)
; D2 - Bits 7..0, Address Decoder Kind (zero if unknown)
;
; Destroys: A0-A7,D0-D6
;
; Called by: BSR6 from StartInit.
;
; Function: checks to see if a portable needs to be switched into econo-mode
;————————————————————————————————————————————————————————————————————————————————
CheckEconoMode
MOVEA.L A6,A7 ; save the return address <H18>
BigBSR6 InitWallyWorld,A1 ; download code into the PMGR, if necessary <H18>
MOVEQ #0,D2 ; <H18>
BigBSR6 GetHardwareInfo,A0 ; figure out what we're running on
MOVE.L D2,D4 ; save the decoder type around the PRAM calls <H18>
MOVEQ #$10,D1 ; read the PRAM validation byte <H18>
MOVEA.L DecoderInfo.VIA1Addr(A0),A2 ; point to base of VIA1 <H19>
BigBSR6 RdXByte,A0 ; <H18>
MOVEQ #$A8-256,D0 ; compare what was read against expected value <H18>
SUB.B D1,D0 ; <H18>
MOVEQ #0,D1 ; (assume PRAM's invalid) <H18>
TST.B D0 ; is PRAM OK? <H18>
BNE.S @BadPRAM ; -> no, run at full speed for now <H18>
MOVEQ #PmgrPramBase+PmgrPramRec.PmgrOtherFlags,D1 ; default to standard PRAM location <H7>
MOVE.L PowerManagerPtr(A1),D0 ; does this box have a PMgr primitives table? <H36><H37>
BEQ.S @UseDefPRAM ; -> no, use the default location <H36>
MOVEA.L A1,A2 ; <H36><H37>
ADDA.L D0,A2 ; point to the primitives table for this box <H36>
ADDA.L PmgrPrimsRec.PrimInfoPtr(A2),A2 ; and then to the primitives info table <H7>
MOVE.B PrimInfoTbleRec.PrimPRAMBase(A2),D1 ; get the base Power Manager PRAM byte <H7>
ADDQ.B #PmgrPramRec.PmgrOtherFlags,D1 ; and adjust for the byte we want <H7>
@UseDefPRAM MOVEA.L A1,A0 ; point back to the DecoderInfo table <H37>
ADDA.L DecoderInfoPtr(A0),A0 ; <H37>
MOVEA.L DecoderInfo.VIA1Addr(A0),A2 ; point to the base of VIA1
BigBSR6 RdXByte,A0 ; read the desired econo-mode setting from PRAM
ANDI.B #(1<<EconoBit),D1 ; and mask off the econo-mode bit
@BadPRAM MOVE.L D4,D2 ; restore the decoder type
MOVEA.L A1,A0 ; point back to the DecoderInfo table <H37>
ADDA.L DecoderInfoPtr(A0),A0 ; one last time <H37>
; at this point:
; A0 - pointer to DecoderInfo table
; A1 - pointer to ProductInfo table
; D2 - decoder type
IF hasMSC THEN
;•••••••••••••••••••••••••••••••••••••••••••••• MSC •••••••••••••••••••••••••••••••••••••••••••••••
IF isUniversal THEN
CMPI.B #DecoderKinds.MSCDecoder,D2 ; do we have a MSC decoder?
BNE NotMSC ; -> nope, bail
ENDIF
ORI.B #MSCDefConfig,D1 ; econo-mode + other default configuration <H6>
BTST #EconoBit,D1 ; are we in going to run in econo-mode? <H15>
BNE.S @NotMSC33MHz ; -> yes, we'll be running at 16MHz regardless <H15>
MOVEQ #7,D2 ; mask off the CPU ID <H10>
AND.W CPUIDValue(A1),D2 ; <H10>
CMP.W #5,D2 ; is it a 33MHz system (DB Lite)? <H38>
BEQ.S @MSC33MHz ; -> yes, do setup <H38>
CMP.W #2,D2 ; maybe it's a 33MHz Escher? <H38>
BNE.S @NotMSC33MHz ; -> no, skip <H38>
@MSC33MHz BCLR #MSC25MHz,D1 ; setup the state machines to run at 33MHz <H10>
@NotMSC33MHz
MOVEA.L DecoderInfo.RBVAddr(A0),A1 ; point to the base of the MSC decoder
MOVEQ #(%11111000)-256,D2 ; mask off the RAM size information <H15>
AND.B MSCConfig(A1),D2 ; <H15>
OR.B D2,D1 ; and add it to the base configuration <H15>
MOVE.B D1,MSCConfig(A1) ; stuff the configuration into the register <H6>
MOVE.L #(0<<16)|(1<<8)|(SetModemInts<<0),D3 ; <H30>
BigBSR6 USTPmgrSendCommand,A2 ; turn off modem interrupts <H30>
;◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊ <H31>
;
; This is the nasty hack. When a Duo is docked to a DuoDock™ or MiniDock™ with an external SCSI
; hard disk connected and powered up, the SCC gets charged up a little bit and ends up in a weird
; state, usually generating level 4 interrupts. Normally we initialize the SCC later, but since
; the Docking Manager isn't initialized soon enough, as soon as interrupts are opened up, we get
; stuck in the level 4 interrupt handler (which is hopefully set up). This hack will talk to the
; DuoDock/MiniDock hardware directly and reset the external SCC.
ROMSigAddr EQU $FEFFFFE4 ; where to find the ROM signature
ROMSigLo EQU 'Russ' ; and what it is
ROMSigHi EQU 'SWC!'
vscClockPwr EQU $FEE00021 ; VSC power control register
vscSCCclock EQU 1 ; 1=turn on SCC clock
vscSCCAddr EQU $FEE08000 ; SCC base address
If Not ForRomulator Then
MOVEA.L SP,A5 ; save the return address
BSET #beok,D7 ; allow bus errors
BSR6 @WhackSCC ; go whack the SCC (bad SCC! bad SCC! blah blah)
BCLR #beok,D7 ; disallow bus errors
Endif
BRA.S ExitEconoMode
@InitBData DC.B 9,$C0 ; do a hard reset
DC.B 9,$40 ; reset the channel
DC.B 4,$4C ; set async mode (magic?)
DC.B 2,$00 ; zero interrupt vector for dispatcher
DC.B 3,$C0 ; DCD not an auto-enable
DC.B 15,$00 ; no interrupts
DC.B 0,$10 ; reset ext/sts interrupts twice
DC.B 0,$10
DC.B 1,$00 ; no interrupts
@InitAData DC.B 9,$80 ; reset the channel
DC.B 4,$4C ; set async mode (magic?)
DC.B 3,$C0 ; DCD not an auto-enable
DC.B 15,$00 ; no interrupts
DC.B 0,$10 ; reset ext/sts interrupts twice
DC.B 0,$10
DC.B 1,$00 ; no interrupts
@WhackSCC CMPI.L #ROMSigLo,ROMSigAddr ; is the signature in the config ROM?
BNE.S @NotGemini ; -> no, not the ROM we're looking for
CMPI.L #ROMSigHi,ROMSigAddr+4 ; ditto with the other part of the signature
BNE.S @NotGemini ; -> no, not the ROM we're looking for
BSET #vscSCCclock,vscClockPwr ; turn on clocks to the SCC
LEA vscSCCAddr,A0
LEA @InitBData,A2 ; point to channel B init data
MOVEQ #@InitAData-@InitBData,D1
LEA @ResumeB,A1
BRA.S @WriteSCC
@ResumeB ADDQ.W #ACtl,A0 ; point to channel A
MOVEQ #@WhackSCC-@InitAData,D1
LEA @ResumeA,A1
@WriteSCC MOVE.B (A0),D2 ; read to make sure the SCC is sync'ed up
BRA.S @2 ; delay for timing, too
@1 MOVE.L (SP),(SP) ; delay long for reset
MOVE.L (SP),(SP)
MOVE.B (A2)+,(A0)
@2 DBRA D1,@1
JMP (A1)
@ResumeA BCLR #vscSCCclock,vscClockPwr ; turn off clocks to the SCC
@NotGemini RTS6
;◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊◊ <H31>
NotMSC
ENDIF
ExitEconoMode
MOVEA.L A7,A6 ; restore the return address <H23>
;———————————————————————————————————————————————————————————————————————————————— <H23>
; Routine: InitAndBlankScreen |
; V
; Input: a6 - return address
;
; Destroys: A0-A7,D0-D6
;
; Called by: BSR6 from StartInit.
;
; Function: initialize and blank the screen to meet timing requirements
;————————————————————————————————————————————————————————————————————————————————
InitAndBlankScreen
IF hasNiagra | hasMSC THEN
movea.l a6,a7 ; save original return address
IF isUniversal THEN
MOVEQ #0,D2 ;
BigBSR6 GetHardwareInfo,A0 ; figure out what we're running on
cmp.b #Decoderkinds.NiagraDecoder,D2 ; Do we have a Niagra decoder?
beq.s @BlankNiagra ; -> yes
cmpi.b #DecoderKinds.MSCDecoder,D2 ; do we have a MSC decoder?
bne @ExitInitAndBlank ; -> no, continue
ENDIF
IF hasMSC THEN ; <H29>
MOVEA.L DecoderInfo.RBVAddr(A0),A2 ; point to the base of the MSC <H29>
BSET #MSCLCDReset,MSCClkCntl(A2) ; turn on clocks to the GSC so we can program it<H29>
BRA.S @TestForGSC ; <H29>
ENDIF ; <H29>
IF hasNiagra THEN
; send command to power manager to blank the screen and delay before talking to the gsc
; D3- [data2] [data1] [length] [command]
; A0- pointer to DecoderInfo
; A6- return address
@BlankNiagra
MOVE.l #($E0<<0) | \ ; Write Pmgr Ram
(03<<8) | \ ; count 3, 2 address + 1 data
(00<<16) | \ ; addrH - $00xxH
($EA<<24),D3 ; addrL - $xxEA
BigBSR6 USTPMGRSendCommand,A2 ; reset the system
move.b #$0A,D3 ; port 4: d[2] = 0 (blank), d[0] = 1 adb inactive
BigBSR5 USTPMgrSendByte,A4 ; and send it
* bra.s @TestForGSC ; <H29>
ENDIF
; test for gsc chip
@TestForGSC MOVEA.L DecoderInfo.VDACAddr(A0),A0 ; point to base of gsc
movea.l a7,a5 ; save return address in case of bus error <H26>
bset.l #beok,d7 ; allow bus errors
bsr6 @checkforGSC ; check for gsc chip
bne @ExitInitAndBlank ; if not zero, buserror, no gsc, exit
; initialize GSC early to meet hardware timing spec
@loadSetup
moveq.l #7,D0 ; mask off the display ID
And.b GSCPanelID(A0),D0 ; get the display id
MULU #(GSCPanelSkew-GSCPanelSetup+1)+(GSCDiag2-GSCDiag0+1),D0 ;
LEA @GSCInitTable,A2 ; point to the entry for this display
ADDA.L D0,A2
ADDQ.W #GSCPanelSetup,A0 ; point to the first register to blast <H25>
MOVE.L (A2)+,(A0)+ ; initialize the main display registers <H25>
MOVE.L (A2)+,(A0)+ ; <H25>
LEA GSCDiag0-GSCPanelSkew-1(A0),A0 ; point to the diagnostic registers <H25>
MOVE.B (A2)+,(A0)+ ; and initialize them too <H25>
MOVE.W (A2)+,(A0)+ ; <H25>
bra.s @ExitInitAndBlank ; done
@checkforGSC
move.b GSCPanelID(A0),D0 ; try reading a register
moveq #0,d0 ; set CC to Equal, buserr will return not Equal <H26>
rts6
; GSC initialization table. Each entry is based on the LCD panel ID.
;
; panel gray poly panel ACD refresh blank panel
; setup scale adjust adjust clock rate shade skew diag0 diag1 diag2
@GSCInitTable
DC.B $10, $00, $64, $00, $80, $02, $00, $A0, $00, $00, $03 ; ID=0 TFT1Bit <H27>
DC.B $12, $00, $64, $00, $80, $02, $00, $FF, $00, $00, $03 ; ID=1 TFT3Bit <H27>
DC.B $10, $00, $64, $00, $80, $02, $00, $FF, $00, $00, $03 ; ID=2 TFT4Bit <H27>
DC.B $10, $00, $64, $00, $80, $02, $00, $A0, $00, $00, $03 ; ID=3 NotAssignedTFT <H27>
DC.B $10, $00, $64, $00, $80, $05, $00, $A0, $00, $00, $03 ; ID=4 NotAssignedSTN <H27>
DC.B $10, $00, $64, $00, $80, $05, $00, $A0, $00, $00, $03 ; ID=5 TimSTN <H27>
DC.B $10, $00, $63, $00, $80, $05, $00, $9C, $00, $00, $03 ; ID=6 DBLiteSTN <H29>
DC.B $10, $00, $64, $00, $80, $05, $00, $A0, $00, $00, $03 ; ID=7 No Display <H27>
@ExitInitAndBlank
bclr.l #beok,d7 ; disallow bus errors
movea.l a7,a6 ; restore original return address
ENDIF ; {hasNiagra | hasMSC}
ENDIF ; if 0 then
;————————————————————————————————————————————————————————————————————————————————
; Routine: Exit
;———————————————————————————————————————————————————————————————————————————————— |
; V
NonPwrMgr RTS6 ; return to start init <H23> ; All done
ENDIF ; is hasPwrControls
;————————————————————————————————————————————————————————————————————————————————
; Routine: BklightInstall
; Input: None
;
; Destroys: None
;
; Called by: BSR.L from StartInit.
;
; Function: Installs and opens ROM backlight driver
;————————————————————————————————————————————————————————————————————————————————
STRING PASCAL
DriverID equ -16511 ; id of driver resource
DriverType equ 'DRVR' ; resource type of driver
StartEntry equ (48-1) ; this avoids appletalk area
BacklightRegs reg A0-A3/D0-D3
EXPORT BacklightPatch
BacklightPatch
bsr.s BklightInstall
move.l (sp)+,a0
SUBQ #4, SP ; save space for handle
MOVE.L #'SERD', -(SP) ; push type
jmp (a0)
EXPORT BklightInstall
BklightInstall ;
movem.l BacklightRegs,-(sp) ; save the world
IF isUniversal THEN ;
TestFor hwCbPwrMgr
beq.s @ExitInstallBacklight
ENDIF
@install
move.l #DriverType,d1 ; load resource type in d1
move.w #DriverID,d2 ; load resource id in d2
bsr.s GetDetachRes ; get and detach resource (a1)
beq.s @exit ; exit if no handle
@findEntry move.l UTableBase,a0 ; point to utable array
move.l #(StartEntry*4),d3 ; start at entry (48-1)
@testEntry addq.l #4,d3 ; increment to next entry
tst.l 0(a0,d3) ; test entry
bne.s @testEntry ; if != 0, next entry
@createDce move.l d3,d0 ; put offset into d0
lsr.l #2,d0 ; divide by 4 to get entry number
addq.l #1,d0 ; add 1 (refnum is -(entry number + 1)
neg.l d0 ; negate to get reference number
_DrvrInstall ; create dce
tst.l d0 ; test for error
bne.s @releaseDrvr ; ... exit if error
move.l (a0,d3),a3 ; get handle to dce in a3
move.l (a3),a3 ; get pointer to dce
move.l a1,dCtlDriver(a3) ; load driver
move.l (a1),a1 ; get pointer to driver
move.w drvrFlags(a1),dCtlFlags(a3) ; copy data to dce
move.w drvrDelay(a1),dCtlDelay(a3)
move.w drvrEMask(a1),dCtlEMask(a3)
move.w drvrMenu(a1),dCtlMenu(a3)
bset.b #dNeedLock,dCtlFlags+1(a3) ; set the handle bit
@openDrvr lea #'.Backlight',A1 ; load pointer to driver name
bsr.s OpenDRVR
@exit
movem.l (sp)+,BacklightRegs ; restore the world
rts
@releaseDrvr move.l a1,a0 ; move handle to a0
_disposHandle ; release the memory
@ExitInstallBacklight
movem.l (sp)+,BacklightRegs ; restore the world
rts
;------------------------------------------------------------------------------------------
;
; GetDetachRes - Gets and detaches a resource.
;
; input
; d1 Resource Type
; d2 Resource ID
;
; output
; a1 Handle to resource
;
; usage
; d a1 - Handle to resource
; d d0 - Resource Type
; d1 - Resource Type
; d2 - Resource ID
;
;------------------------------------------------------------------------------------------
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
;------------------------------------------------------------------------------------------
;
; OpenDRVR - routine used to open a driver
;
; input
; a1 - pointer to driver name
;
; output
; none
;
; usage
; a0 - pointer to iopb
; a1 - pointer to driver name
;
;------------------------------------------------------------------------------------------
OpenRegs reg A0-A3/D1-D2
OpenDRVR MOVEM.L OpenRegs,-(SP)
SUB.W #ioQElSize,SP ; Allocate IO stack frame
MOVE.L SP,A0 ; set a0 to point to the pb
MOVE.L A1,ioVNPtr(A0) ; load pointer to name
MOVE.B #fsCurPerm,ioPermssn(A0) ; set permission (not used)
_Open
ADD.W #ioQElSize,SP ; Release stack frame
MOVEM.L (SP)+,OpenRegs
RTS ; Sucess returned in status
;••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
; PATCHES TO InterruptHandlers.a
;--------------------------------------------------------------------------------
;———————————————————————————————————————————————————————————————————————————————— <9> HJR
; Routine: PowerOffPatch
;
; Destroys: None
;
; Called by: PowerOff. from BSR
;
; Calls: _PmgrOp, _HideCursor, _Sleep
;————————————————————————————————————————————————————————————————————————————————
EXPORT PmgrPowerOffPatch
IMPORT StartBoot
WITH pmCommandRec
PmgrPowerOffPatch
IF hasPwrControls THEN
IF isUniversal THEN
TestFor hwCbPwrMgr
beq.s PmgrOffDone
ENDIF
CLR.L -(SP) ; pmRBuffer = nil
CLR.L -(SP) ; pmRBuffer = nil
CLR.W -(SP) ; pmLength = 0
MOVE.W #PmgrADBoff,-(SP) ; pmCommand = turn ADB autopoll off
MOVE.L SP,A0 ; point to the parameter block
_PmgrOp
LEA pmRBuffer+4(SP),SP ; clean up the stack
_HideCursor
CLR.L WarmStart ; be sure to do startup testing
; If we have the new PMGR then this command will work. If not then the call will
; fail and we will do it the old fashioned way.
PEA 'MATT' ; shutdown signature <H4>
MOVE.L SP,-(SP) ; pmRBuffer (not used) <H4>
MOVE.L (SP),-(SP) ; pmSBuffer (the sleep signature) <H4>
MOVE.W #4,-(SP) ; pmLength = 4 <H4>
MOVE.W #PmgrPWRoff,-(SP) ; pmCommand = power off <H4>
MOVE.L SP,A0 ; point to the parameter block <H4>
_PmgrOp ; power off using the PMGR <H4>
LEA pmRBuffer+4+4(SP),SP; clean up the stack <H4>
BNE.S @callSleep ; -> the call failed, so we have an old PMGR <H4>
BRA.S * ; Let the cyanide take affect
@callsleep MOVE.W #SleepNow,D0 ; Set it to sleep
_Sleep
BigJSR StartBoot,A0 ; Reboot the guy.
PmgrOffDone
ENDIF ;
RTS ; Get Out of Here <9> HJR
ENDWITH
;••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
; PATCHES TO PmgrOp
;--------------------------------------------------------------------------------
;————————————————————————————————————————————————————————————————————————————————
; Routine: DartModemCmds
;
; Input: A0 - points the pmgrop PB
;
; Destroys: d1
;
; Called by: Bra from NewPmgrOp
;
; Function: filter the modem $5X commands, $50 should still go the power manager
;————————————————————————————————————————————————————————————————————————————————
EXPORT DartModemCmds
DartModemCmds
cmp.w #modemSet,pmCommand(A0) ; <H22>
bne.s DartSPI ; Handle call through SPI <H22>
moveq #1,d1 ; set CC to not handled here <H22>
rts ; return <H22>
;————————————————————————————————————————————————————————————————————————————————
; Routine: DartSPI <H16>
;
; Input: A0 - points the pmgrop PB
;
; Destroys: d1
;
; Called by: Bra from NewPmgrOp
;
; Function: transfer data through new SPI port
;————————————————————————————————————————————————————————————————————————————————
EXPORT DartSPI
DartSPI
savedRegs REG D1-D4/A0-A3
; ----- dynamic test for SPI ----
movea.l PMgrBase,a3 ; point to the Power Manager's variables <H17>
btst.b #PmgrDartSPI,PmgrFlags1(a3) ; test if SPI modem installed <H17>
bne.s @SPIStart ; Handle call through SPI <H17>
moveq #1,d1 ; set CC to not handled here <H17>
rts ; return
@SPIStart
movem.l savedRegs,-(sp)
MOVEA.L UnivInfoPtr,a2 ; point to the ProductInfo table,
ADDA.L DecoderInfoPtr(a2),a2 ; then to the DecoderInfo table,
MOVEA.L JAWSAddr(a2),a2 ; then to the Niagra base address,
ADDA.L #NiagraGUR,a2 ; point to the base of the GUR space
; ----- send command and count ----
move.w pmCommand(a0),d3
move.w d3,d1
bsr SendSPI ; send command byte
bne.s @PMgrOpExit ; exit if error returned <H24>
MOVEA.L PMgrBase,A1 ; point to the Power Manager's variables <H21>
MOVEA.L vSendCountTbl(A1),A1 ; and get the send count table <H21>
move.w pmLength(a0),d2 ; pop the count into d2
tst.b (a1,d3)
bpl.s @noCount ; if positive, no count
move.w d2,d1
bsr SendSPI ; send count byte
bne.s @PMgrOpExit ; exit if error returned <H24>
; ----- send data ----
@noCount movea.l pmSBuffer(a0),a3 ; get the pointer to the command's data bytes
moveq #0,d1 ; (set CCR for BEQ so DBNE below won't fall thru)
bra.s @StartSend
@SendData MOVE.B (a3)+,D1 ; get the next data byte
BSR SendSPI ; and send it
@StartSend DBNE d2,@SendData ; -> more bytes to send
BNE.S @PMgrOpExit ; -> error
; ----- receive data -----
MOVEA.L PMgrBase,A1 ; point to the Power Manager's variables <H21>
MOVEA.L vRecvCountTbl(A1),A1 ; and get the receive count table <H21>
clr.l d4 ; clear count register
move.b (a1,d3),d4 ; initialize to count
bmi.s @readReplyCount ; (<0)
cmp.b #1,d4 ; test against 1
ble.s @readData ; if ( =0 or =1 ) go to read
subq #1,d4 ; (>1) correct count
bra.s @readData ; if 0 or 1 go to read
@readReplyCount
bsr ReceiveSPI ; read first byte for receive count
bne.s @PMgrOpExit ; exit if error returned <H24>
move.w d1,d4 ; move count into d4
@readData ; d4 has receive byte count
movea.l pmRBuffer(a0),a3 ; a3 new points
move.w d4,pmLength(a0) ;
bra.s @StartReceive ; start receiving data
@ReceiveByte
bsr.s ReceiveSPI ; read a byte into d1
bne.s @PMgrOpExit ; -> error
move.b d1,(a3)+ ; move data byte into buffer
@StartReceive
dbra d4,@ReceiveByte ; -> more bytes to send
@PMgrOpExit
moveq #0,d1 ; indicate we handled call <H17>
@exit
movem.l (sp)+,savedRegs ; restore working registers
rts
;———————————————————————————————————————————————————————————————————————————————— <H24>
; Routine: WaitSPIAckHi
;
; Input: a2.l - pointer to GUR space
;
; Destroys: d0
;
; Returns d0.b - 0 = ok, non-zero = error
;
; Function: wait for SPI ack high
;———————————————————————————————————————————————————————————————————————————————— <H24>
WaitSPIAckHi
@workRegs reg D1-d2
movem.l @workRegs,-(sp) ; save working set
move.w #32,d2 ; loop to max 32 msec
@nextmsec
move.w timedbra,d1 ; 1 msec count
@waitAckhi
btst.b #PontiSPIAck,PontiSPIMdmCtl(a2) ; test ack
dbne d1,@waitAckhi ; loop for upto 1 msec
dbne d2,@nextmsec ; loop for d2 msec
seq d0 ; set result (d0 <> 0 = error), bit lo
tst.b d0 ; set the condition codes <H26>
movem.l (sp)+,@workRegs
rts
;———————————————————————————————————————————————————————————————————————————————— <H24>
; Routine: WaitSPIAckLo
;
; Input: a2 - pointer to GUR space
;
; Destroys: d0
;
; Returns d0 - 0 = ok, non-zero = error
;
; Function: wait for SPI ack lo
;
;———————————————————————————————————————————————————————————————————————————————— <H24>
WaitSPIAckLo
@workRegs reg D1-d2
movem.l @workRegs,-(sp) ; save working set
move.w #32,d2 ; loop to max 32 msec
@nextmsec
move.w timedbra,d1 ; 1 msec count
@waitAckhi
btst.b #PontiSPIAck,PontiSPIMdmCtl(a2) ; test ack
dbeq d1,@waitAckhi ; loop for upto 1 msec
dbeq d2,@nextmsec ; loop for d2 msec
sne d0 ; set result (d0 <> 0 = error), bit hi
tst.b d0 ; set the condition codes <H26>
movem.l (sp)+,@workRegs
rts
;————————————————————————————————————————————————————————————————————————————————
; Routine: SendSPI
;
; Input: a2.l - pointer to GUR space
; d1.b - byte to send
;
; Destroys: d0
;
; Returns d0.w - 0 = ok, non-zero = error
;
; Function: send a byte thru the SPI
;
;————————————————————————————————————————————————————————————————————————————————
SendSPI
bsr.s WaitSPIAckHi ; (1) wait for pmgr idle <H24>
bne.s @error ; if bit low, error <H24>
;begin transaction
bset.b #PontiLmpSPIDir,PontiLmpSftCtl(a2) ; (2) set direction to output
move.b d1,PontiSPISftReg(a2) ; (3) write data
bclr.b #PontiSPIReq,PontiSPIMdmCtl(a2) ; (4) assert data valid
bsr.s WaitSPIAckLo ; (5) --> modem shift data <H24>
; (6) wait for data accepted <H24>
bne.s @error ; if bit low, error <H24>
bset.b #PontiSPIReq,PontiSPIMdmCtl(a2) ; (7) clear data valid
MOVE.W #noErr,D0 ; report no error
rts
@error ; <H24>
MOVE.W #pmSendStartErr,D0 ; report send error <H24>
rts
;————————————————————————————————————————————————————————————————————————————————
; Routine: ReceiveSPI
;
; Input: a2.l - pointer to GUR space
; d1.b - byte to send
;
; Destroys: d0
;
; Returns d0.w - 0 = ok, non-zero = error
;
; Function: read a byte from the spi
;
;————————————————————————————————————————————————————————————————————————————————
ReceiveSPI
bsr.s WaitSPIAckHi ; (1) wait for pmgr idle <H24>
bne.s @error ; if bit low, error <H24>
;begin transaction
bclr.b #PontiLmpSPIDir,PontiLmpSftCtl(a2) ; (2) set direction to input
bclr.b #PontiSPIReq,PontiSPIMdmCtl(a2) ; (3) (RFD) ready for data
bsr.s WaitSPIAckLo ; (4) acknowledge req <H24>
; (5) <-- modem shifting <H24>
bne.s @error ; if bit low, error <H24>
bset.b #PontiSPIReq,PontiSPIMdmCtl(a2) ; (6) acknowledge ack
bsr.s WaitSPIAckHi ; (7) wait (DAV) <H24>
bne.s @error ; if bit low, error <H24>
move.b PontiSPISftReg(a2),d1 ; (8) read data
MOVE.W #noErr,D0 ; report no error
rts
@error
MOVE.W #pmRecvStartErr,D0 ; mark as recieve error <H24>
rts ; <H24>
;••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
; That's all folks.
;--------------------------------------------------------------------------------
END