;*DDK*************************************************************************/
;
; 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.;
;*****************************************************************************/
;/*****************************************************************************
;*
;* SOURCE FILE NAME = TOUMAIN.ASM
;*
;* DESCRIPTIVE NAME = Touch device dependant device driver
;*
;*
;* VERSION      V2.0
;*
;* DATE         01/10/92
;*
;* DESCRIPTION
;*
;* FUNCTIONS    strat_entry,    req_open,       req_close,
;*              req_ioctl,      req_shtdwn,     req_deins,
;*              req_err,        idc_entry,      idc_q_conf,
;*              idc_read_en,    idc_read_dis,   idc_enable_dev,
;*              idc_disable_dev,idc_set_emul,   idc_set_beep,
;*              idc_q_dev_stat, set_raw_mode,   set_xyz_mode,
;*              bmove,          queue_flush,    process_data,
;*              abs_ax,         get_ltime,      build_pkt,
;*              stream_dis,     stream_en,      wait_cmd,
;*              req_init,       hw_init,        pause,
;*              essi2dsdi.
;*
;*
;* NOTES        NONE
;*
;* STRUCTURES   NONE
;*
;* EXTERNAL REFERENCES
;*
;*              NONE
;*
;* EXTERNAL FUNCTIONS
;*
;*              NONE
;*
;* CHANGE ACTIVITY =
;*   DATE      FLAG        APAR   CHANGE DESCRIPTION
;*   --------  ----------  -----  --------------------------------------
;*   mm/dd/yy  @Vr.mpppxx  xxxxx  xxxxxxx
;*****************************************************************************/

SD_BEEP         equ     2       ; selection beeper (0-none, 1-sem, 2-devhlp)
CLK_LCK         equ     1       ; click locking

# DEBUG         equ     0       ; on if defined
NEW_MOUSE       equ     1       ; use proper mouse status


.286p

.seq
DSEG            segment word public 'DATA'
DSEG            ends
CSEG            segment word public 'CODE'
CSEG            ends


.xlist
.xcref

include devhlp.inc
include struc.inc
include proc.inc
include toudderr.inc
include touequ.inc
include toustruc.inc
include toumacro.inc

.cref
.list


        extrn   DOSWRITE:far
        extrn   DOSREAD:far
        extrn   KBDFLUSHBUFFER:far
        extrn   KBDSTRINGIN:far

        extrn   PROCESS_INIT_FILE:far

        extrn   mou_int_pkt_off:word
        extrn   mou_dddd_idc:byte
        extrn   mou_dev_status:word
        extrn   mou_stream_dis:near
        extrn   mou_stream_en:near
        extrn   mou_header:byte

        extrn   prescott_hw_init:near
        extrn   prescott_hw_deinit:near
        extrn   prescott_failed:word
        extrn   prescott_io:near

        extrn   int_pkt:byte
        extrn   ioc_read_data:near
        extrn   ioc_set_mode:near
        extrn   ioc_get_mode:near
        extrn   ioc_read_mem:near
        extrn   ioc_write_mem:near
        extrn   ioc_set_mpi:near
        extrn   ioc_get_mpi:near
        extrn   ioc_set_cc:near
        extrn   ioc_get_cc:near
        extrn   ioc_set_rate:near
        extrn   ioc_get_rate:near
        extrn   ioc_set_thresh:near
        extrn   ioc_get_thresh:near
        extrn   ioc_set_filter:near
        extrn   ioc_get_filter:near
        extrn   ioc_set_offset:near
        extrn   ioc_get_offset:near
        extrn   ioc_set_click:near
        extrn   ioc_get_click:near
        extrn   set_thresholds:near
        extrn   set_report_rate:near
        extrn   set_filters:near
        extrn   ioc_set_beep:near
        extrn   ioc_get_beep:near
        extrn   ioc_set_emul:near
        extrn   ioc_get_emul:near


        public  devhlp
        public  essi2dsdi
        public  bmove
        public  int_pkt_off
        public  dddd_idc
        public  conf_data
        public  toudd_fail
        public  idc_enable_dev
        public  idc_disable_dev
        public  dev_status


;*
;* Coordinate system defaults
;*
XSIZE           equ     4095            ; x (col) coord size
YSIZE           equ     4095            ; y (row) coord size
ZSIZE           equ     255             ; z (push) coord size
XHYST           equ     500             ; (== 0.5)
YHYST           equ     500             ; (== 0.5)


TOUCH_CMD_RETRY         equ     10


DSEG    segment

public  header
                ;*
                ;* Link to driver in next module but in same data seg
                ;*
header          dw      offset dseg:mou_header
                dw      dseg
                        ;*
                        ;* Honour sharing to stop multiple opens of DD
                        ;*
                dw      DATT_CHR+DATT_IDC+DATT_OPN+DATT_SHR+(7 shl DATT_LSHFT)
                dw      strat_entry
                dw      idc_entry
                db      'PDITOU$ '
                dw      0, 0, 0, 0


        db      'Copyright (C) International Business Machines Corp. 1991.'
        db      'All rights reserved', 0


devhlp          dd      0               ; DevHlp entry point (bimodal)
dev_status      dw      0               ; internal DD status
int_pkt_off     dw      0               ; addr shared int pkt, owned by DIDD
didd_name       db      'TOUCH$  '      ; name of DIDD
dddd_idc        IDC     <?>             ; returned data from AttachDD
gdt_info_seg    dw      0               ; ring 0 info seg selector

;*
;* selection locking data
;*
sd_old_stat     dw      0
sd_xpos         dw      0
sd_ypos         dw      0
sd_time         dd      0
sd_count        db      0

public          sess_id
sess_id         dw      0

public  emul_mode, raw_mode, calib_mode, open_count, has_been_calib, beep_mode

;*
;* emul mode determines how (or if) the mouse didd is called
;*
emul_mode       db      1               ; emulation mode (0,1,2), set via idc

;*
;* beep mode determines if the emul sd beeper
;*
beep_mode       db      1               ; beep mode (0,1), set via idc

;*
;* calib mode stops mouse & touch didds being called.
;* only dddd data allowed
;*
calib_mode      db      1               ; calibration (0,1) set via DDDD
                                        ;   open/close

;*
;* used by close to enable xyz mode, set by dcc
;*
has_been_calib  db      0               ; calibration has been done at some
                                        ;   time (0,1)

;*
;* raw mode determines raw/xyz data for calibration mode
;*
raw_mode        db      0               ; xyz/raw mode (0,1), set via DDDD ioctl

;*
;* open count used req open
;*
open_count      db      0               ; count of successful opens


current_row_siz equ     YSIZE           ; y
current_col_siz equ     XSIZE           ; x
current_col_max equ     XSIZE           ; temp
current_row_max equ     YSIZE           ; temp

public          curr_pkt
curr_pkt        TPKT    <>              ; current
last_pkt        TPKT    <>              ; last actual
data_pkt        XYZ     <>              ; interrupt routine data buffer

public          data_count
data_count      dw      0               ; data pkt count

;*
;* Read state flags
;*
RS_NONE         equ     0
RS_XYZ          equ     1
RS_RAW          equ     2
read_state      db      RS_NONE

;*
;* Stream state flags
;*
SS_NONE         equ     0
SS_DIS          equ     1
SS_EN           equ     2
stream_state    db      SS_NONE

;*
;* stream count used by stream disable/enable
;*
stream_count    db      0               ; count of stream disables

public          read_state, stream_state, stream_count

conf_data       CONF    <>              ; configuration data

;*
;* Needs to be kept after init as is used by set thresholds ioctl
;*
public  coord_sys
coord_sys       CSYS    <0, XSIZE, 0, YSIZE, 0, ZSIZE>

;*
;* Constant used by threshold scaling routines
;*
public  thre_scale_fact
thre_scale_fact dw      DEF_THRE_SFACT  ; thresholds scale factor

;*
;* Table of report rates, used by set rates
;*
public  rates
rates           db      10, 20, 30, 40, 60      ; report rates per second

;*
;* ioctl data area
;*
public  _def_emul
_def_emul       db      1               ; set from config parms or control panel

public  _def_beep
_def_beep       db      1               ; set from config parms or control panel

public  _glass_mpi
_glass_mpi      dw      DEF_USER_MPI    ; glass emulation, mickeys per inch


;*
;* Click lock parameters
;*
public  _clk_size, _clk_time, _clk_type
_clk_size       dw      DEF_CLK_SIZE    ; active size, in prescott coords!
_clk_time       dw      DEF_CLK_TIME    ; msecs, timeout
_clk_type       db      DEF_CLK_TYPE    ; 0-none, 1-lock sd, 2-lock 2*sd


public  _filter_parms
_filter_parms   FP      <DEF_FILT_TYPE, DEF_FILT_FREQ>


;*
;* Thresholds in-terms-of Z-scale
;*
public  _thre_oth_z, _thre_phy_z, _thre_pth_z
_thre_oth_z     dw      DEF_THRE_OTH_Z
_thre_phy_z     dw      DEF_THRE_PHY_Z
_thre_pth_z     dw      DEF_THRE_PTH_Z

;*
;* Thresholds in-terms-of Prescott
;*
public  thresh_p
thresh_p        THRE    <>              ; actual values set by set_thresholds
                                        ;   routine


public  _report_rate
_report_rate    db      DEF_REP_RATE    ; current report rate


;*
;* Mouse Emulation x/y pointer offsets
;*
public  _y_offset, _x_offset
_y_offset       dw      0               ; row
_x_offset       dw      0               ; col


eq_buf  DBUF    <>                      ; calibration mode data buffer, raw/xyz

public  eq_buf, eq_base, eq_end, eq_size, eq_head, eq_tail

EVNTQ_MAX       equ     10              ; calib queue max entries

eq_base DBUF    EVNTQ_MAX dup (<>)      ; event queue
eq_end  label   word                    ; end of queue
eq_size dw      0                       ; event queue size
eq_head dw      offset eq_base          ; event queue head ptr
eq_tail dw      offset eq_base          ; event queue tail ptr


public          calib_cons
;*
;* Calibration Constants. Init as duff values to show not calibrated.
;*
calib_cons      dd      10 dup (PFLOAT_0)       ; calibration constants


public  filt_table
filt_table      EQU     $
include         toufilt.inc             ; filter constants data


idc_table       label   word
IDC_MIN         equ     1

        dw      idc_q_conf              ; 1 query configuration
        dw      idc_read_en             ; 2 enable read
        dw      idc_read_dis            ; 3 disable read
        dw      idc_enable_dev          ; 4 enable device
        dw      idc_disable_dev         ; 5 disable device
        dw      idc_set_emul            ; 6 set emulation state
        dw      idc_set_beep            ; 7 set emul sd beeper

IDC_MAX         equ     (($-idc_table)/2)+IDC_MIN-1


public          ioc_table
ioc_table       label   byte

IOC_MIN         equ     50h

;*
;*      WORD    near offset of function
;*      BYTE    true if stream enable/disable needed around ioctl function
;*
        dw      req_err                 ; 50
        db      0
        dw      req_err                 ; 51
        db      0
        dw      ioc_set_cc              ; 52
        db      1
        dw      ioc_read_data           ; 53
        db      0
        dw      ioc_set_mode            ; 54
        db      1
        dw      ioc_set_click           ; 55
        db      0
        dw      ioc_set_thresh          ; 56
        db      1
        dw      ioc_set_offset          ; 57
        db      0
        dw      ioc_set_rate            ; 58
        db      1
        dw      ioc_set_filter          ; 59
        db      1
        dw      ioc_write_mem           ; 5a
        db      1
        dw      ioc_set_mpi             ; 5b
        db      0
        dw      ioc_set_beep            ; 5c
        db      0
        dw      ioc_set_emul            ; 5d
        db      0
        dw      req_err                 ; 5e
        db      0
        dw      req_err                 ; 5f
        db      0
        dw      ioc_get_cc              ; 60
        db      0
        dw      ioc_get_mode            ; 61
        db      0
        dw      ioc_get_click           ; 62
        db      0
        dw      ioc_get_thresh          ; 63
        db      0
        dw      ioc_get_offset          ; 64
        db      0
        dw      ioc_get_rate            ; 65
        db      0
        dw      ioc_get_filter          ; 66
        db      0
        dw      ioc_read_mem            ; 67
        db      1
        dw      ioc_get_mpi             ; 68
        db      0
        dw      ioc_get_beep            ; 69
        db      0
        dw      ioc_get_emul            ; 6a
        db      0

IOC_MAX         equ     (($-ioc_table)/3)+IOC_MIN-1


public  prescott_io_dat, prescott_io_resp
public  pio_cmd_lens, pio_add_lens

;*
;* The following data area must be >= to the largest data item
;* which is download_mc, at the moment!
;*

prescott_io_dat db      255+5+1 dup (0) ; abios tsbs data area
prescott_io_resp db     6 dup (0)       ; (see below for max)

toudd_fail      db      0               ; permanent failure flag


if 1

;* PIO_FIRST_CMD  equ     0b0h
;* PIO_LAST_CMD   equ     0cfh

;*
;* table of command lengths starting at cmd=0B0h
;* where: 0 is illegal cmd and -1 is 6+n for download micro code
;*
;*
;* Write memory                 B0h
;* Read memory                  B1h
;* STAT REQ                     B2h
;* RES WRAP                     B3h
;* Read code level byte         B4h
;* SET WRAP                     B5h
;* RAM EXE                      B6h
;* Read post status             B7h
;* READ TYPE                    B8h
;* Acquire offsets              B9h >= 130, removed
;* Resend                       BAh
;* Reset                        BBh
;* (not used)                   BCh
;* Set coordinate system        BDh
;* Read processed data          BEh >= 190, read processed data 1 + 12
;* Feed forward data            BFh >= 190, feed forward 33 + 0
;* Load thresholds              C0h >= 130, one word less
;* Set stream mode              C1h
;* Read data                    C2h
;* SET REMOTE                   C3h
;* SET SAMPLE                   C4h
;* Enable stream mode           C5h
;* Disable stream mode          C6h
;* SET DEF                      C7h
;* SET MISC                     C8h
;* Enable raw mode              C9h
;* Enable XYZ mode              CAh
;* (not used)                   CBh
;* Download micro code          CCh
;* SET ENV                      CDh >= 130, removed
;* Set calibration constants    CEh
;* Set filter constants         CFh >= 130, one byte extra (tau)

IF MC_LEVEL ge 190
;*                       0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
;*                       ----------------------------------------------
pio_cmd_lens    db       4, 3, 1, 1, 1, 1, 3, 1, 1, 0, 1, 1, 0,13, 1,33 ; 0B?h
                db       9, 1, 1, 1, 2, 1, 1, 1, 6, 1, 1, 0,-1, 0,41,30 ; 0C?h
ELSE
IF MC_LEVEL ge 130
;*                       0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
;*                       ----------------------------------------------
pio_cmd_lens    db       4, 3, 1, 1, 1, 1, 3, 1, 1, 0, 1, 1, 0,13, 0, 0 ; 0B?h
                db       9, 1, 1, 1, 2, 1, 1, 1, 6, 1, 1, 0,-1, 0,41,30 ; 0C?h
ELSE    ; <130
;*                       0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
;*                       ----------------------------------------------
pio_cmd_lens    db       4, 3, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 0,13, 0, 0 ; 0B?h
                db      11, 1, 1, 1, 2, 1, 1, 1, 6, 1, 1, 0,-1,16,41,29 ; 0C?h
ENDIF   ; >=130
ENDIF   ; >=190


;*
;* table of length of additional responses starting at cmd=0B0h
;* (see prescott work book)
;*
IF MC_LEVEL ge 190
;*                       0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
;*                       ----------------------------------------------
pio_add_lens    db       0, 1, 6, 0, 1, 0, 0, 2, 1, 0, 0, 2, 0, 0,12, 0 ; 0B?h
                db       0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; 0C?h
ELSE
;*                       0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
;*                       ----------------------------------------------
pio_add_lens    db       0, 1, 6, 0, 1, 0, 0, 2, 1, 1, 0, 2, 0, 0, 0, 0 ; 0B?h
                db       0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ; 0C?h
ENDIF
endif

;*
;* *** All following data will be discarded after init ***
;*
;* END_DATA     equ     $
;*

;*
;* Defaults for miscellaneous data, set at init time
;*
;*       coord origin:   upper-left
;*       selection mech: push-harder
;*
misc_data       db      00000101B       ; set everything!
                dw      XHYST           ; set up at init from coord sys, above
                dw      YHYST           ; set up at init from coord sys, above

code_level      dw      0               ; current code level of ROM
mparm_level     db      '??',0          ; code level for printing

mparm_vers      db      VERSION, 0      ; version string

mcrlf           db      CR, LF
mcrlf_len       equ     $-mcrlf

print_err       db      CR, LF
                db      '(string too big)'
                db      CR, LF
print_err_len   equ     $-print_err

code_token      db      'CODE=', 0
init_token      db      'INIT=', 0

mc_file_name    db      128 dup (?)     ; for config mc file name
init_file_name  db      128 dup (?)     ; for config init file name

hex             db      '0123456789ABCDEF'
hex_buff        db      4 dup (?)
char_buff       db      ?
xfer_len        dw      ?

sys_msg_name    db      'OSO001.MSG', 0 ; system message file name
PauseRequired   dw      0

DSEG    ends


CSEG    segment
        assume  cs:CSEG, ds:DSEG


;/***************************************************************************
;*
;* FUNCTION NAME = strat_entry
;*
;* DESCRIPTION   = Strategy Entry
;*
;*
;* INPUT         = NONE
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;*
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

pubdeb          strat_entry
PROCEDURE       strat_entry     far

VARIABLE        temp_es         word
VARIABLE        temp_bx         word

        BEGINPROC

        mov     temp_es, es
        mov     temp_bx, bx

;*
;* NB. Will need exclusion semaphore on req functions if more than one
;* request can be active. That is, if multiple opens allowed or a process
;* inherits its open handles from a parent.
;*

        .if     <<word ptr devhlp.xseg> ne 0> and
        .if     <bit dev_status nand DEVS_DEINS>

                ;*
                ;* init done and not deinstalled yet
                ;*

                .if     <es:[bx].req_cmd eq CMD_DEINS>
                        ;*
                        ;* deinstall cmd
                        ;*
                        call    req_deins

                .elseifs <es:[bx].req_cmd eq CMD_OPEN>
                        ;*
                        ;* open cmd
                        ;*
                        call    req_open

                .elseifs <es:[bx].req_cmd eq CMD_CLOSE>
                        ;*
                        ;* close cmd
                        ;*
                        call    req_close

                .elseifs <es:[bx].req_cmd eq CMD_IOCTL>
                        ;*
                        ;* ioctl cmd
                        ;*
                        call    req_ioctl

                .elseifs <es:[bx].req_cmd eq CMD_IFLUSH>
                        ;*
                        ;* input flush cmd
                        ;*
                        call    queue_flush

                .elseifs <es:[bx].req_cmd eq CMD_SHTDWN>
                        ;*
                        ;* shut down cmd
                        ;*
                        call    req_shtdwn

                .else                   ; not valid cmd
                        call    req_err

                .endif                  ; cmd test


                DH_DEVDONE      temp_es, temp_bx


        .else                           ; not installed

                .if     <es:[bx].req_cmd eq CMD_INIT>
                        ;*
                        ;* init cmd
                        ;*
                        call    req_init

                .else   ;*
                        ;* not init cmd
                        ;* flag as unknown cmd
                        ;*
                        call    req_err

                .endif                  ; cmd test

                ;*
                ;* cmd done
                ;*
                or      es:[bx].req_status, STAT_DONE

        .endif                          ; init/deins test

FREEVAR temp_es
FREEVAR temp_bx

        ENDPROC strat_entry


;/***************************************************************************
;*
;* FUNCTION NAME = req_open
;*
;* DESCRIPTION   = Request Open
;*
;*
;* INPUT         = NONE
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;*
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

public          req_open
PROCEDURE       req_open        near
VARIABLE        temp_es         word
VARIABLE        temp_bx         word
        BEGINPROC

        mov     temp_es, es
        mov     temp_bx, bx

        .if     <open_count eq 0>
                ;*
                ;* only one open allowed
                ;*

                ;*
                ;* Get session ID
                ;*
                DH_GETDOSVAR    DH_GDV_LIS
                .if     <nc>
                        mov     es, ax
                        les     bx, es:[bx]
                        mov     ax, es:[bx].lis_sesid
                        mov     sess_id, ax

                        mov     ah, es:[bx].lis_ptype

                        .if     <ah eq LIS_PT_DETACHED>
                                mov     sess_id, SG_VIOPOP
                        .else
                                .if     <ah eq LIS_PT_VIOWIN> or
                                .if     <ah eq LIS_PT_PRESMGR>
                                        mov     sess_id, SG_SHELL
                                .endif
                        .endif

                        mov     es, temp_es
                        mov     bx, temp_bx
                .else
                        SET_REQSTAT     STAT_GENF
                .endif

                mov     calib_mode, 1           ; stop mouse & touch didd data

                inc     open_count              ; bump open count

                call    queue_flush             ; get rid of any left-overs

        .else
                ;*
                ;* Should not come here as tddcalls.dll opens driver for
                ;* exclusive access & driver header is set to honour sharing.
                ;* So TddOpen should fail with share violation.
                ;*

                SET_REQSTAT     STAT_GENF       ; already open!
        .endif

FREEVAR temp_es
FREEVAR temp_bx

ENDPROC         req_open


;/***************************************************************************
;*
;* FUNCTION NAME = req_close
;*
;* DESCRIPTION   = Request Close
;*
;*
;* INPUT         = NONE
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;*
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

public          req_close
PROCEDURE       req_close       near
VARIABLE        temp_es         word
VARIABLE        temp_bx         word
        BEGINPROC

        mov     temp_es, es
        mov     temp_bx, bx

        .if     <has_been_calib ne 0>
                ;*
                ;* only if has been calibrated at some time
                ;* not neccesarily calibrated now
                ;*

                ;*
                ;* enable xyz to allow mouse data to pass thru prescott
                ;*
                call    set_xyz_mode    ; set xyz mode
                .if     <nc>
                        ;*
                        ;* actually calibrated & back in xyz mode
                        ;*
                        mov     calib_mode, 0   ; re-enable mouse & touch didd
                .endif

        .else   ;*
                ;* As prescott is in raw mode & has never been calibrated
                ;* it cannot be put back into xyz mode, so the mouse cannot
                ;* be re-enabled at this point.
                ;*

                ;*
                ;* if not yet calibrated
                ;* stop any raw data affecting mouse!
                ;*
                mov     stream_count, 0 ; force disable
                call    stream_dis
                mov     stream_count, 0
        .endif

        dec     open_count              ; bump open count


IFDEF DEBUG
        ;*
        ;* check that stream enables & disables match up
        ;*

        .if     <stream_count ne 0>
                int     3
        .endif
ENDIF

FREEVAR temp_es
FREEVAR temp_bx

ENDPROC         req_close


;/***************************************************************************
;*
;* FUNCTION NAME = req_ioctl
;*
;* DESCRIPTION   = Request IOCtl
;*
;*
;* INPUT         = NONE
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;*
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

public          req_ioctl
PROCEDURE       req_ioctl       near
VARIABLE        temp_es         word
VARIABLE        temp_bx         word
        BEGINPROC

        mov     temp_es, es
        mov     temp_bx, bx

        .if     <es:[bx].req_data.ioctl_fcat eq IOCTL_TOU_CAT>
                ;*
                ;* our category
                ;*

                mov     al, es:[bx].req_data.ioctl_fcode

                .if     <al b IOC_MIN> or
                .if     <al a IOC_MAX>
                        ;*
                        ;* invalid function
                        ;*
                        call    req_err

                .else   ;*
                        ;* valid func
                        ;*
                        sub     al, IOC_MIN
                        cbw
                        mov     di, ax
                        shl     di, 1
                        add     di, ax

                        .if     <<byte ptr ioc_table[di+2]> ne 0>
                                call    stream_dis
                                .if     <c>
                                        SET_REQSTAT     STAT_GENF
                                .endif
                        .else
                                clc
                        .endif

                        .if     <nc>
                                ;*
                                ;* no errors from possible stream disable
                                ;*
                                push    di
                                call    word ptr ioc_table[di]
                                pop     di
                        .endif

                        .if     <<byte ptr ioc_table[di+2]> ne 0>
                                call    stream_en
                                .if     <c>
                                        SET_REQSTAT     STAT_GENF
                                .endif
                        .endif

                .endif                  ; tou func test

        .else                           ; invalid category
                call    req_err

        .endif                          ; category test

        mov     es, temp_es
        mov     bx, temp_bx

FREEVAR temp_es
FREEVAR temp_bx

ENDPROC         req_ioctl


;/***************************************************************************
;*
;* FUNCTION NAME = req_shtdwn
;*
;* DESCRIPTION   = Request Shutdown
;*
;*
;* INPUT         = NONE
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;*
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

pubdeb          req_shtdwn
req_shtdwn      proc    near

        .if     <bit dev_status and DEVS_ABIOS>
                ;*
                ;* abios installed
                ;*

                mov     stream_count, 0 ; force disable
                call    stream_dis
                mov     stream_count, 0 ; inhibit re-enable

        .endif                          ; abios installed test

        ret

req_shtdwn      endp


;/***************************************************************************
;*
;* FUNCTION NAME = req_deins
;*
;* DESCRIPTION   = Requset De-install
;*
;*
;* INPUT         = NONE
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;*
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

req_deins       proc    near

        .if     <bit dev_status and DEVS_ATTACHED>
                ;*
                ;* attached to didd so tell it we are deinstalling
                ;*
                XIDC_DISSUP     dddd_idc

        .endif

        call    prescott_hw_deinit

        or      dev_status, DEVS_DEINS

        ret

req_deins       endp


;/***************************************************************************
;*
;* FUNCTION NAME = req_err
;*
;* DESCRIPTION   = Request Error
;*
;*
;* INPUT         = NONE
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;*
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

req_err         proc    near

        mov     es:[bx].req_status, STAT_UCMD
        ret

req_err         endp


;/***************************************************************************
;*
;* FUNCTION NAME = idc_entry
;*
;* DESCRIPTION   = IDC Entry
;*
;*
;* INPUT         = NONE
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;*
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

idc_entry       proc    far

        push    bx

        .if     <ax ge IDC_MIN> and
        .if     <ax le IDC_MAX> and
        .if     <bit dev_status nand DEVS_DEINS>
                ;*
                ;* IDC func valid & installed
                ;*

                sub     ax, IDC_MIN
                mov     bx, ax
                shl     bx, 1
                call    idc_table[bx]

        .else
                ;*
                ;* IDC func illegal or deinstalled
                ;*

                ;*
                ;* flag error
                ;*
                stc
                mov     ax, 1

        .endif

        pop     bx

        ret

idc_entry       endp


;/***************************************************************************
;*
;* FUNCTION NAME = idc_q_conf
;*
;* DESCRIPTION   = IDC Query Configuration
;*
;*
;* INPUT         = NONE
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;*
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

idc_q_conf      proc    near

        mov     cx, es:[di]             ; get size

        .if     <cx gt <size CONF>>
                mov     cx, size CONF
        .endif

        mov     si, offset conf_data
        cld
        rep     movsb

        xor     ax, ax
        ret

idc_q_conf      endp


;/***************************************************************************
;*
;* FUNCTION NAME = idc_read_en
;*
;* DESCRIPTION   = IDC Read Enable
;*
;*
;* INPUT         = NONE
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;*
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

idc_read_en     proc    near

        cli

        .if     <bit dev_status nand DEVS_ATTACHED>
                ;*
                ;* not attached
                ;*

                ;*
                ;* save shared int packet addr
                ;*
                mov     int_pkt_off, di

                DH_ATTACHDD     didd_name, dddd_idc
                .if     <nc>
                        ;*
                        ;* attach successful
                        ;*
                        or      dev_status, DEVS_READ_EN+DEVS_ATTACHED

                        xor     ax, ax

                .endif

        .else                           ; attached

                or      dev_status, DEVS_READ_EN

                xor     ax, ax

        .endif                          ; attach test

        sti
        ret

idc_read_en     endp


;/***************************************************************************
;*
;* FUNCTION NAME = idc_read_dis
;*
;* DESCRIPTION   = IDC Read Disable
;*
;*
;* INPUT         = NONE
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;*
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

idc_read_dis    proc    near

        and     dev_status, not DEVS_READ_EN

        xor     ax, ax
        ret

idc_read_dis    endp


;/***************************************************************************
;*
;* FUNCTION NAME = idc_enable_dev
;*
;* DESCRIPTION   = IDC Enable Device
;*
;*
;* INPUT         = NONE
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;*
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

idc_enable_dev  proc    near

        or      dev_status, DEVS_EN_DEV

        xor     ax, ax
        ret

idc_enable_dev  endp


;/***************************************************************************
;*
;* FUNCTION NAME = idc_disable_dev
;*
;* DESCRIPTION   = IDC Disable Device
;*
;*
;* INPUT         = NONE
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;*
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

idc_disable_dev proc    near

        and     dev_status, not DEVS_EN_DEV

        xor     ax, ax
        ret

idc_disable_dev endp


;/***************************************************************************
;*
;* FUNCTION NAME = idc_set_emul
;*
;* DESCRIPTION   = IDC Set Emulation Mode
;*
;*
;* INPUT         = Emulation mode passed in SI register.
;*       SI:   0 - Emulation off. Mouse driver not called with emulation data
;*             1 - Absoloute mouse emulation. Mose driver called with
;*                 absolute data
;*             2 - Relative mouse emulation. Mouse drvier called with
;*                 relative data
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;*
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

idc_set_emul    proc    near

        mov     ax, si

        ;*
        ;* inhibit emul on if defaults not enabled
        ;*
        .if     <_def_emul eq 0>
                mov     al, 0           ; emul on not allowed
        .endif

        mov     emul_mode, al

        xor     ax, ax                  ; clc, ax = 0
        ret

idc_set_emul    endp


;/***************************************************************************
;*
;* FUNCTION NAME = idc_set_beep
;*
;* DESCRIPTION   = IDC Set Beeper
;*
;*
;* INPUT         = Beep mode passed in SI register.
;*       SI:   0 - current off
;*             1 - current on
;*             2 - default off
;*             3 - default on
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;*
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

idc_set_beep    proc    near

        mov     ax, si

        .if     <bit al and 2>
                ;*
                ;* set default beep mode
                ;*
                and     al, 1
                mov     _def_beep, al
        .endif

        ;*
        ;* set current beep mode
        ;*
        .if     <bit al and 1>
                mov     al, _def_beep
        .else
                mov     al, 0
        .endif

        mov     beep_mode, al

        xor     ax, ax  ; clc, ax = 0
        ret

idc_set_beep    endp


;/***************************************************************************
;*
;* FUNCTION NAME = idc_q_dev_stat
;*
;* DESCRIPTION   = IDC Query Device Status
;*           Bit :  0       Calibrated
;*                  1 - 7   not used
;*
;*
;* INPUT         = NONE
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;*
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

idc_q_dev_stat  proc    near

        mov     bx, dev_status

        xor     ax, ax
        ret

idc_q_dev_stat  endp


;/***************************************************************************
;*
;* FUNCTION NAME = set_raw_mode
;*
;* DESCRIPTION   = Set Raw Mode
;*
;*
;* INPUT         = NONE
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;*
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

public          set_raw_mode
PROCEDURE       set_raw_mode    near

VARIABLE        rc              word    ; return code

        BEGINPROC

        mov     rc, 0                   ; reset return code

        call    stream_dis
        .if     <c>
                ret                     ; return as disable failed & enable
                                        ;   not needed
        .endif

;*      .if     <read_state ne RS_RAW>
                ;*
                ;* set raw mode
                ;*

                push    PIO_EN_RAW
                push    ax              ; dummy
                push    ax              ; dummy
                call    prescott_io
                .if     <c>
                        mov     rc, 1
                        jmp     short exit_set_raw_mode ; enable stream needed
                .endif

                mov     read_state, RS_RAW

                mov     raw_mode, 1     ; now raw mode

                call    queue_flush

;*      .endif                          ; rm_raw test


exit_set_raw_mode:

        call    stream_en
        .if     <c>
                ret                     ; exit if error
        .endif

        shr     rc, 1                   ; put error bit, if any, into CY

FREEVAR rc

ENDPROC         set_raw_mode


;/***************************************************************************
;*
;* FUNCTION NAME = set_xyz_mode
;*
;* DESCRIPTION   = Set XYZ mode
;*
;*
;* INPUT         = NONE
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;*
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

public          set_xyz_mode
PROCEDURE       set_xyz_mode    near

VARIABLE        rc              word    ; return code

        BEGINPROC

        mov     rc, 0                   ; reset return code

        call    stream_dis
        .if     <c>
                ret                     ; return as disable failed & enable
                                        ;   not needed
        .endif

;*      .if     <read_state ne RS_XYZ>
                ;*
                ;* set xyz mode
                ;*

                push    PIO_EN_XYZ
                push    ax              ; dummy
                push    ax              ; dummy
                call    prescott_io
                .if     <c>
                        jmp     short exit_set_xyz_mode ; enable stream needed
                .endif

                mov     read_state, RS_XYZ

                mov     raw_mode, 0     ; not raw mode

                call    queue_flush

;*      .endif                          ; xyz test

exit_set_xyz_mode:

        call    stream_en
        .if     <c>
                ret                     ; exit if error
        .endif

        shr     rc, 1                   ; put error bit, if any, into CY

FREEVAR rc

ENDPROC         set_xyz_mode


;/***************************************************************************
;*
;* FUNCTION NAME = bmove
;*
;* DESCRIPTION   = void  bmove(src, dst, siz)
;*                 mov ds:src -> ds:dst
;*
;*
;* INPUT         = NONE
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;*
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

PROCEDURE       bmove   near
PARAMETER       siz     word
PARAMETER       dst     word
PARAMETER       src     word
        BEGINPROC

        push    es
        push    si
        push    di
        push    cx

        mov     cx, ds
        mov     es, cx

        mov     si, src
        mov     di, dst
        mov     cx, siz

        rep     movsb

        pop     cx
        pop     di
        pop     si
        pop     es

ENDPROC         bmove


;/***************************************************************************
;*
;* FUNCTION NAME = queue_flush
;*
;* DESCRIPTION   = Flush Data Queue
;*
;*
;* INPUT         = NONE
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;*
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

public          queue_flush
queue_flush     proc    near

        pushf
        cli
        mov     eq_size, 0
        mov     eq_head, offset eq_base
        mov     eq_tail, offset eq_base
        popf

        ret

queue_flush     endp


;/***************************************************************************
;*
;* FUNCTION NAME = process_data
;*
;* DESCRIPTION   = Process data for int service rtn
;*
;*
;* INPUT         = NONE
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;*
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

public          process_data
process_data    proc    near

        ;*
        ;* move to internal data pkt
        ;*

        .if     <bit <byte ptr int_pkt.0> and PRES_MOU_IND>
                ;*
                ;* current packet is for mouse
                ;*
                ;* reset data count
                ;*
                mov     data_count, 0

        .else                           ; touch packet

                .if     <bit <byte ptr int_pkt.0> and PRES_PKT_IND>
                        ;*
                        ;* 2nd packet rxed
                        ;*

                        .if     <data_count eq 0>
                                ;*
                                ;* 2nd follwed by 2nd, expecting 1st pkt
                                ;* discard current pkt, wait for new 1st
                                ;*

                                jmp     proc_data_exit
                        .endif

                .else                   ; 1st packet rxed

                        .if     <data_count eq 3>
                                ;*
                                ;* 1st followed by 1st, expecting 2nd pkt
                                ;* discard last pkt, keep current 1st
                                ;*

                                mov     data_count, 0
                        .endif

                .endif                  ; 1st/2nd pkt test

        .endif                          ; mouse/touch pkt test

        mov     di, data_count
        mov     al, byte ptr int_pkt.0
        mov     byte ptr data_pkt[di].0, al
        mov     al, byte ptr int_pkt.1
        mov     byte ptr data_pkt[di].1, al
        mov     al, byte ptr int_pkt.2
        mov     byte ptr data_pkt[di].2, al

        add     word ptr data_count, 3  ; advance to next packet

        .if     <bit <byte ptr data_pkt.0> and PRES_MOU_IND> near
                ;*
                ;* current packet is for mouse
                ;*

                ;*
                ;* one pkt for mouse
                ;*

                mov     data_count, 0

                .if     <bit mou_dev_status and DEVS_READ_EN>
                        ;*
                        ;* mou DIDD ready for data
                        ;*

                        ;*
                        ;* process mouse data
                        ;*

                        and     mou_dev_status, not DEVS_READ_EN
                        xor     cx, cx  ; reset status
                        mov     ah, byte ptr data_pkt.0
                        shr     ah, 1
                        .if     <c>
                                or      cx, 2   ; button 1 down
                        .endif

                        shr     ah, 1
                        .if     <c>
                                or      cx, 8   ; button 2 down
                        .endif

                        mov     bh, byte ptr data_pkt.1
                        mov     bl, byte ptr data_pkt.2
                        neg     bl

                        .if     <bx eq 0>
                                ;*
                                ;* no movement
                                ;*
                                shl     cx, 1   ; no movement
                        .else
                                ;*
                                ;* movement
                                ;*
                                .if     <cx eq 0>
                                        inc     cx      ; move & no buttons
                                .endif
                        .endif

                        push    ds      ; save
                        push    es      ; save
                        push    ds      ; ds ->
                        mov     si, mou_int_pkt_off
                        push    ax
                        GET_MODE        ; carry set if prot
                        pop     ax

                        .if     <c>
                                ;*
                                ;* set prot mode DS
                                ;*
                                mov     ds, mou_dddd_idc.idc_p_ds

                        .else   ;*
                                ;* set real mode DS
                                ;*
                                mov     ds, mou_dddd_idc.idc_r_ds

                        .endif

                        mov     [si], cx        ; status
                        mov     al, bh
                        cbw
                        mov     [si].2, ax      ; x mickeys
                        mov     al, bl
                        cbw
                        mov     [si].4, ax      ; y mickeys
                        pop     es              ; -> es

                        ;*
                        ;* call mou DIDD (relative mouse data)
                        ;*
                        sti
                        XIDC_PROCPKT    mou_dddd_idc
                        cli

                        pop     es      ; restore
                        pop     ds      ; restore

                        or      mou_dev_status, DEVS_READ_EN

                .endif                  ; mou DIDD ready test

        .else near

                ;*
                ;* touch packet processing
                ;*

            .if <data_count eq 6> near
                ;*
                ;* received 2nd pkt
                ;*

                mov     data_count, 0   ; reset counter

                ;*
                ;* reformat interrupt packet
                ;*
                mov     di, offset data_pkt
                mov     si, offset curr_pkt
                call    build_pkt

                .if <calib_mode eq 0> near
                    .if <emul_mode eq 1> near
                        ;*
                        ;* absolute mouse emulation
                        ;*

                        .if     <bit mou_dev_status and DEVS_READ_EN> near

                                and     mou_dev_status, not DEVS_READ_EN

                                ;*
                                ;* mou DIDD ready for emulated data
                                ;*

                                ;*
                                ;* get current status
                                ;*
                                mov     dx, curr_pkt.tpkt_stat

                                ;*
                                ;* get x (col) -> bx
                                ;* get y (row) -> ax
                                ;*

                                mov     bx, curr_pkt.tpkt_x     ; col
                                mov     ax, curr_pkt.tpkt_y     ; row

IF SD_BEEP eq 1
IF1
%OUT    *** Selection Beeper (by semaphore) Enabled
ENDIF
                                .if     <beep_mode ne 0> and
                                .if     <bit dx and IDC_STAT_SD> and
                                .if     <bit sd_old_stat nand IDC_STAT_SD>
                                        ;*
                                        ;* sd going off->on
                                        ;* sd beeper
                                        ;*

                                        .if <beep_sem.wlo ne 0> or
                                        .if <beep_sem.whi ne 0>
                                                ;*
                                                ;* sem handle valid,
                                                ;*  so enable beep
                                                ;*

                                                pushf
                                                DH_SEMCLEAR1 beep_sem
                                                ;*
                                                ;* CY error?
                                                ;*
                                                popf

                                        .endif
                                .endif
endif                                   ; beeper

IF SD_BEEP eq 2
IF1
%OUT    *** Selection Beeper (by DevHlp) Enabled
ENDIF
                                .if     <beep_mode ne 0> and
                                .if     <bit dx and IDC_STAT_SD> and
                                .if     <bit sd_old_stat nand IDC_STAT_SD>
                                        ;*
                                        ;* sd going off->on
                                        ;* sd beeper
                                        ;*

                                        push    ax
                                        push    bx
                                        push    dx
;*  drw                                 mov     dl, 64  ; dh_beep
                                        mov     dl, DevHlp_Beep
                                        mov     ax, 3   ; func
                                        mov     bx, 1000; freq
                                        mov     cx, 100 ; duration
                                        call    devhlp
                                        pop     dx
                                        pop     bx
                                        pop     ax

                                .endif
endif                                   ; beeper


if CLK_LCK
IF1
%OUT    *** Click Locking enabled
ENDIF
                                ;*
                                ;* coord locking for 1/2 click, active
                                ;*

                                .if     <sd_count ne 0>
                                    ;*
                                    ;* selection timeout in progress
                                    ;*

                                    push        ax
                                    push        dx
                                    call        get_ltime
                                    sub         ax, sd_time.wlo
                                    sbb         dx, sd_time.whi ; CY: !timeout
                                    pop         dx
                                    pop         ax


                                ;*
                                ;* check to see if dX or dY > _clk_size,
                                ;* if so, reset sd count
                                ;*

                                    .if <c>
                                        ;*
                                        ;* not timed out
                                        ;* compare: abs(dY) - _clk_size
                                        ;*

                                        push    ax
                                        sub     ax, sd_ypos     ; dY
                                        call    abs_ax
                                        cmp     ax, _clk_size   ; CY: dY < size
                                        pop     ax

                                        ;*
                                        ;* Cy set & falls thru
                                        ;*

                                    .endif

                                    .if <c>
                                        ;*
                                        ;* not timed out & dY not too big
                                        ;* compare: abs(dX) - _clk_size
                                        ;*

                                        push    ax
                                        mov     ax, bx          ; X
                                        sub     ax, sd_xpos     ; dX
                                        call    abs_ax
                                        cmp     ax, _clk_size   ; CY: dX < size
                                        pop     ax

                                    .endif

                                    .if <c>
                                        ;*
                                        ;* not timed out and not moved too far
                                        ;*

                                        ;*
                                        ;* force original position
                                        ;*
                                        mov     bx, sd_xpos
                                        mov     ax, sd_ypos

                                        .if     <bit dx nand IDC_STAT_SD> and
                                        .if     <bit sd_old_stat and IDC_STAT_SD>
                                                ;*
                                                ;* sd active->inactive
                                                ;*

                                                mov     cl, sd_count
                                                .if     <cl ae _clk_type>
                                                        ;*
                                                        ;* click count reached
                                                        ;* set sd inactive
                                                        ;*
                                                        mov     sd_count, 0
                                                .endif
                                        .endif

                                    .else       ; NC
                                        ;*
                                        ;* timed out or moved too far
                                        ;* so, set sd inactive
                                        ;*

                                        mov     sd_count, 0     ; not active

                                    .endif

                                .endif

else
IF1
%OUT    *** Click Locking disabled
ENDIF
endif

                                ;*
                                ;* get button emulation
                                ;*

                                xor     cx, cx          ; no buttons or motion

                                .if     <bit dx and IDC_STAT_SD>

                                        or      cx, 4   ; button1, no motion

if CLK_LCK
                                        ;*
                                        ;* coord locking for 1/2 click, detect
                                        ;*

                                        .if     <_clk_type ne 0> and
                                        .if     <bit sd_old_stat nand IDC_STAT_SD>
                                                ;*
                                                ;* sd locking active &&
                                                ;* select going on
                                                ;*

                                                ;*
                                                ;* time stamp this select
                                                ;*
                                                push    ax
                                                push    dx
                                                call    get_ltime
                                                add     ax, _clk_time
                                                adc     dx, 0
                                                mov     sd_time.wlo, ax
                                                mov     sd_time.whi, dx
                                                ;*
                                                ;* sd time = now + timeout
                                                ;*
                                                pop     dx
                                                pop     ax

                                                .if     <sd_count eq 0>
                                                        ;*
                                                        ;* sd not active now
                                                        ;* save sd position
                                                        ;*
                                                        mov     sd_xpos, bx
                                                        mov     sd_ypos, ax

                                                .endif

                                                ;*
                                                ;* flag sd timeout now active
                                                ;* re-flag if previously active
                                                ;* count num sd going active
                                                ;*
                                                inc     sd_count
                                        .endif
endif                                   ; click lock
                                .endif

                                ;*
                                ;* save current status, for sd change detect
                                ;*
                                mov     sd_old_stat, dx

                                ;*
                                ;* add in offsets to x (bx) & y (ax)
                                ;* & map to a zero based coordinate system
                                ;*
                                ;* add x (col) offset
                                ;*
                                add     bx, _x_offset

                                ;*
                                ;* check x max bounds
                                ;*
                                .if     <bx gt current_col_max>
                                        ;*
                                        ;* too big
                                        ;*
                                        mov     bx, current_col_max
                                .endif

                                ;*
                                ;* check x min bounds
                                ;*
                                .if     <bx lt 0>
                                        ;*
                                        ;* too small
                                        ;*
                                        mov     bx, 0
                                .endif

                                ;*
                                ;* add y (row) offset
                                ;*
                                add     ax, _y_offset

                                ;*
                                ;* check y max bounds
                                ;*
                                .if     <ax gt current_row_max>
                                        ;*
                                        ;* too big
                                        ;*
                                        mov     ax, current_row_max
                                .endif

                                ;*
                                ;* check y min bounds
                                ;*
                                .if     <ax lt 0>
                                        ;*
                                        ;* too small
                                        ;*
                                        mov     ax, 0
                                .endif

IF NEW_MOUSE                            ; for new mouse DD compatibility
IF1
%OUT    *** NEW Mouse Status
ENDIF
                                ;*
                                ;* Always assume motion in x,y or z has
                                ;* occurred as a packet has been reported
                                ;* Adjust status for mouse entry point
                                ;*

                                shr     cx, 1   ; add motion to buttons
                                .if     <z>
                                        ;*
                                        ;* no buttons
                                        ;*
                                        inc     cx      ; motion, no buttons
                                .endif
ELSE
IF1
%OUT    *** OLD Mouse Status
ENDIF
ENDIF
                                ;*
                                ;* save current position
                                ;*

                                push    ds      ; save
                                push    es      ; save
                                push    ds      ; ds -> es, later
                                mov     si, mou_int_pkt_off
                                push    ax
                                GET_MODE        ; carry set if prot
                                pop     ax
                                .if     <c>

                                        ;*
                                        ;* set prot mode DS
                                        ;*
                                        mov     ds, mou_dddd_idc.idc_p_ds

                                .else

                                        ;*
                                        ;* set real mode DS
                                        ;*
                                        mov     ds, mou_dddd_idc.idc_r_ds

                                .endif

                                pop     es      ; (DDDD ds) -> es

                                ;*
                                ;* ds:si -> mou int packet (in mou DIDD)
                                ;* es:   -> DDDD dseg
                                ;*

                                mov     [si].abse_stat, cx

                                mov     [si].abse_row_pos, ax   ; y
                                mov     [si].abse_col_pos, bx   ; x

                                mov     ax, current_row_siz
                                mov     [si].abse_row_siz, ax
                                mov     ax, current_col_siz
                                mov     [si].abse_col_siz, ax

                                ;*
                                ;* call mou DIDD (absolute emulation)
                                ;*
                                sti
                                XIDC_ABSPROCPKT mou_dddd_idc
                                cli

                                pop     es      ; restore
                                pop     ds      ; restore
;*
;* come here from click locking algorithm
;*
PD_IGNORE_MOU_PKT:

                                or      mou_dev_status, DEVS_READ_EN

                        .endif          ; mou DIDD ready for emul data, test

                    .elseif     <emul_mode eq 2> near
                        ;*
                        ;* glass mouse emulation
                        ;*

                        .if     <bit curr_pkt.tpkt_stat and IDC_STAT_TS1> near
                                ;*
                                ;* onscreen
                                ;*

                            .if <bit curr_pkt.tpkt_stat nand IDC_STAT_TS2>
                                ;*
                                ;* touch down
                                ;*

                            .else near  ; not touch down

                                .if <bit mou_dev_status and DEVS_READ_EN> near
                                        ;*
                                        ;* mou DIDD ready for data
                                        ;*

                                        and     mou_dev_status, not DEVS_READ_EN
                                        mov     bx, _glass_mpi

                                        ;*
                                        ;* calculate Dx (col) value
                                        ;*
                                        mov     cx, DEF_FXED_MPI_X
                                        mov     ax, curr_pkt.tpkt_x
                                        sub     ax, last_pkt.tpkt_x
                                        sal     ax, 1
                                        cwd
                                        imul    bx      ; mpi
                                        idiv    cx      ; gain factor
                                        push    ax      ; save Dx

                                        ;*
                                        ;* calculate Dy (row) value
                                        ;*
                                        mov     cx, DEF_FXED_MPI_Y
                                        mov     ax, curr_pkt.tpkt_y
                                        sub     ax, last_pkt.tpkt_y
                                        sal     ax, 2
                                        cwd
                                        imul    bx      ; mpi
                                        idiv    cx      ; gain factor
                                        pop     bx      ; restore Dx

                                        ;*
                                        ;* ax = Dy
                                        ;* bx = Dx
                                        ;*
                                        ;* check for Dx | Dy, motion
                                        ;*
                                        mov     cx, ax  ; Dy
                                        or      cx, bx
                                        .if     <nonzero cx>
                                                ;*
                                                ;* movement
                                                ;* & no button yet
                                                ;*

                                                mov     cx, 1

                                        .else   ;*
                                                ;* no movement
                                                ;* & no button yet
                                                ;*

                                                mov     cx, 2
                                        .endif

                                        ;*
                                        ;* get button emulation
                                        ;*
                                        .if     <bit curr_pkt.tpkt_stat and IDC_STAT_SD>
                                                shl     cx, 1   ; button1 down
                                        .endif

                                        push    ds      ; save
                                        push    es      ; save
                                        push    ds      ; ds ->
                                        mov     si, mou_int_pkt_off
                                        push    ax
                                        GET_MODE        ; carry set if prot
                                        pop     ax

                                        .if     <c>

                                                ;*
                                                ;* set prot mode DS
                                                ;*
                                                mov     ds, mou_dddd_idc.idc_p_ds

                                        .else

                                                ;*
                                                ;* set real mode DS
                                                ;*
                                                mov     ds, mou_dddd_idc.idc_r_ds

                                        .endif

                                        mov     [si].0, cx      ; status
                                        mov     [si].2, bx      ; Dx
                                        mov     [si].4, ax      ; Dy
                                        pop     es              ; -> es

                                        ;*
                                        ;* call mou DIDD (relative emulation)
                                        ;*
                                        sti
                                        XIDC_PROCPKT    mou_dddd_idc
                                        cli

                                        pop     es      ; restore
                                        pop     ds      ; restore

                                        or      mou_dev_status, DEVS_READ_EN

                                .endif  ; mou DIDD ready test

                            .endif      ; touch down test

                        .endif          ; on screen test

                    .endif              ; emulation

                ;*
                ;* Touch data is always sent to the touch driver, whether
                ;* emulation is enabled or not
                ;*

                    .if <bit dev_status and DEVS_READ_EN> near
                        ;*
                        ;* tou DIDD ready for data
                        ;*
                        ;* touch mode
                        ;*

                        and     dev_status, not DEVS_READ_EN    ; disable

                        push    ds      ; save
                        push    es      ; save

                        ;*
                        ;* mov  es, ds
                        ;*
                        push    ds      ; ds ->
                        pop     es      ; -> es
                        GET_MODE        ; carry set if prot
                        .if     <c>

                                ;*
                                ;* set prot mode data seg
                                ;*
                                mov     ds, dddd_idc.idc_p_ds
                        .else

                                ;*
                                ;* set real mode data seg
                                ;*
                                mov     ds, dddd_idc.idc_r_ds
                        .endif

                        mov     di, offset es:curr_pkt
                        mov     si, es:int_pkt_off

                        ;*
                        ;* es:di -> src event pkt
                        ;* ds:si -> dest event pkt
                        ;*

                        ;*
                        ;* set z value
                        ;*
                        mov     ax, es:[di].tpkt_z
                        mov     [si].evnt_z, ax

                        ;*
                        ;* es -> dddd dseg
                        ;* ds -> didd dseg
                        ;*
                        ;* get x (col) value
                        ;*
                        mov     ax, es:[di].tpkt_x
                        mov     [si].evnt_x, ax         ; into didd

                        ;*
                        ;* get y (row) value
                        ;*
                        mov     ax, es:[di].tpkt_y
                        mov     [si].evnt_y, ax         ; into didd

                        ;*
                        ;* convert prescott status to idc status
                        ;*
                        ;* combine prescott ad, cp, fe, oe, he
                        ;*
                        xor     ah, ah
                        .if     <bit es:data_pkt.xyz_s1 and 37h>
                                mov     ah, 80h         ; idc data in error
                        .endif

                        ;*
                        ;* move sd, ts1, ts2 to lo nib
                        ;*
                        mov     al, es:data_pkt.xyz_s2
                        shr     al, 4
                        and     al, 7
                        mov     [si].evnt_stat, ax ; save idc status

                        ;*
                        ;* IDC status bits
                        ;* E--- -S12
                        ;* |     |||_ TS2 - previous on-screen status
                        ;* |     ||__ TS1 - current  on-screen status
                        ;* |     |___  SD - selection detection
                        ;* |_________ Err - data is in error
                        ;*
                        ;*
                        ;* This  only needs to be done once, really
                        ;*
                        mov     [si].evnt_rx, 4095 ; x range
                        mov     [si].evnt_ry, 4095 ; y range
                        mov     [si].evnt_rz, 255  ; z range

                        ;*
                        ;* call tou DIDD
                        ;*
                        sti
                        XIDC_PROCPKT    dddd_idc
                        cli

                        pop     es      ; restore
                        pop     ds      ; restore

                        or      dev_status, DEVS_READ_EN        ; enable

                        ;*
                        ;* save current data packet
                        ;*

                        push    offset curr_pkt
                        push    offset ds:last_pkt
                        push    size TPKT
                        call    bmove

                    .endif              ; touch ready test

                .else near

                        ;*
                        ;* Calibration mode
                        ;*
                        ;* get FG SG ID for this interrupt
                        ;*
                        mov     es, gdt_info_seg
                        mov     al, es:[0].gis_fg_ses
                        xor     ah, ah

                        ;*
                        ;* see if this interrupt is in foreground
                        ;*
                        .if     <ax eq sess_id> near

                        mov     si, offset eq_buf

                        ;*
                        ;* si -> target, reformatted data
                        ;*

                        .if     <raw_mode eq 1>
                                ;*
                                ;* raw calibration data
                                ;*

                                mov     di, offset DSEG:data_pkt

                                ;*
                                ;* di -> input, prescott data pkt
                                ;*

                                mov     al, [di].raw_t1l
                                mov     ah, [di].raw_t12h
                                shr     ah, 4
                                and     ah, 3                   ; t18 & t19
                                mov     [si].dbuf_x, ax         ; aka T1

                                mov     al, [di].raw_t2l
                                mov     ah, [di].raw_t12h
                                and     ah, 3                   ; t28 & t29
                                mov     [si].dbuf_y, ax         ; aka T2

                                mov     al, [di].raw_t3l
                                mov     ah, [di].raw_t34h
                                shr     ah, 4
                                and     ah, 3                   ; t38 & t39
                                mov     [si].dbuf_z, ax         ; aka T3

                                mov     al, [di].raw_t4l
                                mov     ah, [di].raw_t34h
                                and     ah, 3                   ; t48 & t49
                                mov     [si].dbuf_r, ax         ; aka T4

                                mov     al, [di].raw_t12h
                                mov     ah, [di].raw_t34h
                                and     ax, not 3333h           ; remove data
                                mov     [si].dbuf_s, ax         ; stat

                        .else
                                ;*
                                ;* xyz calibration data
                                ;*

                                mov     di, offset DSEG:curr_pkt

                                ;*
                                ;* di -> input, xyz data pkt
                                ;*

                                mov     ax, [di].tpkt_x
                                mov     [si].dbuf_x, ax

                                mov     ax, [di].tpkt_y
                                mov     [si].dbuf_y, ax

                                mov     ax, [di].tpkt_z
                                mov     [si].dbuf_z, ax

                                mov     [si].dbuf_r, 0  ; reserved in xyz mode

                                ;*
                                ;* set original prescott status
                                ;*
                                mov     al, data_pkt.xyz_s1
                                mov     ah, data_pkt.xyz_s2
                                ;*
                                ;* remove top bit for xyz indicator
                                ;*
                                and     ax, not 8000h
                                mov     [si].dbuf_s, ax

                        .endif          ; raw/xyz mode

public  queue_write
queue_write:
                        ;*
                        ;* write xyz/raw data to dddd queue
                        ;*

                        mov     ax, ds
                        mov     es, ax
                        mov     di, eq_tail
                        mov     cx, size DBUF
                        cld

                        rep     movsb

                        .if     <eq_size ge EVNTQ_MAX>
                                ;*
                                ;* evnt Q full
                                ;* thro away oldest
                                ;* advance head to next element
                                ;*
                                add     eq_head, size DBUF

                        .else   ;*
                                ;* Q not full
                                ;*
                                inc     eq_size
                        .endif

                        ;*
                        ;* update tail ptr
                        ;*
                        mov     eq_tail, di

                        ;*
                        ;* test for tail wrap
                        ;*
                        .if     <eq_tail ae <offset eq_end>>
                                ;*
                                ;* tail at end of Q, so...
                                ;*  set tail to base
                                ;*
                                mov     eq_tail, offset eq_base
                        .endif

                        ;*
                        ;* test for head wrap
                        ;*
                        .if     <eq_head ae <offset eq_end>>
                                ;*
                                ;* head at end of Q, so...
                                ;*  set head to base
                                ;*
                                mov     eq_head, offset eq_base
                        .endif

                .endif                  ; foreground test
                .endif                  ; calib test

            .endif                      ; tou double pkt rcvd test
        .endif                          ; mou/tou packet test

PROC_DATA_EXIT:

        ret

process_data    endp


;/***************************************************************************
;*
;* FUNCTION NAME = abs_ax
;*
;* DESCRIPTION   =
;*
;*
;* INPUT         = NONE
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;*
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

abs_ax          proc    near

        push    dx
                                        ; ax    +ve     -ve
        cwd                             ; dx    0       ff
        xor     ax, dx                  ;       -       cmp
        sub     ax, dx                  ;       -       inc

        pop     dx
        ret

abs_ax          endp


;/***************************************************************************
;*
;* FUNCTION NAME = get_ltime
;*
;* DESCRIPTION   =
;*
;*
;* INPUT         = NONE
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;*
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

get_ltime       proc    near

        ;*
        ;* get current time from GIS into dx:ax
        ;*

        push    es

        mov     es, gdt_info_seg

        pushf
        cli
        mov     ax, word ptr es:[0].gis_millisecs.wlo
        mov     dx, word ptr es:[0].gis_millisecs.whi
        popf

        pop     es

        ret

get_ltime       endp


;/***************************************************************************
;*
;* FUNCTION NAME = build_pkt
;*
;* DESCRIPTION   = reformat xyz interrupt buffer into holding buffer
;*        ds:di -> interrupt buffer (XYZ)
;*        ds:si -> formated holding buffer (TPKT)
;*
;*
;* INPUT         = NONE
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;*
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

public          build_pkt
build_pkt       proc    near

        push    ax
        pushf
        cli

        ;*
        ;* set x value
        ;*
        mov     al, [di].xyz_xl
        mov     ah, [di].xyz_yxh
        and     ah, 0fh                 ; get lo nib
        mov     [si].tpkt_x, ax

        ;*
        ;* set y value
        ;*
        mov     al, [di].xyz_yl
        mov     ah, [di].xyz_yxh
        shr     ah, 4                   ; get hi nib
        mov     [si].tpkt_y, ax

        ;*
        ;* set z value
        ;*
        mov     al, [di].xyz_z
        xor     ah, ah                  ; ucbw
        mov     [si].tpkt_z, ax

        ;*
        ;* Convert prescott status to idc status
        ;*

        ;*
        ;* Prescott Status Bits, packet 1:
        ;* --AP -FOH
        ;*   ||  |||_ HE  - hardware error
        ;*   ||  ||__ OE  - offset error
        ;*   ||  |___ FE  - floating point error
        ;*   ||______ CP  - channel pegged
        ;*   |_______ ADJ - adjusted
        ;*
        ;* Prescott Status Bits, packet 2:
        ;* -S12 ----
        ;*  |||______ TS2 - previous on-screen status
        ;*  ||_______ TS1 - current  on-screen status
        ;*  |________ SD  - selection detection
        ;*
        ;*
        ;* IDC Status Bits:
        ;* E--- -S12
        ;* |     |||_ TS2 - previous on-screen status
        ;* |     ||__ TS1 - current  on-screen status
        ;* |     |___  SD - selection detection
        ;* |_________ Err - data is in error
        ;*

        xor     ax, ax                  ; inititialise status

        ;*
        ;* combine prescott adj, cp, fe, oe, he
        ;*
        .if     <bit [di].xyz_s1 and PRES_S1_ERR> ; 37h
                or      ax, IDC_STAT_ERR        ; idc data in error
        .endif

        .if     <bit [di].xyz_s2 and PRES_S2_TS2>
                or      ax, IDC_STAT_TS2
        .endif

        .if     <bit [di].xyz_s2 and PRES_S2_TS1>
                or      ax, IDC_STAT_TS1
        .endif

        .if     <bit [di].xyz_s2 and PRES_S2_SD>
                or      ax, IDC_STAT_SD
        .endif

        mov     [si].tpkt_stat, ax      ; save idc status

        popf
        pop     ax

        ret

build_pkt       endp


;/***************************************************************************
;*
;* FUNCTION NAME = stream_dis
;*
;* DESCRIPTION   = Disable Stream Mode
;*
;*
;* INPUT         = NONE
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;*
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

public  stream_dis
stream_dis      proc    near

        .if     <stream_state ne SS_DIS> and
        .if     <stream_count eq 0>
                ;*
                ;* not already disabled
                ;* only disable on first call
                ;*
                ;*
                ;* disable stream data
                ;*

                mov     cx, TOUCH_CMD_RETRY

stream_dis_retry:

                push    PIO_DIS_STREAM
                push    ax              ; dummy
                push    ax              ; dummy
                call    prescott_io
                .if     <c>
                        .if     <ax eq ABIOS_NAK>
                                loop    stream_dis_retry        ; try again
                                stc     ; set error for exit
                        .endif

                        jmp     short stream_dis_exit   ; retry exhausted
                .endif

                .if     <raw_mode eq 0> and
                .if     <bit conf_data.conf_mou_stat and MS_REAL_MOUSE>
                        ;*
                        ;* not raw mode (prescott ignores mouse in raw mode)
                        ;* real mouse attached
                        ;*

                        call    mou_stream_dis
                        .if     <c>
                                jmp     short stream_dis_exit
                        .endif

                .endif                  ; real mouse test

                ;*
                ;* stream mode succesfully disabled
                ;*
                mov     stream_state, SS_DIS

stream_dis_exit:

        .else
                clc                     ; no errors
        .endif

        .if     <nc> and
        .if     <stream_count b 254>
                inc     stream_count
                clc
        .endif

        ret

stream_dis      endp


;/***************************************************************************
;*
;* FUNCTION NAME = stream_en
;*
;* DESCRIPTION   = Enable Stream Mode
;*
;*
;* INPUT         = NONE
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;*
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

public  stream_en
stream_en       proc    near

        .if     <stream_state ne SS_EN> and
        .if     <stream_count eq 1>
                ;*
                ;* stream mode not enabled yet
                ;* only enable on last call
                ;*
                ;*
                ;* enable stream data
                ;*

                .if     <raw_mode eq 0> and
                .if     <bit conf_data.conf_mou_stat and MS_REAL_MOUSE>
                        ;*
                        ;* not raw mode (prescott ignores mouse in raw mode)
                        ;* real mouse attached
                        ;*

                        call    mou_stream_en
                        jc      stream_en_exit

                .endif  ;*
                        ;* real mouse test
                        ;*

                .if     <bit dev_status and DEVS_DCC> or
                .if     <raw_mode ne 0>
                        ;*
                        ;* enable stream mode if currently calibrated
                        ;* or in raw mode
                        ;*

                        push    PIO_EN_STREAM
                        push    ax      ; dummy
                        push    ax      ; dummy
                        call    prescott_io
                        .if     <c>
                                jmp     short stream_en_exit
                        .endif

                .endif

                ;*
                ;* stream mode succesfully enabled
                ;*
                mov     stream_state, SS_EN

stream_en_exit:

        .else
                clc                     ; no errors
        .endif

        .if     <nc> and
        .if     <stream_count a 0>
                dec     stream_count
                clc
        .endif

        ret

stream_en       endp


;/***************************************************************************
;*
;* FUNCTION NAME = wait_cmd
;*
;* DESCRIPTION   =
;*
;*
;* INPUT         = NONE
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;*
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

public          wait_cmd
PROCEDURE       wait_cmd        near
        BEGINPROC

        pusha

        ;*
        ;* very long wait for Cowie!
        ;*

        mov     cx, 60000

wait1:

@@:     in      al, 61h
        and     al, 10h
        jz      @B                      ; jif while lo

        ;*
        ;* refresh now hi
        ;*

@@:     in      al, 61h
        and     al, 10h
        jnz     @B                      ; jif while hi

        loop    wait1

        popa

ENDPROC wait_cmd


;/***************************************************************************
;*
;* FUNCTION NAME = req_init
;*
;* DESCRIPTION   = Request Initialisation
;*
;*
;* INPUT         = NONE
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;*
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

PROCEDURE       req_init        near
VARIABLE        temp_es         word
VARIABLE        temp_bx         word
        BEGINPROC

        mov     temp_es, es
        mov     temp_bx, bx

        ;*
        ;* set devhlp entry
        ;*
        mov     ax, word ptr es:[bx].req_data.init_pointer_1.xoff
        mov     word ptr devhlp.xoff, ax
        mov     ax, word ptr es:[bx].req_data.init_pointer_1.xseg
        mov     word ptr devhlp.xseg, ax

        ;*
        ;* init req block status
        ;*
        SET_REQSTAT     STAT_NOERR

        ;*
        ;* get gdt info seg ring 0
        ;*

        push    bx
        DH_GETDOSVAR    DH_GDV_GIS; 
        .if     <c>
                ;*
                ;* get dos var fail
                ;*
                pop     bx
                mov     ax, ERR_DD_INIWAIT
                jmp     short req_init_bad
        .endif

        ;*
        ;* update gdt info seg with ring 0 selector
        ;*

        push    es
        mov     es, ax
        mov     ax, es:[bx]
        mov     gdt_info_seg, ax
        pop     es
        pop     bx

        ;*
        ;* init HW
        ;*
        call    hw_init
        .if     <c>
                jmp short       req_init_bad
        .endif

        jmp     short req_init_ok

req_init_bad:

        .if     <ax eq ERR_DD_MCLEVEL>
                ;*
                ;* download microcode failed due to a level inconsistancy
                ;*

                push    ax              ; failure message number
                mov     ax, code_level  ; get prescott code level
                shl     ax, 4           ; make it printable
                shr     al, 4           ; 
                or      ax, 3030H       ; 
                xchg    ah, al
                mov     word ptr mparm_level, ax
                mov     gpm_parms.p1, offset mparm_level
                push    1               ; num parms
                call    getputmsg
        .else
                push    ax              ; failure message
                push    0               ; no parms
                call    getputmsg
        .endif

        SET_REQSTAT     STAT_GENF

        mov     es, temp_es
        mov     bx, temp_bx

        ;*
        ;* *** NB. memory released in next driver
        ;*

        mov     PauseRequired, 1
        mov     toudd_fail, 1           ; show touch driver load has failed
        jmp     short req_init_end

req_init_ok:

        mov     toudd_fail, 0           ; show driver load ok
        mov     es, temp_es
        mov     bx, temp_bx

        ;*
        ;* *** NB. memory requirements set in next driver
        ;*

req_init_end:

        .if     <PauseRequired ne 0>
                call    pause
        .endif

FREEVAR temp_es
FREEVAR temp_bx

ENDPROC         req_init


;/***************************************************************************
;*
;* FUNCTION NAME = hw_init
;*
;* DESCRIPTION   =
;*
;*
;* INPUT         = NONE
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;*
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

public          hw_init
PROCEDURE       hw_init         near

VARIABLE        temp_es         word    ; temp
VARIABLE        temp_bx         word    ; temp
VARIABLE        test_only       word    ; flag to test microcode level only
VARIABLE        returncode      word    ; error return code
VARIABLE        token_parm      nbyte 80; buffer for found token

        BEGINPROC

        mov     temp_es, es
        mov     temp_bx, bx
        mov     returncode, 0

        ;*
        ;* set up configuration defaults
        ;*
        mov     conf_data.conf_mou_stat, MS_REAL_MOUSE or MS_PROT_EMUL or MS_REAL_EMUL

        call    prescott_hw_init
        .if     <c>
                mov     returncode, ax
                jmp     hw_init_fail2
        .endif

        ;*
        ;* reset data packet counter
        ;*
        mov     data_count, 0

        ;*
        ;* reset prescott
        ;*
        mov     cx, 5                   ; reset retry count

hw_init_reset_retry:

        push    PIO_RESET
        push    ax                      ; dummy
        push    ax                      ; dummy
        call    prescott_io
        .if     <c>

                .if     <ax eq 0C001h>
                        ;*
                        ;* mouse error
                        ;*
                        mov     returncode, ERR_DD_NOABIOS
                        jmp     hw_init_fail
                .endif

                .if     <ax eq ABIOS_NAK_RESEND>
                        loop    hw_init_reset_retry
                        mov     returncode, ERR_DD_INIRESET
                        jmp     hw_init_fail
                .endif

                .if     <ax eq ABIOS_SOI>
                        ;*
                        ;* stage-on-int timeout
                        ;*
                        mov     returncode, ERR_DD_SOI_TO
                        jmp     hw_init_fail
                .endif

                ;*
                ;* default error message
                ;*
                mov     returncode, ERR_DD_INIFAIL
                jmp     hw_init_fail

        .endif                          ; if - cy

        ;*
        ;* read post status
        ;*
        push    PIO_READ_POST
        push    ax                      ; dummy
        push    ax                      ; dummy
        call    prescott_io
        .if     <c>
                mov     returncode, ERR_DD_INIPOST
                jmp     hw_init_fail
        .endif

        ;*
        ;* see if internal self test failed
        ;*

        .if     <bit <byte ptr prescott_io_resp> and 7eh>
                ;*
                ;* self test failed
                ;*
                mov     returncode, ERR_DD_SELFTEST
                jmp     hw_init_fail
        .endif

        ;*
        ;* see if code already downloaded from post return
        ;*

        .if     <bit <byte ptr prescott_io_resp> and 1>
                ;*
                ;* download needed
                ;*
                mov     test_only, 0

        .else   ;*
                ;* no download, just test code level
                ;*
                mov     test_only, 1

        .endif                          ; download test

        ;*
        ;* read code level byte
        ;*
        push    PIO_READ_LEVEL
        push    ax                      ; dummy
        push    ax                      ; dummy
        call    prescott_io
        .if     <c>
                mov     returncode, ERR_DD_INILEVEL
                jmp     hw_init_fail
        .endif

        mov     al, byte ptr prescott_io_resp
        xor     ah, ah                  ; ucbw
        mov     code_level, ax

        ;*
        ;* download micro code
        ;*
        mov     es, temp_es
        mov     bx, temp_bx

        push    es:[bx].req_data.init_pointer_2.xseg
        push    es:[bx].req_data.init_pointer_2.xoff
        push    0                       ; target = NULL
        push    0
        push    dseg
        push    offset code_token
        call    get_token_ptr
        mov     returncode, ERR_DD_CDTOK
        .if     <c>
                jmp     hw_init_fail
        .endif

        ;*
        ;* es:si -> first char after token
        ;*

        mov     di, offset dseg:mc_file_name
        mov     cx, SIZE mc_file_name
        call    extract_parm
        mov     returncode, ERR_DD_MCNAME
        .if     <c>
                jmp     hw_init_fail    ; jif target too small
        .endif

        ;*
        ;* download micro code
        ;*

        push    ds
        push    offset mc_file_name
        push    code_level
        push    test_only
        call    download_mc
        or      ax, ax
        mov     returncode, ax
        .if     <nz>
                jmp     hw_init_fail
        .endif

        call    wait_cmd
        mov     returncode, ERR_DD_INIWAIT
        .if     <c>
                jmp     hw_init_fail
        .endif

        ;*
        ;* get init file
        ;*
        mov     es, temp_es
        mov     bx, temp_bx

        push    es:[bx].req_data.init_pointer_2.xseg
        push    es:[bx].req_data.init_pointer_2.xoff
        push    0                       ; target = NULL
        push    0
        push    dseg
        push    offset init_token
        call    get_token_ptr
        .if     <c>
                ;*
                ;* o/p error message
                ;*
                push    ERR_DD_INITOK
                push    0               ; no parms
                call    getputmsg

                ;*
                ;* o/p warning message
                ;*
                push    WRN_DD_INIDEFAULTS
                push    0 ; no parms
                call    getputmsg

                jmp     short hw_init_ini_fail  ; jif token not found
        .endif

        ;*
        ;* es:si -> first char after token
        ;*

        mov     di, offset dseg:init_file_name
        mov     cx, SIZE init_file_name
        call    extract_parm
        .if     <c>
                ;*
                ;* o/p message
                ;*
                push    ERR_DD_ININAME
                push    0 ; no parms
                call    getputmsg

                ;*
                ;* o/p warning message
                ;*
                push    WRN_DD_INIDEFAULTS
                push    0 ; no parms
                call    getputmsg

                jmp     short hw_init_ini_fail  ; jif target too small
        .endif

        ;*
        ;* process init file
        ;*
        push    ds
        push    offset init_file_name
        call    PROCESS_INIT_FILE
        mov     PauseRequired, ax

        ;*
        ;* adjust configuration due to ini file
        ;*

        .if     <_def_emul eq 0>
                ;*
                ;* no emulation
                ;*
                and     conf_data.conf_mou_stat, not (MS_PROT_EMUL or MS_REAL_EMUL)
        .endif

        .if     <_def_beep ne 0>
                or      conf_data.conf_mou_stat, MS_EMUL_BEEP
        .else
                and     conf_data.conf_mou_stat, not MS_EMUL_BEEP
        .endif

hw_init_ini_fail:

        ;*
        ;* enable touch stream mode
        ;*

        push    PIO_EN_STREAM
        push    ax                      ; dummy
        push    ax                      ; dummy
        call    prescott_io
        .if     <c>
                mov     returncode, ERR_DD_INIENST
                jmp     short hw_init_fail
        .endif
        mov     stream_state, SS_EN

        ;*
        ;* Set default report rate
        ;*

        call    set_report_rate
        .if     <c>
                mov     returncode, ERR_DD_INIENST
                jmp     short hw_init_fail
        .endif

        ;*
        ;* Set default thresholds
        ;*

        call    set_thresholds
        .if     <c>
                mov     returncode, ERR_DD_INIENST
                jmp     short hw_init_fail
        .endif

        ;*
        ;* Set default filter parms
        ;*

        call    set_filters
        .if     <c>
                mov     returncode, ERR_DD_INIENST
                jmp     short hw_init_fail
        .endif

        ;*
        ;* Set default coordinate system
        ;*

        mov     ax, offset coord_sys
        push    PIO_SET_COORD
        push    ds
        push    ax
        call    prescott_io
        .if     <c>
                mov     returncode, ERR_DD_INIENST
                jmp     short hw_init_fail
        .endif

        ;*
        ;* Set default coord origin, selection mechanism & x/y hysteresis
        ;*

        mov     ax, offset misc_data
        push    PIO_SET_MISC
        push    ds
        push    ax
        call    prescott_io
        .if     <c>
                mov     returncode, ERR_DD_INIENST
                jmp     short hw_init_fail
        .endif

        clc                             ; no errors
        jmp     short hw_init_exit

hw_init_fail:
hw_init_fail2:

        stc                             ; errors occurred

hw_init_exit:

        mov     ax, returncode

FREEVAR temp_es
FREEVAR temp_bx
FREEVAR test_only
FREEVAR returncode
FREEVAR token_parm

ENDPROC         hw_init


;/***************************************************************************
;*
;* FUNCTION NAME = pause
;*
;* DESCRIPTION   =
;*
;*
;* INPUT         = NONE
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;*
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

PROCEDURE       pause           near
VARIABLE        StrIn           dword
VARIABLE        OpBuff          word
        BEGINPROC

        ;*
        ;* pause on error
        ;*
        push    0
        call    KBDFLUSHBUFFER

        push    seg sys_msg_name
        push    offset sys_msg_name
        push    1726
        push    0
        call    getputmsg1

        mov     StrIn.wlo, 1
        mov     StrIn.whi, 0

        lea     ax, OpBuff
        push    ss
        push    ax
        lea     ax, StrIn
        push    ss
        push    ax
        push    1                       ; wait
        push    0                       ; kbd handle
        call    KBDSTRINGIN

FREEVAR StrIn
FREEVAR OpBuff

ENDPROC         pause


;/***************************************************************************
;*
;* FUNCTION NAME = essi2dsdi
;*
;* DESCRIPTION   = Copy CX byte of data from ES:SI to DS:DI
;*
;*
;* INPUT         = NONE
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;*
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

essi2dsdi       proc    near

        push    cx
        push    si
        push    di
        push    es
        push    ds

        push    ds                      ; swap es <-> ds
        push    es
        pop     ds
        pop     es

        rep     movsb                   ; ds:si -> es:di

        pop     ds
        pop     es
        pop     di
        pop     si
        pop     cx

        ret

essi2dsdi       endp


END_CODE        equ     $


include dmc.asm                         ; download micro code
include touio.inc                       ; i/o code
include gtp.inc                         ; get token parameter


DSEG    segment
msg_name        db      'TDD.MSG', 0    ; set up message file name
DSEG    ends

include gpm.inc                         ; get & put message


CSEG    ends

        end

;*
;* end
;*
