EGLBoolean drm_terminate(_EGLDriver *drv, _EGLDisplay *dpy) { struct drm_device *dev = lookup_drm_device(dpy); struct drm_screen *screen; int i = 0; _eglReleaseDisplayResources(drv, dpy); _eglCleanupDisplay(dpy); drmFreeVersion(dev->version); for (i = 0; i < dev->count_screens; i++) { screen = dev->screens[i]; if (screen->shown) drm_takedown_shown_screen(dpy, screen); drmModeFreeProperty(screen->dpms); drmModeFreeConnector(screen->connector); _eglDestroyScreen(&screen->base); dev->screens[i] = NULL; } dev->screen->destroy(dev->screen); dev->winsys = NULL; drmClose(dev->drmFD); dev->api->destroy(dev->api); free(dev); dpy->DriverData = NULL; return EGL_TRUE; }
drm_public struct fd_device * fd_device_new(int fd) { struct fd_device *dev; drmVersionPtr version; /* figure out if we are kgsl or msm drm driver: */ version = drmGetVersion(fd); if (!version) { ERROR_MSG("cannot get version: %s", strerror(errno)); return NULL; } if (!strcmp(version->name, "kgsl")) { DEBUG_MSG("kgsl DRM device"); dev = kgsl_device_new(fd); } else if (!strcmp(version->name, "msm")) { DEBUG_MSG("msm DRM device"); dev = msm_device_new(fd); } else { ERROR_MSG("unknown device: %s", version->name); dev = NULL; } drmFreeVersion(version); if (!dev) return NULL; atomic_set(&dev->refcnt, 1); dev->fd = fd; dev->handle_table = drmHashCreate(); dev->name_table = drmHashCreate(); init_cache_buckets(dev); return dev; }
/* This is actually the entrypoint to the entire driver, * called by the target bootstrap code. */ struct svga_winsys_screen * svga_drm_winsys_screen_create(int fd) { struct vmw_winsys_screen *vws; struct dri1_api_version drm_ver; drmVersionPtr ver; ver = drmGetVersion(fd); if (ver == NULL) return NULL; drm_ver.major = ver->version_major; drm_ver.minor = ver->version_minor; drm_ver.patch_level = 0; /* ??? */ drmFreeVersion(ver); if (!vmw_dri1_check_version(&drm_ver, &drm_required, &drm_compat, "vmwgfx drm driver")) return NULL; vws = vmw_winsys_create(fd); if (!vws) goto out_no_vws; /* XXX do this properly */ vws->base.surface_from_handle = vws->base.have_gb_objects ? vmw_drm_gb_surface_from_handle : vmw_drm_surface_from_handle; vws->base.surface_get_handle = vmw_drm_surface_get_handle; return &vws->base; out_no_vws: return NULL; }
/* Find the index of a compatible DRM device. */ static int get_device_index(void) { char buf[32]; drmVersionPtr ver; int index = 0; int fd; bool found = false; while (!found) { snprintf(buf, sizeof(buf), "/dev/dri/card%d", index); fd = open(buf, O_RDWR); if (fd == -1) break; ver = drmGetVersion(fd); if (strcmp("exynos", ver->name) == 0) found = true; else ++index; drmFreeVersion(ver); close(fd); } return (found ? index : -1); }
static Bool vmw_screen_init(CustomizerPtr cust, int fd) { struct vmw_customizer *vmw = vmw_customizer(cust); drmVersionPtr ver; vmw->fd = fd; ver = drmGetVersion(fd); if (ver == NULL || (ver->version_major == 1 && ver->version_minor < 1)) { cust->swap_throttling = TRUE; cust->dirty_throttling = TRUE; cust->winsys_context_throttle = vmw_context_no_throttle; } else { cust->swap_throttling = TRUE; cust->dirty_throttling = FALSE; cust->winsys_context_throttle = vmw_context_throttle; debug_printf("%s: Enabling kernel throttling.\n", __func__); } if (ver) drmFreeVersion(ver); vmw_screen_cursor_init(vmw); /* if gallium is used then we don't need to do anything more. */ if (xorg_has_gallium(vmw->pScrn)) return TRUE; vmw_video_init(vmw); return TRUE; }
/* Find the index of a compatible DRM device. */ static int exynos_get_device_index(void) { drmVersionPtr ver; char buf[32] = {0}; int index = 0; bool found = false; while (!found) { int fd; snprintf(buf, sizeof(buf), "/dev/dri/card%d", index); fd = open(buf, O_RDWR); if (fd < 0) break; ver = drmGetVersion(fd); if (string_is_equal(ver->name, "exynos")) found = true; else ++index; drmFreeVersion(ver); close(fd); } if (!found) return -1; return index; }
char * loader_get_driver_for_fd(int fd, unsigned driver_types) { int vendor_id, chip_id, i, j; char *driver = NULL; if (!driver_types) driver_types = _LOADER_GALLIUM | _LOADER_DRI; if (!loader_get_pci_id_for_fd(fd, &vendor_id, &chip_id)) { #ifndef __NOT_HAVE_DRM_H /* fallback to drmGetVersion(): */ drmVersionPtr version = drmGetVersion(fd); if (!version) { log_(_LOADER_WARNING, "failed to get driver name for fd %d\n", fd); return NULL; } driver = strndup(version->name, version->name_len); log_(_LOADER_INFO, "using driver %s for %d\n", driver, fd); drmFreeVersion(version); #endif return driver; } for (i = 0; driver_map[i].driver; i++) { if (vendor_id != driver_map[i].vendor_id) continue; if (!(driver_types & driver_map[i].driver_types)) continue; if (driver_map[i].predicate && !driver_map[i].predicate(fd)) continue; if (driver_map[i].num_chips_ids == -1) { driver = strdup(driver_map[i].driver); goto out; } for (j = 0; j < driver_map[i].num_chips_ids; j++) if (driver_map[i].chip_ids[j] == chip_id) { driver = strdup(driver_map[i].driver); goto out; } } out: log_(driver ? _LOADER_DEBUG : _LOADER_WARNING, "pci id for fd %d: %04x:%04x, driver %s\n", fd, vendor_id, chip_id, driver); return driver; }
/** As long as we are using our fake DRI driver inside of Mesa, we only want * to implement the minimum here to make Mesa load it. */ Bool VBOXDRIScreenInit(ScrnInfoPtr pScrn, ScreenPtr pScreen, VBOXPtr pVBox) { DRI2InfoRec DRI2Info; unsigned i; memset(&DRI2Info, 0, sizeof(DRI2Info)); pVBox->drmFD = -1; for (i = 0; i < RT_ELEMENTS(devicePaths); ++i) { int fd = open(devicePaths[i], O_RDWR); if (fd >= 0) { drmVersionPtr pVersion = drmGetVersion(fd); if ( pVersion && pVersion->name_len && !strcmp(pVersion->name, VBOX_DRM_DRIVER_NAME) && drmSetMaster(fd) == 0) { TRACE_LOG("Opened drm device %s\n", devicePaths[i]); DRI2Info.deviceName = devicePaths[i]; /* Keep the driver open and hope that the path won't change. */ pVBox->drmFD = fd; drmFreeVersion(pVersion); break; } close(fd); drmFreeVersion(pVersion); } } if (!DRI2Info.deviceName) return FALSE; DRI2Info.version = 3; DRI2Info.fd = pVBox->drmFD; DRI2Info.driverName = VBOX_DRI_DRIVER_NAME; DRI2Info.CopyRegion = VBOXDRICopyRegion; DRI2Info.Wait = NULL; DRI2Info.CreateBuffer = VBOXDRICreateBuffer; DRI2Info.DestroyBuffer = VBOXDRIDestroyBuffer; return DRI2ScreenInit(pScreen, &DRI2Info); }
/* Print AMD devices information */ static void amdgpu_print_devices() { int i; drmDevicePtr device; /* Open the first AMD devcie to print driver information. */ if (drm_amdgpu[0] >=0) { /* Display AMD driver version information.*/ drmVersionPtr retval = drmGetVersion(drm_amdgpu[0]); if (retval == NULL) { perror("Cannot get version for AMDGPU device"); return; } printf("Driver name: %s, Date: %s, Description: %s.\n", retval->name, retval->date, retval->desc); drmFreeVersion(retval); } /* Display information of AMD devices */ printf("Devices:\n"); for (i = 0; i < MAX_CARDS_SUPPORTED && drm_amdgpu[i] >=0; i++) if (drmGetDevice2(drm_amdgpu[i], DRM_DEVICE_GET_PCI_REVISION, &device) == 0) { if (device->bustype == DRM_BUS_PCI) { printf("PCI "); printf(" domain:%04x", device->businfo.pci->domain); printf(" bus:%02x", device->businfo.pci->bus); printf(" device:%02x", device->businfo.pci->dev); printf(" function:%01x", device->businfo.pci->func); printf(" vendor_id:%04x", device->deviceinfo.pci->vendor_id); printf(" device_id:%04x", device->deviceinfo.pci->device_id); printf(" subvendor_id:%04x", device->deviceinfo.pci->subvendor_id); printf(" subdevice_id:%04x", device->deviceinfo.pci->subdevice_id); printf(" revision_id:%02x", device->deviceinfo.pci->revision_id); printf("\n"); } drmFreeDevice(&device); } }
/** * DRI2 */ static __DRIscreen * dri2CreateNewScreen(int scrn, int fd, const __DRIextension **extensions, const __DRIconfig ***driver_configs, void *data) { static const __DRIextension *emptyExtensionList[] = { NULL }; __DRIscreen *psp; drmVersionPtr version; if (driDriverAPI.InitScreen2 == NULL) return NULL; psp = calloc(1, sizeof(*psp)); if (!psp) return NULL; setupLoaderExtensions(psp, extensions); version = drmGetVersion(fd); if (version) { psp->drm_version.major = version->version_major; psp->drm_version.minor = version->version_minor; psp->drm_version.patch = version->version_patchlevel; drmFreeVersion(version); } psp->extensions = emptyExtensionList; psp->fd = fd; psp->myNum = scrn; psp->dri2.enabled = GL_TRUE; psp->DriverAPI = driDriverAPI; psp->api_mask = (1 << __DRI_API_OPENGL); *driver_configs = driDriverAPI.InitScreen2(psp); if (*driver_configs == NULL) { free(psp); return NULL; } psp->DriverAPI = driDriverAPI; psp->loaderPrivate = data; driParseOptionInfo(&psp->optionInfo, __dri2ConfigOptions, __dri2NConfigOptions); driParseConfigFiles(&psp->optionCache, &psp->optionInfo, psp->myNum, "dri2"); return psp; }
struct fd_device * fd_device_new(int fd) { struct fd_device *dev; drmVersionPtr version; /* figure out if we are kgsl or msm drm driver: */ version = drmGetVersion(fd); if (!version) { ERROR_MSG("cannot get version: %s", strerror(errno)); return NULL; } if (!strcmp(version->name, "msm")) { DEBUG_MSG("msm DRM device"); if (version->version_major != 1) { ERROR_MSG("unsupported version: %u.%u.%u", version->version_major, version->version_minor, version->version_patchlevel); dev = NULL; goto out; } dev = msm_device_new(fd); dev->version = version->version_minor; #if HAVE_FREEDRENO_KGSL } else if (!strcmp(version->name, "kgsl")) { DEBUG_MSG("kgsl DRM device"); dev = kgsl_device_new(fd); #endif } else { ERROR_MSG("unknown device: %s", version->name); dev = NULL; } out: drmFreeVersion(version); if (!dev) return NULL; p_atomic_set(&dev->refcnt, 1); dev->fd = fd; dev->handle_table = _mesa_hash_table_create(NULL, u32_hash, u32_equals); dev->name_table = _mesa_hash_table_create(NULL, u32_hash, u32_equals); fd_bo_cache_init(&dev->bo_cache, FALSE); fd_bo_cache_init(&dev->ring_cache, TRUE); return dev; }
static Bool has_kernel_mode_setting(const struct pci_device *dev) { char id[20]; int ret, fd; snprintf(id, sizeof(id), "pci:%04x:%02x:%02x.%d", dev->domain, dev->bus, dev->dev, dev->func); ret = drmCheckModesettingSupported(id); if (ret) { if (xf86LoadKernelModule("i915")) ret = drmCheckModesettingSupported(id); if (ret) return FALSE; /* Be nice to the user and load fbcon too */ (void)xf86LoadKernelModule("fbcon"); } /* Confirm that this is a i915.ko device with GEM/KMS enabled */ ret = FALSE; fd = drmOpen(NULL, id); if (fd != -1) { drmVersionPtr version = drmGetVersion(fd); if (version) { ret = strcmp ("i915", version->name) == 0; drmFreeVersion(version); } if (ret) { struct drm_i915_getparam gp; gp.param = I915_PARAM_HAS_GEM; gp.value = &ret; if (drmIoctl(fd, DRM_IOCTL_I915_GETPARAM, &gp)) ret = FALSE; } if (ret) { struct drm_mode_card_res res; memset(&res, 0, sizeof(res)); if (drmIoctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &res)) ret = FALSE; } close(fd); } return ret; }
/* * Create the driver for a DRM fd. */ static struct gralloc_drm_drv_t * init_drv_from_fd(int fd) { struct gralloc_drm_drv_t *drv = NULL; drmVersionPtr version; /* get the kernel module name */ version = drmGetVersion(fd); if (!version) { LOGE("invalid DRM fd"); return NULL; } if (version->name) { #ifdef ENABLE_PIPE drv = gralloc_drm_drv_create_for_pipe(fd, version->name); #endif #ifdef ENABLE_INTEL if (!drv && !strcmp(version->name, "i915")) drv = gralloc_drm_drv_create_for_intel(fd); #endif #ifdef ENABLE_OMAP if (!drv && !strcmp(version->name, "omapdrm")) drv = gralloc_drm_drv_create_for_omap(fd); #endif #ifdef ENABLE_RADEON if (!drv && !strcmp(version->name, "radeon")) drv = gralloc_drm_drv_create_for_radeon(fd); #endif #ifdef ENABLE_NOUVEAU if (!drv && !strcmp(version->name, "nouveau")) drv = gralloc_drm_drv_create_for_nouveau(fd); #endif } if (!drv) { LOGE("unsupported driver: %s", (version->name) ? version->name : "NULL"); } drmFreeVersion(version); return drv; }
static void getversion(int fd) { drmVersionPtr version; version = drmGetVersion(fd); if (version) { printf( "Name: %s\n", version->name ? version->name : "?" ); printf( " Version: %d.%d.%d\n", version->version_major, version->version_minor, version->version_patchlevel ); printf( " Date: %s\n", version->date ? version->date : "?" ); printf( " Desc: %s\n", version->desc ? version->desc : "?" ); drmFreeVersion(version); } else { printf( "No driver available\n" ); } }
drm_public int drm_tegra_new(struct drm_tegra **drmp, int fd) { bool supported = false; drmVersionPtr version; version = drmGetVersion(fd); if (!version) return -ENOMEM; if (!strncmp(version->name, "tegra", version->name_len)) supported = true; drmFreeVersion(version); if (!supported) return -ENOTSUP; return drm_tegra_wrap(drmp, fd, false); }
static void log_drm_version (GstKMSSink * self) { #ifndef GST_DISABLE_GST_DEBUG drmVersion *v; v = drmGetVersion (self->fd); if (v) { GST_INFO_OBJECT (self, "DRM v%d.%d.%d [%s — %s — %s]", v->version_major, v->version_minor, v->version_patchlevel, GST_STR_NULL (v->name), GST_STR_NULL (v->desc), GST_STR_NULL (v->date)); drmFreeVersion (v); } else { GST_WARNING_OBJECT (self, "could not get driver information: %s", GST_STR_NULL (self->devname)); } #endif return; }
static gboolean device_open (Device *device) { gboolean ret = FALSE; device->fd = open ("/dev/dri/card0", O_RDWR); if (device->fd < 0) { g_warning ("Unable to open DRI device"); goto out; } ret = TRUE; drmVersionPtr version = drmGetVersion (device->fd); g_print ("Driver name: %s\n", version->name); drmFreeVersion (version); out: return ret; }
int main(int argc, char *argv[]) { struct etna_device *dev; drmVersionPtr version; int fd, ret = 0; fd = open(argv[1], O_RDWR); if (fd < 0) return 1; version = drmGetVersion(fd); if (version) { printf("Version: %d.%d.%d\n", version->version_major, version->version_minor, version->version_patchlevel); printf(" Name: %s\n", version->name); printf(" Date: %s\n", version->date); printf(" Description: %s\n", version->desc); drmFreeVersion(version); } dev = etna_device_new(fd); if (!dev) { ret = 2; goto out; } test_cache(dev); test_size_rounding(dev); etna_device_del(dev); out: close(fd); return ret; }
int main(int argc, char *argv[]) { struct drm_tegra *tegra; drmVersionPtr version; const char *device; int err, fd; if (argc < 2) device = default_device; else device = argv[1]; fd = open(device, O_RDWR); if (fd < 0) return 1; version = drmGetVersion(fd); if (version) { printf("Version: %d.%d.%d\n", version->version_major, version->version_minor, version->version_patchlevel); printf(" Name: %s\n", version->name); printf(" Date: %s\n", version->date); printf(" Description: %s\n", version->desc); drmFreeVersion(version); } err = drm_tegra_new(&tegra, fd); if (err < 0) return 1; drm_tegra_close(tegra); close(fd); return 0; }
/** * This is the first entrypoint in the driver called by the DRI driver loader * after dlopen()ing it. * * It's used to create global state for the driver across contexts on the same * Display. */ static __DRIscreen * driCreateNewScreen2(int scrn, int fd, const __DRIextension **extensions, const __DRIextension **driver_extensions, const __DRIconfig ***driver_configs, void *data) { static const __DRIextension *emptyExtensionList[] = { NULL }; __DRIscreen *psp; psp = calloc(1, sizeof(*psp)); if (!psp) return NULL; /* By default, use the global driDriverAPI symbol (non-megadrivers). */ psp->driver = globalDriverAPI; /* If the driver exposes its vtable through its extensions list * (megadrivers), use that instead. */ if (driver_extensions) { for (int i = 0; driver_extensions[i]; i++) { if (strcmp(driver_extensions[i]->name, __DRI_DRIVER_VTABLE) == 0) { psp->driver = ((__DRIDriverVtableExtension *)driver_extensions[i])->vtable; } } } setupLoaderExtensions(psp, extensions); #ifndef __NOT_HAVE_DRM_H if (fd != -1) { drmVersionPtr version = drmGetVersion(fd); if (version) { psp->drm_version.major = version->version_major; psp->drm_version.minor = version->version_minor; psp->drm_version.patch = version->version_patchlevel; drmFreeVersion(version); } } #endif psp->loaderPrivate = data; psp->extensions = emptyExtensionList; psp->fd = fd; psp->myNum = scrn; *driver_configs = psp->driver->InitScreen(psp); if (*driver_configs == NULL) { free(psp); return NULL; } int gl_version_override = _mesa_get_gl_version_override(); if (gl_version_override >= 31) { psp->max_gl_core_version = MAX2(psp->max_gl_core_version, gl_version_override); } else { psp->max_gl_compat_version = MAX2(psp->max_gl_compat_version, gl_version_override); } psp->api_mask = (1 << __DRI_API_OPENGL); if (psp->max_gl_core_version > 0) psp->api_mask |= (1 << __DRI_API_OPENGL_CORE); if (psp->max_gl_es1_version > 0) psp->api_mask |= (1 << __DRI_API_GLES); if (psp->max_gl_es2_version > 0) psp->api_mask |= (1 << __DRI_API_GLES2); if (psp->max_gl_es2_version >= 30) psp->api_mask |= (1 << __DRI_API_GLES3); driParseOptionInfo(&psp->optionInfo, __dri2ConfigOptions); driParseConfigFiles(&psp->optionCache, &psp->optionInfo, psp->myNum, "dri2"); return psp; }
/** * Perform the required libGL-side initialization and call the client-side * driver's \c __driCreateNewScreen function. * * \param dpy Display pointer. * \param scrn Screen number on the display. * \param psc DRI screen information. * \param driDpy DRI display information. * \param createNewScreen Pointer to the client-side driver's * \c __driCreateNewScreen function. * \returns A pointer to the \c __DRIscreen structure returned by * the client-side driver on success, or \c NULL on failure. */ static void * CallCreateNewScreen(Display *dpy, int scrn, struct dri_screen *psc, struct dri_display * driDpy) { void *psp = NULL; drm_handle_t hSAREA; drmAddress pSAREA = MAP_FAILED; char *BusID; __DRIversion ddx_version; __DRIversion dri_version; __DRIversion drm_version; __DRIframebuffer framebuffer; int fd = -1; int status; drm_magic_t magic; drmVersionPtr version; int newlyopened; char *driverName; drm_handle_t hFB; int junk; const __DRIconfig **driver_configs; struct glx_config *visual, *configs = NULL, *visuals = NULL; /* DRI protocol version. */ dri_version.major = driDpy->driMajor; dri_version.minor = driDpy->driMinor; dri_version.patch = driDpy->driPatch; framebuffer.base = MAP_FAILED; framebuffer.dev_priv = NULL; framebuffer.size = 0; if (!XF86DRIOpenConnection(dpy, scrn, &hSAREA, &BusID)) { ErrorMessageF("XF86DRIOpenConnection failed\n"); goto handle_error; } fd = drmOpenOnce(NULL, BusID, &newlyopened); free(BusID); /* No longer needed */ if (fd < 0) { ErrorMessageF("drmOpenOnce failed (%s)\n", strerror(-fd)); goto handle_error; } if (drmGetMagic(fd, &magic)) { ErrorMessageF("drmGetMagic failed\n"); goto handle_error; } version = drmGetVersion(fd); if (version) { drm_version.major = version->version_major; drm_version.minor = version->version_minor; drm_version.patch = version->version_patchlevel; drmFreeVersion(version); } else { drm_version.major = -1; drm_version.minor = -1; drm_version.patch = -1; } if (newlyopened && !XF86DRIAuthConnection(dpy, scrn, magic)) { ErrorMessageF("XF86DRIAuthConnection failed\n"); goto handle_error; } /* Get device name (like "radeon") and the ddx version numbers. * We'll check the version in each DRI driver's "createNewScreen" * function. */ if (!XF86DRIGetClientDriverName(dpy, scrn, &ddx_version.major, &ddx_version.minor, &ddx_version.patch, &driverName)) { ErrorMessageF("XF86DRIGetClientDriverName failed\n"); goto handle_error; } free(driverName); /* No longer needed. */ /* * Get device-specific info. pDevPriv will point to a struct * (such as DRIRADEONRec in xfree86/driver/ati/radeon_dri.h) that * has information about the screen size, depth, pitch, ancilliary * buffers, DRM mmap handles, etc. */ if (!XF86DRIGetDeviceInfo(dpy, scrn, &hFB, &junk, &framebuffer.size, &framebuffer.stride, &framebuffer.dev_priv_size, &framebuffer.dev_priv)) { ErrorMessageF("XF86DRIGetDeviceInfo failed\n"); goto handle_error; } framebuffer.width = DisplayWidth(dpy, scrn); framebuffer.height = DisplayHeight(dpy, scrn); /* Map the framebuffer region. */ status = drmMap(fd, hFB, framebuffer.size, (drmAddressPtr) & framebuffer.base); if (status != 0) { ErrorMessageF("drmMap of framebuffer failed (%s)\n", strerror(-status)); goto handle_error; } /* Map the SAREA region. Further mmap regions may be setup in * each DRI driver's "createNewScreen" function. */ status = drmMap(fd, hSAREA, SAREA_MAX, &pSAREA); if (status != 0) { ErrorMessageF("drmMap of SAREA failed (%s)\n", strerror(-status)); goto handle_error; } psp = (*psc->legacy->createNewScreen) (scrn, &ddx_version, &dri_version, &drm_version, &framebuffer, pSAREA, fd, loader_extensions, &driver_configs, psc); if (psp == NULL) { ErrorMessageF("Calling driver entry point failed\n"); goto handle_error; } configs = driConvertConfigs(psc->core, psc->base.configs, driver_configs); visuals = driConvertConfigs(psc->core, psc->base.visuals, driver_configs); if (!configs || !visuals) goto handle_error; glx_config_destroy_list(psc->base.configs); psc->base.configs = configs; glx_config_destroy_list(psc->base.visuals); psc->base.visuals = visuals; psc->driver_configs = driver_configs; /* Visuals with depth != screen depth are subject to automatic compositing * in the X server, so DRI1 can't render to them properly. Mark them as * non-conformant to prevent apps from picking them up accidentally. */ for (visual = psc->base.visuals; visual; visual = visual->next) { XVisualInfo template;
Bool I810DRIScreenInit(ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); I810Ptr pI810 = I810PTR(pScrn); DRIInfoPtr pDRIInfo; I810DRIPtr pI810DRI; unsigned long tom; drm_handle_t agpHandle; drm_handle_t dcacheHandle; int sysmem_size = 0; int back_size = 0; unsigned int pitch_idx = 0; int bufs; int width = pScrn->displayWidth * pI810->cpp; int i; /* Hardware 3D rendering only implemented for 16bpp */ /* And it only works for 5:6:5 (Mark) */ if (pScrn->depth != 16) return FALSE; /* Check that the DRI, and DRM modules have been loaded by testing * for known symbols in each module. */ if (!xf86LoaderCheckSymbol("drmAvailable")) return FALSE; if (!xf86LoaderCheckSymbol("DRIQueryVersion")) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[dri] I810DRIScreenInit failed (libdri.a too old)\n"); return FALSE; } /* adjust width first */ #define Elements(x) sizeof(x)/sizeof(*x) for (pitch_idx = 0; pitch_idx < Elements(i810_pitches); pitch_idx++) if (width <= i810_pitches[pitch_idx]) break; if (pitch_idx == Elements(i810_pitches)) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[dri] Couldn't find depth/back buffer pitch"); DRICloseScreen(pScreen); return FALSE; } else { /* for tiled memory to work, the buffer needs to have the * number of lines as a multiple of 16 (the tile size), * - airlied */ int lines = (pScrn->virtualY + 15) / 16 * 16; back_size = i810_pitches[pitch_idx] * lines; back_size = ((back_size + 4096 - 1) / 4096) * 4096; } pScrn->displayWidth = i810_pitches[pitch_idx] / pI810->cpp; /* Check the DRI version */ { int major, minor, patch; DRIQueryVersion(&major, &minor, &patch); if (major != DRIINFO_MAJOR_VERSION || minor < DRIINFO_MINOR_VERSION) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[dri] I810DRIScreenInit failed because of a version mismatch.\n" "[dri] libdri version is %d.%d.%d bug version %d.%d.x is needed.\n" "[dri] Disabling DRI.\n", major, minor, patch, DRIINFO_MAJOR_VERSION, DRIINFO_MINOR_VERSION); return FALSE; } } pDRIInfo = DRICreateInfoRec(); if (!pDRIInfo) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[dri] DRICreateInfoRec failed. Disabling DRI.\n"); return FALSE; } /* pDRIInfo->wrap.ValidateTree = 0; */ /* pDRIInfo->wrap.PostValidateTree = 0; */ pI810->pDRIInfo = pDRIInfo; pI810->LockHeld = 0; pDRIInfo->drmDriverName = I810KernelDriverName; pDRIInfo->clientDriverName = I810ClientDriverName; if (xf86LoaderCheckSymbol("DRICreatePCIBusID")) { pDRIInfo->busIdString = DRICreatePCIBusID(pI810->PciInfo); } else { pDRIInfo->busIdString = malloc(64); if (pDRIInfo->busIdString) sprintf(pDRIInfo->busIdString, "PCI:%d:%d:%d", ((pI810->PciInfo->domain << 8) | pI810->PciInfo->bus), pI810->PciInfo->dev, pI810->PciInfo->func ); } if (!pDRIInfo->busIdString) { DRIDestroyInfoRec(pI810->pDRIInfo); pI810->pDRIInfo = NULL; return FALSE; } pDRIInfo->ddxDriverMajorVersion = I810_MAJOR_VERSION; pDRIInfo->ddxDriverMinorVersion = I810_MINOR_VERSION; pDRIInfo->ddxDriverPatchVersion = I810_PATCHLEVEL; pDRIInfo->frameBufferPhysicalAddress = (pointer) pI810->LinearAddr; pDRIInfo->frameBufferSize = (((pScrn->displayWidth * pScrn->virtualY * pI810->cpp) + 4096 - 1) / 4096) * 4096; pDRIInfo->frameBufferStride = pScrn->displayWidth * pI810->cpp; pDRIInfo->ddxDrawableTableEntry = I810_MAX_DRAWABLES; if (SAREA_MAX_DRAWABLES < I810_MAX_DRAWABLES) pDRIInfo->maxDrawableTableEntry = SAREA_MAX_DRAWABLES; else pDRIInfo->maxDrawableTableEntry = I810_MAX_DRAWABLES; /* For now the mapping works by using a fixed size defined * in the SAREA header */ if (sizeof(XF86DRISAREARec) + sizeof(I810SAREARec) > SAREA_MAX) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[dri] Data does not fit in SAREA\n"); return FALSE; } pDRIInfo->SAREASize = SAREA_MAX; if (!(pI810DRI = (I810DRIPtr) calloc(sizeof(I810DRIRec), 1))) { DRIDestroyInfoRec(pI810->pDRIInfo); pI810->pDRIInfo = NULL; return FALSE; } pDRIInfo->devPrivate = pI810DRI; pDRIInfo->devPrivateSize = sizeof(I810DRIRec); pDRIInfo->contextSize = sizeof(I810DRIContextRec); pDRIInfo->CreateContext = I810CreateContext; pDRIInfo->DestroyContext = I810DestroyContext; pDRIInfo->SwapContext = I810DRISwapContext; pDRIInfo->InitBuffers = I810DRIInitBuffers; pDRIInfo->MoveBuffers = I810DRIMoveBuffers; pDRIInfo->bufferRequests = DRI_ALL_WINDOWS; pDRIInfo->TransitionTo2d = I810DRITransitionTo2d; pDRIInfo->TransitionTo3d = I810DRITransitionTo3d; pDRIInfo->TransitionSingleToMulti3D = I810DRITransitionSingleToMulti3d; pDRIInfo->TransitionMultiToSingle3D = I810DRITransitionMultiToSingle3d; pDRIInfo->createDummyCtx = TRUE; pDRIInfo->createDummyCtxPriv = FALSE; /* This adds the framebuffer as a drm map *before* we have asked agp * to allocate it. Scary stuff, hold on... */ if (!DRIScreenInit(pScreen, pDRIInfo, &pI810->drmSubFD)) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[dri] DRIScreenInit failed. Disabling DRI.\n"); free(pDRIInfo->devPrivate); pDRIInfo->devPrivate = NULL; DRIDestroyInfoRec(pI810->pDRIInfo); pI810->pDRIInfo = NULL; return FALSE; } /* Check the i810 DRM versioning */ { drmVersionPtr version; /* Check the DRM lib version. * drmGetLibVersion was not supported in version 1.0, so check for * symbol first to avoid possible crash or hang. */ if (xf86LoaderCheckSymbol("drmGetLibVersion")) { version = drmGetLibVersion(pI810->drmSubFD); } else { /* drmlib version 1.0.0 didn't have the drmGetLibVersion * entry point. Fake it by allocating a version record * via drmGetVersion and changing it to version 1.0.0 */ version = drmGetVersion(pI810->drmSubFD); version->version_major = 1; version->version_minor = 0; version->version_patchlevel = 0; } #define REQ_MAJ 1 #define REQ_MIN 1 if (version) { if (version->version_major != REQ_MAJ || version->version_minor < REQ_MIN) { /* incompatible drm library version */ xf86DrvMsg(pScreen->myNum, X_ERROR, "[dri] I810DRIScreenInit failed because of a version mismatch.\n" "[dri] libdrm.a module version is %d.%d.%d but version %d.%d.x is needed.\n" "[dri] Disabling DRI.\n", version->version_major, version->version_minor, version->version_patchlevel, REQ_MAJ, REQ_MIN); drmFreeVersion(version); I810DRICloseScreen(pScreen); return FALSE; } drmFreeVersion(version); } /* Check the i810 DRM version */ version = drmGetVersion(pI810->drmSubFD); if (version) { i810_drm_version = (version->version_major<<16) | version->version_minor; if (version->version_major != 1 || version->version_minor < 2) { /* incompatible drm version */ xf86DrvMsg(pScreen->myNum, X_ERROR, "[dri] I810DRIScreenInit failed because of a version mismatch.\n" "[dri] i810.o kernel module version is %d.%d.%d but version 1.2.0 or greater is needed.\n" "[dri] Disabling DRI.\n", version->version_major, version->version_minor, version->version_patchlevel); I810DRICloseScreen(pScreen); drmFreeVersion(version); return FALSE; } pI810->drmMinor = version->version_minor; drmFreeVersion(version); } } pI810DRI->regsSize = I810_REG_SIZE; if (drmAddMap(pI810->drmSubFD, (drm_handle_t) pI810->MMIOAddr, pI810DRI->regsSize, DRM_REGISTERS, 0, (drmAddress) &pI810DRI->regs) < 0) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[drm] drmAddMap(regs) failed\n"); DRICloseScreen(pScreen); return FALSE; } xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] Registers = 0x%08x\n", (int)pI810DRI->regs); pI810->backHandle = DRM_AGP_NO_HANDLE; pI810->zHandle = DRM_AGP_NO_HANDLE; pI810->cursorHandle = DRM_AGP_NO_HANDLE; pI810->xvmcHandle = DRM_AGP_NO_HANDLE; pI810->sysmemHandle = DRM_AGP_NO_HANDLE; pI810->agpAcquired = FALSE; pI810->dcacheHandle = DRM_AGP_NO_HANDLE; /* Agp Support - Need this just to get the framebuffer. */ if (drmAgpAcquire(pI810->drmSubFD) < 0) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] drmAgpAquire failed\n"); DRICloseScreen(pScreen); return FALSE; } pI810->agpAcquired = TRUE; if (drmAgpEnable(pI810->drmSubFD, 0) < 0) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] drmAgpEnable failed\n"); DRICloseScreen(pScreen); return FALSE; } memset(&pI810->DcacheMem, 0, sizeof(I810MemRange)); memset(&pI810->BackBuffer, 0, sizeof(I810MemRange)); memset(&pI810->DepthBuffer, 0, sizeof(I810MemRange)); pI810->CursorPhysical = 0; pI810->CursorARGBPhysical = 0; /* Dcache - half the speed of normal ram, but has use as a Z buffer * under the DRI. */ drmAgpAlloc(pI810->drmSubFD, 4096 * 1024, 1, NULL, (drmAddress) &dcacheHandle); pI810->dcacheHandle = dcacheHandle; xf86DrvMsg(pScreen->myNum, X_INFO, "[agp] dcacheHandle : 0x%x\n", (int)dcacheHandle); sysmem_size = pScrn->videoRam * 1024; if (dcacheHandle != DRM_AGP_NO_HANDLE) { if (back_size > 4 * 1024 * 1024) { xf86DrvMsg(pScreen->myNum, X_INFO, "[dri] Backsize is larger then 4 meg\n"); sysmem_size = sysmem_size - 2 * back_size; drmAgpFree(pI810->drmSubFD, dcacheHandle); pI810->dcacheHandle = dcacheHandle = DRM_AGP_NO_HANDLE; } else { sysmem_size = sysmem_size - back_size; } } else { sysmem_size = sysmem_size - 2 * back_size; } /* Max size is 48 without XvMC, 41 with 6 surfaces, 40 with 7 surfaces */ if (pI810->numSurfaces && (pI810->numSurfaces == 6)) { if (sysmem_size > (pI810->FbMapSize - 7 * 1024 * 1024)) { sysmem_size = (pI810->FbMapSize - 7 * 1024 * 1024); xf86DrvMsg(pScrn->scrnIndex, X_INFO, "User requested more memory then fits in the agp aperture\n" "Truncating to %d bytes of memory\n", sysmem_size); } } if (pI810->numSurfaces && (pI810->numSurfaces == 7)) { if (sysmem_size > (pI810->FbMapSize - 8 * 1024 * 1024)) { sysmem_size = (pI810->FbMapSize - 8 * 1024 * 1024); xf86DrvMsg(pScrn->scrnIndex, X_INFO, "User requested more memory then fits in the agp aperture\n" "Truncating to %d bytes of memory\n", sysmem_size); } } if (sysmem_size > pI810->FbMapSize) { sysmem_size = pI810->FbMapSize; xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[dri] User requested more memory then fits in the agp" " aperture\n\tTruncating to %d bytes of memory\n", sysmem_size); } sysmem_size -= 4096; /* remove 4k for the hw cursor */ sysmem_size -= 16384; /* remove 16k for the ARGB hw cursor */ pI810->SysMem.Start = 0; pI810->SysMem.Size = sysmem_size; pI810->SysMem.End = sysmem_size; tom = sysmem_size; pI810->SavedSysMem = pI810->SysMem; if (dcacheHandle != DRM_AGP_NO_HANDLE) { if (drmAgpBind(pI810->drmSubFD, dcacheHandle, pI810->DepthOffset) == 0) { memset(&pI810->DcacheMem, 0, sizeof(I810MemRange)); xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[agp] GART: Found 4096K Z buffer memory\n"); pI810->DcacheMem.Start = pI810->DepthOffset; pI810->DcacheMem.Size = 1024 * 4096; pI810->DcacheMem.End = pI810->DcacheMem.Start + pI810->DcacheMem.Size; if (!I810AllocLow (&(pI810->DepthBuffer), &(pI810->DcacheMem), back_size)) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[agp] Depth buffer allocation failed\n"); DRICloseScreen(pScreen); return FALSE; } } else { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[agp] GART: dcache bind failed\n"); drmAgpFree(pI810->drmSubFD, dcacheHandle); pI810->dcacheHandle = dcacheHandle = DRM_AGP_NO_HANDLE; } } else { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[agp] GART: no dcache memory found\n"); } drmAgpAlloc(pI810->drmSubFD, back_size, 0, NULL, (drmAddress) &agpHandle); pI810->backHandle = agpHandle; if (agpHandle != DRM_AGP_NO_HANDLE) { if (drmAgpBind(pI810->drmSubFD, agpHandle, pI810->BackOffset) == 0) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[agp] Bound backbuffer memory\n"); pI810->BackBuffer.Start = pI810->BackOffset; pI810->BackBuffer.Size = back_size; pI810->BackBuffer.End = (pI810->BackBuffer.Start + pI810->BackBuffer.Size); } else { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[agp] Unable to bind backbuffer. Disabling DRI.\n"); DRICloseScreen(pScreen); return FALSE; } } else { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[dri] Unable to allocate backbuffer memory. Disabling DRI.\n"); DRICloseScreen(pScreen); return FALSE; } if (dcacheHandle == DRM_AGP_NO_HANDLE) { drmAgpAlloc(pI810->drmSubFD, back_size, 0, NULL, (drmAddress) &agpHandle); pI810->zHandle = agpHandle; if (agpHandle != DRM_AGP_NO_HANDLE) { if (drmAgpBind(pI810->drmSubFD, agpHandle, pI810->DepthOffset) == 0) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[agp] Bound depthbuffer memory\n"); pI810->DepthBuffer.Start = pI810->DepthOffset; pI810->DepthBuffer.Size = back_size; pI810->DepthBuffer.End = (pI810->DepthBuffer.Start + pI810->DepthBuffer.Size); } else { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[agp] Unable to bind depthbuffer. Disabling DRI.\n"); DRICloseScreen(pScreen); return FALSE; } } else { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[agp] Unable to allocate depthbuffer memory. Disabling DRI.\n"); DRICloseScreen(pScreen); return FALSE; } } /* Now allocate and bind the agp space. This memory will include the * regular framebuffer as well as texture memory. */ drmAgpAlloc(pI810->drmSubFD, sysmem_size, 0, NULL, (drmAddress)&agpHandle); pI810->sysmemHandle = agpHandle; if (agpHandle != DRM_AGP_NO_HANDLE) { if (drmAgpBind(pI810->drmSubFD, agpHandle, 0) == 0) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[agp] Bound System Texture Memory\n"); } else { xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] Unable to bind system texture memory. Disabling DRI.\n"); DRICloseScreen(pScreen); return FALSE; } } else { xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] Unable to allocate system texture memory. Disabling DRI.\n"); DRICloseScreen(pScreen); return FALSE; } /* Allocate 7 or 8MB for XvMC this is setup as follows to best use tiled regions and required surface pitches. (Numbers are adjusted if the AGP region is only 32MB For numSurfaces == 6 44 - 48MB = 4MB Fence, 8 Tiles wide 43 - 44MB = 1MB Fence, 8 Tiles wide 42 - 43MB = 1MB Fence, 4 Tiles wide 41 - 42MB = 1MB Fence, 4 Tiles wide For numSurfaces == 7 44 - 48MB = 4MB Fence, 8 Tiles wide 43 - 44MB = 1MB Fence, 8 Tiles wide 42.5 - 43MB = 0.5MB Fence, 8 Tiles wide 42 - 42.5MB = 0.5MB Fence, 4 Tiles wide 40 - 42MB = 2MB Fence, 4 Tiles wide */ if (pI810->numSurfaces) { if (pI810->numSurfaces == 6) { pI810->MC.Size = 7 * 1024 * 1024; pI810->MC.Start = pI810->FbMapSize - 7 * 1024 * 1024; } if (pI810->numSurfaces == 7) { pI810->MC.Size = 8 * 1024 * 1024; pI810->MC.Start = pI810->FbMapSize - 8 * 1024 * 1024; } drmAgpAlloc(pI810->drmSubFD, pI810->MC.Size, 0, NULL, (drmAddress) &agpHandle); pI810->xvmcHandle = agpHandle; if (agpHandle != DRM_AGP_NO_HANDLE) { if (drmAgpBind(pI810->drmSubFD, agpHandle, pI810->MC.Start) == 0) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "GART: Allocated 7MB for HWMC\n"); pI810->MC.End = pI810->MC.Start + pI810->MC.Size; } else { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "GART: HWMC bind failed\n"); pI810->MC.Start = 0; pI810->MC.Size = 0; pI810->MC.End = 0; } } else { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "GART: HWMC alloc failed\n"); pI810->MC.Start = 0; pI810->MC.Size = 0; pI810->MC.End = 0; } pI810->xvmcContext = 0; } drmAgpAlloc(pI810->drmSubFD, 4096, 2, (unsigned long *)&pI810->CursorPhysical, (drmAddress) &agpHandle); pI810->cursorHandle = agpHandle; if (agpHandle != DRM_AGP_NO_HANDLE) { tom = sysmem_size; if (drmAgpBind(pI810->drmSubFD, agpHandle, tom) == 0) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[agp] GART: Allocated 4K for mouse cursor image\n"); pI810->CursorStart = tom; tom += 4096; } else { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[agp] GART: cursor bind failed\n"); pI810->CursorPhysical = 0; } } else { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[agp] GART: cursor alloc failed\n"); pI810->CursorPhysical = 0; } drmAgpAlloc(pI810->drmSubFD, 16384, 2, (unsigned long *)&pI810->CursorARGBPhysical, (drmAddress) &agpHandle); pI810->cursorARGBHandle = agpHandle; if (agpHandle != DRM_AGP_NO_HANDLE) { if (drmAgpBind(pI810->drmSubFD, agpHandle, tom) == 0) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[agp] GART: Allocated 16K for ARGB mouse cursor image\n"); pI810->CursorARGBStart = tom; tom += 16384; } else { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[agp] GART: ARGB cursor bind failed\n"); pI810->CursorARGBPhysical = 0; } } else { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[agp] GART: ARGB cursor alloc failed\n"); pI810->CursorARGBPhysical = 0; } /* Steal some of the excess cursor space for the overlay regs. */ pI810->OverlayPhysical = pI810->CursorPhysical + 1024; pI810->OverlayStart = pI810->CursorStart + 1024; I810SetTiledMemory(pScrn, 1, pI810->DepthBuffer.Start, i810_pitches[pitch_idx], 8 * 1024 * 1024); I810SetTiledMemory(pScrn, 2, pI810->BackBuffer.Start, i810_pitches[pitch_idx], 8 * 1024 * 1024); /* These are for HWMC surfaces */ if (pI810->numSurfaces == 6) { I810SetTiledMemory(pScrn, 3, pI810->MC.Start, 512, 1024 * 1024); I810SetTiledMemory(pScrn, 4, pI810->MC.Start + 1024 * 1024, 512, 1024 * 1024); I810SetTiledMemory(pScrn, 5, pI810->MC.Start + 1024 * 1024 * 2, 1024, 1024 * 1024); I810SetTiledMemory(pScrn, 6, pI810->MC.Start + 1024 * 1024 * 3, 1024, 4 * 1024 * 1024); } if (pI810->numSurfaces == 7) { I810SetTiledMemory(pScrn, 3, pI810->MC.Start, 512, 2 * 1024 * 1024); I810SetTiledMemory(pScrn, 4, pI810->MC.Start + 2 * 1024 * 1024, 512, 512 * 1024); I810SetTiledMemory(pScrn, 5, pI810->MC.Start + 2 * 1024 * 1024 + 512 * 1024, 1024, 512 * 1024); I810SetTiledMemory(pScrn, 6, pI810->MC.Start + 3 * 1024 * 1024, 1024, 1 * 1024 * 1024); I810SetTiledMemory(pScrn, 7, pI810->MC.Start + 4 * 1024 * 1024, 1024, 4 * 1024 * 1024); } pI810->auxPitch = i810_pitches[pitch_idx]; pI810->auxPitchBits = i810_pitch_flags[pitch_idx]; pI810->SavedDcacheMem = pI810->DcacheMem; pI810DRI->backbufferSize = pI810->BackBuffer.Size; if (drmAddMap(pI810->drmSubFD, (drm_handle_t) pI810->BackBuffer.Start, pI810->BackBuffer.Size, DRM_AGP, 0, (drmAddress) &pI810DRI->backbuffer) < 0) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[drm] drmAddMap(backbuffer) failed. Disabling DRI\n"); DRICloseScreen(pScreen); return FALSE; } pI810DRI->depthbufferSize = pI810->DepthBuffer.Size; if (drmAddMap(pI810->drmSubFD, (drm_handle_t) pI810->DepthBuffer.Start, pI810->DepthBuffer.Size, DRM_AGP, 0, (drmAddress) &pI810DRI->depthbuffer) < 0) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[drm] drmAddMap(depthbuffer) failed. Disabling DRI.\n"); DRICloseScreen(pScreen); return FALSE; } /* Allocate FrontBuffer etc. */ if (!I810AllocateFront(pScrn)) { DRICloseScreen(pScreen); return FALSE; } /* Allocate buffer memory */ I810AllocHigh(&(pI810->BufferMem), &(pI810->SysMem), I810_DMA_BUF_NR * I810_DMA_BUF_SZ); xf86DrvMsg(pScreen->myNum, X_INFO, "[dri] Buffer map : %lx\n", pI810->BufferMem.Start); if (pI810->BufferMem.Start == 0 || pI810->BufferMem.End - pI810->BufferMem.Start > I810_DMA_BUF_NR * I810_DMA_BUF_SZ) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[dri] Not enough memory for dma buffers. Disabling DRI.\n"); DRICloseScreen(pScreen); return FALSE; } if (drmAddMap(pI810->drmSubFD, (drm_handle_t) pI810->BufferMem.Start, pI810->BufferMem.Size, DRM_AGP, 0, (drmAddress) &pI810->buffer_map) < 0) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[drm] drmAddMap(buffer_map) failed. Disabling DRI.\n"); DRICloseScreen(pScreen); return FALSE; } pI810DRI->agp_buffers = pI810->buffer_map; pI810DRI->agp_buf_size = pI810->BufferMem.Size; if (drmAddMap(pI810->drmSubFD, (drm_handle_t) pI810->LpRing->mem.Start, pI810->LpRing->mem.Size, DRM_AGP, 0, (drmAddress) &pI810->ring_map) < 0) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[drm] drmAddMap(ring_map) failed. Disabling DRI.\n"); DRICloseScreen(pScreen); return FALSE; } /* Use the rest of memory for textures. */ pI810DRI->textureSize = pI810->SysMem.Size; i = mylog2(pI810DRI->textureSize / I810_NR_TEX_REGIONS); if (i < I810_LOG_MIN_TEX_REGION_SIZE) i = I810_LOG_MIN_TEX_REGION_SIZE; pI810DRI->logTextureGranularity = i; pI810DRI->textureSize = (pI810DRI->textureSize >> i) << i; /* truncate */ if (pI810DRI->textureSize < 512 * 1024) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[drm] Less then 512k memory left for textures. Disabling DRI.\n"); DRICloseScreen(pScreen); return FALSE; } if (!I810AllocLow(&(pI810->TexMem), &(pI810->SysMem), pI810DRI->textureSize)) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[agp] Texure memory allocation failed\n"); DRICloseScreen(pScreen); return FALSE; } if (drmAddMap(pI810->drmSubFD, (drm_handle_t) pI810->TexMem.Start, pI810->TexMem.Size, DRM_AGP, 0, (drmAddress) &pI810DRI->textures) < 0) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[drm] drmAddMap(textures) failed. Disabling DRI.\n"); DRICloseScreen(pScreen); return FALSE; } if ((bufs = drmAddBufs(pI810->drmSubFD, I810_DMA_BUF_NR, I810_DMA_BUF_SZ, DRM_AGP_BUFFER, pI810->BufferMem.Start)) <= 0) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] failure adding %d %d byte DMA buffers. Disabling DRI.\n", I810_DMA_BUF_NR, I810_DMA_BUF_SZ); DRICloseScreen(pScreen); return FALSE; } xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] added %d %d byte DMA buffers\n", bufs, I810_DMA_BUF_SZ); I810InitDma(pScrn); /* Okay now initialize the dma engine */ if (!pI810DRI->irq) { pI810DRI->irq = drmGetInterruptFromBusID(pI810->drmSubFD, ((pI810->PciInfo->domain << 8) | pI810->PciInfo->bus), pI810->PciInfo->dev, pI810->PciInfo->func ); if ((drmCtlInstHandler(pI810->drmSubFD, pI810DRI->irq)) != 0) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] failure adding irq handler, there is a device " "already using that irq\n Consider rearranging your " "PCI cards. Disabling DRI.\n"); DRICloseScreen(pScreen); return FALSE; } } xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] dma control initialized, using IRQ %d\n", pI810DRI->irq); pI810DRI->deviceID = pI810->PciInfo->device_id; pI810DRI->width = pScrn->virtualX; pI810DRI->height = pScrn->virtualY; pI810DRI->mem = pScrn->videoRam * 1024; pI810DRI->cpp = pI810->cpp; pI810DRI->fbOffset = pI810->FrontBuffer.Start; pI810DRI->fbStride = pI810->auxPitch; pI810DRI->bitsPerPixel = pScrn->bitsPerPixel; pI810DRI->textureOffset = pI810->TexMem.Start; pI810DRI->backOffset = pI810->BackBuffer.Start; pI810DRI->depthOffset = pI810->DepthBuffer.Start; pI810DRI->ringOffset = pI810->LpRing->mem.Start; pI810DRI->ringSize = pI810->LpRing->mem.Size; pI810DRI->auxPitch = pI810->auxPitch; pI810DRI->auxPitchBits = pI810->auxPitchBits; pI810DRI->sarea_priv_offset = sizeof(XF86DRISAREARec); xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[dri] visual configs initialized.\n"); pI810->pDRIInfo->driverSwapMethod = DRI_HIDE_X_CONTEXT; return TRUE; }
unsigned int init_pci(unsigned char bus, const unsigned char forcemem) { int ret = pci_system_init(); if (ret) die(_("Failed to init pciaccess")); struct pci_id_match match; match.vendor_id = 0x1002; match.device_id = PCI_MATCH_ANY; match.subvendor_id = PCI_MATCH_ANY; match.subdevice_id = PCI_MATCH_ANY; match.device_class = 0; match.device_class_mask = 0; match.match_data = 0; struct pci_device_iterator *iter = pci_id_match_iterator_create(&match); struct pci_device *dev = NULL; char busid[32]; while ((dev = pci_device_next(iter))) { pci_device_probe(dev); if ((dev->device_class & 0x00ffff00) != 0x00030000 && (dev->device_class & 0x00ffff00) != 0x00038000) continue; snprintf(busid, sizeof(busid), "pci:%04x:%02x:%02x.%u", dev->domain, dev->bus, dev->dev, dev->func); if (!bus || bus == dev->bus) break; } pci_iterator_destroy(iter); if (!dev) die(_("Can't find Radeon cards")); const unsigned int device_id = dev->device_id; int reg = 2; if (getfamily(device_id) >= BONAIRE) reg = 5; if (!dev->regions[reg].size) die(_("Can't get the register area size")); // printf("Found area %p, size %lu\n", area, dev->regions[reg].size); // DRM support for VRAM drm_fd = drmOpen(NULL, busid); if (drm_fd >= 0) { drmVersionPtr ver = drmGetVersion(drm_fd); if (strcmp(ver->name, "radeon") != 0 && strcmp(ver->name, "amdgpu") != 0) { close(drm_fd); drm_fd = -1; } strcpy(drm_name, ver->name); drmFreeVersion(ver); } if (drm_fd < 0 && access("/dev/ati/card0", F_OK) == 0) // fglrx path drm_fd = open("/dev/ati/card0", O_RDWR); use_ioctl = 0; if (drm_fd >= 0) { authenticate_drm(drm_fd); uint32_t rreg = 0x8010; use_ioctl = get_drm_value(drm_fd, RADEON_INFO_READ_REG, &rreg); } if (forcemem) { printf(_("Forcing the /dev/mem path.\n")); use_ioctl = 0; } if (!use_ioctl) { int mem = open("/dev/mem", O_RDONLY); if (mem < 0) die(_("Cannot access GPU registers, are you root?")); area = mmap(NULL, MMAP_SIZE, PROT_READ, MAP_PRIVATE, mem, dev->regions[reg].base_addr + 0x8000); if (area == MAP_FAILED) die(_("mmap failed")); } bits.vram = 0; if (drm_fd < 0) { printf(_("Failed to open DRM node, no VRAM support.\n")); } else { drmDropMaster(drm_fd); drmVersionPtr ver = drmGetVersion(drm_fd); /* printf("Version %u.%u.%u, name %s\n", ver->version_major, ver->version_minor, ver->version_patchlevel, ver->name);*/ if (ver->version_major < 2 || (ver->version_major == 2 && ver->version_minor < 36)) { printf(_("Kernel too old for VRAM reporting.\n")); drmFreeVersion(ver); goto out; } drmFreeVersion(ver); // No version indicator, so we need to test once // We use different codepaths for radeon and amdgpu // We store vram_size and check below if the ret value is sane if (strcmp(drm_name, "radeon") == 0) { struct drm_radeon_gem_info gem; ret = drmCommandWriteRead(drm_fd, DRM_RADEON_GEM_INFO, &gem, sizeof(gem)); vramsize = gem.vram_size; } else if (strcmp(drm_name, "amdgpu") == 0) { #ifdef ENABLE_AMDGPU struct drm_amdgpu_info_vram_gtt vram_gtt = {}; struct drm_amdgpu_info request; memset(&request, 0, sizeof(request)); request.return_pointer = (unsigned long) &vram_gtt; request.return_size = sizeof(vram_gtt); request.query = AMDGPU_INFO_VRAM_GTT; ret = drmCommandWrite(drm_fd, DRM_AMDGPU_INFO, &request, sizeof(request)); vramsize = vram_gtt.vram_size; #else printf(_("amdgpu DRM driver is used, but amdgpu VRAM size reporting is not enabled\n")); #endif } if (ret) { printf(_("Failed to get VRAM size, error %d\n"), ret); goto out; } ret = getvram(); if (ret == 0) { if (strcmp(drm_name, "amdgpu") == 0) { #ifndef ENABLE_AMDGPU printf(_("amdgpu DRM driver is used, but amdgpu VRAM usage reporting is not enabled\n")); #endif } printf(_("Failed to get VRAM usage, kernel likely too old\n")); goto out; } bits.vram = 1; } out: pci_system_cleanup(); return device_id; }
/* Helper function to do the ioctls needed for setup and init. */ static boolean do_winsys_init(struct radeon_drm_winsys *ws) { struct drm_radeon_gem_info gem_info; int retval; drmVersionPtr version; memset(&gem_info, 0, sizeof(gem_info)); /* We do things in a specific order here. * * DRM version first. We need to be sure we're running on a KMS chipset. * This is also for some features. * * Then, the PCI ID. This is essential and should return usable numbers * for all Radeons. If this fails, we probably got handed an FD for some * non-Radeon card. * * The GEM info is actually bogus on the kernel side, as well as our side * (see radeon_gem_info_ioctl in radeon_gem.c) but that's alright because * we don't actually use the info for anything yet. * * The GB and Z pipe requests should always succeed, but they might not * return sensical values for all chipsets, but that's alright because * the pipe drivers already know that. */ /* Get DRM version. */ version = drmGetVersion(ws->fd); if (version->version_major != 2 || version->version_minor < 3) { fprintf(stderr, "%s: DRM version is %d.%d.%d but this driver is " "only compatible with 2.3.x (kernel 2.6.34) or later.\n", __FUNCTION__, version->version_major, version->version_minor, version->version_patchlevel); drmFreeVersion(version); return FALSE; } ws->info.drm_major = version->version_major; ws->info.drm_minor = version->version_minor; ws->info.drm_patchlevel = version->version_patchlevel; drmFreeVersion(version); /* Get PCI ID. */ if (!radeon_get_drm_value(ws->fd, RADEON_INFO_DEVICE_ID, "PCI ID", &ws->info.pci_id)) return FALSE; /* Check PCI ID. */ switch (ws->info.pci_id) { #define CHIPSET(pci_id, name, family) case pci_id: #include "pci_ids/r300_pci_ids.h" #undef CHIPSET ws->gen = R300; break; #define CHIPSET(pci_id, name, family) case pci_id: #include "pci_ids/r600_pci_ids.h" #undef CHIPSET ws->gen = R600; break; #define CHIPSET(pci_id, name, family) case pci_id: #include "pci_ids/radeonsi_pci_ids.h" #undef CHIPSET ws->gen = SI; break; default: fprintf(stderr, "radeon: Invalid PCI ID.\n"); return FALSE; } /* Get GEM info. */ retval = drmCommandWriteRead(ws->fd, DRM_RADEON_GEM_INFO, &gem_info, sizeof(gem_info)); if (retval) { fprintf(stderr, "radeon: Failed to get MM info, error number %d\n", retval); return FALSE; } ws->info.gart_size = gem_info.gart_size; ws->info.vram_size = gem_info.vram_size; ws->num_cpus = sysconf(_SC_NPROCESSORS_ONLN); /* Generation-specific queries. */ if (ws->gen == R300) { if (!radeon_get_drm_value(ws->fd, RADEON_INFO_NUM_GB_PIPES, "GB pipe count", &ws->info.r300_num_gb_pipes)) return FALSE; if (!radeon_get_drm_value(ws->fd, RADEON_INFO_NUM_Z_PIPES, "Z pipe count", &ws->info.r300_num_z_pipes)) return FALSE; } else if (ws->gen >= R600) { if (ws->info.drm_minor >= 9 && !radeon_get_drm_value(ws->fd, RADEON_INFO_NUM_BACKENDS, "num backends", &ws->info.r600_num_backends)) return FALSE; /* get the GPU counter frequency, failure is not fatal */ radeon_get_drm_value(ws->fd, RADEON_INFO_CLOCK_CRYSTAL_FREQ, NULL, &ws->info.r600_clock_crystal_freq); radeon_get_drm_value(ws->fd, RADEON_INFO_TILING_CONFIG, NULL, &ws->info.r600_tiling_config); if (ws->info.drm_minor >= 11) { radeon_get_drm_value(ws->fd, RADEON_INFO_NUM_TILE_PIPES, NULL, &ws->info.r600_num_tile_pipes); if (radeon_get_drm_value(ws->fd, RADEON_INFO_BACKEND_MAP, NULL, &ws->info.r600_backend_map)) ws->info.r600_backend_map_valid = TRUE; } ws->info.r600_virtual_address = FALSE; if (ws->info.drm_minor >= 13) { ws->info.r600_virtual_address = TRUE; if (!radeon_get_drm_value(ws->fd, RADEON_INFO_VA_START, NULL, &ws->info.r600_va_start)) ws->info.r600_virtual_address = FALSE; if (!radeon_get_drm_value(ws->fd, RADEON_INFO_IB_VM_MAX_SIZE, NULL, &ws->info.r600_ib_vm_max_size)) ws->info.r600_virtual_address = FALSE; } /* Remove this line once the virtual address space feature is fixed. */ if (ws->gen == R600 && !debug_get_bool_option("RADEON_VA", FALSE)) ws->info.r600_virtual_address = FALSE; } /* Get max pipes, this is only needed for compute shaders. All evergreen+ * chips have at least 2 pipes, so we use 2 as a default. */ ws->info.r600_max_pipes = 2; radeon_get_drm_value(ws->fd, RADEON_INFO_MAX_PIPES, NULL, &ws->info.r600_max_pipes); return TRUE; }
/** * DRI2 */ static __DRIscreen * dri2CreateNewScreen(int scrn, int fd, unsigned int sarea_handle, const __DRIextension **extensions, const __DRIconfig ***driver_configs, void *data) { #ifdef TTM_API static const __DRIextension *emptyExtensionList[] = { NULL }; __DRIscreen *psp; unsigned int *p; drmVersionPtr version; if (driDriverAPI.InitScreen2 == NULL) return NULL; psp = _mesa_malloc(sizeof(*psp)); if (!psp) return NULL; setupLoaderExtensions(psp, extensions); version = drmGetVersion(fd); if (version) { psp->drm_version.major = version->version_major; psp->drm_version.minor = version->version_minor; psp->drm_version.patch = version->version_patchlevel; drmFreeVersion(version); } psp->extensions = emptyExtensionList; psp->fd = fd; psp->myNum = scrn; psp->dri2.enabled = GL_TRUE; if (drmBOReference(psp->fd, sarea_handle, &psp->dri2.sareaBO)) { fprintf(stderr, "Failed to reference DRI2 sarea BO\n"); _mesa_free(psp); return NULL; } if (drmBOMap(psp->fd, &psp->dri2.sareaBO, DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0, &psp->dri2.sarea)) { drmBOUnreference(psp->fd, &psp->dri2.sareaBO); _mesa_free(psp); return NULL; } p = psp->dri2.sarea; while (DRI2_SAREA_BLOCK_TYPE(*p)) { switch (DRI2_SAREA_BLOCK_TYPE(*p)) { case DRI2_SAREA_BLOCK_LOCK: psp->dri2.lock = (__DRILock *) p; break; case DRI2_SAREA_BLOCK_EVENT_BUFFER: psp->dri2.buffer = (__DRIEventBuffer *) p; break; } p = DRI2_SAREA_BLOCK_NEXT(p); } psp->lock = (drmLock *) &psp->dri2.lock->lock; psp->DriverAPI = driDriverAPI; *driver_configs = driDriverAPI.InitScreen2(psp); if (*driver_configs == NULL) { drmBOUnmap(psp->fd, &psp->dri2.sareaBO); drmBOUnreference(psp->fd, &psp->dri2.sareaBO); _mesa_free(psp); return NULL; } psp->DriverAPI = driDriverAPI; return psp; #else return NULL; #endif }
boolean vmw_ioctl_init(struct vmw_winsys_screen *vws) { struct drm_vmw_getparam_arg gp_arg; struct drm_vmw_get_3d_cap_arg cap_arg; unsigned int size; int ret; uint32_t *cap_buffer; drmVersionPtr version; boolean have_drm_2_5; VMW_FUNC; version = drmGetVersion(vws->ioctl.drm_fd); if (!version) goto out_no_version; have_drm_2_5 = version->version_major > 2 || (version->version_major == 2 && version->version_minor > 4); vws->ioctl.have_drm_2_6 = version->version_major > 2 || (version->version_major == 2 && version->version_minor > 5); memset(&gp_arg, 0, sizeof(gp_arg)); gp_arg.param = DRM_VMW_PARAM_3D; ret = drmCommandWriteRead(vws->ioctl.drm_fd, DRM_VMW_GET_PARAM, &gp_arg, sizeof(gp_arg)); if (ret || gp_arg.value == 0) { vmw_error("No 3D enabled (%i, %s).\n", ret, strerror(-ret)); goto out_no_3d; } memset(&gp_arg, 0, sizeof(gp_arg)); gp_arg.param = DRM_VMW_PARAM_FIFO_HW_VERSION; ret = drmCommandWriteRead(vws->ioctl.drm_fd, DRM_VMW_GET_PARAM, &gp_arg, sizeof(gp_arg)); if (ret) { vmw_error("Failed to get fifo hw version (%i, %s).\n", ret, strerror(-ret)); goto out_no_3d; } vws->ioctl.hwversion = gp_arg.value; memset(&gp_arg, 0, sizeof(gp_arg)); gp_arg.param = DRM_VMW_PARAM_HW_CAPS; ret = drmCommandWriteRead(vws->ioctl.drm_fd, DRM_VMW_GET_PARAM, &gp_arg, sizeof(gp_arg)); if (ret) vws->base.have_gb_objects = FALSE; else vws->base.have_gb_objects = !!(gp_arg.value & (uint64_t) SVGA_CAP_GBOBJECTS); if (vws->base.have_gb_objects && !have_drm_2_5) goto out_no_3d; if (vws->base.have_gb_objects) { memset(&gp_arg, 0, sizeof(gp_arg)); gp_arg.param = DRM_VMW_PARAM_3D_CAPS_SIZE; ret = drmCommandWriteRead(vws->ioctl.drm_fd, DRM_VMW_GET_PARAM, &gp_arg, sizeof(gp_arg)); if (ret) size = SVGA_FIFO_3D_CAPS_SIZE * sizeof(uint32_t); else size = gp_arg.value; if (vws->base.have_gb_objects) vws->ioctl.num_cap_3d = size / sizeof(uint32_t); else vws->ioctl.num_cap_3d = SVGA3D_DEVCAP_MAX; memset(&gp_arg, 0, sizeof(gp_arg)); gp_arg.param = DRM_VMW_PARAM_MAX_MOB_MEMORY; ret = drmCommandWriteRead(vws->ioctl.drm_fd, DRM_VMW_GET_PARAM, &gp_arg, sizeof(gp_arg)); if (ret) { /* Just guess a large enough value. */ vws->ioctl.max_mob_memory = 256*1024*1024; } else { vws->ioctl.max_mob_memory = gp_arg.value; } memset(&gp_arg, 0, sizeof(gp_arg)); gp_arg.param = DRM_VMW_PARAM_MAX_MOB_SIZE; ret = drmCommandWriteRead(vws->ioctl.drm_fd, DRM_VMW_GET_PARAM, &gp_arg, sizeof(gp_arg)); if (ret || gp_arg.value == 0) { vws->ioctl.max_texture_size = VMW_MAX_DEFAULT_TEXTURE_SIZE; } else { vws->ioctl.max_texture_size = gp_arg.value; } /* Never early flush surfaces, mobs do accounting. */ vws->ioctl.max_surface_memory = -1; } else { vws->ioctl.num_cap_3d = SVGA3D_DEVCAP_MAX; memset(&gp_arg, 0, sizeof(gp_arg)); gp_arg.param = DRM_VMW_PARAM_MAX_SURF_MEMORY; if (have_drm_2_5) ret = drmCommandWriteRead(vws->ioctl.drm_fd, DRM_VMW_GET_PARAM, &gp_arg, sizeof(gp_arg)); if (!have_drm_2_5 || ret) { /* Just guess a large enough value, around 800mb. */ vws->ioctl.max_surface_memory = 0x30000000; } else { vws->ioctl.max_surface_memory = gp_arg.value; } vws->ioctl.max_texture_size = VMW_MAX_DEFAULT_TEXTURE_SIZE; size = SVGA_FIFO_3D_CAPS_SIZE * sizeof(uint32_t); } cap_buffer = calloc(1, size); if (!cap_buffer) { debug_printf("Failed alloc fifo 3D caps buffer.\n"); goto out_no_3d; } vws->ioctl.cap_3d = calloc(vws->ioctl.num_cap_3d, sizeof(*vws->ioctl.cap_3d)); if (!vws->ioctl.cap_3d) { debug_printf("Failed alloc fifo 3D caps buffer.\n"); goto out_no_caparray; } memset(&cap_arg, 0, sizeof(cap_arg)); cap_arg.buffer = (uint64_t) (unsigned long) (cap_buffer); cap_arg.max_size = size; ret = drmCommandWrite(vws->ioctl.drm_fd, DRM_VMW_GET_3D_CAP, &cap_arg, sizeof(cap_arg)); if (ret) { debug_printf("Failed to get 3D capabilities" " (%i, %s).\n", ret, strerror(-ret)); goto out_no_caps; } ret = vmw_ioctl_parse_caps(vws, cap_buffer); if (ret) { debug_printf("Failed to parse 3D capabilities" " (%i, %s).\n", ret, strerror(-ret)); goto out_no_caps; } free(cap_buffer); drmFreeVersion(version); vmw_printf("%s OK\n", __FUNCTION__); return TRUE; out_no_caps: free(vws->ioctl.cap_3d); out_no_caparray: free(cap_buffer); out_no_3d: drmFreeVersion(version); out_no_version: vws->ioctl.num_cap_3d = 0; debug_printf("%s Failed\n", __FUNCTION__); return FALSE; }
/* Initialize the screen-specific data structures for the DRI and the Rage 128. This is the main entry point to the device-specific initialization code. It calls device-independent DRI functions to create the DRI data structures and initialize the DRI state. */ static GLboolean R128DRIScreenInit(DRIDriverContext *ctx) { R128InfoPtr info = ctx->driverPrivate; R128DRIPtr pR128DRI; int err, major, minor, patch; drmVersionPtr version; drm_r128_sarea_t *pSAREAPriv; switch (ctx->bpp) { case 8: /* These modes are not supported (yet). */ case 15: case 24: fprintf(stderr, "[dri] R128DRIScreenInit failed (depth %d not supported). " "[dri] Disabling DRI.\n", ctx->bpp); return GL_FALSE; /* Only 16 and 32 color depths are supports currently. */ case 16: case 32: break; } r128_drm_page_size = getpagesize(); info->registerSize = ctx->MMIOSize; ctx->shared.SAREASize = SAREA_MAX; /* Note that drmOpen will try to load the kernel module, if needed. */ ctx->drmFD = drmOpen("r128", NULL ); if (ctx->drmFD < 0) { fprintf(stderr, "[drm] drmOpen failed\n"); return 0; } /* Check the r128 DRM version */ version = drmGetVersion(ctx->drmFD); if (version) { if (version->version_major != 2 || version->version_minor < 2) { /* incompatible drm version */ fprintf(stderr, "[dri] R128DRIScreenInit failed because of a version mismatch.\n" "[dri] r128.o kernel module version is %d.%d.%d but version 2.2 or greater is needed.\n" "[dri] Disabling the DRI.\n", version->version_major, version->version_minor, version->version_patchlevel); drmFreeVersion(version); return GL_FALSE; } info->drmMinor = version->version_minor; drmFreeVersion(version); } if ((err = drmSetBusid(ctx->drmFD, ctx->pciBusID)) < 0) { fprintf(stderr, "[drm] drmSetBusid failed (%d, %s), %s\n", ctx->drmFD, ctx->pciBusID, strerror(-err)); return 0; } if (drmAddMap( ctx->drmFD, 0, ctx->shared.SAREASize, DRM_SHM, DRM_CONTAINS_LOCK, &ctx->shared.hSAREA) < 0) { fprintf(stderr, "[drm] drmAddMap failed\n"); return 0; } fprintf(stderr, "[drm] added %d byte SAREA at 0x%08lx\n", ctx->shared.SAREASize, ctx->shared.hSAREA); if (drmMap( ctx->drmFD, ctx->shared.hSAREA, ctx->shared.SAREASize, (drmAddressPtr)(&ctx->pSAREA)) < 0) { fprintf(stderr, "[drm] drmMap failed\n"); return 0; } memset(ctx->pSAREA, 0, ctx->shared.SAREASize); fprintf(stderr, "[drm] mapped SAREA 0x%08lx to %p, size %d\n", ctx->shared.hSAREA, ctx->pSAREA, ctx->shared.SAREASize); /* Need to AddMap the framebuffer and mmio regions here: */ if (drmAddMap( ctx->drmFD, (drm_handle_t)ctx->FBStart, ctx->FBSize, DRM_FRAME_BUFFER, 0, &ctx->shared.hFrameBuffer) < 0) { fprintf(stderr, "[drm] drmAddMap framebuffer failed\n"); return 0; } fprintf(stderr, "[drm] framebuffer handle = 0x%08lx\n", ctx->shared.hFrameBuffer); if (!R128MemoryInit(ctx)) return GL_FALSE; /* Initialize AGP */ if (!info->IsPCI && !R128DRIAgpInit(ctx)) { info->IsPCI = GL_TRUE; fprintf(stderr, "[agp] AGP failed to initialize -- falling back to PCI mode.\n"); fprintf(stderr, "[agp] Make sure you have the agpgart kernel module loaded.\n"); } /* Initialize PCIGART */ if (info->IsPCI && !R128DRIPciInit(ctx)) { return GL_FALSE; } /* DRIScreenInit doesn't add all the common mappings. Add additional mappings here. */ if (!R128DRIMapInit(ctx)) { return GL_FALSE; } /* Create a 'server' context so we can grab the lock for * initialization ioctls. */ if ((err = drmCreateContext(ctx->drmFD, &ctx->serverContext)) != 0) { fprintf(stderr, "%s: drmCreateContext failed %d\n", __FUNCTION__, err); return 0; } DRM_LOCK(ctx->drmFD, ctx->pSAREA, ctx->serverContext, 0); /* Initialize the kernel data structures */ if (!R128DRIKernelInit(ctx)) { return GL_FALSE; } /* Initialize the vertex buffers list */ if (!R128DRIBufInit(ctx)) { return GL_FALSE; } /* Initialize IRQ */ R128DRIIrqInit(ctx); /* Initialize and start the CCE if required */ R128DRICCEInit(ctx); /* Quick hack to clear the front & back buffers. Could also use * the clear ioctl to do this, but would need to setup hw state * first. */ drimemsetio((char *)ctx->FBAddress + info->frontOffset, 0, info->frontPitch * ctx->cpp * ctx->shared.virtualHeight ); drimemsetio((char *)ctx->FBAddress + info->backOffset, 0, info->backPitch * ctx->cpp * ctx->shared.virtualHeight ); pSAREAPriv = (drm_r128_sarea_t *)(((char*)ctx->pSAREA) + sizeof(drm_sarea_t)); memset(pSAREAPriv, 0, sizeof(*pSAREAPriv)); /* This is the struct passed to radeon_dri.so for its initialization */ ctx->driverClientMsg = malloc(sizeof(R128DRIRec)); ctx->driverClientMsgSize = sizeof(R128DRIRec); pR128DRI = (R128DRIPtr)ctx->driverClientMsg; pR128DRI->deviceID = info->Chipset; pR128DRI->width = ctx->shared.virtualWidth; pR128DRI->height = ctx->shared.virtualHeight; pR128DRI->depth = ctx->bpp; pR128DRI->bpp = ctx->bpp; pR128DRI->IsPCI = info->IsPCI; pR128DRI->AGPMode = info->agpMode; pR128DRI->frontOffset = info->frontOffset; pR128DRI->frontPitch = info->frontPitch; pR128DRI->backOffset = info->backOffset; pR128DRI->backPitch = info->backPitch; pR128DRI->depthOffset = info->depthOffset; pR128DRI->depthPitch = info->depthPitch; pR128DRI->spanOffset = info->spanOffset; pR128DRI->textureOffset = info->textureOffset; pR128DRI->textureSize = info->textureSize; pR128DRI->log2TexGran = info->log2TexGran; pR128DRI->registerHandle = info->registerHandle; pR128DRI->registerSize = info->registerSize; pR128DRI->agpTexHandle = info->agpTexHandle; pR128DRI->agpTexMapSize = info->agpTexMapSize; pR128DRI->log2AGPTexGran = info->log2AGPTexGran; pR128DRI->agpTexOffset = info->agpTexStart; pR128DRI->sarea_priv_offset = sizeof(drm_sarea_t); return GL_TRUE; }
static EGLBoolean droid_get_pci_id(int fd, int *vendor_id, int *chip_id) { drmVersionPtr version; *chip_id = -1; version = drmGetVersion(fd); if (!version) { _eglLog(_EGL_WARNING, "invalid drm fd"); return EGL_FALSE; } if (!version->name) { _eglLog(_EGL_WARNING, "unable to determine the driver name"); drmFreeVersion(version); return EGL_FALSE; } if (strcmp(version->name, "i915") == 0) { struct drm_i915_getparam gp; int ret; *vendor_id = 0x8086; memset(&gp, 0, sizeof(gp)); gp.param = I915_PARAM_CHIPSET_ID; gp.value = chip_id; ret = drmCommandWriteRead(fd, DRM_I915_GETPARAM, &gp, sizeof(gp)); if (ret) { _eglLog(_EGL_WARNING, "failed to get param for i915"); *chip_id = -1; } } else if (strcmp(version->name, "radeon") == 0) { struct drm_radeon_info info; int ret; *vendor_id = 0x1002; memset(&info, 0, sizeof(info)); info.request = RADEON_INFO_DEVICE_ID; info.value = (unsigned long) chip_id; ret = drmCommandWriteRead(fd, DRM_RADEON_INFO, &info, sizeof(info)); if (ret) { _eglLog(_EGL_WARNING, "failed to get info for radeon"); *chip_id = -1; } } else if (strcmp(version->name, "nouveau") == 0) { *vendor_id = 0x10de; /* not used */ *chip_id = 0; } else if (strcmp(version->name, "vmwgfx") == 0) { *vendor_id = 0x15ad; /* assume SVGA II */ *chip_id = 0x0405; } drmFreeVersion(version); return (*chip_id >= 0); }
/* Helper function to do the ioctls needed for setup and init. */ static boolean do_winsys_init(struct radeon_drm_winsys *ws) { struct drm_radeon_gem_info gem_info; int retval; drmVersionPtr version; memset(&gem_info, 0, sizeof(gem_info)); /* We do things in a specific order here. * * DRM version first. We need to be sure we're running on a KMS chipset. * This is also for some features. * * Then, the PCI ID. This is essential and should return usable numbers * for all Radeons. If this fails, we probably got handed an FD for some * non-Radeon card. * * The GEM info is actually bogus on the kernel side, as well as our side * (see radeon_gem_info_ioctl in radeon_gem.c) but that's alright because * we don't actually use the info for anything yet. * * The GB and Z pipe requests should always succeed, but they might not * return sensical values for all chipsets, but that's alright because * the pipe drivers already know that. */ /* Get DRM version. */ version = drmGetVersion(ws->fd); if (version->version_major != 2 || version->version_minor < 3) { fprintf(stderr, "%s: DRM version is %d.%d.%d but this driver is " "only compatible with 2.3.x (kernel 2.6.34) or later.\n", __FUNCTION__, version->version_major, version->version_minor, version->version_patchlevel); drmFreeVersion(version); return FALSE; } ws->info.drm_major = version->version_major; ws->info.drm_minor = version->version_minor; ws->info.drm_patchlevel = version->version_patchlevel; drmFreeVersion(version); /* Get PCI ID. */ if (!radeon_get_drm_value(ws->fd, RADEON_INFO_DEVICE_ID, "PCI ID", &ws->info.pci_id)) return FALSE; /* Check PCI ID. */ switch (ws->info.pci_id) { #define CHIPSET(pci_id, name, cfamily) case pci_id: ws->info.family = CHIP_##cfamily; ws->gen = DRV_R300; break; #include "pci_ids/r300_pci_ids.h" #undef CHIPSET #define CHIPSET(pci_id, name, cfamily) case pci_id: ws->info.family = CHIP_##cfamily; ws->gen = DRV_R600; break; #include "pci_ids/r600_pci_ids.h" #undef CHIPSET #define CHIPSET(pci_id, name, cfamily) case pci_id: ws->info.family = CHIP_##cfamily; ws->gen = DRV_SI; break; #include "pci_ids/radeonsi_pci_ids.h" #undef CHIPSET default: fprintf(stderr, "radeon: Invalid PCI ID.\n"); return FALSE; } switch (ws->info.family) { default: case CHIP_UNKNOWN: fprintf(stderr, "radeon: Unknown family.\n"); return FALSE; case CHIP_R300: case CHIP_R350: case CHIP_RV350: case CHIP_RV370: case CHIP_RV380: case CHIP_RS400: case CHIP_RC410: case CHIP_RS480: ws->info.chip_class = R300; break; case CHIP_R420: /* R4xx-based cores. */ case CHIP_R423: case CHIP_R430: case CHIP_R480: case CHIP_R481: case CHIP_RV410: case CHIP_RS600: case CHIP_RS690: case CHIP_RS740: ws->info.chip_class = R400; break; case CHIP_RV515: /* R5xx-based cores. */ case CHIP_R520: case CHIP_RV530: case CHIP_R580: case CHIP_RV560: case CHIP_RV570: ws->info.chip_class = R500; break; case CHIP_R600: case CHIP_RV610: case CHIP_RV630: case CHIP_RV670: case CHIP_RV620: case CHIP_RV635: case CHIP_RS780: case CHIP_RS880: ws->info.chip_class = R600; break; case CHIP_RV770: case CHIP_RV730: case CHIP_RV710: case CHIP_RV740: ws->info.chip_class = R700; break; case CHIP_CEDAR: case CHIP_REDWOOD: case CHIP_JUNIPER: case CHIP_CYPRESS: case CHIP_HEMLOCK: case CHIP_PALM: case CHIP_SUMO: case CHIP_SUMO2: case CHIP_BARTS: case CHIP_TURKS: case CHIP_CAICOS: ws->info.chip_class = EVERGREEN; break; case CHIP_CAYMAN: case CHIP_ARUBA: ws->info.chip_class = CAYMAN; break; case CHIP_TAHITI: case CHIP_PITCAIRN: case CHIP_VERDE: case CHIP_OLAND: case CHIP_HAINAN: ws->info.chip_class = SI; break; case CHIP_BONAIRE: case CHIP_KAVERI: case CHIP_KABINI: case CHIP_HAWAII: case CHIP_MULLINS: ws->info.chip_class = CIK; break; } /* Check for dma */ ws->info.r600_has_dma = FALSE; /* DMA is disabled on R700. There is IB corruption and hangs. */ if (ws->info.chip_class >= EVERGREEN && ws->info.drm_minor >= 27) { ws->info.r600_has_dma = TRUE; } /* Check for UVD and VCE */ ws->info.has_uvd = FALSE; ws->info.vce_fw_version = 0x00000000; if (ws->info.drm_minor >= 32) { uint32_t value = RADEON_CS_RING_UVD; if (radeon_get_drm_value(ws->fd, RADEON_INFO_RING_WORKING, "UVD Ring working", &value)) ws->info.has_uvd = value; value = RADEON_CS_RING_VCE; if (radeon_get_drm_value(ws->fd, RADEON_INFO_RING_WORKING, NULL, &value) && value) { if (radeon_get_drm_value(ws->fd, RADEON_INFO_VCE_FW_VERSION, "VCE FW version", &value)) ws->info.vce_fw_version = value; } } /* Check for userptr support. */ { struct drm_radeon_gem_userptr args = {0}; /* If the ioctl doesn't exist, -EINVAL is returned. * * If the ioctl exists, it should return -EACCES * if RADEON_GEM_USERPTR_READONLY or RADEON_GEM_USERPTR_REGISTER * aren't set. */ ws->info.has_userptr = drmCommandWriteRead(ws->fd, DRM_RADEON_GEM_USERPTR, &args, sizeof(args)) == -EACCES; } /* Get GEM info. */ retval = drmCommandWriteRead(ws->fd, DRM_RADEON_GEM_INFO, &gem_info, sizeof(gem_info)); if (retval) { fprintf(stderr, "radeon: Failed to get MM info, error number %d\n", retval); return FALSE; } ws->info.gart_size = gem_info.gart_size; ws->info.vram_size = gem_info.vram_size; /* Get max clock frequency info and convert it to MHz */ radeon_get_drm_value(ws->fd, RADEON_INFO_MAX_SCLK, NULL, &ws->info.max_sclk); ws->info.max_sclk /= 1000; radeon_get_drm_value(ws->fd, RADEON_INFO_SI_BACKEND_ENABLED_MASK, NULL, &ws->info.si_backend_enabled_mask); ws->num_cpus = sysconf(_SC_NPROCESSORS_ONLN); /* Generation-specific queries. */ if (ws->gen == DRV_R300) { if (!radeon_get_drm_value(ws->fd, RADEON_INFO_NUM_GB_PIPES, "GB pipe count", &ws->info.r300_num_gb_pipes)) return FALSE; if (!radeon_get_drm_value(ws->fd, RADEON_INFO_NUM_Z_PIPES, "Z pipe count", &ws->info.r300_num_z_pipes)) return FALSE; } else if (ws->gen >= DRV_R600) { if (ws->info.drm_minor >= 9 && !radeon_get_drm_value(ws->fd, RADEON_INFO_NUM_BACKENDS, "num backends", &ws->info.r600_num_backends)) return FALSE; /* get the GPU counter frequency, failure is not fatal */ radeon_get_drm_value(ws->fd, RADEON_INFO_CLOCK_CRYSTAL_FREQ, NULL, &ws->info.r600_clock_crystal_freq); radeon_get_drm_value(ws->fd, RADEON_INFO_TILING_CONFIG, NULL, &ws->info.r600_tiling_config); if (ws->info.drm_minor >= 11) { radeon_get_drm_value(ws->fd, RADEON_INFO_NUM_TILE_PIPES, NULL, &ws->info.r600_num_tile_pipes); if (radeon_get_drm_value(ws->fd, RADEON_INFO_BACKEND_MAP, NULL, &ws->info.r600_backend_map)) ws->info.r600_backend_map_valid = TRUE; } ws->info.r600_virtual_address = FALSE; if (ws->info.drm_minor >= 13) { uint32_t ib_vm_max_size; ws->info.r600_virtual_address = TRUE; if (!radeon_get_drm_value(ws->fd, RADEON_INFO_VA_START, NULL, &ws->va_start)) ws->info.r600_virtual_address = FALSE; if (!radeon_get_drm_value(ws->fd, RADEON_INFO_IB_VM_MAX_SIZE, NULL, &ib_vm_max_size)) ws->info.r600_virtual_address = FALSE; radeon_get_drm_value(ws->fd, RADEON_INFO_VA_UNMAP_WORKING, NULL, &ws->va_unmap_working); } if (ws->gen == DRV_R600 && !debug_get_bool_option("RADEON_VA", FALSE)) ws->info.r600_virtual_address = FALSE; } /* Get max pipes, this is only needed for compute shaders. All evergreen+ * chips have at least 2 pipes, so we use 2 as a default. */ ws->info.r600_max_pipes = 2; radeon_get_drm_value(ws->fd, RADEON_INFO_MAX_PIPES, NULL, &ws->info.r600_max_pipes); /* All GPUs have at least one compute unit */ ws->info.max_compute_units = 1; radeon_get_drm_value(ws->fd, RADEON_INFO_ACTIVE_CU_COUNT, NULL, &ws->info.max_compute_units); radeon_get_drm_value(ws->fd, RADEON_INFO_MAX_SE, NULL, &ws->info.max_se); if (!ws->info.max_se) { switch (ws->info.family) { default: ws->info.max_se = 1; break; case CHIP_CYPRESS: case CHIP_HEMLOCK: case CHIP_BARTS: case CHIP_CAYMAN: case CHIP_TAHITI: case CHIP_PITCAIRN: case CHIP_BONAIRE: ws->info.max_se = 2; break; case CHIP_HAWAII: ws->info.max_se = 4; break; } } radeon_get_drm_value(ws->fd, RADEON_INFO_MAX_SH_PER_SE, NULL, &ws->info.max_sh_per_se); radeon_get_drm_value(ws->fd, RADEON_INFO_ACCEL_WORKING2, NULL, &ws->accel_working2); if (ws->info.family == CHIP_HAWAII && ws->accel_working2 < 2) { fprintf(stderr, "radeon: GPU acceleration for Hawaii disabled, " "returned accel_working2 value %u is smaller than 2. " "Please install a newer kernel.\n", ws->accel_working2); return FALSE; } if (radeon_get_drm_value(ws->fd, RADEON_INFO_SI_TILE_MODE_ARRAY, NULL, ws->info.si_tile_mode_array)) { ws->info.si_tile_mode_array_valid = TRUE; } if (radeon_get_drm_value(ws->fd, RADEON_INFO_CIK_MACROTILE_MODE_ARRAY, NULL, ws->info.cik_macrotile_mode_array)) { ws->info.cik_macrotile_mode_array_valid = TRUE; } return TRUE; }
int main(int argc, char **argv) { int fd, newlyopened; drmVersionPtr retval; char *busid; //drmDevicePtr dev; //* fd = drmOpen(NULL, "pci:0000:01:00.0"); assert(fd >= 0); retval = drmGetVersion(fd); printf("name=%s\n", retval->name); drmFreeVersion(retval); busid = drmGetBusid(fd); printf("busid=%s\n", busid); drmFreeBusid(busid); /* assert(!drmGetDevice(fd, &dev)); printf("pci:%04x:%02x:%02x.%d\n", dev->businfo.pci->domain, dev->businfo.pci->bus, dev->businfo.pci->dev, dev->businfo.pci->func); */ drmClose(fd); //*/ fd = drmOpenOnceWithType("pci:0000:01:00.0", &newlyopened, DRM_NODE_PRIMARY); //fd = open("/dev/dri/card0", O_RDWR); assert(fd >= 0); retval = drmGetVersion(fd); printf("name=%s\n", retval->name); drmFreeVersion(retval); busid = drmGetBusid(fd); printf("busid=%s\n", busid); drmFreeBusid(busid); /* assert(!drmGetDevice(fd, &dev)); printf("pci:%04x:%02x:%02x.%d\n", dev->businfo.pci->domain, dev->businfo.pci->bus, dev->businfo.pci->dev, dev->businfo.pci->func); */ drmClose(fd); /* drmDevicePtr devs[16]; int num = drmGetDevices(devs, 16); assert(num >= 0); int i; for (i = 0; i < num; i++) { printf("pci:%04x:%02x:%02x.%d\n", devs[i]->businfo.pci->domain, devs[i]->businfo.pci->bus, devs[i]->businfo.pci->dev, devs[i]->businfo.pci->func); } */ /* struct dirent *dent; struct stat sbuf; DIR *sysdir; sysdir = opendir("/dev/dri"); assert(sysdir); while ((dent = readdir(sysdir))) { char node[1024]; snprintf(node, 1024, "/dev/dri/%s", dent->d_name); if (stat(node, &sbuf)) continue; printf("path=%s, dev=%x rdev=%x maj=%d min=%d\n", node, sbuf.st_dev, sbuf.st_rdev, major(sbuf.st_rdev), minor(sbuf.st_rdev)); } */ fd = open("/dev/dri/card0", O_RDWR); assert(fd >= 0); char *path = drmGetDeviceNameFromFd(fd); assert(path != NULL); printf("get path = %s\n", path); return 0; }