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>
7 
8 struct isa_bridge *isa_chain;
9 
fatal_err(const char * reason)10 static void __init fatal_err(const char *reason)
11 {
12 	prom_printf("ISA: fatal error, %s.\n", reason);
13 }
14 
report_dev(struct isa_device * isa_dev,int child)15 static void __init report_dev(struct isa_device *isa_dev, int child)
16 {
17 	if (child)
18 		printk(" (%s)", isa_dev->prom_name);
19 	else
20 		printk(" [%s", isa_dev->prom_name);
21 }
22 
isa_dev_get_resource(struct isa_device * isa_dev,struct linux_prom_registers * pregs,int pregs_size)23 static void __init isa_dev_get_resource(struct isa_device *isa_dev,
24 					struct linux_prom_registers *pregs,
25 					int pregs_size)
26 {
27 	unsigned long base, len;
28 	int prop_len;
29 
30 	prop_len = prom_getproperty(isa_dev->prom_node, "reg",
31 				    (char *) pregs, pregs_size);
32 
33 	if (prop_len <= 0)
34 		return;
35 
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;
41 
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;
46 
47 	request_resource(&isa_dev->bus->parent->io_space,
48 			 &isa_dev->resource);
49 }
50 
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.
54  *
55  * The P1275 standard for ISA devices seems to also have been
56  * totally ignored.
57  *
58  * On later systems, an interrupt-map and interrupt-map-mask scheme
59  * akin to EBUS is used.
60  */
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 */
70 
71 	{ 0, 0x00 }	/* end of table */
72 };
73 
isa_dev_get_irq_using_imap(struct isa_device * isa_dev,struct isa_bridge * isa_br,int * interrupt,struct linux_prom_registers * pregs)74 static int __init isa_dev_get_irq_using_imap(struct isa_device *isa_dev,
75 					     struct isa_bridge *isa_br,
76 					     int *interrupt,
77 					     struct linux_prom_registers *pregs)
78 {
79 	unsigned int hi, lo, irq;
80 	int i;
81 
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;
91 		}
92 	}
93 	return -1;
94 }
95 
isa_dev_get_irq(struct isa_device * isa_dev,struct linux_prom_registers * pregs)96 static void __init isa_dev_get_irq(struct isa_device *isa_dev,
97 				   struct linux_prom_registers *pregs)
98 {
99 	int irq_prop;
100 
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;
109 
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;
116 		}
117 
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;
121 
122 				if (ino == 0)
123 					goto no_irq;
124 
125 				irq_prop = ino;
126 				goto route_irq;
127 			}
128 		}
129 		goto no_irq;
130 
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;
136 	}
137 
138 no_irq:
139 	isa_dev->irq = PCI_IRQ_NONE;
140 }
141 
isa_fill_children(struct isa_device * parent_isa_dev)142 static void __init isa_fill_children(struct isa_device *parent_isa_dev)
143 {
144 	int node = prom_getchild(parent_isa_dev->prom_node);
145 
146 	if (node == 0)
147 		return;
148 
149 	printk(" ->");
150 	while (node != 0) {
151 		struct linux_prom_registers regs[PROMREG_MAX];
152 		struct isa_device *isa_dev;
153 		int prop_len;
154 
155 		isa_dev = kmalloc(sizeof(*isa_dev), GFP_KERNEL);
156 		if (!isa_dev) {
157 			fatal_err("cannot allocate child isa_dev");
158 			prom_halt();
159 		}
160 
161 		memset(isa_dev, 0, sizeof(*isa_dev));
162 
163 		/* Link it in to parent. */
164 		isa_dev->next = parent_isa_dev->child;
165 		parent_isa_dev->child = isa_dev;
166 
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();
175 		}
176 
177 		prop_len = prom_getproperty(node, "compatible",
178 					    (char *) isa_dev->compatible,
179 					    sizeof(isa_dev->compatible));
180 
181 		/* Not having this is OK. */
182 		if (prop_len <= 0)
183 			isa_dev->compatible[0] = '\0';
184 
185 		isa_dev_get_resource(isa_dev, regs, sizeof(regs));
186 		isa_dev_get_irq(isa_dev, regs);
187 
188 		report_dev(isa_dev, 1);
189 
190 		node = prom_getsibling(node);
191 	}
192 }
193 
isa_fill_devices(struct isa_bridge * isa_br)194 static void __init isa_fill_devices(struct isa_bridge *isa_br)
195 {
196 	int node = prom_getchild(isa_br->prom_node);
197 
198 	while (node != 0) {
199 		struct linux_prom_registers regs[PROMREG_MAX];
200 		struct isa_device *isa_dev;
201 		int prop_len;
202 
203 		isa_dev = kmalloc(sizeof(*isa_dev), GFP_KERNEL);
204 		if (!isa_dev) {
205 			fatal_err("cannot allocate isa_dev");
206 			prom_halt();
207 		}
208 
209 		memset(isa_dev, 0, sizeof(*isa_dev));
210 
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 isa_device *tmp = isa_br->devices;
217 
218 			while (tmp->next)
219 				tmp = tmp->next;
220 
221 			tmp->next = isa_dev;
222 		}
223 
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();
232 		}
233 
234 		prop_len = prom_getproperty(node, "compatible",
235 					    (char *) isa_dev->compatible,
236 					    sizeof(isa_dev->compatible));
237 
238 		/* Not having this is OK. */
239 		if (prop_len <= 0)
240 			isa_dev->compatible[0] = '\0';
241 
242 		isa_dev_get_resource(isa_dev, regs, sizeof(regs));
243 		isa_dev_get_irq(isa_dev, regs);
244 
245 		report_dev(isa_dev, 0);
246 
247 		isa_fill_children(isa_dev);
248 
249 		printk("]");
250 
251 		node = prom_getsibling(node);
252 	}
253 }
254 
isa_init(void)255 void __init isa_init(void)
256 {
257 	struct pci_dev *pdev;
258 	unsigned short vendor, device;
259 	int index = 0;
260 
261 	vendor = PCI_VENDOR_ID_AL;
262 	device = PCI_DEVICE_ID_AL_M1533;
263 
264 	pdev = NULL;
265 	while ((pdev = pci_find_device(vendor, device, pdev)) != NULL) {
266 		struct pcidev_cookie *pdev_cookie;
267 		struct pci_pbm_info *pbm;
268 		struct isa_bridge *isa_br;
269 		int prop_len;
270 
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;
276 		}
277 		pbm = pdev_cookie->pbm;
278 
279 		isa_br = kmalloc(sizeof(*isa_br), GFP_KERNEL);
280 		if (!isa_br) {
281 			fatal_err("cannot allocate isa_bridge");
282 			prom_halt();
283 		}
284 
285 		memset(isa_br, 0, sizeof(*isa_br));
286 
287 		/* Link it in. */
288 		isa_br->next = isa_chain;
289 		isa_chain = isa_br;
290 
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));
297 
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));
307 
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));
317 
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));
322 
323 		printk("isa%d:", isa_br->index);
324 
325 		isa_fill_devices(isa_br);
326 
327 		printk("\n");
328 	}
329 }
330