예제 #1
0
파일: xboxvmp.c 프로젝트: hoangduit/reactos
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;
}
예제 #3
0
파일: pci.c 프로젝트: Gaikokujin/WinNT4
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);

}
예제 #4
0
/* 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;
}
예제 #5
0
/* 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 );
}