;       SCCSID = @(#)abiosdh.asm	6.1 90/11/17
SCCSID  equ     "@(#)abiosdh.asm        1.19 90/09/17"
; ****************************************************************************
; *                                                                          *
; *                       IBM/Microsoft Confidential                         *
; *                                                                          *
; *                 Copyright (c) IBM Corporation  1987, 1990                *
; *                 Copyright (c) Microsoft Corp.  1987, 1990                *
; *                           All Rights Reserved                            *
; *                                                                          *
; ****************************************************************************
PAGE    ,132
TITLE   ABIOSDH.ASM - ABIOS DevHlp Routines
NAME    ABIOSDH
.286p

;********************************************************************
;*                                                                  *
;*      SOURCE FILE NAME: ABIOSDH.ASM                               *
;*                                                                  *
;*      DESCRIPTIVE NAME: ABIOS Device Help Routines                *
;*                                                                  *
;*      STATUS: Version 1.1                                         *
;*                                                                  *
;*      FUNCTION: This source file contains the routines needed     *
;*                to call ABIOS                                     *
;*                                                                  *
;*      NOTES: All code in this source file is new to CP/DOS 1.1 @@ *
;*                                                                  *
;*      ENTRY POINTS: InitLIDTable - Initialize LID Ownership Table *
;*                                   Called by SysInit              *
;*                    dh_GetLIDEntry - Get Logical ID               *
;*                                   Called by the DevHlp Router    *
;*                    GetLIDEntry - Get Logical ID                  *
;*                                   Called by kernel components    *
;*                    dh_FreeLIDEntry - Free Logical ID             *
;*                                   Called by the DevHlp Router    *
;*                    FreeLIDEntry - Free Logical ID                *
;*                                   Called by kernel components    *
;*                    dh_ABIOSCall - ABIOS Call Service             *
;*                                   Called by the DevHlp Router    *
;*                    ABIOSCall - ABIOS Call Service                *
;*                                   Called by kernel components    *
;*                    dh_ABIOSCommonEntry - Call ABIOS Common Entry *
;*                                          Point                   *
;*                                   Called by the DevHlp Router    *
;*                    dh_GetDeviceBlock - Get ABIOS Device Block    *
;*                                                                  *
;*      EXTERNAL REFERENCES:                                        *
;*               ROUTINES: _SELAllocKHB                             *
;*                         SeltoSeg                                 *
;*                         ABIOS                                    *
;*        DATA STRUCTURES: ABIOS Common Data Area                   *
;*                         ABIOS Device Blocks                      *
;*                         Device Driver Header                     *
;*                                                                  *
;********************************************************************
.xlist
include dosseg.inc
include basemaca.inc
include osmaca.inc
include mi.inc
include fnodev.inc
include protmode.inc
include struc.inc
include aberror.inc
include abios.inc
include devhdr.inc
include mhandle.inc
include osconst.inc
include pgexport.inc
include vmexport.inc
include selxport.inc
.list

        ModName , FNO_ABIOSDH_ASM
        CpuMode 386

        ReferGlobal     ABIOS_CDA_anchor_r,WORD
        ReferGlobal     ABIOS_CDA_anchor_p,WORD
        ReferGlobal     RealCDASel,WORD
        ReferGlobal     ABIOS_present,BYTE


        EXTRN32         _SELAllocKHB
        EXTRNFAR        SelToSeg

        PUBLIC          GetLIDEntry
        PUBLIC          FreeLIDEntry
        PUBLIC          ABIOSCall
        PUBLIC          ABIOS_DH_present

        FALSE                   equ     0
        TTRUE                   equ     1
        First_Available_LID     equ     3

ABIOSDATA SEGMENT

LIDTable_sel            DW   ?          ; LID Ownership Table protect mode pointer
LIDTable_seg            DW   ?          ; LID Ownership Table real mode pointer
num_LIDS                DW   ?          ; Number of LID's in the CDA
ABIOS_DH_present        DB   0          ; ABIOS Devhlp present flag

ABIOSDATA ENDS

        FARCODE INIT
INITCODE segment

BREAK <InitLIDTable - Initialize LID Ownership Table>
;********************************************************************
;*                                                                  *
;*      SUBROUTINE NAME: InitLIDTable                               *
;*                                                                  *
;*      DESCRIPTIVE NAME: Initialize LogicalID Ownership table      *
;*                                                                  *
;*      FUNCTION:                                                   *
;*                                                                  *
;*      InitLIDTable is called by SYSINIT.                          *
;*      The ownership table will be a word table of size N that     *
;*      contains the associated protect mode DS for LID's that are  *
;*      owned.  InitLIDTable will read the Common Data Area to find *
;*      the Count of LogicalIDs = N.  A call is then made to        *
;*      request an area of memory of size N words.  The table is    *
;*      initialized to zero indicating that all LogicalID's are     *
;*      unowned.  If not enough memory was allocated to set up the  *
;*      ownership table, then the CARRY Flag (CF) is set and a      *
;*      message ID is returned in AX.                               *
;*                                                                  *
;*      ENTRY POINT: InitLIDTbl                                     *
;*      LINKAGE: Near                                               *
;*                                                                  *
;*      INPUT:  None                                                *
;*                                                                  *
;*      EXIT-NORMAL: CF = 0                                         *
;*                   AX = 0                                         *
;*                                                                  *
;*      EXIT-ERROR:  CF = 1                                         *
;*                   AX = MSG_MEMORY_ALLOCATION_FAILED              *
;*                                                                  *
;*      EFFECTS: other than exit registers, all registers unaltered *
;*                                                                  *
;*      INTERNAL REFERENCES:                                        *
;*               ROUTINES: None                                     *
;*        DATA STRUCTURES: LID Ownership Table                      *
;*                                                                  *
;*      EXTERNAL REFERENCES:                                        *
;*               ROUTINES: _SELAllocKHB                             *
;*                         SeltoSeg                                 *
;*                                                                  *
;********************************************************************
ASSUME  DS:NOTHING, ES:NOTHING, SS:NOTHING

Procedure InitLIDTable
;       PMONLY   (called by SYSINIT only)
;       INT     3                       ;<<< DEBUG >>>
        LocalVar lid_vmac, <size VMAC>
        EnterProc
SaveReg         <ebx,cx,dx,di,si,ds,es>

DosContext      ds                      ; DS = DOSGROUP Data

.if < ABIOS_present eq TTRUE > near
        mov     es, ABIOS_CDA_anchor_p  ; Address Protected Mode CDA
        assume  es:nothing

;    Determine segment size, and save num_LIDS before changing DS
        movzx   ebx, es:[0].CDALids      ;
        mov     num_LIDS, bx
        add     ebx, ebx                 ; BX = num_LIDS * 2

;    make DS and ES FLAT context
        FlatContext <ds,es>,ax               ; setup ds and es (uses ax)
;    push    pointer to returned address/selector
        SSToDS  EAX,lid_vmac
        PushP   eax

;    push    owner handle
        mov     eax,LIDOWNER
        PushP   eax                    ; OwnerID - Owner of the segment

;       push    alloc flags (selector mgr flags)
        mov     eax,SELAL_W
        PushP   eax

;    push    alloc flags (VM, PG flags set above)
        mov     eax,VMAC_ALIGNPARA+PG_RESIDENT+PG_1M+PG_CONTIG+PG_U
        PushP   eax

;    push    new size

        PushP   ebx                     ; num_LIDS * 2

;    push    kernal heap handle
        mov     eax, VM_HKH_PUB_RES1MRW
        PushP   eax                        ; push correct handle

        CCALL32  _SELAllocKHB,,,PushP

        .if <zero eax>                  ; memory allocation is successful (EAX=0)
                DosContext      <es,ds>
                mov     cx,lid_vmac.ac_sel
                mov     LIDTable_sel, cx
                mov     es,cx
        ASSUME  es:NOTHING
                xor     edi,edi
                push    cx
                mov     ecx,ebx
                B1EMac   rep stosb
                DosContext      es,cx

                pop     bx
                pushf                   ; save flags
                CALLFAR SelToSeg        ; convert selector to segment
                popf                    ; restore flags

                mov     LIDTable_seg, ax ; CF clear by SeltoSeg
                                        ; set exit normal condition (CF = 0)
                mov     ABIOS_DH_present, 1     ; indicate ABIOS_DH present
                xor     ax,ax           ; return AX = 0
               ;clc                     ; set exit sucess (set CF=0)
        .else                           ; memory allocation failed (EAX!= 0)
                InternalError   <LIDTable allocation failure>
                mov     ax, MSG_MEMORY_ALLOCATION_FAILED ; set exit error condition
                stc
        .endif
.else                                   ; ABIOS not present
        clc                             ; set exit normal condition (CF = 0)
.endif                                  ; Is ABIOS present?

RestoreReg      <es,ds,si,di,dx,cx,ebx>  ; Restore registers used
;       INT     3                       ;<<< DEBUG >>>
LeaveProc
ret

EndProc InitLIDTable
;*******************************************************************

INITCODE ends



        FARCODE LOW
ABIOSCODE    SEGMENT

BREAK <dh_GetLIDEntry - Get Logical ID>
;********************************************************************
;*                                                                  *
;*      SUBROUTINE NAME: dh_GetLIDEntry                             *
;*                                                                  *
;*      DESCRIPTIVE NAME: Get a Logical ID                          *
;*                                                                  *
;*      FUNCTION: Entry point for the Devhelp Router                *
;*                                                                  *
;*      Move the owner tag of the caller into CX.  Calls GetLID to  *
;*      search the Common Data Area for a relative Logical ID for   *
;*      the specified DeviceID.  If the relative Logical ID = 0, a  *
;*      search of the CDA is made for the first available logical   *
;*      ID for the specified device type.  If the relative logical  *
;*      ID n > 0, then a search of the CDA is made for the nth      *
;*      logical ID of the reqested device type.                     *
;*                                                                  *
;*      If an entry is located that matches the caller's form of    *
;*      request, then the LID is returned to the caller with the    *
;*      CARRY Flag (CF) cleared.  Once a LID is given to a device   *
;*      driver, the LID entry is marked as being owned in a LID     *
;*      ownership table and the owner is noted.  If no entry is     *
;*      found, the CARRY Flag is set to indicate an error.  The     *
;*      AX register is then used to distinguish between the         *
;*      errors ABIOS-Not-Present, LID-Does-Not-Exist, and           *
;*      and LID-Already-Owned.                                      *
;*                                                                  *
;*      ENTRY POINT: dh_GetLIDEntry                                 *
;*      LINKAGE: far call to Device_Help with function code 34      *
;*               (DevHlp_GetLIDEntry) in the DL register            *
;*                                                                  *
;*      INPUT:   AL  = Desired DeviceID.                            *
;*               BL  = Relative Logical ID                          *
;*                      0 => First Unclaimed LogicalID              *
;*                      1 => LogicalID #1 for this DeviceID         *
;*               DS  = Data Segment of Requesting Device Driver     *
;*               DH  = Device State                                 *
;*                      0 => Non-Shared Device                      *
;*                      1 => Shared Device (i.e. DMA, POS)          *
;*                                                                  *
;*      EXIT-NORMAL: CF = 0                                         *
;*                   AX = LogicalID #                               *
;*                                                                  *
;*      EXIT-ERROR:  CF = 1                                         *
;*                   AX = ERROR_ABIOS_NOT_PRESENT                   *
;*                        ERROR_LID_ALREADY_OWNED                   *
;*                        ERROR_LID_DOES_NOT_EXIST                  *
;*                                                                  *
;*      EFFECTS: other than exit registers, all registers unaltered *
;*                                                                  *
;*      INTERNAL REFERENCES:                                        *
;*               ROUTINES: GetLID                                   *
;*                                                                  *
;*      EXTERNAL REFERENCES:                                        *
;*               ROUTINES: None                                     *
;*        DATA STRUCTURES: Device Header                            *
;*                                                                  *
;********************************************************************
ASSUME  DS:NOTHING, ES:NOTHING, SS:NOTHING

Procedure   dh_GetLIDEntry
;       PROTMODE

        push    cx
        mov     cx, ds:[0].SDevProtDS   ; Get Prot Mode DS
        Call GetLID
        pop     cx
        ret

EndProc dh_GetLIDEntry
;*******************************************************************


;********************************************************************
;*                                                                  *
;*      SUBROUTINE NAME: GetLIDEntry                                *
;*                                                                  *
;*      DESCRIPTIVE NAME: Get a Logical ID                          *
;*                                                                  *
;*      FUNCTION: Entry point for kernel components                 *
;*                                                                  *
;*      Move the owner tag of the caller into CX.  Calls GetLID to  *
;*      search the Common Data Area for a relative Logical ID for   *
;*      the specified DeviceID.  If the relative Logical ID = 0, a  *
;*      search of the CDA is made for the first available logical   *
;*      ID for the specified device type.  If the relative logical  *
;*      ID n > 0, then a search of the CDA is made for the nth      *
;*      logical ID of the reqested device type.                     *
;*                                                                  *
;*      If an entry is located that matches the caller's form of    *
;*      request, then the LID is returned to the caller with the    *
;*      CARRY Flag (CF) cleared.  Once a LID is given to a device   *
;*      driver, the LID entry is marked as being owned in a LID     *
;*      ownership table and the owner is noted.  If no entry is     *
;*      found, the CARRY Flag is set to indicate an error.  The     *
;*      AX register is then used to distinguish between the         *
;*      errors ABIOS-Not-Present, LID-Does-Not-Exist, and           *
;*      and LID-Already-Owned.                                      *
;*                                                                  *
;*      ENTRY POINT: GetLIDEntry                                    *
;*      LINKAGE: Near call for callers in DOSCODE, far call         *
;*               otherwise                                          *
;*                                                                  *
;*      INPUT:   AL  = Desired DeviceID.                            *
;*               BL  = Relative Logical ID                          *
;*                      0 => First Unclaimed LogicalID              *
;*                      1 => LogicalID #1 for this DeviceID         *
;*               DH  = Device State                                 *
;*                      0 => Non-Shared Device                      *
;*                      1 => Shared Device (i.e. DMA, POS)          *
;*                                                                  *
;*      EXIT-NORMAL: CF = 0                                         *
;*                   AX = LogicalID #                               *
;*                                                                  *
;*      EXIT-ERROR:  CF = 1                                         *
;*                   AX = ERROR_ABIOS_NOT_PRESENT                   *
;*                        ERROR_LID_ALREADY_OWNED                   *
;*                        ERROR_LID_DOES_NOT_EXIST                  *
;*                                                                  *
;*      EFFECTS: other than exit registers, all registers unaltered *
;*                                                                  *
;*      INTERNAL REFERENCES:                                        *
;*               ROUTINES: GetLID                                   *
;*                                                                  *
;*      EXTERNAL REFERENCES:                                        *
;*               ROUTINES: None                                     *
;*                                                                  *
;********************************************************************
Procedure   GetLIDEntry,hybrid
;       PROTMODE

        push    cx
        mov     cx, 0FFFFh              ; ownership tag
        Call GetLID
        pop     cx
        ret

EndProc GetLIDEntry
;*******************************************************************



;********************************************************************
;*                                                                  *
;*      SUBROUTINE NAME: GetLID                                     *
;*                                                                  *
;*      DESCRIPTIVE NAME: Get a Logical ID                          *
;*                                                                  *
;*      FUNCTION:                                                   *
;*                                                                  *
;*      Search the Common Data Area for a relative Logical ID for   *
;*      the specified DeviceID.  If the relative Logical ID = 0, a  *
;*      search of the CDA is made for the first available logical   *
;*      ID for the specified device type.  If the relative logical  *
;*      ID n > 0, then a search of the CDA is made for the nth      *
;*      logical ID of the requested device type.                    *
;*                                                                  *
;*      If an entry is located that matches the caller's form of    *
;*      request, then the LID is returned to the caller with the    *
;*      CARRY Flag (CF) cleared.  Once a LID is given to a device   *
;*      driver, the LID entry is marked as being owned in a LID     *
;*      ownership table and the owner is noted.  If no entry is     *
;*      found, the CARRY Flag is set to indicate an error.  The     *
;*      AX register is then used to distinguish between the         *
;*      errors ABIOS-Not-Present, LID-Does-Not-Exist, and           *
;*      and LID-Already-Owned.                                      *
;*                                                                  *
;*      ENTRY POINT: GetLID                                         *
;*      LINKAGE: near call                                          *
;*                                                                  *
;*      INPUT:   AL  = Desired DeviceID.                            *
;*               BL  = Relative Logical ID                          *
;*                      0 => First Unclaimed LogicalID              *
;*                      1 => LogicalID #1 for this DeviceID         *
;*               CX  = Owner tag of the caller                      *
;*               DH  = Device State                                 *
;*                      0 => Non-Shared Device                      *
;*                      1 => Shared Device (i.e. DMA, POS)          *
;*                                                                  *
;*      EXIT-NORMAL: CF = 0                                         *
;*                   AX = LogicalID #                               *
;*                                                                  *
;*      EXIT-ERROR:  CF = 1                                         *
;*                   AX = ERROR_ABIOS_NOT_PRESENT                   *
;*                        ERROR_LID_ALREADY_OWNED                   *
;*                        ERROR_LID_DOES_NOT_EXIST                  *
;*                                                                  *
;*      EFFECTS: other than exit registers, all registers unaltered *
;*                                                                  *
;*      INTERNAL REFERENCES:                                        *
;*               ROUTINES: None                                     *
;*        DATA STRUCTURES: LID Ownership Table                      *
;*                                                                  *
;*      EXTERNAL REFERENCES:                                        *
;*               ROUTINES: None                                     *
;*        DATA STRUCTURES: ABIOS Common Data Area                   *
;*                         ABIOS Device Blocks                      *
;*                                                                  *
;********************************************************************
Procedure   GetLID
;       PROTMODE
;       INT     3                       ;<<< DEBUG >>>

SaveReg <bx,dx,si,di,ds,es>

LocalVar rel_ID_count,WORD              ; Relative LID loop counter
LocalVar lid_count,WORD                 ; LID loop counter
LocalVar found,WORD                     ; Found boolean operator
LocalVar LIDTable,WORD                  ; LID Ownership Table pointer
LocalVar Owner_tag,WORD                 ; Callers Ownership Tag
LocalVar Device_state,WORD              ; Device State

EnterProc                               ; Save Space on the stack for above

DosContext      ds                      ; DS = DOSGROUP Data

.if < ABIOS_present eq TTRUE > near

        mov     [Owner_tag], cx         ; Ownership tag
        xor     dl, dl
        xchg    dh, dl
        mov     [Device_state], dx      ; Device State

        mov     cx, ABIOS_CDA_anchor_p  ; Address Protected Mode CDA
        mov     dx, LIDTable_sel        ; LID Ownership Table protect
                                        ;   mode pointer

        mov     [LIDTable], dx          ; LID Ownership Table pointer

        mov     [rel_ID_count], 1
        mov     [lid_count], First_Available_LID
        mov     [found], FALSE
        xor     ah, ah                  ; AX = Desired DeviceID
        xor     bh, bh                  ; BX = Relative LID Requested
        mov     dx, num_LIDS


        .while <[lid_count] b dx> and near
        .while <[found] eq FALSE> near

                mov     ds, cx                  ; ABIOS_CDA_anchor
                mov     si, [lid_count]
                shl     si, 3                   ; DS:SI = ABIOS Device Block

                ;**********************************************************
                ;  Is the CDA entry a null pointer
                ;**********************************************************

                .if < <WORD PTR ds:[si].DBSegment> ne 0 > and near
                .if < <WORD PTR ds:[si].FTTSegment> ne 0 > near

                        mov     es, ds:[si].DBSegment
                        mov     di, ds:[si].DBOffset    ; ES:DI = ABIOS Device Block

                        ;**********************************************************
                        ;  Is the LID the desired device type
                        ;**********************************************************

                        .if < <WORD PTR es:[di].DevID> eq ax >

                                mov     ds, [LIDTable]
                                shr     si, 2           ; DS:SI = LIDTable[lid_count]

                                .if < bx ne [rel_ID_count] >
                                        .if < zero bx > and
                                        .if < < WORD PTR ds:[si] > eq 0 > or
                                        .if < < WORD PTR ds:[si] > eq 0FFFEh > and
                                        .if <[Device_state] eq 1 >

                                        ;*******************************************
                                        ; Caller wants the first available LID and
                                        ; it is not owned.  Assign it to the caller
                                        ;*******************************************

                                                .if <[Device_state] eq 1 >
                                                        mov     ax, 0FFFEH
                                                .else
                                                        mov     ax, [Owner_tag]
                                                .endif
                                                mov     ds:[si], ax
                                                mov     ax, [lid_count]
                                                mov     [found], TTRUE
                                                clc
                                        .endif  ; Is requested_relativeID = 0 and is LID owned?
                                        inc     [rel_ID_count]
                                .else           ; requested_relativeID = rel_ID_count)

                                     ;*******************************************
                                     ; Caller wants this LID only.  Now check to
                                     ; see if the LID owned.
                                     ;*******************************************

                                        .if < < WORD PTR ds:[si] > eq 0 > or
                                        .if < < WORD PTR ds:[si] > eq 0FFFEh > and
                                        .if <[Device_state] eq 1 >

                                        ;*******************************************
                                        ; LID is not owned.  Assign it to the caller
                                        ;*******************************************

                                                .if <[Device_state] eq 1 >
                                                        mov     ax, 0FFFEH
                                                .else
                                                        mov     ax, [Owner_tag]
                                                .endif
                                                mov     ds:[si], ax
                                                clc
                                                mov     ax, [lid_count]
                                        .else   ; (LIDTable[lid_count] <> 0)

                                                ;**************************************
                                                ; LID is owned.  Return error
                                                ;**************************************

                                                mov     ax, ERROR_LID_ALREADY_OWNED
                                                stc
                                                jmp     getlidexit
                                        .endif  ; Is LID owned?
                                        mov     [found], TTRUE
                                .endif          ; Is requested_relativeID = rel_ID_count?
                        .endif                  ; Is the LID the desired device type?
                .endif
                inc     [lid_count]
        .endwhile
        .if < found eq FALSE >
                .if < [rel_ID_count] a 1 > and
                .if < zero bx >

                ;**********************************************************
                ;  The entire Common Data Area has been searched and at
                ;  least one LID exists that is the callers
                ;  requested_deviceID type but are all owned.
                ;**********************************************************

                        mov     ax, ERROR_LID_ALREADY_OWNED
                .else

                ;**********************************************************
                ;  The entire Common Data Area has been searched and no LID
                ;  exists that is the callers requested_deviceID type and
                ;  requested_relativeID.
                ;**********************************************************

                        mov     ax, ERROR_LID_DOES_NOT_EXIST
                .endif
                stc
        .endif  ; Is found = FALSE?
.else           ; (ABIOS not present)
        mov     ax, ERROR_ABIOS_NOT_PRESENT
        stc
.endif          ; Is ABIOS present?

getlidexit:

LeaveProc
RestoreReg      <es,ds,di,si,dx,bx>
;       INT     3                       ;<<< DEBUG >>>
ret

EndProc GetLID
;*******************************************************************

BREAK <dh_FreeLIDEntry - Release Logical ID>
;********************************************************************
;*                                                                  *
;*      SUBROUTINE NAME: dh_FreeLIDEntry                            *
;*                                                                  *
;*      DESCRIPTIVE NAME: Release a Logical ID                      *
;*                                                                  *
;*      FUNCTION: Entry point for the Devhelp Router.               *
;*                                                                  *
;*      The owner tag of the caller is moved into CX.               *
;*      dh_FreeLIDEntry calls FreeLID to check to see if the        *
;*      caller's owner tag matches the entry in the LID Ownership   *
;*      Table. If there is a match, FreeLID will release the LID    *
;*      so that it is available for another caller to claim.  If    *
;*      there is no match, the Carry Flag will be set to indicate   *
;*      that the caller does not own the requested LID.  If the LID *
;*      to free is not in the range of 3 - N then the Carry Flag    *
;*      will be set to indicate that the LID does not exist.        *
;*                                                                  *
;*      ENTRY POINT: dh_FreeLIDEntry                                *
;*      LINKAGE: far call to Device_Help with function code 35      *
;*               (DevHlp_FreeLIDEntry) in the DL register           *
;*                                                                  *
;*      INPUT:   AX  = Logical ID to Release                        *
;*               DS  = Data Segment of Requesting Device Driver     *
;*                                                                  *
;*      EXIT-NORMAL: CF = 0                                         *
;*                                                                  *
;*      EXIT-ERROR:  CF = 1                                         *
;*                   AX = ERROR_ABIOS_NOT_PRESENT                   *
;*                        ERROR_NOT_YOUR_LID                        *
;*                        ERROR_LID_DOES_NOT_EXIST                  *
;*                                                                  *
;*      EFFECTS: other than exit registers, all registers unaltered *
;*                                                                  *
;*      INTERNAL REFERENCES:                                        *
;*               ROUTINES: FreeLID                                  *
;*                                                                  *
;*      EXTERNAL REFERENCES:                                        *
;*               ROUTINES: None                                     *
;*        DATA STRUCTURES: Device Header                            *
;*                                                                  *
;********************************************************************
Procedure   dh_FreeLIDEntry
;       PROTMODE

        push    cx
        mov     cx, ds:[0].SDevProtDS   ; Get Prot Mode DS
        Call FreeLID
        pop     cx
        ret

EndProc dh_FreeLIDEntry
;*******************************************************************


;********************************************************************
;*                                                                  *
;*      SUBROUTINE NAME: FreeLIDEntry                               *
;*                                                                  *
;*      DESCRIPTIVE NAME: Release a Logical ID                      *
;*                                                                  *
;*      FUNCTION: Entry point for kernel components                 *
;*                                                                  *
;*      The owner tag of the caller is moved into CX.  FreeLIDEntry *
;*      calls FreeLID to check to see if the caller's owner tag     *
;*      matches the entry in the LID Ownership Table.  If there is  *
;*      a match, FreeLID will release the LID so that it is         *
;*      available for another caller to claim.  If there is no      *
;*      match, the Carry Flag will be set to indicate that the      *
;*      caller does not own the requested LID.  If the LID          *
;*      to free is not in the range of 3 - N then the Carry Flag    *
;*      will be set to indicate that the LID does not exist.        *
;*                                                                  *
;*      ENTRY POINT: FreeLIDEntry                                   *
;*      LINKAGE: Near call for callers in DOSCODE, far call         *
;*               otherwise                                          *
;*                                                                  *
;*      INPUT:   AX  = Logical ID to Release                        *
;*                                                                  *
;*      EXIT-NORMAL: CF = 0                                         *
;*                                                                  *
;*      EXIT-ERROR:  CF = 1                                         *
;*                   AX = ERROR_ABIOS_NOT_PRESENT                   *
;*                        ERROR_NOT_YOUR_LID                        *
;*                        ERROR_LID_DOES_NOT_EXIST                  *
;*                                                                  *
;*      EFFECTS: other than exit registers, all registers unaltered *
;*                                                                  *
;*      INTERNAL REFERENCES:                                        *
;*               ROUTINES: FreeLID                                  *
;*                                                                  *
;*      EXTERNAL REFERENCES:                                        *
;*               ROUTINES: None                                     *
;*                                                                  *
;********************************************************************
Procedure   FreeLIDEntry,hybrid
;       PROTMODE

        push    cx
        mov     cx, 0FFFFh              ; ownership tag
        Call FreeLID
        pop     cx
        ret

EndProc FreeLIDEntry
;*******************************************************************

;********************************************************************
;*                                                                  *
;*      SUBROUTINE NAME: FreeLID                                    *
;*                                                                  *
;*      DESCRIPTIVE NAME: Release a Logical ID                      *
;*                                                                  *
;*      FUNCTION:                                                   *
;*                                                                  *
;*      FreeLID will check to see if the caller's owner tag matches *
;*      the entry in the LID Ownership Table.  If there is a match  *
;*      FreeLID will release the LID so that it is available for    *
;*      another caller to claim.  If there is no match, the Carry   *
;*      Flag will be set to indicate that the caller does not own   *
;*      the requested LID.  If the LID to free is not in the range  *
;*      of 3 - N then the Carry Flag will be set to indicate that   *
;*      the LID does not exist.                                     *
;*                                                                  *
;*      ENTRY POINT: FreeLID                                        *
;*      LINKAGE: Near call                                          *
;*                                                                  *
;*      INPUT:   AX  = Logical ID to Release                        *
;*               CX  = Owner tag of the caller                      *
;*                                                                  *
;*      EXIT-NORMAL: CF = 0                                         *
;*                                                                  *
;*      EXIT-ERROR:  CF = 1                                         *
;*                   AX = ERROR_ABIOS_NOT_PRESENT                   *
;*                        ERROR_NOT_YOUR_LID                        *
;*                        ERROR_LID_DOES_NOT_EXIST                  *
;*                                                                  *
;*      EFFECTS: other than exit registers, all registers unaltered *
;*                                                                  *
;*      INTERNAL REFERENCES:                                        *
;*               ROUTINES: None                                     *
;*        DATA STRUCTURES: LID Ownership Table                      *
;*                                                                  *
;*      EXTERNAL REFERENCES:                                        *
;*               ROUTINES: None                                     *
;*                                                                  *
;********************************************************************
Procedure   FreeLID
;       PROTMODE
;       INT     3                       ;<<< DEBUG >>>

SaveReg <bx,si,ds>

DosContext      ds                      ; DS = DOSGROUP Data

.if < ABIOS_present eq TTRUE >

        mov     bx, num_LIDS

        .if < ax ae First_Available_LID > and
        .if < ax b bx >

                mov     bx, LIDTable_sel ; LID Ownership Table protect mode pointer
                mov     si, ax
                mov     ds, bx                  ; LID Ownership Table pointer
                add     si, si

                ;*******************************************
                ; Is the LID owned by the caller?
                ;*******************************************

                .if < <WORD PTR ds:[si]> eq cx > ; LIDTable[LID] = Owner_tag
                        mov     WORD PTR ds:[si], 0 ; LIDTable[LID] := 0
                        clc     ; exit normal condition (CF = 0)
                .elseif < <WORD PTR ds:[si]> eq 0FFFEH >        ; Shared LID
                        clc     ; exit normal condition (CF = 0)
                .else           ; (LIDTable[LID] <> Owner_tag)
                        mov     ax, ERROR_NOT_YOUR_LID ; exit error condition (CF = 1)
                        stc
                .endif          ; Is the LID owned by the caller?
        .else                   ; (LID is not in the range (0 - num_LIDS))
                mov     ax, ERROR_LID_DOES_NOT_EXIST ; exit error condition (CF = 1)
                stc
        .endif                  ; Is the LID is in the range (0 - num_LIDS)?
.else                           ; ABIOS not present
        mov     ax, ERROR_ABIOS_NOT_PRESENT     ; exit error condition (CF = 1)
        stc
.endif                          ; Is ABIOS present?

RestoreReg      <ds,si,bx>
;       INT     3                       ;<<< DEBUG >>>
ret

EndProc FreeLID
;*******************************************************************

BREAK <dh_ABIOSCall - ABIOS Call>
;********************************************************************
;*                                                                  *
;*      SUBROUTINE NAME: dh_ABIOSCall                               *
;*                                                                  *
;*      DESCRIPTIVE NAME: ABIOS Call Service                        *
;*                                                                  *
;*      FUNCTION: Entry point for the Devhelp Router.               *
;*                                                                  *
;*      Move the owner tag of the caller into CX.  Calls ABIOSEntry *
;*      to set up the stack according to Operating System Transfer  *
;*      Convention and invoke the desired ABIOS service.  The       *
;*      following parameters are pushed on the stack before a call  *
;*      far indirect to Function Transfer Table Pointer, which is   *
;*      code in ABIOS:                                              *
;*                                                                  *
;*      Anchor (Pointer to the appropriate CDA)                     *
;*      Request Block Pointer                                       *
;*      Device Block Pointer                                        *
;*      Function Transfer Table Pointer                             *
;*                                                                  *
;*      Clean up the stack as needed after return from              *
;*      ABIOS service.                                              *
;*                                                                  *
;*      ENTRY POINT: dh_ABIOSCall                                   *
;*      LINKAGE: far call to Device_Help with function code 36      *
;*               (DevHlp_ABIOSCall) in the DL register              *
;*                                                                  *
;*      INPUT:   AX  = Logical ID                                   *
;*               DS  = Data Segment of Requesting Device Driver     *
;*               SI  = Offset to ABIOS Request Block                *
;*               DH  = ABIOS Entry Point to Call                    *
;*                      0 => Start Entry Point                      *
;*                      1 => Interrupt Entry Point                  *
;*                      2 => Timeout Entry Point                    *
;*                                                                  *
;*      EXIT-NORMAL: CF = 0                                         *
;*                   ABIOS puts return code into request block for  *
;*                   caller process.                                *
;*                                                                  *
;*      EXIT-ERROR:  CF = 1                                         *
;*                   AX = ERROR_ABIOS_NOT_PRESENT                   *
;*                        ERROR_NOT_YOUR_LID                        *
;*                        ERROR_LID_DOES_NOT_EXIST                  *
;*                        ERROR_INVALID_ENTRY_POINT                 *
;*                                                                  *
;*      EFFECTS: other than exit registers, all registers unaltered *
;*                                                                  *
;*      INTERNAL REFERENCES:                                        *
;*               ROUTINES: ABIOSEntry                               *
;*                                                                  *
;*      EXTERNAL REFERENCES:                                        *
;*               ROUTINES: None                                     *
;*        DATA STRUCTURES: Device Header                            *
;*                                                                  *
;********************************************************************
Procedure   dh_ABIOSCall
;       DUALMODE (Called in real mode by Modeswitch code at init time)

        push    cx
        mov     cx, ds:[0].SDevProtDS           ; Get Prot Mode DS
        Call ABIOSEntry
        pop     cx
        ret

EndProc dh_ABIOSCall
;*******************************************************************


;********************************************************************
;*                                                                  *
;*      SUBROUTINE NAME: ABIOSCall                                  *
;*                                                                  *
;*      DESCRIPTIVE NAME: ABIOS Call Service                        *
;*                                                                  *
;*      FUNCTION: Entry point for kernel components                 *
;*                                                                  *
;*      Move the owner tag of the caller into CX.  Calls ABIOSEntry *
;*      to set up the stack according to Operating System Transfer  *
;*      Convention and invoke the desired ABIOS service.  The       *
;*      following parameters are pushed on the stack before a call  *
;*      far indirect to Function Transfer Table Pointer, which is   *
;*      code in ABIOS:                                              *
;*                                                                  *
;*      Anchor (Pointer to the appropriate CDA)                     *
;*      Request Block Pointer                                       *
;*      Device Block Pointer                                        *
;*      Function Transfer Table Pointer                             *
;*                                                                  *
;*      Clean up the stack as needed after return from              *
;*      ABIOS service.                                              *
;*                                                                  *
;*      ENTRY POINT: ABIOSCall                                      *
;*      LINKAGE: Near call for callers in DOSCODE, far call         *
;*               otherwise                                          *
;*                                                                  *
;*      INPUT:   AX  = Logical ID                                   *
;*               DS  = Data Segment that the Request Block resides  *
;*               SI  = Offset to ABIOS Request Block                *
;*               DH  = ABIOS Entry Point to Call                    *
;*                      0 => Start Entry Point                      *
;*                      1 => Interrupt Entry Point                  *
;*                      2 => Timeout Entry Point                    *
;*                                                                  *
;*      EXIT-NORMAL: CF = 0                                         *
;*                   ABIOS puts return code into request block for  *
;*                   caller process.                                *
;*                                                                  *
;*      EXIT-ERROR:  CF = 1                                         *
;*                   AX = ERROR_ABIOS_NOT_PRESENT                   *
;*                        ERROR_NOT_YOUR_LID                        *
;*                        ERROR_LID_DOES_NOT_EXIST                  *
;*                        ERROR_INVALID_ENTRY_POINT                 *
;*                                                                  *
;*      EFFECTS: other than exit registers, all registers unaltered *
;*                                                                  *
;*      INTERNAL REFERENCES:                                        *
;*               ROUTINES: ABIOSEntry                               *
;*                                                                  *
;*      EXTERNAL REFERENCES:                                        *
;*               ROUTINES: None                                     *
;*                                                                  *
;********************************************************************
Procedure   ABIOSCall,hybrid
;       DUALMODE (Called in real mode by Modeswitch code at init time)

        push    cx
        mov     cx, 0FFFFh                      ; ownership tag
        Call ABIOSEntry
        pop     cx
        ret

EndProc ABIOSCall
;*******************************************************************

;********************************************************************
;*                                                                  *
;*      SUBROUTINE NAME: ABIOSEntry                                 *
;*                                                                  *
;*      DESCRIPTIVE NAME: ABIOS Call Service                        *
;*                                                                  *
;*      FUNCTION:                                                   *
;*                                                                  *
;*      Sets up the stack according to the Operating System         *
;*      Transfer Convention and invoke the desired ABIOS service.   *
;*      The following parameters are pushed on the stack before a   *
;*      call far indirect to Function Transfer Table Pointer,       *
;*      which is code in ABIOS:                                     *
;*                                                                  *
;*      Anchor (Pointer to the appropriate CDA)                     *
;*      Request Block Pointer                                       *
;*      Device Block Pointer                                        *
;*      Function Transfer Table Pointer                             *
;*                                                                  *
;*      Clean up the stack as needed after return from              *
;*      ABIOS service.                                              *
;*                                                                  *
;*      ENTRY POINT: ABIOSEntry                                     *
;*      LINKAGE: Near call                                          *
;*                                                                  *
;*      INPUT:   AX  = Logical ID                                   *
;*               CX  = Owner tag of the caller                      *
;*               DS  = Data Segment that the Request Block resides  *
;*               SI  = Offset to ABIOS Request Block                *
;*               DH  = ABIOS Entry Point to Call                    *
;*                      0 => Start Entry Point                      *
;*                      1 => Interrupt Entry Point                  *
;*                      2 => Timeout Entry Point                    *
;*                                                                  *
;*      EXIT-NORMAL: CF = 0                                         *
;*                   ABIOS puts return code into request block for  *
;*                   caller process.                                *
;*                                                                  *
;*      EXIT-ERROR:  CF = 1                                         *
;*                   AX = ERROR_ABIOS_NOT_PRESENT                   *
;*                        ERROR_NOT_YOUR_LID                        *
;*                        ERROR_LID_DOES_NOT_EXIST                  *
;*                        ERROR_INVALID_ENTRY_POINT                 *
;*                                                                  *
;*      EFFECTS: other than exit registers, all registers unaltered *
;*                                                                  *
;*      INTERNAL REFERENCES:                                        *
;*               ROUTINES: None                                     *
;*        DATA STRUCTURES: LID Ownership Table                      *
;*                                                                  *
;*      EXTERNAL REFERENCES:                                        *
;*               ROUTINES: ABIOS                                    *
;*        DATA STRUCTURES: ABIOS Common Data Area                   *
;*                                                                  *
;********************************************************************
Procedure   ABIOSEntry
;       DUALMODE (Called in real mode by Modeswitch code at init time)
;       INT     3                       ;<<< DEBUG >>>

SaveReg <bx,dx,di,es>

LocalVar Callers_LID,WORD               ; Callers LID

EnterProc                               ; Save Space on the stack for above

DosContext      es                      ; ES = DOSGROUP Data

.if < es:ABIOS_present eq TTRUE > near

        .if < ax ae First_Available_LID > and near  ; LID is in the range (0 - numLIDS)
        .if < ax b es:num_LIDS > near

                mov     [Callers_LID], ax       ; Save callers LID
                mov     di, ax
                add     di, di

                whatmode        ax
                .if c                   ; If Protected Mode
                        mov     ax, es:ABIOS_CDA_anchor_p ; Address Protected Mode CDA
                        mov     bx, es:LIDTable_sel ; LID Ownership Table protect mode pointer
                .else
                        mov     ax, es:ABIOS_CDA_anchor_r ; Else Address Real Mode CDA
                        mov     bx, es:LIDTable_seg ; LID Ownership Table real mode pointer
                .endif

                mov     es, bx          ; ES:DI = LID Ownership Table pointer

                ;*******************************************
                ; Is the LID owned by the caller?
                ;*******************************************

                .if < <WORD PTR es:[di]> eq cx > or     ; LIDTable[LID] = Owner_tag
                .if < <WORD PTR es:[di]> eq 0FFFEH >     ; Shared LID

                        shl     di, 2
                        mov     es, ax          ; ES:DI = CDA Pointer

                        .if < dh be 2 > and     ; the entry point passed is in the range (0 - 2)
                        .if < es:[di].FTTSegment ne 0 > ; entry point in the function transfer table is not 0

                                ;**********************************************
                                ;  Set up the stack according to the Operating
                                ;  System Transfer convention and call ABIOS
                                ;**********************************************

                                push    es                      ; Anchor

                                push    ds                      ; RB Pointer
                                push    si
                                push    es:[di].FTTSegment      ; FTT Pointer
                                push    es:[di].FTTOffset
                                push    es:[di].DBSegment       ; DB Pointer
                                push    es:[di].DBOffset

                                call    abios_setup
                                call    dword ptr es:[bx]       ; Call ABIOS

                                add     sp, 14                  ; Clean up Stack
                                mov     ax, [Callers_LID]       ; Restore callers LID
                                clc                             ; set exit normal condition
                        .else   ; (the entry point passed is not in the range (0 - 2))
                                mov     ax, ERROR_INVALID_ENTRY_POINT ; exit error condition (CF = 1)
                                stc
                        .endif  ; Is the entry point passed in the range (0 - 2)?
                .else           ; LID is not owned by the caller
                        mov     ax, ERROR_NOT_YOUR_LID ; exit error condition (CF = 1)
                        stc
                .endif  ; Is the LID is owned by the caller?
        .else   ; LID is not in the range (First_Available_LID  - num_LIDS)
                mov     ax, ERROR_LID_DOES_NOT_EXIST ; exit error condition (CF = 1)
                stc
        .endif  ; Is the LID is in the range (First_Available_LID  - num_LIDS)?
.else           ; ABIOS not present
    mov         ax, ERROR_ABIOS_NOT_PRESENT     ; exit error condition (CF = 1)
    stc
.endif          ; Is ABIOS present?

LeaveProc

RestoreReg      <es,di,dx,bx>
;       INT     3                       ;<<< DEBUG >>>
ret

EndProc ABIOSEntry
;*******************************************************************

BREAK <dh_ABIOSCommonEntry - ABIOS Common Entry>
;********************************************************************
;*                                                                  *
;*      SUBROUTINE NAME: dh_ABIOSCommonEntry                        *
;*                                                                  *
;*      DESCRIPTIVE NAME: Call ABIOS Common Entry Point             *
;*                                                                  *
;*      FUNCTION: Entry point for the Devhelp Router.               *
;*                                                                  *
;*       Invoke the ABIOS Common Entry Point according to the ABIOS *
;*       Transfer Convention.  The following parameters are pushed  *
;*       on the stack before a call far indirect to Common Routines,*
;*       which is code in ABIOS (space is reserved on the stack for *
;*       Device Block and Function Transfer Table Pointers):        *
;*                                                                  *
;*          Anchor (Pointer to the appropriate CDA)                 *
;*          Request Block Pointer                                   *
;*                                                                  *
;*       Clean up the stack as needed after return from ABIOS       *
;*       service.                                                   *
;*                                                                  *
;*      ENTRY POINT: dh_ABIOSCommonEntry                            *
;*      LINKAGE: far call to Device_Help with function code 37      *
;*               (DevHlp_ABIOSCommonEntry) in the DL register       *
;*                                                                  *
;*      INPUT:   DS  = Data Segment of Requesting Device Driver     *
;*               SI  = Offset to Request Block                      *
;*               DH  = ABIOS Entry Point to Call                    *
;*                      0 => Start Entry Point                      *
;*                      1 => Interrupt Entry Point                  *
;*                      2 => Timeout Entry Point                    *
;*                                                                  *
;*      EXIT-NORMAL: CF = 0                                         *
;*                   ABIOS puts return code into request block for  *
;*                   caller process.                                *
;*                                                                  *
;*      EXIT-ERROR:  CF = 1                                         *
;*                   AX = ERROR_ABIOS_NOT_PRESENT                   *
;*                        ERROR_NOT_YOUR_LID                        *
;*                        ERROR_LID_DOES_NOT_EXIST                  *
;*                        ERROR_INVALID_ENTRY_POINT                 *
;*                                                                  *
;*      EFFECTS: other than exit registers, all registers unaltered *
;*                                                                  *
;*      INTERNAL REFERENCES:                                        *
;*               ROUTINES: None                                     *
;*        DATA STRUCTURES: LID Ownership Table                      *
;*                                                                  *
;*      EXTERNAL REFERENCES:                                        *
;*               ROUTINES: ABIOS                                    *
;*        DATA STRUCTURES: ABIOS Common Data Area                   *
;*                                                                  *
;********************************************************************
Procedure   dh_ABIOSCommonEntry
;       PROTMODE
;       INT     3                       ;<<< DEBUG >>>

SaveReg <bx,cx,dx,di,es>

LocalVar Callers_LID,WORD               ; Callers LID

EnterProc                               ; Save Space on the stack for above

DosContext      es                      ; ES = DOSGROUP Data

.if < es:ABIOS_present eq TTRUE > near

        mov     [Callers_LID], ax       ; Save callers AX
        mov     ax, ds:[si]+2           ; AX = LID# in the ABIOS request block

        .if < ax ae First_Available_LID > and ; LID is in the range (0 - num_LIDS)
        .if < ax b es:num_LIDS >

                mov     di, ax          ; Owner LID
                add     di, di          ; Set up for addressability to LIDTable

                mov     ax, es:ABIOS_CDA_anchor_p ; Address Protected Mode CDA
                mov     cx, es:LIDTable_sel ; LID Ownership Table protect mode pointer
                mov     bx, ds:[0].SDevProtDS   ; Get Prot Mode DS
                mov     es, cx               ; ES:DI = LID Ownership Table pointer

                ;*******************************************
                ; Is the LID owned by the caller?
                ;*******************************************

                .if < <WORD PTR es:[di]> eq bx > or     ; LIDTable[LID] = Owner_tag
                .if < <WORD PTR es:[di]> eq 0FFFEH >    ; Shared LID

                        mov       es, ax
                        mov       di, 010h      ; Offset for LID #2

                        .if < dh be 2 >         ; the entry point passed is in the range (0 - 2)

                        ;************************************************
                        ;  Set up the stack according to the ABIOS
                        ;  Transfer convention and call ABIOS
                        ;************************************************

                                push    es      ; Anchor

                                push    ds      ; RB Pointer
                                push    si
                                sub     sp, 8   ; Reserved for FTT@, DB@

                                call    abios_setup
                                call    dword ptr es:[bx]       ; Call ABIOS

                                add     sp, 14                  ; Clean up Stack
                                mov     ax, [Callers_LID]       ; Restore callers LID
                                clc                             ; set exit normal condition

                     .else      ; (the entry point passed is not in the range (0 - 2))
                          mov       ax, ERROR_INVALID_ENTRY_POINT ; exit error condition (CF = 1)
                          stc
                     .endif     ; Is the entry point passed in the range (0 - 2)?
                .else           ; LID is not owned by the caller
                        mov     ax, ERROR_NOT_YOUR_LID ; exit error condition (CF = 1)
                        stc
                .endif          ; Is the LID is owned by the caller?
        .else   ; LID is not in the range (First_Available_LID  - num_LIDS)
                mov     ax, ERROR_LID_DOES_NOT_EXIST ; exit error condition (CF = 1)
                stc
        .endif  ; Is the LID is in the range (First_Available_LID  - num_LIDS)?
.else                   ; ABIOS not present
        mov     ax, ERROR_ABIOS_NOT_PRESENT     ; exit error condition (CF = 1)
        stc
.endif          ; Is ABIOS present?

LeaveProc

RestoreReg      <es,di,dx,cx,bx>
;       INT     3                       ;<<< DEBUG >>>
ret

EndProc dh_ABIOSCommonEntry

abios_setup proc near
        mov     bx, es:[di].FTTOffset
        mov     es, es:[di].FTTSegment  ; ES:BX = FTT

        xor     dl, dl
        xchg    dh, dl
        shl     dx, 2
        add     bx, dx  ; Get Entry Point
        ret
abios_setup endp


;*******************************************************************


BREAK <dh_GetDeviceBlock - Get ABIOS Device Block>
;********************************************************************
;*                                                                  *
;*      SUBROUTINE NAME: dh_GetDeviceBlock                          *
;*                                                                  *
;*      DESCRIPTIVE NAME: Get ABIOS Device Block                    *
;*                                                                  *
;*      FUNCTION:                                                   *
;*                                                                  *
;*      Return ABIOS Device block pointers.  Returns protect mode   *
;*      pointer only.  Real mode pointer not returned, data is      *
;*      initialized to zero.                                        *
;*      This routine is callable at init time only.                 *
;*                                                                  *
;*      ENTRY POINT: dh_GetDeviceBlock                              *
;*      LINKAGE: far call to Device_Help with function code 38      *
;*               (DevHlp_GetDeviceBlock) in the DL register         *
;*                                                                  *
;*      INPUT:   DS  = Data Segment of Requesting Device Driver     *
;*               AX  = Logical ID                                   *
;*                                                                  *
;*      EXIT-NORMAL: CF = 0                                         *
;*                   CX:DX = Protect mode device block pointer      *
;*                   AX:BX = 00:00 (was real mode device block ptr) *
;*                           returned as 00:00 for compatability    *
;*      EXIT-ERROR:  CF = 1                                         *
;*                   AX = ERROR_ABIOS_NOT_PRESENT                   *
;*                        ERROR_NOT_YOUR_LID                        *
;*                        ERROR_LID_DOES_NOT_EXIST                  *
;*                                                                  *
;*      EFFECTS: other than exit registers, all registers unaltered *
;*                                                                  *
;*      INTERNAL REFERENCES:                                        *
;*               ROUTINES: None                                     *
;*        DATA STRUCTURES: LID Ownership Table                      *
;*                                                                  *
;*      EXTERNAL REFERENCES:                                        *
;*               ROUTINES: None                                     *
;*        DATA STRUCTURES: ABIOS Common Data Area                   *
;*                                                                  *
;********************************************************************
Procedure   dh_GetDeviceBlock
;       PMONLY  (called at init time only)
;       INT     3                       ;<<< DEBUG >>>

SaveReg         <di,es>
DosContext      es                                      ; ES = DOSGROUP Data

.if < es:ABIOS_present eq TTRUE > near

        .if < ax ae First_Available_LID > and near      ; LID is in the range (0 - numLIDS)
        .if < ax b es:num_LIDS > near

                mov     di, ax
                add     di, di                  ; Set up for addressability to LIDTable

                mov     es, es:LIDTable_sel     ; LID Ownership Table protect mode pointer

                mov     ax, ds:[0].SDevProtDS   ; Get Prot Mode DS
                ;*******************************************
                ; Is the LID owned by the caller?
                ;*******************************************

                .if < <WORD PTR es:[di]> eq ax > or     ; LIDTable[LID] = Owner_tag
                .if < <WORD PTR es:[di]> eq 0FFFEH >    ; Shared LID

                        shl     di, 2
                        DosContext      es                                      ; ES = DOSGROUP Data
                        xor     ax, ax                  ; zero out ax
                        xor     bx, bx                  ; zero out bx
                        mov     es, es:ABIOS_CDA_anchor_p ; Address Protected Mode CDA
                        mov     cx, es:[di].DBSegment   ; DB Pointer Segment
                        mov     dx, es:[di].DBOffset    ; DB Pointer Offset
                       ;clc                             ; clear from XOR above
                .else                                   ; LID is not owned by the caller
                        mov     ax, ERROR_NOT_YOUR_LID ; exit error condition (CF = 1)
                        stc
                .endif  ; Is the LID is owned by the caller?
        .else   ; LID is not in the range (First_Available_LID  - num_LIDS)
                mov     ax, ERROR_LID_DOES_NOT_EXIST ; exit error condition (CF = 1)
                stc
        .endif  ; Is the LID is in the range (First_Available_LID  - num_LIDS)?
.else           ; ABIOS not present
        mov     ax, ERROR_ABIOS_NOT_PRESENT     ; exit error condition (CF = 1)
        stc
.endif          ; Is ABIOS present?

RestoreReg      <es,di>
;       INT     3                       ;<<< DEBUG >>>
ret

EndProc dh_GetDeviceBlock
;*******************************************************************


BREAK <dh_ABIOSGetParms - ABIOS Get Parmaters>
;********************************************************************
;*                                                                  *
;*      SUBROUTINE NAME: dh_ABIOSGetParms                           *
;*                                                                  *
;*      DESCRIPTIVE NAME: ABIOS Get Parameters                      *
;*                                                                  *
;*      FUNCTION: Return ABIOS Parmameters to Device Driver.        *
;*                                                                  *
;*      Return the info necessary to call ABIOS from device driver. *
;*      Called only at INIT time, and only for a valid LID.         *
;*                                                                  *
;*      ENTRY POINT: dh_ABIOSGetParms                               *
;*      LINKAGE: far call to Device_Help with function code         *
;*               (DevHlp_ABIOSGetParms) in the DL register          *
;*                                                                  *
;*      INPUT:   AX  = Logical ID                                   *
;*               DS  = Data Segment of Requesting Device Driver     *
;*               SI  = Offset to ABIOS Parameter Area               *
;*                                                                  *
;*      EXIT-NORMAL: CF = 0                                         *
;*                                                                  *
;*      EXIT-ERROR:  CF = 1                                         *
;*                   AX = ERROR_ABIOS_NOT_PRESENT                   *
;*                        ERROR_NOT_YOUR_LID                        *
;*                        ERROR_LID_DOES_NOT_EXIST                  *
;*                                                                  *
;*      EFFECTS: other than exit registers, all registers unaltered *
;*                                                                  *
;*      INTERNAL REFERENCES:                                        *
;*                                                                  *
;*      EXTERNAL REFERENCES:                                        *
;*                                                                  *
;********************************************************************
Procedure   dh_ABIOSGetParms
;   PMONLY  (called at init time only)
;       INT     3                       ;<<< DEBUG >>>

    pusha
    push    es

    DosContext      <es>

    mov     cx, ds:[0].SDevProtDS                   ; Get Prot Mode DS

    .if < es:ABIOS_present eq TTRUE > near

        .if < ax ae First_Available_LID > and near  ; LID is valid range
        .if < ax b es:num_LIDS > near

            mov     di, ax
            add     di, di

            mov     es, es:LIDTable_sel             ; (es:di) = LID Ownership Tbl

            ; Test LID Ownership

            .if < <word ptr es:[di]> eq cx > or     ; LIDTable[LID] = Owner_tag
            .if < <word ptr es:[di]> eq 0FFFEH >    ; Shared LID

                shl     di, 2                       ; (di) = Offset in CDA
                DosContext  <es>                    ;        to LID Entry

                sub     ax, ax
                mov     word ptr [si].RealCDA, ax   ; Zero out Real mode data,
                mov     word ptr [si].RealFTT, ax   ; not used any more
                mov     word ptr [si].RealFTT+2, ax ; not used any more
                mov     word ptr [si].RealDB, ax    ;
                mov     word ptr [si].RealDB+2, ax  ;

                mov     ax, es:ABIOS_CDA_anchor_p
                mov     [si].ProtCDA, ax
                mov     es, ax

                mov     ax, es:[di].FTTOffset
                mov     word ptr [si].ProtFTT, ax

                mov     ax, es:[di].FTTSegment
                mov     word ptr [si].ProtFTT+2, ax

                mov     ax, es:[di].DBOffset
                mov     word ptr [si].ProtDB, ax

                mov     ax, es:[di].DBSegment
                mov     word ptr [si].ProtDB+2, ax

               ;clc                                 ; clear from SUB above
            .else
                mov     ax, ERROR_NOT_YOUR_LID
                stc
            .endif
        .else
            mov     ax, ERROR_LID_DOES_NOT_EXIST
            stc
        .endif
    .else
        mov         ax, ERROR_ABIOS_NOT_PRESENT
        stc
    .endif

    pop     es
    popa

;       INT     3                       ;<<< DEBUG >>>
    ret

EndProc dh_ABIOSGetParms


ABIOSCODE    ENDS
        END
