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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * BK Id: %F% %I% %G% %U% %#%
  3.  */
  4. /*
  5.  * Procedures for interfacing to the Open Firmware PROM on
  6.  * Power Macintosh computers.
  7.  *
  8.  * In particular, we are interested in the device tree
  9.  * and in using some of its services (exit, write to stdout).
  10.  *
  11.  * Paul Mackerras August 1996.
  12.  * Copyright (C) 1996 Paul Mackerras.
  13.  */
  14. #include <linux/config.h>
  15. #include <linux/kernel.h>
  16. #include <linux/string.h>
  17. #include <linux/init.h>
  18. #include <linux/version.h>
  19. #include <linux/threads.h>
  20. #include <linux/spinlock.h>
  21. #include <linux/pci.h>
  22. #include <linux/slab.h>
  23. #include <asm/sections.h>
  24. #include <asm/prom.h>
  25. #include <asm/page.h>
  26. #include <asm/processor.h>
  27. #include <asm/irq.h>
  28. #include <asm/open_pic.h>
  29. #include <asm/system.h>
  30. #include <asm/btext.h>
  31. #include <asm/pci-bridge.h>
  32. struct pci_address {
  33. unsigned a_hi;
  34. unsigned a_mid;
  35. unsigned a_lo;
  36. };
  37. struct pci_reg_property {
  38. struct pci_address addr;
  39. unsigned size_hi;
  40. unsigned size_lo;
  41. };
  42. struct isa_reg_property {
  43. unsigned space;
  44. unsigned address;
  45. unsigned size;
  46. };
  47. typedef unsigned long interpret_func(struct device_node *, unsigned long,
  48.      int, int);
  49. static interpret_func interpret_pci_props;
  50. static interpret_func interpret_dbdma_props;
  51. static interpret_func interpret_isa_props;
  52. static interpret_func interpret_macio_props;
  53. static interpret_func interpret_root_props;
  54. extern char *klimit;
  55. /* Set for a newworld or CHRP machine */
  56. int use_of_interrupt_tree;
  57. struct device_node *dflt_interrupt_controller;
  58. int num_interrupt_controllers;
  59. int pmac_newworld;
  60. extern unsigned int rtas_entry;  /* physical pointer */
  61. extern struct device_node *allnodes;
  62. static unsigned long finish_node(struct device_node *, unsigned long,
  63.  interpret_func *, int, int);
  64. static unsigned long finish_node_interrupts(struct device_node *, unsigned long);
  65. extern void enter_rtas(void *);
  66. void phys_call_rtas(int, int, int, ...);
  67. extern char cmd_line[512]; /* XXX */
  68. extern boot_infos_t *boot_infos;
  69. unsigned long dev_tree_size;
  70. void __openfirmware
  71. phys_call_rtas(int service, int nargs, int nret, ...)
  72. {
  73. va_list list;
  74. union {
  75. unsigned long words[16];
  76. double align;
  77. } u;
  78. void (*rtas)(void *, unsigned long);
  79. int i;
  80. u.words[0] = service;
  81. u.words[1] = nargs;
  82. u.words[2] = nret;
  83. va_start(list, nret);
  84. for (i = 0; i < nargs; ++i)
  85. u.words[i+3] = va_arg(list, unsigned long);
  86. va_end(list);
  87. rtas = (void (*)(void *, unsigned long)) rtas_entry;
  88. rtas(&u, rtas_data);
  89. }
  90. /*
  91.  * finish_device_tree is called once things are running normally
  92.  * (i.e. with text and data mapped to the address they were linked at).
  93.  * It traverses the device tree and fills in the name, type,
  94.  * {n_}addrs and {n_}intrs fields of each node.
  95.  */
  96. void __init
  97. finish_device_tree(void)
  98. {
  99. unsigned long mem = (unsigned long) klimit;
  100. struct device_node *np;
  101. /* All newworld pmac machines and CHRPs now use the interrupt tree */
  102. for (np = allnodes; np != NULL; np = np->allnext) {
  103. if (get_property(np, "interrupt-parent", 0)) {
  104. use_of_interrupt_tree = 1;
  105. break;
  106. }
  107. }
  108. if (_machine == _MACH_Pmac && use_of_interrupt_tree)
  109. pmac_newworld = 1;
  110. #ifdef CONFIG_BOOTX_TEXT
  111. if (boot_infos && pmac_newworld) {
  112. prom_print("WARNING ! BootX/miBoot booting is not supported on this machinen");
  113. prom_print("          You should use an Open Firmware bootloadern");
  114. }
  115. #endif /* CONFIG_BOOTX_TEXT */
  116. if (use_of_interrupt_tree) {
  117. /*
  118.  * We want to find out here how many interrupt-controller
  119.  * nodes there are, and if we are booted from BootX,
  120.  * we need a pointer to the first (and hopefully only)
  121.  * such node.  But we can't use find_devices here since
  122.  * np->name has not been set yet.  -- paulus
  123.  */
  124. int n = 0;
  125. char *name, *ic;
  126. int iclen;
  127. for (np = allnodes; np != NULL; np = np->allnext) {
  128. ic = get_property(np, "interrupt-controller", &iclen);
  129. name = get_property(np, "name", NULL);
  130. /* checking iclen makes sure we don't get a false
  131.    match on /chosen.interrupt_controller */
  132. if ((name != NULL
  133.      && strcmp(name, "interrupt-controller") == 0)
  134.     || (ic != NULL && iclen == 0 && strcmp(name, "AppleKiwi"))) {
  135. if (n == 0)
  136. dflt_interrupt_controller = np;
  137. ++n;
  138. }
  139. }
  140. num_interrupt_controllers = n;
  141. }
  142. mem = finish_node(allnodes, mem, NULL, 1, 1);
  143. dev_tree_size = mem - (unsigned long) allnodes;
  144. klimit = (char *) mem;
  145. }
  146. static unsigned long __init
  147. finish_node(struct device_node *np, unsigned long mem_start,
  148.     interpret_func *ifunc, int naddrc, int nsizec)
  149. {
  150. struct device_node *child;
  151. int *ip;
  152. np->name = get_property(np, "name", 0);
  153. np->type = get_property(np, "device_type", 0);
  154. if (!np->name)
  155. np->name = "<NULL>";
  156. if (!np->type)
  157. np->type = "<NULL>";
  158. /* get the device addresses and interrupts */
  159. if (ifunc != NULL)
  160. mem_start = ifunc(np, mem_start, naddrc, nsizec);
  161. if (use_of_interrupt_tree)
  162. mem_start = finish_node_interrupts(np, mem_start);
  163. /* Look for #address-cells and #size-cells properties. */
  164. ip = (int *) get_property(np, "#address-cells", 0);
  165. if (ip != NULL)
  166. naddrc = *ip;
  167. ip = (int *) get_property(np, "#size-cells", 0);
  168. if (ip != NULL)
  169. nsizec = *ip;
  170. if (np->parent == NULL)
  171. ifunc = interpret_root_props;
  172. else if (np->type == 0)
  173. ifunc = NULL;
  174. else if (!strcmp(np->type, "pci") || !strcmp(np->type, "vci"))
  175. ifunc = interpret_pci_props;
  176. else if (!strcmp(np->type, "dbdma"))
  177. ifunc = interpret_dbdma_props;
  178. else if (!strcmp(np->type, "mac-io")
  179.  || ifunc == interpret_macio_props)
  180. ifunc = interpret_macio_props;
  181. else if (!strcmp(np->type, "isa"))
  182. ifunc = interpret_isa_props;
  183. else if (!strcmp(np->name, "uni-n"))
  184. ifunc = interpret_root_props;
  185. else if (!((ifunc == interpret_dbdma_props
  186.     || ifunc == interpret_macio_props)
  187.    && (!strcmp(np->type, "escc")
  188.        || !strcmp(np->type, "media-bay"))))
  189. ifunc = NULL;
  190. /* if we were booted from BootX, convert the full name */
  191. if (boot_infos
  192.     && strncmp(np->full_name, "Devices:device-tree", 19) == 0) {
  193. if (np->full_name[19] == 0) {
  194. strcpy(np->full_name, "/");
  195. } else if (np->full_name[19] == ':') {
  196. char *p = np->full_name + 19;
  197. np->full_name = p;
  198. for (; *p; ++p)
  199. if (*p == ':')
  200. *p = '/';
  201. }
  202. }
  203. for (child = np->child; child != NULL; child = child->sibling)
  204. mem_start = finish_node(child, mem_start, ifunc,
  205. naddrc, nsizec);
  206. return mem_start;
  207. }
  208. /*
  209.  * Find the interrupt parent of a node.
  210.  */
  211. static struct device_node * __init
  212. intr_parent(struct device_node *p)
  213. {
  214. phandle *parp;
  215. parp = (phandle *) get_property(p, "interrupt-parent", NULL);
  216. if (parp == NULL)
  217. return p->parent;
  218. p = find_phandle(*parp);
  219. if (p != NULL)
  220. return p;
  221. /*
  222.  * On a powermac booted with BootX, we don't get to know the
  223.  * phandles for any nodes, so find_phandle will return NULL.
  224.  * Fortunately these machines only have one interrupt controller
  225.  * so there isn't in fact any ambiguity.  -- paulus
  226.  */
  227. if (num_interrupt_controllers == 1)
  228. p = dflt_interrupt_controller;
  229. return p;
  230. }
  231. /*
  232.  * Find out the size of each entry of the interrupts property
  233.  * for a node.
  234.  */
  235. static int __init
  236. prom_n_intr_cells(struct device_node *np)
  237. {
  238. struct device_node *p;
  239. unsigned int *icp;
  240. for (p = np; (p = intr_parent(p)) != NULL; ) {
  241. icp = (unsigned int *)
  242. get_property(p, "#interrupt-cells", NULL);
  243. if (icp != NULL)
  244. return *icp;
  245. if (get_property(p, "interrupt-controller", NULL) != NULL
  246.     || get_property(p, "interrupt-map", NULL) != NULL) {
  247. printk("oops, node %s doesn't have #interrupt-cellsn",
  248.        p->full_name);
  249. return 1;
  250. }
  251. }
  252. printk("prom_n_intr_cells failed for %sn", np->full_name);
  253. return 1;
  254. }
  255. /*
  256.  * Map an interrupt from a device up to the platform interrupt
  257.  * descriptor.
  258.  */
  259. static int __init
  260. map_interrupt(unsigned int **irq, struct device_node **ictrler,
  261.       struct device_node *np, unsigned int *ints, int nintrc)
  262. {
  263. struct device_node *p, *ipar;
  264. unsigned int *imap, *imask, *ip;
  265. int i, imaplen, match;
  266. int newintrc, newaddrc;
  267. unsigned int *reg;
  268. int naddrc;
  269. reg = (unsigned int *) get_property(np, "reg", NULL);
  270. naddrc = prom_n_addr_cells(np);
  271. p = intr_parent(np);
  272. while (p != NULL) {
  273. if (get_property(p, "interrupt-controller", NULL) != NULL)
  274. /* this node is an interrupt controller, stop here */
  275. break;
  276. imap = (unsigned int *)
  277. get_property(p, "interrupt-map", &imaplen);
  278. if (imap == NULL) {
  279. p = intr_parent(p);
  280. continue;
  281. }
  282. imask = (unsigned int *)
  283. get_property(p, "interrupt-map-mask", NULL);
  284. if (imask == NULL) {
  285. printk("oops, %s has interrupt-map but no maskn",
  286.        p->full_name);
  287. return 0;
  288. }
  289. imaplen /= sizeof(unsigned int);
  290. match = 0;
  291. ipar = NULL;
  292. while (imaplen > 0 && !match) {
  293. /* check the child-interrupt field */
  294. match = 1;
  295. for (i = 0; i < naddrc && match; ++i)
  296. match = ((reg[i] ^ imap[i]) & imask[i]) == 0;
  297. for (; i < naddrc + nintrc && match; ++i)
  298. match = ((ints[i-naddrc] ^ imap[i]) & imask[i]) == 0;
  299. imap += naddrc + nintrc;
  300. imaplen -= naddrc + nintrc;
  301. /* grab the interrupt parent */
  302. ipar = find_phandle((phandle) *imap++);
  303. --imaplen;
  304. if (ipar == NULL && num_interrupt_controllers == 1)
  305. /* cope with BootX not giving us phandles */
  306. ipar = dflt_interrupt_controller;
  307. if (ipar == NULL) {
  308. printk("oops, no int parent %x in map of %sn",
  309.        imap[-1], p->full_name);
  310. return 0;
  311. }
  312. /* find the parent's # addr and intr cells */
  313. ip = (unsigned int *)
  314. get_property(ipar, "#interrupt-cells", NULL);
  315. if (ip == NULL) {
  316. printk("oops, no #interrupt-cells on %sn",
  317.        ipar->full_name);
  318. return 0;
  319. }
  320. newintrc = *ip;
  321. ip = (unsigned int *)
  322. get_property(ipar, "#address-cells", NULL);
  323. newaddrc = (ip == NULL)? 0: *ip;
  324. imap += newaddrc + newintrc;
  325. imaplen -= newaddrc + newintrc;
  326. }
  327. if (imaplen < 0) {
  328. printk("oops, error decoding int-map on %s, len=%dn",
  329.        p->full_name, imaplen);
  330. return 0;
  331. }
  332. if (!match) {
  333. printk("oops, no match in %s int-map for %sn",
  334.        p->full_name, np->full_name);
  335. return 0;
  336. }
  337. p = ipar;
  338. naddrc = newaddrc;
  339. nintrc = newintrc;
  340. ints = imap - nintrc;
  341. reg = ints - naddrc;
  342. }
  343. if (p == NULL)
  344. printk("hmmm, int tree for %s doesn't have ctrlern",
  345.        np->full_name);
  346. *irq = ints;
  347. *ictrler = p;
  348. return nintrc;
  349. }
  350. /*
  351.  * New version of finish_node_interrupts.
  352.  */
  353. static unsigned long __init
  354. finish_node_interrupts(struct device_node *np, unsigned long mem_start)
  355. {
  356. unsigned int *ints;
  357. int intlen, intrcells;
  358. int i, j, n, offset;
  359. unsigned int *irq;
  360. struct device_node *ic;
  361. ints = (unsigned int *) get_property(np, "interrupts", &intlen);
  362. if (ints == NULL)
  363. return mem_start;
  364. intrcells = prom_n_intr_cells(np);
  365. intlen /= intrcells * sizeof(unsigned int);
  366. np->n_intrs = intlen;
  367. np->intrs = (struct interrupt_info *) mem_start;
  368. mem_start += intlen * sizeof(struct interrupt_info);
  369. for (i = 0; i < intlen; ++i) {
  370. np->intrs[i].line = 0;
  371. np->intrs[i].sense = 1;
  372. n = map_interrupt(&irq, &ic, np, ints, intrcells);
  373. if (n <= 0)
  374. continue;
  375. offset = 0;
  376. /*
  377.  * On a CHRP we have an 8259 which is subordinate to
  378.  * the openpic in the interrupt tree, but we want the
  379.  * openpic's interrupt numbers offsetted, not the 8259's.
  380.  * So we apply the offset if the controller is at the
  381.  * root of the interrupt tree, i.e. has no interrupt-parent.
  382.  * This doesn't cope with the general case of multiple
  383.  * cascaded interrupt controllers, but then neither will
  384.  * irq.c at the moment either.  -- paulus
  385.  */
  386. if (num_interrupt_controllers > 1 && ic != NULL
  387.     && get_property(ic, "interrupt-parent", NULL) == NULL)
  388. offset = 16;
  389. np->intrs[i].line = irq[0] + offset;
  390. if (n > 1)
  391. np->intrs[i].sense = irq[1];
  392. if (n > 2) {
  393. printk("hmmm, got %d intr cells for %s:", n,
  394.        np->full_name);
  395. for (j = 0; j < n; ++j)
  396. printk(" %d", irq[j]);
  397. printk("n");
  398. }
  399. ints += intrcells;
  400. }
  401. return mem_start;
  402. }
  403. /*
  404.  * When BootX makes a copy of the device tree from the MacOS
  405.  * Name Registry, it is in the format we use but all of the pointers
  406.  * are offsets from the start of the tree.
  407.  * This procedure updates the pointers.
  408.  */
  409. void __init
  410. relocate_nodes(void)
  411. {
  412. unsigned long base;
  413. struct device_node *np;
  414. struct property *pp;
  415. #define ADDBASE(x) (x = (x)? ((typeof (x))((unsigned long)(x) + base)): 0)
  416. base = (unsigned long) boot_infos + boot_infos->deviceTreeOffset;
  417. allnodes = (struct device_node *)(base + 4);
  418. for (np = allnodes; np != 0; np = np->allnext) {
  419. ADDBASE(np->full_name);
  420. ADDBASE(np->properties);
  421. ADDBASE(np->parent);
  422. ADDBASE(np->child);
  423. ADDBASE(np->sibling);
  424. ADDBASE(np->allnext);
  425. for (pp = np->properties; pp != 0; pp = pp->next) {
  426. ADDBASE(pp->name);
  427. ADDBASE(pp->value);
  428. ADDBASE(pp->next);
  429. }
  430. }
  431. }
  432. int
  433. prom_n_addr_cells(struct device_node* np)
  434. {
  435. int* ip;
  436. do {
  437. if (np->parent)
  438. np = np->parent;
  439. ip = (int *) get_property(np, "#address-cells", 0);
  440. if (ip != NULL)
  441. return *ip;
  442. } while (np->parent);
  443. /* No #address-cells property for the root node, default to 1 */
  444. return 1;
  445. }
  446. int
  447. prom_n_size_cells(struct device_node* np)
  448. {
  449. int* ip;
  450. do {
  451. if (np->parent)
  452. np = np->parent;
  453. ip = (int *) get_property(np, "#size-cells", 0);
  454. if (ip != NULL)
  455. return *ip;
  456. } while (np->parent);
  457. /* No #size-cells property for the root node, default to 1 */
  458. return 1;
  459. }
  460. static unsigned long __init
  461. interpret_pci_props(struct device_node *np, unsigned long mem_start,
  462.     int naddrc, int nsizec)
  463. {
  464. struct address_range *adr;
  465. struct pci_reg_property *pci_addrs;
  466. int i, l, *ip;
  467. pci_addrs = (struct pci_reg_property *)
  468. get_property(np, "assigned-addresses", &l);
  469. if (pci_addrs != 0 && l >= sizeof(struct pci_reg_property)) {
  470. i = 0;
  471. adr = (struct address_range *) mem_start;
  472. while ((l -= sizeof(struct pci_reg_property)) >= 0) {
  473. /* XXX assumes PCI addresses mapped 1-1 to physical */
  474. adr[i].space = pci_addrs[i].addr.a_hi;
  475. adr[i].address = pci_addrs[i].addr.a_lo;
  476. adr[i].size = pci_addrs[i].size_lo;
  477. ++i;
  478. }
  479. np->addrs = adr;
  480. np->n_addrs = i;
  481. mem_start += i * sizeof(struct address_range);
  482. }
  483. if (use_of_interrupt_tree)
  484. return mem_start;
  485. ip = (int *) get_property(np, "AAPL,interrupts", &l);
  486. if (ip == 0 && np->parent)
  487. ip = (int *) get_property(np->parent, "AAPL,interrupts", &l);
  488. if (ip == 0)
  489. ip = (int *) get_property(np, "interrupts", &l);
  490. if (ip != 0) {
  491. np->intrs = (struct interrupt_info *) mem_start;
  492. np->n_intrs = l / sizeof(int);
  493. mem_start += np->n_intrs * sizeof(struct interrupt_info);
  494. for (i = 0; i < np->n_intrs; ++i) {
  495. np->intrs[i].line = *ip++;
  496. np->intrs[i].sense = 1;
  497. }
  498. }
  499. return mem_start;
  500. }
  501. static unsigned long __init
  502. interpret_dbdma_props(struct device_node *np, unsigned long mem_start,
  503.       int naddrc, int nsizec)
  504. {
  505. struct reg_property *rp;
  506. struct address_range *adr;
  507. unsigned long base_address;
  508. int i, l, *ip;
  509. struct device_node *db;
  510. base_address = 0;
  511. for (db = np->parent; db != NULL; db = db->parent) {
  512. if (!strcmp(db->type, "dbdma") && db->n_addrs != 0) {
  513. base_address = db->addrs[0].address;
  514. break;
  515. }
  516. }
  517. rp = (struct reg_property *) get_property(np, "reg", &l);
  518. if (rp != 0 && l >= sizeof(struct reg_property)) {
  519. i = 0;
  520. adr = (struct address_range *) mem_start;
  521. while ((l -= sizeof(struct reg_property)) >= 0) {
  522. adr[i].space = 2;
  523. adr[i].address = rp[i].address + base_address;
  524. adr[i].size = rp[i].size;
  525. ++i;
  526. }
  527. np->addrs = adr;
  528. np->n_addrs = i;
  529. mem_start += i * sizeof(struct address_range);
  530. }
  531. if (use_of_interrupt_tree)
  532. return mem_start;
  533. ip = (int *) get_property(np, "AAPL,interrupts", &l);
  534. if (ip == 0)
  535. ip = (int *) get_property(np, "interrupts", &l);
  536. if (ip != 0) {
  537. np->intrs = (struct interrupt_info *) mem_start;
  538. np->n_intrs = l / sizeof(int);
  539. mem_start += np->n_intrs * sizeof(struct interrupt_info);
  540. for (i = 0; i < np->n_intrs; ++i) {
  541. np->intrs[i].line = *ip++;
  542. np->intrs[i].sense = 1;
  543. }
  544. }
  545. return mem_start;
  546. }
  547. static unsigned long __init
  548. interpret_macio_props(struct device_node *np, unsigned long mem_start,
  549.       int naddrc, int nsizec)
  550. {
  551. struct reg_property *rp;
  552. struct address_range *adr;
  553. unsigned long base_address;
  554. int i, l, *ip;
  555. struct device_node *db;
  556. base_address = 0;
  557. for (db = np->parent; db != NULL; db = db->parent) {
  558. if (!strcmp(db->type, "mac-io") && db->n_addrs != 0) {
  559. base_address = db->addrs[0].address;
  560. break;
  561. }
  562. }
  563. rp = (struct reg_property *) get_property(np, "reg", &l);
  564. if (rp != 0 && l >= sizeof(struct reg_property)) {
  565. i = 0;
  566. adr = (struct address_range *) mem_start;
  567. while ((l -= sizeof(struct reg_property)) >= 0) {
  568. adr[i].space = 2;
  569. adr[i].address = rp[i].address + base_address;
  570. adr[i].size = rp[i].size;
  571. ++i;
  572. }
  573. np->addrs = adr;
  574. np->n_addrs = i;
  575. mem_start += i * sizeof(struct address_range);
  576. }
  577. if (use_of_interrupt_tree)
  578. return mem_start;
  579. ip = (int *) get_property(np, "interrupts", &l);
  580. if (ip == 0)
  581. ip = (int *) get_property(np, "AAPL,interrupts", &l);
  582. if (ip != 0) {
  583. np->intrs = (struct interrupt_info *) mem_start;
  584. np->n_intrs = l / sizeof(int);
  585. for (i = 0; i < np->n_intrs; ++i) {
  586. np->intrs[i].line = *ip++;
  587. np->intrs[i].sense = 1;
  588. }
  589. mem_start += np->n_intrs * sizeof(struct interrupt_info);
  590. }
  591. return mem_start;
  592. }
  593. static unsigned long __init
  594. interpret_isa_props(struct device_node *np, unsigned long mem_start,
  595.     int naddrc, int nsizec)
  596. {
  597. struct isa_reg_property *rp;
  598. struct address_range *adr;
  599. int i, l, *ip;
  600. rp = (struct isa_reg_property *) get_property(np, "reg", &l);
  601. if (rp != 0 && l >= sizeof(struct isa_reg_property)) {
  602. i = 0;
  603. adr = (struct address_range *) mem_start;
  604. while ((l -= sizeof(struct reg_property)) >= 0) {
  605. adr[i].space = rp[i].space;
  606. adr[i].address = rp[i].address
  607. + (adr[i].space? 0: _ISA_MEM_BASE);
  608. adr[i].size = rp[i].size;
  609. ++i;
  610. }
  611. np->addrs = adr;
  612. np->n_addrs = i;
  613. mem_start += i * sizeof(struct address_range);
  614. }
  615. if (use_of_interrupt_tree)
  616. return mem_start;
  617. ip = (int *) get_property(np, "interrupts", &l);
  618. if (ip != 0) {
  619. np->intrs = (struct interrupt_info *) mem_start;
  620. np->n_intrs = l / (2 * sizeof(int));
  621. mem_start += np->n_intrs * sizeof(struct interrupt_info);
  622. for (i = 0; i < np->n_intrs; ++i) {
  623. np->intrs[i].line = *ip++;
  624. np->intrs[i].sense = *ip++;
  625. }
  626. }
  627. return mem_start;
  628. }
  629. static unsigned long __init
  630. interpret_root_props(struct device_node *np, unsigned long mem_start,
  631.      int naddrc, int nsizec)
  632. {
  633. struct address_range *adr;
  634. int i, l, *ip;
  635. unsigned int *rp;
  636. int rpsize = (naddrc + nsizec) * sizeof(unsigned int);
  637. rp = (unsigned int *) get_property(np, "reg", &l);
  638. if (rp != 0 && l >= rpsize) {
  639. i = 0;
  640. adr = (struct address_range *) mem_start;
  641. while ((l -= rpsize) >= 0) {
  642. adr[i].space = (naddrc >= 2? rp[naddrc-2]: 2);
  643. adr[i].address = rp[naddrc - 1];
  644. adr[i].size = rp[naddrc + nsizec - 1];
  645. ++i;
  646. rp += naddrc + nsizec;
  647. }
  648. np->addrs = adr;
  649. np->n_addrs = i;
  650. mem_start += i * sizeof(struct address_range);
  651. }
  652. if (use_of_interrupt_tree)
  653. return mem_start;
  654. ip = (int *) get_property(np, "AAPL,interrupts", &l);
  655. if (ip == 0)
  656. ip = (int *) get_property(np, "interrupts", &l);
  657. if (ip != 0) {
  658. np->intrs = (struct interrupt_info *) mem_start;
  659. np->n_intrs = l / sizeof(int);
  660. mem_start += np->n_intrs * sizeof(struct interrupt_info);
  661. for (i = 0; i < np->n_intrs; ++i) {
  662. np->intrs[i].line = *ip++;
  663. np->intrs[i].sense = 1;
  664. }
  665. }
  666. return mem_start;
  667. }
  668. /*
  669.  * Work out the sense (active-low level / active-high edge)
  670.  * of each interrupt from the device tree.
  671.  */
  672. void __init
  673. prom_get_irq_senses(unsigned char *senses, int off, int max)
  674. {
  675. struct device_node *np;
  676. int i, j;
  677. /* default to level-triggered */
  678. memset(senses, 1, max - off);
  679. if (!use_of_interrupt_tree)
  680. return;
  681. for (np = allnodes; np != 0; np = np->allnext) {
  682. for (j = 0; j < np->n_intrs; j++) {
  683. i = np->intrs[j].line;
  684. if (i >= off && i < max)
  685. senses[i-off] = np->intrs[j].sense;
  686. }
  687. }
  688. }
  689. /*
  690.  * Construct and return a list of the device_nodes with a given name.
  691.  */
  692. struct device_node *
  693. find_devices(const char *name)
  694. {
  695. struct device_node *head, **prevp, *np;
  696. prevp = &head;
  697. for (np = allnodes; np != 0; np = np->allnext) {
  698. if (np->name != 0 && strcasecmp(np->name, name) == 0) {
  699. *prevp = np;
  700. prevp = &np->next;
  701. }
  702. }
  703. *prevp = 0;
  704. return head;
  705. }
  706. /*
  707.  * Construct and return a list of the device_nodes with a given type.
  708.  */
  709. struct device_node *
  710. find_type_devices(const char *type)
  711. {
  712. struct device_node *head, **prevp, *np;
  713. prevp = &head;
  714. for (np = allnodes; np != 0; np = np->allnext) {
  715. if (np->type != 0 && strcasecmp(np->type, type) == 0) {
  716. *prevp = np;
  717. prevp = &np->next;
  718. }
  719. }
  720. *prevp = 0;
  721. return head;
  722. }
  723. /*
  724.  * Returns all nodes linked together
  725.  */
  726. struct device_node * __openfirmware
  727. find_all_nodes(void)
  728. {
  729. struct device_node *head, **prevp, *np;
  730. prevp = &head;
  731. for (np = allnodes; np != 0; np = np->allnext) {
  732. *prevp = np;
  733. prevp = &np->next;
  734. }
  735. *prevp = 0;
  736. return head;
  737. }
  738. /* Checks if the given "compat" string matches one of the strings in
  739.  * the device's "compatible" property
  740.  */
  741. int
  742. device_is_compatible(struct device_node *device, const char *compat)
  743. {
  744. const char* cp;
  745. int cplen, l;
  746. cp = (char *) get_property(device, "compatible", &cplen);
  747. if (cp == NULL)
  748. return 0;
  749. while (cplen > 0) {
  750. if (strncasecmp(cp, compat, strlen(compat)) == 0)
  751. return 1;
  752. l = strlen(cp) + 1;
  753. cp += l;
  754. cplen -= l;
  755. }
  756. return 0;
  757. }
  758. /*
  759.  * Indicates whether the root node has a given value in its
  760.  * compatible property.
  761.  */
  762. int
  763. machine_is_compatible(const char *compat)
  764. {
  765. struct device_node *root;
  766. root = find_path_device("/");
  767. if (root == 0)
  768. return 0;
  769. return device_is_compatible(root, compat);
  770. }
  771. /*
  772.  * Construct and return a list of the device_nodes with a given type
  773.  * and compatible property.
  774.  */
  775. struct device_node *
  776. find_compatible_devices(const char *type, const char *compat)
  777. {
  778. struct device_node *head, **prevp, *np;
  779. prevp = &head;
  780. for (np = allnodes; np != 0; np = np->allnext) {
  781. if (type != NULL
  782.     && !(np->type != 0 && strcasecmp(np->type, type) == 0))
  783. continue;
  784. if (device_is_compatible(np, compat)) {
  785. *prevp = np;
  786. prevp = &np->next;
  787. }
  788. }
  789. *prevp = 0;
  790. return head;
  791. }
  792. /*
  793.  * Find the device_node with a given full_name.
  794.  */
  795. struct device_node *
  796. find_path_device(const char *path)
  797. {
  798. struct device_node *np;
  799. for (np = allnodes; np != 0; np = np->allnext)
  800. if (np->full_name != 0 && strcasecmp(np->full_name, path) == 0)
  801. return np;
  802. return NULL;
  803. }
  804. /*
  805.  * Find the device_node with a given phandle.
  806.  */
  807. struct device_node * __init
  808. find_phandle(phandle ph)
  809. {
  810. struct device_node *np;
  811. for (np = allnodes; np != 0; np = np->allnext)
  812. if (np->node == ph)
  813. return np;
  814. return NULL;
  815. }
  816. /*
  817.  * Find a property with a given name for a given node
  818.  * and return the value.
  819.  */
  820. unsigned char *
  821. get_property(struct device_node *np, const char *name, int *lenp)
  822. {
  823. struct property *pp;
  824. for (pp = np->properties; pp != 0; pp = pp->next)
  825. if (pp->name != NULL && strcmp(pp->name, name) == 0) {
  826. if (lenp != 0)
  827. *lenp = pp->length;
  828. return pp->value;
  829. }
  830. return 0;
  831. }
  832. /*
  833.  * Add a property to a node
  834.  */
  835. void __openfirmware
  836. prom_add_property(struct device_node* np, struct property* prop)
  837. {
  838. struct property **next = &np->properties;
  839. prop->next = NULL;
  840. while (*next)
  841. next = &(*next)->next;
  842. *next = prop;
  843. }
  844. /* I quickly hacked that one, check against spec ! */
  845. static inline unsigned long __openfirmware
  846. bus_space_to_resource_flags(unsigned int bus_space)
  847. {
  848. u8 space = (bus_space >> 24) & 0xf;
  849. if (space == 0)
  850. space = 0x02;
  851. if (space == 0x02)
  852. return IORESOURCE_MEM;
  853. else if (space == 0x01)
  854. return IORESOURCE_IO;
  855. else {
  856. printk(KERN_WARNING "prom.c: bus_space_to_resource_flags(), space: %xn",
  857.      bus_space);
  858. return 0;
  859. }
  860. }
  861. static struct resource* __openfirmware
  862. find_parent_pci_resource(struct pci_dev* pdev, struct address_range *range)
  863. {
  864. unsigned long mask;
  865. int i;
  866. /* Check this one */ 
  867. mask = bus_space_to_resource_flags(range->space);
  868. for (i=0; i<DEVICE_COUNT_RESOURCE; i++) {
  869. if ((pdev->resource[i].flags & mask) == mask &&
  870. pdev->resource[i].start <= range->address &&
  871. pdev->resource[i].end > range->address) {
  872. if ((range->address + range->size - 1) > pdev->resource[i].end) {
  873. /* Add better message */
  874. printk(KERN_WARNING "PCI/OF resource overlap !n");
  875. return NULL;
  876. }
  877. break;
  878. }
  879. }
  880. if (i == DEVICE_COUNT_RESOURCE)
  881. return NULL;
  882. return &pdev->resource[i];
  883. }
  884. /*
  885.  * Request an OF device resource. Currently handles child of PCI devices,
  886.  * or other nodes attached to the root node. Ultimately, put some
  887.  * link to resources in the OF node.
  888.  * WARNING: out_resource->name should be initialized before calling this
  889.  * function.
  890.  */
  891. struct resource* __openfirmware
  892. request_OF_resource(struct device_node* node, int index, const char* name_postfix)
  893. {
  894. struct pci_dev* pcidev;
  895. u8 pci_bus, pci_devfn;
  896. unsigned long iomask;
  897. struct device_node* nd;
  898. struct resource* parent;
  899. struct resource *res = NULL;
  900. int nlen, plen;
  901. if (index >= node->n_addrs)
  902. goto fail;
  903. /* Sanity check on bus space */
  904. iomask = bus_space_to_resource_flags(node->addrs[index].space);
  905. if (iomask & IORESOURCE_MEM)
  906. parent = &iomem_resource;
  907. else if (iomask & IORESOURCE_IO)
  908. parent = &ioport_resource;
  909. else
  910. goto fail;
  911. /* Find a PCI parent if any */
  912. nd = node;
  913. pcidev = NULL;
  914. while(nd) {
  915. if (!pci_device_from_OF_node(nd, &pci_bus, &pci_devfn))
  916. pcidev = pci_find_slot(pci_bus, pci_devfn);
  917. if (pcidev) break;
  918. nd = nd->parent;
  919. }
  920. if (pcidev)
  921. parent = find_parent_pci_resource(pcidev, &node->addrs[index]);
  922. if (!parent) {
  923. printk(KERN_WARNING "request_OF_resource(%s), parent not foundn",
  924. node->name);
  925. goto fail;
  926. }
  927. res = __request_region(parent, node->addrs[index].address, node->addrs[index].size, NULL);
  928. if (!res)
  929. goto fail;
  930. nlen = strlen(node->name);
  931. plen = name_postfix ? strlen(name_postfix) : 0;
  932. res->name = (const char *)kmalloc(nlen+plen+1, GFP_KERNEL);
  933. if (res->name) {
  934. strcpy((char *)res->name, node->name);
  935. if (plen)
  936. strcpy((char *)res->name+nlen, name_postfix);
  937. }
  938. return res;
  939. fail:
  940. return NULL;
  941. }
  942. int __openfirmware
  943. release_OF_resource(struct device_node* node, int index)
  944. {
  945. struct pci_dev* pcidev;
  946. u8 pci_bus, pci_devfn;
  947. unsigned long iomask;
  948. struct device_node* nd;
  949. struct resource* parent;
  950. struct resource *res = NULL;
  951. if (index >= node->n_addrs)
  952. return -EINVAL;
  953. /* Sanity check on bus space */
  954. iomask = bus_space_to_resource_flags(node->addrs[index].space);
  955. if (iomask & IORESOURCE_MEM)
  956. parent = &iomem_resource;
  957. else if (iomask & IORESOURCE_IO)
  958. parent = &ioport_resource;
  959. else
  960. return -EINVAL;
  961. /* Find a PCI parent if any */
  962. nd = node;
  963. pcidev = NULL;
  964. while(nd) {
  965. if (!pci_device_from_OF_node(nd, &pci_bus, &pci_devfn))
  966. pcidev = pci_find_slot(pci_bus, pci_devfn);
  967. if (pcidev) break;
  968. nd = nd->parent;
  969. }
  970. if (pcidev)
  971. parent = find_parent_pci_resource(pcidev, &node->addrs[index]);
  972. if (!parent) {
  973. printk(KERN_WARNING "request_OF_resource(%s), parent not foundn",
  974. node->name);
  975. return -ENODEV;
  976. }
  977. /* Find us in the parent */
  978. res = parent->child;
  979. while (res) {
  980. if (res->start == node->addrs[index].address &&
  981.     res->end == (res->start + node->addrs[index].size - 1))
  982.      break;
  983. res = res->sibling;
  984. }
  985. if (!res)
  986. return -ENODEV;
  987. if (res->name) {
  988. kfree(res->name);
  989. res->name = NULL;
  990. }
  991. release_resource(res);
  992. kfree(res);
  993. return 0;
  994. }
  995. #if 0
  996. void __openfirmware
  997. print_properties(struct device_node *np)
  998. {
  999. struct property *pp;
  1000. char *cp;
  1001. int i, n;
  1002. for (pp = np->properties; pp != 0; pp = pp->next) {
  1003. printk(KERN_INFO "%s", pp->name);
  1004. for (i = strlen(pp->name); i < 16; ++i)
  1005. printk(" ");
  1006. cp = (char *) pp->value;
  1007. for (i = pp->length; i > 0; --i, ++cp)
  1008. if ((i > 1 && (*cp < 0x20 || *cp > 0x7e))
  1009.     || (i == 1 && *cp != 0))
  1010. break;
  1011. if (i == 0 && pp->length > 1) {
  1012. /* looks like a string */
  1013. printk(" %sn", (char *) pp->value);
  1014. } else {
  1015. /* dump it in hex */
  1016. n = pp->length;
  1017. if (n > 64)
  1018. n = 64;
  1019. if (pp->length % 4 == 0) {
  1020. unsigned int *p = (unsigned int *) pp->value;
  1021. n /= 4;
  1022. for (i = 0; i < n; ++i) {
  1023. if (i != 0 && (i % 4) == 0)
  1024. printk("n                ");
  1025. printk(" %08x", *p++);
  1026. }
  1027. } else {
  1028. unsigned char *bp = pp->value;
  1029. for (i = 0; i < n; ++i) {
  1030. if (i != 0 && (i % 16) == 0)
  1031. printk("n                ");
  1032. printk(" %02x", *bp++);
  1033. }
  1034. }
  1035. printk("n");
  1036. if (pp->length > 64)
  1037. printk("                 ... (length = %d)n",
  1038.        pp->length);
  1039. }
  1040. }
  1041. }
  1042. #endif
  1043. static spinlock_t rtas_lock = SPIN_LOCK_UNLOCKED;
  1044. /* this can be called after setup -- Cort */
  1045. int __openfirmware
  1046. call_rtas(const char *service, int nargs, int nret,
  1047.   unsigned long *outputs, ...)
  1048. {
  1049. va_list list;
  1050. int i;
  1051. unsigned long s;
  1052. struct device_node *rtas;
  1053. int *tokp;
  1054. union {
  1055. unsigned long words[16];
  1056. double align;
  1057. } u;
  1058. rtas = find_devices("rtas");
  1059. if (rtas == NULL)
  1060. return -1;
  1061. tokp = (int *) get_property(rtas, service, NULL);
  1062. if (tokp == NULL) {
  1063. printk(KERN_ERR "No RTAS service called %sn", service);
  1064. return -1;
  1065. }
  1066. u.words[0] = *tokp;
  1067. u.words[1] = nargs;
  1068. u.words[2] = nret;
  1069. va_start(list, outputs);
  1070. for (i = 0; i < nargs; ++i)
  1071. u.words[i+3] = va_arg(list, unsigned long);
  1072. va_end(list);
  1073. /*
  1074.  * RTAS doesn't use floating point.
  1075.  * Or at least, according to the CHRP spec we enter RTAS
  1076.  * with FP disabled, and it doesn't change the FP registers.
  1077.  *  -- paulus.
  1078.  */
  1079. spin_lock_irqsave(&rtas_lock, s);
  1080. enter_rtas((void *)__pa(&u));
  1081. spin_unlock_irqrestore(&rtas_lock, s);
  1082. if (nret > 1 && outputs != NULL)
  1083. for (i = 0; i < nret-1; ++i)
  1084. outputs[i] = u.words[i+nargs+4];
  1085. return u.words[nargs+3];
  1086. }