;      /*****************************************************************/
;      /*                                                               */
;      /*           Copyright (c) IBM Corporation  1987, 1992           */
;      /*                     All Rights Reserved                       */
;      /*                                                               */
;      /*****************************************************************/
;      /******************* START OF SPECIFICATIONS *********************/
;      /*                                                               */
;      /*  SOURCE FILE NAME: GIO.ASM                                    */
;      /*                                                               */
;      /*  DESCRIPTIVE NAME: Generic IOCTL handler                      */
;      /*                                                               */
;      /*  COPYRIGHT:  IBM Corp. 1992                                   */
;      /*                                                               */
;      /*  STATUS:  Version 1.0                                         */
;      /*                                                               */
;      /*  NOTES: This module provides routines to service the          */
;      /*         architected pen IOCTLs. Device dependent IOCTLs       */
;      /*         are serviced in the device dependent routine.         */
;      /*                                                               */
;      /*         A routine can be subclassed, or replaced, by replacing*/
;      /*         the routine address in the IOCTL branch table.        */
;      /*                                                               */
;      /*  ENTRY POINTS:                                                */
;      /*      See public statements                                    */
;      /*  EXTERNAL REFERENCES:                                         */
;      /*      See extrn statements                                     */
;      /*                                                               */
;      /******************* END  OF  SPECIFICATIONS *********************/
public Gio_UnPanic,Gio_Panic  ; must occur before emi.inc
public Gio_CallAll
public Gio_CallUnit
public Gio_CallType
.xlist
  include pensegs.inc
  include pen.inc
  include penei.inc
  include penioctl.inc
  include devsym.inc
  include struc.inc
.list

.286p

;------------------------------------------------------------------------------
; external routines
;------------------------------------------------------------------------------

extrn Gio_rtb  : near
extrn Gio_qtts : near
extrn Gio_qtt  : near
extrn Gio_stts : near
extrn But_CalcCaps : near
extrn Idc_UpdateCaps : near
extrn Loc_qlrc       : near
extrn Dsp_SetInactPeriod : near
extrn Dsp_SDS    : near
extrn Dev_IOCTL_rtn  : near

;------------------------------------------------------------------------------
; external data
;------------------------------------------------------------------------------

extrn RegCaps0 : byte
extrn DDPanic  : dword

;------------------------------------------------------------------------------
; local data
;------------------------------------------------------------------------------

ERROR_BAD_COMMAND equ 08003h
ERROR_BAD_UNIT    equ 08001h
ERROR_BAD_PARM    equ 08013h

DSEG segment

public DCB_Anchor
DCB_Anchor    dw 0 ; anchor for dcb list
dataPack      dd 0
paraPack      dd 0

FIND_UNIT  equ 01h        ; load DCB before calling
CHECK_TYPE equ 02h        ; check the type before calling
PASS_PARM  equ 04h        ; pass parm packet in fs:di
PASS_DATA  equ 08h        ; pass parm packet in gs:si

; Category table
public ioctl_table,tbl_W_Driver,tbl_R_Driver,tbl_W_Locator,tbl_R_Locator

              dw    (ioctl_tableE-ioctl_table)/4 ;category count
ioctl_table   dw    tbl_W_Driver  ; category 90h writes
              dw    tbl_R_Driver  ; category 90h reads
              dw    tbl_W_Locator ; category 91h writes
              dw    tbl_R_Locator ; category 91h reads
              dw    tbl_W_Button  ; category 92h writes
              dw    tbl_R_Button  ; category 92h reads
              dw    tbl_W_Display ; category 93h writes
              dw    tbl_R_Display ; category 93h reads
ioctl_tableE  label byte

; Driver IOCTLs - Category 90h

              dw     (tbl_W_DriverE-tbl_W_Driver)/2 ;function count
tbl_W_Driver  dw     Gio_susd     ; 50h Set Unit Specific Data
              db     0            ; no type
              db     FIND_UNIT+PASS_PARM+PASS_DATA

              dw     Gio_suv      ; 51h Set Unit Variable
              db     0            ; no type
              db     FIND_UNIT+PASS_PARM

              dw     Gio_rtb      ; 52h Reset Trace Buffer
              db     0            ; no type
              db     0            ;

              dw     Gio_stts     ; 53h Set Trace Table Size
              db     0            ; no type
              db     PASS_PARM    ;
tbl_W_DriverE label  byte

              dw     (tbl_R_DriverE-tbl_R_Driver)/2 ;function count
tbl_R_Driver  dw     Gio_qusd     ; 60H Query Unit Specific Data
              db     0            ; no type
              db     FIND_UNIT+PASS_PARM+PASS_DATA

              dw     Gio_quv      ; 61H Query Unit Variable
              db     0            ; no type
              db     FIND_UNIT+PASS_PARM

              dw     Gio_quc      ; 62H Query Unit Capabilities
              db     0            ; no type
              db     FIND_UNIT+PASS_PARM+PASS_DATA

              dw     Gio_qtt      ; 63H Query Trace Table
              db     0            ; no type
              db     PASS_PARM+PASS_DATA

              dw     Gio_qtts     ; 64H Query Trace Table Size
              db     0            ; no type
              db     PASS_DATA
tbl_R_DriverE label  byte

; LocatorIOCTLs - Category 91h

              dw     (tbl_W_LocatorE-tbl_W_locator)/2 ;function count
tbl_W_Locator dw     Gio_slo      ; 50h Set Locator Offset
              db     DT_LOCATOR
              db     FIND_UNIT+CHECK_TYPE+PASS_PARM

              dw     Gio_slpr     ; 51h Set Locator Pass Rate
              db     DT_LOCATOR
              db     FIND_UNIT+CHECK_TYPE+PASS_PARM

              dw     Gio_slsr     ; 52h Set Locator Sample Rate
              db     DT_LOCATOR
              db     FIND_UNIT+CHECK_TYPE+PASS_PARM

tbl_W_LocatorE label  byte

              dw     (tbl_R_LocatorE-tbl_R_Locator)/2 ;function count
tbl_R_Locator dw     Gio_qlv      ; 60H Query Locator Variables
              db     DT_LOCATOR
              db     FIND_UNIT+CHECK_TYPE+PASS_DATA

              dw     Gio_qlrc     ; 61H Query Locator Raw Coordinate
              db     DT_LOCATOR
              db     FIND_UNIT+CHECK_TYPE+PASS_PARM+PASS_DATA

              dw     Gio_qdle      ; 62H Query Default Locator Extents
              db     DT_LOCATOR    ; no type
              db     FIND_UNIT+CHECK_TYPE+PASS_PARM+PASS_DATA
tbl_R_LocatorE label  byte

; Button IOCTLs - Category 92h

              dw     (tbl_W_ButtonE-tbl_W_Button)/2 ;function count
tbl_W_Button  dw     Gio_sba      ; 50h Set Button Assignment
              db     DT_BUTTON
              db     FIND_UNIT+CHECK_TYPE+PASS_PARM

tbl_W_ButtonE label  byte

              dw     (tbl_R_ButtonE-tbl_R_Button)/2 ;function count
tbl_R_Button  dw     Gio_qba      ; 60H Query Button Assignment
              db     DT_BUTTON
              db     FIND_UNIT+CHECK_TYPE+PASS_PARM+PASS_DATA
tbl_R_ButtonE label  byte

; Display IOCTLs - Category 93h

              dw     (tbl_W_DisplayE-tbl_W_Display)/2 ;function count
tbl_W_Display dw     Gio_sds      ; 50h Set Display State
              db     DT_DISPLAY
              db     FIND_UNIT+CHECK_TYPE+PASS_PARM

              dw     Gio_sdip     ; 51h Set Display Inactivity Period
              db     DT_DISPLAY
              db     FIND_UNIT+CHECK_TYPE+PASS_PARM
tbl_W_DisplayE label  byte

              dw     (tbl_R_DisplayE-tbl_R_Display)/2 ;function count
tbl_R_Display dw     Gio_qds      ; 60H Query Display State
              db     DT_DISPLAY
              db     FIND_UNIT+CHECK_TYPE+PASS_DATA
tbl_R_DisplayE label  byte

DSEG ends

CSEG SEGMENT
     ASSUME    CS:CSEG, SS:nothing, ES:nothing, DS:DGROUP

;---- OS/2 GENERIC IO ENTRY POINT ---------------------------------------------
; Handle OS/2 generic IOCTL commands
;  es:bx = request packet
;------------------------------------------------------------------------------
public GIO_Entry
GIO_Entry    PROC  NEAR
  push  es
  push  bx

  mov   ah, PEN_CAT_DRIVER         ; calculate the last category defined
  add   ah, byte ptr ioctl_table-2 ; (actually one more than)

  mov   al, byte ptr es:[bx].GIOCategory
  .if <al b  PEN_CAT_DRIVER> OR      ; its not a defined IOCTL category
  .if <al ae ah>
     call Dev_IOCTL_rtn
  .else near
     xor   ah, ah
     and   al, 0fh
     mov   si, ax
     sal   si, 2

     mov   ah, byte ptr es:[bx].GIOFunction
     and   ah, 70h
     .if   <ah ne 50h> AND
     .if   <ah ne 60h>
        mov  ax,ERROR_BAD_COMMAND
     .else  near
        .if <ah eq 60h> ; use read table
           add si, 2
        .endif
        mov  si,[si].ioctl_table    ; get function table
        add  ah, byte ptr [si-2] ; calculate one past highest function
        mov  al, byte ptr es:[bx].GIOFunction
        .if <al ae ah>
           mov   ax, ERROR_BAD_COMMAND
        .else
           and   al, 0Fh
           sal   al, 2
           xor   ah,ah
           add   si,ax
           .386p
           mov   ecx, es:[bx].GIOParaPack  ; get parms
           mov   paraPack,ecx
           mov   ecx, es:[bx].GIODataPack  ; get data
           mov   dataPack,ecx
           mov   dx,[si]          ; get routine to call
           .if   <bit <byte ptr [si+3]> nz FIND_UNIT>
              lfs  di, es:[bx].GIOParaPack  ; get parms
              mov  al, byte ptr fs:[di]     ; get unit number
              mov  bx, DCB_Anchor
              .repeat
                 .if <al eq [bx].dcb_Unit>
                    jmp  short gio_n1
                    clc
                    ret
                 .endif
                 mov  bx, [bx].dcb_Link
              .until <zero bx>
              mov   ax, ERROR_BAD_UNIT
              jmp   gio_exit
gio_n1:
              .if   <bit <byte ptr [si+3]> nz CHECK_TYPE>
                 mov  al,[bx].dcb_DevType
                 .if <al ne [si+2]>
                    mov   ax, ERROR_BAD_UNIT
                    jmp   short gio_exit
                 .endif
              .endif
           .endif
           .if   <bit <byte ptr [si+3]> nz PASS_PARM>
              lfs di,paraPack
           .endif
           .if   <bit <byte ptr [si+3]> nz PASS_DATA>
              lgs si,dataPack
           .endif
           call  dx
           .286p
        .endif
     .endif
  .endif
gio_exit:
  pop   bx
  pop   es
  mov   es:[bx].PktStatus, ax
  ret                              ; Return to Request Handler Rtn.
GIO_Entry ENDP

;---- DRIVER ROUTINES----------------------------------------------------------
;
;------------------------------------------------------------------------------

;---- OS/2 GENERIC IO ENTRY POINT ---------------------------------------------
; Handle OS/2 generic IOCTL commands
;   fs:di parm packet if requested
;   gs:si data packet if requested
;------------------------------------------------------------------------------

.386p

;------------------------------------------------------------------------------
; 50h Set Unit Specific Data
;   fs:di parm packet
;   gs:si data packet
;------------------------------------------------------------------------------
public Gio_susd
Gio_susd proc
  .if <[bx].dcb_DevType eq DT_LOCATOR> AND
  .if <bit [bx].dcb_Xtrans.trn_flags nz STANDARD_USD> AND
  .if <bit [bx].dcb_Ytrans.trn_flags nz STANDARD_USD>
     mov   cx, word ptr fs:[di].pqusd_byteCount
     .if   <cx ge <size SLUSD>>

        .if <<word ptr gs:[si].slusd_XmeasuredExtent> eq 0> OR
        .if <<word ptr gs:[si].slusd_YmeasuredExtent> eq 0>
           mov  ax,ERROR_BAD_PARM
           ret
        .endif

        mov  eax, dword ptr gs:[si].slusd_Xorigin
        mov  [bx].dcb_Xtrans.trn_org_adj,  eax                  ; doragh
        mov  [bx].dcb_Xtrans.trn_org_calibrated, eax            ; doragh
                                                                ; doragh
        mov  eax, dword ptr gs:[si].slusd_XmeasuredExtent       ; doragh
        mov  [bx].dcb_Xtrans.trn_ext_adj, eax                   ; doragh
        mov  [bx].dcb_Xtrans.trn_ext_adj_calibrated, eax        ; doragh
                                                                ; doragh
        mov  eax, dword ptr gs:[si].slusd_Yorigin               ; doragh
        mov  [bx].dcb_Ytrans.trn_org_adj, eax                   ; doragh
        mov  [bx].dcb_Ytrans.trn_org_calibrated, eax            ; doragh
                                                                ; doragh
        mov  eax, dword ptr gs:[si].slusd_YmeasuredExtent       ; doragh
        mov  [bx].dcb_Ytrans.trn_ext_adj, eax                   ; doragh
        mov  [bx].dcb_Ytrans.trn_ext_adj_calibrated, eax        ; doragh
     .endif
  .endif
  push  gs
  pop   es
  mov   di,si
  CALL_NZ_OK [bx].dcb_@Dev_susd ; Set Unit Specific Data IOCTL rtn
                             ; cx = target byte size
                             ; es:di = target area
  ret
Gio_susd endp

;------------------------------------------------------------------------------
; 51h Set Unit Variable
;   fs:di parm packet
;------------------------------------------------------------------------------
public Gio_suv
Gio_suv proc
  mov  al, byte ptr fs:[di].psuv_index
  mov  si, [bx].dcb_@UVars
  .if <nonzero si>,AND
  .if <al lt <byte ptr [si].uv_numVars>
     push ax
     inc  ax ; skip arrary size
     sal  ax,2
     add  si,ax
     pop  ax
     mov  edx, fs:[di].psuv_value
     CALL_NZ_OK [bx].dcb_@Dev_suv  ; routine can change value before saving
     mov  [si], edx
  .else
     mov  ax, ERROR_BAD_PARM
  .endif
  ret
Gio_suv endp

;------------------------------------------------------------------------------
; 60H Query Unit Specific Data
;   fs:di parm packet
;   gs:si data packet
;------------------------------------------------------------------------------
public Gio_qusd
Gio_qusd proc
  .if <[bx].dcb_DevType eq DT_LOCATOR> AND NEAR
  .if <bit [bx].dcb_Xtrans.trn_flags nz STANDARD_USD> AND NEAR
  .if <bit [bx].dcb_Ytrans.trn_flags nz STANDARD_USD> NEAR
     mov   cx, word ptr fs:[di].pqusd_byteCount
     .if   <cx ge <size SLUSD>>
        mov  gs:[si].slusd_length,size SLUSD

        mov  eax, [bx].dcb_Xtrans.trn_org_default
        mov  gs:[si].slusd_XoriginDefault,eax

        mov  eax, [bx].dcb_Xtrans.trn_org_calibrated     ; doragh
        mov  gs:[si].slusd_Xorigin,eax

        mov  eax, [bx].dcb_Xtrans.trn_ext_adj_calibrated ; doragh
        mov  gs:[si].slusd_XmeasuredExtent,eax

        mov  eax, [bx].dcb_Ytrans.trn_org_default
        mov  gs:[si].slusd_YoriginDefault,eax

        mov  eax, [bx].dcb_Ytrans.trn_org_calibrated     ; doragh
        mov  gs:[si].slusd_Yorigin,eax

        mov  eax, [bx].dcb_Ytrans.trn_ext_adj_calibrated ; doragh
        mov  gs:[si].slusd_YmeasuredExtent,eax

        mov  gs:[di].slusd_length,size SLUSD
        mov  fs:[di].pqusd_RetByteCount,size SLUSD
        mov  fs:[di].pqusd_rc,QUSD_OK
     .elseif   <cx ge 4>
        mov  gs:[di].slusd_length,size SLUSD
        mov  fs:[di].pqusd_RetByteCount,4
        mov  fs:[di].pqusd_rc,QUSD_TRUNC
     .else
        mov  fs:[di].pqusd_RetByteCount,0
        mov  fs:[di].pqusd_rc,QUSD_TRUNC
     .endif
     mov  eax,QUSD_LENGTH+QUSD_STANDARD
     .if  <bit [bx].dcb_Xtrans.trn_flags nz INVERTED_COORD>
        or eax,QUSD_X_INVERT
     .endif
     .if  <bit [bx].dcb_Ytrans.trn_flags nz INVERTED_COORD>
        or eax,QUSD_Y_INVERT
     .endif
     mov  fs:[di].pqusd_Capabilities,eax
  .endif

; The device dependent QUSD routine can overwrite the RetByteCount,Capabilities,
; and rc field in the parm packet

  CALL_NZ_OK [bx].dcb_@Dev_qusd ; Query Unit Specific Data IOCTL rtn
                             ; cx = target byte size
                             ; gs:si = data packet
                             ; fs:di = parm packet
  ret
Gio_qusd endp

;------------------------------------------------------------------------------
; 61H Query Unit Variable
;   fs:di parm packet
;   gs:si data packet
;------------------------------------------------------------------------------
public Gio_quv
Gio_quv proc
  mov  al, byte ptr fs:[di].pquv_index
  mov  si, [bx].dcb_@UVars
  .if <nonzero si>,AND
  .if <al lt <byte ptr [si].uv_numVars>
     push ax
     inc  ax ; skip array size
     sal  ax,2
     add  si,ax
     mov  edx, [si]
     pop  ax
     push si
     CALL_NZ_OK [bx].dcb_@Dev_quv   ; let him change it
     pop  si
     mov  [si],edx
     lfs  di, dataPack
     mov  fs:[di].dquv_value, edx
  .else
     mov  ax, ERROR_BAD_PARM
  .endif
  ret
Gio_quv endp

;------------------------------------------------------------------------------
; 62H Query Unit Capabilites
;   fs:di parm packet
;   gs:si data packet
;------------------------------------------------------------------------------
public Gio_quc
Gio_quc proc

  push si            ; save destination address

  mov  fs:[di].pquc_rc,QUSD_OK
  mov  si, [bx].dcb_@RegCaps ; get capibility packet
  xor  ecx, ecx
  mov  cx, [si]
  .if  <fs:[di].pquc_byteCount lt ecx>
     mov  fs:[di].pquc_rc,QUSD_TRUNC
     mov  ecx,fs:[di].pquc_byteCount
  .endif
  mov  fs:[di].pquc_RetByteCount,ecx

  push gs            ; set up for movsb
  pop  es
  pop  di            ; restore destination into destination movsb reg

  rep  movsb         ; move it
  xor  ax,ax
  ret
Gio_quc endp


;---- LOCATOR IOCTLs ----------------------------------------------------------
;
;------------------------------------------------------------------------------

;------------------------------------------------------------------------------
; 50h Set Locator Offset
;   fs:di parm packet
;------------------------------------------------------------------------------
public Gio_slo
Gio_slo proc
  .if <bit fs:[di].pslo_command nz PSLO_SET_X>
     mov ax,word ptr fs:[di].pslo_xOffset
     mov [bx].dcb_Xtrans.trn_offset,ax
  .endif
  .if <bit fs:[di].pslo_command nz PSLO_SET_Y>
     mov ax,word ptr fs:[di].pslo_yOffset
     mov [bx].dcb_Ytrans.trn_offset,ax
  .endif
  xor ax,ax
  ret
Gio_slo endp

;------------------------------------------------------------------------------
; 51h Set Locator Pass Rate
;   fs:di parm packet
;------------------------------------------------------------------------------
public Gio_slpr
Gio_slpr proc
  mov si, [bx].dcb_@RegCaps
  mov al,byte ptr fs:[di].pslpr_passRate
  mov [si].lcap_pass_rate,al
  call IDC_UpdateCaps                ; update caps
  xor ax,ax
  ret
Gio_slpr endp

;------------------------------------------------------------------------------
; 52h Set Locator Sample Rate
;   fs:di parm packet
;------------------------------------------------------------------------------
public Gio_slsr
Gio_slsr proc
  mov si, [bx].dcb_@RegCaps
  mov ax,word ptr fs:[di].pslsr_sampleRate
  .if <zero ax>
     mov ax,[si].lcap_max_sample_rate
  .endif
  mov [si].lcap_sample_rate,ax
  CALL_NZ_OK [bx].dcb_@slsr             ; change rate device
  .if <zero ax>
     call IDC_UpdateCaps                ; update caps
  .endif
  ret
Gio_slsr endp

;------------------------------------------------------------------------------
; 60H Query Locator Variables
;   fs:di parm packet
;   gs:si data packet
;------------------------------------------------------------------------------
public Gio_qlv
Gio_qlv proc
  mov ax, [bx].dcb_Xtrans.trn_offset
  cwde
  mov gs:[si].dqlv_xOffset,eax

  mov ax, [bx].dcb_Ytrans.trn_offset
  cwde
  mov gs:[si].dqlv_yOffset,eax

  mov di, [bx].dcb_@RegCaps
  mov ax, [di].lcap_sample_rate
  cwde
  mov gs:[si].dqlv_sampleRate,eax

  mov al, [di].lcap_pass_rate
  cbw
  cwde
  mov gs:[si].dqlv_passRate,eax
  xor ax,ax
  ret
Gio_qlv endp

;------------------------------------------------------------------------------
; 61H Query Locator Raw Coordinate
;   fs:di parm packet
;   gs:si data packet
;------------------------------------------------------------------------------
public Gio_qlrc
Gio_qlrc proc
  mov  edx,fs:[di].pqlrc_timeout
  push gs
  push si
  call Loc_qlrc
  pop  si
  pop  gs
  mov  gs:[si].dqlrc_xRaw,ecx
  mov  gs:[si].dqlrc_yRaw,edx
  mov  gs:[si].dqlrc_rc,eax

  xor ax,ax
  ret
Gio_qlrc endp

;------------------------------------------------------------------------------
; 62H Query Default Locator Extents
;   fs:di parm packet
;   gs:si data packet
;------------------------------------------------------------------------------
public Gio_qdle
Gio_qdle proc
   mov  gs:[si].dqdle_rc, QDLE_FAIL
  .if <bit [bx].dcb_Xtrans.trn_flags nz STANDARD_USD> AND NEAR
  .if <bit [bx].dcb_Ytrans.trn_flags nz STANDARD_USD> NEAR
      mov  eax, [bx].dcb_Xtrans.trn_ext_adj_default
      mov  gs:[si].dqdle_Xdefault,eax

      mov  eax, [bx].dcb_Ytrans.trn_ext_adj_default
      mov  gs:[si].dqdle_Ydefault,eax

      mov  gs:[si].dqdle_rc, QDLE_OK
  .endif
  ret
Gio_qdle endp
;---- BUTTON  IOCTLs ----------------------------------------------------------
;
;------------------------------------------------------------------------------

;------------------------------------------------------------------------------
; 50h Set Button Assignment
;   fs:di parm packet
;------------------------------------------------------------------------------
public Gio_sba
Gio_sba proc
  mov cx,word ptr fs:[di].psba_buttonIndex
  mov si,[bx].dcb_NumButDefs
  dec si
  .if <cx le si>   ; in range of defined buttons
     mov  ax, 1                            ; make a mask of the index
     shl  ax, cl
     mov  dx, ax

     mov  cl,byte ptr fs:[di].psba_action  ; make a mask of the action
     mov  ax, 1
     shl  ax, cl

; see if this assignment is legal for this type of button

     mov  si,[bx].dcb_@regCaps

     .if <bit [si].bcap_typeMask nz dx >   ; check by button type
        and ax, [si].bcap_barrel           ; check barrel capabilities
     .else
        and ax, [si].bcap_nonbarrel        ; check non-barrel capabilities
     .endif
     jz short sba_error

; its OK, go ahead and assign it

     mov  ax,word ptr fs:[di].psba_buttonIndex
     sal  ax,BUT_DEF_SIZE_SHIFT
     mov  si,[bx].dcb_@ButDefArray
     add  si,ax
     mov  al,byte ptr fs:[di].psba_action
     mov  [si].but_action,al
     mov  al,byte ptr fs:[di].psba_value
     mov  [si].but_value,al
     call But_CalcCaps                  ; re-calc the capability packet
     call IDC_UpdateCaps                ; update caps
     xor  ax,ax
  .else
sba_error:
     mov  ax, ERROR_BAD_PARM
  .endif
  ret
Gio_sba endp

;------------------------------------------------------------------------------
; 60H Query Button Assignment
;   fs:di parm packet
;   gs:si data packet
;------------------------------------------------------------------------------
public Gio_qba
Gio_qba proc
  mov ax,word ptr fs:[di].psba_buttonIndex
  mov cx,[bx].dcb_NumButDefs
  dec cx
  .if <ax le cx>
     sal  ax,BUT_DEF_SIZE_SHIFT
     mov  di,[bx].dcb_@ButDefArray
     add  di,ax
     xor  eax,eax
     mov  al,[di].but_action
     mov  gs:[si].dqba_action,eax
     mov  al,[di].but_value
     mov  gs:[si].dqba_value,eax
     xor  ax,ax
  .else
     mov  ax, ERROR_BAD_PARM
  .endif
  ret
Gio_qba endp

;---- DISPLAY IOCTLs ----------------------------------------------------------
;
;------------------------------------------------------------------------------

;------------------------------------------------------------------------------
; 50h Set Display State
;   fs:di parm packet
;------------------------------------------------------------------------------
public Gio_sds
Gio_sds proc
  mov  al, byte ptr fs:[di].psds_command
  call Dsp_SDS
  xor  ax,ax
  ret
Gio_sds endp

;------------------------------------------------------------------------------
; 51h Set Display Inactivity Period (and automatic processing options)
;   fs:di parm packet
;------------------------------------------------------------------------------
public Gio_sdip
Gio_sdip proc
  mov  ax, word ptr fs:[di].psdip_command

; update opaque option

 .if  <bit al nz SDIP_EN_OPAQUE>
    or  [bx].dcb_DspFlags,DSP_OPAQUE
 .endif
 .if  <bit al nz SDIP_DI_OPAQUE>
    and [bx].dcb_DspFlags,not DSP_OPAQUE
 .endif

; only allow the following if capabilities permit

  mov  si, [bx].dcb_@RegCaps
  .if  <bit [si].dcap_auto_flag nz 1>

;    change the period

     .if  <bit ax nz SDIP_PERIOD>
        mov  edx, fs:[di].psdip_period
        mov  [bx].dcb_inactPeriod,edx
     .endif

;    set auto on/off option

     .if  <bit al nz SDIP_EN_AUTO>
        or  [bx].dcb_DspFlags,DSP_AUTO_ENABLED
     .endif
     .if  <bit al nz SDIP_DI_AUTO>
        and [bx].dcb_DspFlags,not DSP_AUTO_ENABLED
     .endif

;    set suppress option

     .if  <bit ax nz SDIP_EN_SUPPRESS>
        or  [bx].dcb_DspFlags,DSP_SUPPRESS
     .endif
     .if  <bit ax nz SDIP_DI_SUPPRESS>
        and [bx].dcb_DspFlags,not DSP_SUPPRESS
     .endif

;    update state of display engine

     call Dsp_SetInactPeriod

  .endif
  xor  ax,ax
  ret
Gio_sdip endp

;------------------------------------------------------------------------------
; 60H Query Display State
;   fs:di parm packet
;   gs:si data packet
;------------------------------------------------------------------------------
public Gio_qds
Gio_qds proc
  xor eax, eax
  .if <bit [bx].dcb_DspFlags nz DSP_STATE_ON>
     mov al, 1
  .endif
  mov gs:[si].dqds_state,eax

  xor eax, eax
  mov dx,[bx].dcb_DspFlags
  .if  <bit dx nz DSP_OPAQUE>
     or  ax,SDIP_EN_OPAQUE
  .else
     or  ax,SDIP_DI_OPAQUE
  .endif
  .if <bit dx nz DSP_AUTO_ENABLED>
     or  ax,SDIP_EN_AUTO
  .else
     or  ax,SDIP_DI_AUTO
  .endif
  .if <bit dx nz DSP_SUPPRESS>
     or  ax,SDIP_EN_SUPPRESS
  .else
     or  ax,SDIP_DI_SUPPRESS
  .endif
  mov gs:[si].dqds_automatic,eax

  mov eax,[bx].dcb_InactPeriod
  mov gs:[si].dqds_period,eax

  xor ax,ax
  ret
Gio_qds endp

.286p

;---- MISC   ROUTINES----------------------------------------------------------
;
;------------------------------------------------------------------------------

;------------------------------------------------------------------------------
; panic routine
; al = panic value
;------------------------------------------------------------------------------
public GIO_Panic
GIO_Panic proc
  .if <al eq <byte ptr DDPanic>> OR
  .if <al eq <byte ptr DDPanic+1>> OR
  .if <al eq <byte ptr DDPanic+2>> OR
  .if <al eq <byte ptr DDPanic+3>>
     stc
     ret
  .endif
  .if <<byte ptr DDPanic> eq 0>
    mov  byte ptr DDPanic,al
  .elseif <<byte ptr DDPanic+1> eq 0>
    mov  byte ptr DDPanic+1,al
  .elseif <<byte ptr DDPanic+2> eq 0>
    mov  byte ptr DDPanic+2,al
  .elseif <<byte ptr DDPanic+3> eq 0>
    mov  byte ptr DDPanic+3,al
  .endif
  stc
  ret
GIO_Panic endp

;------------------------------------------------------------------------------
; unpanic routine
; al = panic value
;------------------------------------------------------------------------------
public GIO_UnPanic
GIO_UnPanic proc
  .if <<byte ptr DDPanic> eq al>
    mov  byte ptr DDPanic,0
  .elseif <<byte ptr DDPanic+1> eq al>
    mov  byte ptr DDPanic+1,0
  .elseif <<byte ptr DDPanic+2> eq al>
    mov  byte ptr DDPanic+2,0
  .elseif <<byte ptr DDPanic+3> eq al>
    mov  byte ptr DDPanic+3,0
  .endif
  ret
GIO_UnPanic endp

;------------------------------------------------------------------------------
; Add a dcb to the dcb list and assign unit number
;  bx = DCB
;------------------------------------------------------------------------------
public Gio_AddDCB
Gio_AddDCB proc
  mov  si, bx                   ; link DCB
  xchg si, DCB_Anchor
  mov  [bx].dcb_Link,si

  mov  al, RegCaps0.ddcap_unitCount     ; assign unit number
  mov  [bx].dcb_Unit,al
  inc  RegCaps0.ddcap_unitCount
  ret
Gio_AddDCB endp

;------------------------------------------------------------------------------
; Do a passed routine for each DCB on the list
;  si = routine to call
; exit
;  bx = DCB passed to routine that returned NC
;     = 0 if all routines returned C
;  NC = a routine returned NC and search stopped
;  CY = all routines returned CY
;------------------------------------------------------------------------------
Gio_CallAll  proc
  mov  bx, DCB_Anchor
  .repeat
     push  bx
     call  si
     pop   bx
     .leave nc
     mov  bx, [bx].dcb_Link
  .until <zero bx>
  ret
Gio_CallAll  endp

;------------------------------------------------------------------------------
; Do a passed routine for each DCB on the list of the requested type
;  ax = DCB type
;  si = routine to call
; exit
;  nothing
;------------------------------------------------------------------------------
Gio_CallType proc
  mov  bx, DCB_Anchor
  .repeat
     .if <al eq [bx].dcb_DevType>
        push  ax
        push  bx
        push  si
        call  si
        pop   si
        pop   bx
        pop   ax
     .endif
     mov  bx, [bx].dcb_Link
  .until <zero bx>
  ret
Gio_CallType endp

;------------------------------------------------------------------------------
; call the dcb by unit number
;  al = unit
;  si = rtn to call
; exit
;  bx = DCB & NC for success
;     = DCB & CY for error return
;     = 0 if not found & CY set
;------------------------------------------------------------------------------
Gio_CallUnit proc
  mov  bx, DCB_Anchor
  .repeat
     .if <al eq [bx].dcb_Unit>
        call  si
        clc
        ret
     .endif
     mov  bx, [bx].dcb_Link
  .until <zero bx>
  stc
  ret
Gio_CallUnit endp

CSEG ends

end
