;*DDK*************************************************************************/
;
; COPYRIGHT (C) Microsoft Corporation, 1989
; 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.;
;*****************************************************************************/
PAGE    ,132
NAME    CDROMSTUB
TITLE   CDROM stub device driver
;/*****************************************************************************
;*
;* SOURCE FILE NAME = CDSTUB.ASM
;*
;* DESCRIPTIVE NAME = CDROM VDD V86 box stub driver
;*
;*
;* VERSION      V2.0
;*
;* DATE         08-21-91
;*
;* DESCRIPTION  small V86 CDROM stub device driver
;*
;* FUNCTIONS    The CDROM stub driver serves three purposes.
;*
;*              (1) To supply a device driver header that a DOS application
;*                  can find to determine whether CDROM is installed.
;*
;*              (2) To hook int 2fh, and forward those requests to VCDROM
;*                  through ARPL. We cannot hook int 2fh in VCDROMCreate
;*                  because the DOS kernel stomps over the interrupt table after
;*                  calling VCDROMCreate.
;*
;*              (3) To convert device driver requests other than init to
;*                  int 2F, function 1510h, and send them to VCDROM. This
;*                  support is for apps like Groliers that bypass MSCDEX,
;*                  and call the device driver directly.
;*
;*              This stub code will be copied to the VDM address space and
;*              installed by the VDD, not the loader.  It will be installed on
;*              a paragraph boundary.
;*
;* NOTES        NONE
;*
;* STRUCTURES   NONE
;*
;* EXTERNAL REFERENCES
;*
;*              NONE
;*
;* EXTERNAL FUNCTIONS
;*
;*              NONE
;*
;* CHANGE ACTIVITY =
;*   DATE      FLAG        APAR   CHANGE DESCRIPTION
;*   --------  ----------  -----  --------------------------------------
;*   mm/dd/yy  @Vr.mpppxx  xxxxx  xxxxxxx
;*   08/21/91                     created
;*
;*   08/11/92                     Changed the dos stub device driver to
;*                                use ARPL to call VCDROM via int 2fh
;*                                instead of int 66h.
;*
;*   08/11/92                     Changed the attribute word in header from
;*                                A800h to C800h.  Header was also missing
;*                                the last 4 bytes; reserved, drive letter,
;*                                and number of units supported.
;*
;*****************************************************************************/

        .8086           ; This is run in real mode

;* ***LD+ CDROM DOS STUB DD data structures
;*
;*        DD header indicates character device, open allowed,
;*        and removable media.  OldInt2f stores the address to
;*        chain to at interrupt time.  NOTE: The header must
;*        be at the start of the segment.
;*
;*

DONE            equ     0100h
Int2f           equ     2fh * 4h    ; hook vector 2f
CDROM_FUNCTION  equ     015h        ; the MSCDEX CDROM function code
VDDINTERFACE    equ     066h        ; Int vector for VDD interface

reqhdr   struc                      ; initialize header
    rh_reqlen   db      ?
    rh_unit     db      ?
    rh_command  db      ?
    rh_status   dw      ?
    rh_rs2      db      8 dup (?)
    rh_units    db      ?
    rh_addr     dd      ?
    rh_count    dw      ?
    rh_rs3      dw      ?
reqhdr ends

CODE    SEGMENT BYTE PUBLIC 'CODE'

        assume cs:CODE,ds:CODE,es:CODE

        org 0

;*
;* When this is run through the makefile, CDROMStubStart will be the
;* start of the data block, and CDROMStubLength its length.
;*
;* The next few lines are used by an REXX script.
;*
;* #### HEADERFILE=cdstub.h
;* #### ENTRYPOINT=CDROMStubStart
;* #### LENGTH=CDROMStubLength
;*
;* #### BEGIN EXTRACTION
;* It is used by n REXX script to convert the listing file into an .ASM file.
;*
;* Standard Device Driver Header follows

Header      dd  -1              ; link to nxet driver; -1 = end of list
Attrib      dw  0C800h          ; character, ioctl, ibm, removable
            dw  Strategy        ; "Strategy" entry point
            dw  Interrupt       ; "Interrupt" entry point
patch1      LABEL byte          ; #### LABEL=CDROMDevName
            db  'MSCD001 '      ; Device name, Grolliers app looks for it
            dw  0               ; reserved (must be zero)
            db  0               ; drive letter (must be zero)
patch2      LABEL byte          ; #### LABEL=CDROMNumUnits
            db  0               ; number of units supported

; Global variables go here

ReqHdr      dd  ?               ; address of Request Header
OldInt2f    dd  ?               ; old 2f handler address
ctrladdr    dw  ?               ; offset to CDROMControl


;/***************************************************************************
;*
;* FUNCTION NAME = CDROMInt2f
;*
;* DESCRIPTION   = CDROM DOS STUB Int 2f handler
;*
;*      This function catches int 2fh's.  It only reacts to the following:
;*
;*              AH=15h
;*
;*      All other functions are passed down the chain.
;*
;*      NOTE:   At VDM creation time, VCDROM loads this device driver and hooks
;*              int 2fh.  VCDROM's int 2fh handler will not be called directly
;*              since the DOS kernel loads next, hooks int 2fh, and then
;*              initializes this DOS device driver.  The DOS kernel must be
;*              last in the int 2fh chain and does not pass int 2fh requests
;*              to VCDROM.  So, this DOS device driver at init time hooks int
;*              2fh ahead of the DOS kernel.  DOS applications that issue a
;*              MSCDEX int 2fh call will be trapped by the device driver's
;*              CDROMInt2f routine and sent to VCDROM VCDROMDosLink for
;*              processing.
;*
;*              GLOBAL EFFECTS:
;*              VCDROM modifies appropriate registers and request packet
;*                fields.
;*
;*              PSEUDOCODE:
;*              Call VCDROM through local device driver routine with ARPL
;*
;* INPUT         = AX = function call
;*
;* OUTPUT        = MSCDEX request serviced
;*
;* RETURN-NORMAL =
;* RETURN-ERROR  =
;*
;**************************************************************************/

CDROMInt2f proc far

        cmp     ah, CDROM_FUNCTION      ; MSCDEX function?
        jne     short Int2fNextInt      ; nope, someone else service it

        sti
        call    word ptr cs:[ctrladdr]  ; call vcdrom via device driver hook
        iret

Int2fNextInt:
        cli
        jmp     cs:[OldInt2f]           ; chain to old handler

CDROMInt2f endp


;/***************************************************************************
;*
;* FUNCTION NAME = CDROMControl
;*
;* DESCRIPTION   = CDROM DOS STUB control function
;*
;*                 All CDROM calls get routed through here.
;*                 We simply jump to the ARPL we saved away;
;*                 the jump will eventually reach the VCDROM handler
;*                 which is sitting in protected mode.
;*
;*                 During initialization, the ARPL address will be
;*                 placed in the space labelled "patch0".
;*
;*                 The first several bytes are required by the specification.
;*
;*                 GLOBAL EFFECTS:
;*                 depends on which function was called
;*
;*                 METHOD:
;*                 Perform a short jump, followed by three nops, as required
;*                         by the specifications.
;*                 Fake an interrupt by pushing the flags, then performing
;*                         a far call.
;*
;* INPUT         = AH = function request number
;*                 other registers as appropriate
;*
;* OUTPUT        = depends on which function was called
;*
;* RETURN-NORMAL =
;* RETURN-ERROR  =
;*
;**************************************************************************/

CDROMControl    proc near
        jmp     short CDROMControlEntry ; for "hookability"
        nop                             ; NOTE: The jump must be a short
        nop                             ;  jump to indicate the end of
        nop                             ;  any hook chain.  The nop's
                                        ;  allow a far jump to be
                                        ;  patched in.

CDROMControlEntry:
        pushf

        db      09ah                    ; far call
patch0  LABEL   byte                    ; #### LABEL=CDROMPatch0
        dd      ?                       ; This number will get patched
                                        ; during installation.
        ret
CDROMControl    endp


;/***************************************************************************
;*
;* FUNCTION NAME = Strategy
;*
;* DESCRIPTION   = CDROM DOS STUB DD strategy handler
;*
;*                 This function is called by DOS whenever the driver is
;*                 accessed.
;*
;*                 GLOBAL EFFECTS:
;*                 ReqHdr  points to the request header
;*
;*                 PSEUDOCODE:
;*                 Save the address of the request packet in ReqHdr .
;*
;* INPUT         = ES:BX = Address of Request Header
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL =
;* RETURN-ERROR  =
;*
;**************************************************************************/

Strategy    proc far

        mov     word ptr cs:[ReqHdr], bx
        mov     word ptr cs:[ReqHdr+2], es

        ret

Strategy    endp


;/***************************************************************************
;*
;* FUNCTION NAME = Interrupt
;*
;* DESCRIPTION   = CDROM DOS DD Stub interrupt routine
;*
;*                 This function is called by DOS after calling Strategy.
;*
;*                 PSEUDOCODE:
;*                 Initialize - Hook 2F and set the break address.
;*                 Convert all other commands to int 2F, function 1510h and
;*                   call VCDROM through int 66h.
;*
;* INPUT         = Request packet saved by Strategy
;*
;* OUTPUT        = Request serviced, status code set
;*
;* RETURN-NORMAL =
;* RETURN-ERROR  =
;*
;**************************************************************************/

Interrupt proc far

        push    ax
        push    bx
        push    es

        les     bx, cs:[ReqHdr]

        mov     word ptr es:[bx.rh_status], DONE
        mov     al, es:[bx.rh_command]
        or      al, al
        jz      Initialize

;* Support for apps that call the driver directly.
;* Convert into a 2f, function 1510h type request and send to vcdrom.

        push    cx                      ; es:bx -> req hdr
        mov     ax, 1510h               ; 2f, send device request
        xor     cx, cx                  ; cx=0 means drive letter not passed
        call    word ptr cs:[ctrladdr]  ; call vcdrom via device driver hook
        pop     cx

InterruptExit:
        pop     es
        pop     bx
        pop     ax
        ret

        ;* all code from here on is discarded after initialization

Initialize:                             ; cannot be a function

        mov     word ptr es:[bx.rh_status], DONE
        mov     word ptr es:[bx.rh_addr], offset Initialize
        mov     word ptr es:[bx.rh_addr+2], cs

        mov     ax, offset CDROMControl         ; REXX cannot perform fixups
        mov     ctrladdr, ax                    ; must do it myself, sigh!

        xor     ax, ax                          ; hook the int 2fh handler
        mov     es, ax

        cli

        mov     ax, cs
        xchg    ax, word ptr es:[Int2f+2]
        mov     word ptr [OldInt2f+2], ax

        mov     ax, offset CDROMInt2f
        xchg    ax, word ptr es:[Int2f]
        mov     word ptr [OldInt2f], ax

        sti
        jmp     InterruptExit

Interrupt endp


CDROMEnd    label   byte           ; This line is a dummy to keep
                                   ; the REXX happy with the byte length count
                                   ; PUT ALL DATA/CODE ABOVE THIS LABEL
;*
;* #### END EXTRACTION
;*

CODE    ends
        end
