summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Dawes <dawes@xfree86.org>2001-07-30 19:59:39 +0000
committerDavid Dawes <dawes@xfree86.org>2001-07-30 19:59:39 +0000
commit56bd9c207770d41a497f3e8237a1099dd9d4cd91 (patch)
tree528632e9ff74ae98caa8c55d4a8f201669c00e93
parent84a5e7108773d5a5ff7242e1460c98e3acb178a8 (diff)
Merge the multihead-1-0-0 branch into the trunk, with the exception of the
glide header files. The changes include: - Brian Paul's changes to the tdfx client-side 3D driver to make it dlopen() the correct glide library (Voodoo3 or Voodoo5). This allows both types of the glide library to co-exist, and allows Voodoo3/Voodoo5 cards to be mixed in multi-head configs. - DRM kernel driver changes to allow a driver to set up multiple instances (minor numbers), one for each card present that the driver supports. This is currently implemented and tested only for the tdfx DRM driver. - Add some missing missing <stdarg.h> includes. - Some log message cleanups. - Change the 2D tdfx driver to access VGA legacy registers via their PCI I/O space access points rather than their legacy addresses, and fix some problems with the way the VGA-related bits are initialised. Status: - With these changes, multi-head direct rendering works with multiple Voodoo3 and/or Voodoo5 cards. This has been tested with two PCI Voodoo3 cards and an AGP Voodoo5 card, and all permutations of those. Caveats: - Xinerama is not supported. If Xinerama is enabled, then direct rendering gets disabled. - The text mode on secondary screens will show junk after the X server exits. - On some hardware, starting the X server on multiple 3dfx cards will result in a hard lockup. One workaround is to enable APIC support in a uni-processor kernel, or use an SMP kernel.
-rw-r--r--libdrm/xf86drm.c62
-rw-r--r--linux-core/drm_drv.c192
-rw-r--r--linux-core/drm_init.c6
-rw-r--r--linux-core/drm_stub.c8
-rw-r--r--linux-core/tdfx_drv.c9
-rw-r--r--linux/drm_drv.h192
-rw-r--r--linux/drm_init.h6
-rw-r--r--linux/drm_stub.h8
-rw-r--r--linux/tdfx_drv.c9
9 files changed, 369 insertions, 123 deletions
diff --git a/libdrm/xf86drm.c b/libdrm/xf86drm.c
index a04cf7ae..5ed8f1f8 100644
--- a/libdrm/xf86drm.c
+++ b/libdrm/xf86drm.c
@@ -55,6 +55,7 @@
# include <sys/ioctl.h>
# include <sys/mman.h>
# include <sys/time.h>
+# include <stdarg.h>
# ifdef DRM_USE_MALLOC
# define _DRM_MALLOC malloc
# define _DRM_FREE free
@@ -107,6 +108,28 @@ extern unsigned long _bus_base(void);
#define makedev(x,y) ((dev_t)(((x) << 8) | (y)))
#endif
+#define DRM_MSG_VERBOSITY 3
+
+static void
+drmMsg(const char *format, ...)
+{
+ va_list ap;
+
+#ifndef XFree86Server
+ const char *env;
+ if ((env = getenv("LIBGL_DEBUG")) && strstr(env, "verbose"))
+#endif
+ {
+ va_start(ap, format);
+#ifdef XFree86Server
+ xf86VDrvMsgVerb(-1, X_NONE, DRM_MSG_VERBOSITY, format, ap);
+#else
+ vfprintf(stderr, format, ap);
+#endif
+ va_end(ap);
+ }
+}
+
static void *drmHashTable = NULL; /* Context switch callbacks */
typedef struct drmHashEntry {
@@ -182,6 +205,8 @@ static int drmOpenDevice(long dev, int minor)
gid_t group = DRM_DEV_GID;
#endif
+ drmMsg("drmOpenDevice: minor is %d\n", minor);
+
#if defined(XFree86Server)
devmode = xf86ConfigDRI.mode ? xf86ConfigDRI.mode : DRM_DEV_MODE;
dirmode = (devmode & S_IRUSR) ? S_IXUSR : 0;
@@ -203,6 +228,7 @@ static int drmOpenDevice(long dev, int minor)
#endif
sprintf(buf, DRM_DEV_NAME, DRM_DIR_NAME, minor);
+ drmMsg("drmOpenDevice: node name is %s\n", buf);
if (stat(buf, &st) || st.st_rdev != dev) {
if (!isroot) return DRM_ERR_NOT_ROOT;
remove(buf);
@@ -213,7 +239,11 @@ static int drmOpenDevice(long dev, int minor)
chmod(buf, devmode);
#endif
- if ((fd = open(buf, O_RDWR, 0)) >= 0) return fd;
+ fd = open(buf, O_RDWR, 0);
+ drmMsg("drmOpenDevice: open result is %d, (%s)\n",
+ fd, fd < 0 ? strerror(errno) : "OK");
+ if (fd >= 0) return fd;
+ drmMsg("drmOpenDevice: Open failed\n");
remove(buf);
return -errno;
}
@@ -261,9 +291,13 @@ static int drmOpenByBusid(const char *busid)
int fd;
const char *buf;
+ drmMsg("drmOpenByBusid: busid is %s\n", busid);
for (i = 0; i < DRM_MAX_MINOR; i++) {
- if ((fd = drmOpenMinor(i, 0)) >= 0) {
+ fd = drmOpenMinor(i, 1);
+ drmMsg("drmOpenByBusid: drmOpenMinor returns %d\n", fd);
+ if (fd >= 0) {
buf = drmGetBusid(fd);
+ drmMsg("drmOpenByBusid: drmGetBusid reports %s\n", buf);
if (buf && !strcmp(buf, busid)) {
drmFreeBusid(buf);
return fd;
@@ -280,6 +314,7 @@ static int drmOpenByName(const char *name)
int i;
int fd;
drmVersionPtr version;
+ char * id;
if (!drmAvailable()) {
#if !defined(XFree86Server)
@@ -294,15 +329,30 @@ static int drmOpenByName(const char *name)
#endif
}
+ /*
+ * Open the first minor number that matches the driver name and isn't
+ * already in use. If it's in use it will have a busid assigned already.
+ */
for (i = 0; i < DRM_MAX_MINOR; i++) {
if ((fd = drmOpenMinor(i, 1)) >= 0) {
if ((version = drmGetVersion(fd))) {
if (!strcmp(version->name, name)) {
drmFreeVersion(version);
- return fd;
+ id = drmGetBusid(fd);
+ drmMsg("drmGetBusid returned '%s'\n", id ? id : "NULL");
+ if (!id || !*id) {
+ if (id) {
+ drmFreeBusid(id);
+ }
+ return fd;
+ } else {
+ drmFreeBusid(id);
+ }
+ } else {
+ drmFreeVersion(version);
}
- drmFreeVersion(version);
}
+ close(fd);
}
}
@@ -459,7 +509,9 @@ int drmSetBusid(int fd, const char *busid)
u.unique = (char *)busid;
u.unique_len = strlen(busid);
- if (ioctl(fd, DRM_IOCTL_SET_UNIQUE, &u)) return -errno;
+ if (ioctl(fd, DRM_IOCTL_SET_UNIQUE, &u)) {
+ return -errno;
+ }
return 0;
}
diff --git a/linux-core/drm_drv.c b/linux-core/drm_drv.c
index c5f231c7..dd46f227 100644
--- a/linux-core/drm_drv.c
+++ b/linux-core/drm_drv.c
@@ -101,9 +101,16 @@
#define DRIVER_IOCTLS
#endif
+/*
+ * The default number of instances (minor numbers) to initialize.
+ */
+#ifndef DRIVER_NUM_CARDS
+#define DRIVER_NUM_CARDS 1
+#endif
-static drm_device_t DRM(device);
-static int DRM(minor);
+static drm_device_t *DRM(device);
+static int *DRM(minor);
+static int DRM(numdevs) = 0;
static struct file_operations DRM(fops) = {
#if LINUX_VERSION_CODE >= 0x020400
@@ -460,46 +467,102 @@ static int DRM(takedown)( drm_device_t *dev )
return 0;
}
+/*
+ * Figure out how many instances to initialize.
+ */
+static int drm_count_cards(void)
+{
+ int num = 0;
+#if defined(DRIVER_CARD_LIST)
+ u_int *l;
+ u_int device, vendor;
+ struct pci_dev *pdev = NULL;
+#endif
+
+ DRM_DEBUG( "\n" );
+
+#if defined(DRIVER_COUNT_CARDS)
+ num = DRIVER_COUNT_CARDS();
+#elif defined(DRIVER_CARD_LIST)
+ for (l = DRIVER_CARD_LIST; *l; l++) {
+ pdev = NULL;
+ device = *l & 0xFFFF;
+ if (device == 0xFFFF)
+ device = PCI_ANY_ID;
+ vendor = (*l >> 16) & 0xFFFF;
+ if (vendor == 0xFFFF)
+ vendor = PCI_ANY_ID;
+ while ((pdev = pci_find_device(vendor, device, pdev))) {
+ num++;
+ }
+ }
+#else
+ num = DRIVER_NUM_CARDS;
+#endif
+ DRM_DEBUG("numdevs = %d\n", num);
+ return num;
+}
+
/* drm_init is called via init_module at module load time, or via
* linux/init/main.c (this is not currently supported).
*/
static int __init drm_init( void )
{
- drm_device_t *dev = &DRM(device);
+
+ drm_device_t *dev;
+ int i;
#if __HAVE_CTX_BITMAP
int retcode;
#endif
DRM_DEBUG( "\n" );
- memset( (void *)dev, 0, sizeof(*dev) );
- dev->count_lock = SPIN_LOCK_UNLOCKED;
- sema_init( &dev->struct_sem, 1 );
-
#ifdef MODULE
DRM(parse_options)( drm_opts );
#endif
+
+ DRM(numdevs) = drm_count_cards();
+ /* Force at least one instance. */
+ if (DRM(numdevs) <= 0)
+ DRM(numdevs) = 1;
+
+ DRM(device) = kmalloc(sizeof(*DRM(device)) * DRM(numdevs), GFP_KERNEL);
+ if (!DRM(device)) {
+ return -ENOMEM;
+ }
+ DRM(minor) = kmalloc(sizeof(*DRM(minor)) * DRM(numdevs), GFP_KERNEL);
+ if (!DRM(minor)) {
+ kfree(DRM(device));
+ return -ENOMEM;
+ }
+
DRIVER_PREINIT();
DRM(mem_init)();
- if ((DRM(minor) = DRM(stub_register)(DRIVER_NAME, &DRM(fops),dev)) < 0)
- return -EPERM;
- dev->device = MKDEV(DRM_MAJOR, DRM(minor) );
- dev->name = DRIVER_NAME;
+ for (i = 0; i < DRM(numdevs); i++) {
+ dev = &(DRM(device)[i]);
+ memset( (void *)dev, 0, sizeof(*dev) );
+ dev->count_lock = SPIN_LOCK_UNLOCKED;
+ sema_init( &dev->struct_sem, 1 );
+
+ if ((DRM(minor)[i] = DRM(stub_register)(DRIVER_NAME, &DRM(fops),dev)) < 0)
+ return -EPERM;
+ dev->device = MKDEV(DRM_MAJOR, DRM(minor)[i] );
+ dev->name = DRIVER_NAME;
#if __REALLY_HAVE_AGP
- dev->agp = DRM(agp_init)();
+ dev->agp = DRM(agp_init)();
#if __MUST_HAVE_AGP
- if ( dev->agp == NULL ) {
- DRM_ERROR( "Cannot initialize the agpgart module.\n" );
- DRM(stub_unregister)(DRM(minor));
- DRM(takedown)( dev );
- return -ENOMEM;
- }
+ if ( dev->agp == NULL ) {
+ DRM_ERROR( "Cannot initialize the agpgart module.\n" );
+ DRM(stub_unregister)(DRM(minor)[i]);
+ DRM(takedown)( dev );
+ return -ENOMEM;
+ }
#endif
#if __REALLY_HAVE_MTRR
- if (dev->agp)
- dev->agp->agp_mtrr = mtrr_add( dev->agp->agp_info.aper_base,
+ if (dev->agp)
+ dev->agp->agp_mtrr = mtrr_add( dev->agp->agp_info.aper_base,
dev->agp->agp_info.aper_size*1024*1024,
MTRR_TYPE_WRCOMB,
1 );
@@ -507,25 +570,25 @@ static int __init drm_init( void )
#endif
#if __HAVE_CTX_BITMAP
- retcode = DRM(ctxbitmap_init)( dev );
- if( retcode ) {
- DRM_ERROR( "Cannot allocate memory for context bitmap.\n" );
- DRM(stub_unregister)(DRM(minor));
- DRM(takedown)( dev );
- return retcode;
- }
+ retcode = DRM(ctxbitmap_init)( dev );
+ if( retcode ) {
+ DRM_ERROR( "Cannot allocate memory for context bitmap.\n" );
+ DRM(stub_unregister)(DRM(minor)[i]);
+ DRM(takedown)( dev );
+ return retcode;
+ }
#endif
+ DRM_INFO( "Initialized %s %d.%d.%d %s on minor %d\n",
+ DRIVER_NAME,
+ DRIVER_MAJOR,
+ DRIVER_MINOR,
+ DRIVER_PATCHLEVEL,
+ DRIVER_DATE,
+ DRM(minor)[i] );
+ }
DRIVER_POSTINIT();
- DRM_INFO( "Initialized %s %d.%d.%d %s on minor %d\n",
- DRIVER_NAME,
- DRIVER_MAJOR,
- DRIVER_MINOR,
- DRIVER_PATCHLEVEL,
- DRIVER_DATE,
- DRM(minor) );
-
return 0;
}
@@ -533,38 +596,48 @@ static int __init drm_init( void )
*/
static void __exit drm_cleanup( void )
{
- drm_device_t *dev = &DRM(device);
+ drm_device_t *dev;
+ int i;
DRM_DEBUG( "\n" );
- if ( DRM(stub_unregister)(DRM(minor)) ) {
- DRM_ERROR( "Cannot unload module\n" );
- } else {
- DRM_INFO( "Module unloaded\n" );
- }
+ for (i = DRM(numdevs) - 1; i >= 0; i--) {
+ dev = &(DRM(device)[i]);
+ if ( DRM(stub_unregister)(DRM(minor)[i]) ) {
+ DRM_ERROR( "Cannot unload module\n" );
+ } else {
+ DRM_DEBUG("minor %d unregistered\n", DRM(minor)[i]);
+ if (i == 0) {
+ DRM_INFO( "Module unloaded\n" );
+ }
+ }
#if __HAVE_CTX_BITMAP
- DRM(ctxbitmap_cleanup)( dev );
+ DRM(ctxbitmap_cleanup)( dev );
#endif
#if __REALLY_HAVE_AGP && __REALLY_HAVE_MTRR
- if ( dev->agp && dev->agp->agp_mtrr ) {
- int retval;
- retval = mtrr_del( dev->agp->agp_mtrr,
+ if ( dev->agp && dev->agp->agp_mtrr ) {
+ int retval;
+ retval = mtrr_del( dev->agp->agp_mtrr,
dev->agp->agp_info.aper_base,
dev->agp->agp_info.aper_size*1024*1024 );
- DRM_DEBUG( "mtrr_del=%d\n", retval );
- }
+ DRM_DEBUG( "mtrr_del=%d\n", retval );
+ }
#endif
- DRM(takedown)( dev );
+ DRM(takedown)( dev );
#if __REALLY_HAVE_AGP
- if ( dev->agp ) {
- DRM(agp_uninit)();
- DRM(free)( dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS );
- dev->agp = NULL;
- }
+ if ( dev->agp ) {
+ DRM(agp_uninit)();
+ DRM(free)( dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS );
+ dev->agp = NULL;
+ }
#endif
+ }
+ kfree(DRM(minor));
+ kfree(DRM(device));
+ DRM(numdevs) = 0;
}
module_init( drm_init );
@@ -608,8 +681,19 @@ int DRM(version)( struct inode *inode, struct file *filp,
int DRM(open)( struct inode *inode, struct file *filp )
{
- drm_device_t *dev = &DRM(device);
+ drm_device_t *dev = NULL;
int retcode = 0;
+ int i;
+
+ for (i = 0; i < DRM(numdevs); i++) {
+ if (MINOR(inode->i_rdev) == DRM(minor)[i]) {
+ dev = &(DRM(device)[i]);
+ break;
+ }
+ }
+ if (!dev) {
+ return -ENODEV;
+ }
DRM_DEBUG( "open_count = %d\n", dev->open_count );
diff --git a/linux-core/drm_init.c b/linux-core/drm_init.c
index d9d8e3a2..2d6b6a3c 100644
--- a/linux-core/drm_init.c
+++ b/linux-core/drm_init.c
@@ -64,18 +64,18 @@ static void DRM(parse_option)(char *s)
return;
}
-/* drm_parse_options parse the insmod "drm=" options, or the command-line
+/* drm_parse_options parse the insmod "drm_opts=" options, or the command-line
* options passed to the kernel via LILO. The grammar of the format is as
* follows:
*
- * drm ::= 'drm=' option_list
+ * drm ::= 'drm_opts=' option_list
* option_list ::= option [ ';' option_list ]
* option ::= 'device:' major
* | 'debug'
* | 'noctx'
* major ::= INTEGER
*
- * Note that 's' contains option_list without the 'drm=' part.
+ * Note that 's' contains option_list without the 'drm_opts=' part.
*
* device=major,minor specifies the device number used for /dev/drm
* if major == 0 then the misc device is used
diff --git a/linux-core/drm_stub.c b/linux-core/drm_stub.c
index bc958796..6811d6ba 100644
--- a/linux-core/drm_stub.c
+++ b/linux-core/drm_stub.c
@@ -121,11 +121,13 @@ static int DRM(stub_putminor)(int minor)
return 0;
}
+
int DRM(stub_register)(const char *name, struct file_operations *fops,
drm_device_t *dev)
{
struct drm_stub_info *i = NULL;
-
+
+ DRM_DEBUG("\n");
if (register_chrdev(DRM_MAJOR, "drm", &DRM(stub_fops)))
i = (struct drm_stub_info *)inter_module_get("drm");
@@ -133,9 +135,11 @@ int DRM(stub_register)(const char *name, struct file_operations *fops,
/* Already registered */
DRM(stub_info).info_register = i->info_register;
DRM(stub_info).info_unregister = i->info_unregister;
- } else {
+ DRM_DEBUG("already registered\n");
+ } else if (DRM(stub_info).info_register != DRM(stub_getminor)) {
DRM(stub_info).info_register = DRM(stub_getminor);
DRM(stub_info).info_unregister = DRM(stub_putminor);
+ DRM_DEBUG("calling inter_module_register\n");
inter_module_register("drm", THIS_MODULE, &DRM(stub_info));
}
if (DRM(stub_info).info_register)
diff --git a/linux-core/tdfx_drv.c b/linux-core/tdfx_drv.c
index b6c95498..94e5d41c 100644
--- a/linux-core/tdfx_drv.c
+++ b/linux-core/tdfx_drv.c
@@ -44,6 +44,15 @@
#define DRIVER_MINOR 0
#define DRIVER_PATCHLEVEL 0
+static u_int DRM(idlist)[] = {
+ 0x121A0003, /* Banshee */
+ 0x121A0005, /* Voodoo3 */
+ 0x121A0009, /* Voodoo5 */
+ 0
+};
+
+#define DRIVER_CARD_LIST DRM(idlist)
+
#include "drm_auth.h"
#include "drm_bufs.h"
diff --git a/linux/drm_drv.h b/linux/drm_drv.h
index c5f231c7..dd46f227 100644
--- a/linux/drm_drv.h
+++ b/linux/drm_drv.h
@@ -101,9 +101,16 @@
#define DRIVER_IOCTLS
#endif
+/*
+ * The default number of instances (minor numbers) to initialize.
+ */
+#ifndef DRIVER_NUM_CARDS
+#define DRIVER_NUM_CARDS 1
+#endif
-static drm_device_t DRM(device);
-static int DRM(minor);
+static drm_device_t *DRM(device);
+static int *DRM(minor);
+static int DRM(numdevs) = 0;
static struct file_operations DRM(fops) = {
#if LINUX_VERSION_CODE >= 0x020400
@@ -460,46 +467,102 @@ static int DRM(takedown)( drm_device_t *dev )
return 0;
}
+/*
+ * Figure out how many instances to initialize.
+ */
+static int drm_count_cards(void)
+{
+ int num = 0;
+#if defined(DRIVER_CARD_LIST)
+ u_int *l;
+ u_int device, vendor;
+ struct pci_dev *pdev = NULL;
+#endif
+
+ DRM_DEBUG( "\n" );
+
+#if defined(DRIVER_COUNT_CARDS)
+ num = DRIVER_COUNT_CARDS();
+#elif defined(DRIVER_CARD_LIST)
+ for (l = DRIVER_CARD_LIST; *l; l++) {
+ pdev = NULL;
+ device = *l & 0xFFFF;
+ if (device == 0xFFFF)
+ device = PCI_ANY_ID;
+ vendor = (*l >> 16) & 0xFFFF;
+ if (vendor == 0xFFFF)
+ vendor = PCI_ANY_ID;
+ while ((pdev = pci_find_device(vendor, device, pdev))) {
+ num++;
+ }
+ }
+#else
+ num = DRIVER_NUM_CARDS;
+#endif
+ DRM_DEBUG("numdevs = %d\n", num);
+ return num;
+}
+
/* drm_init is called via init_module at module load time, or via
* linux/init/main.c (this is not currently supported).
*/
static int __init drm_init( void )
{
- drm_device_t *dev = &DRM(device);
+
+ drm_device_t *dev;
+ int i;
#if __HAVE_CTX_BITMAP
int retcode;
#endif
DRM_DEBUG( "\n" );
- memset( (void *)dev, 0, sizeof(*dev) );
- dev->count_lock = SPIN_LOCK_UNLOCKED;
- sema_init( &dev->struct_sem, 1 );
-
#ifdef MODULE
DRM(parse_options)( drm_opts );
#endif
+
+ DRM(numdevs) = drm_count_cards();
+ /* Force at least one instance. */
+ if (DRM(numdevs) <= 0)
+ DRM(numdevs) = 1;
+
+ DRM(device) = kmalloc(sizeof(*DRM(device)) * DRM(numdevs), GFP_KERNEL);
+ if (!DRM(device)) {
+ return -ENOMEM;
+ }
+ DRM(minor) = kmalloc(sizeof(*DRM(minor)) * DRM(numdevs), GFP_KERNEL);
+ if (!DRM(minor)) {
+ kfree(DRM(device));
+ return -ENOMEM;
+ }
+
DRIVER_PREINIT();
DRM(mem_init)();
- if ((DRM(minor) = DRM(stub_register)(DRIVER_NAME, &DRM(fops),dev)) < 0)
- return -EPERM;
- dev->device = MKDEV(DRM_MAJOR, DRM(minor) );
- dev->name = DRIVER_NAME;
+ for (i = 0; i < DRM(numdevs); i++) {
+ dev = &(DRM(device)[i]);
+ memset( (void *)dev, 0, sizeof(*dev) );
+ dev->count_lock = SPIN_LOCK_UNLOCKED;
+ sema_init( &dev->struct_sem, 1 );
+
+ if ((DRM(minor)[i] = DRM(stub_register)(DRIVER_NAME, &DRM(fops),dev)) < 0)
+ return -EPERM;
+ dev->device = MKDEV(DRM_MAJOR, DRM(minor)[i] );
+ dev->name = DRIVER_NAME;
#if __REALLY_HAVE_AGP
- dev->agp = DRM(agp_init)();
+ dev->agp = DRM(agp_init)();
#if __MUST_HAVE_AGP
- if ( dev->agp == NULL ) {
- DRM_ERROR( "Cannot initialize the agpgart module.\n" );
- DRM(stub_unregister)(DRM(minor));
- DRM(takedown)( dev );
- return -ENOMEM;
- }
+ if ( dev->agp == NULL ) {
+ DRM_ERROR( "Cannot initialize the agpgart module.\n" );
+ DRM(stub_unregister)(DRM(minor)[i]);
+ DRM(takedown)( dev );
+ return -ENOMEM;
+ }
#endif
#if __REALLY_HAVE_MTRR
- if (dev->agp)
- dev->agp->agp_mtrr = mtrr_add( dev->agp->agp_info.aper_base,
+ if (dev->agp)
+ dev->agp->agp_mtrr = mtrr_add( dev->agp->agp_info.aper_base,
dev->agp->agp_info.aper_size*1024*1024,
MTRR_TYPE_WRCOMB,
1 );
@@ -507,25 +570,25 @@ static int __init drm_init( void )
#endif
#if __HAVE_CTX_BITMAP
- retcode = DRM(ctxbitmap_init)( dev );
- if( retcode ) {
- DRM_ERROR( "Cannot allocate memory for context bitmap.\n" );
- DRM(stub_unregister)(DRM(minor));
- DRM(takedown)( dev );
- return retcode;
- }
+ retcode = DRM(ctxbitmap_init)( dev );
+ if( retcode ) {
+ DRM_ERROR( "Cannot allocate memory for context bitmap.\n" );
+ DRM(stub_unregister)(DRM(minor)[i]);
+ DRM(takedown)( dev );
+ return retcode;
+ }
#endif
+ DRM_INFO( "Initialized %s %d.%d.%d %s on minor %d\n",
+ DRIVER_NAME,
+ DRIVER_MAJOR,
+ DRIVER_MINOR,
+ DRIVER_PATCHLEVEL,
+ DRIVER_DATE,
+ DRM(minor)[i] );
+ }
DRIVER_POSTINIT();
- DRM_INFO( "Initialized %s %d.%d.%d %s on minor %d\n",
- DRIVER_NAME,
- DRIVER_MAJOR,
- DRIVER_MINOR,
- DRIVER_PATCHLEVEL,
- DRIVER_DATE,
- DRM(minor) );
-
return 0;
}
@@ -533,38 +596,48 @@ static int __init drm_init( void )
*/
static void __exit drm_cleanup( void )
{
- drm_device_t *dev = &DRM(device);
+ drm_device_t *dev;
+ int i;
DRM_DEBUG( "\n" );
- if ( DRM(stub_unregister)(DRM(minor)) ) {
- DRM_ERROR( "Cannot unload module\n" );
- } else {
- DRM_INFO( "Module unloaded\n" );
- }
+ for (i = DRM(numdevs) - 1; i >= 0; i--) {
+ dev = &(DRM(device)[i]);
+ if ( DRM(stub_unregister)(DRM(minor)[i]) ) {
+ DRM_ERROR( "Cannot unload module\n" );
+ } else {
+ DRM_DEBUG("minor %d unregistered\n", DRM(minor)[i]);
+ if (i == 0) {
+ DRM_INFO( "Module unloaded\n" );
+ }
+ }
#if __HAVE_CTX_BITMAP
- DRM(ctxbitmap_cleanup)( dev );
+ DRM(ctxbitmap_cleanup)( dev );
#endif
#if __REALLY_HAVE_AGP && __REALLY_HAVE_MTRR
- if ( dev->agp && dev->agp->agp_mtrr ) {
- int retval;
- retval = mtrr_del( dev->agp->agp_mtrr,
+ if ( dev->agp && dev->agp->agp_mtrr ) {
+ int retval;
+ retval = mtrr_del( dev->agp->agp_mtrr,
dev->agp->agp_info.aper_base,
dev->agp->agp_info.aper_size*1024*1024 );
- DRM_DEBUG( "mtrr_del=%d\n", retval );
- }
+ DRM_DEBUG( "mtrr_del=%d\n", retval );
+ }
#endif
- DRM(takedown)( dev );
+ DRM(takedown)( dev );
#if __REALLY_HAVE_AGP
- if ( dev->agp ) {
- DRM(agp_uninit)();
- DRM(free)( dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS );
- dev->agp = NULL;
- }
+ if ( dev->agp ) {
+ DRM(agp_uninit)();
+ DRM(free)( dev->agp, sizeof(*dev->agp), DRM_MEM_AGPLISTS );
+ dev->agp = NULL;
+ }
#endif
+ }
+ kfree(DRM(minor));
+ kfree(DRM(device));
+ DRM(numdevs) = 0;
}
module_init( drm_init );
@@ -608,8 +681,19 @@ int DRM(version)( struct inode *inode, struct file *filp,
int DRM(open)( struct inode *inode, struct file *filp )
{
- drm_device_t *dev = &DRM(device);
+ drm_device_t *dev = NULL;
int retcode = 0;
+ int i;
+
+ for (i = 0; i < DRM(numdevs); i++) {
+ if (MINOR(inode->i_rdev) == DRM(minor)[i]) {
+ dev = &(DRM(device)[i]);
+ break;
+ }
+ }
+ if (!dev) {
+ return -ENODEV;
+ }
DRM_DEBUG( "open_count = %d\n", dev->open_count );
diff --git a/linux/drm_init.h b/linux/drm_init.h
index d9d8e3a2..2d6b6a3c 100644
--- a/linux/drm_init.h
+++ b/linux/drm_init.h
@@ -64,18 +64,18 @@ static void DRM(parse_option)(char *s)
return;
}
-/* drm_parse_options parse the insmod "drm=" options, or the command-line
+/* drm_parse_options parse the insmod "drm_opts=" options, or the command-line
* options passed to the kernel via LILO. The grammar of the format is as
* follows:
*
- * drm ::= 'drm=' option_list
+ * drm ::= 'drm_opts=' option_list
* option_list ::= option [ ';' option_list ]
* option ::= 'device:' major
* | 'debug'
* | 'noctx'
* major ::= INTEGER
*
- * Note that 's' contains option_list without the 'drm=' part.
+ * Note that 's' contains option_list without the 'drm_opts=' part.
*
* device=major,minor specifies the device number used for /dev/drm
* if major == 0 then the misc device is used
diff --git a/linux/drm_stub.h b/linux/drm_stub.h
index bc958796..6811d6ba 100644
--- a/linux/drm_stub.h
+++ b/linux/drm_stub.h
@@ -121,11 +121,13 @@ static int DRM(stub_putminor)(int minor)
return 0;
}
+
int DRM(stub_register)(const char *name, struct file_operations *fops,
drm_device_t *dev)
{
struct drm_stub_info *i = NULL;
-
+
+ DRM_DEBUG("\n");
if (register_chrdev(DRM_MAJOR, "drm", &DRM(stub_fops)))
i = (struct drm_stub_info *)inter_module_get("drm");
@@ -133,9 +135,11 @@ int DRM(stub_register)(const char *name, struct file_operations *fops,
/* Already registered */
DRM(stub_info).info_register = i->info_register;
DRM(stub_info).info_unregister = i->info_unregister;
- } else {
+ DRM_DEBUG("already registered\n");
+ } else if (DRM(stub_info).info_register != DRM(stub_getminor)) {
DRM(stub_info).info_register = DRM(stub_getminor);
DRM(stub_info).info_unregister = DRM(stub_putminor);
+ DRM_DEBUG("calling inter_module_register\n");
inter_module_register("drm", THIS_MODULE, &DRM(stub_info));
}
if (DRM(stub_info).info_register)
diff --git a/linux/tdfx_drv.c b/linux/tdfx_drv.c
index b6c95498..94e5d41c 100644
--- a/linux/tdfx_drv.c
+++ b/linux/tdfx_drv.c
@@ -44,6 +44,15 @@
#define DRIVER_MINOR 0
#define DRIVER_PATCHLEVEL 0
+static u_int DRM(idlist)[] = {
+ 0x121A0003, /* Banshee */
+ 0x121A0005, /* Voodoo3 */
+ 0x121A0009, /* Voodoo5 */
+ 0
+};
+
+#define DRIVER_CARD_LIST DRM(idlist)
+
#include "drm_auth.h"
#include "drm_bufs.h"