diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/parisc/kernel/drivers.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'arch/parisc/kernel/drivers.c')
-rw-r--r-- | arch/parisc/kernel/drivers.c | 765 |
1 files changed, 765 insertions, 0 deletions
diff --git a/arch/parisc/kernel/drivers.c b/arch/parisc/kernel/drivers.c new file mode 100644 index 000000000000..ebf186656afb --- /dev/null +++ b/arch/parisc/kernel/drivers.c | |||
@@ -0,0 +1,765 @@ | |||
1 | /* | ||
2 | * drivers.c | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation; either version | ||
7 | * 2 of the License, or (at your option) any later version. | ||
8 | * | ||
9 | * Copyright (c) 1999 The Puffin Group | ||
10 | * Copyright (c) 2001 Matthew Wilcox for Hewlett Packard | ||
11 | * Copyright (c) 2001 Helge Deller <deller@gmx.de> | ||
12 | * Copyright (c) 2001,2002 Ryan Bradetich | ||
13 | * Copyright (c) 2004-2005 Thibaut VARENE <varenet@parisc-linux.org> | ||
14 | * | ||
15 | * The file handles registering devices and drivers, then matching them. | ||
16 | * It's the closest we get to a dating agency. | ||
17 | * | ||
18 | * If you're thinking about modifying this file, here are some gotchas to | ||
19 | * bear in mind: | ||
20 | * - 715/Mirage device paths have a dummy device between Lasi and its children | ||
21 | * - The EISA adapter may show up as a sibling or child of Wax | ||
22 | * - Dino has an optionally functional serial port. If firmware enables it, | ||
23 | * it shows up as a child of Dino. If firmware disables it, the buswalk | ||
24 | * finds it and it shows up as a child of Cujo | ||
25 | * - Dino has both parisc and pci devices as children | ||
26 | * - parisc devices are discovered in a random order, including children | ||
27 | * before parents in some cases. | ||
28 | */ | ||
29 | |||
30 | #include <linux/slab.h> | ||
31 | #include <linux/types.h> | ||
32 | #include <linux/kernel.h> | ||
33 | #include <linux/pci.h> | ||
34 | #include <linux/spinlock.h> | ||
35 | #include <linux/string.h> | ||
36 | #include <asm/hardware.h> | ||
37 | #include <asm/io.h> | ||
38 | #include <asm/pdc.h> | ||
39 | #include <asm/parisc-device.h> | ||
40 | |||
41 | /* See comments in include/asm-parisc/pci.h */ | ||
42 | struct hppa_dma_ops *hppa_dma_ops; | ||
43 | EXPORT_SYMBOL(hppa_dma_ops); | ||
44 | |||
45 | static struct device root = { | ||
46 | .bus_id = "parisc", | ||
47 | }; | ||
48 | |||
49 | #define for_each_padev(padev) \ | ||
50 | for (padev = next_dev(&root); padev != NULL; \ | ||
51 | padev = next_dev(&padev->dev)) | ||
52 | |||
53 | #define check_dev(padev) \ | ||
54 | (padev->id.hw_type != HPHW_FAULTY) ? padev : next_dev(&padev->dev) | ||
55 | |||
56 | /** | ||
57 | * next_dev - enumerates registered devices | ||
58 | * @dev: the previous device returned from next_dev | ||
59 | * | ||
60 | * next_dev does a depth-first search of the tree, returning parents | ||
61 | * before children. Returns NULL when there are no more devices. | ||
62 | */ | ||
63 | static struct parisc_device *next_dev(struct device *dev) | ||
64 | { | ||
65 | if (!list_empty(&dev->children)) { | ||
66 | dev = list_to_dev(dev->children.next); | ||
67 | return check_dev(to_parisc_device(dev)); | ||
68 | } | ||
69 | |||
70 | while (dev != &root) { | ||
71 | if (dev->node.next != &dev->parent->children) { | ||
72 | dev = list_to_dev(dev->node.next); | ||
73 | return to_parisc_device(dev); | ||
74 | } | ||
75 | dev = dev->parent; | ||
76 | } | ||
77 | |||
78 | return NULL; | ||
79 | } | ||
80 | |||
81 | /** | ||
82 | * match_device - Report whether this driver can handle this device | ||
83 | * @driver: the PA-RISC driver to try | ||
84 | * @dev: the PA-RISC device to try | ||
85 | */ | ||
86 | static int match_device(struct parisc_driver *driver, struct parisc_device *dev) | ||
87 | { | ||
88 | const struct parisc_device_id *ids; | ||
89 | |||
90 | for (ids = driver->id_table; ids->sversion; ids++) { | ||
91 | if ((ids->sversion != SVERSION_ANY_ID) && | ||
92 | (ids->sversion != dev->id.sversion)) | ||
93 | continue; | ||
94 | |||
95 | if ((ids->hw_type != HWTYPE_ANY_ID) && | ||
96 | (ids->hw_type != dev->id.hw_type)) | ||
97 | continue; | ||
98 | |||
99 | if ((ids->hversion != HVERSION_ANY_ID) && | ||
100 | (ids->hversion != dev->id.hversion)) | ||
101 | continue; | ||
102 | |||
103 | return 1; | ||
104 | } | ||
105 | return 0; | ||
106 | } | ||
107 | |||
108 | static void claim_device(struct parisc_driver *driver, struct parisc_device *dev) | ||
109 | { | ||
110 | dev->driver = driver; | ||
111 | request_mem_region(dev->hpa, 0x1000, driver->name); | ||
112 | } | ||
113 | |||
114 | static int parisc_driver_probe(struct device *dev) | ||
115 | { | ||
116 | int rc; | ||
117 | struct parisc_device *pa_dev = to_parisc_device(dev); | ||
118 | struct parisc_driver *pa_drv = to_parisc_driver(dev->driver); | ||
119 | |||
120 | rc = pa_drv->probe(pa_dev); | ||
121 | |||
122 | if(!rc) | ||
123 | claim_device(pa_drv, pa_dev); | ||
124 | |||
125 | return rc; | ||
126 | } | ||
127 | |||
128 | static int parisc_driver_remove(struct device *dev) | ||
129 | { | ||
130 | struct parisc_device *pa_dev = to_parisc_device(dev); | ||
131 | struct parisc_driver *pa_drv = to_parisc_driver(dev->driver); | ||
132 | if (pa_drv->remove) | ||
133 | pa_drv->remove(pa_dev); | ||
134 | release_mem_region(pa_dev->hpa, 0x1000); | ||
135 | |||
136 | return 0; | ||
137 | } | ||
138 | |||
139 | |||
140 | /** | ||
141 | * register_parisc_driver - Register this driver if it can handle a device | ||
142 | * @driver: the PA-RISC driver to try | ||
143 | */ | ||
144 | int register_parisc_driver(struct parisc_driver *driver) | ||
145 | { | ||
146 | /* FIXME: we need this because apparently the sti | ||
147 | * driver can be registered twice */ | ||
148 | if(driver->drv.name) { | ||
149 | printk(KERN_WARNING | ||
150 | "BUG: skipping previously registered driver %s\n", | ||
151 | driver->name); | ||
152 | return 1; | ||
153 | } | ||
154 | |||
155 | if (!driver->probe) { | ||
156 | printk(KERN_WARNING | ||
157 | "BUG: driver %s has no probe routine\n", | ||
158 | driver->name); | ||
159 | return 1; | ||
160 | } | ||
161 | |||
162 | driver->drv.bus = &parisc_bus_type; | ||
163 | |||
164 | /* We install our own probe and remove routines */ | ||
165 | WARN_ON(driver->drv.probe != NULL); | ||
166 | WARN_ON(driver->drv.remove != NULL); | ||
167 | |||
168 | driver->drv.probe = parisc_driver_probe; | ||
169 | driver->drv.remove = parisc_driver_remove; | ||
170 | driver->drv.name = driver->name; | ||
171 | |||
172 | return driver_register(&driver->drv); | ||
173 | } | ||
174 | EXPORT_SYMBOL(register_parisc_driver); | ||
175 | |||
176 | /** | ||
177 | * count_parisc_driver - count # of devices this driver would match | ||
178 | * @driver: the PA-RISC driver to try | ||
179 | * | ||
180 | * Use by IOMMU support to "guess" the right size IOPdir. | ||
181 | * Formula is something like memsize/(num_iommu * entry_size). | ||
182 | */ | ||
183 | int count_parisc_driver(struct parisc_driver *driver) | ||
184 | { | ||
185 | struct parisc_device *device; | ||
186 | int cnt = 0; | ||
187 | |||
188 | for_each_padev(device) { | ||
189 | if (match_device(driver, device)) | ||
190 | cnt++; | ||
191 | } | ||
192 | |||
193 | return cnt; | ||
194 | } | ||
195 | |||
196 | |||
197 | |||
198 | /** | ||
199 | * unregister_parisc_driver - Unregister this driver from the list of drivers | ||
200 | * @driver: the PA-RISC driver to unregister | ||
201 | */ | ||
202 | int unregister_parisc_driver(struct parisc_driver *driver) | ||
203 | { | ||
204 | driver_unregister(&driver->drv); | ||
205 | return 0; | ||
206 | } | ||
207 | EXPORT_SYMBOL(unregister_parisc_driver); | ||
208 | |||
209 | static struct parisc_device *find_device_by_addr(unsigned long hpa) | ||
210 | { | ||
211 | struct parisc_device *dev; | ||
212 | for_each_padev(dev) { | ||
213 | if (dev->hpa == hpa) | ||
214 | return dev; | ||
215 | } | ||
216 | return NULL; | ||
217 | } | ||
218 | |||
219 | /** | ||
220 | * find_pa_parent_type - Find a parent of a specific type | ||
221 | * @dev: The device to start searching from | ||
222 | * @type: The device type to search for. | ||
223 | * | ||
224 | * Walks up the device tree looking for a device of the specified type. | ||
225 | * If it finds it, it returns it. If not, it returns NULL. | ||
226 | */ | ||
227 | const struct parisc_device * | ||
228 | find_pa_parent_type(const struct parisc_device *padev, int type) | ||
229 | { | ||
230 | const struct device *dev = &padev->dev; | ||
231 | while (dev != &root) { | ||
232 | struct parisc_device *candidate = to_parisc_device(dev); | ||
233 | if (candidate->id.hw_type == type) | ||
234 | return candidate; | ||
235 | dev = dev->parent; | ||
236 | } | ||
237 | |||
238 | return NULL; | ||
239 | } | ||
240 | |||
241 | #ifdef CONFIG_PCI | ||
242 | static inline int is_pci_dev(struct device *dev) | ||
243 | { | ||
244 | return dev->bus == &pci_bus_type; | ||
245 | } | ||
246 | #else | ||
247 | static inline int is_pci_dev(struct device *dev) | ||
248 | { | ||
249 | return 0; | ||
250 | } | ||
251 | #endif | ||
252 | |||
253 | /* | ||
254 | * get_node_path fills in @path with the firmware path to the device. | ||
255 | * Note that if @node is a parisc device, we don't fill in the 'mod' field. | ||
256 | * This is because both callers pass the parent and fill in the mod | ||
257 | * themselves. If @node is a PCI device, we do fill it in, even though this | ||
258 | * is inconsistent. | ||
259 | */ | ||
260 | static void get_node_path(struct device *dev, struct hardware_path *path) | ||
261 | { | ||
262 | int i = 5; | ||
263 | memset(&path->bc, -1, 6); | ||
264 | |||
265 | if (is_pci_dev(dev)) { | ||
266 | unsigned int devfn = to_pci_dev(dev)->devfn; | ||
267 | path->mod = PCI_FUNC(devfn); | ||
268 | path->bc[i--] = PCI_SLOT(devfn); | ||
269 | dev = dev->parent; | ||
270 | } | ||
271 | |||
272 | while (dev != &root) { | ||
273 | if (is_pci_dev(dev)) { | ||
274 | unsigned int devfn = to_pci_dev(dev)->devfn; | ||
275 | path->bc[i--] = PCI_SLOT(devfn) | (PCI_FUNC(devfn)<< 5); | ||
276 | } else if (dev->bus == &parisc_bus_type) { | ||
277 | path->bc[i--] = to_parisc_device(dev)->hw_path; | ||
278 | } | ||
279 | dev = dev->parent; | ||
280 | } | ||
281 | } | ||
282 | |||
283 | static char *print_hwpath(struct hardware_path *path, char *output) | ||
284 | { | ||
285 | int i; | ||
286 | for (i = 0; i < 6; i++) { | ||
287 | if (path->bc[i] == -1) | ||
288 | continue; | ||
289 | output += sprintf(output, "%u/", (unsigned char) path->bc[i]); | ||
290 | } | ||
291 | output += sprintf(output, "%u", (unsigned char) path->mod); | ||
292 | return output; | ||
293 | } | ||
294 | |||
295 | /** | ||
296 | * print_pa_hwpath - Returns hardware path for PA devices | ||
297 | * dev: The device to return the path for | ||
298 | * output: Pointer to a previously-allocated array to place the path in. | ||
299 | * | ||
300 | * This function fills in the output array with a human-readable path | ||
301 | * to a PA device. This string is compatible with that used by PDC, and | ||
302 | * may be printed on the outside of the box. | ||
303 | */ | ||
304 | char *print_pa_hwpath(struct parisc_device *dev, char *output) | ||
305 | { | ||
306 | struct hardware_path path; | ||
307 | |||
308 | get_node_path(dev->dev.parent, &path); | ||
309 | path.mod = dev->hw_path; | ||
310 | return print_hwpath(&path, output); | ||
311 | } | ||
312 | EXPORT_SYMBOL(print_pa_hwpath); | ||
313 | |||
314 | #if defined(CONFIG_PCI) || defined(CONFIG_ISA) | ||
315 | /** | ||
316 | * get_pci_node_path - Determines the hardware path for a PCI device | ||
317 | * @pdev: The device to return the path for | ||
318 | * @path: Pointer to a previously-allocated array to place the path in. | ||
319 | * | ||
320 | * This function fills in the hardware_path structure with the route to | ||
321 | * the specified PCI device. This structure is suitable for passing to | ||
322 | * PDC calls. | ||
323 | */ | ||
324 | void get_pci_node_path(struct pci_dev *pdev, struct hardware_path *path) | ||
325 | { | ||
326 | get_node_path(&pdev->dev, path); | ||
327 | } | ||
328 | EXPORT_SYMBOL(get_pci_node_path); | ||
329 | |||
330 | /** | ||
331 | * print_pci_hwpath - Returns hardware path for PCI devices | ||
332 | * dev: The device to return the path for | ||
333 | * output: Pointer to a previously-allocated array to place the path in. | ||
334 | * | ||
335 | * This function fills in the output array with a human-readable path | ||
336 | * to a PCI device. This string is compatible with that used by PDC, and | ||
337 | * may be printed on the outside of the box. | ||
338 | */ | ||
339 | char *print_pci_hwpath(struct pci_dev *dev, char *output) | ||
340 | { | ||
341 | struct hardware_path path; | ||
342 | |||
343 | get_pci_node_path(dev, &path); | ||
344 | return print_hwpath(&path, output); | ||
345 | } | ||
346 | EXPORT_SYMBOL(print_pci_hwpath); | ||
347 | |||
348 | #endif /* defined(CONFIG_PCI) || defined(CONFIG_ISA) */ | ||
349 | |||
350 | static void setup_bus_id(struct parisc_device *padev) | ||
351 | { | ||
352 | struct hardware_path path; | ||
353 | char *output = padev->dev.bus_id; | ||
354 | int i; | ||
355 | |||
356 | get_node_path(padev->dev.parent, &path); | ||
357 | |||
358 | for (i = 0; i < 6; i++) { | ||
359 | if (path.bc[i] == -1) | ||
360 | continue; | ||
361 | output += sprintf(output, "%u:", (unsigned char) path.bc[i]); | ||
362 | } | ||
363 | sprintf(output, "%u", (unsigned char) padev->hw_path); | ||
364 | } | ||
365 | |||
366 | struct parisc_device * create_tree_node(char id, struct device *parent) | ||
367 | { | ||
368 | struct parisc_device *dev = kmalloc(sizeof(*dev), GFP_KERNEL); | ||
369 | if (!dev) | ||
370 | return NULL; | ||
371 | |||
372 | memset(dev, 0, sizeof(*dev)); | ||
373 | dev->hw_path = id; | ||
374 | dev->id.hw_type = HPHW_FAULTY; | ||
375 | |||
376 | dev->dev.parent = parent; | ||
377 | setup_bus_id(dev); | ||
378 | |||
379 | dev->dev.bus = &parisc_bus_type; | ||
380 | dev->dma_mask = 0xffffffffUL; /* PARISC devices are 32-bit */ | ||
381 | |||
382 | /* make the generic dma mask a pointer to the parisc one */ | ||
383 | dev->dev.dma_mask = &dev->dma_mask; | ||
384 | dev->dev.coherent_dma_mask = dev->dma_mask; | ||
385 | device_register(&dev->dev); | ||
386 | |||
387 | return dev; | ||
388 | } | ||
389 | |||
390 | /** | ||
391 | * alloc_tree_node - returns a device entry in the iotree | ||
392 | * @parent: the parent node in the tree | ||
393 | * @id: the element of the module path for this entry | ||
394 | * | ||
395 | * Checks all the children of @parent for a matching @id. If none | ||
396 | * found, it allocates a new device and returns it. | ||
397 | */ | ||
398 | static struct parisc_device * alloc_tree_node(struct device *parent, char id) | ||
399 | { | ||
400 | struct device *dev; | ||
401 | |||
402 | list_for_each_entry(dev, &parent->children, node) { | ||
403 | struct parisc_device *padev = to_parisc_device(dev); | ||
404 | if (padev->hw_path == id) | ||
405 | return padev; | ||
406 | } | ||
407 | |||
408 | return create_tree_node(id, parent); | ||
409 | } | ||
410 | |||
411 | static struct parisc_device *create_parisc_device(struct hardware_path *modpath) | ||
412 | { | ||
413 | int i; | ||
414 | struct device *parent = &root; | ||
415 | for (i = 0; i < 6; i++) { | ||
416 | if (modpath->bc[i] == -1) | ||
417 | continue; | ||
418 | parent = &alloc_tree_node(parent, modpath->bc[i])->dev; | ||
419 | } | ||
420 | return alloc_tree_node(parent, modpath->mod); | ||
421 | } | ||
422 | |||
423 | struct parisc_device * | ||
424 | alloc_pa_dev(unsigned long hpa, struct hardware_path *mod_path) | ||
425 | { | ||
426 | int status; | ||
427 | unsigned long bytecnt; | ||
428 | u8 iodc_data[32]; | ||
429 | struct parisc_device *dev; | ||
430 | const char *name; | ||
431 | |||
432 | /* Check to make sure this device has not already been added - Ryan */ | ||
433 | if (find_device_by_addr(hpa) != NULL) | ||
434 | return NULL; | ||
435 | |||
436 | status = pdc_iodc_read(&bytecnt, hpa, 0, &iodc_data, 32); | ||
437 | if (status != PDC_OK) | ||
438 | return NULL; | ||
439 | |||
440 | dev = create_parisc_device(mod_path); | ||
441 | if (dev->id.hw_type != HPHW_FAULTY) { | ||
442 | char p[64]; | ||
443 | print_pa_hwpath(dev, p); | ||
444 | printk("Two devices have hardware path %s. Please file a bug with HP.\n" | ||
445 | "In the meantime, you could try rearranging your cards.\n", p); | ||
446 | return NULL; | ||
447 | } | ||
448 | |||
449 | dev->id.hw_type = iodc_data[3] & 0x1f; | ||
450 | dev->id.hversion = (iodc_data[0] << 4) | ((iodc_data[1] & 0xf0) >> 4); | ||
451 | dev->id.hversion_rev = iodc_data[1] & 0x0f; | ||
452 | dev->id.sversion = ((iodc_data[4] & 0x0f) << 16) | | ||
453 | (iodc_data[5] << 8) | iodc_data[6]; | ||
454 | dev->hpa = hpa; | ||
455 | name = parisc_hardware_description(&dev->id); | ||
456 | if (name) { | ||
457 | strlcpy(dev->name, name, sizeof(dev->name)); | ||
458 | } | ||
459 | |||
460 | return dev; | ||
461 | } | ||
462 | |||
463 | static int parisc_generic_match(struct device *dev, struct device_driver *drv) | ||
464 | { | ||
465 | return match_device(to_parisc_driver(drv), to_parisc_device(dev)); | ||
466 | } | ||
467 | |||
468 | #define pa_dev_attr(name, field, format_string) \ | ||
469 | static ssize_t name##_show(struct device *dev, char *buf) \ | ||
470 | { \ | ||
471 | struct parisc_device *padev = to_parisc_device(dev); \ | ||
472 | return sprintf(buf, format_string, padev->field); \ | ||
473 | } | ||
474 | |||
475 | #define pa_dev_attr_id(field, format) pa_dev_attr(field, id.field, format) | ||
476 | |||
477 | pa_dev_attr(irq, irq, "%u\n"); | ||
478 | pa_dev_attr_id(hw_type, "0x%02x\n"); | ||
479 | pa_dev_attr(rev, id.hversion_rev, "0x%x\n"); | ||
480 | pa_dev_attr_id(hversion, "0x%03x\n"); | ||
481 | pa_dev_attr_id(sversion, "0x%05x\n"); | ||
482 | |||
483 | static struct device_attribute parisc_device_attrs[] = { | ||
484 | __ATTR_RO(irq), | ||
485 | __ATTR_RO(hw_type), | ||
486 | __ATTR_RO(rev), | ||
487 | __ATTR_RO(hversion), | ||
488 | __ATTR_RO(sversion), | ||
489 | __ATTR_NULL, | ||
490 | }; | ||
491 | |||
492 | struct bus_type parisc_bus_type = { | ||
493 | .name = "parisc", | ||
494 | .match = parisc_generic_match, | ||
495 | .dev_attrs = parisc_device_attrs, | ||
496 | }; | ||
497 | |||
498 | /** | ||
499 | * register_parisc_device - Locate a driver to manage this device. | ||
500 | * @dev: The parisc device. | ||
501 | * | ||
502 | * Search the driver list for a driver that is willing to manage | ||
503 | * this device. | ||
504 | */ | ||
505 | int register_parisc_device(struct parisc_device *dev) | ||
506 | { | ||
507 | if (!dev) | ||
508 | return 0; | ||
509 | |||
510 | if (dev->driver) | ||
511 | return 1; | ||
512 | |||
513 | return 0; | ||
514 | } | ||
515 | |||
516 | /** | ||
517 | * match_pci_device - Matches a pci device against a given hardware path | ||
518 | * entry. | ||
519 | * @dev: the generic device (known to be contained by a pci_dev). | ||
520 | * @index: the current BC index | ||
521 | * @modpath: the hardware path. | ||
522 | * @return: true if the device matches the hardware path. | ||
523 | */ | ||
524 | static int match_pci_device(struct device *dev, int index, | ||
525 | struct hardware_path *modpath) | ||
526 | { | ||
527 | struct pci_dev *pdev = to_pci_dev(dev); | ||
528 | int id; | ||
529 | |||
530 | if (index == 5) { | ||
531 | /* we are at the end of the path, and on the actual device */ | ||
532 | unsigned int devfn = pdev->devfn; | ||
533 | return ((modpath->bc[5] == PCI_SLOT(devfn)) && | ||
534 | (modpath->mod == PCI_FUNC(devfn))); | ||
535 | } | ||
536 | |||
537 | id = PCI_SLOT(pdev->devfn) | (PCI_FUNC(pdev->devfn) << 5); | ||
538 | return (modpath->bc[index] == id); | ||
539 | } | ||
540 | |||
541 | /** | ||
542 | * match_parisc_device - Matches a parisc device against a given hardware | ||
543 | * path entry. | ||
544 | * @dev: the generic device (known to be contained by a parisc_device). | ||
545 | * @index: the current BC index | ||
546 | * @modpath: the hardware path. | ||
547 | * @return: true if the device matches the hardware path. | ||
548 | */ | ||
549 | static int match_parisc_device(struct device *dev, int index, | ||
550 | struct hardware_path *modpath) | ||
551 | { | ||
552 | struct parisc_device *curr = to_parisc_device(dev); | ||
553 | char id = (index == 6) ? modpath->mod : modpath->bc[index]; | ||
554 | |||
555 | return (curr->hw_path == id); | ||
556 | } | ||
557 | |||
558 | /** | ||
559 | * parse_tree_node - returns a device entry in the iotree | ||
560 | * @parent: the parent node in the tree | ||
561 | * @index: the current BC index | ||
562 | * @modpath: the hardware_path struct to match a device against | ||
563 | * @return: The corresponding device if found, NULL otherwise. | ||
564 | * | ||
565 | * Checks all the children of @parent for a matching @id. If none | ||
566 | * found, it returns NULL. | ||
567 | */ | ||
568 | static struct device * | ||
569 | parse_tree_node(struct device *parent, int index, struct hardware_path *modpath) | ||
570 | { | ||
571 | struct device *device; | ||
572 | |||
573 | list_for_each_entry(device, &parent->children, node) { | ||
574 | if (device->bus == &parisc_bus_type) { | ||
575 | if (match_parisc_device(device, index, modpath)) | ||
576 | return device; | ||
577 | } else if (is_pci_dev(device)) { | ||
578 | if (match_pci_device(device, index, modpath)) | ||
579 | return device; | ||
580 | } else if (device->bus == NULL) { | ||
581 | /* we are on a bus bridge */ | ||
582 | struct device *new = parse_tree_node(device, index, modpath); | ||
583 | if (new) | ||
584 | return new; | ||
585 | } | ||
586 | } | ||
587 | |||
588 | return NULL; | ||
589 | } | ||
590 | |||
591 | /** | ||
592 | * hwpath_to_device - Finds the generic device corresponding to a given hardware path. | ||
593 | * @modpath: the hardware path. | ||
594 | * @return: The target device, NULL if not found. | ||
595 | */ | ||
596 | struct device *hwpath_to_device(struct hardware_path *modpath) | ||
597 | { | ||
598 | int i; | ||
599 | struct device *parent = &root; | ||
600 | for (i = 0; i < 6; i++) { | ||
601 | if (modpath->bc[i] == -1) | ||
602 | continue; | ||
603 | parent = parse_tree_node(parent, i, modpath); | ||
604 | if (!parent) | ||
605 | return NULL; | ||
606 | } | ||
607 | if (is_pci_dev(parent)) /* pci devices already parse MOD */ | ||
608 | return parent; | ||
609 | else | ||
610 | return parse_tree_node(parent, 6, modpath); | ||
611 | } | ||
612 | EXPORT_SYMBOL(hwpath_to_device); | ||
613 | |||
614 | /** | ||
615 | * device_to_hwpath - Populates the hwpath corresponding to the given device. | ||
616 | * @param dev the target device | ||
617 | * @param path pointer to a previously allocated hwpath struct to be filled in | ||
618 | */ | ||
619 | void device_to_hwpath(struct device *dev, struct hardware_path *path) | ||
620 | { | ||
621 | struct parisc_device *padev; | ||
622 | if (dev->bus == &parisc_bus_type) { | ||
623 | padev = to_parisc_device(dev); | ||
624 | get_node_path(dev->parent, path); | ||
625 | path->mod = padev->hw_path; | ||
626 | } else if (is_pci_dev(dev)) { | ||
627 | get_node_path(dev, path); | ||
628 | } | ||
629 | } | ||
630 | EXPORT_SYMBOL(device_to_hwpath); | ||
631 | |||
632 | #define BC_PORT_MASK 0x8 | ||
633 | #define BC_LOWER_PORT 0x8 | ||
634 | |||
635 | #define BUS_CONVERTER(dev) \ | ||
636 | ((dev->id.hw_type == HPHW_IOA) || (dev->id.hw_type == HPHW_BCPORT)) | ||
637 | |||
638 | #define IS_LOWER_PORT(dev) \ | ||
639 | ((gsc_readl(dev->hpa + offsetof(struct bc_module, io_status)) \ | ||
640 | & BC_PORT_MASK) == BC_LOWER_PORT) | ||
641 | |||
642 | #define MAX_NATIVE_DEVICES 64 | ||
643 | #define NATIVE_DEVICE_OFFSET 0x1000 | ||
644 | |||
645 | #define FLEX_MASK F_EXTEND(0xfffc0000) | ||
646 | #define IO_IO_LOW offsetof(struct bc_module, io_io_low) | ||
647 | #define IO_IO_HIGH offsetof(struct bc_module, io_io_high) | ||
648 | #define READ_IO_IO_LOW(dev) (unsigned long)(signed int)gsc_readl(dev->hpa + IO_IO_LOW) | ||
649 | #define READ_IO_IO_HIGH(dev) (unsigned long)(signed int)gsc_readl(dev->hpa + IO_IO_HIGH) | ||
650 | |||
651 | static void walk_native_bus(unsigned long io_io_low, unsigned long io_io_high, | ||
652 | struct device *parent); | ||
653 | |||
654 | void walk_lower_bus(struct parisc_device *dev) | ||
655 | { | ||
656 | unsigned long io_io_low, io_io_high; | ||
657 | |||
658 | if(!BUS_CONVERTER(dev) || IS_LOWER_PORT(dev)) | ||
659 | return; | ||
660 | |||
661 | if(dev->id.hw_type == HPHW_IOA) { | ||
662 | io_io_low = (unsigned long)(signed int)(READ_IO_IO_LOW(dev) << 16); | ||
663 | io_io_high = io_io_low + MAX_NATIVE_DEVICES * NATIVE_DEVICE_OFFSET; | ||
664 | } else { | ||
665 | io_io_low = (READ_IO_IO_LOW(dev) + ~FLEX_MASK) & FLEX_MASK; | ||
666 | io_io_high = (READ_IO_IO_HIGH(dev)+ ~FLEX_MASK) & FLEX_MASK; | ||
667 | } | ||
668 | |||
669 | walk_native_bus(io_io_low, io_io_high, &dev->dev); | ||
670 | } | ||
671 | |||
672 | /** | ||
673 | * walk_native_bus -- Probe a bus for devices | ||
674 | * @io_io_low: Base address of this bus. | ||
675 | * @io_io_high: Last address of this bus. | ||
676 | * @parent: The parent bus device. | ||
677 | * | ||
678 | * A native bus (eg Runway or GSC) may have up to 64 devices on it, | ||
679 | * spaced at intervals of 0x1000 bytes. PDC may not inform us of these | ||
680 | * devices, so we have to probe for them. Unfortunately, we may find | ||
681 | * devices which are not physically connected (such as extra serial & | ||
682 | * keyboard ports). This problem is not yet solved. | ||
683 | */ | ||
684 | static void walk_native_bus(unsigned long io_io_low, unsigned long io_io_high, | ||
685 | struct device *parent) | ||
686 | { | ||
687 | int i, devices_found = 0; | ||
688 | unsigned long hpa = io_io_low; | ||
689 | struct hardware_path path; | ||
690 | |||
691 | get_node_path(parent, &path); | ||
692 | do { | ||
693 | for(i = 0; i < MAX_NATIVE_DEVICES; i++, hpa += NATIVE_DEVICE_OFFSET) { | ||
694 | struct parisc_device *dev; | ||
695 | |||
696 | /* Was the device already added by Firmware? */ | ||
697 | dev = find_device_by_addr(hpa); | ||
698 | if (!dev) { | ||
699 | path.mod = i; | ||
700 | dev = alloc_pa_dev(hpa, &path); | ||
701 | if (!dev) | ||
702 | continue; | ||
703 | |||
704 | register_parisc_device(dev); | ||
705 | devices_found++; | ||
706 | } | ||
707 | walk_lower_bus(dev); | ||
708 | } | ||
709 | } while(!devices_found && hpa < io_io_high); | ||
710 | } | ||
711 | |||
712 | #define CENTRAL_BUS_ADDR F_EXTEND(0xfff80000) | ||
713 | |||
714 | /** | ||
715 | * walk_central_bus - Find devices attached to the central bus | ||
716 | * | ||
717 | * PDC doesn't tell us about all devices in the system. This routine | ||
718 | * finds devices connected to the central bus. | ||
719 | */ | ||
720 | void walk_central_bus(void) | ||
721 | { | ||
722 | walk_native_bus(CENTRAL_BUS_ADDR, | ||
723 | CENTRAL_BUS_ADDR + (MAX_NATIVE_DEVICES * NATIVE_DEVICE_OFFSET), | ||
724 | &root); | ||
725 | } | ||
726 | |||
727 | static void print_parisc_device(struct parisc_device *dev) | ||
728 | { | ||
729 | char hw_path[64]; | ||
730 | static int count; | ||
731 | |||
732 | print_pa_hwpath(dev, hw_path); | ||
733 | printk(KERN_INFO "%d. %s at 0x%lx [%s] { %d, 0x%x, 0x%.3x, 0x%.5x }", | ||
734 | ++count, dev->name, dev->hpa, hw_path, dev->id.hw_type, | ||
735 | dev->id.hversion_rev, dev->id.hversion, dev->id.sversion); | ||
736 | |||
737 | if (dev->num_addrs) { | ||
738 | int k; | ||
739 | printk(", additional addresses: "); | ||
740 | for (k = 0; k < dev->num_addrs; k++) | ||
741 | printk("0x%lx ", dev->addr[k]); | ||
742 | } | ||
743 | printk("\n"); | ||
744 | } | ||
745 | |||
746 | /** | ||
747 | * init_parisc_bus - Some preparation to be done before inventory | ||
748 | */ | ||
749 | void init_parisc_bus(void) | ||
750 | { | ||
751 | bus_register(&parisc_bus_type); | ||
752 | device_register(&root); | ||
753 | get_device(&root); | ||
754 | } | ||
755 | |||
756 | /** | ||
757 | * print_parisc_devices - Print out a list of devices found in this system | ||
758 | */ | ||
759 | void print_parisc_devices(void) | ||
760 | { | ||
761 | struct parisc_device *dev; | ||
762 | for_each_padev(dev) { | ||
763 | print_parisc_device(dev); | ||
764 | } | ||
765 | } | ||