obiecany 3dfx driver

Krzysztof G. Baranowski kgb w manjak.knm.org.pl
Pią, 13 Lis 1998, 09:32:53 CET


Obiecany patch zrobiony na podstawie 2.1.127 w attachu.

Kris
-- 
Krzysztof G. Baranowski - Prezes Klubu Nieszkodliwych Manjaków
"Smith & Wesson - The original point and click interface..."
http://www.knm.org.pl/              <prezes w manjak.knm.org.pl>
-------------- następna część ---------
diff -urN linux-2.1/Documentation/Configure.help linux/Documentation/Configure.help
--- linux-2.1/Documentation/Configure.help	Mon Nov  9 09:11:35 1998
+++ linux/Documentation/Configure.help	Thu Nov 12 16:55:28 1998
@@ -8204,6 +8204,20 @@
   to it. For more information on how to use the driver please read
   Documentation/joystick.txt
 
+3Dfx boards support
+CONFIG_3DFX
+  Say Y here if you have 3Dfx card with Voodoo or Voodoo2 chipset and
+  want Glide applications to run without root privledges.  No changes
+  to existing applications are required. It is strongly suggested that
+  you use this driver to access the 3Dfx device.
+
+  To use this, you need to create a character special file under /dev
+  called "3dfx" with major number 107 and minor number 0 using mknod
+  ("man mknod"). You will also need Linux Glide available at
+  http://glide.xxedgexx.com/3DfxRPMS.html
+
+  If you don't know what all this is about, say N.
+
 Atomwide Serial Support
 CONFIG_ATOMWIDE_SERIAL
   If you have an Atomwide Serial card for an Acorn system, say Y to
diff -urN linux-2.1/drivers/char/3dfx.c linux/drivers/char/3dfx.c
--- linux-2.1/drivers/char/3dfx.c	Thu Jan  1 01:00:00 1970
+++ linux/drivers/char/3dfx.c	Thu Nov 12 16:41:21 1998
@@ -0,0 +1,581 @@
+/*
+   3dfx.c: device driver for 3Dfx boards.
+
+   Copyright 1998 by Daryll Strauss <daryll w harlot.rb.ca.us>.
+
+   2.1.x rewrite (C) 1998 by Krzysztof G. Baranowski <kgb w knm.org.pl>.
+   Please report any problems regarding this driver and 2.1.x kernels
+   to the address above. (with Cc: to Daryll of course, as he is in
+   charge here ;-)
+
+   This software may be used and distributed according to the terms
+   of the GNU Public License, incorporated herein by reference.
+   Contact the author for use under other terms.
+
+   To set MTRRs use:
+	insmod 3dfx.o mtrrs=1
+  
+   $Id: 3dfx.c,v 1.8 1998/11/12 15:41:07 kgb Exp $
+*/
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/fs.h>
+#include <asm/uaccess.h>
+#include <asm/mtrr.h>
+#include <asm/init.h>
+#include <asm/io.h>
+
+#define PCI_VENDOR_ID_LINUX 		0x0
+#define PCI_DEVICE_ID_LINUX 		0x2
+#define PCI_COMMAND_LINUX 		0x4
+#define PCI_REVISION_ID_LINUX 		0x8
+#define PCI_BASE_ADDRESS_0_LINUX 	0x10
+#define SST1_PCI_SPECIAL1_LINUX 	0x40
+#define SST1_PCI_SPECIAL2_LINUX 	0x44
+#define SST1_PCI_SPECIAL3_LINUX 	0x48
+#define SST1_PCI_SPECIAL4_LINUX 	0x54
+
+#define VGA_INPUT_STATUS_1C 	0x3DA
+#define VGA_MISC_OUTPUT_READ 	0x3cc
+#define VGA_MISC_OUTPUT_WRITE 	0x3c2
+#define SC_INDEX 		0x3c4
+#define SC_DATA  		0x3c5
+
+#ifdef 3DFX_DEBUG
+#define DEBUGMSG printk
+#else
+#define DEBUGMSG(fmt, args...)
+#endif
+
+#ifdef CONFIG_3DFX_MTRR 
+#define USE_MTRRS 1
+#else
+#define USE_MTRRS 0
+#endif
+
+typedef struct pioData_t {
+	short port;
+	short size;
+	int device;
+	void *value;
+} pioData;
+
+typedef struct cardInfo_t {
+	int vendor;
+	int type;
+	int addr;
+	int mtrr_reg0;
+	int mtrr_reg1;
+	struct pci_dev *dev_3dfx;
+	struct file *curFile;
+} cardInfo;
+
+#define MAXCARDS 16
+
+cardInfo cards[MAXCARDS];
+static int major_3dfx = 107;
+static int numCards = 0;
+#ifdef CONFIG_MTRR
+static int mtrrs = USE_MTRRS;
+#endif
+
+/*
+ *	Module documentation.
+ */
+MODULE_AUTHOR("Daryll Strauss <daryll w harlot.rb.ca.us>");
+MODULE_DESCRIPTION("Device driver for 3Dfx boards.");
+MODULE_PARM(major_3dfx, "i");
+MODULE_PARM(numCards, "i");
+MODULE_PARM(mtrrs, "i");
+
+static const char *strvendor(unsigned int vendor)
+{
+	switch (vendor) {
+		case PCI_VENDOR_ID_3DFX:
+			return "3Dfx Interactive, Inc.";
+		case PCI_VENDOR_ID_ALLIANCE:
+			return "Alliance Semiconductor Corporation";
+	}
+	return NULL;
+}
+
+static const char *strdevice(unsigned int device)
+{
+	switch (device) {
+		case PCI_DEVICE_ID_3DFX_VOODOO:
+			return "Voodoo";
+		case PCI_DEVICE_ID_3DFX_VOODOO2:
+			return "Voodoo2";
+		case PCI_DEVICE_ID_ALLIANCE_AT3D:
+			return "AT3D";
+	}
+	return NULL;
+}
+
+static void findCardType(int vendor, int device)
+{
+	int i;
+	struct pci_dev *pdev = NULL;
+
+	for (i = 0; numCards < MAXCARDS; i++) {
+		pdev = pci_find_device(vendor, device, pdev);
+		if (pdev == NULL)
+			return;
+		pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &cards[numCards].addr);
+		cards[numCards].addr &= ~0xF;
+		cards[numCards].vendor = vendor;
+		cards[numCards].type = device;
+		cards[numCards].curFile = 0;
+		cards[numCards].dev_3dfx = pdev;
+
+		printk("Found %s %s located at 0x%x bus %d dev %d.\n", 
+			strvendor(vendor), strdevice(device), 
+			cards[numCards].addr, 
+			cards[numCards].dev_3dfx->bus->number, 
+			cards[numCards].dev_3dfx->devfn);
+		numCards++;
+	}
+}
+
+static int findCards(void)
+{
+	if (!pci_present())
+		return -ENODEV;
+	numCards = 0;
+	findCardType(PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO);
+	findCardType(PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO2);
+	findCardType(PCI_VENDOR_ID_ALLIANCE, PCI_DEVICE_ID_ALLIANCE_AT3D);
+	return numCards;
+}
+
+static int open_3dfx(struct inode *inode, struct file *file)
+{
+	MOD_INC_USE_COUNT;
+	return 0;
+}
+
+static int release_3dfx(struct inode *inode, struct file *file)
+{
+	int i;
+
+	for (i = 0; i < numCards; i++) {
+		if (cards[i].curFile == file)
+			cards[i].curFile = NULL;
+	}
+
+	MOD_DEC_USE_COUNT;
+	return 0;
+}
+
+static int mmap_3dfx(struct file *file, struct vm_area_struct *vma)
+{
+	size_t len;
+	int i;
+
+	for (i = 0; i < numCards; i++) {
+		if (cards[i].addr == vma->vm_offset)
+			break;
+	}
+	if (i == numCards) {
+		DEBUGMSG("Couldn't match address %lx to a card.\n", vma->vm_offset);
+		return -EPERM;
+	}
+	if (cards[i].curFile) {
+		DEBUGMSG("3Dfx card already in use.\n");
+		return -EBUSY;
+	}
+	if ((vma->vm_offset) & ~PAGE_MASK) {
+		DEBUGMSG("Map request not page aligned.\n");
+		return -ENXIO;
+	}
+	len = vma->vm_end - vma->vm_start;
+	if ((len < 0) || (len > 0x1000000)) {
+		DEBUGMSG("Invalid mapping size requested.\n");
+		return -EINVAL;
+	}
+#if defined(__i386__)
+	pgprot_val(vma->vm_page_prot) |= _PAGE_PCD;
+#endif
+	if (remap_page_range(vma->vm_start, vma->vm_offset, len, vma->vm_page_prot)) {
+		DEBUGMSG("Page remap failed.\n");
+		return -EAGAIN;
+	}
+	vma->vm_file = file;
+	file->f_count++;
+	cards[i].curFile = file;
+	return 0;
+}
+
+static int doQueryBoards(void)
+{
+	return numCards;
+}
+
+static int doQueryFetch(pioData * desc)
+{
+	char retchar;
+	short retword;
+	int retlong;
+
+	if (desc->device < 0 || desc->device >= numCards)
+		return -EINVAL;
+	switch (desc->port) {
+		case PCI_VENDOR_ID_LINUX:
+			if (desc->size != 2)
+				return -EINVAL;
+			if (copy_to_user(desc->value, &cards[desc->device].vendor, desc->size))
+				return -EFAULT;
+			return 0;
+		case PCI_DEVICE_ID_LINUX:
+			if (desc->size != 2)
+				return -EINVAL;
+			if (copy_to_user(desc->value, &cards[desc->device].type, desc->size))
+				return -EFAULT;
+			return 0;
+		case PCI_BASE_ADDRESS_0_LINUX:
+			if (desc->size != 4)
+				return -EINVAL;
+			if (copy_to_user(desc->value, &cards[desc->device].addr, desc->size))
+				return -EFAULT;
+			return 0;
+		case SST1_PCI_SPECIAL1_LINUX:
+			if (desc->size != 4)
+				return -EINVAL;
+			break;
+		case PCI_REVISION_ID:
+			if (desc->size != 1)
+				return -EINVAL;
+			break;
+		case SST1_PCI_SPECIAL4_LINUX:
+			if (desc->size != 4)
+				return -EINVAL;
+			break;
+		default:
+			return -EINVAL;
+	}
+	switch (desc->size) {
+		case 1:
+			pci_read_config_byte(cards[desc->device].dev_3dfx, 
+					     desc->port, &retchar);
+			if (copy_to_user(desc->value, &retchar, 1))
+				return -EFAULT;
+			break;
+		case 2:
+			pci_read_config_word(cards[desc->device].dev_3dfx,
+				  	     desc->port, &retword);
+			if (copy_to_user(desc->value, &retword, 2))
+				return -EFAULT;
+			break;
+		case 4:
+			pci_read_config_dword(cards[desc->device].dev_3dfx,
+				  	      desc->port, &retlong);
+			if (copy_to_user(desc->value, &retlong, 4))
+				return -EFAULT;
+			break;
+		default:
+			return -EINVAL;
+	}
+	return 0;
+}
+
+static int doQueryUpdate(pioData * desc)
+{
+	int retval;
+	int preval;
+	int mask;
+	char retchar;
+	short retword;
+	int retlong;
+
+	if (desc->device < 0 || desc->device >= numCards)
+		return -EINVAL;
+	switch (desc->port) {
+		case PCI_COMMAND_LINUX:
+			if (desc->size != 2)
+				return -EINVAL;
+			break;
+		case SST1_PCI_SPECIAL1_LINUX:
+			if (desc->size != 4)
+				return -EINVAL;
+			break;
+		case SST1_PCI_SPECIAL2_LINUX:
+			if (desc->size != 4)
+				return -EINVAL;
+			break;
+		case SST1_PCI_SPECIAL3_LINUX:
+			if (desc->size != 4)
+				return -EINVAL;
+			break;
+		case SST1_PCI_SPECIAL4_LINUX:
+			if (desc->size != 4)
+				return -EINVAL;
+			break;
+		default:
+			return -EINVAL;
+	}
+	pci_read_config_dword(cards[desc->device].dev_3dfx,
+			      desc->port & ~0x3, &retval);
+	switch (desc->size) {
+		case 1:
+			if (copy_from_user(&retchar, desc->value, 1))
+				return -EFAULT;
+			preval = retchar << (8 * (desc->port & 0x3));
+			mask = 0xFF << (8 * (desc->port & 0x3));
+			break;
+		case 2:
+			if (copy_from_user(&retword, desc->value, 2))
+				return -EFAULT;
+			preval = retword << (8 * (desc->port & 0x3));
+			mask = 0xFFFF << (8 * (desc->port & 0x3));
+			break;
+		case 4:
+			if (copy_from_user(&retlong, desc->value, 4))
+				return -EFAULT;
+			preval = retlong;
+			mask = ~0;
+			break;
+		default:
+			return -EINVAL;
+	}
+	retval = (retval & ~mask) | preval;
+	pci_write_config_dword(cards[desc->device].dev_3dfx,desc->port, retval);
+	return 0;
+}
+
+static int doQuery(unsigned int cmd, unsigned long arg)
+{
+	pioData desc;
+
+	if (_IOC_NR(cmd) == 2)
+		return doQueryBoards();
+	if (copy_from_user(&desc, (void *) arg, sizeof(pioData)))
+		return -EFAULT;
+	if (_IOC_NR(cmd) == 3)
+		return doQueryFetch(&desc);
+	if (_IOC_NR(cmd) == 4)
+		return doQueryUpdate(&desc);
+	return -EINVAL;
+}
+
+static int doPIORead(pioData * desc)
+{
+	char retchar;
+	short retword;
+	int retlong;
+
+	switch (desc->port) {
+		case VGA_INPUT_STATUS_1C:
+			break;
+		case SC_INDEX:
+			break;
+		case SC_DATA:
+			break;
+		case VGA_MISC_OUTPUT_READ:
+			break;
+		default:
+			return -EPERM;
+	}
+
+	/* ???? */
+	if (desc->size != 1)
+		return -EINVAL;
+
+	switch (desc->size) {
+		case 1:
+			retchar = inb(desc->port);
+			if (copy_to_user(desc->value, &retchar, sizeof(char)))
+				return -EFAULT;
+			break;
+		case 2:
+			retword = inw(desc->port);
+			if (copy_to_user(desc->value, &retword, sizeof(short)))
+				return -EFAULT;
+			break;
+		case 4:
+			retlong = inl(desc->port);
+			if (copy_to_user(desc->value, &retlong, sizeof(int)))
+				return -EFAULT;
+			break;
+		default:
+			return -EINVAL;
+	}
+	return 0;
+}
+
+static int doPIOWrite(pioData * desc)
+{
+	char retchar;
+	short retword;
+	int retlong;
+
+	switch (desc->port) {
+		case SC_INDEX:
+			break;
+		case SC_DATA:
+			break;
+		case VGA_MISC_OUTPUT_WRITE:
+			break;
+		default:
+			return -EPERM;
+	}
+
+	/* ???? */
+	if (desc->size != 1)
+		return -EINVAL;
+
+	switch (desc->size) {
+		case 1:
+			if (copy_from_user(&retchar, desc->value, sizeof(char)))
+				return -EFAULT;
+			outb(retchar, desc->port);
+			break;
+		case 2:
+			if (copy_from_user(&retword, desc->value, sizeof(short)))
+				return -EFAULT;
+			outw(retword, desc->port);
+			break;
+		case 4:
+			if (copy_from_user(&retlong, desc->value, sizeof(int)))
+				return -EFAULT;
+			outl(retlong, desc->port);
+			break;
+		default:
+			return -EINVAL;
+	}
+	return 0;
+}
+
+static int doPIO(unsigned int cmd, unsigned long arg)
+{
+	pioData desc;
+
+	if (copy_from_user(&desc, (void *) arg, sizeof(pioData)))
+		return -EFAULT;
+	if (_IOC_DIR(cmd) == _IOC_READ)
+		return doPIORead(&desc);
+	if (_IOC_DIR(cmd) == _IOC_WRITE)
+		return doPIOWrite(&desc);
+	return -EINVAL;
+}
+
+static int ioctl_3dfx(struct inode *inode, struct file *file,
+		      unsigned int cmd, unsigned long arg)
+{
+	switch (_IOC_TYPE(cmd)) {
+		case '3':
+			return doQuery(cmd, arg);
+		case 0:
+			return doPIO(cmd, arg);
+		default:
+			DEBUGMSG("Unknown 3Dfx request made.\n");
+		return -EINVAL;
+	}
+}
+
+#ifdef CONFIG_MTRR
+static int setmtrr_3dfx(void)
+{
+	int i, retval = 0;
+	unsigned char dlc;
+	struct pci_dev *pdev = NULL;
+
+	/* First do a bios fixup if this system has a 82441FX chipset */
+	pdev = pci_find_device(PCI_VENDOR_ID_INTEL, 
+			       PCI_DEVICE_ID_INTEL_82371SB_0, pdev);
+	if (pdev != NULL) {
+		pci_read_config_byte(pdev, 0x82, &dlc);
+		if (!(dlc & 1 << 1)) {
+			dlc |= 1 << 1;
+			pci_write_config_byte(pdev, 0x82, dlc);
+			printk("PIIX3: Enabling Passive Release.\n");
+		}
+	}
+	/* Set up the mtrr's */
+	for (i = 0; i < numCards; i++) {
+		if (cards[i].vendor != PCI_VENDOR_ID_3DFX)
+			continue;
+		/* Frame buffer to write combining */
+		retval = mtrr_add(cards[i].addr, 0x400000, 1, 1);
+		/* Save the value for del_mtrr3dfx() */
+		cards[i].mtrr_reg0 = retval;
+
+		if (retval < 0) {
+			printk("Could not set MTRR for 3Dfx board.\n");
+			/* Can still run */
+			return 0;
+		} else {
+			/* Control registers uncacheable */
+			retval = mtrr_add(cards[i].addr, 0x1000, 0, 1);
+			cards[i].mtrr_reg1 = retval;
+		}
+	}
+	return retval;
+}
+
+#ifdef MODULE
+static void delmtrr_3dfx(void)
+{
+	int i;
+
+	for (i = 0;  i < numCards; i++) {
+		if (cards[i].mtrr_reg0 >= 0)
+			mtrr_del(cards[i].mtrr_reg0, 0, 0);
+		if (cards[i].mtrr_reg1 >= 0)
+			mtrr_del(cards[i].mtrr_reg1, 0, 0);
+	}
+}
+#endif /* MODULE */
+#endif /* CONFIG_MTRR */
+
+static struct file_operations fops_3dfx =
+{
+	NULL,			/* llseek */
+	NULL,			/* read */
+	NULL,			/* write */
+	NULL,			/* readdir */
+	NULL,			/* pool */
+	ioctl_3dfx,
+	mmap_3dfx,
+	open_3dfx,
+	NULL,			/* flush */
+	release_3dfx,
+};
+
+
+int __init init_3dfx(void)
+{
+	int error;
+
+	if (!findCards())
+		return -ENODEV;
+	error = register_chrdev(major_3dfx, "3dfx", &fops_3dfx);
+	if (error) {
+		printk("Unable to get major %d for 3Dfx device.\n", major_3dfx);
+		return error;
+	}
+#ifdef CONFIG_MTRR
+	if (mtrrs)
+		setmtrr_3dfx();
+#endif
+	return 0;
+}
+
+#ifdef MODULE
+int init_module(void)
+{
+	return init_3dfx();
+}
+
+void cleanup_module(void)
+{
+#ifdef CONFIG_MTRR
+	if (mtrrs)
+		delmtrr_3dfx();
+#endif
+	unregister_chrdev(major_3dfx, "3dfx");
+}
+#endif /* MODULE */
diff -urN linux-2.1/drivers/char/Config.in linux/drivers/char/Config.in
--- linux-2.1/drivers/char/Config.in	Sat Oct 24 11:44:44 1998
+++ linux/drivers/char/Config.in	Thu Nov 12 16:12:07 1998
@@ -128,6 +128,10 @@
 if [ "$CONFIG_JOYSTICK" != "n" ]; then
   source drivers/char/joystick/Config.in
 fi
+tristate '3Dfx boards support' CONFIG_3DFX
+if [ "$CONFIG_3DFX" != "n" -a "$CONFIG_MTRR" = "y" ]; then
+	bool '     Set MTRRs for 3Dfx boards by default when available' CONFIG_3DFX_MTRR
+fi
 mainmenu_option next_comment
 comment 'Ftape, the floppy tape device driver'
 tristate 'Ftape (QIC-80/Travan) support' CONFIG_FTAPE
diff -urN linux-2.1/drivers/char/Makefile linux/drivers/char/Makefile
--- linux-2.1/drivers/char/Makefile	Mon Nov  9 09:11:38 1998
+++ linux/drivers/char/Makefile	Thu Nov 12 16:03:17 1998
@@ -264,6 +264,14 @@
   endif
 endif
 
+ifeq ($(CONFIG_3DFX),y)
+LX_OBJS += 3dfx.o
+else
+  ifeq ($(CONFIG_3DFX),m)
+    MX_OBJS += 3dfx.o
+  endif
+endif
+
 ifeq ($(CONFIG_VIDEO_DEV),y)
 LX_OBJS += videodev.o
 else
diff -urN linux-2.1/drivers/char/tty_io.c linux/drivers/char/tty_io.c
--- linux-2.1/drivers/char/tty_io.c	Mon Nov  9 09:11:39 1998
+++ linux/drivers/char/tty_io.c	Thu Nov 12 16:06:47 1998
@@ -2162,5 +2162,8 @@
 #ifdef CONFIG_VT
 	vcs_init();
 #endif
+#ifdef CONFIG_3DFX
+	init_3dfx();
+#endif
 	return 0;
 }
diff -urN linux-2.1/include/linux/tty.h linux/include/linux/tty.h
--- linux-2.1/include/linux/tty.h	Mon Nov  9 09:14:15 1998
+++ linux/include/linux/tty.h	Thu Nov 12 16:10:03 1998
@@ -351,6 +351,7 @@
 extern int riscom8_init(void);
 extern int specialix_init(void);
 extern int espserial_init(void);
+extern int init_3dfx(void);
 
 extern int tty_paranoia_check(struct tty_struct *tty, kdev_t device,
 			      const char *routine);


Więcej informacji o liście dyskusyjnej pld-devel-pl