ebus.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:10k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /* $Id: ebus.c,v 1.64.2.1 2002/03/12 18:46:14 davem Exp $
  2.  * ebus.c: PCI to EBus bridge device.
  3.  *
  4.  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
  5.  * Copyright (C) 1999  David S. Miller (davem@redhat.com)
  6.  */
  7. #include <linux/config.h>
  8. #include <linux/kernel.h>
  9. #include <linux/types.h>
  10. #include <linux/init.h>
  11. #include <linux/slab.h>
  12. #include <linux/string.h>
  13. #include <asm/system.h>
  14. #include <asm/page.h>
  15. #include <asm/pbm.h>
  16. #include <asm/ebus.h>
  17. #include <asm/oplib.h>
  18. #include <asm/bpp.h>
  19. #include <asm/irq.h>
  20. struct linux_ebus *ebus_chain = 0;
  21. #ifdef CONFIG_SUN_AUXIO
  22. extern void auxio_probe(void);
  23. #endif
  24. static inline void *ebus_alloc(size_t size)
  25. {
  26. void *mem;
  27. mem = kmalloc(size, GFP_ATOMIC);
  28. if (!mem)
  29. panic("ebus_alloc: out of memory");
  30. memset((char *)mem, 0, size);
  31. return mem;
  32. }
  33. static void __init ebus_ranges_init(struct linux_ebus *ebus)
  34. {
  35. int success;
  36. ebus->num_ebus_ranges = 0;
  37. success = prom_getproperty(ebus->prom_node, "ranges",
  38.    (char *)ebus->ebus_ranges,
  39.    sizeof(ebus->ebus_ranges));
  40. if (success != -1)
  41. ebus->num_ebus_ranges = (success/sizeof(struct linux_prom_ebus_ranges));
  42. }
  43. static void __init ebus_intmap_init(struct linux_ebus *ebus)
  44. {
  45. int success;
  46. ebus->num_ebus_intmap = 0;
  47. success = prom_getproperty(ebus->prom_node, "interrupt-map",
  48.    (char *)ebus->ebus_intmap,
  49.    sizeof(ebus->ebus_intmap));
  50. if (success == -1)
  51. return;
  52. ebus->num_ebus_intmap = (success/sizeof(struct linux_prom_ebus_intmap));
  53. success = prom_getproperty(ebus->prom_node, "interrupt-map-mask",
  54.    (char *)&ebus->ebus_intmask,
  55.    sizeof(ebus->ebus_intmask));
  56. if (success == -1) {
  57. prom_printf("ebus: can't get interrupt-map-maskn");
  58. prom_halt();
  59. }
  60. }
  61. int __init ebus_intmap_match(struct linux_ebus *ebus,
  62.      struct linux_prom_registers *reg,
  63.      int *interrupt)
  64. {
  65. unsigned int hi, lo, irq;
  66. int i;
  67. if (!ebus->num_ebus_intmap)
  68. return 0;
  69. hi = reg->which_io & ebus->ebus_intmask.phys_hi;
  70. lo = reg->phys_addr & ebus->ebus_intmask.phys_lo;
  71. irq = *interrupt & ebus->ebus_intmask.interrupt;
  72. for (i = 0; i < ebus->num_ebus_intmap; i++) {
  73. if ((ebus->ebus_intmap[i].phys_hi == hi) &&
  74.     (ebus->ebus_intmap[i].phys_lo == lo) &&
  75.     (ebus->ebus_intmap[i].interrupt == irq)) {
  76. *interrupt = ebus->ebus_intmap[i].cinterrupt;
  77. return 0;
  78. }
  79. }
  80. return -1;
  81. }
  82. void __init fill_ebus_child(int node, struct linux_prom_registers *preg,
  83.     struct linux_ebus_child *dev, int non_standard_regs)
  84. {
  85. int regs[PROMREG_MAX];
  86. int irqs[PROMREG_MAX];
  87. int i, len;
  88. dev->prom_node = node;
  89. prom_getstring(node, "name", dev->prom_name, sizeof(dev->prom_name));
  90. printk(" (%s)", dev->prom_name);
  91. len = prom_getproperty(node, "reg", (void *)regs, sizeof(regs));
  92. dev->num_addrs = len / sizeof(regs[0]);
  93. if (non_standard_regs) {
  94. /* This is to handle reg properties which are not
  95.  * in the parent relative format.  One example are
  96.  * children of the i2c device on CompactPCI systems.
  97.  *
  98.  * So, for such devices we just record the property
  99.  * raw in the child resources.
  100.  */
  101. for (i = 0; i < dev->num_addrs; i++)
  102. dev->resource[i].start = regs[i];
  103. } else {
  104. for (i = 0; i < dev->num_addrs; i++) {
  105. int rnum = regs[i];
  106. if (rnum >= dev->parent->num_addrs) {
  107. prom_printf("UGH: property for %s was %d, need < %dn",
  108.     dev->prom_name, len, dev->parent->num_addrs);
  109. panic("fill_ebus_child");
  110. }
  111. dev->resource[i].start = dev->parent->resource[i].start;
  112. dev->resource[i].end = dev->parent->resource[i].end;
  113. dev->resource[i].flags = IORESOURCE_MEM;
  114. dev->resource[i].name = dev->prom_name;
  115. }
  116. }
  117. for (i = 0; i < PROMINTR_MAX; i++)
  118. dev->irqs[i] = PCI_IRQ_NONE;
  119. len = prom_getproperty(node, "interrupts", (char *)&irqs, sizeof(irqs));
  120. if ((len == -1) || (len == 0)) {
  121. dev->num_irqs = 0;
  122. /*
  123.  * Oh, well, some PROMs don't export interrupts
  124.  * property to children of EBus devices...
  125.  *
  126.  * Be smart about PS/2 keyboard and mouse.
  127.  */
  128. if (!strcmp(dev->parent->prom_name, "8042")) {
  129. if (!strcmp(dev->prom_name, "kb_ps2")) {
  130. dev->num_irqs = 1;
  131. dev->irqs[0] = dev->parent->irqs[0];
  132. } else {
  133. dev->num_irqs = 1;
  134. dev->irqs[0] = dev->parent->irqs[1];
  135. }
  136. }
  137. } else {
  138. dev->num_irqs = len / sizeof(irqs[0]);
  139. for (i = 0; i < dev->num_irqs; i++) {
  140. struct pci_pbm_info *pbm = dev->bus->parent;
  141. struct pci_controller_info *p = pbm->parent;
  142. if (ebus_intmap_match(dev->bus, preg, &irqs[i]) != -1) {
  143. dev->irqs[i] = p->irq_build(pbm,
  144.     dev->bus->self,
  145.     irqs[i]);
  146. } else {
  147. /* If we get a bogus interrupt property, just
  148.  * record the raw value instead of punting.
  149.  */
  150. dev->irqs[i] = irqs[i];
  151. }
  152. }
  153. }
  154. }
  155. static int __init child_regs_nonstandard(struct linux_ebus_device *dev)
  156. {
  157. if (!strcmp(dev->prom_name, "i2c"))
  158. return 1;
  159. return 0;
  160. }
  161. void __init fill_ebus_device(int node, struct linux_ebus_device *dev)
  162. {
  163. struct linux_prom_registers regs[PROMREG_MAX];
  164. struct linux_ebus_child *child;
  165. int irqs[PROMINTR_MAX];
  166. int i, n, len;
  167. dev->prom_node = node;
  168. prom_getstring(node, "name", dev->prom_name, sizeof(dev->prom_name));
  169. printk(" [%s", dev->prom_name);
  170. len = prom_getproperty(node, "reg", (void *)regs, sizeof(regs));
  171. if (len == -1) {
  172. dev->num_addrs = 0;
  173. goto probe_interrupts;
  174. }
  175. if (len % sizeof(struct linux_prom_registers)) {
  176. prom_printf("UGH: proplen for %s was %d, need multiple of %dn",
  177.     dev->prom_name, len,
  178.     (int)sizeof(struct linux_prom_registers));
  179. prom_halt();
  180. }
  181. dev->num_addrs = len / sizeof(struct linux_prom_registers);
  182. for (i = 0; i < dev->num_addrs; i++) {
  183. /* XXX Learn how to interpret ebus ranges... -DaveM */
  184. if (regs[i].which_io >= 0x10)
  185. n = (regs[i].which_io - 0x10) >> 2;
  186. else
  187. n = regs[i].which_io;
  188. dev->resource[i].start  = dev->bus->self->resource[n].start;
  189. dev->resource[i].start += (unsigned long)regs[i].phys_addr;
  190. dev->resource[i].end    =
  191. (dev->resource[i].start + (unsigned long)regs[i].reg_size - 1UL);
  192. dev->resource[i].flags  = IORESOURCE_MEM;
  193. dev->resource[i].name   = dev->prom_name;
  194. request_resource(&dev->bus->self->resource[n],
  195.  &dev->resource[i]);
  196. }
  197. probe_interrupts:
  198. for (i = 0; i < PROMINTR_MAX; i++)
  199. dev->irqs[i] = PCI_IRQ_NONE;
  200. len = prom_getproperty(node, "interrupts", (char *)&irqs, sizeof(irqs));
  201. if ((len == -1) || (len == 0)) {
  202. dev->num_irqs = 0;
  203. } else {
  204. dev->num_irqs = len / sizeof(irqs[0]);
  205. for (i = 0; i < dev->num_irqs; i++) {
  206. struct pci_pbm_info *pbm = dev->bus->parent;
  207. struct pci_controller_info *p = pbm->parent;
  208. if (ebus_intmap_match(dev->bus, &regs[0], &irqs[i]) != -1) {
  209. dev->irqs[i] = p->irq_build(pbm,
  210.     dev->bus->self,
  211.     irqs[i]);
  212. } else {
  213. /* If we get a bogus interrupt property, just
  214.  * record the raw value instead of punting.
  215.  */
  216. dev->irqs[i] = irqs[i];
  217. }
  218. }
  219. }
  220. if ((node = prom_getchild(node))) {
  221. printk(" ->");
  222. dev->children = ebus_alloc(sizeof(struct linux_ebus_child));
  223. child = dev->children;
  224. child->next = 0;
  225. child->parent = dev;
  226. child->bus = dev->bus;
  227. fill_ebus_child(node, &regs[0],
  228. child, child_regs_nonstandard(dev));
  229. while ((node = prom_getsibling(node))) {
  230. child->next = ebus_alloc(sizeof(struct linux_ebus_child));
  231. child = child->next;
  232. child->next = 0;
  233. child->parent = dev;
  234. child->bus = dev->bus;
  235. fill_ebus_child(node, &regs[0],
  236. child, child_regs_nonstandard(dev));
  237. }
  238. }
  239. printk("]");
  240. }
  241. static struct pci_dev *find_next_ebus(struct pci_dev *start, int *is_rio_p)
  242. {
  243. struct pci_dev *pdev = start;
  244. do {
  245. pdev = pci_find_device(PCI_VENDOR_ID_SUN, PCI_ANY_ID, pdev);
  246. if (pdev &&
  247.     (pdev->device == PCI_DEVICE_ID_SUN_EBUS ||
  248.      pdev->device == PCI_DEVICE_ID_SUN_RIO_EBUS))
  249. break;
  250. } while (pdev != NULL);
  251. if (pdev && (pdev->device == PCI_DEVICE_ID_SUN_RIO_EBUS))
  252. *is_rio_p = 1;
  253. else
  254. *is_rio_p = 0;
  255. return pdev;
  256. }
  257. void __init ebus_init(void)
  258. {
  259. struct pci_pbm_info *pbm;
  260. struct linux_ebus_device *dev;
  261. struct linux_ebus *ebus;
  262. struct pci_dev *pdev;
  263. struct pcidev_cookie *cookie;
  264. int nd, ebusnd, is_rio;
  265. int num_ebus = 0;
  266. if (!pci_present())
  267. return;
  268. pdev = find_next_ebus(NULL, &is_rio);
  269. if (!pdev) {
  270. printk("ebus: No EBus's found.n");
  271. return;
  272. }
  273. cookie = pdev->sysdata;
  274. ebusnd = cookie->prom_node;
  275. ebus_chain = ebus = ebus_alloc(sizeof(struct linux_ebus));
  276. ebus->next = 0;
  277. ebus->is_rio = is_rio;
  278. while (ebusnd) {
  279. /* SUNW,pci-qfe uses four empty ebuses on it.
  280.    I think we should not consider them here,
  281.    as they have half of the properties this
  282.    code expects and once we do PCI hot-plug,
  283.    we'd have to tweak with the ebus_chain
  284.    in the runtime after initialization. -jj */
  285. if (!prom_getchild (ebusnd)) {
  286. pdev = find_next_ebus(pdev, &is_rio);
  287. if (!pdev) {
  288. if (ebus == ebus_chain) {
  289. ebus_chain = NULL;
  290. printk("ebus: No EBus's found.n");
  291. return;
  292. }
  293. break;
  294. }
  295. ebus->is_rio = is_rio;
  296. cookie = pdev->sysdata;
  297. ebusnd = cookie->prom_node;
  298. continue;
  299. }
  300. printk("ebus%d:", num_ebus);
  301. prom_getstring(ebusnd, "name", ebus->prom_name, sizeof(ebus->prom_name));
  302. ebus->index = num_ebus;
  303. ebus->prom_node = ebusnd;
  304. ebus->self = pdev;
  305. ebus->parent = pbm = cookie->pbm;
  306. ebus_ranges_init(ebus);
  307. ebus_intmap_init(ebus);
  308. nd = prom_getchild(ebusnd);
  309. if (!nd)
  310. goto next_ebus;
  311. ebus->devices = ebus_alloc(sizeof(struct linux_ebus_device));
  312. dev = ebus->devices;
  313. dev->next = 0;
  314. dev->children = 0;
  315. dev->bus = ebus;
  316. fill_ebus_device(nd, dev);
  317. while ((nd = prom_getsibling(nd))) {
  318. dev->next = ebus_alloc(sizeof(struct linux_ebus_device));
  319. dev = dev->next;
  320. dev->next = 0;
  321. dev->children = 0;
  322. dev->bus = ebus;
  323. fill_ebus_device(nd, dev);
  324. }
  325. next_ebus:
  326. printk("n");
  327. pdev = find_next_ebus(pdev, &is_rio);
  328. if (!pdev)
  329. break;
  330. cookie = pdev->sysdata;
  331. ebusnd = cookie->prom_node;
  332. ebus->next = ebus_alloc(sizeof(struct linux_ebus));
  333. ebus = ebus->next;
  334. ebus->next = 0;
  335. ebus->is_rio = is_rio;
  336. ++num_ebus;
  337. }
  338. #ifdef CONFIG_SUN_AUXIO
  339. auxio_probe();
  340. #endif
  341. }