linux-old/drivers/pnp/quirks.c
<<
>>
Prefs
   1/*
   2 *  This file contains quirk handling code for ISAPnP devices
   3 *  Some devices do not report all their resources, and need to have extra
   4 *  resources added. This is most easily accomplished at initialisation time
   5 *  when building up the resource structure for the first time.
   6 *
   7 *  Copyright (c) 2000 Peter Denison <peterd@pnd-pc.demon.co.uk>
   8 *
   9 *  Heavily based on PCI quirks handling which is
  10 *
  11 *  Copyright (c) 1999 Martin Mares <mj@ucw.cz>
  12 */
  13
  14#include <linux/types.h>
  15#include <linux/kernel.h>
  16#include <linux/pci.h>
  17#include <linux/init.h>
  18#include <linux/isapnp.h>
  19#include <linux/string.h>
  20
  21#if 0
  22#define ISAPNP_DEBUG
  23#endif
  24
  25static void __init quirk_awe32_resources(struct pci_dev *dev)
  26{
  27        struct isapnp_port *port, *port2, *port3;
  28        struct isapnp_resources *res = dev->sysdata;
  29
  30        /*
  31         * Unfortunately the isapnp_add_port_resource is too tightly bound
  32         * into the PnP discovery sequence, and cannot be used. Link in the
  33         * two extra ports (at offset 0x400 and 0x800 from the one given) by
  34         * hand.
  35         */
  36        for ( ; res ; res = res->alt ) {
  37                port2 = isapnp_alloc(sizeof(struct isapnp_port));
  38                port3 = isapnp_alloc(sizeof(struct isapnp_port));
  39                if (!port2 || !port3)
  40                        return;
  41                port = res->port;
  42                memcpy(port2, port, sizeof(struct isapnp_port));
  43                memcpy(port3, port, sizeof(struct isapnp_port));
  44                port->next = port2;
  45                port2->next = port3;
  46                port2->min += 0x400;
  47                port2->max += 0x400;
  48                port3->min += 0x800;
  49                port3->max += 0x800;
  50        }
  51        printk(KERN_INFO "isapnp: AWE32 quirk - adding two ports\n");
  52}
  53
  54static void __init quirk_cmi8330_resources(struct pci_dev *dev)
  55{
  56        struct isapnp_resources *res = dev->sysdata;
  57
  58        for ( ; res ; res = res->alt ) {
  59
  60                struct isapnp_irq *irq;
  61                struct isapnp_dma *dma;
  62        
  63                for( irq = res->irq; irq; irq = irq->next )     // Valid irqs are 5, 7, 10
  64                        irq->map = 0x04A0;                                              // 0000 0100 1010 0000
  65
  66                for( dma = res->dma; dma; dma = dma->next ) // Valid 8bit dma channels are 1,3
  67                        if( ( dma->flags & IORESOURCE_DMA_TYPE_MASK ) == IORESOURCE_DMA_8BIT )
  68                                dma->map = 0x000A;
  69        }
  70        printk(KERN_INFO "isapnp: CMI8330 quirk - fixing interrupts and dma\n");
  71}
  72
  73static void __init quirk_sb16audio_resources(struct pci_dev *dev)
  74{
  75        struct isapnp_port *port;
  76        struct isapnp_resources *res = dev->sysdata;
  77        int    changed = 0;
  78
  79        /* 
  80         * The default range on the mpu port for these devices is 0x388-0x388.
  81         * Here we increase that range so that two such cards can be
  82         * auto-configured.
  83         */
  84        
  85        for( ; res ; res = res->alt ) {
  86                port = res->port;
  87                if(!port)
  88                        continue;
  89                port = port->next;
  90                if(!port)
  91                        continue;
  92                port = port->next;
  93                if(!port)
  94                        continue;
  95                if(port->min != port->max)
  96                        continue;
  97                port->max += 0x70;
  98                changed = 1;
  99        }
 100        if(changed)
 101                printk(KERN_INFO "isapnp: SB audio device quirk - increasing port range\n");
 102        return;
 103}
 104
 105/*
 106 *  ISAPnP Quirks
 107 *  Cards or devices that need some tweaking due to broken hardware
 108 */
 109
 110static struct isapnp_fixup isapnp_fixups[] __initdata = {
 111        /* Soundblaster awe io port quirk */
 112        { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0021),
 113                quirk_awe32_resources },
 114        { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0022),
 115                quirk_awe32_resources },
 116        { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0023),
 117                quirk_awe32_resources },
 118        /* CMI 8330 interrupt and dma fix */
 119        { ISAPNP_VENDOR('@','X','@'), ISAPNP_DEVICE(0x0001),
 120                quirk_cmi8330_resources },
 121        /* Soundblaster audio device io port range quirk */
 122        { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0001),
 123                quirk_sb16audio_resources },
 124        { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0031),
 125                quirk_sb16audio_resources },
 126        { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0041),
 127                quirk_sb16audio_resources },
 128        { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0042),
 129                quirk_sb16audio_resources },
 130        { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0043),
 131                quirk_sb16audio_resources },
 132        { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0044),
 133                quirk_sb16audio_resources },
 134        { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0045),
 135                quirk_sb16audio_resources },
 136        { 0 }
 137};
 138
 139void isapnp_fixup_device(struct pci_dev *dev)
 140{
 141        int i = 0;
 142
 143        while (isapnp_fixups[i].vendor != 0) {
 144                if ((isapnp_fixups[i].vendor == dev->vendor) &&
 145                    (isapnp_fixups[i].device == dev->device)) {
 146#ifdef ISAPNP_DEBUG
 147                        printk(KERN_DEBUG "isapnp: Calling quirk for %02x:%02x\n",
 148                               dev->bus->number, dev->devfn);
 149#endif
 150                        isapnp_fixups[i].quirk_function(dev);
 151                }
 152                i++;
 153        }
 154}
 155
 156
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.