Пример #1
0
/* Called for IOCTL_VIDEO_UNSHARE_VIDEO_MEMORY.
 * Unmaps framebuffer previously mapped with IOCTL_VIDEO_SHARE_VIDEO_MEMORY.
 */
BOOLEAN VBoxMPUnshareVideoMemory(PVBOXMP_DEVEXT pExt, PVIDEO_SHARE_MEMORY pMem, PSTATUS_BLOCK pStatus)
{
    LOGF_ENTER();

    pStatus->Status = VideoPortUnmapMemory(pExt, pMem->RequestedVirtualAddress, pMem->ProcessHandle);

    LOGF_LEAVE();
    return TRUE;
}
Пример #2
0
/* Called for IOCTL_VIDEO_UNMAP_VIDEO_MEMORY.
 * Unmaps previously mapped FrameBuffer and video RAM from caller's virtual adress space.
 */
BOOLEAN VBoxMPUnmapVideoMemory(PVBOXMP_DEVEXT pExt, PVIDEO_MEMORY VideoMemory, PSTATUS_BLOCK pStatus)
{
    LOGF_ENTER();

    HGSMIAreaClear(&pExt->areaDisplay);
    pStatus->Status = VideoPortUnmapMemory(pExt, VideoMemory->RequestedVirtualAddress, NULL);

    LOGF_LEAVE();
    return TRUE;
}
Пример #3
0
BOOLEAN FASTCALL
XboxVmpUnmapVideoMemory(
   PXBOXVMP_DEVICE_EXTENSION DeviceExtension,
   PVIDEO_MEMORY VideoMemory,
   PSTATUS_BLOCK StatusBlock)
{
  VideoPortUnmapMemory(DeviceExtension, VideoMemory->RequestedVirtualAddress,
                       NULL);

  return TRUE;
}
Пример #4
0
BOOLEAN  VGAUnmapVideoMemory(IN PVOID DeviceExtension,
                             IN PVIDEO_MEMORY  MemoryToUnmap,
                             OUT PSTATUS_BLOCK  StatusBlock)
{
    if (VideoPortUnmapMemory(DeviceExtension,
                             MemoryToUnmap->RequestedVirtualAddress,
                             0) == NO_ERROR)
        return TRUE;
    else
        return FALSE;
}
void VBoxMPCmnUnmapAdapterMemory(PVBOXMP_COMMON pCommon, void **ppv)
{
    LOGF_ENTER();

    PVBOXMP_DEVEXT pPEXT = VBoxCommonToPrimaryExt(pCommon);

    if (*ppv)
    {
#ifndef VBOX_WITH_WDDM
        VP_STATUS Status;
        Status = VideoPortUnmapMemory(pPEXT, *ppv, NULL);
        VBOXMP_WARN_VPS(Status);
#else
        NTSTATUS ntStatus;
        ntStatus = pPEXT->u.primary.DxgkInterface.DxgkCbUnmapMemory(pPEXT->u.primary.DxgkInterface.DeviceHandle, *ppv);
        Assert(ntStatus == STATUS_SUCCESS);
#endif
    }

    *ppv = NULL;

    LOGF_LEAVE();
}
Пример #6
0
BOOLEAN
DGXStartIO(
    PVOID HwDeviceExtension,
    PVIDEO_REQUEST_PACKET RequestPacket
    )

/*++

Routine Description:

    This routine is the main execution routine for the miniport driver. It
    acceptss a Video Request Packet, performs the request, and then returns
    with the appropriate status.

Arguments:

    HwDeviceExtension - Supplies a pointer to the miniport's device extension.

    RequestPacket - Pointer to the video request packet. This structure
        contains all the parameters passed to the VideoIoControl function.

Return Value:


--*/

{
    PHW_DEVICE_EXTENSION hwDeviceExtension = HwDeviceExtension;
    VP_STATUS status;
    PVIDEO_MODE_INFORMATION modeInformation;
    PVIDEO_MEMORY_INFORMATION memoryInformation;
    ULONG inIoSpace, ulTemp;
    PVIDEO_CLUT clutBuffer;
    ULONG modeNumber;
    PVIDEO_SHARE_MEMORY pShareMemory;
    PVIDEO_SHARE_MEMORY_INFORMATION pShareMemoryInformation;
    PHYSICAL_ADDRESS shareAddress;
    PVOID virtualAddress;
    ULONG sharedViewSize;

    //
    // Switch on the IoContolCode in the RequestPacket. It indicates which
    // function must be performed by the driver.
    //

    switch (RequestPacket->IoControlCode) {


    case IOCTL_VIDEO_SHARE_VIDEO_MEMORY:

        VideoDebugPrint((2, "DGXStartIO - ShareVideoMemory\n"));

        if ( (RequestPacket->OutputBufferLength < sizeof(VIDEO_SHARE_MEMORY_INFORMATION)) ||
             (RequestPacket->InputBufferLength < sizeof(VIDEO_MEMORY)) ) {

            status = ERROR_INSUFFICIENT_BUFFER;
            break;

        }

        pShareMemory = RequestPacket->InputBuffer;

        if ( (pShareMemory->ViewOffset > hwDeviceExtension->FrameLength) ||
             ((pShareMemory->ViewOffset + pShareMemory->ViewSize) >
                  hwDeviceExtension->FrameLength) ) {

            status = ERROR_INVALID_PARAMETER;
            break;

        }

        RequestPacket->StatusBlock->Information =
                                    sizeof(VIDEO_SHARE_MEMORY_INFORMATION);

        //
        // Beware: the input buffer and the output buffer are the same
        // buffer, and therefore data should not be copied from one to the
        // other
        //

        virtualAddress = pShareMemory->ProcessHandle;
        sharedViewSize = pShareMemory->ViewSize;

        inIoSpace = 0;

        //
        // NOTE:  we are ignoring ViewOffset
        //

        shareAddress.QuadPart =
            hwDeviceExtension->PhysicalFrameAddress.QuadPart;

        status = VideoPortMapMemory(hwDeviceExtension,
                                    shareAddress,
                                    &sharedViewSize,
                                    &inIoSpace,
                                    &virtualAddress);

        pShareMemoryInformation = RequestPacket->OutputBuffer;

        pShareMemoryInformation->SharedViewOffset = pShareMemory->ViewOffset;
        pShareMemoryInformation->VirtualAddress = virtualAddress;
        pShareMemoryInformation->SharedViewSize = sharedViewSize;


        break;


    case IOCTL_VIDEO_UNSHARE_VIDEO_MEMORY:

        VideoDebugPrint((2, "DGXStartIO - UnshareVideoMemory\n"));

        if (RequestPacket->InputBufferLength < sizeof(VIDEO_SHARE_MEMORY)) {

            status = ERROR_INSUFFICIENT_BUFFER;
            break;

        }

        pShareMemory = RequestPacket->InputBuffer;

        status = VideoPortUnmapMemory(hwDeviceExtension,
                                      pShareMemory->RequestedVirtualAddress,
                                      pShareMemory->ProcessHandle);

        break;


    case IOCTL_VIDEO_MAP_VIDEO_MEMORY:

        VideoDebugPrint((2, "DGXStartIO - MapVideoMemory\n"));

        if ( (RequestPacket->OutputBufferLength < sizeof(VIDEO_MEMORY_INFORMATION)) ||
             (RequestPacket->InputBufferLength < sizeof(VIDEO_MEMORY)) ) {

            status = ERROR_INSUFFICIENT_BUFFER;
            break;

        }

        RequestPacket->StatusBlock->Information =  sizeof(VIDEO_MEMORY_INFORMATION);

        memoryInformation = RequestPacket->OutputBuffer;

        memoryInformation->VideoRamBase = ((PVIDEO_MEMORY)
                (RequestPacket->InputBuffer))->RequestedVirtualAddress;

        memoryInformation->VideoRamLength = hwDeviceExtension->FrameLength;

        inIoSpace = 0;

        status = VideoPortMapMemory(hwDeviceExtension,
                                    hwDeviceExtension->PhysicalFrameAddress,
                                    &(memoryInformation->VideoRamLength),
                                    &inIoSpace,
                                    &(memoryInformation->VideoRamBase));

        //
        // The frame buffer and virtual memory and equivalent in this
        // case.
        //

        memoryInformation->FrameBufferBase = memoryInformation->VideoRamBase;
        memoryInformation->FrameBufferLength = memoryInformation->VideoRamLength;

        break;


    case IOCTL_VIDEO_UNMAP_VIDEO_MEMORY:

        VideoDebugPrint((2, "DGXStartIO - UnMapVideoMemory\n"));

        if (RequestPacket->InputBufferLength < sizeof(VIDEO_MEMORY)) {

            status = ERROR_INSUFFICIENT_BUFFER;

        } else {

            status = VideoPortUnmapMemory(hwDeviceExtension,
                                          ((PVIDEO_MEMORY)
                                           (RequestPacket->InputBuffer))->
                                               RequestedVirtualAddress,
                                          0);
        }

        break;


    case IOCTL_VIDEO_QUERY_CURRENT_MODE:

        VideoDebugPrint((2, "DGXStartIO - QueryCurrentModes\n"));

        modeInformation = RequestPacket->OutputBuffer;

        if (RequestPacket->OutputBufferLength < sizeof(VIDEO_MODE_INFORMATION)) {

            status = ERROR_INSUFFICIENT_BUFFER;

        } else {

            RequestPacket->StatusBlock->Information = sizeof(VIDEO_MODE_INFORMATION);

            *((PVIDEO_MODE_INFORMATION)RequestPacket->OutputBuffer) =
                DGXModes[hwDeviceExtension->CurrentModeNumber].modeInformation;

            status = NO_ERROR;
        }

        break;

    case IOCTL_VIDEO_QUERY_AVAIL_MODES:

    {
        UCHAR i;

        VideoDebugPrint((2, "DGXStartIO - QueryAvailableModes\n"));

        if (RequestPacket->OutputBufferLength <
                hwDeviceExtension->NumValidModes * sizeof(VIDEO_MODE_INFORMATION)) {

            status = ERROR_INSUFFICIENT_BUFFER;

        } else {

            RequestPacket->StatusBlock->Information =
                 hwDeviceExtension->NumValidModes * sizeof(VIDEO_MODE_INFORMATION);

            modeInformation = RequestPacket->OutputBuffer;

            for (i = 0; i < NumDGXModes; i++) {

                if (DGXModes[i].bValid) {

                    *modeInformation = DGXModes[i].modeInformation;
                    modeInformation++;

                }
            }

            status = NO_ERROR;
        }

        break;
    }


    case IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES:

        VideoDebugPrint((2, "DGXStartIO - QueryNumAvailableModes\n"));

        //
        // Find out the size of the data to be put in the the buffer and
        // return that in the status information (whether or not the
        // information is there). If the buffer passed in is not large
        // enough return an appropriate error code.
        //
        // WARNING: This must be changed to take into account which monitor
        // is present on the machine.
        //

        if (RequestPacket->OutputBufferLength < sizeof(VIDEO_NUM_MODES)) {

            status = ERROR_INSUFFICIENT_BUFFER;

        } else {

            RequestPacket->StatusBlock->Information = sizeof(VIDEO_NUM_MODES);
            ((PVIDEO_NUM_MODES)RequestPacket->OutputBuffer)->NumModes =
                hwDeviceExtension->NumValidModes;
            ((PVIDEO_NUM_MODES)RequestPacket->OutputBuffer)->ModeInformationLength =
                sizeof(VIDEO_MODE_INFORMATION);

            status = NO_ERROR;
        }

        break;


    case IOCTL_VIDEO_SET_CURRENT_MODE:

        VideoDebugPrint((2, "DGXStartIO - SetCurrentMode\n"));

        //
        // verify data
        // WARNING: Make sure it is one of the valid modes on the list
        // calculated using the monitor information.
        //

        modeNumber = ((PVIDEO_MODE)(RequestPacket->InputBuffer))->RequestedMode;

        if ( (modeNumber >= hwDeviceExtension->NumValidModes) ||
             (!DGXModes[modeNumber].bValid) ) {

            status = ERROR_INVALID_PARAMETER;
            break;
        }

        DevInitDGX(hwDeviceExtension,
                   (PULONG)DGXModes[modeNumber].pVData,
                   DGXModes[modeNumber].Count);

        if (DGXModes[modeNumber].modeInformation.BitsPerPlane == 16) {

            DevSet16BppPalette(hwDeviceExtension);

        }

        hwDeviceExtension->CurrentModeNumber = modeNumber;

        status = NO_ERROR;

        break;


    case IOCTL_VIDEO_SET_COLOR_REGISTERS:

        VideoDebugPrint((2, "DGXStartIO - SetColorRegs\n"));

        clutBuffer = RequestPacket->InputBuffer;

        //
        // Check if the size of the data in the input buffer is large enough.
        //

        if ( (RequestPacket->InputBufferLength < sizeof(VIDEO_CLUT) -
                    sizeof(ULONG)) ||
             (RequestPacket->InputBufferLength < sizeof(VIDEO_CLUT) +
                    (sizeof(ULONG) * (clutBuffer->NumEntries - 1)) ) ) {

            status = ERROR_INSUFFICIENT_BUFFER;
            break;

        }

        if (DGXModes[hwDeviceExtension->CurrentModeNumber].
                modeInformation.BitsPerPlane == 8) {

            DevSetPalette(hwDeviceExtension,
                          (PULONG)clutBuffer->LookupTable,
                          clutBuffer->FirstEntry,
                          clutBuffer->NumEntries);

            status = NO_ERROR;
        }
        break;

    case IOCTL_VIDEO_ENABLE_POINTER:

        VideoDebugPrint((2, "DGXStartIO - EnablePointer\n"));

        ulTemp = *hwDeviceExtension->pControlRegA;
        ulTemp &= ~DAC_DISABLEPOINTER;
        DacDelay();
        *hwDeviceExtension->pControlRegA = ulTemp;

        status = NO_ERROR;

        break;


    case IOCTL_VIDEO_DISABLE_POINTER:

        VideoDebugPrint((2, "DGXStartIO - DisablePointer\n"));

        DevPointerOff(hwDeviceExtension);

        status = NO_ERROR;

        break;


    case IOCTL_VIDEO_SET_POINTER_POSITION:
    {
        PVIDEO_POINTER_POSITION pointerPosition;

        VideoDebugPrint((2, "DGXStartIO - SetpointerPostion\n"));

        pointerPosition = RequestPacket->InputBuffer;

        //
        // Check if the size of the data in the input buffer is large enough.
        //

        if (RequestPacket->InputBufferLength < sizeof(VIDEO_POINTER_POSITION)) {

            status = ERROR_INSUFFICIENT_BUFFER;

        } else {

            hwDeviceExtension->ulPointerX = (ULONG)pointerPosition->Row;
            hwDeviceExtension->ulPointerY = (ULONG)pointerPosition->Column;

            DevSetPointerPos(hwDeviceExtension,
                             (ULONG)pointerPosition->Column,
                             (ULONG)pointerPosition->Row);

            status = NO_ERROR;
        }

        break;
    }


    case IOCTL_VIDEO_QUERY_POINTER_POSITION:
    {
        PVIDEO_POINTER_POSITION pPointerPosition = RequestPacket->OutputBuffer;

        VideoDebugPrint((2, "DGXStartIO - QuerypointerPostion\n"));

        //
        // Make sure the output buffer is big enough.
        //

        if (RequestPacket->OutputBufferLength < sizeof(VIDEO_POINTER_POSITION)) {

            RequestPacket->StatusBlock->Information = 0;
            return ERROR_INSUFFICIENT_BUFFER;

        }

        //
        // Return the pointer position
        //

        RequestPacket->StatusBlock->Information = sizeof(VIDEO_POINTER_POSITION);

        pPointerPosition->Row = (SHORT)hwDeviceExtension->ulPointerX;
        pPointerPosition->Column = (SHORT)hwDeviceExtension->ulPointerY;

        status = NO_ERROR;

        break;
    }

    case IOCTL_VIDEO_SET_POINTER_ATTR:
    {
        PVIDEO_POINTER_ATTRIBUTES pointerAttributes;
        USHORT *pHWCursorShape;           // Temp Buffer
        USHORT *pHWCursorAddr;           // DAC buffer
        ULONG iCount = 512;

        VideoDebugPrint((2, "DGXStartIO - SetPointerAttributes\n"));

        pointerAttributes = RequestPacket->InputBuffer;

        //
        // Check if the size of the data in the input buffer is large enough.
        //

        if (RequestPacket->InputBufferLength <
                (sizeof(VIDEO_POINTER_ATTRIBUTES) + ((sizeof(UCHAR) *
                (CURSOR_WIDTH/8) * CURSOR_HEIGHT) * 2))) {

            status = ERROR_INSUFFICIENT_BUFFER;
            break;

        }

        //
        // If the specified cursor width or height is not valid, then
        // return an invalid parameter error.
        //

        if ((pointerAttributes->Width > CURSOR_WIDTH) ||
            (pointerAttributes->Height > CURSOR_HEIGHT)) {

            status = ERROR_INVALID_PARAMETER;
            break;

        }
        //
        // Try to copy the pointer to our buffer. When we copy it
        // we convert it to our 2bpp format. If sucessfull, then
        // copy it to the DAC and set the position.
        //

        if (!(pointerAttributes->Flags & VIDEO_MODE_ANIMATE_UPDATE)) {

            DevPointerOff(hwDeviceExtension);

        }

        if (pointerAttributes->Flags & VIDEO_MODE_MONO_POINTER) {

            if (CopyMonoCursor(hwDeviceExtension,
                               (PUCHAR)&pointerAttributes->Pixels[0])) {


                pHWCursorAddr = (USHORT *)hwDeviceExtension->pHardWareCursorAddr;
                pHWCursorShape = (USHORT *)&hwDeviceExtension->HardwareCursorShape[0];

                while (iCount--) {

                    *pHWCursorAddr++ = *pHWCursorShape++;
                    pHWCursorAddr++;
                    DacDelay();

                }

                DevSetPointerPos(hwDeviceExtension,
                                 (ULONG)pointerAttributes->Column,
                                 (ULONG)pointerAttributes->Row);

                status = NO_ERROR;

                break;

            }
        }

        //
        // Something failed. Remove the current HW Cursor.
        //

        DevPointerOff(hwDeviceExtension);

        status = ERROR_INVALID_PARAMETER;

        break;
    }

    case IOCTL_VIDEO_QUERY_POINTER_CAPABILITIES:

    {
        PVIDEO_POINTER_CAPABILITIES pointerCaps = RequestPacket->OutputBuffer;

        VideoDebugPrint((2, "DGXStartIO - QueryPointerCapabilities\n"));

        if (RequestPacket->OutputBufferLength < sizeof(VIDEO_POINTER_CAPABILITIES)) {

            RequestPacket->StatusBlock->Information = 0;
            status = ERROR_INSUFFICIENT_BUFFER;

        }

        pointerCaps->Flags = VIDEO_MODE_ASYNC_POINTER | VIDEO_MODE_MONO_POINTER;
        pointerCaps->MaxWidth = CURSOR_WIDTH;
        pointerCaps->MaxHeight = CURSOR_HEIGHT;
        pointerCaps->HWPtrBitmapStart = 0;        // No VRAM storage for pointer
        pointerCaps->HWPtrBitmapEnd = 0;

        //
        // Number of bytes we're returning.
        //

        RequestPacket->StatusBlock->Information = sizeof(VIDEO_POINTER_CAPABILITIES);

        status = NO_ERROR;

        break;

    }

    case IOCTL_VIDEO_RESET_DEVICE:

        VideoDebugPrint((2, "DGXStartIO - RESET_DEVICE\n"));

        DevDisableDGX(hwDeviceExtension);

        status = NO_ERROR;

        break;

    //
    // if we get here, an invalid IoControlCode was specified.
    //

    default:

        VideoDebugPrint((1, "Fell through DGX startIO routine - invalid command\n"));

        status = ERROR_INVALID_FUNCTION;

        break;

    }

    RequestPacket->StatusBlock->Status = status;

    return TRUE;

} // end DGXStartIO()                                                        z
Пример #7
0
/* Main I/O request handler routine. */
BOOLEAN HwVidStartIO( PVOID HwDevExt, PVIDEO_REQUEST_PACKET ReqPkt )
{
    PHW_DEV_EXT                         pExt = HwDevExt;
    VP_STATUS                           status = NO_ERROR;
    PVIDEO_MODE_INFORMATION             modeInfo;
    PVIDEO_MEMORY                       vidMem;
    PVIDEO_SHARE_MEMORY                 pShrMem;
    PVOID                               virtualAddress;
    ULONG                               inIoSpace;
    ULONG                               modeNumber;
    ULONG                               ulLen;
    ULONG                               i;

    VideoDebugPrint( (2, "videomp: HwVidStartIO: ") );

    /* Process the VRP. Required requests are handled first. */
    switch( ReqPkt->IoControlCode ) {
    case IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES:
    {
        PVIDEO_NUM_MODES        numModes;

        VideoDebugPrint( (2, "QUERY_NUM_AVAIL_MODES\n") );        
        if( ReqPkt->OutputBufferLength < sizeof( VIDEO_NUM_MODES ) ) {
            status = ERROR_INSUFFICIENT_BUFFER;
        } else {
            ReqPkt->StatusBlock->Information = sizeof( VIDEO_NUM_MODES );
            numModes = (PVIDEO_NUM_MODES)ReqPkt->OutputBuffer;
            numModes->ModeInformationLength = sizeof( VIDEO_MODE_INFORMATION );
            numModes->NumModes = pExt->NumValidModes;
        }
        break;
    }

    case IOCTL_VIDEO_QUERY_AVAIL_MODES:
        VideoDebugPrint( (2, "QUERY_AVAIL_MODES\n") );
        ulLen = pExt->NumValidModes * sizeof( VIDEO_MODE_INFORMATION );
        if( ReqPkt->OutputBufferLength < ulLen ) {
            status = ERROR_INSUFFICIENT_BUFFER;
        } else {
            ReqPkt->StatusBlock->Information = ulLen;
            modeInfo = ReqPkt->OutputBuffer;
            for( i = 0; i < ulAllModes; ++i ) {
                if( VideoModes[i].bValid ) {
                    vmpFillModeInfo( modeInfo, VideoModes[i].HorzRes,
                                     VideoModes[i].VertRes, VideoModes[i].Bpp );
                    modeInfo->ModeIndex = i; //VideoModes[i].modeInformation.ModeIndex;

                    modeInfo++;
                }
            }
        }
        break;

    case IOCTL_VIDEO_QUERY_CURRENT_MODE:
        VideoDebugPrint( (2, "QUERY_CURRENT_MODE\n") );
        if( ReqPkt->OutputBufferLength < sizeof( VIDEO_MODE_INFORMATION ) ) {
            status = ERROR_INSUFFICIENT_BUFFER;
        } else {
            ReqPkt->StatusBlock->Information = sizeof( VIDEO_MODE_INFORMATION );
            modeInfo  = ReqPkt->OutputBuffer;
            vmpFillModeInfo( modeInfo, 
                             VideoModes[pExt->CurrentModeNumber].HorzRes,
                             VideoModes[pExt->CurrentModeNumber].VertRes,
                             VideoModes[pExt->CurrentModeNumber].Bpp );
            modeInfo->ModeIndex = pExt->CurrentModeNumber; //VideoModes[pExt->CurrentModeNumber].modeInformation.ModeIndex;
        }

        break;

    case IOCTL_VIDEO_SET_CURRENT_MODE:
        VideoDebugPrint( (2, "SET_CURRENT_MODE\n") );

        /* Ensure the mode is valid. */
        modeNumber = ((PVIDEO_MODE)(ReqPkt->InputBuffer))->RequestedMode;

        if( (modeNumber > ulAllModes) || (!VideoModes[modeNumber].bValid) ) {
            status = ERROR_INVALID_PARAMETER;
            break;
        }

        BOXV_ext_mode_set( pExt, VideoModes[modeNumber].HorzRes, 
                           VideoModes[modeNumber].VertRes, VideoModes[modeNumber].Bpp,
                           VideoModes[modeNumber].HorzRes, VideoModes[modeNumber].VertRes );

        pExt->CurrentModeNumber = modeNumber;
        break;

    case IOCTL_VIDEO_RESET_DEVICE:
        VideoDebugPrint( (2, "RESET_DEVICE\n") );
	/* Not calling the following routine avoids some visual glitches. */
        /* BOXV_ext_disable( pExt ); */
        break;

    case IOCTL_VIDEO_MAP_VIDEO_MEMORY:
    {
        PVIDEO_MEMORY_INFORMATION           memInfo;

        VideoDebugPrint( (2, "MAP_VIDEO_MEMORY\n") );
        if( (ReqPkt->OutputBufferLength < sizeof( VIDEO_MEMORY_INFORMATION )) ||
            (ReqPkt->InputBufferLength < sizeof( VIDEO_MEMORY )) ) {

            status = ERROR_INSUFFICIENT_BUFFER;
            break;
        }

        ReqPkt->StatusBlock->Information =  sizeof( VIDEO_MEMORY_INFORMATION );

        vidMem    = (PVIDEO_MEMORY)ReqPkt->InputBuffer;
        memInfo   = ReqPkt->OutputBuffer;
        inIoSpace = FALSE;

        memInfo->VideoRamBase   = vidMem->RequestedVirtualAddress;
        memInfo->VideoRamLength = pExt->FramebufLen;

        status = VideoPortMapMemory( pExt, pExt->PhysicalFrameAddress,
                                     &memInfo->VideoRamLength, &inIoSpace,
                                     &memInfo->VideoRamBase );

        /* The framebuffer covers the entire video memory. */
        memInfo->FrameBufferBase   = memInfo->VideoRamBase;
        memInfo->FrameBufferLength = memInfo->VideoRamLength;
        break;
    }

    case IOCTL_VIDEO_UNMAP_VIDEO_MEMORY:
        VideoDebugPrint( (2, "UNMAP_VIDEO_MEMORY\n") );
        if( ReqPkt->InputBufferLength < sizeof( VIDEO_MEMORY ) ) {
            status = ERROR_INSUFFICIENT_BUFFER;
        } else {
            vidMem  = (PVIDEO_MEMORY)ReqPkt->InputBuffer;
            status = VideoPortUnmapMemory( pExt,
                                           vidMem->RequestedVirtualAddress,
                                           0 );
        }
        break;

    /* The following request is required for palettized modes. */
    case IOCTL_VIDEO_SET_COLOR_REGISTERS:
    {
        PVIDEO_CLUT     clutBuffer;

        VideoDebugPrint( (2, "SET_COLOR_REGISTERS\n") );
        clutBuffer = ReqPkt->InputBuffer;

        if( (ReqPkt->InputBufferLength < sizeof( VIDEO_CLUT ) - sizeof( ULONG )) ||
            (ReqPkt->InputBufferLength < sizeof( VIDEO_CLUT ) +
                    (sizeof( ULONG ) * (clutBuffer->NumEntries - 1)) ) ) {

            status = ERROR_INSUFFICIENT_BUFFER;
            break;
        }

        if( VideoModes[pExt->CurrentModeNumber].Bpp == 8 ) {
            BOXV_dac_set( pExt, clutBuffer->FirstEntry, clutBuffer->NumEntries,
                          clutBuffer->LookupTable );
        }
        break;
    }

    /* The following requests are optional. */
    case IOCTL_VIDEO_QUERY_POINTER_CAPABILITIES:
    {
        PVIDEO_POINTER_CAPABILITIES     ptrCaps = ReqPkt->OutputBuffer;

        VideoDebugPrint( (2, "QUERY_POINTER_CAPABILITIES\n") );
        if( ReqPkt->OutputBufferLength < sizeof( VIDEO_POINTER_CAPABILITIES ) ) {
            ReqPkt->StatusBlock->Information = 0;
            status = ERROR_INSUFFICIENT_BUFFER;
        }

        ptrCaps->Flags = 0;     /* Indicate no pointer support. */
        ptrCaps->MaxWidth = ptrCaps->MaxHeight = 0;
        /* Documentation and sample code disagree on whether no display
         * memory for cursor is indicated by 0 or -1.
         */
        ptrCaps->HWPtrBitmapStart = ptrCaps->HWPtrBitmapEnd = ~0;

        ReqPkt->StatusBlock->Information = sizeof( VIDEO_POINTER_CAPABILITIES );
        break;
    }

    /* The share/unshare IOCTLs are new for NT 3.51. */
    case IOCTL_VIDEO_SHARE_VIDEO_MEMORY:
    {
        PVIDEO_SHARE_MEMORY_INFORMATION     pShrMemInfo;
        PHYSICAL_ADDRESS                    shareAddress;
        ULONG                               sharedViewSize;

        VideoDebugPrint( (2, "SHARE_VIDEO_MEMORY\n") );
        if( (ReqPkt->OutputBufferLength < sizeof( VIDEO_SHARE_MEMORY_INFORMATION )) ||
            (ReqPkt->InputBufferLength < sizeof( VIDEO_MEMORY )) ) {

            status = ERROR_INSUFFICIENT_BUFFER;
            break;
        }

        pShrMem = ReqPkt->InputBuffer;

        if( (pShrMem->ViewOffset > pExt->FramebufLen) ||
            ((pShrMem->ViewOffset + pShrMem->ViewSize) > pExt->FramebufLen) ) {

            status = ERROR_INVALID_PARAMETER;
            break;
        }

        ReqPkt->StatusBlock->Information = sizeof( VIDEO_SHARE_MEMORY_INFORMATION );

        /* The input buffer is also the output buffer; remember the input. */
        virtualAddress = pShrMem->ProcessHandle;
        sharedViewSize = pShrMem->ViewSize;

        inIoSpace = FALSE;

        /* NB: ViewOffset is not being taken into account. */
        shareAddress.QuadPart = pExt->PhysicalFrameAddress.QuadPart;

        status = VideoPortMapMemory( pExt, shareAddress,
                                     &sharedViewSize, &inIoSpace,
                                     &virtualAddress );

        pShrMemInfo = ReqPkt->OutputBuffer;
        pShrMemInfo->SharedViewOffset = pShrMem->ViewOffset;
        pShrMemInfo->VirtualAddress   = virtualAddress;
        pShrMemInfo->SharedViewSize   = sharedViewSize;
        break;
    }

    case IOCTL_VIDEO_UNSHARE_VIDEO_MEMORY:
        VideoDebugPrint( (2, "UNSHARE_VIDEO_MEMORY\n") );
        if( ReqPkt->InputBufferLength < sizeof( VIDEO_SHARE_MEMORY ) ) {
            status = ERROR_INSUFFICIENT_BUFFER;
            break;
        }

        pShrMem = ReqPkt->InputBuffer;
        status = VideoPortUnmapMemory( pExt, pShrMem->RequestedVirtualAddress,
                                       pShrMem->ProcessHandle );
        break;


    /* The child state IOCTLs are new for NT 5.0 (Windows 2000). */
    case IOCTL_VIDEO_GET_CHILD_STATE:
    {
        PULONG      pChildIndex;
        PULONG      pChildState;

        VideoDebugPrint( (2, "GET_CHILD_STATE\n") );
        if( ReqPkt->InputBufferLength < sizeof( ULONG ) ||
            ReqPkt->OutputBufferLength < sizeof( ULONG ) ) {
            status = ERROR_INSUFFICIENT_BUFFER;
            break;
        }

        pChildIndex = ReqPkt->InputBuffer;
        pChildState = ReqPkt->OutputBuffer;

        /* Always say the child is active. */
        *pChildState = VIDEO_CHILD_ACTIVE;
        break;
    }

    /* Any other request is invalid and fails. */
    default:
        VideoDebugPrint( (1, "Unhandled IoControlCode %08x!\n", ReqPkt->IoControlCode) );
        status = ERROR_INVALID_FUNCTION;
        break;
    }

    ReqPkt->StatusBlock->Status = status;
    return( TRUE );
}