mirror of
https://github.com/elliotnunn/boot3.git
synced 2024-06-09 17:29:28 +00:00
5b0f0cc134
Resource forks are included only for .rsrc files. These are DeRezzed into their data fork. 'ckid' resources, from the Projector VCS, are not included. The Tools directory, containing mostly junk, is also excluded.
849 lines
28 KiB
Plaintext
849 lines
28 KiB
Plaintext
;
|
|
; File: ApolloDriver.a
|
|
;
|
|
; Contains: This file contains the video driver for use by the Macintosh
|
|
; OS on the Apollo hardware
|
|
;
|
|
; Written by: Mike Puckett.
|
|
;
|
|
; Copyright: © 1991-1992 by Apple Computer, Inc. All rights reserved.
|
|
;
|
|
; Change History (most recent first):
|
|
;
|
|
; <SM3> 11/5/92 SWC Changed VideoEqu.a->Video.a and ShutdownEqu.a->Shutdown.a.
|
|
; <SM2> 11/2/92 kc Don't include SonicEqu.a
|
|
; <1> 10/6/92 GDW New location for ROMLink tool.
|
|
; <1> 3/30/92 JSM first checked in
|
|
; <6> 5/22/91 jmp Code Review changes: For consistency, did a StripAddress on
|
|
; VidOpenÕs copy of the privates; eliminated the redundant clears
|
|
; and checks for the the driver copy of the fixed-entry clut; and
|
|
; replaced #0Õs with #noErrÕs where appropriate.
|
|
; <5> 5/15/91 jmp SetInterrupt wasnÕt checking the input value correctly -- it was
|
|
; doing a csMode(A3) instead of csMode(A2). So, it would either
|
|
; enable (0) or disable (1), depending on whether csMode(A3) was
|
|
; non-zero or not. Also, GetInterrupt returned -1.w (instead of
|
|
; 1.b) for disabled, so some test tools were confused; so, I now
|
|
; just return 1.b when interrupts are disabled.
|
|
; <4> 5/10/91 jmp Fixed a bug in GetInterrupt where I wasnÕt returning the
|
|
; interrupt status, but instead was writing into my private
|
|
; storage! Fixed the error-handling code in VidOpen. Fixed a bug
|
|
; in GetEntries where A0 was not loaded properly. Made GetEntries
|
|
; 32-bit clean. GetEntries was trashing A1, so async calls were
|
|
; failing (i.e., jumping thru IODone requires A1 to be pointing to
|
|
; the AuxDCE). Indexed GetEntries didnÕt work at all because I
|
|
; was checking for indexed via A3 instead of A2! Made the Control
|
|
; & Status dispatchers 32-bit clean. SaveMode was never being
|
|
; setup! Code review changes: Eliminated SetEntries &
|
|
; SetDefaultMode, and fixed GetDefaultMode.
|
|
; <3> 4/17/91 jmp Updated comments and cleaned up the fixed-device support.
|
|
; <2> 2/15/91 jmp Added everything! The only things left to are: 1) Need to
|
|
; change VISA names to Eagle names once Gus/Jim/Celia update the
|
|
; equate files and 2) Need to get the fixed device stuff working
|
|
; properly.
|
|
; <1> 2/10/91 jmp First checked into TERROR ROM.
|
|
;
|
|
; To Do:
|
|
;
|
|
; 1) Need to change VISA names in interrupt handling code to Eagle names.
|
|
; This entails touching SetInterrupt, WaitVSync, and BeginIH.
|
|
;
|
|
|
|
STRING C
|
|
|
|
PRINT OFF
|
|
LOAD 'StandardEqu.d'
|
|
|
|
INCLUDE 'DockingEqu.a'
|
|
INCLUDE 'EgretEqu.a'
|
|
INCLUDE 'GestaltEqu.a'
|
|
INCLUDE 'GestaltPrivateEqu.a'
|
|
INCLUDE 'HardwarePrivateEqu.a'
|
|
INCLUDE 'IOPrimitiveEqu.a'
|
|
INCLUDE 'PowerPrivEqu.a'
|
|
INCLUDE 'ROMEqu.a'
|
|
INCLUDE 'Video.a'
|
|
INCLUDE 'SlotMgrEqu.a'
|
|
INCLUDE 'ShutDown.a'
|
|
; INCLUDE 'SonicEqu.a'
|
|
INCLUDE 'UniversalEqu.a'
|
|
|
|
INCLUDE 'DepVideoEqu.a'
|
|
PRINT ON
|
|
|
|
SEG '_sApolloDriver'
|
|
|
|
BLANKS ON
|
|
STRING ASIS
|
|
MACHINE MC68020
|
|
|
|
; This is device storage which is stored in the dCtlStorage field of the AuxDCE.
|
|
|
|
ApolloVidPrivates RECORD 0
|
|
saveBaseAddr DS.L 1 ; the screen base address
|
|
saveSQElPtr DS.L 1 ; the SQ element pointer (for _SIntRemove)
|
|
saveFixedCLUT DS.L 1 ; pointer to fixed-entry CLUT
|
|
saveNumFixedEntries DS.W 1 ; number of entries in fixed CLUT (zero based)
|
|
saveMode DS.W 1 ; the current mode setting
|
|
GFlags DS.W 1 ; flags word
|
|
ApolloVidPrivSize EQU *
|
|
ENDR
|
|
|
|
LApolloDriver MAIN EXPORT
|
|
|
|
WITH spBlock,SlotIntQElement
|
|
;-------------------------------------------------------------------
|
|
; Video Driver Header
|
|
;-------------------------------------------------------------------
|
|
;
|
|
ApolloDrvr DC.W $4C00 ; ctl,status,needsLock
|
|
DC.W 0,0,0 ; not an ornament
|
|
|
|
; Entry point offset table
|
|
|
|
DC.W ApolloVidOpen-ApolloDrvr ; open routine
|
|
DC.W ApolloDrvr-ApolloDrvr ; no prime
|
|
DC.W ApolloVidCtl-ApolloDrvr ; control
|
|
DC.W ApolloVidStatus-ApolloDrvr ; status
|
|
DC.W ApolloVidClose-ApolloDrvr ; close
|
|
|
|
STRING Pascal
|
|
ApolloVidTitle
|
|
DC.B '.Display_Video_Apple_Apollo'
|
|
STRING ASIS
|
|
ALIGN 2 ; make sure we're word aligned
|
|
DC.W CurApolloDrvrVersion ; version
|
|
|
|
|
|
**********************************************************************
|
|
*
|
|
* ApolloVidOpen allocates private storage for the device in the AuxDCE and locks
|
|
* it down for perpetuity. Also, install the simulated interrupt handler and
|
|
* start it going.
|
|
*
|
|
* Entry: A0 = param block pointer
|
|
* A1 = AuxDCE pointer
|
|
*
|
|
* Locals: A3 = pointer to private storage
|
|
*
|
|
**********************************************************************
|
|
|
|
WITH VDPageInfo,ApolloVidPrivates
|
|
|
|
ApolloVidOpen
|
|
|
|
;
|
|
; Allocate private storage (since block is CLEAR, GFlags are zeroed) and get
|
|
; a pointer to it in A3.
|
|
;
|
|
|
|
MOVEQ #ApolloVidPrivSize,D0 ; get size of parameters
|
|
_ResrvMem ,SYS ; make room as low as possible
|
|
MOVEQ #ApolloVidPrivSize,D0 ; get size of parameters
|
|
_NewHandle ,SYS,CLEAR ; get some memory for private storage
|
|
BNE @OpError1 ; => return an error in open
|
|
MOVE.L A0,dCtlStorage(A1) ; save returned handle in AuxDCE
|
|
_HLock ; and lock it down forever
|
|
|
|
MOVE.L (A0),D0 ; Get a 32-bit clean pointer
|
|
_StripAddress ; to our privates into A3.
|
|
Move.l D0,A3
|
|
|
|
MOVE.L dCtlDevBase(A1),saveBaseAddr(A3) ; save the screen base address
|
|
|
|
; Get and install the interrupt handler. Call the EnableVGuts utility code to do
|
|
; this. This utility also starts the interrupts going. If there is an error
|
|
; condition, EnableVGuts returns with Z-bit cleared.
|
|
;
|
|
|
|
MOVEQ #sqHDSize,D0 ; allocate a slot queue element
|
|
_NewPtr ,SYS,CLEAR ; get it from system heap cleared
|
|
BNE.S @OpError2 ; if not allocated, return bad
|
|
MOVE.L A0,saveSQElPtr(A3) ; save the SQ element pointer.
|
|
|
|
BSR ApolloEnableVGuts ; do it
|
|
BNE.S @OpError2 ;
|
|
|
|
; For doing GetEntries, we need to get our fixed-entry CLUT from the Slot Manager.
|
|
;
|
|
With spBlock
|
|
|
|
Suba #spBlockSize,Sp ; Make an SpBlock on the stack and
|
|
Move.l Sp,A0 ; get a pointer to it in A0.
|
|
|
|
Move.b dCtlSlot(A1),spSlot(A0) ; Get the slotnumber.
|
|
Move.b dCtlSlotID(A1),spID(A0) ; Get the spID of video sRsrc.
|
|
Clr.b spExtDev(A0) ;
|
|
_sRsrcInfo ; Try to get the spsPointer.
|
|
Bne.s @OpError3 ; WeÕre dead if this fails.
|
|
|
|
Move.b #firstVidMode,spID(A0) ; Look for our mode entry.
|
|
_sFindStruct ; If we donÕt find it, then
|
|
Bne.s @OpError3 ; weÕre dead.
|
|
|
|
Move.b #mTable,spID(A0) ; Get our fixed-entry CLUT.
|
|
_sGetBlock ; If we donÕt get it, then
|
|
Bne.s @OpError3 ; weÕre dead.
|
|
|
|
Move.l spResult(A0),A0 ; Get ptr to fixed-entry CLUT
|
|
Move.w ctSize(A0),saveNumFixedEntries(A3) ; Save the number of entries.
|
|
Lea ctTable(A0),A0 ; Get ptr to table, and
|
|
Move.l A0,saveFixedCLUT(A3) ; save it.
|
|
|
|
Adda #spBlockSize,Sp ; restore stack
|
|
|
|
EndWith
|
|
|
|
; ThereÕs only one vidMode, so save it now because SetMode doesnÕt need to.
|
|
;
|
|
Move.w #firstVidMode,saveMode(A3)
|
|
|
|
; All done!
|
|
;
|
|
@AllDone MOVEQ #noErr,D0 ; no error
|
|
@EndOpen RTS ; return
|
|
|
|
@OpError3 ADD.W #spBlockSize,SP ; release the spBlock
|
|
@OpError2 MOVE.L dCtlStorage(A1),A0 ; get the private storage back
|
|
_DisposHandle ; release the driver private storage
|
|
@OpError1 MOVE.L #OpenErr,D0 ; say can't open driver
|
|
BRA.S @EndOpen
|
|
|
|
ENDWITH
|
|
|
|
**********************************************************************
|
|
*
|
|
* Video Driver Control Call Handler. There are ten calls:
|
|
*
|
|
* (0) Reset (VAR mode, page: INTEGER; VAR BaseAddr: Ptr);
|
|
* (1) KillIO
|
|
* (2) SetMode(mode, page: INTEGER; VAR BaseAddr: Ptr);
|
|
* (3) SetEntries ( Table: Ptr; Start,Count : integer );
|
|
* (4) SetGamma ( Table : Ptr );
|
|
* (5) GrayPage (page);
|
|
* (6) SetGray (csMode = 0 for color, 1 for gray)
|
|
* (7) SetInterrupt ( csMode = 0 for enable, 1 for disable)
|
|
* (8) DirectSetEntries (not implemented)
|
|
* (9) SetDefaultMode
|
|
*
|
|
* Entry: A0 = param block pointer
|
|
* A1 = AuxDCE pointer
|
|
* Uses: A2 = ptr to cs parameters (ie. A2 <- csParam(A0))
|
|
* A3 = scratch (doesn't need to be preserved)
|
|
* A4 = scratch (must be preserved)
|
|
* D0-D3 = scratch (don't need to be preserved)
|
|
*
|
|
* Exit: D0 = error code
|
|
*
|
|
**********************************************************************
|
|
|
|
;
|
|
; Decode the call
|
|
;
|
|
|
|
ApolloVidCtl
|
|
MOVEM.L A0/A1,-(SP) ; Preserve exit registers.
|
|
|
|
MOVE.L csParam(A0),A2 ; A2 <- Ptr to control parameters
|
|
|
|
MOVE.L dCtlStorage(A1),A3 ; A3 <- Ptr to private storage
|
|
MOVE.L (A3),D0 ;
|
|
_StripAddress ;
|
|
MOVE.L D0,A3 ;
|
|
|
|
MOVE.W csCode(A0),D0 ; get the opCode
|
|
|
|
CMP.W #9,D0 ; IF csCode NOT IN [0..9] THEN
|
|
BHI.S ApolloCtlBad ; Error, csCode out of bounds
|
|
MOVE.W ApolloCtlJumpTbl(PC,D0.W*2),D0 ; Get the relative offset to the routine
|
|
JMP ApolloCtlJumpTbl(PC,D0.W) ; GOTO the proper routine
|
|
|
|
ApolloCtlJumpTbl
|
|
DC.W ApolloVidReset-ApolloCtlJumpTbl ; $00 => VidReset
|
|
DC.W ApolloCtlGood-ApolloCtlJumpTbl ; $01 => KillIO
|
|
DC.W ApolloSetVidMode-ApolloCtlJumpTbl ; $02 => SetVidMode
|
|
DC.W ApolloCtlBad-ApolloCtlJumpTbl ; $03 => SetEntries (not needed)
|
|
DC.W ApolloCtlBad-ApolloCtlJumpTbl ; $04 => SetGamma (not needed)
|
|
DC.W ApolloGrayPage-ApolloCtlJumpTbl ; $05 => GrayPage
|
|
DC.W ApolloCtlBad-ApolloCtlJumpTbl ; $06 => SetGray (not needed)
|
|
DC.W ApolloSetInterrupt-ApolloCtlJumpTbl ; $07 => SetInterrupt
|
|
DC.W ApolloCtlBad-ApolloCtlJumpTbl ; $08 => DirectSetEntries (not needed)
|
|
DC.W ApolloCtlBad-ApolloCtlJumpTbl ; $09 => SetDefaultMode (not needed)
|
|
|
|
ApolloCtlBad MOVEQ #controlErr,D0 ; else say we don't do this one
|
|
BRA.S ApolloCtlDone ; and return
|
|
|
|
ApolloCtlGood MOVEQ #noErr,D0 ; return no error
|
|
|
|
ApolloCtlDone MOVEM.L (SP)+,A0/A1 ; Restore exit registers.
|
|
BRA ApolloExitDrvr
|
|
|
|
ApolloVidReset
|
|
;---------------------------------------------------------------------
|
|
;
|
|
; Reset the card to its default
|
|
;
|
|
;---------------------------------------------------------------------
|
|
|
|
WITH VDPageInfo,ApolloVidPrivates
|
|
|
|
MOVE #FirstVidMode,csMode(A2) ; return default mode
|
|
MOVE #FirstVidMode,saveMode(A3) ; remember FirstVidMode as the requested mode
|
|
CLR.W csPage(A2) ; return page zero
|
|
MOVE.L saveBaseAddr(A3),csBaseAddr(A2) ; return the base address
|
|
BSR ApolloGrayScreen ; paint the screen gray
|
|
BRA.S ApolloCtlGood ; => no error
|
|
|
|
ENDWITH
|
|
|
|
ApolloSetVidMode
|
|
;---------------------------------------------------------------------
|
|
;
|
|
; Set the card to the specified mode and page. If it's not 1-bit
|
|
; mode, page zero, then return an error
|
|
;
|
|
; If the card is already set to the specified mode, then do nothing.
|
|
;
|
|
;---------------------------------------------------------------------
|
|
|
|
WITH VDPageInfo,ApolloVidPrivates
|
|
|
|
CMP.W #FirstVidMode,csMode(A2) ; is it one-bit (the first and only)
|
|
BNE.S ApolloCtlBad ; => not a valid mode
|
|
|
|
TST.W csPage(A2) ; it is page zero?
|
|
BNE.S ApolloCtlBad ; => not a valid page
|
|
|
|
MOVE.L saveBaseAddr(A3),csBaseAddr(A2) ; return the base address
|
|
BRA ApolloCtlGood ; => return no error
|
|
|
|
ENDWITH
|
|
|
|
ApolloSetEntries
|
|
;---------------------------------------------------------------------
|
|
;
|
|
; Since Apollo has no color table, thereÕs nothing do here. Return a ctl
|
|
; bad result (but do it up above in the control dispatcher, since it
|
|
; saves a few bytes.
|
|
;
|
|
;---------------------------------------------------------------------
|
|
|
|
ApolloSetGamma
|
|
;---------------------------------------------------------------------
|
|
;
|
|
; Since Apollo has no color table, there's no opportunity to set the
|
|
; gamma correction in this hardware. Return a ctl bad result (but
|
|
; do it up above in the control dispatcher, since it saves a few bytes.
|
|
;
|
|
;---------------------------------------------------------------------
|
|
|
|
ApolloGrayPage
|
|
;---------------------------------------------------------------------
|
|
;
|
|
; Clear the specified page in the current mode to gray
|
|
;
|
|
; A0 = Ptr to private storage
|
|
; A1 = Ptr to AuxDCE
|
|
; A2 = Ptr to cs parameter record
|
|
;
|
|
;---------------------------------------------------------------------
|
|
|
|
WITH VDPageInfo,ApolloVidPrivates
|
|
|
|
TST.W csPage(A2) ; Is it requesting page zero?
|
|
BNE ApolloCtlBad
|
|
|
|
BSR ApolloGrayScreen ; paint the screen gray
|
|
BRA ApolloCtlGood ; => return no error
|
|
|
|
ENDWITH
|
|
|
|
ApolloSetGray
|
|
;---------------------------------------------------------------------
|
|
;
|
|
; Since Apollo has no color table, there's no opportunity to set
|
|
; luminence mapping in this hardware. Return a ctl bad result (but
|
|
; do it up above in the control dispatcher, since it saves a few bytes.
|
|
;
|
|
;---------------------------------------------------------------------
|
|
|
|
ApolloSetInterrupt
|
|
;---------------------------------------------------------------------
|
|
;
|
|
; Enable (csMode = 0) or disable (csMode = non-zero) VBL interrupts
|
|
;
|
|
; As a future performance enhancement, interrupts on the card can be
|
|
; disabled or enabled from software. For instance, if the cursor is
|
|
; not on a screen, and there is nothing in the Slot Interrupt Queue
|
|
; for that device, interrupts may be disabled reducing interrupt
|
|
; overhead for the system.
|
|
;
|
|
; The slot interrupt queue element is always allocated by the Open call.
|
|
; This routine just inserts and removes it from the slot interrupt task queue.
|
|
;
|
|
; A1 = Ptr to AuxDCE
|
|
; A2 = Ptr to cs parameter record
|
|
; A3 = Ptr to private storage
|
|
;
|
|
;---------------------------------------------------------------------
|
|
|
|
WITH VDPageInfo,ApolloVidPrivates
|
|
|
|
Tst.b csMode(A2) ; If csMode = 0, then we are
|
|
Beq.s @EnableThem ; enabling VBL interrupts.
|
|
|
|
; This is the code that disables VBL interrupts, then removes the interrupt handler.
|
|
;
|
|
Bsr.s ApolloDisableVGuts ; Do disabling activities, and
|
|
Bra ApolloCtlGood ; return noErr.
|
|
|
|
; This is the code that installs and enables the interrupt handler.
|
|
;
|
|
@EnableThem
|
|
Bsr.s ApolloEnableVGuts ; Do enabling activites, and
|
|
Bne ApolloCtlBad ; flag problem on errors;
|
|
Bra ApolloCtlGood ; otherwise, return noError.
|
|
|
|
; The following two routines are used by SetInterrupt as well as by Open/Close. So,
|
|
; their names donÕt have @Õs in front of them, and they return via Rts instructions.
|
|
;
|
|
ApolloDisableVGuts
|
|
|
|
Bset #IntDisFlag,GFlags(A3) ; Set disabled flag to true.
|
|
|
|
Move.w Sr,-(Sp) ; Preserve the status register.
|
|
Moveq #7,D0 ; Get mask into D0.
|
|
And.b (Sp),D0 ; Get the current interrupt level.
|
|
Subq.b #2,D0 ; If interrupt level ³ 2,
|
|
Bge.s @Ok ; then donÕt change.
|
|
Ori.w #$0200,Sr ; Otherwise, raise it above level 2,
|
|
Andi.w #$FAFF,Sr ; and make it level 2.
|
|
@Ok
|
|
Bsr ApolloWaitVSync ; To be safe, wait for NEXT VBL to occur.
|
|
|
|
MOVE.L VISA,A0 ; Point to the VISA base.
|
|
MOVE.B #$40,RvSEnb(A0) ; Set slot 0 interrupt disabled (slot 0 bit+set/clear to 0).
|
|
|
|
Move.w (Sp)+,Sr ; Restore status register/interrupt level.
|
|
|
|
Clr.w D0 ; Setup for removing slot $0 interrupt handler.
|
|
Move.l saveSQElPtr(A3),A0 ; Get the SQ element ptr.
|
|
_SIntRemove ; Remove the interrupt handler.
|
|
|
|
Rts ; Return home.
|
|
|
|
ApolloEnableVGuts
|
|
|
|
Bclr #IntDisFlag,GFlags(A3) ; Set disabled flag to false.
|
|
|
|
Move.l saveSQElPtr(A3),A0 ; Get the queue element.
|
|
Lea ApolloBeginIH,A2 ; Save pointer to interrupt handler.
|
|
Move.w #siQType,sqType(A0) ; Setup queue ID.
|
|
Move.l A2,sqAddr(A0) ; Setup routine address.
|
|
Move.l A3,SQParm(A0) ; Cache ApolloVidPrivates.
|
|
Clr.w D0 ; Do it for slot $0.
|
|
_SIntInstall
|
|
Bne.s @IntBad
|
|
|
|
MOVE.L VISA,A0 ; Point to the VISA base.
|
|
MOVE.B #$C0,VsSEnb(A0) ; Set slot 0 interrupt enabled (slot 0 bit+set/clear to 1).
|
|
|
|
Cmp D0,D0 ; Clear z-bit for good result.
|
|
@IntBad Rts ; Return home.
|
|
|
|
ENDWITH
|
|
|
|
ApolloSetDefaultMode
|
|
;---------------------------------------------------------------------
|
|
;
|
|
; Since Apollo only has one video sRsrc and itÕs already set, just return
|
|
; a ctl bad result (but do it up above in the control dispatcher, since
|
|
; it saves a few bytes.
|
|
;
|
|
;---------------------------------------------------------------------
|
|
|
|
**********************************************************************
|
|
*
|
|
* VideoClose releases the device's private storage and removes the
|
|
* interrupt handler.
|
|
*
|
|
*
|
|
* Entry: A0 = param block pointer
|
|
* A1 = AuxDCE pointer
|
|
*
|
|
* Other: A2 = temporary AuxDCE pointer copy
|
|
*
|
|
**********************************************************************
|
|
|
|
WITH ApolloVidPrivates
|
|
|
|
ApolloVidClose
|
|
MOVE.L dCtlStorage(A1),A3 ; A3 <- Ptr to private storage
|
|
MOVE.L (A3),D0 ;
|
|
_StripAddress ;
|
|
MOVE.L D0,A3 ;
|
|
|
|
Bsr ApolloDisableVGuts ; Call utility to deactivate interrupts.
|
|
Move.l saveSQElPtr(A3),A0 ; Dispose of the slot interrupt queue element ptr
|
|
_DisposPtr
|
|
|
|
Move.l saveFixedCLUT(A3),A0 ; Dispose of our fixed-entry CLUT.
|
|
_DisposPtr
|
|
|
|
MOVE.L dCtlStorage(A1),A0 ; Dispose of the private storage
|
|
_DisposHandle ;
|
|
|
|
MOVEQ #noErr,D0 ; no error
|
|
RTS ; and return
|
|
|
|
ENDWITH
|
|
|
|
**********************************************************************
|
|
*
|
|
* Video Driver Status Call Handler. Right now there are ten calls:
|
|
*
|
|
* (0) Error
|
|
* (1) Error
|
|
* (2) GetMode
|
|
* (3) GetEntries
|
|
* (4) GetPage
|
|
* (5) GetPageBase
|
|
* (6) GetGray
|
|
* (7) GetInterrupt
|
|
* (8) GetGamma
|
|
* (9) GetDefaultMode
|
|
*
|
|
* Entry: A0 = param block
|
|
* A1 = AuxDCE pointer
|
|
* Uses: A2 = cs parameters
|
|
* A3 = pointer to private storage
|
|
* D0-D3 = scratch (don't need to be preserved)
|
|
*
|
|
* Exit: D0 = error code
|
|
*
|
|
**********************************************************************
|
|
|
|
ApolloVidStatus
|
|
MOVEM.L A0/A1,-(SP) ; Preserve exit registers.
|
|
|
|
MOVE.L csParam(A0),A2 ; A2 <- Ptr to control parameters
|
|
|
|
MOVE.L dCtlStorage(A1),A3 ; A3 <- Ptr to private storage
|
|
MOVE.L (A3),D0 ;
|
|
_StripAddress ;
|
|
MOVE.L D0,A3 ;
|
|
|
|
MOVE.W csCode(A0),D0 ; get routine selector
|
|
|
|
CMP.W #9,D0 ;IF csCode NOT IN [0..9] THEN
|
|
BHI.S ApolloStatBad ; Error, csCode out of bounds.
|
|
MOVE.W ApolloStatJumpTbl(PC,D0.W*2),D0 ;Get the relative offset to the routine.
|
|
JMP ApolloStatJumpTbl(PC,D0.W) ;GOTO the proper routine.
|
|
|
|
ApolloStatJumpTbl
|
|
DC.W ApolloStatBad-ApolloStatJumpTbl ;$00 => Error
|
|
DC.W ApolloStatBad-ApolloStatJumpTbl ;$01 => Error
|
|
DC.W ApolloGetMode-ApolloStatJumpTbl ;$02 => GetMode
|
|
DC.W ApolloGetEntries-ApolloStatJumpTbl ;$03 => GetEntries
|
|
DC.W ApolloGetPage-ApolloStatJumpTbl ;$04 => GetPage
|
|
DC.W ApolloGetPageBase-ApolloStatJumpTbl ;$05 => GetPageBase
|
|
DC.W ApolloStatBad-ApolloStatJumpTbl ;$06 => GetGray (not needed)
|
|
DC.W ApolloGetInterrupt-ApolloStatJumpTbl ;$07 => GetInterrupt
|
|
DC.W ApolloStatBad-ApolloStatJumpTbl ;$08 => GetGamma (not needed)
|
|
DC.W ApolloGetDefaultMode-ApolloStatJumpTbl ;$09 => GetDefaultMode
|
|
|
|
ApolloStatBad MOVEQ #statusErr,D0 ; else say we don't do this one
|
|
BRA.S ApolloStatDone ; and return
|
|
|
|
ApolloStatGood MOVEQ #noErr,D0 ; return no error
|
|
|
|
ApolloStatDone MOVEM.L (SP)+,A0/A1 ; Restore exit registers.
|
|
BRA ApolloExitDrvr
|
|
|
|
ApolloGetMode
|
|
;---------------------------------------------------------------------
|
|
;
|
|
; Return the current mode
|
|
;
|
|
; Inputs : A2 = pointer to csParams
|
|
; A3 = pointer to private storage
|
|
;
|
|
;---------------------------------------------------------------------
|
|
|
|
WITH ApolloVidPrivates,VDPageInfo
|
|
|
|
MOVE.W saveMode(A3),csMode(A2) ; return the mode
|
|
CLR.W csPage(A2) ; return the page number
|
|
MOVE.L saveBaseAddr(A3),csBaseAddr(A2) ; and the base address
|
|
|
|
BRA.S ApolloStatGood ; => return no error
|
|
|
|
ENDWITH
|
|
|
|
ApolloGetEntries
|
|
;---------------------------------------------------------------------
|
|
;
|
|
; Fake the current contents of the CLUT. There isn't really a clut around,
|
|
; but that's no reason not to return a reasonable looking response
|
|
;
|
|
; Inputs : A2 = pointer to csParams
|
|
; A3 = pointer to privates
|
|
;
|
|
; For Apollo the color table is fixed. So, weÕll always return good values
|
|
; as long as there is a reasonable looking color table around.
|
|
;
|
|
; Idea: If weÕre in indexed mode, weÕll cycle thru the input
|
|
; table. While doing this, weÕll ignore all entries
|
|
; whose value fields are out of range. For entries
|
|
; whose value field are in range, weÕll return the
|
|
; appropriate rgb fields.
|
|
;
|
|
; If weÕre in sequential mode, we just need to write out
|
|
; the number of entries we know about.
|
|
;
|
|
;---------------------------------------------------------------------
|
|
|
|
With ApolloVidPrivates
|
|
|
|
Move.l csTable(A2),D0 ; If we were handed a nil pointer,
|
|
Beq ApolloStatBad ; then hike.
|
|
_StripAddress ; Otherwise, make it 32-bit clean.
|
|
|
|
Move.l D4,-(Sp) ; Save work register.
|
|
|
|
; Calculate the index rangeÉ
|
|
;
|
|
Move.w saveNumFixedEntries(A3),D3 ; Get number of entries to check against.
|
|
|
|
Move.w csCount(A2),D4 ; Get the number of entries to set,
|
|
Bmi.s @GEErr ; and hike if itÕs out of range.
|
|
Cmp.w D3,D4 ; If D4-D3 > 0 (count > # of entries),
|
|
Bhi.s @GEErr ; then hike.
|
|
Move.w D4,D2 ; Otherwise, copy the count.
|
|
|
|
Move.l D0,A0 ; Get pointer to input table.
|
|
Cmp.w #indexEntries,csStart(A2) ; If table accesses are to be indexed,
|
|
Beq.s @GECom ; then go on.
|
|
|
|
Move.w D4,D1 ; Otherwise, sequence thru table from
|
|
Add.w csStart(A2),D2 ; csStart thru csCount entries.
|
|
|
|
; The following code is BAD, BAD, BAD! We should build our own table here so
|
|
; as to NOT mess up the userÕs data. But all the previous Apple video drivers
|
|
; have done the same thing, so weÕll continue the trend for now.
|
|
|
|
@TableLoop Move.w D2,value(A0,D1*colorSpecSize) ; Write the index into the table.
|
|
Subq #1,D2 ; Decrement index.
|
|
Dbra D1,@TableLoop
|
|
|
|
@GECom
|
|
@Repeat Move.w value(A0),D1 ; Get the NEXT table position into D1.
|
|
Cmp.w D3,D1 ; If this position is out of range,
|
|
Bhi.s @Until ; then go on.
|
|
|
|
Move.l saveFixedCLUT(A3),A1 ; Point to start of fixed CLUT.
|
|
Lea (A1,D1*colorSpecSize),A1 ; Index into right entry.
|
|
|
|
Move.w rgb+red(A1),rgb+red(A0) ; Copy red,
|
|
Move.w rgb+green(A1),rgb+green(A0) ; green,
|
|
Move.w rgb+blue(A1),rgb+blue(A0) ; blue.
|
|
|
|
@Until Addq #colorSpecSize,A0 ; Point to next entry in input ColorTable.
|
|
Dbra D4,@Repeat
|
|
|
|
Move.l (Sp)+,D4 ; Restore work register.
|
|
Bra ApolloStatGood ; Return noError.
|
|
|
|
@GEErr Move.l (Sp)+,D4 ; Restore work register.
|
|
Bra ApolloStatBad ; Return statError.
|
|
|
|
EndWith
|
|
|
|
ApolloGetPage
|
|
;---------------------------------------------------------------------
|
|
;
|
|
; Return the number of pages in the specified mode.
|
|
;
|
|
;---------------------------------------------------------------------
|
|
|
|
WITH ApolloVidPrivates,VDPageInfo
|
|
|
|
CMP.W #FirstVidMode,csMode(A2) ; this mode, or else
|
|
BNE ApolloStatBad ; oh,oh
|
|
|
|
MOVE.W #OBMPagesApollo,csPage(A2) ; return page count
|
|
BRA ApolloStatGood ; => return no error
|
|
|
|
ENDWITH
|
|
|
|
ApolloGetPageBase
|
|
;---------------------------------------------------------------------
|
|
;
|
|
; Return the base address for the specified page in the current mode
|
|
;
|
|
;---------------------------------------------------------------------
|
|
|
|
WITH ApolloVidPrivates,VDPageInfo
|
|
|
|
MOVE.W csPage(A2),D0 ; get the requested page
|
|
BNE ApolloStatBad ; => no, just return
|
|
|
|
MOVE.L saveBaseAddr(A3),csBaseAddr(A2) ; return the base address
|
|
BRA ApolloStatGood ; => return no error
|
|
|
|
ENDWITH
|
|
|
|
ApolloGetGray
|
|
;---------------------------------------------------------------------
|
|
;
|
|
; No CLUT, so this routine returns an status error. It's implemented
|
|
; in the Status dispatch table above.
|
|
;
|
|
;---------------------------------------------------------------------
|
|
|
|
ApolloGetInterrupt
|
|
;---------------------------------------------------------------------
|
|
;
|
|
; Return a boolean in csMode, set true if VBL interrupts are disabled
|
|
;
|
|
;---------------------------------------------------------------------
|
|
|
|
WITH ApolloVidPrivates,VDPageInfo
|
|
|
|
Btst #IntDisFlag,GFlags(A3) ; If interrupts are enabled (zero)
|
|
Beq.s @IsOn ; then return enabled state.
|
|
Move.b #1,csMode(A2) ; Otherwise, return disabled.
|
|
Bra ApolloStatGood
|
|
@IsOn
|
|
Clr.b csMode(A2) ; Return enabled state.
|
|
Bra ApolloStatGood ; return noErr
|
|
|
|
ENDWITH
|
|
|
|
ApolloGetGamma
|
|
;---------------------------------------------------------------------
|
|
;
|
|
; No CLUT, so this routine returns an status error. It's implemented
|
|
; in the Status dispatch table above.
|
|
;
|
|
;---------------------------------------------------------------------
|
|
|
|
ApolloGetDefaultMode
|
|
;---------------------------------------------------------------------
|
|
;
|
|
; Read the card default mode from slot pRAM.
|
|
;
|
|
; A1 = Ptr to AuxDCE
|
|
; A2 = Ptr to cs parameter record
|
|
; A3 = Ptr to private storage
|
|
;
|
|
;---------------------------------------------------------------------
|
|
|
|
; For most video drivers, we look in pRAM to see what the last
|
|
; configuration set was. However, for Apollo, there only one
|
|
; mode possible, so we just return that value here.
|
|
|
|
WITH VDPageInfo ; GDW1
|
|
MOVE.B dCtlSlotID(A1),csMode(A2) ; return the result
|
|
BRA ApolloStatGood ;
|
|
ENDWITH ; GDW1
|
|
|
|
;---------------------------------------------------------------------
|
|
;
|
|
; Exit from Control or Status.
|
|
;
|
|
; A0 = Ptr to param block.
|
|
; A1 = Ptr to AuxDCE.
|
|
; D0 = error code.
|
|
;
|
|
;---------------------------------------------------------------------
|
|
|
|
ApolloExitDrvr BTST #NoQueueBit,ioTrap(A0) ; no queue bit set?
|
|
BEQ.S ApolloGoIODone ; => no, not immediate
|
|
RTS ; otherwise, it was an immediate call
|
|
|
|
ApolloGoIODone MOVE.L JIODone,-(Sp) ; Get the IODone address,
|
|
Rts ; and go there.
|
|
|
|
;=====================================================================
|
|
;
|
|
; Utilities
|
|
;
|
|
;=====================================================================
|
|
|
|
;---------------------------------------------------------------------
|
|
;
|
|
; Wait for vertical blanking. Interrupts are raised to level-2 around
|
|
; this routine.
|
|
;
|
|
; A1 = AuxDCE POINTER
|
|
; A3 = pointer to private storage
|
|
;---------------------------------------------------------------------
|
|
|
|
ApolloWaitVSync
|
|
|
|
Movem.l A0/D0,-(Sp) ; Save work registers.
|
|
|
|
MOVE.L VISA,A0 ; Point to VISA.
|
|
MOVE.B #$40,VsSInt(A0) ; Clear the interrupt, just in case,
|
|
; since the intHndlr can't get
|
|
; called here.
|
|
|
|
ADDA #VsSInt,A0 ; Point to interrupt register.
|
|
@0 MOVE.B (A0),D0 ; Read the Vert-Sync state.
|
|
BTST #6,D0 ;
|
|
BNE.S @0 ; Repeat until it goes hi.
|
|
|
|
Movem.l (Sp)+,A0/D0 ; Restore registers.
|
|
Rts
|
|
|
|
|
|
ApolloGrayScreen
|
|
;---------------------------------------------------------------------
|
|
;
|
|
; Fill the screen with a 50% dithered gray pattern.
|
|
; A3 = driver private storage
|
|
;
|
|
; All registers are preserved
|
|
;
|
|
|
|
WITH ApolloVidPrivates
|
|
|
|
MOVEM.L D0/D2/D3/A0/A1,-(SP) ; save all registers
|
|
|
|
MOVE.L #OneBitGray,D3 ; get the one-bit gray pattern
|
|
|
|
MOVE.L saveBaseAddr(A3),A0 ; get the frame buffer base address
|
|
MOVE.W #defmBounds_BApollo-1,D0 ; get the # of rows
|
|
|
|
@NxtRow MOVE.W #(OBMApolloRB/4)-1,D2 ; get the # of longs/row
|
|
@NxtLong MOVE.L D3,(A0)+ ; write gray
|
|
DBRA D2,@NxtLong ; for each scanline
|
|
NOT.L D3 ; invert pattern on next row
|
|
DBRA D0,@NxtRow ; for each row
|
|
|
|
MOVEM.L (SP)+,D0/D2/D3/A0/A1 ; restore registers
|
|
RTS
|
|
|
|
ENDWITH
|
|
|
|
;-------------------------------------------------------------
|
|
; The Interrupt handler Apollo Built-In Video
|
|
;-------------------------------------------------------------
|
|
; On entry A1 contains the pointer to the driver's private storage
|
|
; D0-D3/A0-A3 have been preserved.
|
|
|
|
ApolloBeginIH
|
|
|
|
MOVE.L VISA,A0 ; Point to VISA.
|
|
MOVE.B #$40,VsSInt(A0) ; Clear the interrupt.
|
|
|
|
Clr.w D0 ; Setup for slot $0 VBLTask.
|
|
Move.l JVBLTask,A0
|
|
Jsr (A0)
|
|
|
|
Moveq #1,D0 ; Tell the caller that interrupt was handled,
|
|
Rts ; and return.
|
|
|
|
ENDWITH
|
|
END
|