shithub: minivmac

ref: 649e0914486b43f31c89f8d17efc16d9df120198
dir: /extras/mydriver/video/firmware.a/

View raw version
	STRING	C
	MACHINE	MC68020
	PRINT	OFF
	INCLUDE	'SlotEqu.a'
	INCLUDE	'VideoEqu.a'
	INCLUDE	'Traps.a'
	INCLUDE	'SysEqu.a'
	INCLUDE	'SysErr.a'
	PRINT	ON

VideoDeclROM	MAIN

;========================================================================================

; General Directives

	BLANKS	ON
	STRING	ASIS

kCmndVideoSetIntEnbl  EQU $0003
kCmndVideoClearInt    EQU $0004
kCmndVideoStatus      EQU $0005
kCmndVideoControl     EQU $0006

;========================================================================================
;	       Local Vars, definitions, etc...
;========================================================================================

;This is device storage, a handle to which is stored in the dCtlStorage field of the DCE.

saveSQElPtr EQU 0 ; the SQ element pointer (for
                    ;   _SIRemove
dCtlSize    EQU saveSQElPtr+4 ; size of the dCtlStorage

;========================================================================================
;           Video Driver Header
;========================================================================================

VidDrvr
	DC.W    $4C00       ; ctl,status,needsLock
	DC.W    0, 0, 0     ; not an ornament

;Entry point offset table

	DC.W    VideoOpen - VidDrvr   ; open routine
	DC.W    VidDrvr - VidDrvr     ; no prime
	DC.W    VideoCtl - VidDrvr    ; control
	DC.W    VideoStatus - VidDrvr ; status
	DC.W    VideoClose - VidDrvr  ; close

VideoTitle
	STRING  Pascal
	DC.W    '.Display_Video_Sample'
	STRING  ASIS
	ALIGN   2       ; make sure we're aligned
	DC.W    0       ; version-0

;========================================================================================
;VideoOpen allocates private storage for the device in the DCE and locks
;      it down for perpetuity. It installs the interrupt handler and enables
;      the interrupts. It also sets the default gamma table included in the driver.
;
;Entry:
;   A0 = param block pointer
;   A1 = DCE pointer
;
;Locals:
;   A2 = Saved param block pointer
;   A3 = Saved DCE pointer
;   A4 = Saved interrupt handler ptr
;========================================================================================

;Save registers
VideoOpen
	MOVE.L     A0, A2  ; A2 <- param block pointer
	MOVE.L     A1, A3  ; A3 <- DCE pointer

;Allocate private storage
	MOVEQ      #dCtlSize, D0 ; get size of parameters
	_ResrvMem ,SYS           ; make room as low as possible
	MOVEQ      #dCtlSize, D0 ; get size of parameters
	_NewHandle ,SYS,CLEAR    ; get some memory for private
	                         ; storage
	BNE        OpError       ;=> return an error in open
	MOVE.L     A0, dCtlStorage(A3) ; saved returned handle in DCE
	_HLock                   ; and lock it down

;Get and install the interrupt handler
	LEA        BeginIH, A4   ; Save point to interrupt handler
	MOVEQ      #SlotIntQElement.sqHDSize,D0  ; allocate a slot queue element
	_NewPtr    ,SYS,CLEAR    ; get it from system heap cleared
	BNE        OpError
	MOVE.W     #SIQType, SlotIntQElement.sqType(A0) ; setup queue ID
	MOVE.L     A4, SlotIntQElement.sqAddr(A0)  ; setup int routine address
	MOVE.L     A3, SlotIntQElement.sqParm(A0)  ; save slot base addr as A3 parm
	CLR.L      D0
	MOVE.B     dctlSlot(A3), D0 ; setup slot #
	_SIntInstall   ; and do install
	BNE.S      OpError

;Save SQElPtr for removal
	MOVE.L     dCtlStorage(A3), A1  ; Get point to private storage
	MOVE.L     (A1), A1
	MOVE.L     A0, saveSQElPtr(A1)  ; Save the SQ element pointer

;Enable interrupts

	MOVE.W     #1, -(A7) ; enabled
	SUBQ       #2, A7    ; result code
	MOVE.W     #kCmndVideoSetIntEnbl, -(A7)
	LEA        TailData, A0
	MOVE.L     (A0)+, -(A7)
	MOVEA.L    (A0), A0
	MOVE.L     A7, (A0)
	ADDA.W     #10, A7

	MOVEQ      #0, D0      ; no error
	BRA.S      EndOpen

; Error
OpError
	MOVE.L     #openErr, D0  ; say can't open driver
EndOpen
	RTS

;========================================================================================
;          The interrupt handler for the board
;========================================================================================

; On entry A1 contains DCE

; wrong! : "D0-D3/A0-A3 have been preserved."
; (comment from Apples sample code.)
; must preserve registers except A1/D0

BeginIH
	MOVE.L     A0, -(A7)

	; clear interrupt from card

	SUBQ       #2, A7    ; result code
	MOVE.W     #kCmndVideoClearInt, -(A7)

	LEA        TailData, A0
	MOVE.L     (A0)+, -(A7)
	MOVEA.L    (A0), A0
	MOVE.L     A7, (A0)

	ADDQ.W     #8, A7

	MOVE.L     dctlDevBase(A1), D0 ; D0 = $Fsxxxxxx
	ROL.L      #8, D0              ; D0 <- $xxxxxxFs     Convert the
	                               ;                     address into
	AND        #$0F, D0            ; D0 <- $xxxx000x     the slot
	                               ;                     number
	MOVE.L     JVBLTask, A0        ; call the VBL task manager
	JSR        (A0)                ; with slot # in D0

	MOVE.L     (A7)+, A0
	MOVEQ      #1, D0     ; signal that int was serviced
	RTS                   ; and return to caller

;========================================================================================
;
;VideoClose releases the device's private storage.
;
;Entry:
;   A0 = param block pointer
;   A1 = DCE pointer
;
;Locals:
;   A2 = Saved param block pointer
;   A3 = Saved DCE pointer
;   A4 = Temporary
;
;========================================================================================

VideoClose

	MOVE.L     A3, -(A7) ; save
	MOVE.L     dCtlStorage(A1), A3; Get pointer to private storage

	MOVE.W     #0, -(A7) ; disabled
	SUBQ       #2, A7 ; result code
	MOVE.W     #kCmndVideoSetIntEnbl, -(A7)
	LEA        TailData, A0
	MOVE.L     (A0)+, -(A7)
	MOVEA.L    (A0), A0
	MOVE.L     A7, (A0)
	ADDA.W     #10, A7

	MOVE.L     (A3), A0
	MOVE.L     saveSQElPtr(A0), A0 ; Get the SQ element pointer
	_SIntRemove          ; Remove the interrupt handler

	MOVE.L     A3, A0    ; Dispose of the private storage
	_DisposHandle
	MOVEQ      #0, D0    ; get error into D0

	MOVE.L     (A7)+, A3 ; restore A3
	RTS                  ; return to caller

;========================================================================================
;
;Video Driver Control Call Handler.
;
;      Entry:
;   A0    = param block pointer
;   A1    = DCE pointer
;      Uses:
;   A2    = cs paramaters (i.e. A2 <- csParam(A0)) (must be preserved)
;   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
VideoCtl
	MOVE.L     A0, -(A7)
	SUBQ       #2, A7 ; result code
	MOVE.W     #kCmndVideoControl, -(A7)
	BRA.S      VideoStatusControlCommon

;========================================================================================
;
;Video DriverStatus Call Handler.  Right now there are three calls:
;
;      (2)  GetMode
;      (4)  GetPage
;      (5)  GetPageBase
;
;      Entry:
;   A0    = param block
;   A1    = DCE pointer
;      Uses:
;   A2    = cs paramaters (i.e. A2 <- csParam(A0)) (must be preserved)
;   A3    = scratch (doesn't need to be preserved)
;   D0-D3 = scratch (don't need to be preserved)
;
;      Exit:  D0    =       error code
;
;========================================================================================

VideoStatus
	MOVE.L     A0, -(A7)
	SUBQ       #2, A7 ; result code
	MOVE.W     #kCmndVideoStatus, -(A7)
VideoStatusControlCommon
	LEA        TailData, A0
	MOVE.L     (A0)+, -(A7)
	MOVEA.L    (A0), A0
	MOVE.L     A7, (A0)

	ADDA.W     #6, A7
	MOVE.W     (A7)+, D0 ; save result code
	MOVE.L     (A7)+, A0 ; restore A0

;========================================================================================
;      Exit from control or status
;========================================================================================

	BTST       #NoQueueBit,ioTrap(A0) ;no queue bit set?
	BEQ.S      GoIODone     ;=> no, not immediate
	RTS                     ;otherwise, it was an immediate call

GoIODone
	MOVE.L     JIODone,A0   ;get the IODone address
	JMP        (A0)

TailData

	ENDP

	END