~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/drivers/pnp/quirks.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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@suse.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 static void __init quirk_awe32_resources(struct pci_dev *dev)
 22 {
 23         struct isapnp_port *port, *port2, *port3;
 24         struct isapnp_resources *res = dev->sysdata;
 25 
 26         /*
 27          * Unfortunately the isapnp_add_port_resource is too tightly bound
 28          * into the PnP discovery sequence, and cannot be used. Link in the
 29          * two extra ports (at offset 0x400 and 0x800 from the one given) by
 30          * hand.
 31          */
 32         for ( ; res ; res = res->alt ) {
 33                 port2 = isapnp_alloc(sizeof(struct isapnp_port));
 34                 port3 = isapnp_alloc(sizeof(struct isapnp_port));
 35                 if (!port2 || !port3)
 36                         return;
 37                 port = res->port;
 38                 memcpy(port2, port, sizeof(struct isapnp_port));
 39                 memcpy(port3, port, sizeof(struct isapnp_port));
 40                 port->next = port2;
 41                 port2->next = port3;
 42                 port2->min += 0x400;
 43                 port2->max += 0x400;
 44                 port3->min += 0x800;
 45                 port3->max += 0x800;
 46         }
 47         printk(KERN_INFO "isapnp: AWE32 quirk - adding two ports\n");
 48 }
 49 
 50 static void __init quirk_cmi8330_resources(struct pci_dev *dev)
 51 {
 52         struct isapnp_resources *res = dev->sysdata;
 53 
 54         for ( ; res ; res = res->alt ) {
 55 
 56                 struct isapnp_irq *irq;
 57                 struct isapnp_dma *dma;
 58         
 59                 for( irq = res->irq; irq; irq = irq->next )     // Valid irqs are 5, 7, 10
 60                         irq->map = 0x04A0;                                              // 0000 0100 1010 0000
 61 
 62                 for( dma = res->dma; dma; dma = dma->next ) // Valid 8bit dma channels are 1,3
 63                         if( ( dma->flags & IORESOURCE_DMA_TYPE_MASK ) == IORESOURCE_DMA_8BIT )
 64                                 dma->map = 0x000A;
 65         }
 66         printk(KERN_INFO "isapnp: CMI8330 quirk - fixing interrupts and dma\n");
 67 }
 68 
 69 static void __init quirk_sb16audio_resources(struct pci_dev *dev)
 70 {
 71         struct isapnp_port *port;
 72         struct isapnp_resources *res = dev->sysdata;
 73         int    changed = 0;
 74 
 75         /* 
 76          * The default range on the mpu port for these devices is 0x388-0x388.
 77          * Here we increase that range so that two such cards can be
 78          * auto-configured.
 79          */
 80         
 81         for( ; res ; res = res->alt ) {
 82                 port = res->port;
 83                 if(!port)
 84                         continue;
 85                 port = port->next;
 86                 if(!port)
 87                         continue;
 88                 port = port->next;
 89                 if(!port)
 90                         continue;
 91                 if(port->min != port->max)
 92                         continue;
 93                 port->max += 0x70;
 94                 changed = 1;
 95         }
 96         if(changed)
 97                 printk(KERN_INFO "isapnp: SB audio device quirk - increasing port range\n");
 98         return;
 99 }
100 
101 /*
102  *  ISAPnP Quirks
103  *  Cards or devices that need some tweaking due to broken hardware
104  */
105 
106 static struct isapnp_fixup isapnp_fixups[] __initdata = {
107         /* Soundblaster awe io port quirk */
108         { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0021),
109                 quirk_awe32_resources },
110         { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0022),
111                 quirk_awe32_resources },
112         { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0023),
113                 quirk_awe32_resources },
114         /* CMI 8330 interrupt and dma fix */
115         { ISAPNP_VENDOR('@','X','@'), ISAPNP_DEVICE(0x0001),
116                 quirk_cmi8330_resources },
117         /* Soundblaster audio device io port range quirk */
118         { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0001),
119                 quirk_sb16audio_resources },
120         { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0031),
121                 quirk_sb16audio_resources },
122         { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0041),
123                 quirk_sb16audio_resources },
124         { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0042),
125                 quirk_sb16audio_resources },
126         { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0043),
127                 quirk_sb16audio_resources },
128         { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0044),
129                 quirk_sb16audio_resources },
130         { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0045),
131                 quirk_sb16audio_resources },
132         { 0 }
133 };
134 
135 void isapnp_fixup_device(struct pci_dev *dev)
136 {
137         int i = 0;
138 
139         while (isapnp_fixups[i].vendor != 0) {
140                 if ((isapnp_fixups[i].vendor == dev->vendor) &&
141                     (isapnp_fixups[i].device == dev->device)) {
142                         printk(KERN_DEBUG "isapnp: Calling quirk for %02x:%02x\n",
143                                dev->bus->number, dev->devfn);
144                         isapnp_fixups[i].quirk_function(dev);
145                 }
146                 i++;
147         }
148 }
149 
150 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.