VP_STATUS NTAPI XboxVmpFindAdapter( IN PVOID HwDeviceExtension, IN PVOID HwContext, IN PWSTR ArgumentString, IN OUT PVIDEO_PORT_CONFIG_INFO ConfigInfo, OUT PUCHAR Again) { PXBOXVMP_DEVICE_EXTENSION XboxVmpDeviceExtension; VIDEO_ACCESS_RANGE AccessRanges[3]; VP_STATUS Status; VideoPortDebugPrint(Trace, "XboxVmpFindAdapter\n"); XboxVmpDeviceExtension = (PXBOXVMP_DEVICE_EXTENSION) HwDeviceExtension; Status = VideoPortGetAccessRanges(HwDeviceExtension, 0, NULL, 3, AccessRanges, NULL, NULL, NULL); if (NO_ERROR == Status) { XboxVmpDeviceExtension->PhysControlStart = AccessRanges[0].RangeStart; XboxVmpDeviceExtension->ControlLength = AccessRanges[0].RangeLength; XboxVmpDeviceExtension->PhysFrameBufferStart = AccessRanges[1].RangeStart; } return Status; }
/* 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; }
BOOLEAN PciGetBaseAddr( PHW_DEVICE_EXTENSION HwDeviceExtension ) /*++ Routine Description: Perform board detection and if present return the P9 base address. Arguments: HwDeviceExtension - Pointer to the miniport driver's device extension. Return Value: TRUE - Board found, P9 and Frame buffer address info was placed in the device extension. PCI extended base address was placed in the device extension. FALSE - Board not found. --*/ { VIDEO_ACCESS_RANGE PciAccessRange; PVIDEO_ACCESS_RANGE DefaultDACRegRange; ULONG ulTempAddr; ULONG ulBiosAddr; ULONG ulBoardAddr; ULONG ulTemp; LONG i; VP_STATUS status; ULONG wcpID; // // Only the viper p9000 works on the Siemens boxes // if (HwDeviceExtension->MachineType == SIEMENS || HwDeviceExtension->MachineType == SIEMENS_P9100_VLB) { return FALSE; } // // See if the PCI HAL can locate a Weitek 9001 PCI Board. // // // First check for a P9100 // if (PciFindDevice(HwDeviceExtension, WTK_9100_ID, WTK_VENDOR_ID, &HwDeviceExtension->PciSlotNum)) { wcpID = P9100_ID; HwDeviceExtension->usBusType = PCI; // Just a hack to get things working. // NOTE: !!! WE should really do the detection. HwDeviceExtension->p91State.bVideoPowerEnabled = FALSE; // Now make sure we are looking for a P9100, if were not // then fail. if (HwDeviceExtension->P9CoprocInfo.CoprocId != P9100_ID) { return(FALSE); } #ifdef _MIPS_ // // SNI platform recognition and specific stuff // { extern VP_STATUS GetCPUIdCallback( PVOID HwDeviceExtension, PVOID Context, VIDEO_DEVICE_DATA_TYPE DeviceDataType, PVOID Identifier, ULONG IdentifierLength, PVOID ConfigurationData, ULONG ConfigurationDataLength, PVOID ComponentInformation, ULONG ComponentInformationLength ); if(VideoPortIsCpu(L"RM200PCI") || VideoPortIsCpu(L"RM300PCI") || VideoPortIsCpu(L"RM300PCI MP") || VideoPortIsCpu(L"RM400PCI") || VideoPortIsCpu(L"RM4x0PCI")) { // adjust the VGA physical address with the E/ISA I/O space DriverAccessRanges[1].RangeStart.LowPart += 0x14000000 ; HwDeviceExtension->MachineType = SIEMENS_P9100_PCi; } } #endif } else if (PciFindDevice(HwDeviceExtension, WTK_9001_ID, WTK_VENDOR_ID, &HwDeviceExtension->PciSlotNum)) { wcpID = P9000_ID; // Now make sure we are looking for a P9000, if were not // then fail. if (HwDeviceExtension->P9CoprocInfo.CoprocId != P9000_ID) { return(FALSE); } // // Read the config space to determine if // this is Rev 1 or 2. This will determine at which addresses // the DAC registers are mapped. // if (!VideoPortGetBusData(HwDeviceExtension, PCIConfiguration, HwDeviceExtension->PciSlotNum, &ulTemp, P9001_REV_ID, sizeof(ulTemp))) { return(FALSE); } // // Got the 9001 rev id. Choose the appropriate table of DAC register // addresses. // switch((UCHAR) (ulTemp)) { case 1 : // // This is a Rev 1 9001, which uses the standard VL DAC // Addresses. All known rev 1 implementations use the // Weitek 5286 VGA chip. // DefaultDACRegRange = VLDefDACRegRange; HwDeviceExtension->AdapterDesc.bWtk5x86 = TRUE; break; case 2 : default: // // This is a Rev 2 9001. Set up the table of DAC register // offsets accordingly. // DefaultDACRegRange = Pci9001DefDACRegRange; // // A Rev 2 9001 is present. Get the BIOS ROM address from the // PCI configuration space so we can do a ROM scan to // determine if this is a Viper PCI adapter. // PciAccessRange.RangeStart.LowPart = 0; PciAccessRange.RangeStart.HighPart = 0; if (VideoPortGetBusData(HwDeviceExtension, PCIConfiguration, HwDeviceExtension->PciSlotNum, &PciAccessRange.RangeStart.LowPart, P9001_BIOS_BASE_ADDR, sizeof(ULONG)) == 0) { return FALSE; } if (PciAccessRange.RangeStart.LowPart) { // // We found an address for the BIOS. Verify it. // // Set up the access range so we can map out the BIOS ROM // space. This will allow us to scan the ROM and detect the // presence of a Viper PCI adapter. // PciAccessRange.RangeInIoSpace = FALSE; PciAccessRange.RangeVisible = TRUE; PciAccessRange.RangeShareable = TRUE; PciAccessRange.RangeLength = BIOS_RANGE_LEN; // // Check to see if another miniport driver has allocated the // BIOS' memory space. // if (VideoPortVerifyAccessRanges(HwDeviceExtension, 1L, &PciAccessRange) != NO_ERROR) { PciAccessRange.RangeStart.LowPart = 0; } } if (PciAccessRange.RangeStart.LowPart == 0) { // // The Adapter has not been enabled, so we need to map the // BIOS address. // IO_RESOURCE_DESCRIPTOR ioResource = { IO_RESOURCE_PREFERRED, CmResourceTypeMemory, CmResourceShareDeviceExclusive, 0, CM_RESOURCE_MEMORY_READ_WRITE, 0, { BIOS_RANGE_LEN, // Length BIOS_RANGE_LEN, // Alignment { 0x10000000, 0 }, // Minimum start address { 0xefffffff, 0} // Maximum end address } }; status = VideoPortGetAccessRanges(HwDeviceExtension, 1, &ioResource, 1, &PciAccessRange, NULL, NULL, &HwDeviceExtension->PciSlotNum); if (status != NO_ERROR) { return(FALSE); } } // // Map in the BIOS' memory space. If it can't be mapped, // return an error. // if ((ulBiosAddr = (ULONG) VideoPortGetDeviceBase(HwDeviceExtension, PciAccessRange.RangeStart, PciAccessRange.RangeLength, PciAccessRange.RangeInIoSpace)) == 0) { return(FALSE); } // // Enable the Adapter BIOS. // ulTemp = PciAccessRange.RangeStart.LowPart | PCI_BIOS_ENB; VideoPortSetBusData(HwDeviceExtension, PCIConfiguration, HwDeviceExtension->PciSlotNum, &ulTemp, P9001_BIOS_BASE_ADDR, sizeof(ULONG)); if (VideoPortScanRom(HwDeviceExtension, (PUCHAR) ulBiosAddr, BIOS_RANGE_LEN, VIPER_ID_STR)) { // // A Viper PCI is present, use the Viper set mode, // enable/disable video function pointers, and clk // divisor values. Also, Viper PCI does not // use a Weitek VGA. // HwDeviceExtension->AdapterDesc.OEMSetMode = ViperSetMode; HwDeviceExtension->AdapterDesc.P9EnableVideo = ViperPciP9Enable; HwDeviceExtension->AdapterDesc.P9DisableVideo = ViperPciP9Disable; HwDeviceExtension->AdapterDesc.iClkDiv = 4; HwDeviceExtension->AdapterDesc.bWtk5x86 = FALSE; } else { // // All non-Viper Rev 2 implementations use a Weitek // 5286 VGA chip. // HwDeviceExtension->AdapterDesc.bWtk5x86 = TRUE; } // // Restore the BIOS register to it's original value. // VideoPortSetBusData(HwDeviceExtension, PCIConfiguration, HwDeviceExtension->PciSlotNum, &ulTempAddr, P9001_BIOS_BASE_ADDR, sizeof(ULONG)); VideoPortFreeDeviceBase(HwDeviceExtension, (PVOID) ulBiosAddr); break; } } else if (PciFindDevice(HwDeviceExtension, // Search for a Weitek 9002. WTK_9002_ID, WTK_VENDOR_ID, &HwDeviceExtension->PciSlotNum)) { wcpID = P9000_ID; // Now make sure we are looking for a P9000, if were not // then fail. if (HwDeviceExtension->P9CoprocInfo.CoprocId != P9000_ID) { return(FALSE); } // // Found a 9002 board. Set up the table of DAC addresses // accordingly. // DefaultDACRegRange = Pci9002DefDACRegRange; } else { // // No Weitek PCI devices were found, return an error. // return(FALSE); } // // Get the base address of the adapter. // Some machines rely on the address not changing - if the address changes // the machine randomly appears to corrupt memory. // So use the pre-configured address if it is available. // HwDeviceExtension->P9PhysAddr.LowPart = 0; VideoPortGetBusData(HwDeviceExtension, PCIConfiguration, HwDeviceExtension->PciSlotNum, &HwDeviceExtension->P9PhysAddr.LowPart, P9001_BASE_ADDR, sizeof(ULONG)); if (HwDeviceExtension->P9PhysAddr.LowPart == 0) { IO_RESOURCE_DESCRIPTOR ioResource = { IO_RESOURCE_PREFERRED, CmResourceTypeMemory, CmResourceShareDeviceExclusive, 0, CM_RESOURCE_MEMORY_READ_WRITE, 0, { RESERVE_PCI_ADDRESS_SPACE, // Length RESERVE_PCI_ADDRESS_SPACE, // Alignment { 0x10000000, 0 }, // Minimum start address { 0xefffffff, 0} // Maximum end address } }; status = VideoPortGetAccessRanges(HwDeviceExtension, 1, &ioResource, 1, &PciAccessRange, NULL, NULL, &HwDeviceExtension->PciSlotNum); if (status == NO_ERROR) { HwDeviceExtension->P9PhysAddr = PciAccessRange.RangeStart; // // Save the physical base address in the PCI config space. // VideoPortSetBusData(HwDeviceExtension, PCIConfiguration, HwDeviceExtension->PciSlotNum, &HwDeviceExtension->P9PhysAddr.LowPart, P9001_BASE_ADDR, sizeof(ULONG)); } } if (HwDeviceExtension->P9PhysAddr.LowPart == 0) { return(FALSE); } // // The P9100 can access the DAC directly, so no I/O space needs to be // allocated for DAC access. // if (wcpID == P9000_ID) { // // The Adapter has not been enabled, so we need to map the // base IO address. // IO_RESOURCE_DESCRIPTOR ioResource = { IO_RESOURCE_PREFERRED, CmResourceTypePort, CmResourceShareDeviceExclusive, 0, CM_RESOURCE_PORT_IO, 0, { P9001_IO_RANGE, // Length P9001_IO_RANGE, // Alignment { 0x00001000, 0 }, // Minimum start address { 0x0000ffff, 0} // Maximum end address } }; status = VideoPortGetAccessRanges(HwDeviceExtension, 1, &ioResource, 1, &PciAccessRange, NULL, NULL, &HwDeviceExtension->PciSlotNum); if (status == NO_ERROR) { HwDeviceExtension->P9001PhysicalAddress = PciAccessRange.RangeStart; } else { return(FALSE); } // // Save the physical base address in the PCI config space. // ulTemp = HwDeviceExtension->P9001PhysicalAddress.LowPart | 0x01; VideoPortSetBusData(HwDeviceExtension, PCIConfiguration, HwDeviceExtension->PciSlotNum, &ulTemp, P9001_REG_BASE, sizeof(ULONG)); // // Compute the actual base address. // HwDeviceExtension->P9001PhysicalAddress.LowPart &= 0xFFFFFFFE; // // If this is a 9002 board, map in and read the VGA id register. // if (DefaultDACRegRange == Pci9002DefDACRegRange) { // // Set up the access range so we can map out the VGA ID register. // PciAccessRange.RangeInIoSpace = TRUE; PciAccessRange.RangeVisible = TRUE; PciAccessRange.RangeShareable = TRUE; PciAccessRange.RangeLength = 1; PciAccessRange.RangeStart = HwDeviceExtension->P9001PhysicalAddress; PciAccessRange.RangeStart.LowPart += P9002_VGA_ID; // // Map in the VGA ID register. If it can't be mapped, // we can't determine the VGA type, so just use the default. // if ((ulBoardAddr = (ULONG) VideoPortGetDeviceBase(HwDeviceExtension, PciAccessRange.RangeStart, PciAccessRange.RangeLength, PciAccessRange.RangeInIoSpace)) != 0) { HwDeviceExtension->AdapterDesc.bWtk5x86 = (VideoPortReadPortUchar((PUCHAR) ulBoardAddr) & VGA_MSK == WTK_VGA); VideoPortFreeDeviceBase(HwDeviceExtension, (PVOID) ulBoardAddr); } else { // // Assume this is a 5x86 VGA. // HwDeviceExtension->AdapterDesc.bWtk5x86 = TRUE; } } // // Compute the actual DAC register addresses relative to the PCI // base address. // for (i = 0; i < HwDeviceExtension->Dac.cDacRegs; i++) { // // If this is not a palette addr or data register, and the board // is not using the standard VL addresses, compute the register // address relative to the register base address. // if ((i > 3) && (DefaultDACRegRange != VLDefDACRegRange)) { DefaultDACRegRange[i].RangeStart.LowPart += HwDeviceExtension->P9001PhysicalAddress.LowPart; } } // // Copy the DAC register access range into the global list of access // ranges. // VideoPortMoveMemory(&DriverAccessRanges[NUM_DRIVER_ACCESS_RANGES], DefaultDACRegRange, sizeof(VIDEO_ACCESS_RANGE) * HwDeviceExtension->Dac.cDacRegs); // // This is a hack. Initialize an additional access range to map out // the entire 4K range of contiguous IO space starting at PCI_REG_BASE. // apparently the 9001 decodes accesses over this entire range rather // than the individual register offsets within this range. // // // Set up the access range so we can map the entire 4k IO range. // PciAccessRange.RangeInIoSpace = TRUE; PciAccessRange.RangeVisible = TRUE; PciAccessRange.RangeShareable = TRUE; PciAccessRange.RangeLength = P9001_IO_RANGE; PciAccessRange.RangeStart = HwDeviceExtension->P9001PhysicalAddress; VideoPortMoveMemory(&DriverAccessRanges[NUM_DRIVER_ACCESS_RANGES + NUM_DAC_ACCESS_RANGES], &PciAccessRange, sizeof(VIDEO_ACCESS_RANGE)); } 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; }
/* 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 ); }