original comment: +Wilson03172004,marked due to this pci host does not support MWI
[linux-2.4.git] / drivers / pnp / quirks.c
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
25 static 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
54 static 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
73 static 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
110 static 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
139 void 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