COMMENT @
 ************************************************************************
 *                                                                      *
 *     Copyright (c) 1992 Intel Corporation                             *
 *     All Rights Reserved                                              *
 *                                                                      *
 *     INTEL CORPORATION PROPRIETARY INFORMATION                        *
 *                                                                      *
 *     This software is supplied under the terms of a licence           *
 *     agreement with Intel Corporation and may not be copied nor       *
 *     disclosed except in accordance with the terms of that agreement. *
 *                                                                      *
 ************************************************************************
@

COMMENT @

 Description:  Hardware-specific routines for ATI 68800 adapters

 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
   HISTORY:

 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@

INCLUDE  DCIMACRO.INC

DGROUP   GROUP   _DATA
_DATA    SEGMENT PARA PUBLIC 'DATA'
         EXTERN  C _C000h:WORD  
         EXTERN  C Selector:WORD 
         EXTERN  C gHdwCur:BYTE
AdConfig DWORD   ?                ; Address of ATIConfiguration
AdXYLin  DWORD   ?                ; Address of ATIXYToLinear
AdVXD    DWORD   ?                ; Address of VXD
LinBase  DWORD   ?                ; First linear address in frame buffer
SelBase  DWORD   ?                ; Current selector base
hModDISP WORD    ?                ; Module handle of DISPLAY
hModMACH WORD    ?                ; Module handle of MACH32
;Selector WORD    0                ; Selector for linear addressing
LimitXDT WORD    ?                ; Two xDT variables must be contiguous
BaseXDT  DWORD   ?                ; Two xDT variables must be contiguous
EyeCatch BYTE    "761295520", 0
szDISP   BYTE    "DISPLAY", 0
szMACH   BYTE    "MACH32", 0
Version  BYTE    "ATIVersion", 0
Config   BYTE    "ATIConfiguration", 0
XYToLin  BYTE    "ATIXYtoLinear", 0
_DATA    ENDS

ASM_TEXT SEGMENT PARA USE16 PUBLIC 'CODE'
         OPTION  LANGUAGE:C
        .386
         ASSUME  DS:DGROUP
         EXTERN	 PASCAL SETSELLIMIT:FAR 
         
COMMENT @
Function DispatchATI68800:
Dispatch the hardware functions
@
         ALIGN   16
DispatchATI68800 PROC FAR
         Dispatch                 ; Same code for all dispatchers
         ret                      ; Return to caller
DispatchATI68800 ENDP

         OPTION  PROC:PRIVATE     ; Functions below are local

COMMENT @
Function QueryBank:
Determine whether this device should be treated as a banked device
or linear.

Returns:  AX = TRUE or FALSE
@
         ALIGN   16
QueryBank PROC  FAR SaveAX:WORD
         xor     ax, ax           ; Set return code to FALSE
         ret
QueryBank ENDP

COMMENT @
Function GetEntryPoint:
Look for an entry point in one of two modules

Returns:  EAX = entry point address
                0 if entry point not found
@
         EXTERN  PASCAL GETMODULEHANDLE:FAR
         EXTERN  PASCAL GETPROCADDRESS:FAR  
         
GetEntryPoint PROC PASCAL FuncName:NEAR PTR
         mov     ax, hModDISP     ; Look in DISPLAY first
         test    ax, ax           ; Did we find DISPLAY?
         je      CheckNext        ; Skip if DISPLAY not found
         push    ax               ; Parameters for GetProcAddress
         push    ds               ;
         push    FuncName         ;
         call    GETPROCADDRESS   ;
         shl     eax, 16          ; Combine high and low portions of address
         shrd    eax, edx, 16     ;
         jnz     Done             ; Skip if we found the entry point
CheckNext:
         mov     ax, hModMACH     ; Look in MACH32
         movzx   eax, ax          ; Zero out high order word
         test    ax, ax           ; Did we find MACH32?
         je      Done             ; Skip if MACH32 not found
         push    ax               ; Parameters for GetProcAddress
         push    ds               ;
         push    FuncName         ;
         call    GETPROCADDRESS   ;
         shl     eax, 16          ; Combine high and low portions of address
         shrd    eax, edx, 16     ;
Done:
         ret                      ; Return to caller
GetEntryPoint ENDP

COMMENT @
Function Identify:
Determine if this hardware routine matches the current adapter and
driver

Returns:  AX = TRUE   hardware matches
               FALSE  hardware does not match
@
         EXTERN  PASCAL ALLOCSELECTOR:FAR
         EXTERN  PASCAL SETSELECTORBASE:FAR
         EXTERN  PASCAL SETSELECTORLIMIT:FAR
         
Identify PROC    FAR USES ES SI DI
         LOCAL   SelMagic:WORD    ; ATI linear magic selector

         mov     si, OFFSET EyeCatch
         lea     di, _C000h       ; Get selector of video BIOS
         mov     es, di           ;
         mov     di, 31H          ; Fixed offset in ATI BIOS
         mov     cx, SIZEOF EyeCatch   ; Get length of string
         cld                      ; Search forwards
         repz    cmpsb            ; Does the signature match?
         jne     NoMatch          ; Skip if no match
         test    BYTE PTR es:[44H], 40H ; Bit off means graphics engine present
         jnz     NoMatch          ; ATI 68800 has a graphics engine

         push    ds               ;
         push    OFFSET szDISP    ; Look for DISPLAY module
         call    GETMODULEHANDLE  ;
         mov     hModDISP, ax     ; Save the module handle

         push    ds               ;
         push    OFFSET szMACH    ; Look for MACH32 module
         call    GETMODULEHANDLE  ;
         mov     hModMACH, ax     ; Save the module handle

         push    OFFSET Version   ; Get address of ATIVersion entry point
         call    GetEntryPoint    ;
         test    eax, eax         ; Was entry point found?
         je      NoMatch          ; Skip if entry point not found
                                  ; Ignore address of ATIVersion entry point

         push    OFFSET Config    ; Get address of ATIConfiguration entry point
         call    GetEntryPoint    ;
         test    eax, eax         ; Was entry point found?
         je      NoMatch          ; Skip if entry point not found
         mov     AdConfig, eax    ; Save address of ATIConfiguration entry point

         push    OFFSET XYToLin   ; Get address of ATIXYtoLinear entry point
         call    GetEntryPoint    ;
         test    eax, eax         ; Was entry point found?
         je      NoMatch          ; Skip if entry point not found
         mov     AdXYLin, eax     ; Save address of ATIXYtoLinear entry point

         mov     ax, 1684H        ; Get VXD device API entry point
         xor     di, di           ;
         mov     es, di           ;
         mov     bx, 30H          ; VXD ID
         int     2FH              ;
         mov     ax, es           ; Put the returned address in EDI
         shl     edi, 16          ;
         shrd    edi, eax, 16     ;
         jz      NoMatch          ; Skip if VXD device API entry point not found
         mov     AdVXD, edi       ; Save VXD device API entry point

         push    ds               ; Copy ds, a read/write 16-bit expand-up
         call    ALLOCSELECTOR    ;  data segment
         test    ax, ax           ; Was selector allocated?
         jz      NoMatch          ; Skip if selector was not allocated
         mov     Selector, ax     ; Save the selector

         mov     ax, 2            ; Allocate the linear magic selector
         call    [AdVXD]          ;
         mov     SelMagic, ax     ; Save the selector

         test    al, 4            ; Is magic selector from LDT?
         jnz     UseLDT           ; Skip if magic selector is from LDT
         sgdt    LimitXDT         ; Get the GDT address and limit
         jmp     GotDT            ; Skip to common GDT/LDT handling
UseLDT:
         sldt    LimitXDT         ; Get the LDT address and limit
GotDT:
                                  ; Assign selector to GDT or LDT for now
         push    Selector         ; Set the selector base
         push    BaseXDT          ;
         call    SETSELECTORBASE  ;
;; BUGBUG : following is used to set selector limit - extracted from 
;;			Todd Laney's code
         
         push    Selector         ; Set the selector limit
         push    40H              ; High word of selector limit
         push    0                ; Low word
;         call    SETSELECTORLIMIT ;
         call	 SETSELLIMIT	  ; call Todd's routine
         
         mov     es, Selector     ; Point to the GDT or LDT
         mov     bx, SelMagic     ; Inspect the linear magic selector
         and     bl, 0F8H         ; Remove TI, RPL bits
         mov     eax, es:[BX+1]   ; Get the selector base
         mov     al, es:[BX+7]    ;
         ror     eax, 8           ;
         mov     LinBase, eax     ; Save the linear address

         mov     ax, 3            ; Free the linear magic selector
         mov     bx, SelMagic     ;
         call    [AdVXD]          ;

         push    0                ; Push (0,0)
         push    0                ;
         call    [AdXYLin]        ;
         add     LinBase, eax     ; Compute first linear address in frame buffer

         mov     al, 1            ; Set return code to TRUE    
         
         mov	 gHdwCur, 1		  ; set hardware cursor to TRUE
Exit:
         ret                      ; Return to caller

NoMatch:
         xor     ax, ax           ; Set return code to FALSE
         jmp     Exit             ; Go to common exit

Identify ENDP

COMMENT @
Function RestBank:
Flush the virtual aperture before returning control to the engine
@
         ALIGN   16
RestBank PROC    FAR USES DS, SaveAX:WORD, ShowCursor:WORD
         push    DGROUP           ; Establish data area addressability
         pop     ds               ;
         mov     ax, 7            ; Flush virtual aperture
         call    [AdVXD]          ;
         ret                      ; Return to caller
RestBank ENDP

COMMENT @
Function ScanWidth:
Get the scan width, also known as the pixel pitch

Returns:  AX = Scan width
@
         ALIGN   16
ScanWidth PROC   FAR USES DS, SaveAX:WORD
         LOCAL   ATIConfig[32]:WORD    ; ATIConfiguration structure
                                       ; Xdesktop
                                       ; Ydesktop
                                       ; Pitch     Pitch, in pixels
                                       ; BitsPP    Bits per pixel
                                       ; ClrWeight 0=555, 1=565, 2=655, 3=664
                                       ; ScanLines Total acc memory in scanlines
                                       ; ChipRev   Mach32 chip revision
                                       ; Other crap

         push    DGROUP           ; Establish data area addressability
         pop     ds               ;
         push    SS               ; Get configuration information
         lea     ax, ATIConfig    ; Offset of ATIConfiguration structure
         push    ax               ;
         call    [AdConfig]       ;
         mov     ax, ATIConfig[4] ; Get scan width in pixels
         mul     ATIConfig[6]     ; Multiply by bits per pixel
         shrd    ax, dx, 3        ; Bit count to byte count
         ret                      ; Return to caller
ScanWidth ENDP

COMMENT @
Function SetTarget:
Initialize DX:AX from an offset in the frame buffer

Returns:  DX:AX  = 16:16 pointer in frame buffer
@
         ALIGN   16
         EXTERN  PASCAL SETSELECTORBASE:FAR
SetTarget PROC   FAR USES DS, SaveAX:WORD, Offst:DWORD
         push    DGROUP           ; Establish data area addressability
         pop     ds               ;
         mov     eax, Offst       ; Get offset in the frame buffer
         add     eax, LinBase     ; Add linear base address
         mov     SelBase, eax     ; Save new selector base
         push    Selector         ; Set the selector base
         push    eax              ; New base address
         call    SETSELECTORBASE  ;
         mov     dx, Selector     ; Load the selector
         xor     eax, eax         ; Initial offset is 0
         ret                      ; Return to caller
SetTarget ENDP

COMMENT @
Function Terminate:
Deallocate the linear address selector
@
         EXTERN  PASCAL FREESELECTOR:FAR
Terminate PROC   FAR SaveAX:WORD
         mov     ax, Selector     ; Get the selector
         test    ax, ax           ; Was a selector allocated?
         jz      Done             ; Skip if no selector was allocated
         push    ax               ; Set the selector limit back to 64k
                                  ;  or Windows will free many selectors
         push    0                ; High word of selector limit
         ;push    -1                ; Low word
         push	 0				  
         ;call    SETSELECTORLIMIT ;
         call	 SETSELLIMIT

         push    Selector         ; Free the selector
         call    FREESELECTOR     ;
Done:
         ret                      ; Return to caller
Terminate ENDP

COMMENT @
Stubs for undefined functions
@
         DispStubs

ASM_TEXT ENDS
         END

