;*DDK*************************************************************************/
;
; COPYRIGHT (C) Microsoft Corporation, 1989
; COPYRIGHT    Copyright (C) 1995 IBM Corporation
;
;    The following IBM OS/2 WARP source code is provided to you solely for
;    the purpose of assisting you in your development of OS/2 WARP device
;    drivers. You may use this code in accordance with the IBM License
;    Agreement provided in the IBM Device Driver Source Kit for OS/2. This
;    Copyright statement may not be removed.;
;*****************************************************************************/
;       SCCSID = @(#)screen02.asm       6.1 90/11/17
;SCCSID = @(#)screen02.asm      1.7 90/02/05
;       SCCSID = @(#)screen02.asm       1.7 90/02/05
; ****************************************************************************
; *                                                                          *
; *                                                                          *
; *                                                                          *
; ****************************************************************************
        PAGE    58,132
        TITLE   Screen Device Driver - (Screen02.Asm)
        .286p                                                           ;@T30

;/***********************************************************************/
;/*                                                                     */
;/* SOURCE FILE NAME: Screen02.Asm      STATUS: Version 1.1             */
;/*                                                                     */
;/* DESCRIPTIVE NAME:  Base Video Subsystem Screen Device Driver        */
;/*                                                                     */
;/* FUNCTION:   Processes the Init, DeInstall, and Screen IOCtl         */
;/*             functions listed below.  All other device commands      */
;/*             return an error.                                        */
;/*                                                                     */
;/* NOTES:  Executes on Level 0                                         */
;/*                                                                     */
;/* ENTRY POINT:  Screen_Strategy                                       */
;/*   LINKAGE: Far Call                                                 */
;/*                                                                     */
;/* INPUT:  ES = Selector of Request Packet                             */
;/*         BX = Offset of Request Packet                               */
;/*                                                                     */
;/*   Category 3 Functions:                                             */
;/*                                                                     */
;/*     65h     Get 3xBox CodePage                              @C13    */
;/*     70h     Allocate a Selector                                     */
;/*     71h     Deallocate a Selector                                   */
;/*     74h     Passthru to Video ABIOS                                 */
;/*     75h     Allocate a Selector:Offset                      @T30    */
;/*     76h     Allocate a Selector:Offset with requested attr  @B01    */
;/*                                                                     */
;/* EXIT-NORMAL:  Request Block Status Field set to good return code    */
;/*                                                                     */
;/* EXIT-ERROR:  Request Block Status Field set to error:               */
;/*                                                                     */
;/*              Error Code             Cause                           */
;/*              ------------------------------------------             */
;/*              ERROR_I24_BAD_COMMAND  Invalid Request                 */
;/*                                                                     */
;/* EFFECTS:  None                                                      */
;/*                                                                     */
;/* INTERNAL REFERENCES:  None                                          */
;/*   ROUTINES:  Init, IOCtl, GetVideo, SetVideo                        */
;/*                                                                     */
;/* EXTERNAL REFERENCES:  None                                          */
;/*   ROUTINES:  Device_Help (DevHlp_PhysToUVirt, DevHlp_GetLIDEntry,   */
;/*                  DevHlp_ABIOSCall)                                  */
;/*                                                                     */
;/************************ END OF SPECIFICATIONS ************************/

;Bgnsub Screen_Strategy
;: If Function = INIT
;: : Call Init to initialize the device driver
;: Else
;: : Preset return code for INVALID_CATEGORY
;: : If Category = 3
;: : : Preset return code for BAD_COMMAND
;: : : If Function = DEINSTALL
;: : : : Free the LID
;: : : : Set good return code
;: : : Elseif Funtion = GENERIC IOCtl
;: : : : Call IOCtl to process Screen IOCtl requests
;: : : Endif
;: : Elseif Function = 4,8 or 9  (Read or Write or Write/Verify)
;: : : Set byte count = 0
;: : Endif
;: Endif
;Endsub

;Bgnsub IOCtl
;: Preset return code for BAD_COMMAND
;: If Function = Deallocate selector (71h)
;: : Call Device_Help (DevHlp_PhysToUVirt) to deallocate a selector
;: Elseif Function = Allocate selector (70h)
;: : Check for valid range for physical address
;: : If invalid physical address
;: : : Set return code for     address
;: : Else
;: : : Call Device_Help (DevHlp_PhysToUVirt) to allocate a selector
;: : Endif
;: Elseif Function = Passthru to Video ABIOS (74h)
;: : Call Device_Help (DevHlp_ABIOSCall)
;: Endif
;Endsub

;Bgnsub Init
;: Set up end of data and code addresses
;: Call Device_Help (DevHlp_GetLIDEntry) to get ABIOS information
;: Call Device_Help (DevHlp_ABIOSCall) to get control block sizes
;: Set good return code
;Endsub

        INCLUDE devhlp.inc              ; Define DevHlp functions
        INCLUDE devsym.inc              ; Define DOS equates
        INCLUDE error.inc               ; Define Error Messages
        INCLUDE ioctl.inc               ; Define IOCTL equates
.xlist
        INCLUDE basemaca.inc            ;;;;;; 2.0 unique (dosmac replacement)
        INCLUDE struc.inc               ; Define STRUC macros
.list

;STJFMT,,24

ABIOS_Request_Block     STRUC

ABIOS_RB_Len            dw      0       ;+00h
ABIOS_DevId             dw      0       ;+02h
ABIOS_Unit              dw      0       ;+04h
ABIOS_Func              dw      0       ;+06h
ABIOS_RBFlags           dw      0       ;+08h
ABIOS_ELOff             dw      0       ;+0Ah
ABIOS_RetCode           dw      0       ;+0Ch
ABIOS_TimeOut           dw      0       ;+0Eh
ABIOS_DataPtr1x         dw      0       ;+10h
ABIOS_DataPtr1l         dw      0       ;+12h
ABIOS_DataPtr1h         dw      0       ;+14h
                        dw      0
ABIOS_Count             dw      0       ;+18h
ABIOS_DevCntlFlag       dw      0       ;+1Ah
ABIOS_ScanLines         db      0       ;+1Ch
ABIOS_CharGenType       db      0       ;+1Dh
ABIOS_VideoMode         dw      0       ;+1Eh
ABIOS_MonitorType       dw      0       ;+20h
ABIOS_CharHeight        dw      0       ;+22h
ABIOS_Map2Block         dw      0       ;+24h
ABIOS_UpdateFontFlag    dw      0       ;+26h
ABIOS_CharOffset        dw      0       ;+28h
ABIOS_FontDataSize      dw      0       ;+2Ah
ABIOS_Environment       dw      0       ;+2Ch
ABIOS_SR_Header_Size    dw      0       ;+2Eh
ABIOS_SR_Hdw_Size       dw      0       ;+30h
ABIOS_PaletteReg        dw      0       ;+32h
ABIOS_PaletteValue      dw      0       ;+34h
                        dw      0       ;+36h
                        dw      0       ;+38h
                        dw      0       ;+3Ah
                        dw      0       ;+3Ch
                        dw      0       ;+3Eh = Padding for future use

ABIOS_Request_Block     ENDS

ABIOS_SR_DB_Size        equ     ABIOS_PaletteReg ;+32h
ABIOS_SR_DAC_Size       equ     ABIOS_PaletteValue ;+34h

;STJFMT,

;***************************************
;
;  PVB Address Function Return Structure
;
;***************************************

pvbdata STRUC
pvb_off DW      ?                       ; PVB address offset
pvb_sel DW      ?                       ; PVB address segment/selector
pvb_len DW      ?                       ; Length of the PVB
acc_bit DW      ?                       ; Access bits for function 76H  ;@B01
pvbdata ENDS

;                       start of SVGA support
;SVGA category, functions and parameter packet structures
;All SVGA functions in SVGAROUT.ASM

    EXTRN   SVGA_IOCTL          : NEAR  ;           moved to svgarout.asm
    EXTRN   Init                : NEAR  ;           moved to svgarout.asm

SVGA_CATEGORY  EQU  80h     ; SVGA SCREENDD category

BioData SEGMENT WORD PUBLIC 'DATA'      ;           changed class name

; Define I/O packet offsets for useful values.
;
; SEE ALSO
;       CP/DOS Technical Reference manual section on Installable Device Drivers

dev_attribute EQU DEV_CHAR_DEV+DEVLEV_1+DEV_COUT ;SCRDD Attribute Word Value

;**     Device Table Record
;                  *
;       Devices are described by a chain of these records
;
;  Copied from devhdr.inc in dos subdirectory.
;    Note:  Required since Device Name field was not defined as a String!

        Assume  CS:BiosSeg,DS:BioData,ES:NOTHING,SS:NOTHING
        public  Screen$                 ;@SZL
Screen$ DD      -1                      ; Pointer to next device header ;@SZL
        DW      dev_attribute           ; Attributes of the device
        DW      offset BiosSeg:Screen_Strategy ; Strategy entry point
        DW      offset BiosSeg:JustReturn ; Interrupt entry point
        DB      'SCREEN$ '              ; Dev Name (only 1st byte used for blk)
        DW      0                       ; Prot-mode CS sel of strat entry pt
        DW      0                       ; Prot-mode DS sel
        DW      0                       ; Real-mode CS seg of strat entry pt
        DW      0                       ; Real-mode DS seg

Public  DevHelp
DevHelp DD      0                       ; DevHelp Function Router Address

Public  LID                             ;          
LID     dw      0                       ;Logical Id
ABIOS_RB ABIOS_Request_Block <>         ;ABIOS Request Block

DATA_END LABEL  BYTE

BioData ends

BiosSeg SEGMENT Byte Public 'CODE'
        ASSUME  CS:BiosSeg

        extrn   MemoryIoctl : near                                      ;J-TS920924

Screen_Strategy PROC FAR
        push    es
        push    bx
        push    bp
        sub     bp,bp
        mov     dh,es:[bx].ReqFunc      ; Command code
        .IF     <dh eq CMDInitBase>     ;if a base init request
            CALL    Init                ;process the init
        .ELSE
            mov     ax,STERR+ERROR_I24_BAD_COMMAND ;Preset error
            .IF     <dh eq CMDDeInstall> ;if a deinstall request
                mov     ax,LID
                mov     dl,DevHlp_FreeLIDEntry
                Call    DevHelp         ;Free the LID Entry
                sti
                sub     ax,ax           ;NOERROR
            .ELSE
                .IF     <dh eq CMDGenIOCtl> ;if a generic IOCtl request
                    call    MemoryIoctl                                 ;J-TS920924
                    .if     <ax ne 0>                                   ;J-TS920924
                        .if     <es:[bx].GIOCategory eq IOC_SC>
                            CALL    IOCtl   ;process the IOCtl
                        .else                       ;           start
                          .if     <es:[bx].GIOCategory eq SVGA_CATEGORY>
                            CALL    SVGA_IOCtl      ;process the IOCtl
                          .endif                    ;           end
                        .endif
                    .endif                                              ;J-TS920924
                .else
                    .IF     <dh eq CMDINPUT> OR
                    .IF     <dh eq CMDOUTPUT> OR
                    .IF     <dh eq CMDOUTPUTV>
                        sub     ax,ax   ;NOERROR
                        mov     es:[bx].IOcount,ax ;Byte Count
                    .ENDIF
                .ENDIF
            .ENDIF
        .ENDIF
        pop     bp
        pop     bx
        pop     es
        or      ax,STDON                ; Set the done bit
        mov     es:[bx].ReqStat,ax      ; Set return status

JustReturn LABEL FAR
        ret                             ; restore regs and return
Screen_Strategy ENDP

IOCtl   PROC    NEAR
        public  IOCtl

        enter   2,0                     ;Reserve a word for size        ;@T30
        DataSize equ <word ptr [bp-2]>  ;                               ;@T30
        mov     dh,es:[bx].GIOFunction  ;Get IOCtl function
        .if     <dh eq 71H>             ;Deallocate selector
            mov     di,word ptr es:[bx].GIOParaPack
            mov     ax,word ptr es:[bx].GIOParaPack+2 ;Parm ptr
            mov     cx,2                ;2-byte buffer
            mov     dh,0                ;Read Access
            Call    Verify              ;Verify access
            .if     nc
                mov     es,word ptr es:[bx].GIOParaPack+2 ;Parm ptr
                mov     ax,es:[di]      ; selector to free
                mov     dh,2            ; UnMap      BUGBUG
                mov     dl,DevHlp_PhysToUVirt
                call    DevHelp
                xor     ax,ax
            .endif
        .else   near
            mov     DataSize,2          ;Return selector only           ;@T30
            sub     si,si               ;Default is read access         ;@B01
            .if     <dh ne 70H> near    ;Allocate selector:offset       ;@B01
                mov     DataSize,4      ;Return selector:offset         ;@T30
            .endif                                                      ;@T30
            mov     dl,dh               ;Save IOCTL function            ;@B01
            .if     <dh eq 70H> or near ;Allocate selector              ;@B01
            .if     <dh ae 75H> near                                    ;@B01

                push    es
                push    bx

                mov     di,word ptr es:[bx].GIOParaPack
                mov     ax,word ptr es:[bx].GIOParaPack+2 ;Parm ptr
                mov     cx,6            ;6-byte buffer
                push    dx                                              ;@B01
                mov     dh,0            ;Read Access
                Call    Verify
                pop     dx                                              ;@B01
                .if     nc near                                         ;@B01

                    mov     es,word ptr es:[bx].GIOParaPack+2 ;Parm ptr
                    mov     bx,es:[di].pvb_off ; 32-bit physical address
                    mov     ax,es:[di].pvb_sel ; 32-bit physical address

                    sub     si,si                                       ;@B01
                    mov     cx,es:[di].pvb_len ;Length of PVB
                    .if     <dl eq 76H> near                            ;@B01
                        mov     si,es:[di].acc_bit                      ;@B01
                        .if     <si a 5> or     ;Invalid access bits    ;@B01
                        .if     <si eq 2>       ;Invalid access bits    ;@B01
                            mov     ax,STERR+ERROR_I24_INVALID_PARAMETER;@B01
                            jmp     bad_bits    ;                       ;@B01
                        .endif
                        or      si,8000h                                ;@B01
                    .endif                                              ;@B01
                    dec     cx
                    sub     dx,dx
                    add     cx,bx
                    adc     dx,ax       ;DX:CX = Addr32 of final byte
                    mov     bx,si       ;Access bits                    ;@B01

                    .if     <ax a 000Fh> or ;Above FFFFFh (Prot Mode) or
                    .if     <dx a 000Fh>    ;Above FFFFFh (Prot Mode)
                        mov     ax,STERR+ERROR_I24_INVALID_PARAMETER
                    .else
                        mov     cx,es:[di].pvb_len ;Length of PVB
                        mov     dh,bl       ;Access bits                ;@B01
                        .if     <al ae 000Ah> and
                        .if     <dl b 000Ch>
                            .if     <bh ne 80H> near                    ;@B01
                                mov     dh,5 ;Read/Write Segment ;DCR0216
                            .endif                                      ;@B01
                            sub     si,si ;DCR0216
                        .elseif <bl ne 0> and ;Invalid access bits      ;@B01
                        .if     <bl ne 3>     ;Invalid access bits      ;@B01
                            mov     ax,STERR+ERROR_I24_INVALID_PARAMETER;@B01
                            jmp     bad_bits                            ;@B01
                        .endif          ;Else dh=0=Read Only
                        mov     bx,es:[di].pvb_off ; 32-bit phys addr   ;@B01
                        mov     dl,DevHlp_PhysToUVirt
                        call    DevHelp

                        mov     si,es   ;SI=Selector                    ;@T30
                        mov     dx,bx   ;save offset in DX              ;@T30
                        pop     bx
                        pop     es      ;Restore Request Block Addressibility
                        push    es
                        push    bx      ;Save it again

                        mov     ax,STERR+ERROR_I24_BAD_COMMAND ; Set error
                        .if     nc
                            mov     di,word ptr es:[bx].GIODataPack
                            mov     ax,word ptr es:[bx].GIODataPack+2 ;Data ptr
                            mov     cx,DataSize ;2 or 4-byte buffer ;@@2;@T30
                            push    dx                                  ;@T30
                            mov     dh,1 ;Read/Write Access
                            Call    Verify
                            pop     dx                                  ;@T30
                            .if     nc
                                mov     ds,word ptr es:[bx].GIODataPack+2 ;Data ptr t
                                .if <DataSize eq 2>                     ;@T30
                                    mov     [di],si   ;Return sel. only ;@T30
                                .else                                   ;@T30
                                    mov     [di],dx   ;Return sel:off   ;@T30
                                    mov     [di+2],si                   ;@T30
                                .endif                                  ;@T30
                                sub     ax,ax
                            .endif
                        .endif
                    .endif
                .endif
bad_bits:       pop     bx                                              ;@B01
                pop     es              ;Restore Request Block Addr

            .else
                .if     <dh eq 74H>     ;Passthru to ABIOS ;DCR0226
                    mov     DataSize,2          ;Return selector only   ;@B02   ;@T30
                    mov     di,word ptr es:[bx].GIOParaPack
                    mov     ax,word ptr es:[bx].GIOParaPack+2 ;Parm ptr
                    mov     cx,2        ;2-byte buffer
                    mov     dh,0        ;Read Access
                    Call    Verify      ;Verify access
                    .if     nc
                        push    ds
                        mov     ax,word ptr es:[bx].GIOParaPack+2 ;Parm ptr
                        mov     ds,ax
                        mov     cx,[di].ABIOS_RB_Len
                        pop     ds

                        mov     di,word ptr es:[bx].GIOParaPack
                        mov     ax,word ptr es:[bx].GIOParaPack+2 ;Data ptr
                        mov     dh,1    ;Read/Write Access
                        Call    Verify
                        .if     nc and
                        mov     ax,STERR+ERROR_I24_INVALID_PARAMETER
                        .if     <cx be <size ABIOS_Request_Block>> and
                        .if     <ncxz>  ;Valid length
                            push    ds
                            push    es

                            push    ds
                            lds     si,es:[bx].GIOParaPack ;ABIOS request block
                            pop     es
                            mov     di,offset ABIOS_RB
                            push    di
                            push    cx
                            rep     movsb ;Copy user's RB to local RB
                            pop     cx
                            pop     si  ;Offset of ABIOS Request Block

                            pop     es
                            pop     ds

                            mov     ax,LID ;Get Video device id for DevHelp
                            mov     [si].ABIOS_DevId,ax ;Set Video device id
                            mov     [si].ABIOS_Unit,0 ;Set Video unit number
                            mov     dx,DevHlp_ABIOSCall+256*0 ;Start command
                            Call    DevHelp ;Invoke ABIOS

                            mov     ax,STERR+ERROR_I24_BAD_COMMAND ;Preset error
                            .if     nc
                                les     di,es:[bx].GIOParaPack ;ABIOS Req Blk
                                mov     si,offset ABIOS_RB
                                rep     movsb ;Copy local RB to user's RB
                                sub     ax,ax ;Good return code
                            .endif
                            sti         ;Guarantee interrupts enabled
                        .endif
                    .endif
;@T51           .else                                                   ;@C13
;@T51               .if     <dh eq 65H>         ;Get 3xBox CodePage      @C13
;@T51                   Call    Get3xBoxCP                              ;@C13
;@T51               .endif                                              ;@C13
                .endif
            .endif
        .endif
        leave                                                           ;@T30
        ret
IOCtl   ENDP

Verify  PROC    NEAR
        public  Verify

        mov     dl,DevHlp_VerifyAccess
        Call    DS:DevHelp              ;Verify access
        mov     ax,STERR+error_invalid_access
        ret
Verify  ENDP

;@T51 Get3xBoxCP PROC NEAR                                              ;@C13
;@T51   PUBLIC  Get3xBoxCP                                              ;@C13
;@T51   les     di,dword ptr es:[bx].GIODataPack ;Data ptr               @C13
;@T51   mov     ax,es                   ;Data ptr                        @C13
;@T51   mov     cx,2                    ;2-byte buffer = Length          @C13
;@T51   mov     dh,0                    ;Read Access                     @C13
;@T51   Call    Verify                  ;Verify access                   @C13
;@T51   .if     nc                                                      ;@C13
;@T51       mov     cx,es:[di]          ;Get size of output buffer       @C13
;@T51       mov     ax,es               ;Data ptr                        @C13
;@T51       mov     dh,1                ;Read/Write Access               @C13
;@T51       Call    Verify                                              ;@C13
;@T51       .if     nc                                                  ;@C13

;@T51           .if     <cx ae 4>       ;Enough room for CodePage        @C13
;@T51               push    bx                                          ;@C13
;@T51               mov     al,11       ;Dos CodePage Segment            @C13
;@T51               mov     dl,DevHlp_GetDosVar                         ;@C13
;@T51               call    DevHelp     ;Get Dos Variable table          @C13
;@T51               mov     ds,ax                                       ;@C13
;@T51               mov     cx,[bx]     ;Get current 3xBox CodePage      @C13
;@T51               pop     bx                                          ;@C13

;@T51               mov     es:[di+2],cx ;Return the CodePage            @C13
;@T51               sub     ax,ax                                       ;@C13
;@T51           .endif                                                  ;@C13
;@T51       .endif                                                      ;@C13
;@T51   .endif                                                          ;@C13
;@T51   RET                                                             ;@C13
;@T51 Get3xBoxCP ENDP                                                   ;@C13

; The following label defines the end of the Screen resident code.

;DEVICE_END LABEL BYTE


;**     INIT - Device Driver Initialization routine
;
;       ENTRY
;               ES:BX = Request Packet
;               DS    = ?
;       EXIT
;               Terminating Code Address Set
;               Terminating Data Address Set
;               Status = OK
;               DevHelp Address Saved
;

;Init   PROC    NEAR
;
;; Save DevHelp Function Router Address
;
;       mov     ax,word ptr ES:[bx.InitpEnd]
;       mov     word ptr DevHelp,ax
;       mov     ax,word ptr ES:[bx.InitpEnd+2]
;       mov     word ptr DevHelp+2,ax
;
;       mov     word ptr es:[bx.InitpEnd],offset DEVICE_END-1
;       mov     word ptr es:[bx.InitpEnd+2],offset DATA_END-1
;
;       mov     al,3                    ;Video Device Id ???
;       mov     bl,0                    ;First available LID
;       mov     dh,0                    ;Device State = 0 (Reserved)
;       mov     dl,DevHlp_GetLIDEntry
;       Call    DevHelp
;       sti
;       .if     nc
;           mov     LID,ax              ;Save the LID number
;       .endif
;       sub     ax,ax                   ;DCR0226
;       ret
;Init   ENDP

BiosSeg ends
        end

;DCR0216 = 02/10/89 STJ, Use new PhysToUVirt request type for video validation
;DCR0226 = 02/17/89 STJ, Remove unused IOCTLs and expand valid selector range
;@C13 = 03/29/89 CJJ, Add back IOCTL to get the 3xBox CodePage, B700817
;@SZL = 04/24/89 STJ, Allow combining of all base DDs
;@T30 = 05/10/89 TPL, DCR 511 changes
;@T51 = 08/26/89 TPL, Removal of 3xbox code in 2.0, DCR 432.10
;@B01 = 01/24/90 WKB, Add IOCTL function 76H in 2.0, DCR 702
;           = 12/28/92 Senja, SVGA support.
