ULONG NTAPI DriverEntry(IN PVOID Context1, IN PVOID Context2) { VIDEO_HW_INITIALIZATION_DATA InitData; /* Zero initialization structure and array of extensions, one per screen */ DPRINT1("VMX-SVGAII Loading...\n"); VideoPortZeroMemory(VmxDeviceExtensionArray, sizeof(VmxDeviceExtensionArray)); VideoPortZeroMemory(&InitData, sizeof(InitData)); /* Setup the initialization structure with VideoPort */ InitData.HwInitDataSize = sizeof(VIDEO_HW_INITIALIZATION_DATA); InitData.HwFindAdapter = VmxFindAdapter; InitData.HwInitialize = VmxInitialize; InitData.HwInterrupt = VmxInterrupt; InitData.HwStartIO = VmxStartIO; InitData.HwResetHw = VmxResetHw; InitData.HwGetPowerState = VmxGetPowerState; InitData.HwSetPowerState = VmxSetPowerState; InitData.HwGetVideoChildDescriptor = VmxGetVideoChildDescriptor; InitData.AdapterInterfaceType = PCIBus; InitData.HwInitDataSize = sizeof(VIDEO_HW_INITIALIZATION_DATA); InitData.HwDeviceExtensionSize = sizeof(HW_DEVICE_EXTENSION); return VideoPortInitialize(Context1, Context2, &InitData, NULL); }
VP_STATUS NTAPI VBEGetPowerState( PVOID HwDeviceExtension, ULONG HwId, PVIDEO_POWER_MANAGEMENT VideoPowerControl) { INT10_BIOS_ARGUMENTS BiosRegisters; PVBE_DEVICE_EXTENSION VBEDeviceExtension = (PVBE_DEVICE_EXTENSION)HwDeviceExtension; if (HwId != DISPLAY_ADAPTER_HW_ID || VideoPowerControl->Length < sizeof(VIDEO_POWER_MANAGEMENT)) return ERROR_INVALID_FUNCTION; /* * Get general power support information. */ VideoPortZeroMemory(&BiosRegisters, sizeof(BiosRegisters)); BiosRegisters.Eax = VBE_POWER_MANAGEMENT_EXTENSIONS; BiosRegisters.Ebx = 0; BiosRegisters.Edi = 0; BiosRegisters.SegEs = 0; VBEDeviceExtension->Int10Interface.Int10CallBios( VBEDeviceExtension->Int10Interface.Context, &BiosRegisters); if ( VBE_GETRETURNCODE(BiosRegisters.Eax) == VBE_NOT_SUPPORTED) return ERROR_DEV_NOT_EXIST; if (VBE_GETRETURNCODE(BiosRegisters.Eax) != VBE_SUCCESS) return ERROR_INVALID_FUNCTION; /* * Get current power state. */ VideoPortZeroMemory(&BiosRegisters, sizeof(BiosRegisters)); BiosRegisters.Eax = VBE_POWER_MANAGEMENT_EXTENSIONS; BiosRegisters.Ebx = 0x2; BiosRegisters.Edi = 0; BiosRegisters.SegEs = 0; VBEDeviceExtension->Int10Interface.Int10CallBios( VBEDeviceExtension->Int10Interface.Context, &BiosRegisters); if (VBE_GETRETURNCODE(BiosRegisters.Eax) == VBE_SUCCESS) { VideoPowerControl->DPMSVersion = BiosRegisters.Ebx & 0xFF; switch (BiosRegisters.Ebx >> 8) { case 0: VideoPowerControl->PowerState = VideoPowerOn; break; case 1: VideoPowerControl->PowerState = VideoPowerStandBy; break; case 2: VideoPowerControl->PowerState = VideoPowerSuspend; break; case 4: VideoPowerControl->PowerState = VideoPowerOff; break; case 5: VideoPowerControl->PowerState = VideoPowerOn; break; default: VideoPowerControl->PowerState = VideoPowerUnspecified; } return NO_ERROR; }
ULONG NTAPI DriverEntry(IN PVOID Context1, IN PVOID Context2) { VIDEO_HW_INITIALIZATION_DATA InitData; VideoPortZeroMemory(&InitData, sizeof(InitData)); InitData.AdapterInterfaceType = PCIBus; InitData.HwInitDataSize = sizeof(VIDEO_HW_INITIALIZATION_DATA); InitData.HwFindAdapter = XboxVmpFindAdapter; InitData.HwInitialize = XboxVmpInitialize; InitData.HwStartIO = XboxVmpStartIO; InitData.HwResetHw = XboxVmpResetHw; InitData.HwGetPowerState = XboxVmpGetPowerState; InitData.HwSetPowerState = XboxVmpSetPowerState; InitData.HwDeviceExtensionSize = sizeof(XBOXVMP_DEVICE_EXTENSION); return VideoPortInitialize(Context1, Context2, &InitData, NULL); }
ULONG NTAPI DriverEntry(IN PVOID Context1, IN PVOID Context2) { VIDEO_HW_INITIALIZATION_DATA InitData; VideoPortZeroMemory(&InitData, sizeof(InitData)); InitData.HwInitDataSize = sizeof(VIDEO_HW_INITIALIZATION_DATA); InitData.HwFindAdapter = VBEFindAdapter; InitData.HwInitialize = VBEInitialize; InitData.HwStartIO = VBEStartIO; InitData.HwResetHw = VBEResetHw; InitData.HwGetPowerState = VBEGetPowerState; InitData.HwSetPowerState = VBESetPowerState; InitData.HwGetVideoChildDescriptor = VBEGetVideoChildDescriptor; InitData.HwDeviceExtensionSize = sizeof(VBE_DEVICE_EXTENSION); return VideoPortInitialize(Context1, Context2, &InitData, NULL); }
VOID VgaSizeMemory( PHW_DEVICE_EXTENSION HwDeviceExtension ) /*++ Routine Description: This routine determines the amount of VideoMemory on the adapter. Arguments: HwDeviceExtension - Pointer to the miniport driver's device extension. Return Value: None. --*/ { #ifdef INT10_MODE_SET VIDEO_X86_BIOS_ARGUMENTS biosArguments; VideoPortZeroMemory(&biosArguments, sizeof(VIDEO_X86_BIOS_ARGUMENTS)); biosArguments.Eax = 0x6f07; if (VideoPortInt10(HwDeviceExtension, &biosArguments) == NO_ERROR) { // // int 10 function 6f07 returns al = 6f, ah = # of 256K byte segments // high bit of ah = 1 if vram, 0 if dram // biosArguments.Eax &= 0x7f00; // Strip off unused bits HwDeviceExtension->AdapterMemorySize = ((biosArguments.Eax >> 8) << 18); } else
ULONG NTAPI DriverEntry(IN PVOID Context1, IN PVOID Context2) { VIDEO_HW_INITIALIZATION_DATA InitData; VideoPortZeroMemory(&InitData, sizeof InitData); InitData.HwInitDataSize = sizeof(InitData); /* FIXME: Fill in InitData members */ InitData.StartingDeviceNumber = 0; /* Export driver entry points... */ InitData.HwFindAdapter = VGAFindAdapter; InitData.HwInitialize = VGAInitialize; InitData.HwStartIO = VGAStartIO; /* InitData.HwInterrupt = VGAInterrupt; */ InitData.HwResetHw = VGAResetHw; /* InitData.HwTimer = VGATimer; */ return VideoPortInitialize(Context1, Context2, &InitData, NULL); }
/* Checks if we have a device supported by our driver and initialize * our driver/card specific information. * In particular we obtain VM monitors configuration and configure related structures. */ static VP_STATUS VBoxDrvFindAdapter(IN PVOID HwDeviceExtension, IN PVOID HwContext, IN PWSTR ArgumentString, IN OUT PVIDEO_PORT_CONFIG_INFO ConfigInfo, OUT PUCHAR Again) { RT_NOREF(HwContext, ArgumentString, Again); PVBOXMP_DEVEXT pExt = (PVBOXMP_DEVEXT) HwDeviceExtension; VP_STATUS rc; USHORT DispiId; ULONG cbVRAM = VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES; PHYSICAL_ADDRESS phVRAM = {0}; ULONG ulApertureSize = 0; PAGED_CODE(); LOGF_ENTER(); /* Init video port api */ VBoxSetupVideoPortAPI(pExt, ConfigInfo); VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ID); VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_DATA, VBE_DISPI_ID2); DispiId = VideoPortReadPortUshort((PUSHORT)VBE_DISPI_IOPORT_DATA); if (DispiId != VBE_DISPI_ID2) { WARN(("VBE card not found, returning ERROR_DEV_NOT_EXIST")); return ERROR_DEV_NOT_EXIST; } LOG(("found the VBE card")); /* * Query the adapter's memory size. It's a bit of a hack, we just read * an ULONG from the data port without setting an index before. */ cbVRAM = VideoPortReadPortUlong((PULONG)VBE_DISPI_IOPORT_DATA); /* Write hw information to registry, so that it's visible in windows property dialog */ rc = VideoPortSetRegistryParameters(pExt, L"HardwareInformation.ChipType", g_wszVBoxChipType, sizeof(g_wszVBoxChipType)); VBOXMP_WARN_VPS(rc); rc = VideoPortSetRegistryParameters(pExt, L"HardwareInformation.DacType", g_wszVBoxDACType, sizeof(g_wszVBoxDACType)); VBOXMP_WARN_VPS(rc); rc = VideoPortSetRegistryParameters(pExt, L"HardwareInformation.MemorySize", &cbVRAM, sizeof(ULONG)); VBOXMP_WARN_VPS(rc); rc = VideoPortSetRegistryParameters(pExt, L"HardwareInformation.AdapterString", g_wszVBoxAdapterString, sizeof(g_wszVBoxAdapterString)); VBOXMP_WARN_VPS(rc); rc = VideoPortSetRegistryParameters(pExt, L"HardwareInformation.BiosString", g_wszVBoxBiosString, sizeof(g_wszVBoxBiosString)); VBOXMP_WARN_VPS(rc); /* Call VideoPortGetAccessRanges to ensure interrupt info in ConfigInfo gets set up * and to get LFB aperture data. */ { VIDEO_ACCESS_RANGE tmpRanges[4]; ULONG slot = 0; VideoPortZeroMemory(tmpRanges, sizeof(tmpRanges)); if (VBoxQueryWinVersion(NULL) == WINVERSION_NT4) { /* NT crashes if either of 'vendorId, 'deviceId' or 'slot' parameters is NULL, * and needs PCI ids for a successful VideoPortGetAccessRanges call. */ ULONG vendorId = 0x80EE; ULONG deviceId = 0xBEEF; rc = VideoPortGetAccessRanges(pExt, 0, NULL, RT_ELEMENTS(tmpRanges), tmpRanges, &vendorId, &deviceId, &slot); } else { rc = VideoPortGetAccessRanges(pExt, 0, NULL, RT_ELEMENTS(tmpRanges), tmpRanges, NULL, NULL, &slot); } VBOXMP_WARN_VPS(rc); if (rc != NO_ERROR) { return rc; } /* The first non-IO range is the framebuffer. We require that information. */ for (int iRange = 0; iRange < RT_ELEMENTS(tmpRanges); ++iRange) { if (!tmpRanges[iRange].RangeInIoSpace) { phVRAM = tmpRanges[iRange].RangeStart; ulApertureSize = tmpRanges[iRange].RangeLength; break; } } } /* Initialize VBoxGuest library, which is used for requests which go through VMMDev. */ rc = VbglR0InitClient(); VBOXMP_WARN_VPS(rc); /* Preinitialize the primary extension. */ pExt->pNext = NULL; pExt->pPrimary = pExt; pExt->iDevice = 0; pExt->ulFrameBufferOffset = 0; pExt->ulFrameBufferSize = 0; pExt->u.primary.ulVbvaEnabled = 0; VideoPortZeroMemory(&pExt->areaDisplay, sizeof(HGSMIAREA)); /* Guest supports only HGSMI, the old VBVA via VMMDev is not supported. Old * code will be ifdef'ed and later removed. * The host will however support both old and new interface to keep compatibility * with old guest additions. */ VBoxSetupDisplaysHGSMI(&pExt->u.primary.commonInfo, phVRAM, ulApertureSize, cbVRAM, 0); /* Check if the chip restricts horizontal resolution or not. * Must be done after VBoxSetupDisplaysHGSMI, because it initializes the common structure. */ VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ID); VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_DATA, VBE_DISPI_ID_ANYX); DispiId = VideoPortReadPortUshort((PUSHORT)VBE_DISPI_IOPORT_DATA); if (DispiId == VBE_DISPI_ID_ANYX) VBoxCommonFromDeviceExt(pExt)->fAnyX = TRUE; else VBoxCommonFromDeviceExt(pExt)->fAnyX = FALSE; if (pExt->u.primary.commonInfo.bHGSMI) { LOGREL(("using HGSMI")); VBoxCreateDisplays(pExt, ConfigInfo); } /** @todo pretend success to make the driver work. */ rc = NO_ERROR; LOGF_LEAVE(); VBOXMP_WARN_VPS(rc); return rc; }
VP_STATUS NTAPI VmxFindAdapter(IN PVOID HwDeviceExtension, IN PVOID HwContext, IN PWSTR ArgumentString, IN OUT PVIDEO_PORT_CONFIG_INFO ConfigInfo, OUT PUCHAR Again) { VP_STATUS Status; PHW_DEVICE_EXTENSION DeviceExtension = HwDeviceExtension; DPRINT1("VMX searching for adapter\n"); /* Zero out the fields */ VideoPortZeroMemory(DeviceExtension, sizeof(HW_DEVICE_EXTENSION)); /* Validate the Config Info */ if (ConfigInfo->Length < sizeof(VIDEO_PORT_CONFIG_INFO)) { /* Incorrect OS version? */ DPRINT1("Invalid configuration info\n"); return ERROR_INVALID_PARAMETER; } /* Initialize the device extension and find the adapter */ Status = VmxInitDevice(DeviceExtension); DPRINT1("Init status: %lx\n", Status); if (Status != NO_ERROR) return ERROR_DEV_NOT_EXIST; /* Save this adapter extension */ VmxDeviceExtensionArray[0] = DeviceExtension; /* Create the sync event */ VideoPortCreateEvent(DeviceExtension, NOTIFICATION_EVENT, NULL, &DeviceExtension->SyncEvent); /* Check for multi-monitor configuration */ if (VmxIsMultiMon(DeviceExtension)) { /* Let's not go so far */ UNIMPLEMENTED; while (TRUE); } /* Zero the frame buffer */ VideoPortZeroMemory((PVOID)DeviceExtension->FrameBuffer.LowPart, DeviceExtension->VramSize.LowPart); /* Initialize the video modes */ VmxInitModes(DeviceExtension); /* Setup registry keys */ VideoPortSetRegistryParameters(DeviceExtension, L"HardwareInformation.ChipType", AdapterString, sizeof(AdapterString)); VideoPortSetRegistryParameters(DeviceExtension, L"HardwareInformation.DacType", AdapterString, sizeof(AdapterString)); VideoPortSetRegistryParameters(DeviceExtension, L"HardwareInformation.MemorySize", &DeviceExtension->VramSize.LowPart, sizeof(ULONG)); VideoPortSetRegistryParameters(DeviceExtension, L"HardwareInformation.AdapterString", AdapterString, sizeof(AdapterString)); VideoPortSetRegistryParameters(DeviceExtension, L"HardwareInformation.BiosString", AdapterString, sizeof(AdapterString)); /* No VDM support */ ConfigInfo->NumEmulatorAccessEntries = 0; ConfigInfo->EmulatorAccessEntries = 0; ConfigInfo->EmulatorAccessEntriesContext = 0; ConfigInfo->HardwareStateSize = 0; ConfigInfo->VdmPhysicalVideoMemoryAddress.QuadPart = 0; ConfigInfo->VdmPhysicalVideoMemoryLength = 0; /* Write that this is Windows XP or higher */ VmxWriteUlong(DeviceExtension, SVGA_REG_GUEST_ID, 0x5000 | 0x08); return NO_ERROR; }
ULONG DriverEntry ( PVOID Context1, PVOID Context2 ) /*++ Routine Description: Installable driver initialization entry point. This entry point is called directly by the I/O system. Arguments: Context1 - First context value passed by the operating system. This is the value with which the miniport driver calls VideoPortInitialize(). Context2 - Second context value passed by the operating system. This is the value with which the miniport driver calls VideoPortInitialize(). Return Value: Status from VideoPortInitialize() --*/ { VIDEO_HW_INITIALIZATION_DATA hwInitData; // // Zero out structure. // VideoPortZeroMemory(&hwInitData, sizeof(VIDEO_HW_INITIALIZATION_DATA)); // // Specify sizes of structure and extension. // hwInitData.HwInitDataSize = sizeof(VIDEO_HW_INITIALIZATION_DATA); // // Set entry points. // hwInitData.HwFindAdapter = DGXFindAdapter; hwInitData.HwInitialize = DGXInitialize; hwInitData.HwInterrupt = NULL; hwInitData.HwStartIO = DGXStartIO; // // Determine the size we require for the device extension. // hwInitData.HwDeviceExtensionSize = sizeof(HW_DEVICE_EXTENSION); // // Always start with parameters for device0 in this case. // // hwInitData.StartingDeviceNumber = 0; // // This device only supports the internal bus type. So return the status // value directly to the operating system. // hwInitData.AdapterInterfaceType = Eisa; return VideoPortInitialize(Context1, Context2, &hwInitData, NULL); } // end DriverEntry()
ULONG DriverEntry ( PVOID Context1, PVOID Context2 ) /*++ Routine Description: Installable driver initialization entry point. This entry point is called directly by the I/O system. Arguments: Context1 - First context value passed by the operating system. This is the value with which the miniport driver calls VideoPortInitialize(). Context2 - Second context value passed by the operating system. This is the value with which the miniport driver calls VideoPortInitialize(). Return Value: Status from VideoPortInitialize() --*/ { VIDEO_HW_INITIALIZATION_DATA hwInitData; ULONG initializationStatus; ULONG status; // // Zero out structure. // VideoPortZeroMemory(&hwInitData, sizeof(VIDEO_HW_INITIALIZATION_DATA)); // // Specify sizes of structure and extension. // hwInitData.HwInitDataSize = sizeof(VIDEO_HW_INITIALIZATION_DATA); // // Set entry points. // hwInitData.HwFindAdapter = A8514FindAdapter; hwInitData.HwInitialize = A8514Initialize; hwInitData.HwInterrupt = NULL; hwInitData.HwStartIO = A8514StartIO; // // Determine the size we require for the device extension. // hwInitData.HwDeviceExtensionSize = sizeof(HW_DEVICE_EXTENSION); // // This device only supports many bus types. // hwInitData.AdapterInterfaceType = Isa; initializationStatus = VideoPortInitialize(Context1, Context2, &hwInitData, NULL); hwInitData.AdapterInterfaceType = Eisa; status = VideoPortInitialize(Context1, Context2, &hwInitData, NULL); if (initializationStatus > status) { initializationStatus = status; } hwInitData.AdapterInterfaceType = MicroChannel; status = VideoPortInitialize(Context1, Context2, &hwInitData, NULL); if (initializationStatus > status) { initializationStatus = status; } return initializationStatus; } // end DriverEntry()
VP_STATUS NTAPI VbeSetColorLookup(IN PHW_DEVICE_EXTENSION VgaExtension, IN PVIDEO_CLUT ClutBuffer) { PVBE_COLOR_REGISTER VesaClut; INT10_BIOS_ARGUMENTS BiosArguments; PVOID Context; ULONG Entries; ULONG BufferSize = 4 * 1024; USHORT TrampolineMemorySegment, TrampolineMemoryOffset; VP_STATUS Status; USHORT i; PVIDEOMODE CurrentMode = VgaExtension->CurrentMode; Entries = ClutBuffer->NumEntries; VideoDebugPrint((0, "Setting %lu entries.\n", Entries)); /* * For Vga compatible modes, write them directly. * Otherwise, the LGPL VGABIOS (used in bochs) fails! * It is also said that this way is faster. */ if(!CurrentMode->NonVgaMode) { for (i=ClutBuffer->FirstEntry; i<ClutBuffer->FirstEntry + Entries; i++) { VideoPortWritePortUchar((PUCHAR)0x03c8, i); VideoPortWritePortUchar((PUCHAR)0x03c9, ClutBuffer->LookupTable[i].RgbArray.Red); VideoPortWritePortUchar((PUCHAR)0x03c9, ClutBuffer->LookupTable[i].RgbArray.Green); VideoPortWritePortUchar((PUCHAR)0x03c9, ClutBuffer->LookupTable[i].RgbArray.Blue); } return NO_ERROR; } /* Allocate INT10 context/buffer */ VesaClut = VideoPortAllocatePool(VgaExtension, 1, sizeof(ULONG) * Entries, ' agV'); if (!VesaClut) return ERROR_INVALID_PARAMETER; if (!VgaExtension->Int10Interface.Size) return ERROR_INVALID_PARAMETER; Context = VgaExtension->Int10Interface.Context; Status = VgaExtension->Int10Interface.Int10AllocateBuffer(Context, &TrampolineMemorySegment, &TrampolineMemoryOffset, &BufferSize); if (Status != NO_ERROR) return ERROR_INVALID_PARAMETER; /* VESA has color registers backward! */ for (i = 0; i < Entries; i++) { VesaClut[i].Blue = ClutBuffer->LookupTable[i].RgbArray.Blue; VesaClut[i].Green = ClutBuffer->LookupTable[i].RgbArray.Green; VesaClut[i].Red = ClutBuffer->LookupTable[i].RgbArray.Red; VesaClut[i].Pad = 0; } Status = VgaExtension->Int10Interface.Int10WriteMemory(Context, TrampolineMemorySegment, TrampolineMemoryOffset, VesaClut, Entries * sizeof(ULONG)); if (Status != NO_ERROR) return ERROR_INVALID_PARAMETER; /* Write the palette */ VideoPortZeroMemory(&BiosArguments, sizeof(BiosArguments)); BiosArguments.Ebx = 0; BiosArguments.Ecx = Entries; BiosArguments.Edx = ClutBuffer->FirstEntry; BiosArguments.Edi = TrampolineMemoryOffset; BiosArguments.SegEs = TrampolineMemorySegment; BiosArguments.Eax = VBE_SET_GET_PALETTE_DATA; Status = VgaExtension->Int10Interface.Int10CallBios(Context, &BiosArguments); if (Status != NO_ERROR) return ERROR_INVALID_PARAMETER; VideoPortFreePool(VgaExtension, VesaClut); VideoDebugPrint((Error, "VBE Status: %lx\n", BiosArguments.Eax)); if (VBE_GETRETURNCODE(BiosArguments.Eax) == VBE_SUCCESS) return NO_ERROR; return ERROR_INVALID_PARAMETER; }
ULONG DriverEntry ( PVOID Context1, PVOID Context2 ) /*++ Routine Description: Installable driver initialization entry point. This entry point is called directly by the I/O system. Arguments: Context1 - First context value passed by the operating system. This is the value with which the miniport driver calls VideoPortInitialize(). Context2 - Second context value passed by the operating system. This is the value with which the miniport driver calls VideoPortInitialize(). Return Value: Status from VideoPortInitialize() --*/ { VIDEO_HW_INITIALIZATION_DATA hwInitData; ULONG status; ULONG initializationStatus; // // Zero out structure. // VideoPortZeroMemory(&hwInitData, sizeof(VIDEO_HW_INITIALIZATION_DATA)); // // Specify sizes of structure and extension. // hwInitData.HwInitDataSize = sizeof(VIDEO_HW_INITIALIZATION_DATA); // // Set entry points. // hwInitData.HwFindAdapter = SimFindAdapter; hwInitData.HwInitialize = SimInitialize; hwInitData.HwInterrupt = NULL; hwInitData.HwStartIO = SimStartIO; // // Determine the size we require for the device extension. // hwInitData.HwDeviceExtensionSize = sizeof(HW_DEVICE_EXTENSION); // // Always start with parameters for device0 in this case. // // hwInitData.StartingDeviceNumber = 0; // // Once all the relevant information has been stored, call the video // port driver to do the initialization. // For this device we will repeat this call three times, for ISA, EISA // and MCA. // We will return the minimum of all return values. // hwInitData.AdapterInterfaceType = Isa; initializationStatus = VideoPortInitialize(Context1, Context2, &hwInitData, &DeviceCount); hwInitData.AdapterInterfaceType = Eisa; status = VideoPortInitialize(Context1, Context2, &hwInitData, &DeviceCount); if (initializationStatus > status) { initializationStatus = status; } hwInitData.AdapterInterfaceType = MicroChannel; status = VideoPortInitialize(Context1, Context2, &hwInitData, &DeviceCount); if (initializationStatus > status) { initializationStatus = status; } hwInitData.AdapterInterfaceType = Internal; status = VideoPortInitialize(Context1, Context2, &hwInitData, &DeviceCount); if (initializationStatus > status) { initializationStatus = status; } hwInitData.AdapterInterfaceType = PCIBus; status = VideoPortInitialize(Context1, Context2, &hwInitData, &DeviceCount); if (initializationStatus > status) { initializationStatus = status; } return initializationStatus; } // end DriverEntry()
VOID VgaValidateModes( PHW_DEVICE_EXTENSION HwDeviceExtension ) /*++ Routine Description: Determines which modes are valid and which are not. Arguments: HwDeviceExtension - Pointer to the miniport driver's device extension. Return Value: None. --*/ { ULONG i; VIDEO_X86_BIOS_ARGUMENTS biosArguments; ULONG ulAvailMemory; // Available memory on the card. /*********************************************************************** *** On the AVGA cards, the amount of memory is hardcoded *** *** in the BIOS. To determine the amount of memory available *** *** on the card, we need to perform an INT 10 bios call. *** ***********************************************************************/ VideoPortZeroMemory(&biosArguments, sizeof(VIDEO_X86_BIOS_ARGUMENTS)); /*********************************************************************** *** To find out if we only have 256Kb of RAM on the board we need *** *** to determine if 640x480x256 color modes are supported. *** *** If the mode is supported, we have at least 512kb of RAM. *** *** To determine if this mode is supported we need to perform *** *** An INT 10 call to get the video environment. *** *** AH = BFh ; AL = 03h ; BX = 00h *** *** Then we need to test bit 6. If it is set, the mode is *** *** supported and we have at least 512Kb on the board. *** ***********************************************************************/ biosArguments.Eax = 0xBF03; VideoPortInt10(HwDeviceExtension, &biosArguments); VideoDebugPrint((2,"AVGA.SYS: biosArguments.Ecx = %x\n",biosArguments.Ecx)); VideoDebugPrint((2,"AVGA.SYS: VgaValidateModes - ")); if (biosArguments.Ecx & 0x40) { VideoDebugPrint((2,"512Kb RAM on the board.\n")); ulAvailMemory = 0x80000; } else { VideoDebugPrint((2,"256Kb RAM on the board.\n")); ulAvailMemory = 0x40000; } // // Store the number of modes into the buffer. // HwDeviceExtension->NumAvailableModes = 0; for (i = 0; i < NUM_VIDEO_MODES; i++) { if (ModesVGA[i].sbytes > ulAvailMemory) { // Does the card have ModesVGA[i].ValidMode = FALSE; // enough memory to support continue; // this mode ? } if ((HwDeviceExtension->DisplayType == PANEL) && (ModesVGA[i].hres == 800)) { VideoDebugPrint((2,"AVGA.sys: VgaValidateModes - 800x600 mode with PANEL = %x\n",i)); ModesVGA[i].ValidMode = FALSE; } else { VideoDebugPrint((2,"AVGA.sys: VgaValidateModes - Valid Mode %x\n",i)); ModesVGA[i].ValidMode = TRUE; HwDeviceExtension->NumAvailableModes ++; } } VideoDebugPrint((2,"AVGA.sys: VgaValidateModes - NumMode = %x.\n", HwDeviceExtension->NumAvailableModes)); }
/* Standard NT driver initialization entry point. */ ULONG DriverEntry( PVOID Context1, PVOID Context2 ) { VIDEO_HW_INITIALIZATION_DATA hwInitData; ULONG status; VideoDebugPrint( (1, "videomp: DriverEntry\n") ); /* Prepare the initialization structure. */ VideoPortZeroMemory( &hwInitData, sizeof( VIDEO_HW_INITIALIZATION_DATA ) ); hwInitData.HwInitDataSize = sizeof( VIDEO_HW_INITIALIZATION_DATA ); /* Set up driver callbacks. */ hwInitData.HwFindAdapter = HwVidFindAdapter; hwInitData.HwInitialize = HwVidInitialize; hwInitData.HwStartIO = HwVidStartIO; /* There's no interrupt or timer callback. */ hwInitData.HwInterrupt = NULL; hwInitData.HwTimer = NULL; hwInitData.HwResetHw = HwVidResetHw; /* Power and child device management callbacks were added in NT 5.0. */ hwInitData.HwGetPowerState = HwGetPowerState; hwInitData.HwSetPowerState = HwSetPowerState; hwInitData.HwGetVideoChildDescriptor = HwGetChildDesc; /* Report legacy resources. */ hwInitData.HwLegacyResourceList = LegacyRanges; hwInitData.HwLegacyResourceCount = ulNumLegacyRanges; /* Report the device extension size. */ hwInitData.HwDeviceExtensionSize = sizeof( HW_DEV_EXT ); /* Refer to the CurrentControlSet\Services\xxx\Device0 registry key. */ hwInitData.StartingDeviceNumber = 0; /* Later NT versions support PCI; recent versions ignore this entirely */ hwInitData.AdapterInterfaceType = PCIBus; /* The PsGetVersion function was not available in NT 3.x. We therefore * implement a poor man's version detection by successively reducing the * HwInitDataSize until the video miniport (we hope) accepts it. */ do { /* First try with NT 5.1 (Windows XP) structure size. */ VideoDebugPrint( (1, "videomp: Trying DDI 5.1 HwInitDataSize\n") ); hwInitData.HwInitDataSize = SIZE_OF_WXP_VIDEO_HW_INITIALIZATION_DATA; PortVersion = VP_VER_XP; status = VideoPortInitialize( Context1, Context2, &hwInitData, NULL ); if( status != STATUS_REVISION_MISMATCH ) { /* If status is anything other than a version mismatch, don't * try calling VideoPortInitialize again. The call may have * succeeded, or it failed for some reason whe can't easily fix. */ break; } /* Try the NT 5.0 (Windows 2000) structure size. */ VideoDebugPrint( (1, "videomp: Trying DDI 5.0 HwInitDataSize\n") ); hwInitData.HwInitDataSize = SIZE_OF_W2K_VIDEO_HW_INITIALIZATION_DATA; PortVersion = VP_VER_W2K; status = VideoPortInitialize( Context1, Context2, &hwInitData, NULL ); if( status != STATUS_REVISION_MISMATCH ) { break; } /* Try the NT 4.0 (and also NT 3.51) structure size. */ VideoDebugPrint( (1, "videomp: Trying DDI 4.0 HwInitDataSize\n") ); hwInitData.HwInitDataSize = SIZE_OF_NT4_VIDEO_HW_INITIALIZATION_DATA; PortVersion = VP_VER_NT4; status = VideoPortInitialize( Context1, Context2, &hwInitData, NULL ); if( status != STATUS_REVISION_MISMATCH ) { break; } /* Try the original NT 3.1/3.5 HwInitDataSize. No PCI support. */ VideoDebugPrint( (1, "videomp: Trying DDI 3.1 HwInitDataSize\n") ); hwInitData.HwInitDataSize = offsetof( VIDEO_HW_INITIALIZATION_DATA, HwResetHw ); hwInitData.AdapterInterfaceType = Isa; PortVersion = VP_VER_NT31; status = VideoPortInitialize( Context1, Context2, &hwInitData, NULL ); } while( 0 ); VideoDebugPrint( (1, "videomp: VideoPortInitialize rc=%08x\n", status ) ); return( status ); }
/* Video Miniport Driver entry point */ ULONG DriverEntry(IN PVOID Context1, IN PVOID Context2) { PAGED_CODE(); int irc = RTR0Init(0); if (RT_FAILURE(irc)) { LogRel(("VBoxMP::failed to init IPRT (rc=%#x)", irc)); return ERROR_INVALID_FUNCTION; } LOGF_ENTER(); LOGREL(("VBox XPDM Driver for Windows version %d.%d.%dr%d, %d bit; Built %s %s", VBOX_VERSION_MAJOR, VBOX_VERSION_MINOR, VBOX_VERSION_BUILD, VBOX_SVN_REV, (sizeof (void*) << 3), __DATE__, __TIME__)); VIDEO_HW_INITIALIZATION_DATA vhwData; /*Zero the structure*/ VideoPortZeroMemory(&vhwData, sizeof(vhwData)); /*Required driver callbacks*/ vhwData.HwFindAdapter = VBoxDrvFindAdapter; vhwData.HwInitialize = VBoxDrvInitialize; vhwData.HwStartIO = VBoxDrvStartIO; vhwData.HwSetPowerState = VBoxDrvSetPowerState; vhwData.HwGetPowerState = VBoxDrvGetPowerState; vhwData.HwGetVideoChildDescriptor = VBoxDrvGetVideoChildDescriptor; /*Optional callbacks*/ vhwData.HwResetHw = VBoxDrvResetHW; #ifdef VBOX_WITH_VIDEOHWACCEL vhwData.HwInterrupt = VBoxDrvInterrupt; #endif /*Our private storage space*/ vhwData.HwDeviceExtensionSize = sizeof(VBOXMP_DEVEXT); /*Claim legacy VGA resource ranges*/ vhwData.HwLegacyResourceList = g_aVBoxLegacyVGAResources; vhwData.HwLegacyResourceCount = RT_ELEMENTS(g_aVBoxLegacyVGAResources); /*Size of this structure changes between windows/ddk versions, *so we query current version and report the expected size *to allow our driver to be loaded. */ switch (VBoxQueryWinVersion(NULL)) { case WINVERSION_NT4: LOG(("WINVERSION_NT4")); vhwData.HwInitDataSize = SIZE_OF_NT4_VIDEO_HW_INITIALIZATION_DATA; break; case WINVERSION_2K: LOG(("WINVERSION_2K")); vhwData.HwInitDataSize = SIZE_OF_W2K_VIDEO_HW_INITIALIZATION_DATA; break; default: vhwData.HwInitDataSize = sizeof(VIDEO_HW_INITIALIZATION_DATA); break; } /*Even though msdn claims that this field is ignored and should remain zero-initialized, windows NT4 SP0 dies without the following line. */ vhwData.AdapterInterfaceType = PCIBus; /*Allocate system resources*/ ULONG rc = VideoPortInitialize(Context1, Context2, &vhwData, NULL); if (rc != NO_ERROR) LOG(("VideoPortInitialize failed with %#x", rc)); LOGF_LEAVE(); return rc; }
/* Determine whether the supported adapter is present. Note that this * function is not allowed to change the state of the adapter! */ VP_STATUS HwVidFindAdapter( PVOID HwDevExt, PVOID HwContext, PWSTR ArgumentString, PVIDEO_PORT_CONFIG_INFO ConfigInfo, PUCHAR Again ) { PHW_DEV_EXT pExt = HwDevExt; PVOID *pVirtAddr; ULONG i; INT chip_id; VP_STATUS status; ULONG cbVramSize; PWSTR pwszDesc; ULONG cbDesc; #ifdef USE_GETACCESSRANGES VIDEO_ACCESS_RANGE pciAccessRanges[NUM_PCI_RANGES]; USHORT usVendorId = BOXV_PCI_VEN; USHORT usDeviceId = BOXV_PCI_DEV; ULONG ulSlot = 0; #endif //@todo: The framebuffer address should not be hardcoded for non-PCI access #define NUM_ACCESS_RANGES 2 VIDEO_ACCESS_RANGE accessRanges[NUM_ACCESS_RANGES] = { /* StartLo StartHi Len IO Vis Shr */ { 0x000001CE, 0x00000000, 0x00000002, 1, 1, 0 }, /* I/O ports */ { 0xE0000000, 0x00000000, 0x00400000, 0, 1, 0 } /* Framebuffer */ }; VideoDebugPrint( (1, "videomp: HwVidFindAdapter\n") ); /* Fail if the passed structure is smaller than the NT 3.1 version. */ if( ConfigInfo->Length < offsetof( VIDEO_PORT_CONFIG_INFO, DmaChannel ) ) { return( ERROR_INVALID_PARAMETER ); } /* Sadly, VideoPortGetAccessRanges was not present in NT 3.1. There is no * reasonably simple way to dynamically import port driver routines on * newer versions, so we'll just do without. */ #ifdef USE_GETACCESSRANGES /* If PCI is supported, query the bus for resource mappings. */ if( ConfigInfo->AdapterInterfaceType == PCIBus ) { /* Ask for bus specific access ranges. */ VideoPortZeroMemory( pciAccessRanges, sizeof( pciAccessRanges ) ); status = VideoPortGetAccessRanges( HwDevExt, 0, NULL, NUM_PCI_RANGES, pciAccessRanges, &usVendorId, &usDeviceId, &ulSlot ); if( status == NO_ERROR ) { VideoDebugPrint( (1, "videomp: Found adapter in PCI slot %d\n", ulSlot) ); pExt->ulSlot = ulSlot; /* The framebuffer is in the first slot of the PCI ranges. Copy * the data into the access ranges we're going to request. */ accessRanges[1].RangeStart = pciAccessRanges[0].RangeStart; accessRanges[1].RangeLength = pciAccessRanges[0].RangeLength; } else { /* On NT versions without PCI support, we won't even attempt this. * So if we tried to query the PCI device and failed to find it, * it really isn't there and we have to give up. */ VideoDebugPrint( (1, "videomp: PCI adapter not found\n") ); return( ERROR_DEV_NOT_EXIST ); } } #endif /* Some versions of vga.sys trap accesses to ports 0x1CE-0x1CF used on * old ATI cards. On Windows 2000 and later we can report legacy * resources to resolve this conflict. On NT 4 and older, we use a hack * and claim other, non-conflicting ports. */ if( PortVersion < VP_VER_W2K ) accessRanges[0].RangeStart = RtlConvertUlongToLargeInteger( 0x1CC ); /* Check for a conflict in case someone else claimed our resources. */ status = VideoPortVerifyAccessRanges( HwDevExt, NUM_ACCESS_RANGES, accessRanges ); if( status != NO_ERROR ) { return( status ); } /* Indicate no emulator support. */ ConfigInfo->NumEmulatorAccessEntries = 0; ConfigInfo->EmulatorAccessEntries = NULL; ConfigInfo->EmulatorAccessEntriesContext = 0; ConfigInfo->HardwareStateSize = 0; ConfigInfo->VdmPhysicalVideoMemoryAddress.LowPart = 0; ConfigInfo->VdmPhysicalVideoMemoryAddress.HighPart = 0; ConfigInfo->VdmPhysicalVideoMemoryLength = 0; /* Describe the framebuffer. We claimed the range already. */ pExt->PhysicalFrameAddress = accessRanges[1].RangeStart; /* * Map all memory and I/O ranges into system virtual address space. * NB: The virtual addresses in the HwDevExt must match the number * and type of AccessRange entries. */ pVirtAddr = &pExt->IoPorts; /* Attempt to claim and map the memory and I/O address ranges. */ for( i = 0; i < NUM_ACCESS_RANGES; ++i, ++pVirtAddr ) { *pVirtAddr = VideoPortGetDeviceBase( pExt, accessRanges[i].RangeStart, accessRanges[i].RangeLength, accessRanges[i].RangeInIoSpace ); if( *pVirtAddr == NULL ) { return( ERROR_INVALID_PARAMETER ); } } /* Verify that supported hardware is present. */ chip_id = BOXV_detect( pExt, &pExt->FramebufLen ); if( !chip_id ) { /* If supported hardware was not found, free allocated resources. */ pVirtAddr = &pExt->IoPorts; for( i = 0; i < NUM_ACCESS_RANGES; ++i, ++pVirtAddr ) VideoPortFreeDeviceBase( pExt, *pVirtAddr ); return( ERROR_DEV_NOT_EXIST ); } /* We need to access VGA and other I/O ports. Fortunately the HAL doesn't * care at all how the I/O ports are or aren't mapped on x86 platforms. */ pExt->IOAddrVGA = NULL; /* Only support one attached monitor. */ pExt->NumMonitors = 1; /* Set up mode information. */ pExt->CurrentModeNumber = 0; pExt->NumValidModes = 0; for( i = 0; i < ulAllModes; ++i ) { vmpValidateMode( &VideoModes[i], pExt->FramebufLen ); if( VideoModes[i].bValid ) ++pExt->NumValidModes; } /* Only one adapter supported, no need to call us again. */ *Again = 0; /* Report the hardware names via registry. */ #define TEMP_CHIP_NAME L"bochs Mk II" pwszDesc = TEMP_CHIP_NAME; cbDesc = sizeof( TEMP_CHIP_NAME ); VideoPortSetRegistryParameters( pExt, L"HardwareInformation.ChipType", pwszDesc, cbDesc ); #define TEMP_DAC_NAME L"Integrated DAC" pwszDesc = TEMP_DAC_NAME; cbDesc = sizeof( TEMP_DAC_NAME ); VideoPortSetRegistryParameters( pExt, L"HardwareInformation.DacType", pwszDesc, cbDesc ); #define TEMP_ADAPTER_NAME L"VirtualBox/bochs" pwszDesc = TEMP_ADAPTER_NAME; cbDesc = sizeof( TEMP_ADAPTER_NAME ); VideoPortSetRegistryParameters( pExt, L"HardwareInformation.AdapterString", pwszDesc, cbDesc ); cbVramSize = pExt->FramebufLen; VideoPortSetRegistryParameters( pExt, L"HardwareInformation.MemorySize", &cbVramSize, sizeof( ULONG ) ); /* All is well. */ return( NO_ERROR ); }
BOOLEAN NTAPI VBEInitialize(PVOID HwDeviceExtension) { INT10_BIOS_ARGUMENTS BiosRegisters; VP_STATUS Status; PVBE_DEVICE_EXTENSION VBEDeviceExtension = (PVBE_DEVICE_EXTENSION)HwDeviceExtension; ULONG Length; ULONG ModeCount; ULONG SuitableModeCount; USHORT ModeTemp; ULONG CurrentMode; PVBE_MODEINFO VbeModeInfo; /* * Get the Int 10 interface that we will use for allocating real * mode memory and calling the video BIOS. */ VBEDeviceExtension->Int10Interface.Version = VIDEO_PORT_INT10_INTERFACE_VERSION_1; VBEDeviceExtension->Int10Interface.Size = sizeof(VIDEO_PORT_INT10_INTERFACE); Status = VideoPortQueryServices( HwDeviceExtension, VideoPortServicesInt10, (PINTERFACE)&VBEDeviceExtension->Int10Interface); if (Status != NO_ERROR) { VideoPortDebugPrint(Error, "Failed to get Int 10 service functions (Status %x)\n", Status); return FALSE; } /* * Allocate a bit of memory that will be later used for VBE transport * buffer. This memory must be accessible from V86 mode so it must fit * in the first megabyte of physical memory. */ Length = 0x400; Status = VBEDeviceExtension->Int10Interface.Int10AllocateBuffer( VBEDeviceExtension->Int10Interface.Context, &VBEDeviceExtension->TrampolineMemorySegment, &VBEDeviceExtension->TrampolineMemoryOffset, &Length); if (Status != NO_ERROR) { VideoPortDebugPrint(Error, "Failed to allocate virtual memory (Status %x)\n", Status); return FALSE; } /* * Get the VBE general information. */ VBEDeviceExtension->Int10Interface.Int10WriteMemory( VBEDeviceExtension->Int10Interface.Context, VBEDeviceExtension->TrampolineMemorySegment, VBEDeviceExtension->TrampolineMemoryOffset, "VBE2", 4); VideoPortZeroMemory(&BiosRegisters, sizeof(BiosRegisters)); BiosRegisters.Eax = VBE_GET_CONTROLLER_INFORMATION; BiosRegisters.Edi = VBEDeviceExtension->TrampolineMemoryOffset; BiosRegisters.SegEs = VBEDeviceExtension->TrampolineMemorySegment; VBEDeviceExtension->Int10Interface.Int10CallBios( VBEDeviceExtension->Int10Interface.Context, &BiosRegisters); if (VBE_GETRETURNCODE(BiosRegisters.Eax) == VBE_SUCCESS) { VBEDeviceExtension->Int10Interface.Int10ReadMemory( VBEDeviceExtension->Int10Interface.Context, VBEDeviceExtension->TrampolineMemorySegment, VBEDeviceExtension->TrampolineMemoryOffset, &VBEDeviceExtension->VbeInfo, sizeof(VBEDeviceExtension->VbeInfo)); /* Verify the VBE signature. */ if (VideoPortCompareMemory(VBEDeviceExtension->VbeInfo.Signature, "VESA", 4) != 4) { VideoPortDebugPrint(Error, "No VBE BIOS present\n"); return FALSE; } VideoPortDebugPrint(Trace, "VBE BIOS Present (%d.%d, %8ld Kb)\n", VBEDeviceExtension->VbeInfo.Version / 0x100, VBEDeviceExtension->VbeInfo.Version & 0xFF, VBEDeviceExtension->VbeInfo.TotalMemory * 64); #ifdef VBE12_SUPPORT if (VBEDeviceExtension->VbeInfo.Version < 0x102) #else if (VBEDeviceExtension->VbeInfo.Version < 0x200) #endif { VideoPortDebugPrint(Error, "VBE BIOS present, but incompatible version %d.%d\n", VBEDeviceExtension->VbeInfo.Version / 0x100, VBEDeviceExtension->VbeInfo.Version & 0xFF); return FALSE; } } else { VideoPortDebugPrint(Error, "No VBE BIOS found.\n"); return FALSE; } /* * Build a mode list here that can be later used by * IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES and IOCTL_VIDEO_QUERY_AVAIL_MODES * calls. */ /* * Get the number of supported video modes. * * No need to be map the memory. It's either in the video BIOS memory or * in our trampoline memory. In either case the memory is already mapped. */ for (ModeCount = 0; ; ModeCount++) { /* Read the VBE mode number. */ VBEDeviceExtension->Int10Interface.Int10ReadMemory( VBEDeviceExtension->Int10Interface.Context, HIWORD(VBEDeviceExtension->VbeInfo.VideoModePtr), LOWORD(VBEDeviceExtension->VbeInfo.VideoModePtr) + (ModeCount << 1), &ModeTemp, sizeof(ModeTemp)); /* End of list? */ if (ModeTemp == 0xFFFF || ModeTemp == 0) break; } /* * Allocate space for video modes information. */ VBEDeviceExtension->ModeInfo = VideoPortAllocatePool(HwDeviceExtension, VpPagedPool, ModeCount * sizeof(VBE_MODEINFO), TAG_VBE); VBEDeviceExtension->ModeNumbers = VideoPortAllocatePool(HwDeviceExtension, VpPagedPool, ModeCount * sizeof(USHORT), TAG_VBE); /* * Get the actual mode infos. */ for (CurrentMode = 0, SuitableModeCount = 0; CurrentMode < ModeCount; CurrentMode++) { /* Read the VBE mode number. */ VBEDeviceExtension->Int10Interface.Int10ReadMemory( VBEDeviceExtension->Int10Interface.Context, HIWORD(VBEDeviceExtension->VbeInfo.VideoModePtr), LOWORD(VBEDeviceExtension->VbeInfo.VideoModePtr) + (CurrentMode << 1), &ModeTemp, sizeof(ModeTemp)); /* Call VBE BIOS to read the mode info. */ VideoPortZeroMemory(&BiosRegisters, sizeof(BiosRegisters)); BiosRegisters.Eax = VBE_GET_MODE_INFORMATION; BiosRegisters.Ecx = ModeTemp; BiosRegisters.Edi = VBEDeviceExtension->TrampolineMemoryOffset + 0x200; BiosRegisters.SegEs = VBEDeviceExtension->TrampolineMemorySegment; VBEDeviceExtension->Int10Interface.Int10CallBios( VBEDeviceExtension->Int10Interface.Context, &BiosRegisters); /* Read the VBE mode info. */ VBEDeviceExtension->Int10Interface.Int10ReadMemory( VBEDeviceExtension->Int10Interface.Context, VBEDeviceExtension->TrampolineMemorySegment, VBEDeviceExtension->TrampolineMemoryOffset + 0x200, VBEDeviceExtension->ModeInfo + SuitableModeCount, sizeof(VBE_MODEINFO)); VbeModeInfo = VBEDeviceExtension->ModeInfo + SuitableModeCount; /* Is this mode acceptable? */ if (VBE_GETRETURNCODE(BiosRegisters.Eax) == VBE_SUCCESS && VbeModeInfo->XResolution >= 640 && VbeModeInfo->YResolution >= 480 && (VbeModeInfo->MemoryModel == VBE_MEMORYMODEL_PACKEDPIXEL || VbeModeInfo->MemoryModel == VBE_MEMORYMODEL_DIRECTCOLOR) && VbeModeInfo->PhysBasePtr != 0) { if (VbeModeInfo->ModeAttributes & VBE_MODEATTR_LINEAR) { /* Bit 15 14 13 12 | 11 10 9 8 | 7 6 5 4 | 3 2 1 0 */ // if (ModeTemp & 0x4000) //{ VBEDeviceExtension->ModeNumbers[SuitableModeCount] = ModeTemp | 0x4000; SuitableModeCount++; //} } #ifdef VBE12_SUPPORT else { VBEDeviceExtension->ModeNumbers[SuitableModeCount] = ModeTemp; SuitableModeCount++; } #endif } } if (SuitableModeCount == 0) { VideoPortDebugPrint(Warn, "VBEMP: No video modes supported\n"); return FALSE; } VBEDeviceExtension->ModeCount = SuitableModeCount; /* * Sort the video mode list according to resolution and bits per pixel. */ VBESortModes(VBEDeviceExtension); /* * Print the supported video modes. */ for (CurrentMode = 0; CurrentMode < SuitableModeCount; CurrentMode++) { VideoPortDebugPrint(Trace, "%dx%dx%d\n", VBEDeviceExtension->ModeInfo[CurrentMode].XResolution, VBEDeviceExtension->ModeInfo[CurrentMode].YResolution, VBEDeviceExtension->ModeInfo[CurrentMode].BitsPerPixel); } /* * Enumerate our children. */ VideoPortEnumerateChildren(HwDeviceExtension, NULL); return TRUE; }
/* Checks if we have a device supported by our driver and initialize * our driver/card specific information. * In particular we obtain VM monitors configuration and configure related structures. */ static VP_STATUS VBoxDrvFindAdapter(IN PVOID HwDeviceExtension, IN PVOID HwContext, IN PWSTR ArgumentString, IN OUT PVIDEO_PORT_CONFIG_INFO ConfigInfo, OUT PUCHAR Again) { PVBOXMP_DEVEXT pExt = (PVBOXMP_DEVEXT) HwDeviceExtension; VP_STATUS rc; USHORT DispiId; ULONG AdapterMemorySize = VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES; PAGED_CODE(); LOGF_ENTER(); /* Init video port api */ VBoxSetupVideoPortAPI(pExt, ConfigInfo); VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ID); VideoPortWritePortUshort((PUSHORT)VBE_DISPI_IOPORT_DATA, VBE_DISPI_ID2); DispiId = VideoPortReadPortUshort((PUSHORT)VBE_DISPI_IOPORT_DATA); if (DispiId != VBE_DISPI_ID2) { WARN(("VBE card not found, returning ERROR_DEV_NOT_EXIST")); return ERROR_DEV_NOT_EXIST; } LOG(("found the VBE card")); /* * Query the adapter's memory size. It's a bit of a hack, we just read * an ULONG from the data port without setting an index before. */ AdapterMemorySize = VideoPortReadPortUlong((PULONG)VBE_DISPI_IOPORT_DATA); /* Write hw information to registry, so that it's visible in windows property dialog */ rc = VideoPortSetRegistryParameters(pExt, L"HardwareInformation.ChipType", VBoxChipType, sizeof(VBoxChipType)); VBOXMP_WARN_VPS(rc); rc = VideoPortSetRegistryParameters(pExt, L"HardwareInformation.DacType", VBoxDACType, sizeof(VBoxDACType)); VBOXMP_WARN_VPS(rc); rc = VideoPortSetRegistryParameters(pExt, L"HardwareInformation.MemorySize", &AdapterMemorySize, sizeof(ULONG)); VBOXMP_WARN_VPS(rc); rc = VideoPortSetRegistryParameters(pExt, L"HardwareInformation.AdapterString", VBoxAdapterString, sizeof(VBoxAdapterString)); VBOXMP_WARN_VPS(rc); rc = VideoPortSetRegistryParameters(pExt, L"HardwareInformation.BiosString", VBoxBiosString, sizeof(VBoxBiosString)); VBOXMP_WARN_VPS(rc); /* Call VideoPortGetAccessRanges to ensure interrupt info in ConfigInfo gets set up */ { VIDEO_ACCESS_RANGE tmpRanges[4]; ULONG slot = 0; VideoPortZeroMemory(tmpRanges, sizeof(tmpRanges)); if (VBoxQueryWinVersion() == WINNT4) { /* NT crashes if either of 'vendorId, 'deviceId' or 'slot' parameters is NULL, * and needs PCI ids for a successful VideoPortGetAccessRanges call. */ ULONG vendorId = 0x80EE; ULONG deviceId = 0xBEEF; rc = VideoPortGetAccessRanges(pExt, 0, NULL, RT_ELEMENTS(tmpRanges), tmpRanges, &vendorId, &deviceId, &slot); } else { rc = VideoPortGetAccessRanges(pExt, 0, NULL, RT_ELEMENTS(tmpRanges), tmpRanges, NULL, NULL, &slot); } VBOXMP_WARN_VPS(rc); } /* Initialize VBoxGuest library, which is used for requests which go through VMMDev. */ rc = VbglInit(); VBOXMP_WARN_VPS(rc); /* Preinitialize the primary extension. */ pExt->pNext = NULL; pExt->pPrimary = pExt; pExt->iDevice = 0; pExt->ulFrameBufferOffset = 0; pExt->ulFrameBufferSize = 0; pExt->u.primary.ulVbvaEnabled = 0; VideoPortZeroMemory(&pExt->areaDisplay, sizeof(HGSMIAREA)); /* Guest supports only HGSMI, the old VBVA via VMMDev is not supported. Old * code will be ifdef'ed and later removed. * The host will however support both old and new interface to keep compatibility * with old guest additions. */ VBoxSetupDisplaysHGSMI(&pExt->u.primary.commonInfo, AdapterMemorySize, 0); if (pExt->u.primary.commonInfo.bHGSMI) { LOGREL(("using HGSMI")); VBoxCreateDisplays(pExt, ConfigInfo); } /** @todo pretend success to make the driver work. */ rc = NO_ERROR; LOGF_LEAVE(); VBOXMP_WARN_VPS(rc); return rc; }
VP_STATUS VgaSetMode( PHW_DEVICE_EXTENSION HwDeviceExtension, PVIDEO_MODE Mode, ULONG ModeSize ) /*++ Routine Description: This routine sets the vga into the requested mode. Arguments: HwDeviceExtension - Pointer to the miniport driver's device extension. Mode - Pointer to the structure containing the information about the font to be set. ModeSize - Length of the input buffer supplied by the user. Return Value: ERROR_INSUFFICIENT_BUFFER if the input buffer was not large enough for the input data. ERROR_INVALID_PARAMETER if the mode number is invalid. NO_ERROR if the operation completed successfully. --*/ { PVIDEOMODE pRequestedMode; VP_STATUS status; #ifdef INT10_MODE_SET VIDEO_X86_BIOS_ARGUMENTS biosArguments; #endif // // Check if the size of the data in the input buffer is large enough. // if (ModeSize < sizeof(VIDEO_MODE)) { return ERROR_INSUFFICIENT_BUFFER; } // // Extract the clear memory bit. // if (Mode->RequestedMode & VIDEO_MODE_NO_ZERO_MEMORY) { Mode->RequestedMode &= ~VIDEO_MODE_NO_ZERO_MEMORY; } else { VgaZeroVideoMemory(HwDeviceExtension); } // // Check to see if we are requesting a valid mode // if ( (Mode->RequestedMode >= NumVideoModes) || (!ModesVGA[Mode->RequestedMode].ValidMode) ) { return ERROR_INVALID_PARAMETER; } pRequestedMode = &ModesVGA[Mode->RequestedMode]; #ifdef INT10_MODE_SET VideoPortZeroMemory(&biosArguments, sizeof(VIDEO_X86_BIOS_ARGUMENTS)); biosArguments.Ebx = pRequestedMode->Int10ModeNumber; if (biosArguments.Ebx != 0) { biosArguments.Eax = 0x6f05; status = VideoPortInt10(HwDeviceExtension, &biosArguments); if (status != NO_ERROR) { return status; } } #endif // // Call the interpreter // VgaInterpretCmdStream(HwDeviceExtension, pRequestedMode->CmdStrings[HwDeviceExtension->AdapterType]); #ifdef INT10_MODE_SET { UCHAR temp; UCHAR dummy; UCHAR bIsColor; if (!(pRequestedMode->fbType & VIDEO_MODE_GRAPHICS)) { // // Fix to make sure we always set the colors in text mode to be // intensity, and not flashing // For this zero out the Mode Control Regsiter bit 3 (index 0x10 // of the Attribute controller). // if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress + MISC_OUTPUT_REG_READ_PORT) & 0x01) { bIsColor = TRUE; } else { bIsColor = FALSE; } if (bIsColor) { dummy = VideoPortReadPortUchar(HwDeviceExtension->IOAddress + INPUT_STATUS_1_COLOR); } else { dummy = VideoPortReadPortUchar(HwDeviceExtension->IOAddress + INPUT_STATUS_1_MONO); } VideoPortWritePortUchar(HwDeviceExtension->IOAddress + ATT_ADDRESS_PORT, (0x10 | VIDEO_ENABLE)); temp = VideoPortReadPortUchar(HwDeviceExtension->IOAddress + ATT_DATA_READ_PORT); temp &= 0xF7; if (bIsColor) { dummy = VideoPortReadPortUchar(HwDeviceExtension->IOAddress + INPUT_STATUS_1_COLOR); } else { dummy = VideoPortReadPortUchar(HwDeviceExtension->IOAddress + INPUT_STATUS_1_MONO); } VideoPortWritePortUchar(HwDeviceExtension->IOAddress + ATT_ADDRESS_PORT, (0x10 | VIDEO_ENABLE)); VideoPortWritePortUchar(HwDeviceExtension->IOAddress + ATT_DATA_WRITE_PORT, temp); } } #endif // // Update the location of the physical frame buffer within video memory. // HwDeviceExtension->PhysicalFrameLength = MemoryMaps[pRequestedMode->MemMap].MaxSize; HwDeviceExtension->PhysicalFrameBase.LowPart = MemoryMaps[pRequestedMode->MemMap].Start; // // Store the new mode value. // HwDeviceExtension->ModeIndex = Mode->RequestedMode; HwDeviceExtension->CurrentMode = pRequestedMode; return NO_ERROR; } //end VgaSetMode()
/*Query video port for api functions or fill with stubs if those are not supported*/ void VBoxSetupVideoPortAPI(PVBOXMP_DEVEXT pExt, PVIDEO_PORT_CONFIG_INFO pConfigInfo) { VBOXVIDEOPORTPROCS *pAPI = &pExt->u.primary.VideoPortProcs; VideoPortZeroMemory(pAPI, sizeof(VBOXVIDEOPORTPROCS)); if (VBoxQueryWinVersion() <= WINVERSION_NT4) { /* VideoPortGetProcAddress is available for >= win2k */ pAPI->pfnWaitForSingleObject = vboxWaitForSingleObjectVoid; pAPI->pfnSetEvent = vboxSetEventVoid; pAPI->pfnClearEvent = vboxClearEventVoid; pAPI->pfnCreateEvent = vboxCreateEventVoid; pAPI->pfnDeleteEvent = vboxDeleteEventVoid; pAPI->pfnAllocatePool = vboxAllocatePoolVoid; pAPI->pfnFreePool = vboxFreePoolVoid; pAPI->pfnQueueDpc = vboxQueueDpcVoid; pAPI->pfnCreateSecondaryDisplay = vboxCreateSecondaryDisplayVoid; return; } VP_GETPROC(pfnWaitForSingleObject, PFNWAITFORSINGLEOBJECT, "VideoPortWaitForSingleObject"); VP_GETPROC(pfnSetEvent, PFNSETEVENT, "VideoPortSetEvent"); VP_GETPROC(pfnClearEvent, PFNCLEAREVENT, "VideoPortClearEvent"); VP_GETPROC(pfnCreateEvent, PFNCREATEEVENT, "VideoPortCreateEvent"); VP_GETPROC(pfnDeleteEvent, PFNDELETEEVENT, "VideoPortDeleteEvent"); if(pAPI->pfnWaitForSingleObject && pAPI->pfnSetEvent && pAPI->pfnClearEvent && pAPI->pfnCreateEvent && pAPI->pfnDeleteEvent) { pAPI->fSupportedTypes |= VBOXVIDEOPORTPROCS_EVENT; } else { pAPI->pfnWaitForSingleObject = vboxWaitForSingleObjectVoid; pAPI->pfnSetEvent = vboxSetEventVoid; pAPI->pfnClearEvent = vboxClearEventVoid; pAPI->pfnCreateEvent = vboxCreateEventVoid; pAPI->pfnDeleteEvent = vboxDeleteEventVoid; } VP_GETPROC(pfnAllocatePool, PFNALLOCATEPOOL, "VideoPortAllocatePool"); VP_GETPROC(pfnFreePool, PFNFREEPOOL, "VideoPortFreePool"); if(pAPI->pfnAllocatePool && pAPI->pfnFreePool) { pAPI->fSupportedTypes |= VBOXVIDEOPORTPROCS_POOL; } else { pAPI->pfnAllocatePool = vboxAllocatePoolVoid; pAPI->pfnFreePool = vboxFreePoolVoid; } VP_GETPROC(pfnQueueDpc, PFNQUEUEDPC, "VideoPortQueueDpc"); if(pAPI->pfnQueueDpc) { pAPI->fSupportedTypes |= VBOXVIDEOPORTPROCS_DPC; } else { pAPI->pfnQueueDpc = vboxQueueDpcVoid; } VP_GETPROC(pfnCreateSecondaryDisplay, PFNCREATESECONDARYDISPLAY, "VideoPortCreateSecondaryDisplay"); if (pAPI->pfnCreateSecondaryDisplay) { pAPI->fSupportedTypes |= VBOXVIDEOPORTPROCS_CSD; } else { pAPI->pfnCreateSecondaryDisplay = vboxCreateSecondaryDisplayVoid; } }
int VBoxVbvaEnable(PVBOXMP_DEVEXT pExt, BOOLEAN bEnable, VBVAENABLERESULT *pResult) { int rc = VINF_SUCCESS; LOGF_ENTER(); VMMDevMemory *pVMMDevMemory = NULL; rc = VbglQueryVMMDevMemory (&pVMMDevMemory); if (RT_FAILURE(rc)) { WARN(("VbglQueryVMMDevMemory rc = %#xrc", rc)); LOGF_LEAVE(); return rc; } if (pExt->iDevice>0) { PVBOXMP_DEVEXT pPrimary = pExt->pPrimary; LOGF(("skipping non-primary display %d", pExt->iDevice)); if (bEnable && pPrimary->u.primary.ulVbvaEnabled && pVMMDevMemory) { pResult->pVbvaMemory = &pVMMDevMemory->vbvaMemory; pResult->pfnFlush = VBoxVbvaFlush; pResult->pvFlush = pExt; } else { VideoPortZeroMemory(&pResult, sizeof(VBVAENABLERESULT)); } LOGF_LEAVE(); return rc; } /* Allocate the memory block for VMMDevReq_VideoAccelFlush request. */ if (pExt->u.primary.pvReqFlush == NULL) { VMMDevVideoAccelFlush *req = NULL; rc = VbglGRAlloc((VMMDevRequestHeader **)&req, sizeof(VMMDevVideoAccelFlush), VMMDevReq_VideoAccelFlush); if (RT_SUCCESS(rc)) { pExt->u.primary.pvReqFlush = req; } else { WARN(("VbglGRAlloc(VMMDevVideoAccelFlush) rc = %#xrc", rc)); LOGF_LEAVE(); return rc; } } ULONG ulEnabled = 0; VMMDevVideoAccelEnable *req = NULL; rc = VbglGRAlloc((VMMDevRequestHeader **)&req, sizeof(VMMDevVideoAccelEnable), VMMDevReq_VideoAccelEnable); if (RT_SUCCESS(rc)) { req->u32Enable = bEnable; req->cbRingBuffer = VBVA_RING_BUFFER_SIZE; req->fu32Status = 0; rc = VbglGRPerform(&req->header); if (RT_SUCCESS(rc)) { if (req->fu32Status & VBVA_F_STATUS_ACCEPTED) { LOG(("accepted")); /* Initialize the result information and VBVA memory. */ if (req->fu32Status & VBVA_F_STATUS_ENABLED) { pResult->pVbvaMemory = &pVMMDevMemory->vbvaMemory; pResult->pfnFlush = VBoxVbvaFlush; pResult->pvFlush = pExt; ulEnabled = 1; } else { VideoPortZeroMemory(&pResult, sizeof(VBVAENABLERESULT)); } } else { LOG(("rejected")); /* Disable VBVA for old hosts. */ req->u32Enable = 0; req->cbRingBuffer = VBVA_RING_BUFFER_SIZE; req->fu32Status = 0; VbglGRPerform(&req->header); rc = VERR_NOT_SUPPORTED; } } else { WARN(("rc = %#xrc", rc)); } VbglGRFree(&req->header); } else { WARN(("VbglGRAlloc(VMMDevVideoAccelEnable) rc = %#xrc", rc)); } pExt->u.primary.ulVbvaEnabled = ulEnabled; LOGF_LEAVE(); return rc; }
VP_STATUS VgaSetMode( PHW_DEVICE_EXTENSION HwDeviceExtension, PVIDEO_MODE Mode, ULONG ModeSize ) /*++ Routine Description: This routine sets the VGA into the requested mode. Arguments: HwDeviceExtension - Pointer to the miniport driver's device extension. Mode - Pointer to the structure containing the information about the font to be set. ModeSize - Length of the input buffer supplied by the user. Return Value: ERROR_INSUFFICIENT_BUFFER if the input buffer was not large enough for the input data. ERROR_INVALID_PARAMETER if the mode number is invalid. NO_ERROR if the operation completed successfully. --*/ { PVIDEOMODE pRequestedMode; VP_STATUS status; // // Check if the size of the data in the input buffer is large enough. // if (ModeSize < sizeof(VIDEO_MODE)) { return ERROR_INSUFFICIENT_BUFFER; } // // Extract the clear memory bit. // if (Mode->RequestedMode & VIDEO_MODE_NO_ZERO_MEMORY) { Mode->RequestedMode &= ~VIDEO_MODE_NO_ZERO_MEMORY; } else { VgaZeroVideoMemory(HwDeviceExtension); } // // Check to see if we are requesting a valid mode // if ((Mode->RequestedMode >= NUM_VIDEO_MODES) || (!ModesVGA[Mode->RequestedMode].ValidMode)) { VideoDebugPrint((0,"AVGA.sys: VGASetMode - ERROR_INVALID_PARAMETER.\n")); return ERROR_INVALID_PARAMETER; } pRequestedMode = &ModesVGA[Mode->RequestedMode]; HwDeviceExtension->ModeIndex = Mode->RequestedMode; // // Store the new mode value. // HwDeviceExtension->CurrentMode = pRequestedMode; #ifdef INT10_MODE_SET { VIDEO_X86_BIOS_ARGUMENTS biosArguments; UCHAR temp; UCHAR dummy; UCHAR bIsColor; /*********************************************************************** *** There appears to be a problem with some application *** *** which reset the first 16 palette registers. *** *** Since the palette is not reset when going to and *** *** from text modes by doing a set mode (instead of *** *** the hardware save restore), some colors might not *** *** appear as expected in the text modes. The bios *** *** calls seem to reload the palette so Andre Vachon *** *** suggested that we implement an Int10 mode set for the *** *** text modes. *** *** To accomplish this, we need to hard code the first *** *** three modes in modeset.h in the following switch. *** *** If more text modes are added to modeset.h, their *** *** index must be added to this switch statement. *** ***********************************************************************/ VideoPortZeroMemory(&biosArguments, sizeof(VIDEO_X86_BIOS_ARGUMENTS)); switch (Mode->RequestedMode) { case 0: // 720x400 /*********************************************************************** *** Prepare the card for the VGA mode 3+ instead of the CGA mode 3 *** ***********************************************************************/ biosArguments.Eax = 0x1202; // Select Scan line number biosArguments.Ebx = 0x0030; // to be 400 scan lines status = VideoPortInt10(HwDeviceExtension, &biosArguments); /*********************************************************************** *** Set the video mode to BIOS mode 3. *** ***********************************************************************/ VideoPortZeroMemory(&biosArguments, sizeof(VIDEO_X86_BIOS_ARGUMENTS)); biosArguments.Eax = 0x03; // bios mode 0x03 status = VideoPortInt10(HwDeviceExtension, &biosArguments); break; case 1: // 640x350 /*********************************************************************** *** Prepare the card for the EGA mode 3* instead of the CGA mode 3 *** ***********************************************************************/ biosArguments.Eax = 0x1201; // Select Scan line number biosArguments.Ebx = 0x0030; // to be 350 scan lines status = VideoPortInt10(HwDeviceExtension, &biosArguments); /*********************************************************************** *** Set the video mode to BIOS mode 3. *** ***********************************************************************/ VideoPortZeroMemory(&biosArguments, sizeof(VIDEO_X86_BIOS_ARGUMENTS)); biosArguments.Eax = 0x03; // bios mode 0x03 status = VideoPortInt10(HwDeviceExtension, &biosArguments); break; default: // all graphics modes are // handled by the default case biosArguments.Eax = pRequestedMode->Int10ModeNumber; status = VideoPortInt10(HwDeviceExtension, &biosArguments); break; } if (status != NO_ERROR) { return status; } // // Fix to get 640x350 text mode // if (!(pRequestedMode->fbType & VIDEO_MODE_GRAPHICS)) { // if ((pRequestedMode->hres == 640) && // (pRequestedMode->vres == 350)) { // // VgaInterpretCmdStream(HwDeviceExtension, VGA_TEXT_1); // // } else { // // Fix to make sure we always set the colors in text mode to be // intensity, and not flashing // For this zero out the Mode Control Regsiter bit 3 (index 0x10 // of the Attribute controller). // if (VideoPortReadPortUchar(HwDeviceExtension->IOAddress + MISC_OUTPUT_REG_READ_PORT) & 0x01) { bIsColor = TRUE; } else { bIsColor = FALSE; } if (bIsColor) { dummy = VideoPortReadPortUchar(HwDeviceExtension->IOAddress + INPUT_STATUS_1_COLOR); } else { dummy = VideoPortReadPortUchar(HwDeviceExtension->IOAddress + INPUT_STATUS_1_MONO); } VideoPortWritePortUchar(HwDeviceExtension->IOAddress + ATT_ADDRESS_PORT, (0x10 | VIDEO_ENABLE)); temp = VideoPortReadPortUchar(HwDeviceExtension->IOAddress + ATT_DATA_READ_PORT); temp &= 0xF7; if (bIsColor) { dummy = VideoPortReadPortUchar(HwDeviceExtension->IOAddress + INPUT_STATUS_1_COLOR); } else { dummy = VideoPortReadPortUchar(HwDeviceExtension->IOAddress + INPUT_STATUS_1_MONO); } VideoPortWritePortUchar(HwDeviceExtension->IOAddress + ATT_ADDRESS_PORT, (0x10 | VIDEO_ENABLE)); VideoPortWritePortUchar(HwDeviceExtension->IOAddress + ATT_DATA_WRITE_PORT, temp); // } } } #else VgaInterpretCmdStream(HwDeviceExtension, pRequestedMode->CmdStrings); #endif // // Update the location of the physical frame buffer within video memory. // HwDeviceExtension->PhysicalFrameLength = MemoryMaps[pRequestedMode->MemMap].MaxSize; HwDeviceExtension->PhysicalFrameBase.LowPart = MemoryMaps[pRequestedMode->MemMap].Start; return NO_ERROR; } // end VgaSetMode()