## Virtual Device Driver Reference for OS/2

[prev][next][parent][TOC]

### VDHInstallIOHook - Purpose

Context Issues: This function can be called only in the task context.

DOS Session Terminations: There are no DOS session termination implications for this function. I/O hooks are automatically removed during DOS session termination.

Notes: This function installs I/O port trap handlers for a contiguous range of I/O addresses. Trapping is initially enabled for the specified ports. The I/O hook entry contains the handlers for each kind of I/O operation. If an entry in the table is NULL, that I/O type is simulated by using a lower I/O type (for example, WORD-I/O is simulated by performing two-byte I/O operations). I/O port hooks are kept on a per-DOS session basis; a virtual device driver generally installs I/O hooks at DOS session creation time.

VDHSetIOHookState can be used to enable or disable I/O trapping on a per- port, per-DOS session basis except when the VDHIIH_ALWAYS_TRAP option is specified. In this case, VDHSetIOHookState cannot be called on any port in the range for the current DOS session.

I/O hooks can take their parameters either from registers or the stack. High-performance hooks take register parameters (the I/O hook router is optimized for this case). Hooks with lower performance requirements take stack parameters, and therefore can be written in the C language.

WordInput, WordOutput and Other hooks can be NULL. In this case, the DOS Session Manager simulates these routines by using the ByteInput and ByteOutput routines. If the ByteInput or ByteOutput handlers are NULL, the DOS Session Manager uses default internal routines that do input and output to the hardware ports. This is most useful when a virtual device driver shadows the hardware state (by trapping OUT instructions) but does not care what is returned by IN instructions.

The client register frame (CRF) is updated as the instructions are simulated. For example, when the string I/O instructions are simulated, the client's EDI/ESI and ECX is incremented or decremented.

In a particular DOS session, a particular I/O port address can be hooked only by a single virtual device driver. If this function fails, no I/O hooks are installed.

The routing of I/O instructions to the supplied port hooks covers the specified range exactly. If an I/O instruction overlaps port address ranges hooked on separate VDHInstallIOHook calls, the instruction is simulated with smaller I/O operations to ensure that the hooks in each range are called correctly. For example, a virtual device driver that hooks 100H-103H , and installs a byte, WORD, and DWORD (other) handler would work as follows:

        VDHInstallIOHook (reserved,0x100,4,&iohA,NULL);

The I/O instructions to each address with the length indicated cause the following hooks to be called:

    /--------------------------------------------------------------\

    |Address        |Length         |Hooks Called                  |

    |---------------+---------------+------------------------------|

    |  100          |   4           |iohA.Other(100,DWORD)         |

    |---------------+---------------+------------------------------|

    |  101          |   4           |iohA.Word(101) iohA.Byte(103) |

    |---------------+---------------+------------------------------|

    |  102          |   4           |iohA.Word(102)                |

    |---------------+---------------+------------------------------|

    |  103          |   4           |iohA.Byte(103)                |

    \--------------------------------------------------------------/

VDHRemoveIOHook must be called with identical StartingPort and NumPorts in order to remove these I/O hooks. Port hooks cannot be removed for a subset of the range of ports hooked on the call to VDHInstallIOHook. If the IOPortHookEntry is in instance data, the address passed to VDHInstallIOHook must be the same address passed to VDHRemoveIOHook or VDHSetIOHookState.

Virtual device drivers hook ports in all cases, even if the desired behavior is to act as though direct port access were allowed. This keeps the I/O Permissions Map small. Only a port that requires high performance ( for example, a graphics card) is allowed to go straight through. The existence of such ports increases the size of the I/O Permissions Map in the Task State segment even if SetIOHookState is never called for them.

Interfaces for IOPortHookEntry are as follows:

    typedef struct ioh {

        PBIH ioh_pbihByteInput;

        PBOH ioh_pbohByteOutput;

        PWIH ioh_pwihWordInput;

        PWOH ioh_pwohWordOutput;

        POTH ioh_pothOther;

    } IOH;

    BYTE HOOKENTRY ByteInput(port, pcrf)

        ENTRY    port                   - Port number

                 pcrf                   - Client register frame pointer

        EXIT     Returns data read

        USES     EAX, ECX, EDX, FS, GS, Flags

        CONTEXT  DOS session-task

    BYTE HOOKENTRY ByteOutput(bOutputData, port, pcrf)

        ENTRY    bOutputData     - Data to write

                 port            - Port number

                 pcrf            - Client register frame pointer

        EXIT     None

        USES     EAX, ECX, EDX, FS, GS, Flags

        CONTEXT  DOS session-task

    USHORT HOOKENTRY WordInput(port, pcrf)

        ENTRY    port                - Port number

                 pcrf                - Client register frame pointer

        EXIT     Returns data read

        USES     EAX, ECX, EDX, FS, GS, Flags

        CONTEXT  DOS session-task

    USHORT HOOKENTRY WordOutput(usOutputData, port, pcrf)

        ENTRY    usOutputData           - Data to write

                 port                   - Port number

                 pcrf                   - Client register frame pointer

        EXIT     None

        USES     EAX, ECX, EDX, FS, GS, Flags

        CONTEXT  DOS session-task

    ULONG HOOKENTRY Other(ulOutputData, pulInputData, port, flType, pcrf)

        ENTRY    ulOutputData               - Data for DWORD writes

                 pulInputData               - Pointer to put input data

                 port                       - Port number

                 flType                     - I/O type

                     IO_TYPE_SHIFT        - Shift for type

                     IO_TYPE_MASK         - Mask for type

                     IO_TYPE_INPUT        - If set input else output

                     IO_TYPE_BYTE         - If set byte else WORD/DWORD

                     IO_TYPE_DWORD

                     IO_TYPE_STRING

                     IO_TYPE_REVERSE

                     IO_TYPE_ADDR32

                     IO_TYPE_REP

                     IO_SEG_SHIFT         - Shift for SEG  field

                     IO_SEG_MASK          - Mask for SEG field

                     IO_SEG_CS

                     IO_SEG_SS

                     IO_SEG_ES

                     IO_SEG_FS

                     IO_SEG_GS

                 pcrf                       - Client register frame pointer

        EXIT        *pulInputData           - Data from DWORD reads

                    if returns 0, simulate the I/O operation

                    if returns a nonzero value, I/O is done

        USES     EAX, ECX, EDX, FS, GS, Flags

        CONTEXT  DOS session-task

        NOTES    (1) The ASM Other hook does not need the pulInputData

                     parameter because it returns DWORD input values in EAX,

                     with the carry flag used to indicate done/simulate. See

                     "VDHInstallIOHook" in Assembler Language Syntax.

                     The C hook has to use EAX to return status, and so needs

                     the additional parameter.