isa.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  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. struct sparc_isa_bridge *isa_chain;
  8. static void __init fatal_err(const char *reason)
  9. {
  10. prom_printf("ISA: fatal error, %s.\n", reason);
  11. }
  12. static void __init report_dev(struct sparc_isa_device *isa_dev, int child)
  13. {
  14. if (child)
  15. printk(" (%s)", isa_dev->prom_node->name);
  16. else
  17. printk(" [%s", isa_dev->prom_node->name);
  18. }
  19. static struct linux_prom_registers * __init
  20. isa_dev_get_resource(struct sparc_isa_device *isa_dev)
  21. {
  22. struct linux_prom_registers *pregs;
  23. unsigned long base, len;
  24. int prop_len;
  25. pregs = of_get_property(isa_dev->prom_node, "reg", &prop_len);
  26. /* Only the first one is interesting. */
  27. len = pregs[0].reg_size;
  28. base = (((unsigned long)pregs[0].which_io << 32) |
  29. (unsigned long)pregs[0].phys_addr);
  30. base += isa_dev->bus->parent->io_space.start;
  31. isa_dev->resource.start = base;
  32. isa_dev->resource.end = (base + len - 1UL);
  33. isa_dev->resource.flags = IORESOURCE_IO;
  34. isa_dev->resource.name = isa_dev->prom_node->name;
  35. request_resource(&isa_dev->bus->parent->io_space,
  36. &isa_dev->resource);
  37. return pregs;
  38. }
  39. /* I can't believe they didn't put a real INO in the isa device
  40. * interrupts property. The whole point of the OBP properties
  41. * is to shield the kernel from IRQ routing details.
  42. *
  43. * The P1275 standard for ISA devices seems to also have been
  44. * totally ignored.
  45. *
  46. * On later systems, an interrupt-map and interrupt-map-mask scheme
  47. * akin to EBUS is used.
  48. */
  49. static struct {
  50. int obp_irq;
  51. int pci_ino;
  52. } grover_irq_table[] = {
  53. { 1, 0x00 }, /* dma, unknown ino at this point */
  54. { 2, 0x27 }, /* floppy */
  55. { 3, 0x22 }, /* parallel */
  56. { 4, 0x2b }, /* serial */
  57. { 5, 0x25 }, /* acpi power management */
  58. { 0, 0x00 } /* end of table */
  59. };
  60. static int __init isa_dev_get_irq_using_imap(struct sparc_isa_device *isa_dev,
  61. struct sparc_isa_bridge *isa_br,
  62. int *interrupt,
  63. struct linux_prom_registers *pregs)
  64. {
  65. unsigned int hi, lo, irq;
  66. int i;
  67. hi = pregs->which_io & isa_br->isa_intmask.phys_hi;
  68. lo = pregs->phys_addr & isa_br->isa_intmask.phys_lo;
  69. irq = *interrupt & isa_br->isa_intmask.interrupt;
  70. for (i = 0; i < isa_br->num_isa_intmap; i++) {
  71. if ((isa_br->isa_intmap[i].phys_hi == hi) &&
  72. (isa_br->isa_intmap[i].phys_lo == lo) &&
  73. (isa_br->isa_intmap[i].interrupt == irq)) {
  74. *interrupt = isa_br->isa_intmap[i].cinterrupt;
  75. return 0;
  76. }
  77. }
  78. return -1;
  79. }
  80. static void __init isa_dev_get_irq(struct sparc_isa_device *isa_dev,
  81. struct linux_prom_registers *pregs)
  82. {
  83. int irq_prop;
  84. irq_prop = of_getintprop_default(isa_dev->prom_node,
  85. "interrupts", -1);
  86. if (irq_prop <= 0) {
  87. goto no_irq;
  88. } else {
  89. struct pci_controller_info *pcic;
  90. struct pci_pbm_info *pbm;
  91. int i;
  92. if (isa_dev->bus->num_isa_intmap) {
  93. if (!isa_dev_get_irq_using_imap(isa_dev,
  94. isa_dev->bus,
  95. &irq_prop,
  96. pregs))
  97. goto route_irq;
  98. }
  99. for (i = 0; grover_irq_table[i].obp_irq != 0; i++) {
  100. if (grover_irq_table[i].obp_irq == irq_prop) {
  101. int ino = grover_irq_table[i].pci_ino;
  102. if (ino == 0)
  103. goto no_irq;
  104. irq_prop = ino;
  105. goto route_irq;
  106. }
  107. }
  108. goto no_irq;
  109. route_irq:
  110. pbm = isa_dev->bus->parent;
  111. pcic = pbm->parent;
  112. isa_dev->irq = pcic->irq_build(pbm, NULL, irq_prop);
  113. return;
  114. }
  115. no_irq:
  116. isa_dev->irq = PCI_IRQ_NONE;
  117. }
  118. static void __init isa_fill_children(struct sparc_isa_device *parent_isa_dev)
  119. {
  120. struct device_node *dp = parent_isa_dev->prom_node->child;
  121. if (!dp)
  122. return;
  123. printk(" ->");
  124. while (dp) {
  125. struct linux_prom_registers *regs;
  126. struct sparc_isa_device *isa_dev;
  127. isa_dev = kmalloc(sizeof(*isa_dev), GFP_KERNEL);
  128. if (!isa_dev) {
  129. fatal_err("cannot allocate child isa_dev");
  130. prom_halt();
  131. }
  132. memset(isa_dev, 0, sizeof(*isa_dev));
  133. /* Link it in to parent. */
  134. isa_dev->next = parent_isa_dev->child;
  135. parent_isa_dev->child = isa_dev;
  136. isa_dev->bus = parent_isa_dev->bus;
  137. isa_dev->prom_node = dp;
  138. regs = isa_dev_get_resource(isa_dev);
  139. isa_dev_get_irq(isa_dev, regs);
  140. report_dev(isa_dev, 1);
  141. dp = dp->sibling;
  142. }
  143. }
  144. static void __init isa_fill_devices(struct sparc_isa_bridge *isa_br)
  145. {
  146. struct device_node *dp = isa_br->prom_node->child;
  147. while (dp) {
  148. struct linux_prom_registers *regs;
  149. struct sparc_isa_device *isa_dev;
  150. isa_dev = kmalloc(sizeof(*isa_dev), GFP_KERNEL);
  151. if (!isa_dev) {
  152. fatal_err("cannot allocate isa_dev");
  153. prom_halt();
  154. }
  155. memset(isa_dev, 0, sizeof(*isa_dev));
  156. /* Link it in. */
  157. isa_dev->next = NULL;
  158. if (isa_br->devices == NULL) {
  159. isa_br->devices = isa_dev;
  160. } else {
  161. struct sparc_isa_device *tmp = isa_br->devices;
  162. while (tmp->next)
  163. tmp = tmp->next;
  164. tmp->next = isa_dev;
  165. }
  166. isa_dev->bus = isa_br;
  167. isa_dev->prom_node = dp;
  168. regs = isa_dev_get_resource(isa_dev);
  169. isa_dev_get_irq(isa_dev, regs);
  170. report_dev(isa_dev, 0);
  171. isa_fill_children(isa_dev);
  172. printk("]");
  173. dp = dp->sibling;
  174. }
  175. }
  176. static void __init get_bridge_props(struct sparc_isa_bridge *isa_br)
  177. {
  178. struct device_node *dp = isa_br->prom_node;
  179. void *pval;
  180. int len;
  181. pval = of_get_property(dp, "ranges", &len);
  182. if (pval) {
  183. memcpy(isa_br->isa_ranges, pval, len);
  184. isa_br->num_isa_ranges =
  185. len / sizeof(struct linux_prom_isa_ranges);
  186. } else {
  187. isa_br->num_isa_ranges = 0;
  188. }
  189. pval = of_get_property(dp, "interrupt-map", &len);
  190. if (pval) {
  191. memcpy(isa_br->isa_intmap, pval, len);
  192. isa_br->num_isa_intmap =
  193. (len / sizeof(struct linux_prom_isa_intmap));
  194. } else {
  195. isa_br->num_isa_intmap = 0;
  196. }
  197. pval = of_get_property(dp, "interrupt-map-mask", &len);
  198. if (pval)
  199. memcpy(&isa_br->isa_intmask, pval,
  200. sizeof(isa_br->isa_intmask));
  201. }
  202. void __init isa_init(void)
  203. {
  204. struct pci_dev *pdev;
  205. unsigned short vendor, device;
  206. int index = 0;
  207. vendor = PCI_VENDOR_ID_AL;
  208. device = PCI_DEVICE_ID_AL_M1533;
  209. pdev = NULL;
  210. while ((pdev = pci_get_device(vendor, device, pdev)) != NULL) {
  211. struct pcidev_cookie *pdev_cookie;
  212. struct pci_pbm_info *pbm;
  213. struct sparc_isa_bridge *isa_br;
  214. pdev_cookie = pdev->sysdata;
  215. if (!pdev_cookie) {
  216. printk("ISA: Warning, ISA bridge ignored due to "
  217. "lack of OBP data.\n");
  218. continue;
  219. }
  220. pbm = pdev_cookie->pbm;
  221. isa_br = kmalloc(sizeof(*isa_br), GFP_KERNEL);
  222. if (!isa_br) {
  223. fatal_err("cannot allocate sparc_isa_bridge");
  224. prom_halt();
  225. }
  226. memset(isa_br, 0, sizeof(*isa_br));
  227. /* Link it in. */
  228. isa_br->next = isa_chain;
  229. isa_chain = isa_br;
  230. isa_br->parent = pbm;
  231. isa_br->self = pdev;
  232. isa_br->index = index++;
  233. isa_br->prom_node = pdev_cookie->prom_node;
  234. get_bridge_props(isa_br);
  235. printk("isa%d:", isa_br->index);
  236. isa_fill_devices(isa_br);
  237. printk("\n");
  238. }
  239. }