[SCSI] qla2xxx: Correct issue where driver improperly issued SNS commands in N2N...
[linux-2.6/openmoko-kernel/knife-kernel.git] / arch / sparc64 / kernel / isa.c
blob30862abee611d745fd3182722c2c23e73bda488f
1 #include <linux/kernel.h>
2 #include <linux/init.h>
3 #include <linux/pci.h>
4 #include <linux/slab.h>
5 #include <asm/oplib.h>
6 #include <asm/isa.h>
8 struct sparc_isa_bridge *isa_chain;
10 static void __init fatal_err(const char *reason)
12 prom_printf("ISA: fatal error, %s.\n", reason);
15 static void __init report_dev(struct sparc_isa_device *isa_dev, int child)
17 if (child)
18 printk(" (%s)", isa_dev->prom_name);
19 else
20 printk(" [%s", isa_dev->prom_name);
23 static void __init isa_dev_get_resource(struct sparc_isa_device *isa_dev,
24 struct linux_prom_registers *pregs,
25 int pregs_size)
27 unsigned long base, len;
28 int prop_len;
30 prop_len = prom_getproperty(isa_dev->prom_node, "reg",
31 (char *) pregs, pregs_size);
33 if (prop_len <= 0)
34 return;
36 /* Only the first one is interesting. */
37 len = pregs[0].reg_size;
38 base = (((unsigned long)pregs[0].which_io << 32) |
39 (unsigned long)pregs[0].phys_addr);
40 base += isa_dev->bus->parent->io_space.start;
42 isa_dev->resource.start = base;
43 isa_dev->resource.end = (base + len - 1UL);
44 isa_dev->resource.flags = IORESOURCE_IO;
45 isa_dev->resource.name = isa_dev->prom_name;
47 request_resource(&isa_dev->bus->parent->io_space,
48 &isa_dev->resource);
51 /* I can't believe they didn't put a real INO in the isa device
52 * interrupts property. The whole point of the OBP properties
53 * is to shield the kernel from IRQ routing details.
55 * The P1275 standard for ISA devices seems to also have been
56 * totally ignored.
58 * On later systems, an interrupt-map and interrupt-map-mask scheme
59 * akin to EBUS is used.
61 static struct {
62 int obp_irq;
63 int pci_ino;
64 } grover_irq_table[] = {
65 { 1, 0x00 }, /* dma, unknown ino at this point */
66 { 2, 0x27 }, /* floppy */
67 { 3, 0x22 }, /* parallel */
68 { 4, 0x2b }, /* serial */
69 { 5, 0x25 }, /* acpi power management */
71 { 0, 0x00 } /* end of table */
74 static int __init isa_dev_get_irq_using_imap(struct sparc_isa_device *isa_dev,
75 struct sparc_isa_bridge *isa_br,
76 int *interrupt,
77 struct linux_prom_registers *pregs)
79 unsigned int hi, lo, irq;
80 int i;
82 hi = pregs->which_io & isa_br->isa_intmask.phys_hi;
83 lo = pregs->phys_addr & isa_br->isa_intmask.phys_lo;
84 irq = *interrupt & isa_br->isa_intmask.interrupt;
85 for (i = 0; i < isa_br->num_isa_intmap; i++) {
86 if ((isa_br->isa_intmap[i].phys_hi == hi) &&
87 (isa_br->isa_intmap[i].phys_lo == lo) &&
88 (isa_br->isa_intmap[i].interrupt == irq)) {
89 *interrupt = isa_br->isa_intmap[i].cinterrupt;
90 return 0;
93 return -1;
96 static void __init isa_dev_get_irq(struct sparc_isa_device *isa_dev,
97 struct linux_prom_registers *pregs)
99 int irq_prop;
101 irq_prop = prom_getintdefault(isa_dev->prom_node,
102 "interrupts", -1);
103 if (irq_prop <= 0) {
104 goto no_irq;
105 } else {
106 struct pci_controller_info *pcic;
107 struct pci_pbm_info *pbm;
108 int i;
110 if (isa_dev->bus->num_isa_intmap) {
111 if (!isa_dev_get_irq_using_imap(isa_dev,
112 isa_dev->bus,
113 &irq_prop,
114 pregs))
115 goto route_irq;
118 for (i = 0; grover_irq_table[i].obp_irq != 0; i++) {
119 if (grover_irq_table[i].obp_irq == irq_prop) {
120 int ino = grover_irq_table[i].pci_ino;
122 if (ino == 0)
123 goto no_irq;
125 irq_prop = ino;
126 goto route_irq;
129 goto no_irq;
131 route_irq:
132 pbm = isa_dev->bus->parent;
133 pcic = pbm->parent;
134 isa_dev->irq = pcic->irq_build(pbm, NULL, irq_prop);
135 return;
138 no_irq:
139 isa_dev->irq = PCI_IRQ_NONE;
142 static void __init isa_fill_children(struct sparc_isa_device *parent_isa_dev)
144 int node = prom_getchild(parent_isa_dev->prom_node);
146 if (node == 0)
147 return;
149 printk(" ->");
150 while (node != 0) {
151 struct linux_prom_registers regs[PROMREG_MAX];
152 struct sparc_isa_device *isa_dev;
153 int prop_len;
155 isa_dev = kmalloc(sizeof(*isa_dev), GFP_KERNEL);
156 if (!isa_dev) {
157 fatal_err("cannot allocate child isa_dev");
158 prom_halt();
161 memset(isa_dev, 0, sizeof(*isa_dev));
163 /* Link it in to parent. */
164 isa_dev->next = parent_isa_dev->child;
165 parent_isa_dev->child = isa_dev;
167 isa_dev->bus = parent_isa_dev->bus;
168 isa_dev->prom_node = node;
169 prop_len = prom_getproperty(node, "name",
170 (char *) isa_dev->prom_name,
171 sizeof(isa_dev->prom_name));
172 if (prop_len <= 0) {
173 fatal_err("cannot get child isa_dev OBP node name");
174 prom_halt();
177 prop_len = prom_getproperty(node, "compatible",
178 (char *) isa_dev->compatible,
179 sizeof(isa_dev->compatible));
181 /* Not having this is OK. */
182 if (prop_len <= 0)
183 isa_dev->compatible[0] = '\0';
185 isa_dev_get_resource(isa_dev, regs, sizeof(regs));
186 isa_dev_get_irq(isa_dev, regs);
188 report_dev(isa_dev, 1);
190 node = prom_getsibling(node);
194 static void __init isa_fill_devices(struct sparc_isa_bridge *isa_br)
196 int node = prom_getchild(isa_br->prom_node);
198 while (node != 0) {
199 struct linux_prom_registers regs[PROMREG_MAX];
200 struct sparc_isa_device *isa_dev;
201 int prop_len;
203 isa_dev = kmalloc(sizeof(*isa_dev), GFP_KERNEL);
204 if (!isa_dev) {
205 fatal_err("cannot allocate isa_dev");
206 prom_halt();
209 memset(isa_dev, 0, sizeof(*isa_dev));
211 /* Link it in. */
212 isa_dev->next = NULL;
213 if (isa_br->devices == NULL) {
214 isa_br->devices = isa_dev;
215 } else {
216 struct sparc_isa_device *tmp = isa_br->devices;
218 while (tmp->next)
219 tmp = tmp->next;
221 tmp->next = isa_dev;
224 isa_dev->bus = isa_br;
225 isa_dev->prom_node = node;
226 prop_len = prom_getproperty(node, "name",
227 (char *) isa_dev->prom_name,
228 sizeof(isa_dev->prom_name));
229 if (prop_len <= 0) {
230 fatal_err("cannot get isa_dev OBP node name");
231 prom_halt();
234 prop_len = prom_getproperty(node, "compatible",
235 (char *) isa_dev->compatible,
236 sizeof(isa_dev->compatible));
238 /* Not having this is OK. */
239 if (prop_len <= 0)
240 isa_dev->compatible[0] = '\0';
242 isa_dev_get_resource(isa_dev, regs, sizeof(regs));
243 isa_dev_get_irq(isa_dev, regs);
245 report_dev(isa_dev, 0);
247 isa_fill_children(isa_dev);
249 printk("]");
251 node = prom_getsibling(node);
255 void __init isa_init(void)
257 struct pci_dev *pdev;
258 unsigned short vendor, device;
259 int index = 0;
261 vendor = PCI_VENDOR_ID_AL;
262 device = PCI_DEVICE_ID_AL_M1533;
264 pdev = NULL;
265 while ((pdev = pci_get_device(vendor, device, pdev)) != NULL) {
266 struct pcidev_cookie *pdev_cookie;
267 struct pci_pbm_info *pbm;
268 struct sparc_isa_bridge *isa_br;
269 int prop_len;
271 pdev_cookie = pdev->sysdata;
272 if (!pdev_cookie) {
273 printk("ISA: Warning, ISA bridge ignored due to "
274 "lack of OBP data.\n");
275 continue;
277 pbm = pdev_cookie->pbm;
279 isa_br = kmalloc(sizeof(*isa_br), GFP_KERNEL);
280 if (!isa_br) {
281 fatal_err("cannot allocate sparc_isa_bridge");
282 prom_halt();
285 memset(isa_br, 0, sizeof(*isa_br));
287 /* Link it in. */
288 isa_br->next = isa_chain;
289 isa_chain = isa_br;
291 isa_br->parent = pbm;
292 isa_br->self = pdev;
293 isa_br->index = index++;
294 isa_br->prom_node = pdev_cookie->prom_node;
295 strncpy(isa_br->prom_name, pdev_cookie->prom_name,
296 sizeof(isa_br->prom_name));
298 prop_len = prom_getproperty(isa_br->prom_node,
299 "ranges",
300 (char *) isa_br->isa_ranges,
301 sizeof(isa_br->isa_ranges));
302 if (prop_len <= 0)
303 isa_br->num_isa_ranges = 0;
304 else
305 isa_br->num_isa_ranges =
306 (prop_len / sizeof(struct linux_prom_isa_ranges));
308 prop_len = prom_getproperty(isa_br->prom_node,
309 "interrupt-map",
310 (char *) isa_br->isa_intmap,
311 sizeof(isa_br->isa_intmap));
312 if (prop_len <= 0)
313 isa_br->num_isa_intmap = 0;
314 else
315 isa_br->num_isa_intmap =
316 (prop_len / sizeof(struct linux_prom_isa_intmap));
318 prop_len = prom_getproperty(isa_br->prom_node,
319 "interrupt-map-mask",
320 (char *) &(isa_br->isa_intmask),
321 sizeof(isa_br->isa_intmask));
323 printk("isa%d:", isa_br->index);
325 isa_fill_devices(isa_br);
327 printk("\n");