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.main
parent
84a5e71087
commit
56bd9c2077
|
@ -55,6 +55,7 @@
|
||||||
# include <sys/ioctl.h>
|
# include <sys/ioctl.h>
|
||||||
# include <sys/mman.h>
|
# include <sys/mman.h>
|
||||||
# include <sys/time.h>
|
# include <sys/time.h>
|
||||||
|
# include <stdarg.h>
|
||||||
# ifdef DRM_USE_MALLOC
|
# ifdef DRM_USE_MALLOC
|
||||||
# define _DRM_MALLOC malloc
|
# define _DRM_MALLOC malloc
|
||||||
# define _DRM_FREE free
|
# define _DRM_FREE free
|
||||||
|
@ -107,6 +108,28 @@ extern unsigned long _bus_base(void);
|
||||||
#define makedev(x,y) ((dev_t)(((x) << 8) | (y)))
|
#define makedev(x,y) ((dev_t)(((x) << 8) | (y)))
|
||||||
#endif
|
#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 */
|
static void *drmHashTable = NULL; /* Context switch callbacks */
|
||||||
|
|
||||||
typedef struct drmHashEntry {
|
typedef struct drmHashEntry {
|
||||||
|
@ -182,6 +205,8 @@ static int drmOpenDevice(long dev, int minor)
|
||||||
gid_t group = DRM_DEV_GID;
|
gid_t group = DRM_DEV_GID;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
drmMsg("drmOpenDevice: minor is %d\n", minor);
|
||||||
|
|
||||||
#if defined(XFree86Server)
|
#if defined(XFree86Server)
|
||||||
devmode = xf86ConfigDRI.mode ? xf86ConfigDRI.mode : DRM_DEV_MODE;
|
devmode = xf86ConfigDRI.mode ? xf86ConfigDRI.mode : DRM_DEV_MODE;
|
||||||
dirmode = (devmode & S_IRUSR) ? S_IXUSR : 0;
|
dirmode = (devmode & S_IRUSR) ? S_IXUSR : 0;
|
||||||
|
@ -203,6 +228,7 @@ static int drmOpenDevice(long dev, int minor)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
sprintf(buf, DRM_DEV_NAME, DRM_DIR_NAME, minor);
|
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 (stat(buf, &st) || st.st_rdev != dev) {
|
||||||
if (!isroot) return DRM_ERR_NOT_ROOT;
|
if (!isroot) return DRM_ERR_NOT_ROOT;
|
||||||
remove(buf);
|
remove(buf);
|
||||||
|
@ -213,7 +239,11 @@ static int drmOpenDevice(long dev, int minor)
|
||||||
chmod(buf, devmode);
|
chmod(buf, devmode);
|
||||||
#endif
|
#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);
|
remove(buf);
|
||||||
return -errno;
|
return -errno;
|
||||||
}
|
}
|
||||||
|
@ -261,9 +291,13 @@ static int drmOpenByBusid(const char *busid)
|
||||||
int fd;
|
int fd;
|
||||||
const char *buf;
|
const char *buf;
|
||||||
|
|
||||||
|
drmMsg("drmOpenByBusid: busid is %s\n", busid);
|
||||||
for (i = 0; i < DRM_MAX_MINOR; i++) {
|
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);
|
buf = drmGetBusid(fd);
|
||||||
|
drmMsg("drmOpenByBusid: drmGetBusid reports %s\n", buf);
|
||||||
if (buf && !strcmp(buf, busid)) {
|
if (buf && !strcmp(buf, busid)) {
|
||||||
drmFreeBusid(buf);
|
drmFreeBusid(buf);
|
||||||
return fd;
|
return fd;
|
||||||
|
@ -280,6 +314,7 @@ static int drmOpenByName(const char *name)
|
||||||
int i;
|
int i;
|
||||||
int fd;
|
int fd;
|
||||||
drmVersionPtr version;
|
drmVersionPtr version;
|
||||||
|
char * id;
|
||||||
|
|
||||||
if (!drmAvailable()) {
|
if (!drmAvailable()) {
|
||||||
#if !defined(XFree86Server)
|
#if !defined(XFree86Server)
|
||||||
|
@ -294,16 +329,31 @@ static int drmOpenByName(const char *name)
|
||||||
#endif
|
#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++) {
|
for (i = 0; i < DRM_MAX_MINOR; i++) {
|
||||||
if ((fd = drmOpenMinor(i, 1)) >= 0) {
|
if ((fd = drmOpenMinor(i, 1)) >= 0) {
|
||||||
if ((version = drmGetVersion(fd))) {
|
if ((version = drmGetVersion(fd))) {
|
||||||
if (!strcmp(version->name, name)) {
|
if (!strcmp(version->name, name)) {
|
||||||
drmFreeVersion(version);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
|
@ -459,7 +509,9 @@ int drmSetBusid(int fd, const char *busid)
|
||||||
u.unique = (char *)busid;
|
u.unique = (char *)busid;
|
||||||
u.unique_len = strlen(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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -101,9 +101,16 @@
|
||||||
#define DRIVER_IOCTLS
|
#define DRIVER_IOCTLS
|
||||||
#endif
|
#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 drm_device_t *DRM(device);
|
||||||
static int DRM(minor);
|
static int *DRM(minor);
|
||||||
|
static int DRM(numdevs) = 0;
|
||||||
|
|
||||||
static struct file_operations DRM(fops) = {
|
static struct file_operations DRM(fops) = {
|
||||||
#if LINUX_VERSION_CODE >= 0x020400
|
#if LINUX_VERSION_CODE >= 0x020400
|
||||||
|
@ -460,31 +467,87 @@ static int DRM(takedown)( drm_device_t *dev )
|
||||||
return 0;
|
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
|
/* drm_init is called via init_module at module load time, or via
|
||||||
* linux/init/main.c (this is not currently supported).
|
* linux/init/main.c (this is not currently supported).
|
||||||
*/
|
*/
|
||||||
static int __init drm_init( void )
|
static int __init drm_init( void )
|
||||||
{
|
{
|
||||||
drm_device_t *dev = &DRM(device);
|
|
||||||
|
drm_device_t *dev;
|
||||||
|
int i;
|
||||||
#if __HAVE_CTX_BITMAP
|
#if __HAVE_CTX_BITMAP
|
||||||
int retcode;
|
int retcode;
|
||||||
#endif
|
#endif
|
||||||
DRM_DEBUG( "\n" );
|
DRM_DEBUG( "\n" );
|
||||||
|
|
||||||
memset( (void *)dev, 0, sizeof(*dev) );
|
|
||||||
dev->count_lock = SPIN_LOCK_UNLOCKED;
|
|
||||||
sema_init( &dev->struct_sem, 1 );
|
|
||||||
|
|
||||||
#ifdef MODULE
|
#ifdef MODULE
|
||||||
DRM(parse_options)( drm_opts );
|
DRM(parse_options)( drm_opts );
|
||||||
#endif
|
#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();
|
DRIVER_PREINIT();
|
||||||
|
|
||||||
DRM(mem_init)();
|
DRM(mem_init)();
|
||||||
|
|
||||||
if ((DRM(minor) = DRM(stub_register)(DRIVER_NAME, &DRM(fops),dev)) < 0)
|
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;
|
return -EPERM;
|
||||||
dev->device = MKDEV(DRM_MAJOR, DRM(minor) );
|
dev->device = MKDEV(DRM_MAJOR, DRM(minor)[i] );
|
||||||
dev->name = DRIVER_NAME;
|
dev->name = DRIVER_NAME;
|
||||||
|
|
||||||
#if __REALLY_HAVE_AGP
|
#if __REALLY_HAVE_AGP
|
||||||
|
@ -492,7 +555,7 @@ static int __init drm_init( void )
|
||||||
#if __MUST_HAVE_AGP
|
#if __MUST_HAVE_AGP
|
||||||
if ( dev->agp == NULL ) {
|
if ( dev->agp == NULL ) {
|
||||||
DRM_ERROR( "Cannot initialize the agpgart module.\n" );
|
DRM_ERROR( "Cannot initialize the agpgart module.\n" );
|
||||||
DRM(stub_unregister)(DRM(minor));
|
DRM(stub_unregister)(DRM(minor)[i]);
|
||||||
DRM(takedown)( dev );
|
DRM(takedown)( dev );
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
@ -510,21 +573,21 @@ static int __init drm_init( void )
|
||||||
retcode = DRM(ctxbitmap_init)( dev );
|
retcode = DRM(ctxbitmap_init)( dev );
|
||||||
if( retcode ) {
|
if( retcode ) {
|
||||||
DRM_ERROR( "Cannot allocate memory for context bitmap.\n" );
|
DRM_ERROR( "Cannot allocate memory for context bitmap.\n" );
|
||||||
DRM(stub_unregister)(DRM(minor));
|
DRM(stub_unregister)(DRM(minor)[i]);
|
||||||
DRM(takedown)( dev );
|
DRM(takedown)( dev );
|
||||||
return retcode;
|
return retcode;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
DRIVER_POSTINIT();
|
|
||||||
|
|
||||||
DRM_INFO( "Initialized %s %d.%d.%d %s on minor %d\n",
|
DRM_INFO( "Initialized %s %d.%d.%d %s on minor %d\n",
|
||||||
DRIVER_NAME,
|
DRIVER_NAME,
|
||||||
DRIVER_MAJOR,
|
DRIVER_MAJOR,
|
||||||
DRIVER_MINOR,
|
DRIVER_MINOR,
|
||||||
DRIVER_PATCHLEVEL,
|
DRIVER_PATCHLEVEL,
|
||||||
DRIVER_DATE,
|
DRIVER_DATE,
|
||||||
DRM(minor) );
|
DRM(minor)[i] );
|
||||||
|
}
|
||||||
|
|
||||||
|
DRIVER_POSTINIT();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -533,15 +596,21 @@ static int __init drm_init( void )
|
||||||
*/
|
*/
|
||||||
static void __exit drm_cleanup( void )
|
static void __exit drm_cleanup( void )
|
||||||
{
|
{
|
||||||
drm_device_t *dev = &DRM(device);
|
drm_device_t *dev;
|
||||||
|
int i;
|
||||||
|
|
||||||
DRM_DEBUG( "\n" );
|
DRM_DEBUG( "\n" );
|
||||||
|
|
||||||
if ( DRM(stub_unregister)(DRM(minor)) ) {
|
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" );
|
DRM_ERROR( "Cannot unload module\n" );
|
||||||
} else {
|
} else {
|
||||||
|
DRM_DEBUG("minor %d unregistered\n", DRM(minor)[i]);
|
||||||
|
if (i == 0) {
|
||||||
DRM_INFO( "Module unloaded\n" );
|
DRM_INFO( "Module unloaded\n" );
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#if __HAVE_CTX_BITMAP
|
#if __HAVE_CTX_BITMAP
|
||||||
DRM(ctxbitmap_cleanup)( dev );
|
DRM(ctxbitmap_cleanup)( dev );
|
||||||
#endif
|
#endif
|
||||||
|
@ -565,6 +634,10 @@ static void __exit drm_cleanup( void )
|
||||||
dev->agp = NULL;
|
dev->agp = NULL;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
kfree(DRM(minor));
|
||||||
|
kfree(DRM(device));
|
||||||
|
DRM(numdevs) = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
module_init( drm_init );
|
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 )
|
int DRM(open)( struct inode *inode, struct file *filp )
|
||||||
{
|
{
|
||||||
drm_device_t *dev = &DRM(device);
|
drm_device_t *dev = NULL;
|
||||||
int retcode = 0;
|
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 );
|
DRM_DEBUG( "open_count = %d\n", dev->open_count );
|
||||||
|
|
||||||
|
|
|
@ -64,18 +64,18 @@ static void DRM(parse_option)(char *s)
|
||||||
return;
|
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
|
* options passed to the kernel via LILO. The grammar of the format is as
|
||||||
* follows:
|
* follows:
|
||||||
*
|
*
|
||||||
* drm ::= 'drm=' option_list
|
* drm ::= 'drm_opts=' option_list
|
||||||
* option_list ::= option [ ';' option_list ]
|
* option_list ::= option [ ';' option_list ]
|
||||||
* option ::= 'device:' major
|
* option ::= 'device:' major
|
||||||
* | 'debug'
|
* | 'debug'
|
||||||
* | 'noctx'
|
* | 'noctx'
|
||||||
* major ::= INTEGER
|
* 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
|
* device=major,minor specifies the device number used for /dev/drm
|
||||||
* if major == 0 then the misc device is used
|
* if major == 0 then the misc device is used
|
||||||
|
|
|
@ -121,11 +121,13 @@ static int DRM(stub_putminor)(int minor)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int DRM(stub_register)(const char *name, struct file_operations *fops,
|
int DRM(stub_register)(const char *name, struct file_operations *fops,
|
||||||
drm_device_t *dev)
|
drm_device_t *dev)
|
||||||
{
|
{
|
||||||
struct drm_stub_info *i = NULL;
|
struct drm_stub_info *i = NULL;
|
||||||
|
|
||||||
|
DRM_DEBUG("\n");
|
||||||
if (register_chrdev(DRM_MAJOR, "drm", &DRM(stub_fops)))
|
if (register_chrdev(DRM_MAJOR, "drm", &DRM(stub_fops)))
|
||||||
i = (struct drm_stub_info *)inter_module_get("drm");
|
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 */
|
/* Already registered */
|
||||||
DRM(stub_info).info_register = i->info_register;
|
DRM(stub_info).info_register = i->info_register;
|
||||||
DRM(stub_info).info_unregister = i->info_unregister;
|
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_register = DRM(stub_getminor);
|
||||||
DRM(stub_info).info_unregister = DRM(stub_putminor);
|
DRM(stub_info).info_unregister = DRM(stub_putminor);
|
||||||
|
DRM_DEBUG("calling inter_module_register\n");
|
||||||
inter_module_register("drm", THIS_MODULE, &DRM(stub_info));
|
inter_module_register("drm", THIS_MODULE, &DRM(stub_info));
|
||||||
}
|
}
|
||||||
if (DRM(stub_info).info_register)
|
if (DRM(stub_info).info_register)
|
||||||
|
|
|
@ -44,6 +44,15 @@
|
||||||
#define DRIVER_MINOR 0
|
#define DRIVER_MINOR 0
|
||||||
#define DRIVER_PATCHLEVEL 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_auth.h"
|
||||||
#include "drm_bufs.h"
|
#include "drm_bufs.h"
|
||||||
|
|
120
linux/drm_drv.h
120
linux/drm_drv.h
|
@ -101,9 +101,16 @@
|
||||||
#define DRIVER_IOCTLS
|
#define DRIVER_IOCTLS
|
||||||
#endif
|
#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 drm_device_t *DRM(device);
|
||||||
static int DRM(minor);
|
static int *DRM(minor);
|
||||||
|
static int DRM(numdevs) = 0;
|
||||||
|
|
||||||
static struct file_operations DRM(fops) = {
|
static struct file_operations DRM(fops) = {
|
||||||
#if LINUX_VERSION_CODE >= 0x020400
|
#if LINUX_VERSION_CODE >= 0x020400
|
||||||
|
@ -460,31 +467,87 @@ static int DRM(takedown)( drm_device_t *dev )
|
||||||
return 0;
|
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
|
/* drm_init is called via init_module at module load time, or via
|
||||||
* linux/init/main.c (this is not currently supported).
|
* linux/init/main.c (this is not currently supported).
|
||||||
*/
|
*/
|
||||||
static int __init drm_init( void )
|
static int __init drm_init( void )
|
||||||
{
|
{
|
||||||
drm_device_t *dev = &DRM(device);
|
|
||||||
|
drm_device_t *dev;
|
||||||
|
int i;
|
||||||
#if __HAVE_CTX_BITMAP
|
#if __HAVE_CTX_BITMAP
|
||||||
int retcode;
|
int retcode;
|
||||||
#endif
|
#endif
|
||||||
DRM_DEBUG( "\n" );
|
DRM_DEBUG( "\n" );
|
||||||
|
|
||||||
memset( (void *)dev, 0, sizeof(*dev) );
|
|
||||||
dev->count_lock = SPIN_LOCK_UNLOCKED;
|
|
||||||
sema_init( &dev->struct_sem, 1 );
|
|
||||||
|
|
||||||
#ifdef MODULE
|
#ifdef MODULE
|
||||||
DRM(parse_options)( drm_opts );
|
DRM(parse_options)( drm_opts );
|
||||||
#endif
|
#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();
|
DRIVER_PREINIT();
|
||||||
|
|
||||||
DRM(mem_init)();
|
DRM(mem_init)();
|
||||||
|
|
||||||
if ((DRM(minor) = DRM(stub_register)(DRIVER_NAME, &DRM(fops),dev)) < 0)
|
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;
|
return -EPERM;
|
||||||
dev->device = MKDEV(DRM_MAJOR, DRM(minor) );
|
dev->device = MKDEV(DRM_MAJOR, DRM(minor)[i] );
|
||||||
dev->name = DRIVER_NAME;
|
dev->name = DRIVER_NAME;
|
||||||
|
|
||||||
#if __REALLY_HAVE_AGP
|
#if __REALLY_HAVE_AGP
|
||||||
|
@ -492,7 +555,7 @@ static int __init drm_init( void )
|
||||||
#if __MUST_HAVE_AGP
|
#if __MUST_HAVE_AGP
|
||||||
if ( dev->agp == NULL ) {
|
if ( dev->agp == NULL ) {
|
||||||
DRM_ERROR( "Cannot initialize the agpgart module.\n" );
|
DRM_ERROR( "Cannot initialize the agpgart module.\n" );
|
||||||
DRM(stub_unregister)(DRM(minor));
|
DRM(stub_unregister)(DRM(minor)[i]);
|
||||||
DRM(takedown)( dev );
|
DRM(takedown)( dev );
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
@ -510,21 +573,21 @@ static int __init drm_init( void )
|
||||||
retcode = DRM(ctxbitmap_init)( dev );
|
retcode = DRM(ctxbitmap_init)( dev );
|
||||||
if( retcode ) {
|
if( retcode ) {
|
||||||
DRM_ERROR( "Cannot allocate memory for context bitmap.\n" );
|
DRM_ERROR( "Cannot allocate memory for context bitmap.\n" );
|
||||||
DRM(stub_unregister)(DRM(minor));
|
DRM(stub_unregister)(DRM(minor)[i]);
|
||||||
DRM(takedown)( dev );
|
DRM(takedown)( dev );
|
||||||
return retcode;
|
return retcode;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
DRIVER_POSTINIT();
|
|
||||||
|
|
||||||
DRM_INFO( "Initialized %s %d.%d.%d %s on minor %d\n",
|
DRM_INFO( "Initialized %s %d.%d.%d %s on minor %d\n",
|
||||||
DRIVER_NAME,
|
DRIVER_NAME,
|
||||||
DRIVER_MAJOR,
|
DRIVER_MAJOR,
|
||||||
DRIVER_MINOR,
|
DRIVER_MINOR,
|
||||||
DRIVER_PATCHLEVEL,
|
DRIVER_PATCHLEVEL,
|
||||||
DRIVER_DATE,
|
DRIVER_DATE,
|
||||||
DRM(minor) );
|
DRM(minor)[i] );
|
||||||
|
}
|
||||||
|
|
||||||
|
DRIVER_POSTINIT();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -533,15 +596,21 @@ static int __init drm_init( void )
|
||||||
*/
|
*/
|
||||||
static void __exit drm_cleanup( void )
|
static void __exit drm_cleanup( void )
|
||||||
{
|
{
|
||||||
drm_device_t *dev = &DRM(device);
|
drm_device_t *dev;
|
||||||
|
int i;
|
||||||
|
|
||||||
DRM_DEBUG( "\n" );
|
DRM_DEBUG( "\n" );
|
||||||
|
|
||||||
if ( DRM(stub_unregister)(DRM(minor)) ) {
|
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" );
|
DRM_ERROR( "Cannot unload module\n" );
|
||||||
} else {
|
} else {
|
||||||
|
DRM_DEBUG("minor %d unregistered\n", DRM(minor)[i]);
|
||||||
|
if (i == 0) {
|
||||||
DRM_INFO( "Module unloaded\n" );
|
DRM_INFO( "Module unloaded\n" );
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#if __HAVE_CTX_BITMAP
|
#if __HAVE_CTX_BITMAP
|
||||||
DRM(ctxbitmap_cleanup)( dev );
|
DRM(ctxbitmap_cleanup)( dev );
|
||||||
#endif
|
#endif
|
||||||
|
@ -565,6 +634,10 @@ static void __exit drm_cleanup( void )
|
||||||
dev->agp = NULL;
|
dev->agp = NULL;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
kfree(DRM(minor));
|
||||||
|
kfree(DRM(device));
|
||||||
|
DRM(numdevs) = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
module_init( drm_init );
|
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 )
|
int DRM(open)( struct inode *inode, struct file *filp )
|
||||||
{
|
{
|
||||||
drm_device_t *dev = &DRM(device);
|
drm_device_t *dev = NULL;
|
||||||
int retcode = 0;
|
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 );
|
DRM_DEBUG( "open_count = %d\n", dev->open_count );
|
||||||
|
|
||||||
|
|
|
@ -64,18 +64,18 @@ static void DRM(parse_option)(char *s)
|
||||||
return;
|
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
|
* options passed to the kernel via LILO. The grammar of the format is as
|
||||||
* follows:
|
* follows:
|
||||||
*
|
*
|
||||||
* drm ::= 'drm=' option_list
|
* drm ::= 'drm_opts=' option_list
|
||||||
* option_list ::= option [ ';' option_list ]
|
* option_list ::= option [ ';' option_list ]
|
||||||
* option ::= 'device:' major
|
* option ::= 'device:' major
|
||||||
* | 'debug'
|
* | 'debug'
|
||||||
* | 'noctx'
|
* | 'noctx'
|
||||||
* major ::= INTEGER
|
* 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
|
* device=major,minor specifies the device number used for /dev/drm
|
||||||
* if major == 0 then the misc device is used
|
* if major == 0 then the misc device is used
|
||||||
|
|
|
@ -121,11 +121,13 @@ static int DRM(stub_putminor)(int minor)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int DRM(stub_register)(const char *name, struct file_operations *fops,
|
int DRM(stub_register)(const char *name, struct file_operations *fops,
|
||||||
drm_device_t *dev)
|
drm_device_t *dev)
|
||||||
{
|
{
|
||||||
struct drm_stub_info *i = NULL;
|
struct drm_stub_info *i = NULL;
|
||||||
|
|
||||||
|
DRM_DEBUG("\n");
|
||||||
if (register_chrdev(DRM_MAJOR, "drm", &DRM(stub_fops)))
|
if (register_chrdev(DRM_MAJOR, "drm", &DRM(stub_fops)))
|
||||||
i = (struct drm_stub_info *)inter_module_get("drm");
|
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 */
|
/* Already registered */
|
||||||
DRM(stub_info).info_register = i->info_register;
|
DRM(stub_info).info_register = i->info_register;
|
||||||
DRM(stub_info).info_unregister = i->info_unregister;
|
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_register = DRM(stub_getminor);
|
||||||
DRM(stub_info).info_unregister = DRM(stub_putminor);
|
DRM(stub_info).info_unregister = DRM(stub_putminor);
|
||||||
|
DRM_DEBUG("calling inter_module_register\n");
|
||||||
inter_module_register("drm", THIS_MODULE, &DRM(stub_info));
|
inter_module_register("drm", THIS_MODULE, &DRM(stub_info));
|
||||||
}
|
}
|
||||||
if (DRM(stub_info).info_register)
|
if (DRM(stub_info).info_register)
|
||||||
|
|
|
@ -44,6 +44,15 @@
|
||||||
#define DRIVER_MINOR 0
|
#define DRIVER_MINOR 0
|
||||||
#define DRIVER_PATCHLEVEL 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_auth.h"
|
||||||
#include "drm_bufs.h"
|
#include "drm_bufs.h"
|
||||||
|
|
Loading…
Reference in New Issue