sys7.1-doc-wip/OS/DockingMgr.a

1898 lines
70 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters

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

;
; File: DockingMgr.a
;
; Contains: support for docking portable Macintoshes into desktop docking modules
;
; Written by: Steve Christensen
;
; Copyright: © 1992-1993 by Apple Computer, Inc. All rights reserved.
;
; This file is used in these builds: ROM
;
; Change History (most recent first):
;
; <SM8> 12/13/93 PN Roll in KAOs and Horror changes to support Malcom and AJ
; machines.
; <SM7> 9/2/93 KH Rolled in the Horror changes (finally)
; <SM7> 9/2/93 SKH My fixes are back in now...
; <SM6> 9/1/93 SKH Backed out my changes until I was certain they wouldn't break builds.
; <SM5> 9/1/93 SKH Rolled in Horror version of docking code (with dock cache control stuff)
; <SM4> 12/4/92 GD Added a forRomulator conditional so that we don't (re)initialize
; the SCC when debugging.
; <SM3> 11/20/92 SWC Rolled in the rest of the Horror changes. Changed INCLUDEs to
; use new filenames.
; <H26> 8/13/92 SWC Added a new selector call in SetupDockBases to do any last
; minute pre-boot initialization. This is provided as a means of
; allowing the config ROMs to patch up anything we might have
; forgotten.
; <H25> 8/11/92 SWC Exported DockInitSCC and fixed it to preserve its registers.
; <H24> 8/10/92 SWC Specifically check for (and handle) the docking slot selector
; in DockingDispatch so handlers, etc., have a way of determining
; which slot they're in.
; <H23> 7/29/92 SWC Fixed a typo (ended up looking at the wrong thing).
; <H22> 7/27/92 SWC Block checking for eject until after we get to the Finder.
; <H21> 7/24/92 SWC Added a check if a bar was added during sleep that's not
; supposed to be added then, and if so, the next time we wake up,
; remove its handler, etc. (takes care of the case of trying to
; add it multiple times).
; <H20> 7/8/92 SWC Made some changes to GracefulShutdown to make it better at
; successfully shutting down. DockingFilter now prevents waking up
; if we'd have to run without the LCD display since we currently
; can't handle removing a monitor from the desktop.
; <H19> 7/1/92 SWC Reset internal [and external] SCCs in SetHardwareBases so we
; won't get spurious interrupts from the unused SCC when a bar
; with another SCC is connected during sleep.
; <H18> 6/29/92 HJR SWC/Fixed my fix to Dave Wong's external32bit code from <H14>.
; <H17> 6/29/92 SWC Added in code to allow us to do a graceful shutdown when the
; eject button is pressed on a docking station.
; <H16> 6/25/92 SWC Pulled out the save/restore A2 code in <H13> since that's all
; fixed now. TravelBarHandler now returns SWIM2 power status if a
; SWIM2 exists.
; <H15> 6/18/92 SWC As part of our continuing incestuous relationship with the Power
; Manager, clear the clamshellClosed flag in the sleep denied
; Notification Manager completion routine so we won't try to keep
; posting messages until the current one goes away. Added
; RegisterVideo to the wakeup installation so we'll have a hook to
; let the system know about the addition of a new video device. It
; currently does nothing.
; <H14> 6/15/92 ag Added code to set the external32bit flag in the gdflags of
; gdevice data structure based the information from the slot
; manager.
; <H13> 6/3/92 SWC Cleaned up some of my duplicated code. Temporarily save/restore
; A2 around calls to the docking handler because the DeskBar and
; Gemini docking handlers trash it (a bug to be fixed).
; <H12> 6/1/92 HJR Changed CheckConnectNiagra for our current implementation. Call
; InitDefGamma in vAddVideoDevice.
; <H11> 5/29/92 SWC Set up docking support for Dartanian. Added a routine to notify
; the user that they tried to attach a bar during sleep that's not
; supposed to be added during sleep.
; <H10> 5/20/92 SWC Now pass the CPU's clock speed to the docking handler so it can
; configure any of its hardware that cares.
; <H9> 5/8/92 SWC Added a new routine to call Alex Kazim's Comm Toolbox hack to
; resolve which serial ports are currently available. Abort wakeup
; docking handler installation if that kind of bar is not allowed
; to be added during sleep.
; <SM2> 10/22/92 CS Change some branch short instructions to branches.
; <1> 5/16/92 kc first checked in
; <H8> 4/22/92 SWC Changed DockingWakeup so that it will only add video if video is
; supported AND a monitor is connected, so we can handle the case
; of adding a bar to use the floppy disk and then remove it when
; we're done (with video it would be locked in until shutdown).
; Added a new routine (DockingSleepDenied) to put up a
; Notification Manager dialog to let the user know that they can't
; put the system to sleep when a bar won't allow it.
; <H7> 4/13/92 SWC Added a flag to show that a bar was added during sleep. Added a
; check for eject from a docking station. Did some code cleanup.
; <H6> 4/3/92 SWC Increased the overpatch padding size to 4K.
; <H5> 3/20/92 SWC Rolled in Dave Wong's new Slot Manager support, and fixed how
; the sleep and wakeup code works. Vectored some more routines.
; Increased the overpatch file size from 1K to 2K since it
; overflowed.
; <H4> 3/6/92 SWC Enable/disable docking slot interrupts depending on whether or
; not a bar is connected. Make the built-in docking handlers
; return the SCC ports available when no bar is connected.
; <H3> 3/3/92 SWC Moved the check for SCSI Disk Mode to SCSIDiskMode.a since
; that's now part of the build, and the logical place to put it.
; <H2> 2/17/92 SWC Load the bar's docking attributes into the Power Manager globals
; so we can decide if we want to sleep, power cycle, etc.
; <H1> 2/14/92 SWC First checked in.
PRINT OFF
LOAD 'StandardEqu.d'
INCLUDE 'HardwarePrivateEqu.a'
INCLUDE 'UniversalEqu.a'
INCLUDE 'GestaltEqu.a'
INCLUDE 'MFPrivate.a'
INCLUDE 'Notification.a'
INCLUDE 'PowerPrivEqu.a'
INCLUDE 'Processes.a'
INCLUDE 'ROMEqu.a'
INCLUDE 'Slots.a'
INCLUDE 'SCSI.a'
INCLUDE 'SCSIPriv.a'
INCLUDE 'Shutdown.a'
INCLUDE 'DockingEqu.a'
PRINT ON
BLANKS ON
STRING ASIS
MACHINE MC68020
Unimplement EQU $A89F ; _Unimplemented trap
SyncIdleTime EQU $ABF7
DockingMgr PROC EXPORT
EXPORT DockingDispatch, InitDocking, SetupDockBases, DockInitSCC, GracefulShutdown
EXPORT DockingSleep, DockingWakeup, DockingSleepDenied, DockingWakeupDenied
IMPORT InitSCC, CacheFlush
WITH DockingGlobRec, NMRec, PmgrRec, pmCommandRec, scsiGlobalRecord, SEBlock, SpBlock
WITH DecoderInfo, DecoderKinds, NubusInfo, ProductInfo, ProcessInfoRec
;__________________________________________________________________________________________________
;
; pascal long DockingDispatch(OSType selector, long params)
;
; dispatches to the appropriate docking handler
;__________________________________________________________________________________________________
DockingDispatch
MOVEA.L DockingGlobals,A0 ; point to our variables
MOVEA.L dockingHandler(A0),A1 ; and get the address of our handler
CMPI.L #dockDockingSlot,8(SP) ; is this the docking slot selector? <H24>
BNE.S @CallHandler ; -> no, pass it thru to the docking handler <H24>
MOVEA.L (SP)+,A1 ; pop the return address <H24>
ADDQ.W #8,SP ; and toss the parameters <H24>
MOVEQ #0,D0 ; <H24>
MOVE.B dockingSlotNum(A0),D0 ; get the docking slot number <H24>
MOVE.L D0,(SP) ; and return it as the result <H24>
@CallHandler
JMP (A1) ; call the docking handler or just return
;__________________________________________________________________________________________________
;
; pascal long NoBoardHandler(OSType selector, long params)
;
; docking handler when no docking module is connected
;__________________________________________________________________________________________________
NoBoardHandler
MOVEA.L (SP)+,A1 ; pop the return address
ADDQ.W #4,SP ; and toss params
MOVEQ #0,D0 ; assume an unsupported selector
CMPI.L #dockSCCPorts,(SP)+ ; is it the port list selector?
BNE.S @Done ; -> nope
MOVEA.L DockingGlobals,A0 ; point to the Docking Manager globals
MOVE.L builtInSCCPorts(A0),D0 ; get which ports are built in
@Done MOVE.L D0,(SP) ; return the selector result
JMP (A1)
;__________________________________________________________________________________________________
;
; pascal long TravelBarHandler(OSType selector, long params)
;
; docking handler for a travel bar (since it has no configuration ROM)
;__________________________________________________________________________________________________
TravelBarHandler
MOVEA.L (SP)+,A1 ; pop the return address
ADDQ.W #4,SP ; and toss params
MOVE.L (SP)+,D1 ; get the selector
MOVEQ #0,D0 ; assume an unsupported selector
MOVEA.L DockingGlobals,A0 ; point to the Docking Manager globals
CMPI.L #dockSCCPorts,D1 ; is it the port list selector?
BNE.S @NotSCCPorts ; -> nope
MOVE.L builtInSCCPorts(A0),D0 ; get which ports are built in
BRA.S @Done
@NotSCCPorts
CMPI.L #dockPowerStatus,D1 ; is it a power status call?
BNE.S @NotPowerStatus ; -> no
BSR.S @TestForSWIM ; yes, do we have a SWIM2?
BNE.S @Done ; -> no
MOVEQ #1<<dockSWIMPower,D0 ; yes, so the SWIM2 is always on
BRA.S @Done
@NotPowerStatus
CMPI.L #dockHardwareAttr,D1 ; is it the hardware attributes selector?
BNE.S @Done ; -> nope
MOVE.L #(1<<dockHasADB)|\
(1<<dockWakeADB),D0 ; assume we support at least ADB
BSR.S @TestForSWIM ; do we have a SWIM2?
BNE.S @Done ; -> nope
ORI.L #(1<<dockHasSWIM)|\
(1<<dockWakeSWIM),D0 ; yes, set its bits too
@Done MOVE.L D0,(SP) ; stuff the result
JMP (A1)
@TestForSWIM
MOVE SR,-(SP) ; save the SR
ORI #$0700,SR ; and lock everyone out while we test
MOVE.L BusErrVct,-(SP) ; save the old bus error vector
PEA @NoSWIM2 ; and point it to ours
MOVE.L (SP)+,BusErrVct
MOVE.L SP,D2 ; save the stack pointer in case we bus error
MOVEQ #$F8-256,D1
MOVE.B D1,([IWM],wPhase) ; write a value to the phase register
TST.B ([ROMBase],4) ; read from the ROM to clear the bus lines
CMP.B ([IWM],rPhase),D1 ; did we get back what was originally written?
BNE.S @NoSWIM2 ; -> nope, we don't have a SWIM2 connected
MOVEQ #0,D1
@NoSWIM2 MOVEA.L D2,SP ; trash the exception frame if we bus errored
MOVE.L (SP)+,BusErrVct ; restore the previous bus error vector
MOVE (SP)+,SR ; re-enable interrupts
TST.L D1 ; set the CCR
RTS
;__________________________________________________________________________________________________
;
; Routine: InitDocking
;
; Inputs: none
;
; Outputs: none
;
; Trashes: none
;
; Function: initializes the Docking Manager if this machine has a slot allocated for docking
;__________________________________________________________________________________________________
InitDocking MOVEM.L D0-D2/A0-A2,-(SP)
MOVEA.L UnivInfoPtr,A1 ; point to this machine's ProductInfo table
ADDA.L NuBusInfoPtr(A1),A1 ; and from there, point to the NubusInfo table
MOVEQ #$0F,D1
@SearchLoop BTST #dockingSlot,(A1)+ ; is this slot used for docking?
DBNE D1,@SearchLoop ; -> keep looping if not
BEQ @NoDocking ; -> no docking slots
SUBI.W #$0F,D1 ; calculate the real slot number
NEG.W D1
MOVEQ #DockingGlobalSize/2,D0 ; allocate docking globals
ADD.L D0,D0
_NewPtr ,SYS,CLEAR
BNE @NoDocking ; -> couldn't do it, so bail on docking support
MOVE.L A0,DockingGlobals ; save the pointer
MOVEA.L A0,A2
LEA NoBoardHandler,A1
MOVE.L A1,(A0)+ ; default docking handler = no board
MOVE.B D1,(A0)+ ; save the docking slot number
; setup to check if a docking station's eject button has been hit...
LEA ejectVBLTask+vblCount+2(A2),A0
MOVE.W #ejectVBLCount,-(A0) ; vblCount
LEA CheckForEject,A1
MOVE.L A1,-(A0) ; vblAddr
ADDQ.W #vType,-(A0) ; vblType
SUBQ.W #vblType-vblink,A0 ; point to the VBL task element
_VInstall ; and install the task
LEA ejectNMEntry(A2),A0 ; set up the eject Notification Manager record
LEA EjectNMResponse,A1 ; response procedure
BSR.S @SetupNMRec
LEA sleepNMEntry(A2),A0 ; set up the sleep Notification Manager record
LEA SleepNMResponse,A1 ; response procedure
BSR.S @SetupNMRec
LEA wakeupNMEntry(A2),A0 ; set up the wakeup Notification Manager record
LEA WakeupNMResponse,A1 ; response procedure
BSR.S @SetupNMRec
; initialize the vector table...
MOVEA.L UnivInfoPtr,A1 ; point to this machine's ProductInfo table
MOVE.B DecoderKind(A1),D0 ; and get the decoder type
LEA DockingVectorTable-4,A1
@NextDecoder
ADDQ.W #4,A1 ; skip over the offset to this decoder's table
MOVE.W (A1)+,D1 ; get the next decoder
BMI.S @FoundTable ; -> end of table: use default vectors
CMP.B D0,D1 ; is this the correct table?
BNE.S @NextDecoder ; -> no, try the next one
@FoundTable ADDA.L (A1),A1 ; point to the vector table
LEA builtInSCCPorts(A2),A0
MOVE.L (A1)+,(A0)+ ; copy the built-in SCC ports
@InitDispatch
MOVE.L (A1)+,D1 ; get the next offset
BEQ.S @InitDone ; -> end of table
ADD.L A1,D1 ; convert it into an absolute address
MOVE.L D1,(A0)+ ; and stuff it into our vector table
BRA.S @InitDispatch
; install the docking handler...
@InitDone MOVEQ #0,D1 ; (boot call)
BSR InstallHandler ; now install the correct handler
@Done MOVEM.L (SP)+,D0-D2/A0-A2
RTS
@SetupNMRec ADDQ.W #nmType,qType(A0) ; queue type
MOVEQ #-1,D0 ; sound: use system sound
MOVE.L D0,nmSound(A0)
MOVE.L A1,nmResp(A0) ; response procedure
RTS
@NoDocking MOVE.W #Unimplement,D0 ; get the _Unimplemented trap's address
_GetTrapAddress ,NEWTOOL
MOVE.W DockTrap,D0 ; and turn off docking
_SetTrapAddress ,NEWTOOL
BRA.S @Done
;__________________________________________________________________________________________________
;
; Routine: SetupDockBases
;
; Inputs: none
;
; Outputs: none
;
; Trashes: D0-D2, A0-A1
;
; Function: using the current bar's hardware attributes, initialize "standard" chip base addresses
; (this is called after enough of the hardware managers are initialized to be able to
; stuff base addresses into their globals)
;__________________________________________________________________________________________________
SetupDockBases
BSR.S DockingDispatchExists ; does the _DockingDispatch trap exist?
BEQ Done ; -> nope, no special initialization is required
MOVE.L A2,-(SP) ; <H16>
MOVEA.L DockingGlobals,A2 ; <H16>
BSR GetDockingAttributes ; get the docking attributes <H11>
MOVEA.L (SP)+,A2 ; <H16>
MOVE.L #dockHardwareAttr,D0 ; get the hardware attributes
BSR DockStatus
BSR SetHardwareBases ; and initialize any chip base addresses we care about
MOVE.L #dockBootHook,D0 ; do any last minute pre-boot setup <H26>
BRA DockStatus ; <H26>
;__________________________________________________________________________________________________
;
; Routine: DockingDispatchExists
;
; Inputs: none
;
; Outputs: CCR - BNE: _DockingDispatch trap exists
;
; Trashes: D0, A0-A1
;
; Function: checks if the _DockingDispatch trap exists on this machine
;__________________________________________________________________________________________________
DockingDispatchExists
MOVE.W #Unimplement,D0 ; does the _DockingDispatch trap exist?
_GetTrapAddress ,NEWTOOL
MOVEA.L A0,A1
MOVE.W DockTrap,D0
_GetTrapAddress ,NEWTOOL
CMPA.L A0,A1
RTS
;__________________________________________________________________________________________________
;
; Routine: DockingSleep
;
; Inputs: A1 - return address
;
; Outputs: A1 - return address
;
; Trashes: D0-D2
;
; Function: calls the handler to save its hardware state before going to sleep.
;__________________________________________________________________________________________________
DockingSleep
MOVE.L ([DockingGlobals],jDockingSleep),-(SP)
RTS
vDockingSleep
MOVEM.L A0-A1,-(SP)
MOVE.L #dockSleepSave,D0 ; have the handler save the bar's state
BSR DockStatus
MOVE.L D0,([DockingGlobals],savedSleepState) ; save the pointer to the state
MOVE.L PMgrBase,a0 ; get PMgr globals <H31>
BCLR #HDPowerOn,PmgrFlags(a0); clear the hard disk semaphor again, to make sure <H31>
CLR.L LastHD(A0) ; clear LastHD too <H32>
MOVEM.L (SP)+,A0-A1
JMP (A1)
;__________________________________________________________________________________________________
;
; Routine: DockingWakeup
;
; Inputs: A1 - return address
;
; Outputs: A1 - return address
;
; Trashes: D0-D2
;
; Function: Checks if a docking module as been added, changed, or removed across sleep.
; If it's been added or changed, clean up after any old handlers and install a new one.
; If it's been removed, clean up after its handler and install the "no board" handler.
;__________________________________________________________________________________________________
DockingWakeup
MOVE.L ([DockingGlobals],jDockingWakeup),-(SP)
RTS
vDockingWakeup
@savedRegs REG D3-D4/A0-A2
MOVEM.L @savedRegs,-(SP)
MOVEA.L DockingGlobals,A2 ; point to our globals
BCLR #dockForceRemoval,dockingFlags(A2) ; did user try to install a "no sleep add" bar? <H21>
BNE.S @SwitchBars ; -> yes, force removal since they could try multiple times <H21>
BSR CheckConnect ; is a docking module currently attached?
BEQ.S @SwitchBars ; -> no
; a module is currently connected; see if it's been added or changed...
BSR CheckBarChanged ; has the bar changed across sleep?
BNE.S @SwitchBars ; -> yes, do the switch
MOVE.L #dockWakeupRestore,D0 ; restore the state of anything that was turned off
MOVEA.L savedSleepState(A2),A0
BSR DockControl
CLR.L savedSleepState(A2) ; mark the state info as updated
MOVE.L #dockHardwareAttr,D0 ; get the hardware attributes <H19>
BSR DockStatus ; <H19>
BSR SetHardwareBases ; force an SCC initialization <H19>
BRA @Done
; no docking module is connected or a new one has been installed, so tell its software...
@SwitchBars BSR @GetNubusSlots ; find out if there are any NuBus connectors on this bar
MOVE.L #dockRemoved,D0 ; tell the board software that its board is gone
BSR DockStatus ; (if it was previously installed)
MOVE.L savedSleepState(A2),D0 ; Get the state info.
Cmpi.l #-1,D0 ; Was it -1?
BEQ.S @NoSavedState1 ; -> yes
Tst.l D0 ; Was it zero?
Beq.s @NoSavedState ; -> yes
MOVEA.L D0,A0 ; no, get the pointer
_DisposPtr ; and get rid of the block
@NoSavedState1
CLR.L savedSleepState(A2) ; mark the state info as updated
@NoSavedState
; clean up after any slots that went away (including the docking slot)...
Moveq #0,D1 ; Always do Slot #0 first.
Btst D1,D3 ; If Slot #0 doesnt to be removed,
Beq.s @SkipZeroRmv ; then just go on.
Bsr RemoveVideo ; Unregister Slot #0s video.
Bsr RemoveSlot ; And make slot zero go away.
@SkipZeroRmv
MOVEQ #sLastSlot,D1
@RemoveSlot BTST D1,D3 ; does this slot need to be removed?
BEQ.S @DontRemove ; -> nope, skip it
BSR RemoveVideo ; unregister any video associated with this slot <H16>
BSR RemoveSlot ; make the slot go away <poof!>
@DontRemove Subq #1,D1 ; decrement down to…
Bne.s @RemoveSlot ; …next slot (skipping zero)
; set everything back up for the new bar...
MOVE.B dockingSlotNum(A2),D1 ; install the bar in the docking slot
BSR AddSlot
BSET #dockSleepAddition,dockingFlags(A2)
; remember that this bar was added during sleep
MOVEQ #(1<<dockWakeupInit),D1 ; (this is a wakeup call)
BSR InstallHandler ; install the appropriate docking code
BTST #dockNoWakeup,D0 ; should we allow wakeup with this bar connected? <H9>
BNE.S @Done ; -> no, bail out <H9>
MOVE.L #dockHardwareAttr,D0 ; get the hardware attributes
BSR DockStatus
SWAP D0 ; and use the wakeup attributes
MOVE.W D0,D4 ; <H8>
; <H8>
TST.B D4 ; video support AND monitor plugged in? <H8>
BPL.S @NoBarVideo ; -> nope <H8>
BSR.S @GetNubusSlots ; find out if there are any NuBus connectors on this bar
Moveq #0,D1 ; Always do Slot #0 first (its never the docking slot).
Btst D1,D3 ; If Slot #0 doesnt to be removed,
Beq.s @SkipZeroAdd ; then just go on.
Bsr AddSlot ; Make the slot appear.
Bsr AddVideoDevice ; Initialize its video.
Beq.s @SkipZeroAdd ; If failed, skip.
Bsr RegisterVideo ; Otherwise, register the new device.
@SkipZeroAdd
MOVEQ #sLastSlot,D1
@AddSlot BTST D1,D3 ; does this slot need to be added?
BEQ.S @DontAdd ; -> nope, skip it
CMP.B dockingSlotNum(A2),D1 ; is this the docking slot? <H15>
BEQ.S @IsAdded ; -> yes, it's already added: just do the video thing <H15>
BSR AddSlot ; make the slot appear <whoosh!>
@IsAdded BSR AddVideoDevice ; and initialize its video (if any)
BEQ.S @DontAdd ; -> no video or error <H15>
BSR RegisterVideo ; register the new device with the system <H15>
@DontAdd Subq #1,D1 ; decrement down to…
Bne.s @AddSlot ; …next slot (skipping zero)
@NoBarVideo MOVE.W D4,D0 ; get the wakeup attributes <H8>
BSR.S SetHardwareBases ; and use them to setup base hardware addresses
BSR ResolveSerialPorts ; make sure serial ports are properly registered <H9>
Move.l #dockFlush,D0 ; Were done waking up,
Bsr DockStatus ; so alert the handler.
@Done MOVEM.L (SP)+,@savedRegs
JMP (A1)
@GetNubusSlots
MOVE.L #dockNuBusConnectors,D0 ; find out if there are any NuBus connectors on this bar
BSR DockStatus
MOVE.L D0,D3 ; and save which slots they're in
MOVEQ #0,D0
MOVE.B dockingSlotNum(A2),D0 ; mark the docking slot as well
BSET D0,D3
RTS
;__________________________________________________________________________________________________
;
; Routine: SetHardwareBases
;
; Inputs: D0 - bitmap of hardware available on the bar
;
; Outputs: none
;
; Trashes: D0-D2, A0-A1
;
; Function: handles installation of hardware base addresses for "standard" chips on the bar
;__________________________________________________________________________________________________
SetHardwareBases
MOVE.L ([DockingGlobals],jSetHardwareBases),-(SP)
RTS
vSetHardwareBases
@savedRegs REG A2-A4
MOVEM.L @savedRegs,-(SP)
MOVEA.L UnivInfoPtr,A0 ; point to the DecoderInfo table
ADDA.L ProductInfo.DecoderInfoPtr(A0),A0
MOVEM.L SCCRdAddr(A0),A0-A1 ; copy the internal SCC's base addresses
MOVEM.L A0-A1,SCCRd ; to the low-mem vectors
BTST #dockHasSCC,D0 ; does the bar contain a SCC?
BEQ.S @NoSCC ; -> no
MOVE.L #dockSCCReadAddr,D0 ; call the handler to get the SCC base read address
BSR DockStatus
BEQ.S @NoSCC ; -> it returned zero (confusion), so just use built-in
MOVE.L D0,A3 ; save the SCC base read address <H19>
MOVE.L #dockSCCWriteAddr,D0 ; call the handler to get the SCC base write address
BSR DockStatus
BEQ.S @NoSCC ; -> it returned zero (confusion), so just use built-in
MOVE.L D0,A4 ; save the SCC base write address <H19>
BSR.S DockInitSCC ; reset the internal SCC so it doesn't cause us trouble <H19>
MOVEM.L A3-A4,SCCRd ; stuff in the new SCC base addresses <H19>
@NoSCC BSR.S DockInitSCC ; initialize the SCC we'll be using <H19>
MOVEA.L SCSIGlobals,A2
MOVE.L #dockSCSIAddr,D0 ; call the handler to get the SCSI registers base address
BSR DockStatus
MOVE.L D0,base5380_2(A2) ; and save it in the SCSI Manager's variables
BNE.S @HaveSCSI2 ; -> second SCSI chip's base is valid
MOVEQ #-1,D0 ; otherwise set SCSI2Base to -1
@HaveSCSI2 MOVE.L D0,SCSI2Base
MOVE.L #dockSCSIDMAAddr,D0 ; call the handler to get the SCSI DMA base address
BSR DockStatus
MOVE.L D0,pdma5380_2(A2) ; and save it in the SCSI Manager's variables
MOVE.L #dockSCSIHskAddr,D0 ; call the handler to get the SCSI handshake base address
BSR DockStatus
MOVE.L D0,hhsk5380_2(A2) ; and save it in the SCSI Manager's variables
MOVEM.L (SP)+,@savedRegs
Done RTS
DockInitSCC MOVEM.L D0-D2/A0-A2,-(SP) ; <H25>
BSR DockingDispatchExists ; is the Docking Manager initialized? <H25>
BEQ.S @Done ; -> no, skip it <H25>
IF forRomulator THEN
TestInRam a0 ; are we running the ROM image from RAM?
bne.s @Done ; if so, then don't init the SCC
ENDIF
MOVEQ #sccOn-256,D0 ; turn SCC power on <H19>
BSR.S @SCCPower
BSR.L InitSCC ; reset the SCC so it doesn't cause us trouble
MOVEQ #sccOff,D0 ; turn SCC power off
BSR.S @SCCPower ; <H25>
@Done MOVEM.L (SP)+,D0-D2/A0-A2 ; <H25>
RTS ; <H25>
@SCCPower
IF hasPwrControls THEN
IF isUniversal THEN
TestFor hwCbPwrMgr ; does this machine have a Power Manager?
BEQ.S @NoPMGR ; -> nope, skip
ENDIF
MOVE.B D0,-(SP)
MOVE.L SP,-(SP) ; pmRBuffer
MOVE.L (SP),-(SP) ; pmSBuffer
MOVE.W #1,-(SP) ; pmLength = 1 byte to send
MOVE.W #powerCntl,-(SP) ; pmCommand = power control
MOVEA.L SP,A0 ; point to the parameter block
_PMgrOp ; turn SCC power on or off
LEA pmRBuffer+4+2(SP),SP ; toss the parameter block and buffer
@NoPMGR
ENDIF
RTS
;__________________________________________________________________________________________________
;
; Routine: CheckConnect
;
; Inputs: A2 - pointer to Docking Manager's globals
;
; Outputs: CCR - BNE: bar connected
;
; Trashes: A0, D0
;
; Function: checks if a connector bar is currently plugged in
;__________________________________________________________________________________________________
CheckConnect
MOVE.L jCheckConnect(A2),-(SP)
RTS
vCheckConnect
MOVEQ #0,D0 ; return BEQ as default case
RTS
;__________________________________________________________________________________________________
;
; Routine: TurnOffBarIO, TurnOnBarIO
;
; Inputs: A2 - pointer to Docking Manager's globals
;
; Outputs: none
;
; Trashes: A0, D0
;
; Function: turns bar I/O clock on or off
;__________________________________________________________________________________________________
TurnOffBarIO
MOVE.L jTurnOffBarIO(A2),-(SP)
RTS
TurnOnBarIO MOVE.L jTurnOnBarIO(A2),-(SP)
RTS
;__________________________________________________________________________________________________
;
; Routine: InstallHandler
;
; Inputs: D1 - startup/wakeup flag to pass to docking handler's initialization code
; - (if D1.l is -1, then we just want to reload the docking attributes)
; A2 - pointer to Docking Manager's globals
;
; Outputs: D0 - docking attributes returned by the new bar
;
; Trashes: D0-D2, A0-A1
;
; Function: installs the appropriate support code into the docking selector for the
; currently installed board (or no board)
;__________________________________________________________________________________________________
InstallHandler
MOVE.L jInstallHandler(A2),-(SP)
RTS
vInstallHandler
Cmpi.l #-1,D1 ; If we just want to reload the docking attributes,
Beq.s GetDockingAttributes ; then go there now.
MOVEA.L NoBoardAddr(A2),A1 ; default to "no board"
BSR.S TurnOffBarIO ; turn off bar I/O
BSR.S CheckConnect ; is a board connected?
BEQ.S @DoInstall ; -> nope
BSR.S TurnOnBarIO ; turn on bar I/O
BSR GetDockingHandler ; try to load the docking handler for this bar
BEQ.S @DoInstall ; -> got it
MOVEA.L TravelBarAddr(A2),A1 ; bar doesn't have a handler, so use the travel bar's
@DoInstall MOVEA.L dockingHandler(A2),A0 ; get the address of the old docking handler
MOVE.L A1,dockingHandler(A2) ; and install the new one
CMPA.L noBoardAddr(A2),A0 ; is the old handler the "no board" one?
BEQ.S @Done ; -> yes, we're done
CMPA.L travelBarAddr(A2),A0 ; is the old handler the travel bar one?
BEQ.S @Done ; -> yes, we're done
_DisposPtr ; dispose of the block it occupied
@Done
IF NOT forRomulator THEN ; <H27>
MOVE.L D1,-(SP) ; save startup/wakeup flag <H28>
Move.l #dockCacheStatus,D0 ; Set up to determine if an external cache…
Movea.l #dockCacheCPU,A0 ; …works with our CPU.
Bsr.s DockControl ; Do it.
MOVE.L (SP)+,D1 ; restore startup/wakeup flag <H28>
Moveq #0,D2 ; Clear D2 for good measure.
Move.b CPUFlag,D2 ; Get the current CPU flag.
Addq #1,D2 ; De-normalize it.
Btst D2,D0 ; If we can deal with this cache,
Bne.s @UseExtCache ; then do so.
BSET #dockIgnoreExtCache,D1 ; Otherwise, just ignore it.
@UseExtCache
ENDIF ; <H27>
MOVE.L #dockInit,D0 ; call the new handler to initialize itself…
MOVEA.L D1,A0 ; …with the appropriate flags
BSR.S DockControl ; <H2>
IF hasPwrControls THEN ; <H2>
IF isUniversal THEN ; <H2>
TestFor hwCbPwrMgr ; does this machine have a Power Manager? <H2>
BEQ.S GetDockingAttributes ; -> nope, skip <H2>
ENDIF ; <H2>
MOVEQ #PowerDispRec.CPUSpeedDisp,D0 ; <H10>
_PowerDispatch ; get the CPU's maximum and current speed in MHz <H10>
EXT.L D0 ; sign-extend it to a long <H10>
BMI.S GetDockingAttributes ; -> either very fast, or selector is not supported :) <H10>
MOVEA.L D0,A0 ; stuff it into params <H10>
MOVE.L #dockCPUSpeed,D0 ; go tell the docking handler what it is <H10>
BSR.S DockControl ; <H10>
ENDIF ; <H2>
GetDockingAttributes
MOVE.L #dockDockingAttr,D0 ; get the docking attributes for this bar <H2>
BSR.S DockStatus ; <H2>
BTST #dockSleepAddition,dockingFlags(A2) ; is this a startup or wakeup case? <H11>
BNE.S @SaveAttr ; -> wakeup: pass the attributes unmodified <H11>
BCLR #dockNoWakeup,D0 ; startup: if we go to sleep, we want to wake up again <H11>
@SaveAttr BSR.S DockingFilter ; do any filtering before we save it <H16>
IF hasPwrControls THEN ; <H2>
IF isUniversal THEN ; <H2>
TestFor hwCbPwrMgr ; does this machine have a Power Manager? <H2>
BEQ.S @NoPMgr ; -> nope, skip <H2>
ENDIF ; <H2>
MOVEA.L PmgrBase,A1 ; and save them in the Power Manager's globals <H2>
MOVE.B D0,PmgrRec.dockFlags(A1); <H2>
@NoPMgr ; <H2>
ENDIF ; <H2>
RTS ; <H2>
;__________________________________________________________________________________________________
;
; Routine: DockStatus,DockControl
;
; Inputs: D0 - docking selector
; A0 - parameters for control calls (nil for status calls)
;
; Outputs: D0 - function result
;
; Trashes: D1-D2, A0-A1
;
; Function: executes the handler code for the currently installed docking module
;__________________________________________________________________________________________________
DockStatus SUBA.L A0,A0 ; no parameters for status calls
DockControl SUBQ.W #4,SP ; result
MOVE.L D0,-(SP) ; docking selector
MOVE.L A0,-(SP) ; params
DockTrap _DockingDispatch ; call the handler
MOVE.L (SP)+,D0 ; get the result
RTS
;__________________________________________________________________________________________________
;
; Routine: DockingFilter
;
; Inputs: D0 - docking attributes returned by the bar
; A2 - pointer to Docking Manager's globals
;
; Outputs: D0 - filtered docking attributes
;
; Trashes: D1,D2,A0,A1
;
; Function: filters the docking attributes so we can decide how to behave depending on what kind
; of system software support we have (currently we don't have much)
;__________________________________________________________________________________________________
DockingFilter
MOVE.L jDockingFilter(A2),-(SP)
RTS
vDockingFilter
MOVE.L D0,-(SP)
MOVE.L #dockHardwareAttr,D0 ; get the hardware attributes
BSR DockStatus
MOVE.L D0,D1
MOVE.L (SP)+,D0
BTST #dockSleepAddition,dockingFlags(A2) ; is this a startup or wakeup case?
BEQ.S @Startup ; -> wakeup
SWAP D1 ; use the wakeup hardware attributes
BTST #dockNoLCDScreen,D0 ; do we need to lose the LCD screen? <H20>
BEQ.S @Startup ; -> no <H20>
BSET #dockNoWakeup,D0 ; yes, we can't wakeup since we don't support screen removal<H20>
@Startup ANDI.W #(1<<dockHasFPU)|\
(1<<dockHasVideo),D1 ; does this bar have either an FPU or video?
BEQ.S @Done ; -> no
BSET #dockNoSleep,D0 ; yes, we don't let it sleep
@Done RTS
;__________________________________________________________________________________________________
;
; Routine: CheckBarChanged
;
; Inputs: A2 - pointer to Docking Manager's globals
;
; Outputs: CCR - BNE: bar has changed
;
; Trashes: A0, D0
;
; Function: checks whether or not the currently connected bar is the same one we think is connected
;__________________________________________________________________________________________________
CheckBarChanged
MOVE.L jCheckBarChanged(A2),-(SP)
RTS
vCheckBarChanged
LEA -spBlockSize(SP),SP ; allocate a parameter block on the stack
MOVEA.L SP,A0 ; and point to it
MOVE.B dockingSlotNum(A2),spSlot(A0) ; spSlot = docking slot
* _CheckSlot ; find the board sResource
MOVEQ #$27,D0
_SlotManager
LEA spBlockSize(SP),SP ; clean up the stack
RTS
;__________________________________________________________________________________________________
;
; Routine: AddSlot
;
; Inputs: A2 - pointer to Docking Manager's globals
; D1 - slot number
;
; Outputs: CCR - BNE: bar has changed
;
; Trashes: A0, D0
;
; Function: given that a slot is currently empty, sets up the slot so we can use it
;__________________________________________________________________________________________________
AddSlot MOVE.L jAddSlot(A2),-(SP)
RTS
vAddSlot MOVEQ #spBlockSize/2-1,D0 ; allocate a cleared parameter block on the stack <H33>
@ClearBlock CLR.W -(SP) ; <H33>
DBRA D0,@ClearBlock ; <H33>
MOVEA.L SP,A0 ; and point to it
MOVE.B D1,spSlot(A0) ; spSlot = slot to add
* _AddCard ; initialize a newly-installed card
MOVEQ #$1E,D0
_SlotManager
LEA spBlockSize(SP),SP ; clean up the stack
RTS
;__________________________________________________________________________________________________
;
; Routine: RemoveSlot
;
; Inputs: A2 - pointer to Docking Manager's globals
; D1 - slot number
;
; Outputs: none
;
; Trashes: A0, D0
;
; Function: cleans up a slot after a bar has gone away
;__________________________________________________________________________________________________
RemoveSlot MOVE.L jRemoveSlot(A2),-(SP)
RTS
vRemoveSlot MOVEQ #spBlockSize/2-1,D0 ; allocate a cleared parameter block on the stack <H33>
@ClearBlock CLR.W -(SP) ; <H33>
DBRA D0,@ClearBlock ; <H33>
MOVEA.L SP,A0 ; and point to it
MOVE.B D1,spSlot(A0) ; spSlot = slot to kill
* _RemoveCard ; throw everything away
MOVEQ #$1F,D0
_SlotManager
LEA spBlockSize(SP),SP ; clean up the stack
RTS
;__________________________________________________________________________________________________
;
; Routine: GetDockingHandler
;
; Inputs: A2 - pointer to Docking Manager's globals
;
; Outputs: A1 - pointer to docking handler if it's found
; CCR - BNE: couldn't load the docking handler
;
; Trashes: A0, D0-D1
;
; Function: tries to load the docking handler if it can find one
;__________________________________________________________________________________________________
GetDockingHandler
MOVE.L jGetDockingHandler(A2),-(SP)
RTS
vGetDockingHandler
LEA -spBlockSize(SP),SP ; allocate a parameter block on the stack
MOVEA.L SP,A0 ; and point to it
MOVE.W #CatDock,spCategory(A0) ; spCategory = docking handler
CLR.W spCType(A0) ; spCType = 0
CLR.W spDrvrSW(A0) ; spDrvrSW = 0
CLR.W spDrvrHW(A0) ; spDrvrHW = 0
MOVE.B #7,spTBMask(A0) ; spTBMask = mask cType, DrSW, DrHW
MOVE.B dockingSlotNum(A2),spSlot(A0) ; spSlot = docking slot
CLR.B spId(A0) ; spId = 0
CLR.B spExtDev(A0) ; no external devices
CLR.W spHwDev(A0) ; spHWDev = 0
Clr.l spParamData(A0) ; (The docking sRsrc must be enabled.)
Bset #foneslot,spParamData+3(A0) ; Limit search to this slot.
_GetTypeSRsrc ; Get the spsPointer.
BNE.S @NoHandler ; -> can't find a docking handler
MOVE.B #sRsrcDock,spId(A0) ; spId = docking handler
_SGetBlock ; load the docking handler into the system heap
BNE.S @NoHandler ; -> couldn't do it
MOVEA.L spResult(A0),A1 ; get the address of the docking handler
Bsr.l CacheFlush ; Flush those caches (trashes reg D1).
Moveq #0,D0 ; Make sure we return BEQ here.
@NoHandler LEA spBlockSize(SP),SP ; toss the parameter block
RTS
;__________________________________________________________________________________________________
;
; Routine: AddVideoDevice
;
; Inputs: A2 - pointer to Docking Manager's globals
; D1 - slot number
;
; Outputs: D0 - video driver's refNum
; CCR - BNE: video device was successfully installed
;
; Trashes: D0, D2, A0, A1
;
; Function: Looks for a video driver in the specified slot. If it finds one, it installs it,
; and then sets up and initializes a GDevice for that monitor.
;__________________________________________________________________________________________________
AddVideoDevice
MOVE.L jAddVideoDevice(A2),-(SP)
RTS
AVStack RECORD {A6Save},DECREMENT
result DS.W 1
A6Save DS.L 1
driverName DS.B 256
sExecBlock DS.B seBlockSize
slotPB DS.B spBlockSize
AVStackSz EQU *
ENDR
WITH AVStack
vAddVideoDevice
@savedRegs REG D1/D3/A2-A3 ; <H14>
MOVEM.L @savedRegs,-(SP) ; <H14>
CLR.W -(SP) ; assume we can't setup a video device <H15>
LINK A6,#AVStackSz ; allocate a parameter block on the stack
MOVEA.L SP,A0 ; and point to it
MOVEQ #1<<foneslot,D0 ; look only in the given slot
MOVE.L D0,spParamData(A0)
MOVE.W #CatDisplay,spCategory(A0) ; category = display
MOVE.W #typVideo,spCType(A0) ; type = video
MOVE.W #drSwApple,spDrvrSW(A0) ; software type = Apple
CLR.W spDrvrHW(A0) ; hardware type = any
MOVE.B #1,spTBMask(A0) ; mask = ignore spDrvrHW
MOVE.B D1,spSlot(A0) ; spSlot = slot to check
CLR.B spID(A0) ; begin at ID 0
CLR.B spExtDev(A0) ; no external devices
_GetTypeSRsrc ; look for any video driver
BNE @NoDriver ; -> couldn't find one
MOVEA.L spsPointer(A0),A2 ; save ptr to sRsrc <H14>
LEA driverName(A6),A1 ; point to the driver name string
MOVE.L A1,spResult(A0)
_sReadDrvrName ; get the driver's name
BNE @NoDriver ; -> couldn't find it
MOVE.W spSlot(A0),sExecBlock+seSlot(A6) ; copy slot number and sRsrc ID
MOVE.L A1,sExecBlock+seIOFileName(A6) ; pointer to driver's name
MOVE.B spExtDev(A0),sExecBlock+seDevice(A6); which device to read from
LEA -ioQElSize(SP),SP ; allocate a parameter block on the stack
MOVE.L spResult(A0),ioFileName(SP) ; driver name
CLR.B ioPermssn(SP) ; permission = whatever goes
CLR.L ioMix(SP) ; this needs to be zero
MOVEQ #1<<fMulti,D0 ; show that we're using an SEBlock
MOVE.W D0,ioFlags(SP)
LEA sExecBlock(A6),A1
MOVE.L A1,ioSEBlkPtr(SP) ; pointer to SEBlock
MOVE.L A0,A1 ; save the pointer to the spBlock
MOVEA.L SP,A0 ; and point to the I/O pb
_Open ,IMMED ; open the driver
MOVEQ #0,D3 ; <H15>
MOVE.W ioRefNum(A0),D3 ; save the driver's reference number <H15>
MOVEA.L A1,SP ; toss the parameter block
MOVEA.L A1,A0 ; point back at the slot pb
LEA -SizesPRAMRec(SP),SP ; allocate a slot PRAM record on the stack
MOVE.L SP,spResult(A0) ; and point to it
_sReadPRAMRec ; get info about this video device
MOVEQ #0,D0
MOVE.B 2(SP),D0 ; get the default video mode
LEA SizesPRAMRec(SP),SP ; clean up
MOVE.L D0,-(SP) ; save mode <H14>
MOVE.B #sRsrcFlags,spID(A0) ; look for sRsrcFlags <H14>
MOVE.L A2,spsPointer(A0) ; set spsPointer to sRsrc <H14>
_sReadWord ; read flag word <H14>
BNE.S @Use24Bit ; no flag field - default to 24 bit mode <H14>
MOVEQ #1<<f32BitMode,D0 ; is this a 32-bit device? <H14>
AND.L spResult(A0),D0 ; d0 = flag word <H14>
BEQ.S @Use24Bit ; -> no <H14>
BSET #31,D3 ; yes - set flag in d3 <H18>
@Use24Bit MOVE.L (SP)+,D0 ; restore mode <H14>
SUBQ.W #4,SP
MOVE.W D3,-(SP) ; refNum <H18>
MOVE.L D0,-(SP) ; mode
_NewGDevice ; allocate a new GDevice for our card
MOVE.L (SP)+,D0 ; was it allocated?
BEQ.S @NoDriver ; -> no, bail
MOVEA.L D0,A3 ; save the GDHandle
LEA DeviceList-gdNextGD,A0
MOVEQ #0,D1 ; initialize rightmost screen location
BRA.S @FirstDevice
@NextDevice MOVEA.L D0,A0 ; get the handle to the next GDevice
MOVEA.L (A0),A0 ; and de-reference it
MOVE.W gdRect+right(A0),D0 ; get the right edge of this device
CMP.W D0,D1 ; is this one farther right than the last?
BGE.S @FirstDevice ; -> nope
MOVE.W D0,D1 ; yes, keep track of it
@FirstDevice
MOVE.L gdNextGD(A0),D0 ; any more GDevices in the list?
BNE.S @NextDevice ; -> yes
MOVE.L A3,gdNextGD(A0) ; tack our GDevice onto the end of the list
MOVEA.L (A3),A0 ; de-reference the handle
BSET #screenDevice-8,gdFlags(A0) ; mark our GDevice as a screen device
TST.L D3 ; test flag whether this a 32 bit device <H18>
BPL.S @Not32 ; no <H18>
BSET.B #ext32Device-8,gdFlags(A0) ; mark as 32 bit frame buffer <H14>
@Not32 PEA gdRect(A0) ; theRect = device's bounds
MOVE.L D1,-(SP) ; dv,dh
MOVEA.L gdPMap(A0),A0 ; get the PixMap handle
MOVEA.L (A0),A0 ; and de-reference it
PEA pmBounds(A0) ; theRect = PixMap's bounds
MOVE.L D1,-(SP) ; dv,dh
_OffsetRect ; move the PixMap's bounds
_OffsetRect ; and gdRect to their new location
MOVEA.L A3,A0 ; put the GDevice handle into A0 <H12>
IMPORT InitDefGamma ; <H12>
BSR.L InitDefGamma ; call this to test <H12>
MOVE.W D3,result(A6) ; show success <H15>
@NoDriver UNLK A6 ; clean up the stack
MOVE.W (SP)+,D0 ; save the refNum and setup the CCR <H15>
MOVEM.L (SP)+,@savedRegs ; restore them regs correctly <H14>
RTS
ENDWITH ; {AVStack}
;__________________________________________________________________________________________________
;
; Routine: RegisterVideo
;
; Inputs: A2 - pointer to Docking Manager's globals
; D0 - video driver's refNum
; D1 - slot number
;
; Outputs: none
;
; Trashes: D0, D2, A0, A1
;
; Function: Given that we've successfully installed a video driver from the docking bar's ROM,
; this routine makes the system aware of the new device, ála the Monitors control panel.
;__________________________________________________________________________________________________
RegisterVideo
MOVE.L jRegisterVideo(A2),-(SP)
RTS
vRegisterVideo
RTS
;__________________________________________________________________________________________________
;
; Routine: RemoveVideo
;
; Inputs: A2 - pointer to Docking Manager's globals
; D1 - slot number
;
; Outputs: none
;
; Trashes: D0, D2, A0, A1
;
; Function: Provides an expansion hook for future system software to allow us to gracefully
; remove a monitor from the desktop.
;__________________________________________________________________________________________________
RemoveVideo MOVE.L jRemoveVideo(A2),-(SP)
RTS
vRemoveVideo
RTS
;__________________________________________________________________________________________________ <H9>
;
; Routine: ResolveSerialPorts
;
; Inputs: A2 - pointer to Docking Manager's globals
;
; Outputs: none
;
; Trashes: D0, D1, D2, A0, A1
;
; Function: Calls Alex Kazim's hack to the Comm Toolbox to remove and add the appropriate serial
; port resources.
;__________________________________________________________________________________________________
ResolveSerialPorts
MOVE.L jResolveSerialPorts(A2),-(SP)
RTS
vResolveSerialPorts
MOVE.W #CTB_ModemIconID,-(SP) ; remove the modem port (if it exists)
_CTBRemovePort
MOVE.W #CTB_PrinterIconID,-(SP); remove the printer port (if it exists)
_CTBRemovePort
MOVE.W #CTB_ModemIconID,-(SP) ; add in the modem port (if it exists)
_CTBAddPort
MOVE.W #CTB_PrinterIconID,-(SP); add in the printer port (if it exists)
_CTBAddPort
RTS
;__________________________________________________________________________________________________
;
; Routine: DockSleepDenied
;
; Inputs: A0 - pointer to the Power Manager's variables
;
; Outputs: CCR - BNE: NM task was successfully installed, BEQ: can't install
;
; Trashes: none
;
; Function: If the Docking Manager was initialized, install a Notification Manager request to
; let the user know that they can't put the portable to sleep because the connected
; bar doesn't think that's a good idea.
;__________________________________________________________________________________________________
DockingSleepDenied
MOVE.L ([DockingGlobals],jDockingSleepDenied),-(SP)
RTS
vDockingSleepDenied
@savedRegs REG D0-D2/A0-A1
MOVEM.L @savedRegs,-(SP)
BSR DockingDispatchExists ; is the Docking Manager initialized?
BEQ.S @NoDocking ; -> no, bail
MOVEA.L DockingGlobals,A0 ; point to our globals
LEA sleepNMEntry(A0),A0 ; and then to the NM record
BSR NMInstall ; install the NM request if it's not already installed
@NoDocking MOVEM.L (SP)+,@savedRegs
RTS
;__________________________________________________________________________________________________
;
; Routine: DockingWakeupDenied
;
; Inputs: none
;
; Outputs: none
;
; Trashes: none
;
; Function: If the Docking Manager was initialized, install a Notification Manager request to
; let the user know that they tried to wakeup with a new bar attached that's not
; supposed to be added during sleep. After this call is made, the system will go
; back to sleep, so the message will be displayed when we succussfully wake up.
;__________________________________________________________________________________________________
DockingWakeupDenied
MOVE.L ([DockingGlobals],jDockingWakeDenied),-(SP)
RTS
vDockingWakeupDenied
@savedRegs REG D0-D2/A0-A1
MOVEM.L @savedRegs,-(SP)
BSR DockingDispatchExists ; is the Docking Manager initialized?
BEQ.S @NoDocking ; -> no, bail
MOVE.L #dockEjectCPU,D0 ; tell the docking station to eject when the power goes off
BSR DockStatus
MOVEA.L DockingGlobals,A0 ; remember we have to remove the current handler next time we wake up
BSET #dockForceRemoval,dockingFlags(A0) ; <H21>
LEA wakeupNMEntry(A0),A0 ; point to the NM record
BSR NMInstall ; install the NM request if it's not already installed
@NoDocking MOVEM.L (SP)+,@savedRegs
RTS
;__________________________________________________________________________________________________
;
; pascal void SleepNMResponse(NMRec *nmReq)
;
; Notification Manager response procedure for signaling that the sleep notification is complete.
;__________________________________________________________________________________________________
SleepNMResponse
MOVEA.L PMgrBase,A1
BCLR #InSleep,PmgrFlags(A1) ; show that we're not in the sleep code anymore
BCLR #ClamshellClosed,PmgrFlags(A1) ; and that the clamshell switch is fair game again <H15>
BRA.S WakeupNMResponse ; branch to the standard response procedure
;__________________________________________________________________________________________________
;
; pascal void EjectNMResponse(NMRec *nmReq)
;
; Notification Manager response procedure for signaling that the eject notification is complete.
;__________________________________________________________________________________________________
EjectNMResponse
MOVEA.L DockingGlobals,A1 ; <H17>
CLR.B dockingEjectFlags(A1) ; back us out of the eject <H17>
MOVE.L #dockEjectStatus,D0 ; reset the eject switch in case the user pressed it <H17>
BSR DockStatus ; while the NM dialog was up <H17>
* BRA.S WakeupNMResponse ; fall thru into the standard response procedure
;__________________________________________________________________________________________________
;
; pascal void WakeupNMResponse(NMRec *nmReq)
;
; Notification Manager response procedure for signaling that the wakeup notification is complete.
;__________________________________________________________________________________________________
WakeupNMResponse
MOVEA.L (SP)+,A1 ; pop the return address
MOVEA.L (SP)+,A0 ; and the pointer to the NM record
CLR.B nmRefCon(A0) ; flag that the notification has been received
_NMRemove ; remove the request from the queue
JMP (A1)
;__________________________________________________________________________________________________
;
; Routine: CheckForEject
;
; Inputs: A0 - pointer to VBL task element
;
; Outputs: none
;
; Trashes: D0, D1, D2, A0, A1, A2
;
; Function: Checks if the user has pushed the eject button on a docking station (assuming there
; is one). If so, it shuts down and ejects the CPU if it's not locked into the station.
; If it is locked, we'll put up a message telling them why they can't eject.
;__________________________________________________________________________________________________
CheckForEject
MOVE.L A0,-(SP)
MOVE.W #Unimplement,D0 ; is _SyncIdleTime implemented?
_GetTrapAddress ,NEWTOOL
MOVEA.L A0,A1
MOVE.W #SyncIdleTime,D0
_GetTrapAddress ,NEWTOOL
CMPA.L A0,A1
BEQ.S @NoSyncIdle ; -> no, we're done
MOVEA.L DockingGlobals,A2
MOVE.L A0,dockOldSyncIdleTime(A2) ; save the old trap address
LEA EjectShutdown,A0 ; and head patch us
MOVE.W #SyncIdleTime,D0
_SetTrapAddress ,NEWTOOL
LEA CheckForEject2,A1
MOVE.L A1,ejectVBLTask+vblAddr(A2) ; shorten this VBL task (no _SyncIdleTime check now)
@NoSyncIdle MOVEA.L (SP)+,A0
CheckForEject2
MOVE.W #ejectVBLCount,vblCount(A0) ; reset the counter
IF hasPwrControls THEN ; <H22>
MOVEA.L PMgrBase,A1 ; <H22>
TST.B SysTaskFlag(A1) ; has SystemTask been called yet? <H22>
BEQ.S NMDone ; -> no, don't allow ejects yet (the system will freak) <H22>
ENDIF ; <H22>
MOVEA.L DockingGlobals,A2 ; point to the docking globals
IF dockEjectPressed=7 THEN
TST.B dockingEjectFlags(A2) ; is a request pending?
BMI.S NMDone ; -> yes, let it complete
ELSE
BTST #dockEjectPressed,dockingEjectFlags(A2) ; is a request pending?
BNE.S NMDone ; -> yes, let it complete
ENDIF
MOVE.L #dockEjectStatus,D0 ; get the eject status
BSR DockStatus
BTST #dockEjectEnabled,D0 ; was the eject button hit?
BEQ.S NMDone ; -> no, done
BSET #dockEjectPressed,dockingEjectFlags(A2) ; set a flag to prevent re-entrancy
MOVE.L #dockLockAttr,D0 ; get the lock attributes
BSR DockStatus
BTST #dockLockEnabled,D0 ; is the CPU locked into the docking station?
BNE.S @Locked ; -> yes, put up a message
MOVE.L #dockEjectCPU,D0 ; tell the docking station to eject on power off
BSR DockStatus
TST.L dockOldSyncIdleTime(A2) ; is the _SyncIdleTime patch installed?
BNE.S NMDone ; -> yes, we'll finish later
_SDPowerOff ; just shutdown the system since the Finder's not running anyway
BRA.S *
@Locked LEA ejectNMEntry(A2),A0 ; point to the NM record
;••• MOVE.L lockedEjectMsg(A2),nmStr(A0); load the “CPU is locked to docking bar” message
NMInstall TST.B nmRefCon(A0) ; is this request already pending?
BNE.S NMDone ; -> yes, let it complete
TST.L nmStr(A0) ; is there a string to use to notify the user?
BEQ.S NMDone ; -> no, can't do anything
_NMInstall ; and install the request
SEQ D0 ; mark the request installed if successful
MOVE.B D0,nmRefCon(A0) ; force CCR to BNE if it was installed
NMDone RTS
;————————————————————————————————————————————————————————————————————————————————————————
; pascal void EjectShutdown(void)
;
; This is a head patch to _SyncIdleTime ($ABF7) to send a shutdown message to
; the Finder at a time when it can do something.
;————————————————————————————————————————————————————————————————————————————————————————
EjectShutdown ; <H17>
MOVEA.L DockingGlobals,A1 ; point to the Docking Manager's globals
IF dockEjectPressed=7 THEN
TST.B dockingEjectFlags(A1) ; has the user pressed the eject button?
BPL.S @NoEject ; -> no, just passing thru
ELSE
BTST #dockEjectPressed,dockingEjectFlags(A1) ; has the user pressed the eject button?
BEQ.S @NoEject ; -> no, just passing thru
ENDIF
TST.B ejectNMEntry+nmRefCon(A1) ; is a NM dialog up?
BNE.S @NoEject ; -> yes, problems, so don't do the eject thing
BSET #dockShuttingDown,dockingEjectFlags(A1) ; have we been here before?
BNE.S @NoEject ; -> yes, once is enough
MOVEA.L jGracefulShutdown(A1),A0 ; call the graceful shutdown routine
JSR (A0)
BEQ.S @NoEject ; -> the shutdown is under way
BCLR #dockShuttingDown,dockingEjectFlags(A1) ; we couldn't shutdown now
TST.W D0 ; are we waiting on the Finder?
BGT.S @NoEject ; -> yes, we'll finish up later
LEA ejectNMEntry(A1),A0 ; point to the NM record
;••• MOVE.L finderBlockedMsg(A1),nmStr(A0); load the “somethings blocking shutdown” message
BSR.S NMInstall ; install the NM request if it's not already installed
BNE.S @NoEject ; -> task was installed
BCLR #dockEjectPressed,dockingEjectFlags(A1) ; back us out of the eject
@NoEject MOVEA.L dockOldSyncIdleTime(A1),A0 ; return so the Finder can do the shutdown
JMP (A0)
;————————————————————————————————————————————————————————————————————————————————————————
; Routine: GracefulShutdown
;
; Inputs: none
;
; Outputs: D0 - result code
; =0: shutdown message successfully sent to the Finder
; >0: waiting for the Finder to become the front process
; <0: a problem occurred (no Finder, something blocking, etc.)
;
; Trashes: none
;
; Function: Sends a shutdown event to the Finder (if the Finder is running) so it will
; quit all running applications. If the required OS support is not present,
; we'll back down to doing just a straight shutdown instead.
;————————————————————————————————————————————————————————————————————————————————————————
receiverIDisPSN EQU $00008000 ; use a process number for the receiver ID
GracefulShutdown
@savedRegs REG D1-D2/A0-A2
MOVEM.L @savedRegs,-(SP)
; check if the Process Manager/MultiFinder is installed...
MOVE.W #Unimplement,D0 ; get the address of the _Unimplemented trap
_GetTrapAddress ,NEWTOOL
MOVEA.L A0,A1
MOVE.W #$A88F,D0 ; get the address of _OSDispatch
_GetTrapAddress ,NEWTOOL
CMPA.L A0,A1 ; is _OSDispatch implemented?
BEQ @JustShutDown ; -> no, do it the old way
MOVE.W @Gestalt,D0 ; is Gestalt implemented?
_GetTrapAddress ,NEWOS
CMPA.L A0,A1
BEQ @JustShutDown ; -> no
MOVE.L #gestaltAppleEventsAttr,D0 ; get AppleEvents attributes
@Gestalt _Gestalt
MOVE.L A0,D0
BTST #gestaltAppleEventsPresent,D0 ; are AppleEvents supported?
BEQ @JustShutDown ; -> no, can't send a message
; try to find the Finder in the list of active processes...
LINK A6,#-ProcessInfoRec.size ; allocate a process info record on the stack
MOVEQ #ProcessInfoRec.size,D0 ; initialize the record
MOVE.L D0,processInfoLength(SP)
CLR.L processName(SP)
CLR.L processNumber.highLongOfPSN(SP)
MOVE.L #kNoProcess,processNumber.lowLongOfPSN(SP)
CLR.L processAppSpec(SP)
MOVEA.L SP,A2 ; point to the process info record
SUBQ.W #2,SP ; space for result (this gets left on the stack)
@FindFinder PEA processNumber(A2) ; PSN
_GetNextProcess ; get the next process' PSN
MOVE.W (SP),D0
BNE @NoFinder ; -> no more processes: couldn't find the Finder
PEA processNumber(A2) ; PSN
MOVE.L A2,-(SP) ; info
_GetProcessInformation ; get information about this process
MOVE.W (SP),D0
BNE.S @NoFinder ; -> bad PSN?
CMPI.L #'FNDR',processType(A2) ; is this process the Finder?
BNE.S @FindFinder ; -> no, keep looking
; make sure the Finder's the front process before telling it to shut down...
LEA -ProcessSerialNumber.size-2(SP),SP ; <H20>
PEA 2(SP) ; PSN <H20>
_GetFrontProcess ; get the process number of the front process <H20>
TST.W (SP)+ ; is there a front process? <H20>
BNE.S @JustShutDown ; -> no, just shut down (why no foreground process?) <H20>
CLR.L -(SP) ; space for result + result code <H20>
PEA processNumber(A2) ; PSN1 <H20>
PEA 4+2+2(SP) ; PSN2 <H20>
PEA 4+4+2(SP) ; result <H20>
_SameProcess ; compare process numbers <H20>
TST.W (SP)+ ; <H20>
BNE.S @JustShutDown ; -> bad process number? <H20>
TST.B (SP)+ ; is the Finder the front process? <H20>
LEA ProcessSerialNumber.size(SP),SP ; (toss the process number record) <H20>
BNE.S @FinderInFront ; -> yes, we're ready to shutdown <H20>
PEA processNumber(A2) ; PSN
_SetFrontProcess ; force the Finder to the front
MOVE.W (SP),D0 ; is it going to happen?
BNE.S @NoFinder ; -> nope, something's preventing it
MOVEQ #1,D0 ; show the Finder is being brought to the front <H20>
BRA.S @NoFinder ; <H20>
; the Finder's now in front so tell it to shut everybody down...
@FinderInFront
_BeginSystemMode ; enter system mode
PEA @ShutDownEvent ; theEvent
PEA processNumber(A2) ; receiverID
CLR.L -(SP) ; msgRefCon
CLR.L -(SP) ; msgBuff
CLR.L -(SP) ; msgLen
MOVE.L #receiverIDisPSN,-(SP) ; postingOptions
_PostHighLevelEvent ; send the event to the Finder (leave result on stack)
_EndSystemMode ; exit system mode
MOVEQ #0,D0 ; show no error
@NoFinder UNLK A6 ; toss the stack frame
MOVEM.L (SP)+,@savedRegs
RTS
@JustShutDown
_SDPowerOff ; single Finder: shutdown the system
BRA.S *
@ShutDownEvent ; HighLevel EventRecord to tell the Finder to shutdown
DC.W 0 ; what
DC.L 'FNDR' ; message = event class (Finder's application signature)
DC.L 0 ; ticks
DC.L 'shut' ; where = event ID (shutdown)
CLR.W 0 ; meta
;__________________________________________________________________________________________________
;
; The following tables are used for initializing the routine vectors for a particular machine.
; If there are no special machine-specific characteristics, there doesn't need to be a vector
; table since in that case the default vectors will be used.
;__________________________________________________________________________________________________
DockingVectorTable
IF hasMSC THEN
DC.B 0,MSCDecoder ; handle MSC Decoder
DC.L MSCVectors-*
ENDIF
IF hasNiagra THEN ; <H11>
DC.B 0,NiagraDecoder ; handle Niagra decoder <H11>
DC.L NiagraVectors-* ; <H11>
ENDIF ; <H11>
IF hasPratt THEN ; <K2>
DC.B 0,PrattDecoder ; handle Pratt decoder <K2>
DC.L PrattVectors-* ; <K2>
ENDIF ; <K2>
DC.W -1 ; default vectors (this should be the last entry)
DC.L DefaultVectors-*
DefaultVectors
DC.L (1<<dockSCCModemPort) |\; both SCC ports are available
(1<<dockSCCPrinterPort)
DC.L NoBoardHandler-(*+4)
DC.L TravelBarHandler-(*+4)
DC.L vDockingSleep-(*+4)
DC.L vDockingWakeup-(*+4)
DC.L vInstallHandler-(*+4)
DC.L vSetHardwareBases-(*+4)
DC.L vCheckConnect-(*+4)
DC.L vCheckBarChanged-(*+4)
DC.L vAddSlot-(*+4)
DC.L vRemoveSlot-(*+4)
DC.L vGetDockingHandler-(*+4)
DC.L Done-(*+4)
DC.L Done-(*+4)
DC.L vAddVideoDevice-(*+4)
DC.L vRegisterVideo-(*+4)
DC.L vRemoveVideo-(*+4)
DC.L vResolveSerialPorts-(*+4)
DC.L vDockingSleepDenied-(*+4)
DC.L vDockingWakeupDenied-(*+4)
DC.L vDockingFilter-(*+4)
DC.L GracefulShutdown-(*+4)
DC.L 0
IF hasMSC THEN
;•••••••••••••••••••••••••••••••••••••••••••••• MSC •••••••••••••••••••••••••••••••••••••••••••••••
MSCVectors DC.L (1<<dockSCCModemPort) ; just the modem port is available
DC.L NoBoardHandler-(*+4)
DC.L TravelBarHandler-(*+4)
DC.L vDockingSleep-(*+4)
DC.L vDockingWakeup-(*+4)
DC.L vInstallHandler-(*+4)
DC.L vSetHardwareBases-(*+4)
DC.L CheckConnectMSC-(*+4)
DC.L vCheckBarChanged-(*+4)
DC.L vAddSlot-(*+4)
DC.L vRemoveSlot-(*+4)
DC.L vGetDockingHandler-(*+4)
DC.L ClockOffMSC-(*+4)
DC.L ClockOnMSC-(*+4)
DC.L vAddVideoDevice-(*+4)
DC.L vRegisterVideo-(*+4)
DC.L vRemoveVideo-(*+4)
DC.L vResolveSerialPorts-(*+4)
DC.L vDockingSleepDenied-(*+4)
DC.L vDockingWakeupDenied-(*+4)
DC.L vDockingFilter-(*+4)
DC.L GracefulShutdown-(*+4)
DC.L 0
;__________________________________________________________________________________________________
;
; Routine: CheckConnectMSC
;
; Inputs: A2 - pointer to Docking Manager's globals
;
; Outputs: CCR - BNE: bar is connected, BEQ: no bar (bar none?)
;
; Trashes: A0,D0
;
; Function: calls the Power Manager to determine if a bar is connected
;__________________________________________________________________________________________________
CheckConnectMSC
CLR.W -(SP) ; make space for the result
MOVE.L SP,-(SP) ; pmRBuffer
MOVE.L (SP),-(SP) ; pmSBuffer
CLR.W -(SP) ; pmLength
MOVE.W #readExtSwitches,-(SP) ; pmCommand
MOVEA.L SP,A0 ; point to the buffer
_PMgrOp ; get the info
LEA pmRBuffer+4(SP),SP ; toss the parameter block
BTST #dockingBar,(SP)+ ; setup the CCR for exit
RTS
;__________________________________________________________________________________________________
;
; Routine: ClockOffMSC
;
; Inputs: A2 - pointer to Docking Manager's globals
;
; Outputs: none
;
; Trashes: A0
;
; Function: turns off the I/O clock going to the connector when a bar is not plugged in
;__________________________________________________________________________________________________
ClockOffMSC MOVEA.L VIA2,A0
BCLR #MSCIOClk,MSCClkCntl(A0); turn off the I/O clock to the bar
MOVE.B #(0<<ifIRQ) | (1<<RvIRQ6En),MSCSlotIER(A0) ; disable slot E interrupts
RTS
;__________________________________________________________________________________________________
;
; Routine: ClockOnMSC
;
; Inputs: A2 - pointer to Docking Manager's globals
;
; Outputs: none
;
; Trashes: A0
;
; Function: turns on the I/O clock going to the connector when a bar IS plugged in
;__________________________________________________________________________________________________
ClockOnMSC MOVEA.L VIA2,A0
BSET #MSCIOClk,MSCClkCntl(A0); turn on the I/O clock to the bar
MOVE.B #(1<<ifIRQ) | (1<<RvIRQ6En),MSCSlotIER(A0) ; enable slot E interrupts
RTS
ENDIF ; {hasMSC}
IF hasNiagra THEN ; <H11>
;•••••••••••••••••••••••••••••••••••••••••••• Niagra ••••••••••••••••••••••••••••••••••••••••••••••
NiagraVectors
DC.L (1<<dockSCCModemPort) |\; both SCC ports are available
(1<<dockSCCPrinterPort)
DC.L NoBoardHandler-(*+4)
DC.L NoBoardHandler-(*+4)
DC.L vDockingSleep-(*+4)
DC.L vDockingWakeup-(*+4)
DC.L vInstallHandler-(*+4)
DC.L vSetHardwareBases-(*+4)
DC.L CheckConnectNiagra-(*+4)
DC.L vCheckBarChanged-(*+4)
DC.L vAddSlot-(*+4)
DC.L vRemoveSlot-(*+4)
DC.L vGetDockingHandler-(*+4)
DC.L Done-(*+4)
DC.L Done-(*+4)
DC.L vAddVideoDevice-(*+4)
DC.L vRegisterVideo-(*+4)
DC.L vRemoveVideo-(*+4)
DC.L Done-(*+4) ; <H12>
DC.L vDockingSleepDenied-(*+4)
DC.L vDockingWakeupDenied-(*+4)
DC.L vDockingFilter-(*+4)
DC.L GracefulShutdown-(*+4)
DC.L 0
ENDIF ; {hasNiagra}
;__________________________________________________________________________________________________ <H12>
;
; Routine: CheckConnectNiagra, CheckConnectPratt
;
; Inputs: A2 - pointer to Docking Manager's globals
;
; Outputs: CCR - BNE: bar is connected, BEQ: no bar (bar none?)
;
; Trashes: A0,D0
;
; Function: returns connected if the VSC video is turned on since Dartanian's bar is built
; into the box.
;__________________________________________________________________________________________________
CheckConnectPratt
CheckConnectNiagra
lea -spBlockSize(sp),sp ; alloc spBlock
movea.l sp,a0
move.b dockingSlotNum(a2),spSlot(a0) ; slot VSC video is on
_sCkCardStat ; see if card was added ok
lea spBlockSize(sp),sp ; dealloc spBlock
seq d0 ; if bad, return "not connected"
tst.b d0 ; set the CCR
rts
IF hasPratt THEN ; <K2>
;•••••••••••••••••••••••••••••••••••••••••••• Pratt ••••••••••••••••••••••••••••••••••••••••••••••
PrattVectors
DC.L (1<<dockSCCModemPort) ; only port A (modem port) is available
DC.L NoBoardHandler-(*+4)
DC.L NoBoardHandler-(*+4)
DC.L vDockingSleep-(*+4)
DC.L vDockingWakeup-(*+4)
DC.L vInstallHandler-(*+4)
DC.L Done-(*+4)
DC.L CheckConnectPratt-(*+4)
DC.L CheckBarChangedPratt-(*+4)
DC.L vAddSlot-(*+4)
DC.L vRemoveSlot-(*+4)
DC.L vGetDockingHandler-(*+4)
DC.L Done-(*+4)
DC.L Done-(*+4)
DC.L vAddVideoDevice-(*+4)
DC.L vRegisterVideo-(*+4)
DC.L vRemoveVideo-(*+4)
DC.L Done-(*+4)
DC.L vDockingSleepDenied-(*+4)
DC.L vDockingWakeupDenied-(*+4)
DC.L PrattDockingFilter-(*+4)
DC.L GracefulShutdown-(*+4)
DC.L 0
;__________________________________________________________________________________________________
;
; Routine: PrattDockingFilter
;
; Inputs: D0 - docking attributes returned by the bar
; A2 - pointer to Docking Manager's globals
;
; Outputs: D0 - filtered docking attributes
;
; Trashes: D1,D2,A0,A1
;
; Function: Filters the docking attributes so we can decide how to behave depending on what kind
; of system software support we have. The Display Manager is (currently) a disk thing,
; so well patch this filter out on disk if the Display Manager is around, otherwise
; we dont allow sleeping if external video is enabled.
;
; Note: This filter differs from the “standard” filters in that we dont need to check
; for the case where the LCD screen isnt useable (since all-in-one PowerBooks
; dont “dock” per se), and since Pratt is 040 based, the FPU doesnt matter.
; (I believe that the FPU wont matter for the PowerPC case, either.)
;__________________________________________________________________________________________________
PrattDockingFilter
MOVE.L D0,-(SP)
MOVE.L #dockHardwareAttr,D0 ; get the hardware attributes
BSR DockStatus
MOVE.L D0,D1
MOVE.L (SP)+,D0
BTST #dockSleepAddition,dockingFlags(A2) ; is this a startup or wakeup case?
BEQ.S @Startup ; -> wakeup
SWAP D1 ; use the wakeup hardware attributes
@Startup ANDI.W #(1<<dockHasVideo),D1 ; does this bar have video?
BEQ.S @Done ; -> no
BSET #dockNoSleep,D0 ; yes, we don't let it sleep
@Done RTS
;__________________________________________________________________________________________________
;
; Routine: CheckBarChangedPratt
;
; Inputs: A2 - pointer to Docking Manager's globals
;
; Outputs: CCR - BNE: bar has changed
;
; Trashes: A0, D0
;
; Function: Since the “bar” on Pratt-based CPUs is built-in, the Docking Handler would never be
; swapped out. So, we now call the Docking Handler to ask it if the world changed.
; If it did, then “BNE”.
;__________________________________________________________________________________________________
CheckBarChangedPratt
Bsr.s DockingDispatchExists ; If DockingDispatch is around,
Bne.s @CallHandler ; then call the Docking Handler.
Moveq #0,D0 ; Otherwise, just say things are okay.
Rts ; And Vamoose.
@CallHandler
Move.l #(1<<dockWorldChanged),D0 ; Inform the Docking Handler that we
Movea.l D0,A0 ; …want to know if the world changed.
Move.l #dockInit,D0 ; The Docking Handler will return
Bsr.s DockControl ; #(1<<dockWorldChanged) if so.
Rts
ENDIF ; {hasPratt}
ENDWITH
END