;*DDK*************************************************************************/
;
; COPYRIGHT (C) Award Software International Inc., 1994
; 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.;
;*****************************************************************************/
                name    SSPCICWM
                page    60, 132
                title   'SSPCICWM'
;******************************************************************************
;*
;*                            File SSPCICWM.ASM
;*
;*                        Socket Services PCIC File
;*
;*                           Window management
;*
;*
;*
;******************************************************************************

                include ssmac.inc           ; Macros
                include ssdefs.inc          ; Sockets Services definitions
                include ss_segm.inc         ; Segment definitions
                include ssPCIC.inc          ; PCIC module defs

ifndef SUPPORT_0WS
SUPPORT_0WS     equ     0                   ; 1 - enable  0WS support
                                            ; 0 - disable 0WS support
endif


;*****************************************************************************
;*                         --- Segment ResData ---
;*****************************************************************************
sBegin          ResData

;----------------------------- Window capabilities ----------------------------

MemWndInfo      MEMWINTBL {PCIC_MWCAP, PCIC_MADDR_F, PCIC_MADDR_L, PCIC_MSIZE_MIN, \
                           PCIC_MSIZE_MAX, PCIC_MREQGRAN, PCIC_MBASE, PCIC_MOFFSET,\
                           SPEED_0250_NS, SPEED_1200_NS                    \
                }

MemWndInfoLen   =       SIZEOF  MemWndInfo

IOWndInfo       IOWINTBL  {PCIC_IWCAP, PCIC_IADDR_F, PCIC_IADDR_L, PCIC_ISIZE_MIN,  \
                           PCIC_ISIZE_MAX, PCIC_IREQGRAN, PCIC_IADDLINES,         \
                           PCIC_IEISA                                         \
                }

IOWndInfoLen    =       SIZEOF  IOWndInfo

;----------------------------- Memory Window Speed ----------------------------

Mem16Speed0     label   BYTE                ; Memory 16 bit access, 0WS
                db      SPEED_0250_NS       ;  0 WS - 250 ns
Num16MemSpeeds0 =       $ - OFFSET Mem16Speed0

Mem16Speed      label   BYTE                ; Memory 16 bit access
                db      SPEED_0400_NS       ;  0 WS - 375 ns
                db      SPEED_0500_NS       ;  1 WS - 500 ns
                db      SPEED_0600_NS       ;  2 WS - 625 ns
                db      SPEED_0800_NS       ;  3 WS - 750 ns
Num16MemSpeeds  =       $ - OFFSET Mem16Speed

Mem08Speed0     label   BYTE                ; Memory 8 bit access, 0WS
                db      SPEED_0500_NS       ;  0 WS - 500 ns
Num08MemSpeeds0 =       $ - OFFSET Mem08Speed0

Mem08Speed      label   BYTE                ; Memory 8 bit access
                db      SPEED_0800_NS       ;  0 WS - 750 ns
                db      SPEED_1000_NS       ;  1 WS - 875 ns
                db      SPEED_1000_NS       ;  2 WS - 1.0 ęs
                db      SPEED_1200_NS       ;  3 WS - 1.125 ęs
Num08MemSpeeds  =       $ - OFFSET Mem08Speed

IO16Speed0      label   BYTE                ; I/O 16 bit access, 0WS
Num16IOSpeeds0  =       $ - OFFSET IO16Speed0

IO16Speed       label   BYTE                ; I/O 16 bit access
                db      SPEED_0400_NS       ;  0 WS - 375 ns
                db      SPEED_0500_NS       ;  1 WS - 500 ns
Num16IOSpeeds   =       $ - OFFSET IO16Speed

IO08Speed0      label   BYTE                ; I/O 8 bit access, 0WS
                db      SPEED_0500_NS       ;  0 WS - 500 ns
Num08IOSpeeds0  =       $ - OFFSET IO08Speed0

IO08Speed       label   BYTE                ; I/O 8 bit access
                db      SPEED_0800_NS       ;  0 WS - 750 ns
Num08IOSpeeds   =       $ - OFFSET IO08Speed

SpeedTable      label   WORD
MemSpeedTable   label   WORD
                dw      Mem08Speed
                dw      Num08MemSpeeds
                dw      Mem08Speed0
                dw      Num08MemSpeeds0
                dw      Mem16Speed
                dw      Num16MemSpeeds
                dw      Mem16Speed0
                dw      Num16MemSpeeds0
IOSpeedTable    label   WORD
                dw      IO08Speed
                dw      Num08IOSpeeds
                dw      IO08Speed0
                dw      Num08IOSpeeds0
                dw      IO16Speed
                dw      Num16IOSpeeds
                dw      IO16Speed0
                dw      Num16IOSpeeds0

sEnd            ResData

;*****************************************************************************
;*                         --- Segment ResCode ---
;*****************************************************************************
sBegin          ResCode


;*****************************************************************************
;*                          --- cowDisableWindow ---
;*
;*     Purpose: Disable window
;*       Input: [BP] = Ptr to ARGS structure
;*      Output: none
;* Scratch reg: none
;*     Written: by Alexis A.Piatetsky 03.05.94
;*****************************************************************************
cowDisableWindow PROC    NEAR

                pushx   <ax, cx>

                call    asGetWindowCtrl     ; al - register index
                not     ah                  ; ah - disable mask

                mov     cx, ax              ; Save it
                call    GetReg              ; al - register contents

                and     al, ch              ; Mask out enable bit
                mov     ah, al              ; ah - new contents
                mov     al, cl              ; al - register index
                call    SetReg              ; Write out

                popx    <cx, ax>
                ret
cowDisableWindow ENDP

;*****************************************************************************
;*                          --- cowEnableWindow ---
;*
;*     Purpose: Enable window
;*       Input: [BP] = Ptr to ARGS structure
;*      Output: none
;* Scratch reg: none
;*     Written: by Alexis A.Piatetsky 03.05.94
;*****************************************************************************
cowEnableWindow PROC    NEAR

                pushx   <ax, cx>

                call    asGetWindowCtrl     ; al - register index
                                            ; ah - enable mask

                mov     cx, ax              ; Save it
                call    GetReg              ; al - register contents

                or      al, ch              ; Set enable bit
                mov     ah, al              ; ah - new contents
                mov     al, cl              ; al - register index
                call    SetReg              ; Write out

                popx    <cx, ax>
                ret
cowEnableWindow ENDP

;*****************************************************************************
;*                         --- cowIsWinEnabled ---
;*
;*     Purpose: Check, if Window is enabled
;*       Input: [BP] = Ptr to ARGS structure
;*      Output: NZ - if enabled, ZR - if disabled
;* Scratch reg: none
;*     Written: by Alexis A.Piatetsky 03.05.94
;*****************************************************************************
cowIsWinEnabled PROC    NEAR

                pushx   <ax, cx>

                call    asGetWindowCtrl     ; al - register index
                                            ; ah - enable mask
                mov     cx, ax              ; Save it
                call    GetReg              ; al - register contents

                and     al, ch              ; Check enable bit

                popx    <cx, ax>
                ret

cowIsWinEnabled ENDP


;*****************************************************************************
;*                            --- cowValWinPars ---
;*
;*     Purpose: Validate Window parameters
;*       Input: [BP] = Pointer to entry args on stack
;*              [BX] = Pointer to adapter entry in Adapters array
;*      Output: If success: NC and:
;*                      ah - Speed
;*                      al - Requested Attributtes
;*                      dx - Window Start address
;*                      cx - Window End address
;*              If fail: CY and AH - RETCODE
;* Scratch reg: none
;*     Written: by Alexis A.Piatetsky 29.07.94
;*****************************************************************************
cowValWinPars   PROC    NEAR

                mov     al, (ARGS PTR [BP]).DHReg ; Window state
                cmp     (ARGS PTR [BP]).bWindowType, WIN_IO
                je      vwp_check_io

; Validate memory window ----------

                test    al, WS_IO
                jnz     vwp_bad_type

                mov     si, offset MemWndInfo ; Establish pointer to WIN_INFO

                jmp     short val_args

; Validate I/O window ----------

vwp_check_io:   test    al, WS_IO
                jz      vwp_bad_type

                mov     si, offset IOWndInfo ; Establish pointer to
                                            ; WIN_INFO structure

;--------- We profite the match of beginning of MEMWINTBL and IOWINTBL --------

val_args:       mov     ah, byte ptr (WIN_INFO PTR [si]).m.MemWndCaps
                not     ah                  ; ah - mask of unsupported bits
                push    ax
                and     al, ah
                pop     ax
                jnz     vwp_bad_attr

;--------------------------- Validate base and size ---------------------------

                mov     cx, (ARGS PTR [BP]).CXReg ; Get requested size
                cmp     cx, (WIN_INFO PTR [SI]).m.MinSize ; Below minimum ?
                jb      vwp_bad_size        ; No, continue

                cmp     cx, (WIN_INFO PTR [SI]).m.MaxSize ; Above maximum ?
                ja      vwp_bad_size        ; Yes, error out

                mov     dx, (ARGS PTR [BP]).DIReg ; Get requested base
                cmp     dx, (WIN_INFO PTR [SI]).m.FirstByte ; Below first address ?
                jb      vwp_bad_base

                add     cx, dx              ; Add base to size
                dec     cx                  ; Less one for last address
                cmp     cx, (WIN_INFO PTR [SI]).m.LastByte ;     base ?
                ja      vwp_bad_base        ; Yes, error out

;-------------------------- Validate requested speed --------------------------

                mov     ah, (ARGS PTR [BP]).DLReg
                test    al, WS_IO           ; No meaning for I/O window
                jnz     @f

                call    couIsValidSpeed     ; Check speed value
                jc      vwp_bad_speed

@@:             clc
                jmp     short vwp_done

vwp_bad_speed:  mov     ah, BAD_SPEED
                jmp     vwp_fail

vwp_bad_type:   mov     ah, BAD_TYPE
                jmp     vwp_fail

vwp_bad_size:   mov     ah, BAD_SIZE
                jmp     short vwp_fail

vwp_bad_base:   mov     ah, BAD_BASE
                jmp     short vwp_fail

vwp_bad_attr:   mov     ah, BAD_ATTRIBUTE
;               jmp     short vwp_fail

vwp_fail:       stc
vwp_done:       ret
cowValWinPars   ENDP

COMMENT ~*********************************************************************
        Procedure:      GetWndReg
        Revision:       1
        Date:           05/25/1993
        Purpose:        Read a TI window register
        Entry:          [AL] = Offset of register to read
        Exit:           [AL] = Data read
*****************************************************************************~
GetWndReg       PROC    NEAR

                add     al, (ARGS PTR [BP]).bWindowIdx
                call    GetReg
                ret
GetWndReg       ENDP

COMMENT ~*********************************************************************
        Procedure:      SetWndReg
        Revision:       1
        Date:           05/25/1993
        Purpose:        Write a TI window register
        Entry:          [AL] = Offset of register to write
                        [AH] = Data to write
        Exit:           [AL] = Data written
*****************************************************************************~
SetWndReg       PROC    NEAR

                add     al, (ARGS PTR [BP]).bWindowIdx
                call    SetReg
                ret

SetWndReg       ENDP

COMMENT ~*********************************************************************
        Procedure:      CalcWndIndex
        Revision:       4
        Date:           05/25/1993
        Purpose:        Calculate window arguments
        Entry:          [AL] = Window number (base zero on adapter)
                        [BP] = Ptr to ARGS structure
                        [BX] = Ptr to adapter data structure
        Exit:           No significant registers
        Note:           Sets bWindowIdx, bWindowNum and bSocketNum
                         in ARGS structure as appropriate
                        Window number MUST be valid!
*****************************************************************************~
CalcWndIndex    PROC    NEAR

                pushx   <ax, cx, si>

;------------------------ Get Socket and window number ------------------------

                xor     ah, ah
                mov     cx, PCIC_WIN_PER_SKT
                div     cl                  ; ah - Window number on socket
                                            ; al - Socket number
                mov     (ARGS PTR [BP]).bSocketNum, al
                mov     al, ah
                xor     ah, ah

;------------------------------ Get Window Index ------------------------------

                cmp     al, PCIC_MEMWIN_PER_SKT ; Memory Window?
                jb      @f                  ; Yes, setup memory window

; I/O WIndow ----------

                sub     al, PCIC_MEMWIN_PER_SKT
                mov     (ARGS PTR [BP]).bWindowType, WIN_IO
                mov     cx, PCIC_IOWININC
                mov     si, PCIC_IOWIN0
                jmp     short cwi_calc

; Mem Window ----------

@@:
                mov     (ARGS PTR [BP]).bWindowType, WIN_MEM
                mov     cx, PCIC_MEMWININC
                mov     si, PCIC_MEMWIN0

; Actually al - Window number, cx - window increment, si - window base

cwi_calc:       mov     (ARGS PTR [BP]).bWindowNum, al  ; Save window number
                mul     cl
                add     ax, si
                mov     (ARGS PTR [BP]).bWindowIdx, al
                popx    <si, cx, ax>
                ret
CalcWndIndex    ENDP

;*****************************************************************************
;*                          --- asGetWindowCtrl ---
;*
;*     Purpose: Return number of window control register
;*       Input: [BP] = Ptr to ARGS structure
;*      Output: al   - index of window control
;*              ah   - Window enable mask
;* Scratch reg: AX
;*     Written: by Alexis A.Piatetsky 03.05.94
;*****************************************************************************
asGetWindowCtrl PROC    NEAR

                mov     ah, 00000001b
                cmp     (ARGS PTR [BP]).bWindowType, WIN_MEM
                je      @f                  ; I/O window


                mov     ah, 01000000b

@@:             mov     cl, (ARGS PTR [BP]).bWindowNum
                shl     ah, cl

                mov     al, PCIC_WINDOW
                ret
asGetWindowCtrl ENDP

COMMENT ~*********************************************************************
        Procedure:      InquireWindow
        Revision:       2
        Date:           05/25/1993
        Purpose:        Return window capabilities
        Entry:          [BP] = Pointer to entry args on stack
                        [BX] = Pointer to adapter entry in Adapters array
                        [ES]:[DI] = Client-supplied buffer for characteristics
        Exit:           Args.BLReg = Window Capabilities (set = true)
                          WC_COMMON     (Bit 0)    = Common memory
                          WC_ATTRIBUTE  (Bit 1)    = Attribute memory
                          WC_IO         (Bit 2)    = I/O
                          WC_WAIT       (Bit 7)    = WAIT supported
                          All other bits are reserved and are reset to zero (0)
                        Args.CXReg = Bit-map of assignable sockets
                        Client-supplied buffer filled with window characteristics
*****************************************************************************~
InquireWindow   PROC    NEAR

;----------------------- Copy WIndow Info to the buffer -----------------------

                mov     cx, MemWndInfoLen       ; Get length of memory window data
                mov     si, OFFSET MemWndInfo   ; Point to source of data
                mov     al, PCIC_MEMWINCAPS     ; Indicate Mem Window
                cmp     (ARGS PTR [BP]).bWindowType, WIN_IO
                jne     @f


                mov     al, PCIC_IOWINCAPS      ; Indicate I/O window and wait
                mov     cx, IOWndInfoLen        ; Get length of I/O window data
                mov     si, offset IOWndInfo    ; Point to source of data

@@:             MOV     (ARGS PTR [BP]).BLReg, al ; Return capabilities
                call    couCopyInfo

;--------------------- Create assignable sockets bit-mask ---------------------

                xor     ah, ah
                mov     al, 1
                mov     cl, (ARGS PTR [BP]).bSocketNum
                jcxz    @f
                shl     ax, CL

@@:             mov     (ARGS PTR [BP]).CXReg, ax
                mov     ah, SUCCESS
                ret

InquireWindow   ENDP

COMMENT ~*********************************************************************
        Procedure:      GetWindow
        Revision:       3
        Date:           05/25/1993
        Purpose:        Return current window configuration
        Entry:          [BP] = Pointer to entry args on stack
                        [BX] = Pointer to adapter entry in Adapters array
        Exit:           Args.BLReg = Socket (0 .. 16)
                        Args.CXReg = Window Size (Bytes for I/O, 4K units for memory)
                        Args.DHReg = Window State (set to one = true, unless noted)
                          Bit 0    = Window type (reset = memory, set = I/O)
                          If Bit 0 reset to zero (0) - memory window
                            Bit 1  = Memory type (reset = common, set = attribute)
                          If Bit 0 set to one (1) - I/O window
                            Bit 1  = EISA Mapped
                          Bit 2    = Enabled
                          Bit 3    = Data Width (reset = 8-bit, set = 16-bit)
                          If Bit 0 reset to zero (0) - memory window
                            Bit 4  = Subdivided into 16K pages (memory-only)
                            Bit 5  = Reserved (reset to zero)
                            Bit 6  = Software Write-Protected
                          If Bit 0 set to one (1) - I/O window
                            Bit 4  = Reserved (reset to zero)
                            Bit 5  = EISA Non-specific access slot enabled
                          All other bits are reserved and are reset to zero (0)
                        Args.DLReg = Actual Access Speed
                        Args.DIReg = Base Address (Bytes for I/O, 4K units for memory)
*****************************************************************************~
GetWindow       PROC    NEAR

;--------------------------- Return assigned socket ---------------------------

                mov     al, (ARGS PTR [BP]).bSocketNum
                mov     (ARGS PTR [BP]).BLReg, al

;------------------------- Start building Window state ------------------------

                xor     ah, ah              ; Set default state
                call    cowIsWinEnabled
                jz      @f

                or      ah, WS_ENABLED      ; Yes, indicate enabled

@@:             cmp     (ARGS PTR [BP]).bWindowType, WIN_IO
                je      gw_GetIO            ; Get I/O window

;------------------------------ Get Memory Window -----------------------------

                push    ax
                mov     al, PCIC_MEMWIN_STR_L
                call    GetWndReg
                mov     dl, al              ; DL holds PCIC_MEMWIN_STR_L
                mov     al, PCIC_MEMWIN_STR_H
                call    GetWndReg
                mov     dh, al              ; DH holds PCIC_MEMWIN_STR_H

                mov     al, PCIC_MEMWIN_END_L
                call    GetWndReg
                mov     cl, al              ; CL holds PCIC_MEMWIN_END_L
                mov     al, PCIC_MEMWIN_END_H
                call    GetWndReg
                mov     ch, al              ; CH holds PCIC_MEMWIN_END_H
                pop     ax

; Determine data path width and access size ----------

                mov     si, offset MemSpeedTable
                test    dh, PCIC_MEMWIN_M16 ; 16-bit?
                jz      @f                  ; No, skip next

                or      ah, WS_16BIT        ; Yes, indicate 16-bit data size
                add     si, 8               ; Skip 8-bit tables

@@:             test    dh, PCIC_MEMWIN_0WS ; 0WS?
                jz      @f

                add     si, 4               ; Go to 0 WS table
                mov     si, [si]            ; Load the table offset
                mov     al, [si]            ; Only one value is possible
                jmp     short gw_gb

@@:             mov     si, [si]            ; Load the table offset
                push    ax
                push    cx
                mov     al, ch              ; al - PCIC_MEMWIN_END_H
                and     ax, PCIC_MEMWIN_WS  ; Mask in wait state bits, ah = 0
                mov     cl, 6
                shr     al, cl
                pop     cx
                add     si, ax              ; Create pointer to the speed table
                pop     ax
                mov     al, [si]            ; Get speed from the table

; Determine window base and size ----------

gw_gb:          and     cx, PCIC_MEMWIN_MSK
                and     dx, PCIC_MEMWIN_MSK

                sub     cx, dx              ; AdressEnd - AddressBegin
                inc     cx                  ; + 1

; Now: ah - Window attr, al - Speed, dx - base, cx - size

                jmp     short gw_save

;--------------------------------- I/O WIndow ---------------------------------

gw_GetIO:       or      ah, WS_IO           ; No, indicate I/O window
                mov     si, ax              ; Save state
                mov     al, PCIC_IOWIN_STR_H
                call    GetWndReg
                mov     dh, al              ; dh holds PCIC_IOWIN_STR_H
                mov     al, PCIC_IOWIN_STR_L
                call    GetWndReg
                mov     dl, al              ; dl holds PCIC_IOWIN_STR_L

                mov     al, PCIC_IOWIN_END_H
                call    GetWndReg
                mov     ch, al              ; ch holds PCIC_IOWIN_END_H
                mov     al, PCIC_IOWIN_END_L
                call    GetWndReg
                mov     cl, al              ; cl holds PCIC_IOWIN_END_L

; Determine data path width and access size ----------

                mov     al, PCIC_IOWIN_CTRL
                call    GetReg              ; al - hold I/O Window control

                cmp     (ARGS PTR [BP]).bWindowNum, 1
                jb      @f

                push    cx
                mov     cl, 4
                shr     al, cl
                pop     cx

@@:             xchg    dx, si              ; Return window state to ah
                mov     ah, dh
                xchg    dx, si              ; al - still hold window control

                mov     si, offset IOSpeedTable
                test    al, PCIC_IOWIN_IO16 ; 16-bit data path ?
                jz      @f

                or      ah, WS_16BIT        ; Yes, indicate 16-bit data size
                add     si, 8               ; Skip 8-bit tables
                mov     si, [si]            ; Load table offset
                test    al, PCIC_IOWIN_WS   ; Mask in wait state bits
                jz      short gw_getiosp    ; Jump, if no wait

                inc     si                  ; Only one wait state is possible
                jmp     short gw_getiosp

@@:             test    al, PCIC_IOWIN_0WS  ; 8-bit 0WS ?
                jz      @f                  ; No, skip next

                add     si, 4               ; Move to 0WS table

@@:             mov     si, [si]            ; Load table offset, only one value
                                            ; is possible
gw_getiosp:     mov     al, [si]

; Determine window base and size ----------

                sub     cx, dx              ; AdressEnd - AddressBegin
                inc     cx                  ; + 1

; Now: ah - Window attr, al - Speed, dx - base, cx - size

;--------------------- Save window parameters in user regs --------------------


gw_save:        mov     (ARGS PTR [BP]).CXReg, cx
                mov     (ARGS PTR [BP]).DIReg, dx
                mov     (ARGS PTR [BP]).DLReg, al
                mov     (ARGS PTR [BP]).DHReg, ah
                mov     ah, SUCCESS
                ret
GetWindow       ENDP

;*****************************************************************************
;*                           --- SetupMemWin ---
;*
;*     Purpose: Setup Memory window
;*       Input: dx - Window Start, cx - Window end
;*              [BP] = Pointer to entry args on stack
;*              [BX] = Pointer to adapter entry in Adapters array
;*      Output: none
;* Scratch reg: none
;*     Written: by Alexis A.Piatetsky 09.05.94
;*****************************************************************************
SetupMemWin     PROC    NEAR

                pushx   <si, dx, ax>
                call    cowDisableWindow

;----------- Read Old Base to establish change required for offset  -----------

                mov     al, PCIC_MEMWIN_STR_H
                call    GetWndReg
                mov     ah, al
                mov     al, PCIC_MEMWIN_STR_L
                call    GetWndReg               ; AX = old START address
                and     ax, PCIC_MEMWIN_MSK
                mov     si, ax                  ; SI = old START address

                mov     ax, dx                  ; AX = new START address
                and     ax, PCIC_MEMWIN_MSK
                sub     si, ax                  ; SI = (old - new)

;------------------ Establish window start and stop addresses -----------------

                mov     ah, dl
                mov     al, PCIC_MEMWIN_STR_L
                CALL    SetWndReg

                mov     ah, dh
                mov     al, PCIC_MEMWIN_STR_H
                call    SetWndReg

                mov     ah, cl
                mov     al, PCIC_MEMWIN_END_L
                call    SetWndReg

                mov     ah, ch
                mov     al, PCIC_MEMWIN_END_H
                call    SetWndReg

;-------------------------- Finish Adjusting Offset  --------------------------

                mov     al, PCIC_MEMWIN_OFF_H
                CALL    GetWndReg
                mov     ah, al

                mov     al, PCIC_MEMWIN_OFF_L
                call    GetWndReg

                mov     dx, ax

                add     ax, si                  ; add changes
                and     ax, PCIC_MEMWIN_OMSK

                and     dh, PCIC_MEMWIN_ATTR    ; Map to correct type of memory
                xor     dl, dl
                or      ax, dx

                mov     dx, ax

                mov     al, PCIC_MEMWIN_OFF_H
                call    SetWndReg

                mov     ah, dl
                mov     al, PCIC_MEMWIN_OFF_L
                call    SetWndReg

                popx    <ax, dx, si>
                ret
SetupMemWin     ENDP

;*****************************************************************************
;*                            --- SetupIOWin ---
;*
;*     Purpose: Setup I/O window
;*       Input: dx - Window Start, cx - Window end, ah - Window attributtes
;*              [BP] = Pointer to entry args on stack
;*              [BX] = Pointer to adapter entry in Adapters array
;*      Output: none
;* Scratch reg: none
;*     Written: by Alexis A.Piatetsky 09.05.94
;*****************************************************************************
SetupIOWin      PROC    NEAR

                push    dx

                push    ax                  ; Save attributes
                call    cowDisableWindow

                mov     al, PCIC_IOWIN_STR_L
                mov     ah, dl
                call    SetWndReg

                mov     al, PCIC_IOWIN_STR_H
                mov     ah, dh
                call    SetWndReg

                mov     al, PCIC_IOWIN_END_L
                mov     ah, cl
                call    SetWndReg

                mov     al, PCIC_IOWIN_END_H
                mov     ah, ch
                call    SetWndReg

                mov     al, PCIC_IOWIN_CTRL
                call    GetReg
                mov     ah, 0F0h            ; Assume Window 0
                cmp     (ARGS PTR [BP]).bWindowNum, 1
                jne     @f                  ; If Window 0

                mov     ah, 0Fh             ; Mask out Window 1

@@:             and     ah, al              ; Mask out our Window bits
                pop     dx                  ; dh - Window attributes
                or      ah, dh              ; Combine with other window
                mov     al, PCIC_IOWIN_CTRL
                call    SetReg
                mov     ax, dx
                pop     dx
                ret
SetupIOWin      ENDP

COMMENT ~*********************************************************************
        Procedure:      SetWindow
        Revision:       9
        Date:           09/22/1993
        Purpose:        Configure window
        Entry:          [BP] = Pointer to entry args on stack
                        [BX] = Pointer to adapter entry in Adapters array
                        Args.BLReg = Socket (0 .. 3)
                        Args.CXReg = Window Size (Bytes for I/O, 4K units for memory)
                        Args.DHReg = Window State (set to one = true, unless noted)
                          Bit 0    = Window type (reset = memory, set = I/O)
                          Bit 1    = Enabled
                          Bit 2    = Data Width (reset = 8-bit, set = 16-bit)
                          If Bit 0 reset to zero (0) - memory window
                            Bit 3  = Subdivided into 16K pages (memory-only)
                          If Bit 0 set to one (1) - I/O window
                            Bit 3  = EISA Mapped
                            Bit 4  = EISA Non-specific access slot enabled
                          All other bits are reserved and are reset to zero (0)
                        Args.DLReg = Requested Access Speed (memory windows only)
                        Args.DIReg = Base Address (Bytes for I/O, 4K units for memory)
        Exit:           Args.AHReg = Return Code
                        If BAD_ATTRIBUTE, Window State invalid
                        If BAD_BASE, starting address is invalid
                        If BAD_SIZE, window size is invalid
                        If BAD_SPEED, requested speed is too slow
                        If BAD_TYPE, window does not support requested type
*****************************************************************************~
SetWindow       PROC    NEAR

;------------------------- Always force full decoding -------------------------

                mov     al, PCIC_WINDOW
                call    GetReg
                or      al, PCIC_WINDOW_A23A12
                mov     ah, al
                mov     al, PCIC_WINDOW
                call    SetReg

;---------------------- Force 16 bit memory delay inhibit ---------------------

                mov     al, PCIC_CDGCR
                call    GetReg
                or      al, PCIC_CDGCR_16BITMDI
                mov     ah, al
                mov     al, PCIC_CDGCR
                call    SetReg

;-------------------- Validate window is mappable to socket -------------------

                mov     al, (ARGS PTR [BP]).bSocketNum
                cmp     (ARGS PTR [BP]).BLReg, al
                jne     sw_bad_socket

                call    cowValWinPars
                jc      sw_done

; Now ah - Speed, al - Requested Attributtes,
; dx - Window Start address, cx - Window End address

                mov     si, offset SpeedTable
                test    al, WS_IO           ; I/O window ?
                jz      @f                  ; No, continue

                mov     ah, 1               ; Use default 1 WS only
                jmp     short sw_at         ; Skip speed calculation

@@:             test    al, WS_16BIT        ; 16 bit?
                jz      sw_getws            ; No, continue

                add     si, 8

sw_getws:       push    cx                  ; Window end
                push    si                  ; Save table offset

                mov     cx, [si + 2]        ; Table length
                mov     si, [si]            ; Table offset

                push    ax                  ; Save Attributes
                push    cx                  ; Save table size

@@:             lodsb                       ; Get first table speed
                call    couCompSpeed        ; Compare
                jbe     sw_speed_ok
                loop    @b

                add     sp, 8               ; Discard pars in stack
;               jmp     short sw_bad_speed

;------------------------------ Error Dispatcher ------------------------------

sw_bad_speed:   mov     ah, BAD_SPEED
                jmp     sw_done

sw_bad_socket:  mov     ah, BAD_SOCKET
                jmp     sw_done

sw_speed_ok:    mov     si, cx
                pop     cx
                sub     cx, si              ; cx - number of table entry

                pop     ax                  ; Restore attributes in al
                mov     ah, cl              ; AH - number of WS
                pop     si
                pop     cx

; If we received 0 WS here, we probably can have better speed by forcing
; 0 WS signal. This method is not recomended for 16-bit memory window

                or      ah, ah              ; 0 WS?
if SUPPORT_0WS
                jnz     sw_at               ; No, we are ok
else
                jmp     short sw_at         ; Ignore 0WS tables
endif
                add     si, 4               ; Point to corresponding 0WS table

                test    al, WS_IO           ; I/O window?
                jz      @f                  ; No, use short cycle

                test    al, WS_16BIT        ; 16-bit IO?
                jnz     sw_at               ; Yes, don't use short cycle

@@:             mov     si, [si]
                push    ax                  ; Save value
                mov     ah, (ARGS PTR [BP]).DLReg
                lodsb
                call    couCompSpeed        ; Compare
                pop     ax                  ; Restore what we have w/o 0WS
                ja      sw_at               ; 0WS could not be used

                mov     ah, 0FFh            ; Used as flag


;-------------------------- Create Window attributes --------------------------

sw_at:          test    al, WS_IO           ; I/O window ?
                jnz     sw_set_io           ; Yes, continue

                test    al, WS_16BIT        ; 16-bit request ?
                jz      @f                  ; No, continue

                or      dh, PCIC_MEMWIN_M16 ; Yes, set 16-bit data width

@@:             cmp     ah, 0FFh            ; 0WS?
                jne     @f                  ; No continue

                or      dh, PCIC_MEMWIN_0WS ; Force 0WS and go ahead

@@:             or      ah, ah              ; Any WS?
                jz      @f                  ; No, continue

                push    cx
                mov     cl, 6
                shl     ah, cl              ; Create WS mask
                pop     cx
                or      ch, ah

@@:             call    SetupMemWin
                jmp     short sw_success


sw_set_io:      cmp     ah, 0FFh            ; 0WS?
                jne     @f                  ; No, continue

                mov     ah, PCIC_IOWIN_0WS
                jmp     short sw_io_wsok

@@:             or      ah, ah              ; Any WS?
                jz      short sw_io_wsok    ; No, continue

                mov     ah, PCIC_IOWIN_WS

sw_io_wsok:     test    al, WS_16BIT        ; 16-bit request ?
                jz      @f

                or      ah, PCIC_IOWIN_IO16 OR PCIC_IOWIN_IO16SR

@@:             cmp     (ARGS PTR [BP]).bWindowNum, 1
                jne     @f

                push    cx
                mov     cl, 4
                shl     ah, cl
                pop     cx

@@:             call    SetupIOWin

;---------------------------- Terminate operations ----------------------------

sw_success:     test    al, WS_ENABLED      ; Need to enable window?
                jz      @f                  ; Yes, continue
                call    cowEnableWindow     ;  and enable window

@@:             mov     ah, SUCCESS
;               jmp     short sw_done

sw_done:        ret

SetWindow       ENDP

COMMENT ~*********************************************************************
        Procedure:      GetPage
        Revision:       2
        Date:           08/04/1993
        Purpose:        Return PC Card offset and window state
        Entry:          [BP] = Pointer to entry args on stack
                        [BX] = Pointer to adapter entry in Adapters array
        Exit:           Args.DXReg = Page State (set to one = true)
                          Bit 0    = Memory type (reset = common, set = attribute)
                          Bit 1    = Page enabled
                          Bit 2    = Software Write-Protected
                          All other bits are reserved and are reset to zero (0)
                        Args.BLReg = Page number
                        Args.DIReg = Memory Card Offset (4 KByte units)
*****************************************************************************~
GetPage         PROC    NEAR

;----------------------------- Get current offset  ----------------------------

                mov     al, PCIC_MEMWIN_OFF_H
                CALL    GetWndReg
                mov     ah, al

                mov     al, PCIC_MEMWIN_OFF_L
                call    GetWndReg
                push    ax                  ; Save for later

                and     ax, PCIC_MEMWIN_OMSK

                mov     cx, ax

;--- Change to adjust offset from hardware requirements to user requirements --

                mov     al, PCIC_MEMWIN_STR_H
                call    GetWndReg
                mov     ah, al
                mov     al, PCIC_MEMWIN_STR_L
                call    GetWndReg           ; AX: START address

                and     ax, PCIC_MEMWIN_MSK

                add     ax, cx
                and     ax, PCIC_MEMWIN_MSK ; Mask address bytes

                mov     (ARGS PTR [BP]).DIReg, ax

;------------------------------Return page state ------------------------------

                pop     ax                  ; Card OFFSET
                xor     dx, dx
                test    ah, PCIC_MEMWIN_ATTR
                jz      @f

                or      dl, PS_ATTRIBUTE    ; Save memory type

@@:             call    cowIsWinEnabled
                jz      @f

                or      dl, PS_ENABLED

@@:             test    ah, PCIC_MEMWIN_WP
                jz      @f

                or      dl, PS_WP

@@:             mov     (ARGS PTR [BP]).DXReg, dx ; Return page attributes
                mov     (ARGS PTR [BP]).BLReg, 0  ; Cannot page window
                mov     ah, SUCCESS
                ret

GetPage         ENDP

COMMENT ~*********************************************************************
        Procedure:      SetPage
        Revision:       4
        Date:           09/23/1993
        Purpose:        Set PC Card offset and set window state
        Entry:          [BP] = Pointer to entry args on stack
                        [BX] = Pointer to adapter entry in Adapters array
                        Args.DXReg = Page Control (set to one = true)
                          Bit 0    = Memory type (reset = common, set = attribute)
                          Bit 1    = Enable page
                          Bit 2    = Software Write-Protect
                          All other bits are reserved.
                        Args.DIReg = Desired Memory Card Offset (4 KByte units)
                        Args.BLReg = Page number
        Exit:           If offset >= 64 MB
                          Args.AH = BAD_OFFSET
*****************************************************************************~
SetPage         PROC    NEAR

;--------- Set current offset, software write-protect and memory type  --------

                mov     cx, (ARGS PTR [BP]).DIReg ; Card Offset
                mov     dl, (ARGS PTR [BP]).DLReg ; Page Attributes
                test    cx, NOT PCIC_MEMWIN_OMSK
                jnz     sp_bad_offset

;-------------- Change to adjust offset to hardware requirements --------------

                mov     al, PCIC_MEMWIN_STR_H
                call    GetWndReg
                mov     ah, al
                mov     al, PCIC_MEMWIN_STR_L
                call    GetWndReg               ; AX: START address
                and     ax, PCIC_MEMWIN_MSK

                sub     cx, ax                  ; Get Offset
                and     cx, PCIC_MEMWIN_OMSK    ; Mask valid bits

;------------------------------- Set memory type ------------------------------

                test    dl, PS_ATTRIBUTE
                jz      @f

                or      ch, PCIC_MEMWIN_ATTR

@@:             test    dl, PS_WP
                jz      @f

                or      ch, PCIC_MEMWIN_WP

;-------------------------- Write changes to hardware -------------------------

@@:             mov     ah, cl
                mov     al, PCIC_MEMWIN_OFF_L
                call    SetWndReg

                mov     ah, ch
                mov     al, PCIC_MEMWIN_OFF_H
                call    SetWndReg

; Because our hardware doesn't allow paging inside window, we should ignore
; PS_ENABLED. PCMCIA Socket Services Specification, page 5-58. Therefore,
; IBM Card Services for OS/2 do not disable window. IBM consider, that seting
; of page with disabled attribute will do it!

                call    cowDisableWindow

                test    dl, PS_ENABLED
                jz      @f

                call    cowEnableWindow
@@:
                mov     ah, SUCCESS
                jmp     short sp_done

sp_bad_offset:  mov     ah, BAD_OFFSET
                jmp     short sp_done

sp_bad_attr:    mov     ah, BAD_ATTRIBUTE
                jmp     short sp_done

sp_done:        ret

SetPage         ENDP


sEnd            ResCode
                end
