diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2010-01-13 14:26:04 +1000 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2010-01-13 14:32:14 +1000 |
commit | 18e3a649f7df73bc1e6d199ecf7a62ddcfe37d6e (patch) | |
tree | d1dc47d7fe755e05b8be3e031a2dc836a8ed49ea | |
parent | 6267b85460ef364aa51a7d33006940bb00a049d9 (diff) |
Check for drm+kms availability in NVPciProbe()
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r-- | src/nv_driver.c | 206 |
1 files changed, 81 insertions, 125 deletions
diff --git a/src/nv_driver.c b/src/nv_driver.c index 12ec7ce..248a151 100644 --- a/src/nv_driver.c +++ b/src/nv_driver.c @@ -194,110 +194,99 @@ NVIdentify(int flags) } } -/* This returns architecture in hexdecimal, so NV40 is 0x40 */ -static int NVGetArchitecture(volatile uint32_t *regs) -{ - int architecture = 0; - - /* We're dealing with >=NV10 */ - if ((regs[0] & 0x0f000000) > 0 ) - /* Bit 27-20 contain the architecture in hex */ - architecture = (regs[0] & 0xff00000) >> 20; - /* NV04 or NV05 */ - else if ((regs[0] & 0xff00fff0) == 0x20004000) - architecture = 0x04; - - return architecture; -} - -/* Reading the pci_id from the card registers is the most reliable way */ -static uint32_t NVGetPCIID(volatile uint32_t *regs) -{ - int architecture = NVGetArchitecture(regs); - uint32_t pci_id; - - /* Dealing with an unknown or unsupported card */ - if (architecture == 0) - return 0; - - if (architecture >= 0x40) - pci_id = regs[0x88000/4]; - else - pci_id = regs[0x1800/4]; - - /* A pci-id can be inverted, we must correct this */ - if ((pci_id & 0xffff) == PCI_VENDOR_NVIDIA) - pci_id = (PCI_VENDOR_NVIDIA << 16) | (pci_id >> 16); - else if ((pci_id & 0xffff) == PCI_VENDOR_NVIDIA_SGS) - pci_id = (PCI_VENDOR_NVIDIA_SGS << 16) | (pci_id >> 16); - /* Checking endian issues */ - else { - /* PCI_VENDOR_NVIDIA = 0x10DE */ - if ((pci_id & (0xffff << 16)) == (0xDE10 << 16)) /* wrong endian */ - pci_id = (PCI_VENDOR_NVIDIA << 16) | ((pci_id << 8) & 0x0000ff00) | - ((pci_id >> 8) & 0x000000ff); - /* PCI_VENDOR_NVIDIA_SGS = 0x12D2 */ - else if ((pci_id & (0xffff << 16)) == (0xD212 << 16)) /* wrong endian */ - pci_id = (PCI_VENDOR_NVIDIA_SGS << 16) | ((pci_id << 8) & 0x0000ff00) | - ((pci_id >> 8) & 0x000000ff); - } - - return pci_id; -} - -static Bool NVPciProbe ( DriverPtr drv, - int entity_num, - struct pci_device *dev, - intptr_t match_data ) +static Bool +NVPciProbe(DriverPtr drv, int entity_num, struct pci_device *pci_dev, + intptr_t match_data) { + PciChipsets NVChipsets[] = { + { pci_dev->device_id, + (pci_dev->vendor_id << 16) | pci_dev->device_id, NULL }, + { -1, -1, NULL } + }; + struct nouveau_device *dev = NULL; ScrnInfoPtr pScrn = NULL; + drmVersion *version; + int chipset, ret; + char *busid; - volatile uint32_t *regs = NULL; - - /* Temporary mapping to discover the architecture */ - pci_device_map_range(dev, dev->regions[0].base_addr, 0x90000, 0, - (void *) ®s); + if (!xf86LoaderCheckSymbol("DRICreatePCIBusID")) { + xf86DrvMsg(-1, X_ERROR, "[drm] No DRICreatePCIBusID symbol\n"); + return FALSE; + } + busid = DRICreatePCIBusID(pci_dev); - uint8_t architecture = NVGetArchitecture(regs); + ret = nouveau_device_open(&dev, busid); + if (ret) { + xf86DrvMsg(-1, X_ERROR, "[drm] failed to open device\n"); + xfree(busid); + return FALSE; + } - CARD32 pci_id = NVGetPCIID(regs); + /* Check the version reported by the kernel module. In theory we + * shouldn't have to do this, as libdrm_nouveau will do its own checks. + * But, we're currently using the kernel patchlevel to also version + * the DRI interface. + */ + version = drmGetVersion(nouveau_device(dev)->fd); + xf86DrvMsg(-1, X_INFO, "[drm] nouveau interface version: %d.%d.%d\n", + version->version_major, version->version_minor, + version->version_patchlevel); - pci_device_unmap_range(dev, (void *) regs, 0x90000); + ret = !(version->version_patchlevel == NOUVEAU_DRM_HEADER_PATCHLEVEL); + drmFree(version); + if (ret) { + xf86DrvMsg(-1, X_ERROR, + "[drm] wrong version, expecting 0.0.%d\n", + NOUVEAU_DRM_HEADER_PATCHLEVEL); + return FALSE; + } - /* Currently NV04 up to NVAA is known. */ - /* Using 0xAF as upper bound for some margin. */ - if (architecture >= 0x04 && architecture <= 0xAF) { + chipset = dev->chipset; + nouveau_device_close(&dev); - /* At this stage the pci_id should be ok, so we generate this - * to avoid list duplication */ - /* AGP bridge chips need their bridge chip id to be detected */ - PciChipsets NVChipsets[] = { - { pci_id, (dev->vendor_id << 16) | dev->device_id, NULL }, - { -1, -1, NULL } - }; + ret = drmCheckModesettingSupported(busid); + xfree(busid); + if (ret) { + xf86DrvMsg(-1, X_ERROR, "[drm] KMS not enabled\n"); + return FALSE; + } - pScrn = xf86ConfigPciEntity(pScrn, 0, entity_num, NVChipsets, - NULL, NULL, NULL, NULL, NULL); + switch (chipset & 0xf0) { + case 0x00: + case 0x10: + case 0x20: + case 0x30: + case 0x40: + case 0x60: + case 0x50: + case 0x80: + case 0x90: + case 0xa0: + break; + default: + xf86DrvMsg(-1, X_ERROR, "Unknown chipset: NV%02x\n", chipset); + return FALSE; + } - if (pScrn != NULL) { - pScrn->driverVersion = NV_VERSION; - pScrn->driverName = NV_DRIVER_NAME; - pScrn->name = NV_NAME; + pScrn = xf86ConfigPciEntity(pScrn, 0, entity_num, NVChipsets, + NULL, NULL, NULL, NULL, NULL); + if (!pScrn) + return FALSE; - pScrn->Probe = NULL; - pScrn->PreInit = NVPreInit; - pScrn->ScreenInit = NVScreenInit; - pScrn->SwitchMode = NVSwitchMode; - pScrn->AdjustFrame = NVAdjustFrame; - pScrn->EnterVT = NVEnterVT; - pScrn->LeaveVT = NVLeaveVT; - pScrn->FreeScreen = NVFreeScreen; + pScrn->driverVersion = NV_VERSION; + pScrn->driverName = NV_DRIVER_NAME; + pScrn->name = NV_NAME; - return TRUE; - } - } + pScrn->Probe = NULL; + pScrn->PreInit = NVPreInit; + pScrn->ScreenInit = NVScreenInit; + pScrn->SwitchMode = NVSwitchMode; + pScrn->AdjustFrame = NVAdjustFrame; + pScrn->EnterVT = NVEnterVT; + pScrn->LeaveVT = NVLeaveVT; + pScrn->FreeScreen = NVFreeScreen; - return FALSE; + return TRUE; } #define MAX_CHIPS MAXSCREENS @@ -560,7 +549,6 @@ static Bool NVPreInitDRM(ScrnInfoPtr pScrn) { NVPtr pNv = NVPTR(pScrn); - drmVersion *version; char *bus_id; int ret; @@ -570,6 +558,7 @@ NVPreInitDRM(ScrnInfoPtr pScrn) /* Load the kernel module, and open the DRM */ bus_id = DRICreatePCIBusID(pNv->PciInfo); ret = DRIOpenDRMMaster(pScrn, SAREA_MAX, bus_id, "nouveau"); + xfree(bus_id); if (!ret) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "[drm] error opening the drm\n"); @@ -577,46 +566,13 @@ NVPreInitDRM(ScrnInfoPtr pScrn) return FALSE; } - /* Check the version reported by the kernel module. In theory we - * shouldn't have to do this, as libdrm_nouveau will do its own checks. - * But, we're currently using the kernel patchlevel to also version - * the DRI interface. - */ - version = drmGetVersion(DRIMasterFD(pScrn)); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "[drm] nouveau interface version: %d.%d.%d\n", - version->version_major, version->version_minor, - version->version_patchlevel); - - ret = !(version->version_patchlevel == NOUVEAU_DRM_HEADER_PATCHLEVEL); - drmFree(version); - if (ret) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "[drm] wrong version, expecting 0.0.%d\n", - NOUVEAU_DRM_HEADER_PATCHLEVEL); - xfree(bus_id); - return FALSE; - } - /* Initialise libdrm_nouveau */ ret = nouveau_device_open_existing(&pNv->dev, 1, DRIMasterFD(pScrn), 0); if (ret) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "[drm] error creating device\n"); - xfree(bus_id); - return FALSE; - } - - /* Check if KMS is enabled before we do anything, we don't want to - * go stomping on registers behind its back - */ - if (drmCheckModesettingSupported(bus_id)) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "[drm] kernel modesetting not available\n"); - xfree(bus_id); return FALSE; } - xfree(bus_id); return TRUE; } |