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