--- main/drivers/mga_vid.c.orig 2005-09-01 09:30:16.000000000 +0200 +++ main/drivers/mga_vid.c 2005-09-01 09:55:36.000000000 +0200 @@ -29,9 +29,22 @@ * license. See http://www.gnu.org/copyleft/gpl.html for details. */ +/* + * CHANGES + * Updated for linux-2.6.12 to support devfs, pci name changes and paging + * Modified that major number from 178 to 83 taken from linux/Documentation/devices.txt + * + * BUGS + * rmmod mga_vid does not remove the device from devfs so next modprobe reports and error. + * Don't know kernel version when the changes to pci where made, so assumed 2.6.0 + * Don't know kernel version when remap_page_range was renamed to remap_pfn_range, so assumed 2.6.0 + * + */ //It's entirely possible this major conflicts with something else -//use the 'major' parameter to override the default major number (178) -/* mknod /dev/mga_vid c 178 0 */ +//use the 'major' parameter to override the default major number (83) +/* mknod /dev/mga_vid c 83 0 */ +/* mknod /dev/mga_vid0 c 83 0 */ +/* mknod /dev/mga_vid1 c 83 1 */ #include #include @@ -70,7 +83,7 @@ #define TRUE 1 #define FALSE 0 -#define DEFAULT_MGA_VID_MAJOR 178 +#define DEFAULT_MGA_VID_MAJOR 83 #ifndef PCI_DEVICE_ID_MATROX_G200_PCI #define PCI_DEVICE_ID_MATROX_G200_PCI 0x0520 @@ -147,7 +160,7 @@ } #endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) || LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,5) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) static long simple_strtol(const char *cp,char **endp,unsigned int base) { if(*cp=='-') @@ -348,18 +361,28 @@ #define ICLEAR 0x1e18 #define STATUS 0x1e14 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,22) +static inline char *pci_name(struct pci_dev *pdev) +{ + return pdev->name; +} +#endif // global devfs handle for /dev/mga_vid -#ifdef CONFIG_DEVFS_FS +#if defined(CONFIG_DEVFS_FS) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) static devfs_handle_t dev_handle = NULL; +#elif defined(CONFIG_DEVFS_FS) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) +static int uses_devfs = 0; #endif // card local config typedef struct mga_card_s { // local devfs handle for /dev/mga_vidX -#ifdef CONFIG_DEVFS_FS - devfs_handle_t dev_handle; +#if defined(CONFIG_DEVFS_FS) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) + devfs_handle_t dev_handle; +#elif defined(CONFIG_DEVFS_FS) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) + int uses_devfs; #endif uint8_t *param_buff; // buffer for read() @@ -1322,6 +1345,7 @@ struct pci_dev *dev = NULL; char *mga_dev_name; mga_card_t * card; + int mga_dev_ok = 0; while((dev = pci_find_device(PCI_VENDOR_ID_MATROX, PCI_ANY_ID, dev))) { @@ -1344,30 +1368,59 @@ mga_cards[mga_cards_num - 1] = card; + mga_dev_ok = 0; switch(dev->device) { case PCI_DEVICE_ID_MATROX_G550: mga_dev_name = "MGA G550"; - printk(KERN_INFO "mga_vid: Found %s at %s [%s]\n", mga_dev_name, dev->slot_name, dev->name); - cards_init(card, dev, mga_cards_num - 1, 1); + mga_dev_ok = 1; break; case PCI_DEVICE_ID_MATROX_G400: mga_dev_name = "MGA G400/G450"; - printk(KERN_INFO "mga_vid: Found %s at %s [%s]\n", mga_dev_name, dev->slot_name, dev->name); - cards_init(card, dev, mga_cards_num - 1, 1); + mga_dev_ok = 1; break; case PCI_DEVICE_ID_MATROX_G200_AGP: mga_dev_name = "MGA G200 AGP"; - printk(KERN_INFO "mga_vid: Found %s at %s [%s]\n", mga_dev_name, dev->slot_name, dev->name); - cards_init(card, dev, mga_cards_num - 1, 0); + mga_dev_ok = 1; break; case PCI_DEVICE_ID_MATROX_G200_PCI: mga_dev_name = "MGA G200"; - printk(KERN_INFO "mga_vid: Found %s at %s [%s]\n", mga_dev_name, dev->slot_name, dev->name); - cards_init(card, dev, mga_cards_num - 1, 0); + mga_dev_ok = 1; break; default: mga_cards_num--; - printk(KERN_INFO "mga_vid: ignoring matrox device (%d) at %s [%s]\n", dev->device, dev->slot_name, dev->name); + break; + } + + if (mga_dev_ok) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + printk(KERN_INFO "mga_vid: Found %s at %s [%s]\n", mga_dev_name, pci_name(dev), dev->pretty_name); +#else + printk(KERN_INFO "mga_vid: Found %s at %s [%s]\n", mga_dev_name, dev->slot_name, pci_name(dev)); +#endif + } else { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + printk(KERN_INFO "mga_vid: ignoring matrox device (%d) at %s [%s]\n", + dev->device, pci_name(dev), dev->pretty_name); +#else + printk(KERN_INFO "mga_vid: ignoring matrox device (%d) at %s [%s]\n", + dev->device, dev->slot_name, pci_name(dev)); +#endif + } + + switch(dev->device) { + case PCI_DEVICE_ID_MATROX_G550: + cards_init(card, dev, mga_cards_num - 1, 1); + break; + case PCI_DEVICE_ID_MATROX_G400: + cards_init(card, dev, mga_cards_num - 1, 1); + break; + case PCI_DEVICE_ID_MATROX_G200_AGP: + cards_init(card, dev, mga_cards_num - 1, 0); + break; + case PCI_DEVICE_ID_MATROX_G200_PCI: + cards_init(card, dev, mga_cards_num - 1, 0); + break; + default: break; } } @@ -1461,7 +1514,16 @@ return(-EAGAIN); } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,3) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + //printk(KERN_DEBUG "mga_vid: start=vma->vm_start=0x%lx\n", vma->vm_start); + //printk(KERN_DEBUG "mga_vid: vma->vm_end=0x%lx\n", vma->vm_end); + //printk(KERN_DEBUG "mga_vid: card->mem_base=0x%x\n", card->mem_base); + //printk(KERN_DEBUG "mga_vid: card->src_base=0x%x\n", card->src_base); + //printk(KERN_DEBUG "mga_vid: pfn=%d\n", (card->mem_base + card->src_base) >> PAGE_SHIFT); + //printk(KERN_DEBUG "mga_vid: prot=vma->vm_page_prot=%lu\n", vma->vm_page_prot.pgprot); + if(remap_pfn_range(vma, vma->vm_start, (card->mem_base + card->src_base) >> PAGE_SHIFT, + vma->vm_end - vma->vm_start, vma->vm_page_prot)) +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,3) if(remap_page_range(vma, vma->vm_start, card->mem_base + card->src_base, vma->vm_end - vma->vm_start, vma->vm_page_prot)) #else @@ -1494,7 +1556,9 @@ mga_vid_write_regs(card, 1); card->vid_in_use = 0; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) MOD_DEC_USE_COUNT; +#endif return 0; } @@ -1507,7 +1571,7 @@ { mga_card_t * card; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,2) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,2) && LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) int minor = MINOR(inode->i_rdev.value); #else int minor = MINOR(inode->i_rdev); @@ -1539,7 +1603,9 @@ return(-EBUSY); card->vid_in_use = 1; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) MOD_INC_USE_COUNT; +#endif return(0); } @@ -1685,12 +1751,23 @@ #endif // register devfs, let the kernel give us major and minor numbers -#ifdef CONFIG_DEVFS_FS +#if defined(CONFIG_DEVFS_FS) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) snprintf(buffer, 16, "mga_vid%d", card_number); card->dev_handle = devfs_register(NULL, buffer, DEVFS_FL_AUTO_DEVNUM, 0, 0, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IFCHR, &mga_vid_fops, card); +#elif defined(CONFIG_DEVFS_FS) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) + if(devfs_mk_cdev(MKDEV(major, 0), + S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IFCHR, + buffer) < 0) + { + printk(KERN_ERR "mga_vid: unable to get major: %d (devfs 2.6) => fallb\ack to non-devfs mode\n", major); + } + else + { + uses_devfs = 1; + } #endif } @@ -1728,7 +1805,7 @@ unregister_chrdev(major, "mga_vid"); return -EINVAL; } -#ifdef CONFIG_DEVFS_FS +#if defined(CONFIG_DEVFS_FS) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) else { // we assume that this always succeedes dev_handle = devfs_register(NULL, "mga_vid", DEVFS_FL_AUTO_DEVNUM, @@ -1736,6 +1813,17 @@ S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IFCHR, &mga_vid_fops, mga_cards[0]); } +#elif defined(CONFIG_DEVFS_FS) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) + if(devfs_mk_cdev(MKDEV(major, 0), + S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IFCHR, + "mga_vid") < 0) + { + printk(KERN_ERR "mga_vid: unable to get major: %d (devfs 2.6) => fallback to non-devfs mode\n", major); + } + else + { + uses_devfs = 1; + } #endif return(0); @@ -1765,7 +1853,7 @@ iounmap(card->mmio_base); if(card->param_buff) kfree(card->param_buff); -#ifdef CONFIG_DEVFS_FS +#if defined(CONFIG_DEVFS_FS) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) if(card->dev_handle) devfs_unregister(card->dev_handle); #endif @@ -1776,7 +1864,7 @@ //FIXME turn off BES printk(KERN_INFO "mga_vid: Cleaning up module\n"); -#ifdef CONFIG_DEVFS_FS +#if defined(CONFIG_DEVFS_FS) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) if(dev_handle) devfs_unregister(dev_handle); #endif unregister_chrdev(major, "mga_vid");