; Copyright 2013 Castle Technology Ltd
;
; Licensed under the Apache License, Version 2.0 (the "License");
; you may not use this file except in compliance with the License.
; You may obtain a copy of the License at
;
;     http://www.apache.org/licenses/LICENSE-2.0
;
; Unless required by applicable law or agreed to in writing, software
; distributed under the License is distributed on an "AS IS" BASIS,
; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
; See the License for the specific language governing permissions and
; limitations under the License.
;
; > $.Source.VduGrafHAL
;
; ARTHUR OPERATING SYSTEM - Vdu Drivers
; =======================
;
; Vdu driver code - HAL GraphicsV driver
;
; Author K J Bracey
; Date   30.8.02
;

        MACRO
        GVHEntry $name
        ASSERT  . - MOSGraphicsVHAL_Table = GraphicsV_$name * 4
        B       GVHAL_$name
        MEND

MOSGraphicsVHAL ROUT
        ; HAL driver assumed to be driver #0
        CMP     r4, #(MOSGraphicsVHAL_TableEnd - MOSGraphicsVHAL_Table) / 4
        ADDLO   pc, pc, r4, LSL #2
        MOV     pc, lr                  ; reason code not known, so pass it on
MOSGraphicsVHAL_Table
        MOV     pc, lr                  ; 0
        MOV     pc, lr                  ; 1
        GVHEntry SetMode                ; 2
        GVHEntry SetInterlace           ; 3
        GVHEntry SetBlank               ; 4
        GVHEntry UpdatePointer          ; 5
        GVHEntry SetDMAAddress          ; 6
        GVHEntry VetMode                ; 7
        GVHEntry DisplayFeatures        ; 8
        GVHEntry FramestoreAddress      ; 9
        GVHEntry WritePaletteEntry      ; 10
        GVHEntry WritePaletteEntries    ; 11
        GVHEntry ReadPaletteEntry       ; 12
        GVHEntry Render                 ; 13
        GVHEntry IICOp                  ; 14
        MOV     pc, lr                  ; 15
        GVHEntry StartupMode            ; 16
        GVHEntry PixelFormats           ; 17   GVHAL_PixelFormats
MOSGraphicsVHAL_TableEnd

GVHAL_SetMode
        Push    "r0-r3, r9, lr"
        AddressHAL WsPtr
        MOV     r4, #0
        CallHAL HAL_VideoSetMode
        Pull    "r0-r3, r9, pc"

GVHAL_SetInterlace
        Push    "r0-r3, r9, lr"
        AddressHAL WsPtr
        MOV     r4, #0
        CallHAL HAL_VideoSetInterlace
        Pull    "r0-r3, r9, pc"

GVHAL_SetBlank
        Push    "r0-r3, r9, lr"
        AddressHAL WsPtr
        MOV     r4, #0
        CallHAL HAL_VideoSetBlank
        Pull    "r0-r3, r9, pc"

GVHAL_UpdatePointer
        Push    "r0-r3, r9, lr"
        AddressHAL WsPtr
        CallHAL HAL_VideoUpdatePointer
        TEQ     r0, #0
        MOVNE   r4, #0
        Pull    "r0-r3, r9, pc"

GVHAL_SetDMAAddress
        Push    "r0-r3, r9, lr"
        AddressHAL WsPtr
        MOV     r4, #0
        CallHAL HAL_VideoSetDAG
        Pull    "r0-r3, r9, pc"

GVHAL_VetMode
        Push    "r1-r3, r9, lr"
        AddressHAL WsPtr
        MOV     r4, #0
        CallHAL HAL_VideoVetMode
        Pull    "r1-r3, r9, pc"

GVHAL_DisplayFeatures
        Push    "r0,r1,r3, r9, lr"
        AddressHAL WsPtr
        MOV     r4, #0
        CallHAL HAL_VideoFeatures
        STR     r0, [sp, #0]
        CallHAL HAL_VideoPixelFormats
        STR     r0, [sp, #4]
        CallHAL HAL_VideoBufferAlignment
        MOV     r2, r0
        Pull    "r0,r1,r3, r9, pc"

GVHAL_PixelFormats
        Push    "r3, r9, lr"
        AddressHAL WsPtr
        MOV     r0, #0
        MOV     r1, #0
        CallHAL HAL_VideoPixelFormatList
        ORRS    r3, r2, r1
        MOVNE   r4, #0
        Pull    "r3, r9, pc"

GVHAL_FramestoreAddress
        Push    "r3, r9, lr"
        AddressHAL WsPtr
        MOV     r0, #0
        MOV     r1, #0
        CallHAL HAL_VideoFramestoreAddress
        ORRS    r2, r0, r1
        MOVNE   r4, #0
        Pull    "r3, r9, pc"

GVHAL_WritePaletteEntry
        Push    "r0-r3, r9, lr"
        AddressHAL WsPtr
        MOV     r4, #0
        CallHAL HAL_VideoWritePaletteEntry
        Pull    "r0-r3, r9, pc"

GVHAL_WritePaletteEntries
        Push    "r0-r3, r9, lr"
        AddressHAL WsPtr
        MOV     r4, #0
        CallHAL HAL_VideoWritePaletteEntries
        Pull    "r0-r3, r9, pc"

GVHAL_ReadPaletteEntry
        Push    "r0,r2-r3, r9, lr"
        AddressHAL WsPtr
        CheckHAL HAL_VideoReadPaletteEntry, r3
        Pull    "r0,r2-r3, r9, pc", EQ
        MOV     r4, #0
      [ NoARMv5
        MOV     lr, pc
        MOV     pc, r3
      |
        BLX     r3
      ]
        MOV     r1,r0
        Pull    "r0,r2-r3, r9, pc"

GVHAL_Render
        Push    "r9, lr"
        AddressHAL WsPtr
        LDR     WsPtr, [sb, #-(EntryNo_HAL_VideoRender+1) * 4]
        ADRL    lr, NullHALEntry
        TEQ     WsPtr, lr
        Pull    "r9, pc", EQ ; Early-exit if HAL_VideoRender not supported
        Push    "r0-r3"
        ORR     r0, r0, #1:SHL:31
        MOV     lr, pc
        MOV     pc, WsPtr
        TEQ     r0, #0
        MOVPL   r4, #0
        Pull    "r0-r3, r9, pc"

GVHAL_IICOp
        Push    "r1-r3, r9, lr"
        AddressHAL WsPtr
        Push    "r2"                            ; Bytes desired to tranfer
        MOV     r2, sp
        CallHAL HAL_VideoIICOp
        Pull    "r4"                            ; Bytes actually transferred
        Pull    "r1-r3, r9, lr"
        ADD     r1, r1, r4                      ; Advance pointer
        SUB     r2, r2, r4                      ; Bytes not transferred
        MOV     r4, #0
        MOV     pc, lr

GVHAL_StartupMode
        Push    "r1-r3, r9, lr"
        AddressHAL WsPtr
        CallHAL HAL_VideoStartupMode
        MOV     r4, #0
        Pull    "r1-r3, r9, pc"


VduGrafHAL_Init ROUT
        Entry   "r0-r12"
        AddressHAL

        ; Do we actually have a HAL driver?
        ; For now, just use HAL_VideoPixelFormats as a check
        MOV     r0, #0
        CallHAL HAL_VideoPixelFormats
        TEQ     r0, #0
        EXIT    EQ

        ; Good, we have a driver

        ; Register with the OS
        MOV     r0, #ScreenModeReason_RegisterDriver
        MOV     r1, #0
        ADR     r2, VduGrafHAL_Name
        SWI     XOS_ScreenMode
        ; Assume success, since HAL should be first driver registered

        ; Set up VSync IRQ handler
        MOV     r0, #-1
        CallHAL HAL_VideoFlybackDevice
        CMP     r0, #-1
        BEQ     %FT10
        MOV     r5, r0
        ADR     r1, VduGrafHAL_VsyncIRQ
        LDR     r2, =ZeroPage
        SWI     XOS_ClaimDeviceVector
        MOV     r0, r5
        CallHAL HAL_IRQClear            ; clear vsync IRQ
        MOV     r0, r5
        CallHAL HAL_IRQEnable           ; enable vsync IRQ
10

        ;;; sort this out!
        ! 0, "HAL not doing anything useful with HAL_VideoBufferAlignment"
        ! 0, "HAL not dealing with lack of h/w pointer"

        ; Get on GraphicsV
        MOV     r0, #GraphicsV
        ADR     r1, MOSGraphicsVHAL
        LDR     r2, =ZeroPage
        SWI     XOS_Claim

        ; Now let the OS know that we're good to go
        MOV     r0, #ScreenModeReason_StartDriver
        MOV     r1, #0 ; Our driver number (hopefully)
        SWI     XOS_ScreenMode

        EXIT


VduGrafHAL_VsyncIRQ ROUT
        ; Don't push r14 - we're using new interface, and claim the vector
        ; TODO - deal with shared IRQs
        Push    "r4,r9,r12"
        AddressHAL r12
        CallHAL HAL_IRQClear            ; Clear the vsync interrupt
        MOV     r4, #GraphicsV_VSync
        BL      CallGraphicsV           ; Tell the VDU driver
        Pull    "r4,r9,r12,pc"

        ; Might want to add a HAL call for this at some point
VduGrafHAL_Name
        =       "HAL", 0
        ALIGN

        END