Index: programs/Xserver/GL/dri/dri.c =================================================================== RCS file: /home/ncvs/dri/xc/xc/programs/Xserver/GL/dri/dri.c,v retrieving revision 1.48 diff -u -r1.48 dri.c --- programs/Xserver/GL/dri/dri.c 25 Mar 2003 12:04:15 -0000 1.48 +++ programs/Xserver/GL/dri/dri.c 22 Oct 2003 00:50:22 -0000 @@ -118,6 +118,9 @@ int i, fd, drmWasAvailable; Bool xineramaInCore = FALSE; int err = 0; + char *openbusid; + drmVersionPtr drmlibv; + int drmlibmajor, drmlibminor, drmdimajor, drmdiminor; if (DRIGeneration != serverGeneration) { if ((DRIScreenPrivIndex = AllocateScreenPrivateIndex()) < 0) @@ -148,8 +151,31 @@ drmWasAvailable = drmAvailable(); + /* Check the DRM lib version. + * drmGetLibVersion was not supported in version 1.0, so check for + * symbol first to avoid possible crash or hang. + */ + drmlibmajor = 1; + drmlibminor = 0; + if (xf86LoaderCheckSymbol("drmGetLibVersion")) { + drmlibv = drmGetLibVersion(-1); + if (drmlibv != NULL) { + drmlibmajor = drmlibv->version_major; + drmlibminor = drmlibv->version_minor; + drmFreeVersion(drmlibv); + } + } + + /* Check if the libdrm can handle falling back to loading based on name + * if a busid string is passed. + */ + if (drmlibmajor == 1 && drmlibminor >= 2) + openbusid = pDRIInfo->busIdString; + else + openbusid = NULL; + /* Note that drmOpen will try to load the kernel module, if needed. */ - fd = drmOpen(pDRIInfo->drmDriverName, NULL ); + fd = drmOpen(pDRIInfo->drmDriverName, openbusid); if (fd < 0) { /* failed to open DRM */ pScreen->devPrivates[DRIScreenPrivIndex].ptr = NULL; @@ -184,7 +210,40 @@ pDRIPriv->grabbedDRILock = FALSE; pDRIPriv->drmSIGIOHandlerInstalled = FALSE; - if ((err = drmSetBusid(pDRIPriv->drmFD, pDRIPriv->pDriverInfo->busIdString)) < 0) { + if (drmlibmajor == 1 && drmlibminor >= 2) { + drmSetVersion sv; + + /* Get the interface version, asking for 1.1. */ + sv.drm_di_major = 1; + sv.drm_di_minor = 1; + sv.drm_dd_major = -1; + err = drmSetInterfaceVersion(pDRIPriv->drmFD, &sv); + if (err == 0) { + drmdimajor = sv.drm_di_major; + drmdiminor = sv.drm_di_minor; + } else { + /* failure, so set it to 1.0.0. */ + drmdimajor = 1; + drmdiminor = 0; + } + } + else { + /* We can't check the DI DRM interface version, so set it to 1.0.0. */ + drmdimajor = 1; + drmdiminor = 0; + } + DRIDrvMsg(pScreen->myNum, X_INFO, + "[drm] DRM interface version %d.%d\n", drmdimajor, drmdiminor); + + /* If the interface minor number is 1.1, then we've opened a DRM device + * that already had the busid set through drmOpen. + */ + if (drmdimajor == 1 && drmdiminor >= 1) + err = 0; + else + err = drmSetBusid(pDRIPriv->drmFD, pDRIPriv->pDriverInfo->busIdString); + + if (err < 0) { pDRIPriv->directRenderingSupport = FALSE; pScreen->devPrivates[DRIScreenPrivIndex].ptr = NULL; drmClose(pDRIPriv->drmFD); @@ -2114,4 +2173,22 @@ } } else *xdir = 1; +} + +char * +DRICreatePCIBusID(pciVideoPtr PciInfo) +{ + char *busID; + int domain; + PCITAG tag; + + busID = xalloc(20); + if (busID == NULL) + return NULL; + + tag = pciTag(PciInfo->bus, PciInfo->device, PciInfo->func); + domain = xf86GetPciDomain(tag); + snprintf(busID, 20, "pci:%04x:%02x:%02x.%d", domain, PciInfo->bus, + PciInfo->device, PciInfo->func); + return busID; } Index: programs/Xserver/GL/dri/dri.h =================================================================== RCS file: /home/ncvs/dri/xc/xc/programs/Xserver/GL/dri/dri.h,v retrieving revision 1.22 diff -u -r1.22 dri.h --- programs/Xserver/GL/dri/dri.h 25 Mar 2003 12:04:17 -0000 1.22 +++ programs/Xserver/GL/dri/dri.h 22 Oct 2003 00:24:12 -0000 @@ -325,6 +325,8 @@ int *ydir, RegionPtr reg); +extern char *DRICreatePCIBusID(pciVideoPtr PciInfo); + #define _DRI_H_ #endif Index: programs/Xserver/hw/xfree86/drivers/ati/r128_dri.c =================================================================== RCS file: /home/ncvs/dri/xc/xc/programs/Xserver/hw/xfree86/drivers/ati/r128_dri.c,v retrieving revision 1.39 diff -u -r1.39 r128_dri.c --- programs/Xserver/hw/xfree86/drivers/ati/r128_dri.c 16 Sep 2003 20:57:52 -0000 1.39 +++ programs/Xserver/hw/xfree86/drivers/ati/r128_dri.c 22 Oct 2003 00:17:15 -0000 @@ -1022,12 +1022,16 @@ info->pDRIInfo = pDRIInfo; pDRIInfo->drmDriverName = R128_DRIVER_NAME; pDRIInfo->clientDriverName = R128_DRIVER_NAME; - pDRIInfo->busIdString = xalloc(64); - sprintf(pDRIInfo->busIdString, - "PCI:%d:%d:%d", - info->PciInfo->bus, - info->PciInfo->device, - info->PciInfo->func); + if (xf86LoaderCheckSymbol("DRICreatePCIBusID")) { + pDRIInfo->busIdString = DRICreatePCIBusID(info->PciInfo); + } else { + pDRIInfo->busIdString = xalloc(64); + sprintf(pDRIInfo->busIdString, + "PCI:%d:%d:%d", + info->PciInfo->bus, + info->PciInfo->device, + info->PciInfo->func); + } pDRIInfo->ddxDriverMajorVersion = R128_VERSION_MAJOR; pDRIInfo->ddxDriverMinorVersion = R128_VERSION_MINOR; pDRIInfo->ddxDriverPatchVersion = R128_VERSION_PATCH; Index: programs/Xserver/hw/xfree86/drivers/ati/radeon_dri.c =================================================================== RCS file: /home/ncvs/dri/xc/xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_dri.c,v retrieving revision 1.53 diff -u -r1.53 radeon_dri.c --- programs/Xserver/hw/xfree86/drivers/ati/radeon_dri.c 28 Sep 2003 16:02:26 -0000 1.53 +++ programs/Xserver/hw/xfree86/drivers/ati/radeon_dri.c 22 Oct 2003 00:16:45 -0000 @@ -1242,12 +1242,16 @@ else pDRIInfo->clientDriverName = RADEON_DRIVER_NAME; - pDRIInfo->busIdString = xalloc(64); - sprintf(pDRIInfo->busIdString, - "PCI:%d:%d:%d", - info->PciInfo->bus, - info->PciInfo->device, - info->PciInfo->func); + if (xf86LoaderCheckSymbol("DRICreatePCIBusID")) { + pDRIInfo->busIdString = DRICreatePCIBusID(info->PciInfo); + } else { + pDRIInfo->busIdString = xalloc(64); + sprintf(pDRIInfo->busIdString, + "PCI:%d:%d:%d", + info->PciInfo->bus, + info->PciInfo->device, + info->PciInfo->func); + } pDRIInfo->ddxDriverMajorVersion = RADEON_VERSION_MAJOR; pDRIInfo->ddxDriverMinorVersion = RADEON_VERSION_MINOR; pDRIInfo->ddxDriverPatchVersion = RADEON_VERSION_PATCH; Index: programs/Xserver/hw/xfree86/drivers/glint/glint_dri.c =================================================================== RCS file: /home/ncvs/dri/xc/xc/programs/Xserver/hw/xfree86/drivers/glint/glint_dri.c,v retrieving revision 1.28 diff -u -r1.28 glint_dri.c --- programs/Xserver/hw/xfree86/drivers/glint/glint_dri.c 12 Sep 2003 20:10:54 -0000 1.28 +++ programs/Xserver/hw/xfree86/drivers/glint/glint_dri.c 22 Oct 2003 00:19:37 -0000 @@ -483,11 +483,15 @@ /* setup device info */ pDRIInfo->drmDriverName = GLINTKernelDriverName; pDRIInfo->clientDriverName = GLINTClientDriverName; - pDRIInfo->busIdString = xalloc(64); /* Freed in DRIDestroyInfoRec */ - sprintf(pDRIInfo->busIdString, "PCI:%d:%d:%d", - ((pciConfigPtr)pGlint->PciInfo->thisCard)->busnum, - ((pciConfigPtr)pGlint->PciInfo->thisCard)->devnum, - ((pciConfigPtr)pGlint->PciInfo->thisCard)->funcnum); + if (xf86LoaderCheckSymbol("DRICreatePCIBusID")) { + pDRIInfo->busIdString = DRICreatePCIBusID(pGlint->PciInfo); + } else { + pDRIInfo->busIdString = xalloc(64); /* Freed in DRIDestroyInfoRec */ + sprintf(pDRIInfo->busIdString, "PCI:%d:%d:%d", + ((pciConfigPtr)pGlint->PciInfo->thisCard)->busnum, + ((pciConfigPtr)pGlint->PciInfo->thisCard)->devnum, + ((pciConfigPtr)pGlint->PciInfo->thisCard)->funcnum); + } pDRIInfo->ddxDriverMajorVersion = GLINT_MAJOR_VERSION; pDRIInfo->ddxDriverMinorVersion = GLINT_MINOR_VERSION; pDRIInfo->ddxDriverPatchVersion = GLINT_PATCHLEVEL; Index: programs/Xserver/hw/xfree86/drivers/i810/i810_dri.c =================================================================== RCS file: /home/ncvs/dri/xc/xc/programs/Xserver/hw/xfree86/drivers/i810/i810_dri.c,v retrieving revision 1.53 diff -u -r1.53 i810_dri.c --- programs/Xserver/hw/xfree86/drivers/i810/i810_dri.c 16 Sep 2003 20:50:15 -0000 1.53 +++ programs/Xserver/hw/xfree86/drivers/i810/i810_dri.c 22 Oct 2003 00:53:05 -0000 @@ -343,12 +343,15 @@ pDRIInfo->drmDriverName = I810KernelDriverName; pDRIInfo->clientDriverName = I810ClientDriverName; - pDRIInfo->busIdString = xalloc(64); - - sprintf(pDRIInfo->busIdString, "PCI:%d:%d:%d", - ((pciConfigPtr) pI810->PciInfo->thisCard)->busnum, - ((pciConfigPtr) pI810->PciInfo->thisCard)->devnum, - ((pciConfigPtr) pI810->PciInfo->thisCard)->funcnum); + if (xf86LoaderCheckSymbol("DRICreatePCIBusID")) { + pDRIInfo->busIdString = DRICreatePCIBusID(pI810->PciInfo); + } else { + pDRIInfo->busIdString = xalloc(64); + sprintf(pDRIInfo->busIdString, "PCI:%d:%d:%d", + ((pciConfigPtr) pI810->PciInfo->thisCard)->busnum, + ((pciConfigPtr) pI810->PciInfo->thisCard)->devnum, + ((pciConfigPtr) pI810->PciInfo->thisCard)->funcnum); + } pDRIInfo->ddxDriverMajorVersion = I810_MAJOR_VERSION; pDRIInfo->ddxDriverMinorVersion = I810_MINOR_VERSION; pDRIInfo->ddxDriverPatchVersion = I810_PATCHLEVEL; Index: programs/Xserver/hw/xfree86/drivers/i810/i830_dri.c =================================================================== RCS file: /home/ncvs/dri/xc/xc/programs/Xserver/hw/xfree86/drivers/i810/i830_dri.c,v retrieving revision 1.16 diff -u -r1.16 i830_dri.c --- programs/Xserver/hw/xfree86/drivers/i810/i830_dri.c 12 Sep 2003 20:22:24 -0000 1.16 +++ programs/Xserver/hw/xfree86/drivers/i810/i830_dri.c 22 Oct 2003 00:53:37 -0000 @@ -444,12 +444,15 @@ pDRIInfo->drmDriverName = I830KernelDriverName; pDRIInfo->clientDriverName = I830ClientDriverName; - pDRIInfo->busIdString = xalloc(64); - - sprintf(pDRIInfo->busIdString, "PCI:%d:%d:%d", - ((pciConfigPtr) pI830->PciInfo->thisCard)->busnum, - ((pciConfigPtr) pI830->PciInfo->thisCard)->devnum, - ((pciConfigPtr) pI830->PciInfo->thisCard)->funcnum); + if (xf86LoaderCheckSymbol("DRICreatePCIBusID")) { + pDRIInfo->busIdString = DRICreatePCIBusID(pI830->PciInfo); + } else { + pDRIInfo->busIdString = xalloc(64); + sprintf(pDRIInfo->busIdString, "PCI:%d:%d:%d", + ((pciConfigPtr) pI830->PciInfo->thisCard)->busnum, + ((pciConfigPtr) pI830->PciInfo->thisCard)->devnum, + ((pciConfigPtr) pI830->PciInfo->thisCard)->funcnum); + } pDRIInfo->ddxDriverMajorVersion = I830_MAJOR_VERSION; pDRIInfo->ddxDriverMinorVersion = I830_MINOR_VERSION; pDRIInfo->ddxDriverPatchVersion = I830_PATCHLEVEL; Index: programs/Xserver/hw/xfree86/drivers/mga/mga_dri.c =================================================================== RCS file: /home/ncvs/dri/xc/xc/programs/Xserver/hw/xfree86/drivers/mga/mga_dri.c,v retrieving revision 1.54 diff -u -r1.54 mga_dri.c --- programs/Xserver/hw/xfree86/drivers/mga/mga_dri.c 16 Sep 2003 20:57:58 -0000 1.54 +++ programs/Xserver/hw/xfree86/drivers/mga/mga_dri.c 21 Oct 2003 23:33:17 -0000 @@ -1040,11 +1040,15 @@ pDRIInfo->drmDriverName = MGAKernelDriverName; pDRIInfo->clientDriverName = MGAClientDriverName; - pDRIInfo->busIdString = xalloc(64); - sprintf( pDRIInfo->busIdString, "PCI:%d:%d:%d", - ((pciConfigPtr)pMga->PciInfo->thisCard)->busnum, - ((pciConfigPtr)pMga->PciInfo->thisCard)->devnum, - ((pciConfigPtr)pMga->PciInfo->thisCard)->funcnum ); + if (xf86LoaderCheckSymbol("DRICreatePCIBusID")) { + pDRIInfo->busIdString = DRICreatePCIBusID(pMga->PciInfo); + } else { + pDRIInfo->busIdString = xalloc(64); + sprintf( pDRIInfo->busIdString, "PCI:%d:%d:%d", + ((pciConfigPtr)pMga->PciInfo->thisCard)->busnum, + ((pciConfigPtr)pMga->PciInfo->thisCard)->devnum, + ((pciConfigPtr)pMga->PciInfo->thisCard)->funcnum ); + } pDRIInfo->ddxDriverMajorVersion = MGA_MAJOR_VERSION; pDRIInfo->ddxDriverMinorVersion = MGA_MINOR_VERSION; pDRIInfo->ddxDriverPatchVersion = MGA_PATCHLEVEL; Index: programs/Xserver/hw/xfree86/drivers/sis/sis_dri.c =================================================================== RCS file: /home/ncvs/dri/xc/xc/programs/Xserver/hw/xfree86/drivers/sis/sis_dri.c,v retrieving revision 1.22 diff -u -r1.22 sis_dri.c --- programs/Xserver/hw/xfree86/drivers/sis/sis_dri.c 29 Aug 2003 19:36:18 -0000 1.22 +++ programs/Xserver/hw/xfree86/drivers/sis/sis_dri.c 22 Oct 2003 02:40:58 -0000 @@ -247,11 +247,15 @@ pDRIInfo->drmDriverName = SISKernelDriverName; pDRIInfo->clientDriverName = SISClientDriverName; - pDRIInfo->busIdString = xalloc(64); - sprintf(pDRIInfo->busIdString, "PCI:%d:%d:%d", - ((pciConfigPtr)pSIS->PciInfo->thisCard)->busnum, - ((pciConfigPtr)pSIS->PciInfo->thisCard)->devnum, - ((pciConfigPtr)pSIS->PciInfo->thisCard)->funcnum); + if (xf86LoaderCheckSymbol("DRICreatePCIBusID")) { + pDRIInfo->busIdString = DRICreatePCIBusID(pSIS->PciInfo); + } else { + pDRIInfo->busIdString = xalloc(64); + sprintf(pDRIInfo->busIdString, "PCI:%d:%d:%d", + ((pciConfigPtr)pSIS->PciInfo->thisCard)->busnum, + ((pciConfigPtr)pSIS->PciInfo->thisCard)->devnum, + ((pciConfigPtr)pSIS->PciInfo->thisCard)->funcnum); + } /* Hack to keep old DRI working -- checked for major==1 and * minor==1. */ Index: programs/Xserver/hw/xfree86/drivers/tdfx/tdfx_dri.c =================================================================== RCS file: /home/ncvs/dri/xc/xc/programs/Xserver/hw/xfree86/drivers/tdfx/tdfx_dri.c,v retrieving revision 1.42 diff -u -r1.42 tdfx_dri.c --- programs/Xserver/hw/xfree86/drivers/tdfx/tdfx_dri.c 1 May 2003 00:32:17 -0000 1.42 +++ programs/Xserver/hw/xfree86/drivers/tdfx/tdfx_dri.c 22 Oct 2003 00:16:39 -0000 @@ -329,11 +329,15 @@ pDRIInfo->drmDriverName = TDFXKernelDriverName; pDRIInfo->clientDriverName = TDFXClientDriverName; - pDRIInfo->busIdString = xalloc(64); - sprintf(pDRIInfo->busIdString, "PCI:%d:%d:%d", - ((pciConfigPtr)pTDFX->PciInfo->thisCard)->busnum, - ((pciConfigPtr)pTDFX->PciInfo->thisCard)->devnum, - ((pciConfigPtr)pTDFX->PciInfo->thisCard)->funcnum); + if (xf86LoaderCheckSymbol("DRICreatePCIBusID")) { + pDRIInfo->busIdString = DRICreatePCIBusID(pTDFX->PciInfo); + } else { + pDRIInfo->busIdString = xalloc(64); + sprintf(pDRIInfo->busIdString, "PCI:%d:%d:%d", + ((pciConfigPtr)pTDFX->PciInfo->thisCard)->busnum, + ((pciConfigPtr)pTDFX->PciInfo->thisCard)->devnum, + ((pciConfigPtr)pTDFX->PciInfo->thisCard)->funcnum); + } pDRIInfo->ddxDriverMajorVersion = TDFX_MAJOR_VERSION; pDRIInfo->ddxDriverMinorVersion = TDFX_MINOR_VERSION; pDRIInfo->ddxDriverPatchVersion = TDFX_PATCHLEVEL; Index: programs/Xserver/hw/xfree86/os-support/xf86drm.h =================================================================== RCS file: /home/ncvs/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/xf86drm.h,v retrieving revision 1.31 diff -u -r1.31 xf86drm.h --- programs/Xserver/hw/xfree86/os-support/xf86drm.h 12 Sep 2003 19:39:06 -0000 1.31 +++ programs/Xserver/hw/xfree86/os-support/xf86drm.h 21 Oct 2003 18:53:51 -0000 @@ -281,6 +281,12 @@ drmVBlankReply reply; } drmVBlank, *drmVBlankPtr; +typedef struct _drmSetVersion { + int drm_di_major; + int drm_di_minor; + int drm_dd_major; + int drm_dd_minor; +} drmSetVersion, *drmSetVersionPtr; #define __drm_dummy_lock(lock) (*(__volatile__ unsigned int *)lock) @@ -505,6 +511,7 @@ int *uid, unsigned long *magic, unsigned long *iocs); extern int drmGetStats(int fd, drmStatsT *stats); +extern int drmSetInterfaceVersion(int fd, drmSetVersion *version); extern int drmCommandNone(int fd, unsigned long drmCommandIndex); extern int drmCommandRead(int fd, unsigned long drmCommandIndex, void *data, unsigned long size); Index: programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm.h =================================================================== RCS file: /home/ncvs/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm.h,v retrieving revision 1.15 diff -u -r1.15 drm.h --- programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm.h 12 Sep 2003 14:24:17 -0000 1.15 +++ programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm.h 20 Oct 2003 22:51:20 -0000 @@ -405,6 +405,13 @@ unsigned long handle; /* Used for mapping / unmapping */ } drm_scatter_gather_t; +typedef struct drm_set_version { + int drm_di_major; + int drm_di_minor; + int drm_dd_major; + int drm_dd_minor; +} drm_set_version_t; + #define DRM_IOCTL_BASE 'd' #define DRM_IO(nr) _IO(DRM_IOCTL_BASE,nr) #define DRM_IOR(nr,type) _IOR(DRM_IOCTL_BASE,nr,type) @@ -418,6 +425,7 @@ #define DRM_IOCTL_GET_MAP DRM_IOWR(0x04, drm_map_t) #define DRM_IOCTL_GET_CLIENT DRM_IOWR(0x05, drm_client_t) #define DRM_IOCTL_GET_STATS DRM_IOR( 0x06, drm_stats_t) +#define DRM_IOCTL_SET_VERSION DRM_IOWR(0x07, drm_set_version_t) #define DRM_IOCTL_SET_UNIQUE DRM_IOW( 0x10, drm_unique_t) #define DRM_IOCTL_AUTH_MAGIC DRM_IOW( 0x11, drm_auth_t) Index: programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drmP.h =================================================================== RCS file: /home/ncvs/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drmP.h,v retrieving revision 1.37 diff -u -r1.37 drmP.h --- programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drmP.h 20 Oct 2003 00:55:56 -0000 1.37 +++ programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drmP.h 22 Oct 2003 02:57:54 -0000 @@ -390,9 +390,6 @@ extern int DRM(flags); - /* Driver support (drm_drv.h) */ -extern int DRM(version)( DRM_IOCTL_ARGS ); - /* Memory management support (drm_memory.h) */ extern void DRM(mem_init)(void); extern void DRM(mem_uninit)(void); @@ -491,6 +488,8 @@ /* Locking IOCTL support (drm_drv.h) */ extern int DRM(lock)(DRM_IOCTL_ARGS); extern int DRM(unlock)(DRM_IOCTL_ARGS); +extern int DRM(version)( DRM_IOCTL_ARGS ); +extern int DRM(setversion)( DRM_IOCTL_ARGS ); /* Misc. IOCTL support (drm_ioctl.h) */ extern int DRM(irq_busid)(DRM_IOCTL_ARGS); Index: programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_drv.h =================================================================== RCS file: /home/ncvs/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_drv.h,v retrieving revision 1.35 diff -u -r1.35 drm_drv.h --- programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_drv.h 20 Oct 2003 05:09:21 -0000 1.35 +++ programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_drv.h 21 Oct 2003 19:05:38 -0000 @@ -135,6 +135,7 @@ [DRM_IOCTL_NR(DRM_IOCTL_GET_MAP)] = { DRM(getmap), 0, 0 }, [DRM_IOCTL_NR(DRM_IOCTL_GET_CLIENT)] = { DRM(getclient), 0, 0 }, [DRM_IOCTL_NR(DRM_IOCTL_GET_STATS)] = { DRM(getstats), 0, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_SET_VERSION)] = { DRM(setversion), 0, 1 }, [DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE)] = { DRM(setunique), 1, 1 }, [DRM_IOCTL_NR(DRM_IOCTL_BLOCK)] = { DRM(noop), 1, 1 }, Index: programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_ioctl.h =================================================================== RCS file: /home/ncvs/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_ioctl.h,v retrieving revision 1.11 diff -u -r1.11 drm_ioctl.h --- programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_ioctl.h 3 Oct 2003 07:02:51 -0000 1.11 +++ programs/Xserver/hw/xfree86/os-support/bsd/drm/kernel/drm_ioctl.h 22 Oct 2003 03:03:39 -0000 @@ -79,6 +79,12 @@ #endif } +/* + * Beginning in revision 1.1 of the DRM interface, getunique will return + * a unique in the form pci:oooo:bb:dd.f (o=domain, b=bus, d=device, f=function) + * before setunique has been called. The format for the bus-specific part of + * the unique is not defined for any other bus. + */ int DRM(getunique)( DRM_IOCTL_ARGS ) { DRM_DEVICE; @@ -97,6 +103,9 @@ return 0; } +/* Deprecated in DRM version 1.1, and will return EBUSY when setversion has + * requested version 1.1 or greater. + */ int DRM(setunique)( DRM_IOCTL_ARGS ) { DRM_DEVICE; @@ -125,6 +134,26 @@ } +static int +DRM(set_busid)(drm_device_t *dev) +{ + + if (dev->unique != NULL) + return EBUSY; + + dev->unique_len = 20; + dev->unique = DRM(alloc)(dev->unique_len + 1, DRM_MEM_DRIVER); + if (dev->unique == NULL) + return ENOMEM; + + /* XXX How do domains work in *BSD? */ + snprintf(dev->unique, dev->unique_len, "pci:%04x:%02x:%02x.%1x", + 0, pci_get_bus(dev->device), pci_get_slot(dev->device), + pci_get_function(dev->device)); + + return 0; +} + int DRM(getmap)( DRM_IOCTL_ARGS ) { DRM_DEVICE; @@ -230,6 +259,49 @@ return 0; } + +int DRM(setversion)(DRM_IOCTL_ARGS) +{ + DRM_DEVICE; + drm_set_version_t sv; + drm_set_version_t retv; + + DRM_COPY_FROM_USER_IOCTL(sv, (drm_set_version_t *)data, sizeof(sv)); + + retv.drm_di_major = 1; + retv.drm_di_minor = 1; + retv.drm_dd_major = DRIVER_MAJOR; + retv.drm_dd_minor = DRIVER_MINOR; + + DRM_COPY_TO_USER_IOCTL((drm_set_version_t *)data, retv, sizeof(sv)); + + if (sv.drm_di_major != -1) { + if (sv.drm_di_major != 1 || sv.drm_di_minor < 0) + return EINVAL; + /* XXX: What to do with bigger minor values? */ + if (sv.drm_di_minor > 1) + return EINVAL; + if (sv.drm_di_minor >= 1) { + /* + * Version 1.1 includes tying of DRM to specific device + */ + DRM(set_busid)(dev); + } + } + + if (sv.drm_dd_major != -1) { + if (sv.drm_dd_major != DRIVER_MAJOR || sv.drm_dd_minor < 0) + return EINVAL; + /* XXX: What to do with bigger minor values? */ + if (sv.drm_dd_minor > DRIVER_MINOR) + return EINVAL; +#ifdef DRIVER_SETVERSION + DRIVER_SETVERSION(dev, sv); +#endif + } + return 0; +} + int DRM(noop)(DRM_IOCTL_ARGS) { Index: programs/Xserver/hw/xfree86/os-support/linux/drm/xf86drm.c =================================================================== RCS file: /home/ncvs/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/xf86drm.c,v retrieving revision 1.47 diff -u -r1.47 xf86drm.c --- programs/Xserver/hw/xfree86/os-support/linux/drm/xf86drm.c 24 Sep 2003 14:39:25 -0000 1.47 +++ programs/Xserver/hw/xfree86/os-support/linux/drm/xf86drm.c 22 Oct 2003 02:44:40 -0000 @@ -211,6 +211,55 @@ } /** + * Compare two busid strings + * + * \param first + * \param second + * + * \return 1 if matched. + * + * \internal + * This function compares two bus ID strings. It understands the older + * PCI:b:d:f format and the newer pci:oooo:bb:dd.f format. In the format, o is + * domain, b is bus, d is device, f is function. + */ +static int drmMatchBusID(const char *id1, const char *id2) +{ + /* First, check if the IDs are exactly the same */ + if (strcasecmp(id1, id2) == 0) + return 1; + + /* Try to match old/new-style PCI bus IDs. */ + if (strncasecmp(id1, "pci", 3) == 0) { + int o1, b1, d1, f1; + int o2, b2, d2, f2; + int ret; + + ret = sscanf(id1, "pci:%04x:%02x:%02x.%d", &o1, &b1, &d1, &f1); + if (ret != 4) { + o1 = 0; + ret = sscanf(id1, "PCI:%d:%d:%d", &b1, &d1, &f1); + if (ret != 3) + return 0; + } + + ret = sscanf(id2, "pci:%04x:%02x:%02x.%d", &o2, &b2, &d2, &f2); + if (ret != 4) { + o2 = 0; + ret = sscanf(id2, "PCI:%d:%d:%d", &b2, &d2, &f2); + if (ret != 3) + return 0; + } + + if ((o1 != o2) || (b1 != b2) || (d1 != d2) || (f1 != f2)) + return 0; + else + return 1; + } + return 0; +} + +/** * Open the DRM device, creating it if necessary. * * \param dev major and minor numbers of the device. @@ -235,7 +284,8 @@ gid_t group = DRM_DEV_GID; #endif - drmMsg("drmOpenDevice: minor is %d\n", minor); + sprintf(buf, DRM_DEV_NAME, DRM_DIR_NAME, minor); + drmMsg("drmOpenDevice: node name is %s\n", buf); #if defined(XFree86Server) devmode = xf86ConfigDRI.mode ? xf86ConfigDRI.mode : DRM_DEV_MODE; @@ -250,8 +300,7 @@ chmod(DRM_DIR_NAME, DRM_DEV_DIRMODE); } - sprintf(buf, DRM_DEV_NAME, DRM_DIR_NAME, minor); - drmMsg("drmOpenDevice: node name is %s\n", buf); + /* Check if the device node exists and create it if necessary. */ if (stat(buf, &st)) { if (!isroot) return DRM_ERR_NOT_ROOT; remove(buf); @@ -267,10 +316,17 @@ fd, fd < 0 ? strerror(errno) : "OK"); if (fd >= 0) return fd; + /* Check if the device node is not what we expect it to be, and recreate it + * and try again if so. + */ if (st.st_rdev != dev) { if (!isroot) return DRM_ERR_NOT_ROOT; remove(buf); mknod(buf, S_IFCHR | devmode, dev); +#if defined(XFree86Server) + chown(buf, user, group); + chmod(buf, devmode); +#endif } fd = open(buf, O_RDWR, 0); drmMsg("drmOpenDevice: open result is %d, (%s)\n", @@ -360,15 +416,20 @@ int i; int fd; const char *buf; - - drmMsg("drmOpenByBusid: busid is %s\n", busid); + drmSetVersion sv; + + drmMsg("drmOpenByBusid: Searching for BusID %s\n", busid); for (i = 0; i < DRM_MAX_MINOR; i++) { fd = drmOpenMinor(i, 1); drmMsg("drmOpenByBusid: drmOpenMinor returns %d\n", fd); if (fd >= 0) { + sv.drm_di_major = 1; + sv.drm_di_minor = 1; + sv.drm_dd_major = -1; /* Don't care */ + drmSetInterfaceVersion(fd, &sv); buf = drmGetBusid(fd); drmMsg("drmOpenByBusid: drmGetBusid reports %s\n", buf); - if (buf && !strcmp(buf, busid)) { + if (buf && drmMatchBusID(buf, busid)) { drmFreeBusid(buf); return fd; } @@ -494,9 +555,27 @@ */ int drmOpen(const char *name, const char *busid) { +#ifdef XFree86Server + if (!drmAvailable() && name != NULL) { + /* try to load the kernel */ + if (!xf86LoadKernelModule(name)) { + ErrorF("[drm] failed to load kernel module \"%s\"\n", + name); + return -1; + } + } +#endif + + if (busid) { + int fd; - if (busid) return drmOpenByBusid(busid); - return drmOpenByName(name); + fd = drmOpenByBusid(busid); + if (fd >= 0) + return fd; + } + if (name) + return drmOpenByName(name); + return -1; } @@ -647,9 +726,11 @@ * entry point and many drm extensions * revision 1.1.x = added drmCommand entry points for device extensions * added drmGetLibVersion to identify libdrm.a version + * revision 1.2.x = added drmSetInterfaceVersion + * modified drmOpen to handle both busid and name */ version->version_major = 1; - version->version_minor = 1; + version->version_minor = 2; version->version_patchlevel = 0; return (drmVersionPtr)version; @@ -693,6 +774,7 @@ u.unique = drmMalloc(u.unique_len + 1); if (ioctl(fd, DRM_IOCTL_GET_UNIQUE, &u)) return NULL; u.unique[u.unique_len] = '\0'; + return u.unique; } @@ -2027,6 +2109,42 @@ } } return 0; +} + +/** + * Issue a set-version ioctl. + * + * \param fd file descriptor. + * \param drmCommandIndex command index + * \param data source pointer of the data to be read and written. + * \param size size of the data to be read and written. + * + * \return zero on success, or a negative value on failure. + * + * \internal + * It issues a read-write ioctl given by + * \code DRM_COMMAND_BASE + drmCommandIndex \endcode. + */ +int drmSetInterfaceVersion(int fd, drmSetVersion *version ) +{ + int retcode = 0; + drm_set_version_t sv; + + sv.drm_di_major = version->drm_di_major; + sv.drm_di_minor = version->drm_di_minor; + sv.drm_dd_major = version->drm_dd_major; + sv.drm_dd_minor = version->drm_dd_minor; + + if (ioctl(fd, DRM_IOCTL_SET_VERSION, &sv)) { + retcode = -errno; + } + + version->drm_di_major = sv.drm_di_major; + version->drm_di_minor = sv.drm_di_minor; + version->drm_dd_major = sv.drm_dd_major; + version->drm_dd_minor = sv.drm_dd_minor; + + return retcode; } /** Index: programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm.h =================================================================== RCS file: /home/ncvs/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm.h,v retrieving revision 1.45 diff -u -r1.45 drm.h --- programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm.h 12 Sep 2003 14:24:17 -0000 1.45 +++ programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm.h 21 Oct 2003 18:33:06 -0000 @@ -584,6 +584,16 @@ unsigned long handle; /**< Used for mapping / unmapping */ } drm_scatter_gather_t; +/** + * DRM_IOCTL_SET_VERSION ioctl argument type. + */ +typedef struct drm_set_version { + int drm_di_major; + int drm_di_minor; + int drm_dd_major; + int drm_dd_minor; +} drm_set_version_t; + #define DRM_IOCTL_BASE 'd' #define DRM_IO(nr) _IO(DRM_IOCTL_BASE,nr) @@ -598,6 +608,7 @@ #define DRM_IOCTL_GET_MAP DRM_IOWR(0x04, drm_map_t) #define DRM_IOCTL_GET_CLIENT DRM_IOWR(0x05, drm_client_t) #define DRM_IOCTL_GET_STATS DRM_IOR( 0x06, drm_stats_t) +#define DRM_IOCTL_SET_VERSION DRM_IOWR(0x07, drm_set_version_t) #define DRM_IOCTL_SET_UNIQUE DRM_IOW( 0x10, drm_unique_t) #define DRM_IOCTL_AUTH_MAGIC DRM_IOW( 0x11, drm_auth_t) Index: programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drmP.h =================================================================== RCS file: /home/ncvs/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drmP.h,v retrieving revision 1.82 diff -u -r1.82 drmP.h --- programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drmP.h 17 Oct 2003 05:13:47 -0000 1.82 +++ programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drmP.h 21 Oct 2003 21:21:11 -0000 @@ -853,6 +853,8 @@ unsigned int cmd, unsigned long arg); extern int DRM(getstats)(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); +extern int DRM(setversion)(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); /* Context IOCTL support (drm_context.h) */ extern int DRM(resctx)( struct inode *inode, struct file *filp, Index: programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_drv.h =================================================================== RCS file: /home/ncvs/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_drv.h,v retrieving revision 1.46 diff -u -r1.46 drm_drv.h --- programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_drv.h 19 Oct 2003 20:06:03 -0000 1.46 +++ programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_drv.h 22 Oct 2003 00:58:26 -0000 @@ -174,6 +174,7 @@ [DRM_IOCTL_NR(DRM_IOCTL_GET_MAP)] = { DRM(getmap), 0, 0 }, [DRM_IOCTL_NR(DRM_IOCTL_GET_CLIENT)] = { DRM(getclient), 0, 0 }, [DRM_IOCTL_NR(DRM_IOCTL_GET_STATS)] = { DRM(getstats), 0, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_SET_VERSION)] = { DRM(setversion), 0, 1 }, [DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE)] = { DRM(setunique), 1, 1 }, [DRM_IOCTL_NR(DRM_IOCTL_BLOCK)] = { DRM(noop), 1, 1 }, Index: programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_ioctl.h =================================================================== RCS file: /home/ncvs/dri/xc/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_ioctl.h,v retrieving revision 1.15 diff -u -r1.15 drm_ioctl.h --- programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_ioctl.h 27 May 2003 00:37:33 -0000 1.15 +++ programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm_ioctl.h 22 Oct 2003 02:29:08 -0000 @@ -36,6 +36,7 @@ #define __NO_VERSION__ #include "drmP.h" +#include "linux/pci.h" /** * Get interrupt from bus id. @@ -140,7 +141,9 @@ * \return zero on success or a negative number on failure. * * Copies the bus id from userspace into drm_device::unique, and searches for - * the respective PCI device, updating drm_device::pdev. + * the respective PCI device, updating drm_device::pdev. Deprecated in + * interface version 1.1 and will return EBUSY when setversion has requested + * version 1.1 or greater. */ int DRM(setunique)(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) @@ -218,6 +221,36 @@ return 0; } +static int +DRM(set_busid)(drm_device_t *dev) +{ + if (dev->unique != NULL) + return EBUSY; + + dev->unique_len = 20; + dev->unique = DRM(alloc)(dev->unique_len + 1, DRM_MEM_DRIVER); + if (dev->unique == NULL) + return ENOMEM; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,74) + snprintf(dev->unique, dev->unique_len, "pci:%s", pci_name(dev->pdev)); +#else + { + int domain = 0; +#ifdef __alpha__ + struct pci_controller *hose = pci_dev->sysdata; + + domain = hose->bus->number; +#endif + snprintf(dev->unique, dev->unique_len, "pci:%04x:%02x:%02x.%d", + domain, dev->pdev->bus->number, + PCI_SLOT(dev->pdev->devfn), PCI_FUNC(dev->pdev->devfn)); + } +#endif + + return 0; +} + /** * Get a mapping information. @@ -362,5 +395,47 @@ if (copy_to_user((drm_stats_t *)arg, &stats, sizeof(stats))) return -EFAULT; + return 0; +} + +int DRM(setversion)(DRM_IOCTL_ARGS) +{ + DRM_DEVICE; + drm_set_version_t sv; + drm_set_version_t retv; + + DRM_COPY_FROM_USER_IOCTL(sv, (drm_set_version_t *)data, sizeof(sv)); + + retv.drm_di_major = 1; + retv.drm_di_minor = 1; + retv.drm_dd_major = DRIVER_MAJOR; + retv.drm_dd_minor = DRIVER_MINOR; + + DRM_COPY_TO_USER_IOCTL((drm_set_version_t *)data, retv, sizeof(sv)); + + if (sv.drm_di_major != -1) { + if (sv.drm_di_major != 1 || sv.drm_di_minor < 0) + return EINVAL; + /* XXX: What to do with bigger minor values? */ + if (sv.drm_di_minor > 1) + return EINVAL; + if (sv.drm_di_minor >= 1) { + /* + * Version 1.1 includes tying of DRM to specific device + */ + DRM(set_busid)(dev); + } + } + + if (sv.drm_dd_major != -1) { + if (sv.drm_dd_major != DRIVER_MAJOR || sv.drm_dd_minor < 0) + return EINVAL; + /* XXX: What to do with bigger minor values? */ + if (sv.drm_dd_minor > DRIVER_MINOR) + return EINVAL; +#ifdef DRIVER_SETVERSION + DRIVER_SETVERSION(dev, sv); +#endif + } return 0; }