.386p
INCL_DOSMISC    EQU     1
.xlist
include devsym.inc
include devhlp.inc
include basemaca.inc
.list

EXTRN   DOS32FLATDS:ABS              ; 32 bit r/w FLAT selector
stdout          equ     1            ;Standard device handles
cr              equ     0dh          ; ASCII carriage return
lf              equ     0ah         ; ASCII linefeed

                extrn   DosWrite:far
EXTRN   INT_HAND:FAR                ; Interrupt handler for Card

;*************************************************************************************************************
INIT_DATA SEGMENT WORD PUBLIC 'INITDATA' USE16

temp    dd      0

INIT_DATA ENDS

;*************************************************************************************************************
DATA   SEGMENT  DWORD PUBLIC 'DATA' USE16
        EXTRN   FlatSel:WORD
        EXTRN   selector1:WORD        ; Segment address for Cards RAM
        EXTRN   named:BYTE
        EXTRN   device_hlp:DWORD
        EXTRN   Ginfo_Seg:WORD        ; Global Info Segment
        EXTRN   Ginfo_offset:WORD     ; Global Info Offset
        EXTRN   lsw_phys_add:WORD     ; Real 32 bit address LSW FROM SYSTEM
        EXTRN   msw_phys_add:WORD     ; Real 32 bit address MSW FROM SYSTEM
        EXTRN   device_id:WORD        ; Cards Device ID
        EXTRN   MC_MACHINE:BYTE       ; 1= MC bus Machine 0=ISA bus Machine
        EXTRN   pages:WORD            ; Number of valid pages FROM SYSTEM
        EXTRN   iobase:WORD           ; I/O address base FROM SYSTEM
        EXTRN   iorange:WORD          ; I/O address range FROM SYSTEM
        EXTRN   Intr_level:BYTE       ; Interrupt level number
        EXTRN   Intr_channel:BYTE     ; Interrupt level bits from POS3 (used in reg 5)
        EXTRN   DAC_DEFAULT:BYTE      ; Default Vaules dor DAC
        EXTRN   hue:WORD              ;
        EXTRN   saturation:WORD       ;
        EXTRN   contrast:WORD         ;
        EXTRN   Reg12:BYTE            ;
        EXTRN   TotalBytesinBank:DWORD; Bytes in a Bank on the VCA card
        EXTRN   OI_LIST:DWORD         ; Open Instances List
        EXTRN   OI_CURR:DWORD         ; Current Open Instance









;-------------------------------------------------------------------------------
;Structure of an INIT request packet
;-------------------------------------------------------------------------------
IP       equ   es:[bx]          ;Request packet
INITpkt  struc
         db      ?
         db      ?
_Cmd     db      ?                      ; Command code
_Stat    dw      ?                      ; Status word
         dd      ?
         dd      ?
         db      ?
_DHptr   dd      ?                      ; dev help pointer
_I_parms dd      ?                      ; Parms on "DEVICE=" in config.sys
         db      ?
INITpkt  ends

not_available     equ     22h  ;-222    ; This capture device is not available
;------------------- DEVICE IDs OF SUPPORTED DEVICES --------------------------
VCA_ID         equ  704Eh    ;NTSC version of VCA adapter
VCA_PAL        equ  70CEh    ;PAL version of  VCA adapter

CARD_REL       dw   0        ;Card Postion Relative to other VCA cards
                             ; 1 = first  VCA starting from slot 1 going towards 8
                             ; 2 = Second VCA starting from slot 1 going towards 8

msg_1   db      cr,lf,lf
        db      'OS/2 2.0 Video Capture Adapter/A device driver loaded.  Version .01'
        db      cr,lf
msg_1_len equ   $-msg_1

msg_2   db      cr,lf,lf
        db      'Interrupt Allocation #'
msg_2_n db      '  '
        db      ' - FAILED'
        db      '  RC='
msg_2_r db      '1234 '
        db      cr,lf
msg_2_len equ   $-msg_2

msg_3   db      cr,lf,lf
        db      'Interrupt Allocation #'
msg_3_n db      '  '
        db      ' - OK'
        db      cr,lf
msg_3_len equ   $-msg_3

wlen    dw      ?
parm_es         dw   0       ; parameter packet Selector
parm_bx         dw   0       ; parameter packet Offset

; Possible Names for the PDD
base_name_list  equ $
;                123
        db      ' /1'
        db      ' /2'
        db      ' /3'
        db      ' /4'
        db      ' /5'
        db      ' /6'
        db      ' /7'
        db      ' /8'
        db      ' /9'
        db      ' /1'          ; Default

; Possible Card type for the PDD   " /NTSC" or " /PAL"
base_type_list  equ $
        db      ' /PAL'
        db      ' /NTSC'       ; scan routine need names to be same length

;--------------------------------------------------------------------------
;THE FOLLOWING TABLES ARE IN COORDINATION WITH THE ADF FILE
;used by PS/2 Configurator
;used by PS/2 Configurator
;I/O Base decode table
IOB      dw     5D00h, 5D10h,  7F00h,  7F10h, 0DD00h, 0DD10h, 0FF00h, 0FF10h
;Memory address Base decode.  Low and High of 32 bit address.
;                0      1      2       3        4       5        6        7
PALO     dw   0000h, 4000h, 8000h,  0000h,   0000h,  4000h,   0000h,   0000h
;                8      9     10      11       12      13       14       15
         dw   4000h, 4000h, 8000h,  8000h,  0c000h,  8000h,   0000h,   0000h

PAHI     dw   000dh, 000dh, 000dh,  000dh,   000dh,  000dh,   000dh,   000dh
         dw   000dh, 000dh, 000dh,  000dh,   000ch,  000dh,   000ch,   00f6h
;Number of 16k byte pages used
PGRNG    db      4,     2,     2,      1,       1,      1,       1,       1
         db      1,     1,     1,      1,       1,      1,       1,      40
;------------------------------------------------------------------------
;;I/O Base decode table
;IOB      dw     5D00h, 5D10h,  7F00h,  7F10h, 0DD00h, 0DD10h, 0FF00h, 0FF10h
;;Memory address Base decode.  Low and High of 32 bit address.
;;                0      1      2       3        4       5        6        7
;PALO     dw   0000h, 0000h, 0000h,  0000h,   0000h,  0000h,   4000h,   4000h
;;                8      9     10      11       12      13       14       15
;         dw   0000h, 4000h, 8000h,  0C000h,  0000h,  4000h,   8000h,   0C000h
;
;PAHI     dw   00C0h, 00D0h, 00E0h,  00F0h,   000Ch,  000Dh,   000Ch,   000Dh
;         dw   000Ch, 000Ch, 000Ch,  000Ch,   000Dh,  000Dh,   000Dh,   000Dh
;;Number of 16k byte pages used
;PGRNG    db     40,    40,    40,     40,       4,      4,       2,       2
;         db      1,     1,     1,      1,       1,      1,       1,       1
;;------------------------------------------------------------------------

pos_102      db    0      ;POS register value for adapter FROM SYSTEM
pos_103      db    0      ;POS register value for adapter FROM SYSTEM
pos_104      db    0      ;POS register value for adapter FROM SYSTEM
pos_105      db    0      ;POS register value for adapter FROM SYSTEM
pos_106      db    0      ;POS register value for adapter FROM SYSTEM
pos_107      db    0      ;POS register value for adapter FROM SYSTEM
;--------POS reg information equates
POS_SEL        equ  096h       ; POS select reg
POS0           equ  0100h      ; POS reg 0      Device ID
POS1           equ  0101h      ; POS reg 1      Device ID
POS2           equ  0102h      ; POS reg 2
POS3           equ  0103h      ; POS reg 3      ADF # 1
POS4           equ  0104h      ; POS reg 4      ADF # 2
POS5           equ  0105h      ; POS reg 5      ADF # 3
POS6           equ  0106h      ; POS reg 6
POS7           equ  0107h      ; POS reg 7
CardEnable     equ  01         ; Card enable

REG5_Intr_mask       equ  00111000b     ; Reg 5 interrupt channel mask
mindacval    equ  100h
NTSC_Cal  equ  0                       ; starting reg for NTSC calibration

Intr_table      db   00000000b, 03 ; Interrupt channel conversion table
                db   00001000b, 05 ;  used to convert from card's POS register
                db   00010000b, 07 ;  3 value to actual interrupt level number
                db   00011000b, 09
                db   00100000b, 10
                db   00101000b, 11
                db   00110000b, 12
                db   00111000b, 15

StackUsage      equ $                   ; pg 5-47 of os2 Device Drivers book
  SU_cbStruc    DW 14                   ; Size of structure
  SU_flags      DW ?                    ; Flags
  SU_iIRQ       DW ?                    ; IRQ being handled
  SU_cbStackCLI DW ?                    ; bytes used during CLI
  SU_cbStackSTI DW ?                    ; bytes used during STI
  SU_cbStackEOI DW ?                    ; bytes used during EOI
  SU_cNest      DW ?                    ; Nesting Levels
;StackUsage     ENDS

DATA   ENDS


;*************************************************************************************************************
_TEXT   SEGMENT WORD PUBLIC 'CODE' USE16
        EXTRN   END_OF_CODE:ABS
_TEXT   ENDS


;*************************************************************************************************************
INIT_TEXT SEGMENT WORD PUBLIC 'INITCODE' USE16
        ASSUME cs:INIT_TEXT,ds:DATA,es:NOTHING,ss:NOTHING
subttl Initialization Code
page


;-------------------------------------------------------------------------------
; Initialization procedure is placed at the end of the code so it can go away
;  once initialization has been done.
;-------------------------------------------------------------------------------

Procedure INIT,FAR
        ASSUME cs:INIT_TEXT,ds:DATA,es:NOTHING,ss:NOTHING


;
; Save DevHlp entry point, end-of-segment offsets, and display message...
;
         mov   [parm_es],es             ; save pointer to parameter packet
         mov   [parm_bx],bx             ; save pointer to parameter packet

         mov   [OI_LIST],0h             ; No Open Instances
         mov   [OI_CURR],0h             ; No Current Open Instance
         mov   ax,word ptr IP._DHptr    ; get DevHlp entry point
         mov   word ptr device_hlp,ax   ;
         mov   ax,word ptr IP._DHptr+2  ;
         mov   word ptr device_hlp+2,ax ;

         mov   ax,END_OF_CODE           ; Return end of resident code seg
         mov   word ptr IP._DHptr,ax    ; and data segments
         mov   ax,offset DATA:msg_1
         mov   word ptr IP._DHptr+2,ax  ;

         mov    ax,stdout               ; standard output handle
         push   ax                      ;
         push   ds                      ; address of message
         mov    ax,offset DATA:msg_1
         push   ax
         mov    ax,msg_1_len            ; length of message
         push   ax                      ;
         push   ds                      ; address to word that
         mov    ax,offset DATA:wlen     ; receives bytes written
         push   ax                      ;
         call   DosWrite                ; transfer to OS/2
;
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;**** Find name for Device Driver  and which relative card number**********
        mov   bx,[parm_bx]              ; restore request packet pointer
        mov   es,[parm_es]              ; .
        mov   di,word ptr IP._I_Parms   ; get Device= parms address
        mov   es,word ptr IP._I_Parms+2 ; get Device= parms address
        mov   si, offset base_name_list ; table of possible names for PDD
        mov   bx, 3                     ; Size of an entry in the table
        mov   cx, 9                     ; Number of an entries in the table
        Call  FDEVICE                   ; Find Addr parm on DEVICE=
                                        ; defaults to last name in table
                                        ;  of entries = '1'
        mov   bx,[parm_bx]              ; restore request packet pointer
        mov   es,[parm_es]              ; .

name_found:
        mov   si, offset base_name_list

        cmp   cx,9                      ; 9 = No Match found
        jne   card_rel_provided         ; Card Relative Number was provided
        mov   cx,0                      ; Assume First Relative Card Slot
card_rel_provided:
        mov   card_rel,cx               ; Save Relative card number
        mov   ax,cx
        shl   ax,1
        add   cx,ax
        add   cx,2
        add   si,cx
        mov   al,ds:[si]
        mov   Byte ptr named+6,al       ; Change name of PDD on the fly

        mov   bx,[parm_bx]              ; restore request packet pointer
        mov   es,[parm_es]              ; .

; Read POS registers to determine if adapter is present and whether it is
;   PAL or NTSC.
;
         mov   bx,8                    ; set up to start reading POS
         mov   cx,8                    ;   for 1st of 8 slots in PS/2
T_INIT1: mov   dx,POS_SEL              ; select the POS regs for slot
         mov   al,bl                   ;
         out   dx,al                   ;
         mov   dx,POS1                 ; POS0/POS1 contain card ID
         in    al,dx                   ;
         mov   ah,al                   ;
         dec   dx                      ;
         in    al,dx                   ;
         cmp   ax,VCA_ID               ; is this our card NTSC?
         je    its_a_vca               ; yes, continue initialization
         cmp   ax,VCA_PAL              ; is this our card PAL?
         je    its_a_vca               ; yes, continue initialization
         jmp   Next_card
its_a_vca:
         cmp   Card_Rel,0              ; is this the N th vca card
         je    T_INIT2                 ; yes, correct card - continue initialization
         dec   Card_Rel                ; Relative Card

Next_card:
         inc   bx                      ; bump to next slot
         loop  T_INIT1                 ; go look at next slot
         mov   dx,POS_SEL              ; DESELECT the POS regs for slot
         mov   al,0                    ; Very important to DESELECT when done
         out   dx,al                   ;
         mov   device_id,0             ; save adapter ID of 0...
         mov   ax,not_available        ; . and return error, did not find card
         jmp   T_INITX
T_INIT2:
         mov   device_id,ax            ; save adapter ID found first
         mov   dx,POS6                 ; disable memory before enabling card
         xor   al,al
         out   dx,al
         mov   dx,POS2                 ; ADF #0 set
         in    al,dx                   ; get value of POS2
         or    al,CardEnable           ; set enable bit for normal I/O
         out   dx,al                   ;
         mov   pos_102,al              ; POS2
         mov   bl,al                   ;
         mov   cl,al                   ;
         and   bx,00eh                 ; get rid of lower bit of POS2
         mov   ax,ds:IOB[bx]           ; get IObase based on index in reg 2
         mov   iobase,ax               ; save I/O address
         mov   word ptr iorange,16     ; . and IO range
         mov   bl,cl                   ;
         sub   bh,bh
         shr   bx,1                    ;
         shr   bx,1                    ;
         shr   bx,1                    ;
         shr   bx,1                    ;
         and   bx,0fh                  ;
         shl   bx,1                    ;
         mov   ax,ds:PALO[bx]          ; get Physical address low
         mov   lsw_phys_add,ax
         mov   ax,ds:PAHI[bx]          ; get Physical address high
         mov   msw_phys_add,ax
         shr   bx,1
         sub   eax,eax
         mov   al,ds:PGRNG[bx]         ; get Number of pages
         mov   pages,ax
         xor  edx,edx                 ; clear EDX for multiply
         mov  ebx,16*1024             ; each page is 16K long
         mul  ebx                     ; EAX = number of bytes in Bank
         mov  TotalBytesinBank,EAX    ; save total number of Bytes in a Bank
;
; Read remaining POS registers (3-7) and save
;
;        int   3      ; <<----------------------------<<<<<<<<<<<<
         mov   dx,POS3                 ;
         in    al,dx                   ; get value of POS3
         mov   pos_103,al
         mov   dx,POS4                 ;
         in    al,dx                   ; get value of POS4
         mov   pos_104,al
         mov   dx,POS5                 ;
         in    al,dx                   ; get value of POS5
         mov   pos_105,al
         mov   dx,POS6                 ;
         in    al,dx                   ; get value of POS6 memory should be disabled!
         mov   pos_106,al
         mov   dx,POS7                 ;
         in    al,dx                   ; get value of POS7
         mov   pos_107,al
         mov   dx,POS_SEL              ; deselect the POS regs for slot
         mov   al,0                    ;
         out   dx,al                   ;
         ;-------------------------------------------------------------
         mov   ax,iobase               ; get IOBASE keep in DI a while
         push  di                      ; save the offset to init request packet
         mov   di,ax                   ;
         mov   dx,14                   ;
         add   dx,di                   ; DX = reg 14 (Control register)
         mov   al,0                    ; blank display/cursor
         out   dx,al                   ;
;
; TARAM checkout and initialization
;
; The following code sets all TARAM entries and then reads the TARAM to
; determine if any are not functioning (essentially a diagnostic function).
; If the TARAM is functioning properly, the entries corresponding to the
; physical address range selection from PS/2 configuration are set to
; point to the linear addresses in VCA memory.
;
; Since the TARAM address is split across two registers (6 and 7), TARAM
; access is performed with an inner loop of the 256 possible settings for
; register 7 and an outer loop of the 4 possible settings of register 6
; bits 0 and 1, resulting in access to all 1024 TARAM addresses.
;
; First load the TARAM entries:
;
         mov   bx,0                    ;
T_INIT6: mov   dx,6                    ; set all TARAMs to "disable"
         add   dx,di                   ; DX = reg 6
         mov   al,bl                   ; BX = TARAM quadrant number
         out   dx,al                   ; write TARAM quadrant # to register 6
         in    al,dx                   ;
         mov   cx,256                  ;
T_INIT7: mov   dx,7                    ; next 256 TARAM registers
         add   dx,di                   ; reg 7
         mov   al,cl                   ;
         out   dx,al                   ;
         mov   dx,4                    ;
         add   dx,di                   ; reg 4
         mov   al,0                    ;
         out   dx,al                   ;
         dec   dx                      ; reg 3
         mov   al,120                  ; middle page on screen
         out   dx,al                   ;
         loop  T_INIT7                 ;
         inc   bx                      ;
         cmp   bx,4                    ; loop 4 on 4 banks of 256 TARAM regs
         jb    T_INIT6                 ;
;
; Now read TARAM entries back and see if they are OK
;
         xor   si,si                   ; zero bad counter
         mov   bx,0                    ;
T_INIT8: mov   dx,6                    ; see if all TARAMs are zero AND POINTING TO 240
         add   dx,di                   ; reg 6
         mov   al,bl                   ;
         out   dx,al                   ;
         in    al,dx                   ;
         mov   cx,256                  ;
T_INIT9: mov   dx,7                    ;
         add   dx,di                   ; DX = register 7 (TARAM address)
         mov   al,cl                   ;
         out   dx,al                   ; load TARAM address
         mov   dx,4                    ;
         add   dx,di                   ; DX = register 4 (bank/plane/trans format)
         in    al,dx                   ; read half of TARAM value for this slot
         and   al,0C0h                 ; is it enabled ?
         jnz   err1                    ; if so, go count as bad...
         dec   dx                      ; DX = register 3 (TARAM address)
         in    al,dx                   ; read address portion of TARAM slot
         cmp   al,120                  ; is it pointing to 240 ?
         jne   err1                    ; if not, go count as bad...
         jmp   T_INITA
err1:    inc   si                      ;
T_INITA: loop  T_INIT9                 ; inner loop of 256 TARAM addresses
         inc   bx                      ;
         cmp   bx,4                    ;
         jb    T_INIT8                 ; outer loop 4 times (4*256=1024 addresses)
;
; Exit with error if TARAM entries do not check out OK
;
         mov   bx,di                   ; put IOBASE in BX
         pop   di                      ; restore offset to passed structure
         xchg  ax,si                   ; AX= zero normal, AX>0 bad taram
         or    ax,ax                   ; was there an error
         jnz   T_INITX                 ; yes
;
; Read the values of the EEPROM based on installed mode (NTSC/RGB/YC) and save
; !!! Just assume NTSC for now !!!
;
;        mov   al,reg14                ; Register 14
;        test  al,01h                  ; test for RGB
;        jz    try_yc
;        mov   al,RGB_Cal              ; get starting block of RGB
;        jmp   in_sel
;try_yc:
;        test  al,80h                  ; Test for NTSC
;        jz    try_ntsc
;        mov   al,YC_Cal              ; get starting block of Y/C
;        jmp   in_sel
;try_ntsc:
         mov   al,NTSC_Cal            ; get starting block of NTSC
in_sel:
         push  ds                      ; set ES=DS
         pop   es                      ; .
         lea   di,dac_default          ; offset to 1st reg
         call  rd_blk                  ; read EEPROM factory values
         lea   di,dac_default          ; offset to 1st reg
         call  norm_blk                ; normalize values

         sub   ax,ax                   ; indicate no error


;********************************************************************
;*  Hook into interrupt vector for the card                         *
;********************************************************************

         ;Which Interrupt Vector
;        mov   dx,iobase
;        add   dx,5
;        in    al,dx                  ;
;        mov   cl,al
;        and   al,REG5_Intr_mask

         mov   al,pos_105               ; get the POS register 3 value
         and   al,REG5_Intr_mask        ; retain only interrupt level (note-
                                        ;   bit positions same as register 5)

         push  bx
         mov   bx, offset Intr_Table
                                        ; Note the following loop is "safe"
                                        ; because Intr_Table contains all
                                        ; possible combinations of bits in
                                        ; interrupt level specification - it
                                        ; will always find a match.
next_channel:
         cmp   al,[bx]                  ; Check Interrupt Channel Table
         je    channel_found            ; does the channel match the table
         add   bx,2                     ; Move to next entry in table
         jmp   next_channel             ; Try next Channel in the table

channel_found:                          ; Interrupt Channel found
         mov   Intr_channel, al         ; Save card's interrupt channel bits
         mov   al, [bx+1]               ; Lookup interrupt level in table
         mov   Intr_level, al           ; Save cards Intr Channel Number
         pop   bx

;------------------------------------------------------------
; Attach the DD to IRQ for interrupts
;  Not all PC allow interrupt shareing. We will first try to get the
;  interrupt as Shared and if that fails we try it as Unshared
;  and if that fails the DD will fail the Init
;------------------------------------------------------------
         mov     ax, offset _TEXT:INT_HAND     ; Handler
         sub     bx, bx                        ; zero bx
         mov     bl, Intr_level                ; IRQ channel Number
         mov     dh, 1                         ; Share interrupt
                                               ;   not all PCs support share
         mov     dl, DevHlp_SetIRQ             ; Set the IRQ
         call    device_hlp                    ;
         jnc     got_intr
         mov     ax, offset _TEXT:INT_HAND     ; Handler
         sub     bx, bx                        ; zero bx
         mov     bl, Intr_level                ; IRQ channel Number
         mov     dh, 0                         ; Don't share interrupt
                                               ;   not all PCs support share
         mov     dl, DevHlp_SetIRQ             ; Set the IRQ
         call    device_hlp                    ;
;        mov     ax, 05                        ; assume IRQ linkage failed
         jnc     got_intr

         ; Print out Error Message ..............................
         mov    bl, Intr_level          ; IRQ channel Number
         mov    bh,bl
         shr    bh,4
         and    bh,0Fh
         or     bh,30h
         and    bl,0Fh
         or     bl,30h
         mov   Byte ptr msg_2_n+0,bh    ; Put Intr # in message
         mov   Byte ptr msg_2_n+1,bl
         mov   bl,al
         mov    bh,bl
         shr    bh,4
         and    bh,0Fh
         or     bh,30h
         and    bl,0Fh
         or     bl,30h
         mov   Byte ptr msg_2_r+2,bh    ; Put Intr # in message
         mov   Byte ptr msg_2_r+3,bl
         mov   bl,ah
         mov    bh,bl
         shr    bh,4
         and    bh,0Fh
         or     bh,30h
         and    bl,0Fh
         or     bl,30h
         mov   Byte ptr msg_2_r+0,bh    ; Put Intr # in message
         mov   Byte ptr msg_2_r+1,bl
         mov    ax,stdout               ; standard output handle
         push   ax                      ;
         push   ds                      ; address of message
         mov    ax,offset DATA:msg_2
         push   ax
         mov    ax,msg_2_len            ; length of message
         push   ax                      ;
         push   ds                      ; address to word that
         mov    ax,offset DATA:wlen     ; receives bytes written
         push   ax                      ;
         call   DosWrite                ; transfer to OS/2
         mov     ax, 05                        ; assume IRQ linkage failed
         jmp     T_INITX

got_intr:                                      ; OK we got our Interrupt

         ; Print out Message ..............................
         mov    bl, Intr_level          ; IRQ channel Number
         mov    bh,bl
         shr    bh,4
         and    bh,0Fh
         or     bh,30h
         and    bl,0Fh
         or     bl,30h
         mov   Byte ptr msg_3_n+0,bh    ; Put Intr # in message
         mov   Byte ptr msg_3_n+1,bl
         mov    ax,stdout               ; standard output handle
         push   ax                      ;
         push   ds                      ; address of message
         mov    ax,offset DATA:msg_3
         push   ax
         mov    ax,msg_3_len            ; length of message
         push   ax                      ;
         push   ds                      ; address to word that
         mov    ax,offset DATA:wlen     ; receives bytes written
         push   ax                      ;
         call   DosWrite                ; transfer to OS/2

;------------------------------------------------------------
; Indicate the Stack Usage for the interrupt processor
;------------------------------------------------------------
         mov     bx, offset StackUsage
         mov     SU_flags,       01  ; Handler enables interrupts
         mov     al,           Intr_channel  ; IRQ Channel Number
         mov     ah,     0
         mov     SU_iIRQ,        ax  ; IRQ Channel Number
         mov     SU_cbStackCLI,1000  ; 100 bytes used during CLI
         mov     SU_cbStackSTI, 200  ; 100 bytes used during STI
         mov     SU_cbStackEOI, 200  ; 200 bytes used during EOI
         mov     SU_cNest,       02  ; Nest 2 interrupts
         mov     dl, DevHlp_RegisterStackUsage
         call    device_hlp               ;
         mov     ax, 04                        ; assume Stack usage failed
         jc      T_INITX

;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

;
; Allocate a GDT Selector
;
        mov     ax, ds                          ; es gets upper address
        mov     es, ax
        lea     di, Selector1                   ; Get the Selector Address
        mov     cx, 1                           ; One selector
        mov     dl, DevHlp_AllocGDTSelector
; int 3

        call  device_hlp
        mov     ax,not_available          ; Assume allocate GDT failed
        jc      T_INITX                   ; Exit with error
;
; Get FLAT selector
;
        mov     ax,DOS32FLATDS                  ; Get r/w FLAT selector
        mov     FlatSel,ax                      ; Save for later
        mov     fs,ax                           ; setup flat Selector

;Map Physical Address to GDT selector for all can access (Interrupt and Task time)
        mov     ax,msw_phys_add              ; Physical Address to be mapped
        mov     bx,lsw_phys_add              ; Physical Address to be mapped
        mov     si, Selector1                ; Get the Selector Address
        mov     cx,pages                     ; get number of pages
        shl     cx,14                        ; convert to aperature size
        mov     dl, DevHlp_PhystoGDTSelector
        call  device_hlp
        mov     ax,not_available             ; Assume allocate GDT failed
        jc      T_INITX                      ; Exit with error

        ; Get Addess of DOS Varible (need time info)
        mov     al,1                ; Get Global Info Seg
        mov     dl,DevHlp_GetDOSVar ; Function = GetDOSVar
        call    device_hlp          ; Call DevHlp
        jc      T_INITX_F           ; If Error occured exit with error
        push    es
        mov     es,ax               ; Selector
        les     bx,es:[bx]          ; get pointer  to pointer
        mov     [Ginfo_Seg],bx      ; Global Info Segment
        mov     [Ginfo_offset],es   ; Global Info Offset
        pop     es

        jmp     T_INIT_OK

T_INITX_F:
        mov     ax,not_available      ; Could Not Initialize
        jmp     T_INITX

T_INIT_OK:
         sub   ax,ax                  ; indicate no error


T_INITX:
         mov   bx,[parm_bx]          ; restore request packet pointer
         mov   es,[parm_es]          ; .

         ret
EndProc INIT
;INIT     ENDP

;---------------------------------------------------------------------------
; FDEVICE
;
; Find Parms on the Device= Statement from the Config.Sys
; from a list of items to search for
;
; INPUTS:
;
;   ES:DI = pointer to parms on the DEVICE= statement
;      SI = Pointer to list of Items to search for on the DEVICE=
;      BX = Size of an Entry in the Table SI points to
;      CL = Nuber of Entries in the Table SI points to
;
;
; OUTPUT:
;      CL = Number of the Entry where a match was found
;           (0        = first  entry)
;           (1        = Second entry)
;           (input CX = no match found)
;
;---------------------------------------------------------------------------
FDEVICE proc  near

         mov   dx,si
         mov   ah,cl
find_Item:
         mov   cx,0
         mov   cl,ah                    ; Entries in table
         mov   si,dx                    ; index for base addr table

next_Item:
         push  cx
         push  di
         mov   cx,bx                    ; size of each table entry

next_I_byte:
         mov   al,es:[di]
         cmp   al, 00h                  ; is it the end of data
         je    end_D_parms
         cmp   ds:[si],al
         jne   try_next_I
         inc   di
         inc   si
         loop  next_I_byte              ; Check next byte of Item
         pop   di
         pop   cx
         jmp   valid_Item               ; valid address was coded

try_next_I:
         add   si,cx                    ; Start of next table entry
         pop   di
         pop   cx
         loop  next_Item
         inc   di                       ; next byte in device= statement
         jmp   find_Item

end_D_parms:
         pop   di
         pop   cx
         mov   cx,0                     ; Item not found


valid_Item:

fdevice_exit:
         sub   ah, cl                   ; Entry where match was found
         mov   cl, ah

        ret
FDEVICE endp

;---------------------------------------------------------------------------
; Internal routine to read a value in an EEPROM REG
; INPUTS: al = reg to read
; OUTPUT: AX=value read from a 16 bit EEPROM reg
;---------------------------------------------------------------------------
RD_REG   proc  near
         push  bx                      ; save reg
         push  ax                      ;
         call  IDLE                    ;
         pop   ax                      ;
         mov   ah,OpRead               ;
         call  WOPCODE                 ;
         xor   bx,bx                   ; result
         mov   ah,16                   ; 16 reads
RD_REG1: shl   bx,1                    ;
         call  BEG_RT                  ; put some clocks out
         mov   dx,iobase               ;
         add   dx,8                    ; Register 8
         in    al,dx                   ;
         shr   al,7                    ;
         or    bl,al                   ;
         mov   al,C+SK                 ;
         call  W_R6                    ;
         dec   ah                      ;
         jnz   RD_REG1                 ;
         xchg  ax,bx                   ; put result in ax
         pop   bx                      ; restore reg
         ret                           ;
RD_REG   endp
;---------------------------------------------------------------------------
; RD_BLK
;
; Internal routine to read a block of DAC calibration values from EEPROM
;
; INPUTS:
;   AL = starting register number (NTSC_Cal, RGB_Cal, YC_Cal, User1_DAC,
;          User2_DAC, or User3_DAC)
;
;   ES:DI = starting address of buffer into which DAC values are to be read
;
; OUTPUTS: 9 DAC values written to buffer
;          Other registers preserved
;---------------------------------------------------------------------------
RD_BLK   proc  near                    ;
         push  ax
         push  bx
         push  cx
         push  dx
         push  si
         push  di
         push  es
         push  ds
         xor   bx,bx                   ; bl = starting reg number
         mov   bl,al                   ; get starting block
         mov   si,8                    ; set up to read 8 registers
         call  IDLE                    ;
RD_BLK1: mov   al,bl                   ;
         call  RD_REG                  ;
         stosw                         ;
         inc   bl                      ;
         dec   si                      ;
         jnz   RD_BLK1                 ;
         mov   al,bl                   ; get the 9th register and put split word
         call  RD_REG                  ;
         mov   bl,ah                   ;
         xor   ah,ah                   ;
         stosw                         ; save reg 9: the contrast
         mov   al,reg12                ; update locking value (bits 0-4)
         and   al,0e0h                 ; zero out bits 0-4
         and   bl,1fh                  ; zero out bits 5-7
         or    al,bl                   ;
         mov   reg12,al                ;
         pop   ds
         pop   es
         pop   di
         pop   si
         pop   dx
         pop   cx
         pop   bx
         pop   ax
         ret                           ;
RD_BLK   endp

;-EEPROM equates-----------------------------------------------------------
IdleCnt   equ  100                     ; clocks for idle loop
DelayCnt  equ  10                      ; instructions in a delay sequence
Delay10ms equ  22000                   ; delay of approx 10 millsec
NTSC_Cal  equ  0                       ; starting reg for NTSC calibration
RGB_Cal   equ  9                       ; starting reg for RGB cal. values
YC_Cal    equ  18                      ; starting reg for Y/C cal. values
User1_DAC equ  27                      ; starting reg for user block 1
User2_DAC equ  36                      ; starting reg for user block 2
User3_DAC equ  45                      ; starting reg for user block 3
RevN      equ  62                      ; register containing revision number
CheckSumR equ  63                      ; register containing checksum

IC              equ es:[bp]     ; pointer to structure (like GIX above)
IC_BUMP         equ es:[di]     ; pointer to structure for use with stosw

C      equ    020h                     ; control line via reg 6
SK     equ    010h                     ; clock line via reg 6
DO     equ       8                     ; data line via reg 6

OpRead  equ    080h                    ;    {read 1 16 bit reg}
OpWrite equ    040h                    ;    {write 1 16 bit reg}
OpErase equ    0C0h                    ;    {erase 1 16 bit reg}
OpEWEN  equ    03Fh                    ;    {erase/write enable}
OpEWDS  equ    00Fh                    ;    {erase/write disable}
OpERAL  equ    02Fh                    ;    {erase all}
OpWRAL  equ    01Fh                    ;    {write all}


;---------------------------------------------------------------------------
; Internal routine to write a value to register 6 for EEPROM R/W
; INPUTS: none
; OUTPUT: AL=byte to write
;---------------------------------------------------------------------------
W_R6     proc  near
         mov   dx,iobase               ;
         add   dx,6                    ; register 6
         out   dx,al                   ; clear interrupts
         push  cx                      ;
         mov   cx,DelayCnt             ; get delay count
W_R6a:   loop  W_R6a                   ; delay loop
         pop   cx                      ;
         ret                           ;
W_R6     endp
;---------------------------------------------------------------------------
; Internal routine for a 10ms delay that follows erase/write
; INPUTS: none
; OUTPUT: none
;---------------------------------------------------------------------------
D_10ms   proc  near                    ;
         mov   cx,Delay10ms            ; delay of approx 10 millsec
D_10ms1: loop  D_10ms1                 ; delay loop
         ret                           ;
D_10ms   endp
;---------------------------------------------------------------------------
; Internal routine to do some clocking to EEPROM
; INPUTS: none
; OUTPUT: none
;---------------------------------------------------------------------------
BEG_RT   proc  near
         mov   al,C                    ;
         call  W_R6                    ;
         call  W_R6                    ;
         mov   al,C+SK                 ;
         call  W_R6                    ;
         ret                           ;
BEG_RT   endp
;---------------------------------------------------------------------------
; Internal routine for terminal sequence for Enable/disable command
; INPUTS: none
; OUTPUT: none
;---------------------------------------------------------------------------
TERM     proc  near
         mov   cx,1                    ;
         jmp   short IDLE1             ;
TERM     endp                          ;
;---------------------------------------------------------------------------
; Internal routine for idle loop that precedes every sequence
; INPUTS: none
; OUTPUT: none
;---------------------------------------------------------------------------
IDLE     proc  near
         mov   cx,IdleCnt              ;
IDLE1:   mov   al,0                    ;
         call  W_R6                    ;
         call  W_R6                    ;
         mov   al,SK                   ;
         call  W_R6                    ;
         call  W_R6                    ;
         loop  IDLE1                   ;
         ret                           ;
IDLE     endp                          ;
;---------------------------------------------------------------------------
; Internal routine for writing an EEPROM OP code
; INPUTS: AH= Opcode
;         AL = reg number (0 to 63)
; OUTPUT: none
;---------------------------------------------------------------------------
WOPCODE  proc  near
         push  bx                      ; save reg
         push  di                      ; save reg
         push  ax                      ; save OP code
         mov   bl,ah                   ;
         or    bl,al                   ; combine OP code + reg number
         mov   al,0                    ;
         call  W_R6                    ;
         mov   al,C                    ;
         call  W_R6                    ;
         mov   al,C+SK                 ;
         call  W_R6                    ;
         call  W_R6                    ;
         mov   al,C                    ;
         call  W_R6                    ;
         mov   al,C+DO                 ;
         call  W_R6                    ;
         or    al,SK                   ;
         call  W_R6                    ;
         call  W_R6                    ;
         mov   di,8                    ; start bit + OP code + reg number
WOP1:    xor   bh,bh                   ;
         shl   bx,1                    ;
         shl   bh,3                    ;
         mov   al,C                    ;
         or    al,bh                   ;
         call  W_R6                    ;
         call  W_R6                    ;
         or    al,SK                   ;
         call  W_R6                    ;
         call  W_R6                    ;
         dec   di                      ;
         jnz   WOP1                    ;
         pop   ax                      ;
         pop   di                      ; restore bx
         pop   bx                      ; restore bx
         cmp   ah,OpEWEN               ; is this a erase/write enable
         je    WOP2                    ; yes
         cmp   ah,OpEWDS               ; is this a erase/write disable
         je    WOP2                    ; yes
         jmp   D_10ms                  ; delay 10 ms for other op codes
WOP2:    call  BEG_RT                  ;
         call  W_R6                    ;
         jmp   TERM                    ;
WOPCODE  endp
;---------------------------------------------------------------------------
; NORM_BLK
;
; Normalize values if valid between 0 for lowest to 1023 for highest
;
; INPUTS:
;
;   ES:DI = pointer to DAC calibration values to normalize
;
; OUTPUT: none
;---------------------------------------------------------------------------
NORM_BLK proc near
         mov   bx,03ffh
         mov   cx,6                   ; the 6 RGB values need to be 1023-current value
rgbnorm: mov   ax,bx
         sub   ax,IC_BUMP             ; subtract from 1023 the register value
         jge   eepgood
         mov   ax,mindacval           ; use min value if result is negative
eepgood: stosw                        ; save normalized value
         loop  rgbnorm
         mov   ax,7                   ; contrast is 7- current value * 128;
         sub   ax,contrast            ; offset to 1st reg
         mov   cl,7                   ;
         shl   ax,cl                  ;
         mov   contrast,ax            ; offset to 1st reg
         ret
NORM_BLK endp


INIT_TEXT ENDS
END
