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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /* $Id$
  2.  *
  3.  * This file is subject to the terms and conditions of the GNU General Public
  4.  * License.  See the file "COPYING" in the main directory of this archive
  5.  * for more details.
  6.  *
  7.  * Copyright (C) 1992 - 1997, 2000-2002 Silicon Graphics, Inc. All rights reserved.
  8.  */
  9. #include <linux/types.h>
  10. #include <linux/config.h>
  11. #include <linux/slab.h>
  12. #include <linux/ctype.h>
  13. #include <asm/sn/sgi.h>
  14. #include <asm/sn/sn_sal.h>
  15. #include <asm/sn/io.h>
  16. #include <asm/sn/sn_cpuid.h>
  17. #include <asm/sn/iograph.h>
  18. #include <asm/sn/invent.h>
  19. #include <asm/sn/hcl.h>
  20. #include <asm/sn/hcl_util.h>
  21. #include <asm/sn/labelcl.h>
  22. #include <asm/sn/xtalk/xbow.h>
  23. #include <asm/sn/pci/bridge.h>
  24. #include <asm/sn/klconfig.h>
  25. #include <asm/sn/eeprom.h>
  26. #include <asm/sn/sn_private.h>
  27. #include <asm/sn/pci/pcibr.h>
  28. #include <asm/sn/xtalk/xtalk.h>
  29. #include <asm/sn/xtalk/xswitch.h>
  30. #include <asm/sn/xtalk/xwidget.h>
  31. #include <asm/sn/xtalk/xtalk_private.h>
  32. #include <asm/sn/xtalk/xtalkaddrs.h>
  33. /* #define IOGRAPH_DEBUG */
  34. #ifdef IOGRAPH_DEBUG
  35. #define DBG(x...) printk(x)
  36. #else
  37. #define DBG(x...)
  38. #endif /* IOGRAPH_DEBUG */
  39. /* #define PROBE_TEST */
  40. /* At most 2 hubs can be connected to an xswitch */
  41. #define NUM_XSWITCH_VOLUNTEER 2
  42. /*
  43.  * Track which hubs have volunteered to manage devices hanging off of
  44.  * a Crosstalk Switch (e.g. xbow).  This structure is allocated,
  45.  * initialized, and hung off the xswitch vertex early on when the
  46.  * xswitch vertex is created.
  47.  */
  48. typedef struct xswitch_vol_s {
  49. mutex_t xswitch_volunteer_mutex;
  50. int xswitch_volunteer_count;
  51. devfs_handle_t xswitch_volunteer[NUM_XSWITCH_VOLUNTEER];
  52. } *xswitch_vol_t;
  53. void
  54. xswitch_vertex_init(devfs_handle_t xswitch)
  55. {
  56. xswitch_vol_t xvolinfo;
  57. int rc;
  58. xvolinfo = kmalloc(sizeof(struct xswitch_vol_s), GFP_KERNEL);
  59. mutex_init(&xvolinfo->xswitch_volunteer_mutex);
  60. xvolinfo->xswitch_volunteer_count = 0;
  61. rc = hwgraph_info_add_LBL(xswitch, 
  62. INFO_LBL_XSWITCH_VOL,
  63. (arbitrary_info_t)xvolinfo);
  64. ASSERT(rc == GRAPH_SUCCESS); rc = rc;
  65. }
  66. /*
  67.  * When assignment of hubs to widgets is complete, we no longer need the
  68.  * xswitch volunteer structure hanging around.  Destroy it.
  69.  */
  70. static void
  71. xswitch_volunteer_delete(devfs_handle_t xswitch)
  72. {
  73. xswitch_vol_t xvolinfo;
  74. int rc;
  75. rc = hwgraph_info_remove_LBL(xswitch, 
  76. INFO_LBL_XSWITCH_VOL,
  77. (arbitrary_info_t *)&xvolinfo);
  78. #ifdef LATER
  79. ASSERT(rc == GRAPH_SUCCESS); rc = rc;
  80. #endif
  81. kfree(xvolinfo);
  82. }
  83. /*
  84.  * A Crosstalk master volunteers to manage xwidgets on the specified xswitch.
  85.  */
  86. /* ARGSUSED */
  87. static void
  88. volunteer_for_widgets(devfs_handle_t xswitch, devfs_handle_t master)
  89. {
  90. xswitch_vol_t xvolinfo = NULL;
  91. (void)hwgraph_info_get_LBL(xswitch, 
  92. INFO_LBL_XSWITCH_VOL, 
  93. (arbitrary_info_t *)&xvolinfo);
  94. if (xvolinfo == NULL) {
  95. #ifdef LATER
  96.     if (!is_headless_node_vertex(master)) {
  97. #if defined(SUPPORT_PRINTING_V_FORMAT)
  98. printk(KERN_WARNING  "volunteer for widgets: vertex %v has no info label",
  99. xswitch);
  100. #else
  101. printk(KERN_WARNING  "volunteer for widgets: vertex 0x%x has no info label",
  102. xswitch);
  103. #endif
  104.     }
  105. #endif /* LATER */
  106.     return;
  107. }
  108. mutex_lock(&xvolinfo->xswitch_volunteer_mutex);
  109. ASSERT(xvolinfo->xswitch_volunteer_count < NUM_XSWITCH_VOLUNTEER);
  110. xvolinfo->xswitch_volunteer[xvolinfo->xswitch_volunteer_count] = master;
  111. xvolinfo->xswitch_volunteer_count++;
  112. mutex_unlock(&xvolinfo->xswitch_volunteer_mutex);
  113. }
  114. extern int xbow_port_io_enabled(nasid_t nasid, int widgetnum);
  115. /*
  116.  * Assign all the xwidgets hanging off the specified xswitch to the
  117.  * Crosstalk masters that have volunteered for xswitch duty.
  118.  */
  119. /* ARGSUSED */
  120. static void
  121. assign_widgets_to_volunteers(devfs_handle_t xswitch, devfs_handle_t hubv)
  122. {
  123. int curr_volunteer, num_volunteer;
  124. xwidgetnum_t widgetnum;
  125. xswitch_info_t xswitch_info;
  126. xswitch_vol_t xvolinfo = NULL;
  127. nasid_t nasid;
  128. hubinfo_t hubinfo;
  129. hubinfo_get(hubv, &hubinfo);
  130. nasid = hubinfo->h_nasid;
  131. xswitch_info = xswitch_info_get(xswitch);
  132. ASSERT(xswitch_info != NULL);
  133. (void)hwgraph_info_get_LBL(xswitch, 
  134. INFO_LBL_XSWITCH_VOL, 
  135. (arbitrary_info_t *)&xvolinfo);
  136. if (xvolinfo == NULL) {
  137. #ifdef LATER
  138.     if (!is_headless_node_vertex(hubv)) {
  139. #if defined(SUPPORT_PRINTING_V_FORMAT)
  140. printk(KERN_WARNING  "assign_widgets_to_volunteers:vertex %v has "
  141. " no info label",
  142. xswitch);
  143. #else
  144. printk(KERN_WARNING  "assign_widgets_to_volunteers:vertex 0x%x has "
  145. " no info label",
  146. xswitch);
  147. #endif
  148.     }
  149. #endif /* LATER */
  150.     return;
  151. }
  152. num_volunteer = xvolinfo->xswitch_volunteer_count;
  153. ASSERT(num_volunteer > 0);
  154. curr_volunteer = 0;
  155. /* Assign master hub for xswitch itself.  */
  156. if (HUB_WIDGET_ID_MIN > 0) {
  157. hubv = xvolinfo->xswitch_volunteer[0];
  158. xswitch_info_master_assignment_set(xswitch_info, (xwidgetnum_t)0, hubv);
  159. }
  160. /*
  161.  * TBD: Use administrative information to alter assignment of
  162.  * widgets to hubs.
  163.  */
  164. for (widgetnum=HUB_WIDGET_ID_MIN; widgetnum <= HUB_WIDGET_ID_MAX; widgetnum++) {
  165. /*
  166.  * Ignore disabled/empty ports.
  167.  */
  168. if (!xbow_port_io_enabled(nasid, widgetnum)) 
  169.     continue;
  170. /*
  171.  * If this is the master IO board, assign it to the same 
  172.  * hub that owned it in the prom.
  173.  */
  174. if (is_master_nasid_widget(nasid, widgetnum)) {
  175. int i;
  176. for (i=0; i<num_volunteer; i++) {
  177. hubv = xvolinfo->xswitch_volunteer[i];
  178. hubinfo_get(hubv, &hubinfo);
  179. nasid = hubinfo->h_nasid;
  180. if (nasid == get_console_nasid())
  181. goto do_assignment;
  182. }
  183. #ifdef LATER
  184. PRINT_PANIC("Nasid == %d, console nasid == %d",
  185. nasid, get_console_nasid());
  186. #endif
  187. }
  188. /*
  189.  * Do a round-robin assignment among the volunteer nodes.
  190.  */
  191. hubv = xvolinfo->xswitch_volunteer[curr_volunteer];
  192. curr_volunteer = (curr_volunteer + 1) % num_volunteer;
  193. /* fall through */
  194. do_assignment:
  195. /*
  196.  * At this point, we want to make hubv the master of widgetnum.
  197.  */
  198. xswitch_info_master_assignment_set(xswitch_info, widgetnum, hubv);
  199. }
  200. xswitch_volunteer_delete(xswitch);
  201. }
  202. /*
  203.  * Early iograph initialization.  Called by master CPU in mlreset().
  204.  * Useful for including iograph.o in kernel.o.
  205.  */
  206. void
  207. iograph_early_init(void)
  208. {
  209. /*
  210.  * Need new way to get this information ..
  211.  */
  212. cnodeid_t cnode;
  213. nasid_t nasid;
  214. lboard_t *board;
  215. /*
  216.  * Init. the board-to-hwgraph link early, so FRU analyzer
  217.  * doesn't trip on leftover values if we panic early on.
  218.  */
  219. for(cnode = 0; cnode < numnodes; cnode++) {
  220. nasid = COMPACT_TO_NASID_NODEID(cnode);
  221. board = (lboard_t *)KL_CONFIG_INFO(nasid);
  222. DBG("iograph_early_init: Found board 0x%pn", board);
  223. /* Check out all the board info stored on a node */
  224. while(board) {
  225. board->brd_graph_link = GRAPH_VERTEX_NONE;
  226. board = KLCF_NEXT(board);
  227. DBG("iograph_early_init: Found board 0x%pn", board);
  228. }
  229. }
  230. hubio_init();
  231. }
  232. #ifdef LINUX_KERNEL_THREADS
  233. static struct semaphore io_init_sema;
  234. #endif
  235. /*
  236.  * Let boot processor know that we're done initializing our node's IO
  237.  * and then exit.
  238.  */
  239. /* ARGSUSED */
  240. static void
  241. io_init_done(cnodeid_t cnodeid,cpu_cookie_t c)
  242. {
  243. /* Let boot processor know that we're done. */
  244. #ifdef LINUX_KERNEL_THREADS
  245. up(&io_init_sema);
  246. #endif
  247. #ifdef LATER
  248. /* This is for the setnoderun done when the io_init thread
  249.  * started 
  250.  */
  251. restorenoderun(c);
  252. sthread_exit();
  253. #endif
  254. }
  255. /* 
  256.  * Probe to see if this hub's xtalk link is active.  If so,
  257.  * return the Crosstalk Identification of the widget that we talk to.  
  258.  * This is called before any of the Crosstalk infrastructure for 
  259.  * this hub is set up.  It's usually called on the node that we're
  260.  * probing, but not always.
  261.  *
  262.  * TBD: Prom code should actually do this work, and pass through 
  263.  * hwid for our use.
  264.  */
  265. static void
  266. early_probe_for_widget(devfs_handle_t hubv, xwidget_hwid_t hwid)
  267. {
  268. hubreg_t llp_csr_reg;
  269. nasid_t nasid;
  270. hubinfo_t hubinfo;
  271. hubinfo_get(hubv, &hubinfo);
  272. nasid = hubinfo->h_nasid;
  273. llp_csr_reg = REMOTE_HUB_L(nasid, IIO_LLP_CSR);
  274. /* 
  275.  * If link is up, read the widget's part number.
  276.  * A direct connect widget must respond to widgetnum=0.
  277.  */
  278. if (llp_csr_reg & IIO_LLP_CSR_IS_UP) {
  279. /* TBD: Put hub into "indirect" mode */
  280. /*
  281.  * We're able to read from a widget because our hub's 
  282.  * WIDGET_ID was set up earlier.
  283.  */
  284. widgetreg_t widget_id = *(volatile widgetreg_t *)
  285. (RAW_NODE_SWIN_BASE(nasid, 0x0) + WIDGET_ID);
  286. DBG("early_probe_for_widget: Hub Vertex 0x%p is UP widget_id = 0x%x Register 0x%pn", hubv, widget_id,
  287. (volatile widgetreg_t *)(RAW_NODE_SWIN_BASE(nasid, 0x0) + WIDGET_ID) );
  288. hwid->part_num = XWIDGET_PART_NUM(widget_id);
  289. hwid->rev_num = XWIDGET_REV_NUM(widget_id);
  290. hwid->mfg_num = XWIDGET_MFG_NUM(widget_id);
  291. /* TBD: link reset */
  292. } else {
  293. hwid->part_num = XWIDGET_PART_NUM_NONE;
  294. hwid->rev_num = XWIDGET_REV_NUM_NONE;
  295. hwid->mfg_num = XWIDGET_MFG_NUM_NONE;
  296. }
  297. }
  298. /* Add inventory information to the widget vertex 
  299.  * Right now (module,slot,revision) is being
  300.  * added as inventory information.
  301.  */
  302. static void
  303. xwidget_inventory_add(devfs_handle_t  widgetv,
  304.       lboard_t  *board,
  305.       struct xwidget_hwid_s  hwid)
  306. {
  307. if (!board)
  308. return;
  309. /* Donot add inventory information for the baseio
  310.  * on a speedo with an xbox. It has already been
  311.  * taken care of in SN00_vmc.
  312.  * Speedo with xbox's baseio comes in at slot io1 (widget 9)
  313.  */
  314. device_inventory_add(widgetv,INV_IOBD,board->brd_type,
  315.      board->brd_module,
  316.      SLOTNUM_GETSLOT(board->brd_slot),
  317.      hwid.rev_num);
  318. }
  319. /*
  320.  * io_xswitch_widget_init
  321.  *
  322.  */
  323. /* defined in include/linux/ctype.h  */
  324. /* #define toupper(c) (islower(c) ? (c) - 'a' + 'A' : (c)) */
  325. void
  326. io_xswitch_widget_init(devfs_handle_t   xswitchv,
  327.        devfs_handle_t hubv,
  328.        xwidgetnum_t widgetnum,
  329.        async_attach_t aa)
  330. {
  331. xswitch_info_t xswitch_info;
  332. xwidgetnum_t hub_widgetid;
  333. devfs_handle_t widgetv;
  334. cnodeid_t cnode;
  335. widgetreg_t widget_id;
  336. nasid_t nasid, peer_nasid;
  337. struct xwidget_hwid_s  hwid;
  338. hubinfo_t hubinfo;
  339. /*REFERENCED*/
  340. int rc;
  341. char slotname[SLOTNUM_MAXLENGTH];
  342. char  pathname[128];
  343. char new_name[64];
  344. moduleid_t module;
  345. slotid_t slot;
  346. lboard_t *board = NULL;
  347. char buffer[16];
  348. slotid_t get_widget_slotnum(int xbow, int widget);
  349. DBG("nio_xswitch_widget_init: hubv 0x%p, xswitchv 0x%p, widgetnum 0x%xn", hubv, xswitchv, widgetnum);
  350. /*
  351.  * Verify that xswitchv is indeed an attached xswitch.
  352.  */
  353. xswitch_info = xswitch_info_get(xswitchv);
  354. ASSERT(xswitch_info != NULL);
  355. hubinfo_get(hubv, &hubinfo);
  356. nasid = hubinfo->h_nasid;
  357. cnode = NASID_TO_COMPACT_NODEID(nasid);
  358. hub_widgetid = hubinfo->h_widgetid;
  359. /* Who's the other guy on out crossbow (if anyone) */
  360. peer_nasid = NODEPDA(cnode)->xbow_peer;
  361. if (peer_nasid == INVALID_NASID)
  362. /* If I don't have a peer, use myself. */
  363. peer_nasid = nasid;
  364. /* Check my xbow structure and my peer's */
  365. if (!xbow_port_io_enabled(nasid, widgetnum) &&
  366.     !xbow_port_io_enabled(peer_nasid, widgetnum)) {
  367. return;
  368. }
  369. if (xswitch_info_link_ok(xswitch_info, widgetnum)) {
  370. char name[4];
  371. /*
  372.  * If the current hub is not supposed to be the master 
  373.  * for this widgetnum, then skip this widget.
  374.  */
  375. if (xswitch_info_master_assignment_get(xswitch_info,
  376.        widgetnum) != hubv) {
  377. return;
  378. }
  379. module  = NODEPDA(cnode)->module_id;
  380. #ifdef XBRIDGE_REGS_SIM
  381. /* hardwire for now...could do this with something like:
  382.  * xbow_soft_t soft = hwgraph_fastinfo_get(vhdl);
  383.  * xbow_t xbow = soft->base;
  384.  * xbowreg_t xwidget_id = xbow->xb_wid_id;
  385.  * but I don't feel like figuring out vhdl right now..
  386.  * and I know for a fact the answer is 0x2d000049 
  387.  */
  388. DBG("io_xswitch_widget_init: XBRIDGE_REGS_SIM FIXME: reading xwidget id: hardwired to xbridge (0x2d000049).n");
  389. DBG("XWIDGET_PART_NUM(0x2d000049)= 0x%xn", XWIDGET_PART_NUM(0x2d000049));
  390. if (XWIDGET_PART_NUM(0x2d000049)==XXBOW_WIDGET_PART_NUM) {
  391. #else
  392. if (nasid_has_xbridge(nasid)) {
  393. #endif /* XBRIDGE_REGS_SIM */
  394. board = find_lboard_module_class(
  395. (lboard_t *)KL_CONFIG_INFO(nasid),
  396. module,
  397. KLTYPE_IOBRICK);
  398. DBG("io_xswitch_widget_init: Board 0x%pn", board);
  399. {
  400. lboard_t dummy;
  401. if (board) {
  402. DBG("io_xswitch_widget_init: Found KLTYPE_IOBRICK Board 0x%p brd_type 0x%xn", board, board->brd_type);
  403. } else {
  404. DBG("io_xswitch_widget_init: FIXME did not find IOBOARDn");
  405. board = &dummy;
  406. }
  407. }
  408. /*
  409.    * Make sure we really want to say xbrick, pbrick,
  410.  * etc. rather than XIO, graphics, etc.
  411.    */
  412. #ifdef SUPPORT_PRINTING_M_FORMAT
  413. sprintf(pathname, EDGE_LBL_MODULE "/%M/"
  414. "%cbrick" "/%s/%d",
  415. NODEPDA(cnode)->module_id,
  416. #else
  417. memset(buffer, 0, 16);
  418. format_module_id(buffer, NODEPDA(cnode)->module_id, MODULE_FORMAT_BRIEF);
  419. sprintf(pathname, EDGE_LBL_MODULE "/%s/"
  420. "%cbrick" "/%s/%d",
  421. buffer,
  422. #endif
  423. (board->brd_type == KLTYPE_IBRICK) ? 'I' :
  424. (board->brd_type == KLTYPE_PBRICK) ? 'P' :
  425. (board->brd_type == KLTYPE_XBRICK) ? 'X' : '?',
  426. EDGE_LBL_XTALK, widgetnum);
  427. DBG("io_xswitch_widget_init: path= %sn", pathname);
  428. rc = hwgraph_path_add(hwgraph_root, pathname, &widgetv);
  429. ASSERT(rc == GRAPH_SUCCESS);
  430. /* This is needed to let the user programs to map the
  431.  * module,slot numbers to the corresponding widget numbers
  432.  * on the crossbow.
  433.  */
  434. rc = device_master_set(hwgraph_connectpt_get(widgetv), hubv);
  435. /* If we are looking at the global master io6
  436.  * then add information about the version of
  437.  * the io6prom as a part of "detailed inventory"
  438.  * information.
  439.  */
  440. if (is_master_baseio(nasid,
  441.      NODEPDA(cnode)->module_id,
  442.        get_widget_slotnum(0,widgetnum))) {
  443. extern void klhwg_baseio_inventory_add(devfs_handle_t,
  444.        cnodeid_t);
  445. module  = NODEPDA(cnode)->module_id;
  446. #ifdef XBRIDGE_REGS_SIM
  447. DBG("io_xswitch_widget_init: XBRIDGE_REGS_SIM FIXME: reading xwidget id: hardwired to xbridge (0x2d000049).n");
  448. if (XWIDGET_PART_NUM(0x2d000049)==XXBOW_WIDGET_PART_NUM) {
  449. #else
  450. if (nasid_has_xbridge(nasid)) {
  451. #endif /* XBRIDGE_REGS_SIM */
  452. board = find_lboard_module(
  453. (lboard_t *)KL_CONFIG_INFO(nasid),
  454. module);
  455. /*
  456.  * Change iobrick to correct i/o brick
  457.  */
  458. #ifdef SUPPORT_PRINTING_M_FORMAT
  459. sprintf(pathname, EDGE_LBL_MODULE "/%M/"
  460. #else
  461. sprintf(pathname, EDGE_LBL_MODULE "/%x/"
  462. #endif
  463. "iobrick" "/%s/%d",
  464. NODEPDA(cnode)->module_id,
  465. EDGE_LBL_XTALK, widgetnum);
  466. } else {
  467. slot = get_widget_slotnum(0, widgetnum);
  468. board = get_board_name(nasid, module, slot,
  469. new_name);
  470. /*
  471.    * Create the vertex for the widget, 
  472.  * using the decimal 
  473.    * widgetnum as the name of the primary edge.
  474.    */
  475. #ifdef SUPPORT_PRINTING_M_FORMAT
  476. sprintf(pathname, EDGE_LBL_MODULE "/%M/"
  477.                                                 EDGE_LBL_SLOT "/%s/%s",
  478.                                         NODEPDA(cnode)->module_id,
  479.                                         slotname, new_name);
  480. #else
  481. memset(buffer, 0, 16);
  482. format_module_id(buffer, NODEPDA(cnode)->module_id, MODULE_FORMAT_BRIEF);
  483. sprintf(pathname, EDGE_LBL_MODULE "/%s/"
  484.    EDGE_LBL_SLOT "/%s/%s",
  485. buffer,
  486. slotname, new_name);
  487. #endif
  488. }
  489. rc = hwgraph_path_add(hwgraph_root, pathname, &widgetv);
  490. DBG("io_xswitch_widget_init: (2) path= %sn", pathname);
  491.         /*
  492.          * This is a weird ass code needed for error injection
  493.          * purposes.
  494.          */
  495.         rc = device_master_set(hwgraph_connectpt_get(widgetv), hubv);
  496. klhwg_baseio_inventory_add(widgetv,cnode);
  497. }
  498. sprintf(name, "%d", widgetnum);
  499. DBG("io_xswitch_widget_init: FIXME hwgraph_edge_add %s xswitchv 0x%p, widgetv 0x%pn", name, xswitchv, widgetv);
  500. rc = hwgraph_edge_add(xswitchv, widgetv, name);
  501. /*
  502.  * crosstalk switch code tracks which
  503.  * widget is attached to each link.
  504.  */
  505. xswitch_info_vhdl_set(xswitch_info, widgetnum, widgetv);
  506. /*
  507.  * Peek at the widget to get its crosstalk part and
  508.  * mfgr numbers, then present it to the generic xtalk
  509.  * bus provider to have its driver attach routine
  510.  * called (or not).
  511.  */
  512. #ifdef XBRIDGE_REGS_SIM
  513. widget_id = 0x2d000049;
  514. DBG("io_xswitch_widget_init: XBRIDGE_REGS_SIM FIXME: id hardwired to widget_idn");
  515. #else
  516. widget_id = XWIDGET_ID_READ(nasid, widgetnum);
  517. #endif /* XBRIDGE_REGS_SIM */
  518. hwid.part_num = XWIDGET_PART_NUM(widget_id);
  519. hwid.rev_num = XWIDGET_REV_NUM(widget_id);
  520. hwid.mfg_num = XWIDGET_MFG_NUM(widget_id);
  521. /* Store some inventory information about
  522.  * the xwidget in the hardware graph.
  523.  */
  524. xwidget_inventory_add(widgetv,board,hwid);
  525. (void)xwidget_register(&hwid, widgetv, widgetnum,
  526.        hubv, hub_widgetid,
  527.        aa);
  528. #ifdef SN0_USE_BTE
  529. bte_bpush_war(cnode, (void *)board);
  530. #endif
  531. }
  532. }
  533. static void
  534. io_init_xswitch_widgets(devfs_handle_t xswitchv, cnodeid_t cnode)
  535. {
  536. xwidgetnum_t widgetnum;
  537. async_attach_t          aa;
  538. aa = async_attach_new();
  539. DBG("io_init_xswitch_widgets: xswitchv 0x%p for cnode %dn", xswitchv, cnode);
  540. for (widgetnum = HUB_WIDGET_ID_MIN; widgetnum <= HUB_WIDGET_ID_MAX; 
  541.      widgetnum++) {
  542. io_xswitch_widget_init(xswitchv,
  543.        cnodeid_to_vertex(cnode),
  544.        widgetnum, aa);
  545. }
  546. /* 
  547.  * Wait for parallel attach threads, if any, to complete.
  548.  */
  549. async_attach_waitall(aa);
  550. async_attach_free(aa);
  551. }
  552. /*
  553.  * For each PCI bridge connected to the xswitch, add a link from the
  554.  * board's klconfig info to the bridge's hwgraph vertex.  This lets
  555.  * the FRU analyzer find the bridge without traversing the hardware
  556.  * graph and risking hangs.
  557.  */
  558. static void
  559. io_link_xswitch_widgets(devfs_handle_t xswitchv, cnodeid_t cnodeid)
  560. {
  561. xwidgetnum_t widgetnum;
  562. char  pathname[128];
  563. devfs_handle_t vhdl;
  564. nasid_t nasid, peer_nasid;
  565. lboard_t *board;
  566. /* And its connected hub's nasids */
  567. nasid = COMPACT_TO_NASID_NODEID(cnodeid);
  568. peer_nasid = NODEPDA(cnodeid)->xbow_peer;
  569. /* 
  570.  * Look for paths matching "<widgetnum>/pci" under xswitchv.
  571.  * For every widget, init. its lboard's hwgraph link.  If the
  572.  * board has a PCI bridge, point the link to it.
  573.  */
  574. for (widgetnum = HUB_WIDGET_ID_MIN; widgetnum <= HUB_WIDGET_ID_MAX;
  575.  widgetnum++) {
  576. sprintf(pathname, "%d", widgetnum);
  577. if (hwgraph_traverse(xswitchv, pathname, &vhdl) !=
  578.     GRAPH_SUCCESS)
  579. continue;
  580. board = find_lboard_module((lboard_t *)KL_CONFIG_INFO(nasid),
  581. NODEPDA(cnodeid)->module_id);
  582. if (board == NULL && peer_nasid != INVALID_NASID) {
  583. /*
  584.  * Try to find the board on our peer
  585.  */
  586. board = find_lboard_module(
  587. (lboard_t *)KL_CONFIG_INFO(peer_nasid),
  588. NODEPDA(cnodeid)->module_id);
  589. }
  590. if (board == NULL) {
  591. #if defined(SUPPORT_PRINTING_V_FORMAT)
  592. printk(KERN_WARNING  "Could not find PROM info for vertex %v, "
  593. "FRU analyzer may fail",
  594. vhdl);
  595. #else
  596. printk(KERN_WARNING  "Could not find PROM info for vertex 0x%p, "
  597. "FRU analyzer may fail",
  598. (void *)vhdl);
  599. #endif
  600. return;
  601. }
  602. sprintf(pathname, "%d/"EDGE_LBL_PCI, widgetnum);
  603. if (hwgraph_traverse(xswitchv, pathname, &vhdl) == 
  604.     GRAPH_SUCCESS)
  605. board->brd_graph_link = vhdl;
  606. else
  607. board->brd_graph_link = GRAPH_VERTEX_NONE;
  608. }
  609. }
  610. /*
  611.  * Initialize all I/O on the specified node.
  612.  */
  613. static void
  614. io_init_node(cnodeid_t cnodeid)
  615. {
  616. /*REFERENCED*/
  617. devfs_handle_t hubv, switchv, widgetv;
  618. struct xwidget_hwid_s hwid;
  619. hubinfo_t hubinfo;
  620. int is_xswitch;
  621. nodepda_t *npdap;
  622. struct semaphore *peer_sema = 0;
  623. uint32_t widget_partnum;
  624. nodepda_router_info_t *npda_rip;
  625. cpu_cookie_t c = 0;
  626. extern int hubdev_docallouts(devfs_handle_t);
  627. #ifdef LATER
  628. /* Try to execute on the node that we're initializing. */
  629. c = setnoderun(cnodeid);
  630. #endif
  631. npdap = NODEPDA(cnodeid);
  632. /*
  633.  * Get the "top" vertex for this node's hardware
  634.  * graph; it will carry the per-hub hub-specific
  635.  * data, and act as the crosstalk provider master.
  636.  * It's canonical path is probably something of the
  637.  * form /hw/module/%M/slot/%d/node
  638.  */
  639. hubv = cnodeid_to_vertex(cnodeid);
  640. DBG("io_init_node: Initialize IO for cnode %d hubv(node) 0x%p npdap 0x%pn", cnodeid, hubv, npdap);
  641. ASSERT(hubv != GRAPH_VERTEX_NONE);
  642. hubdev_docallouts(hubv);
  643. /*
  644.  * Set up the dependent routers if we have any.
  645.  */
  646. npda_rip = npdap->npda_rip_first;
  647. while(npda_rip) {
  648. /* If the router info has not been initialized
  649.  * then we need to do the router initialization
  650.  */
  651. if (!npda_rip->router_infop) {
  652. router_init(cnodeid,0,npda_rip);
  653. }
  654. npda_rip = npda_rip->router_next;
  655. }
  656. /*
  657.  * Read mfg info on this hub
  658.  */
  659. #ifdef LATER
  660. printk("io_init_node: FIXME need to implement HUB_VERTEX_MFG_INFOn");
  661. HUB_VERTEX_MFG_INFO(hubv);
  662. #endif /* LATER */
  663. /* 
  664.  * If nothing connected to this hub's xtalk port, we're done.
  665.  */
  666. early_probe_for_widget(hubv, &hwid);
  667. if (hwid.part_num == XWIDGET_PART_NUM_NONE) {
  668. #ifdef PROBE_TEST
  669. if ((cnodeid == 1) || (cnodeid == 2)) {
  670. int index;
  671. for (index = 0; index < 600; index++)
  672. DBG("Interfering with device probing!!!n");
  673. }
  674. #endif
  675. /* io_init_done takes cpu cookie as 2nd argument 
  676.  * to do a restorenoderun for the setnoderun done 
  677.  * at the start of this thread 
  678.  */
  679. DBG("**** io_init_node: Node's 0x%p hub widget has XWIDGET_PART_NUM_NONE ****n", hubv);
  680. return;
  681. /* NOTREACHED */
  682. }
  683. /* 
  684.  * attach our hub_provider information to hubv,
  685.  * so we can use it as a crosstalk provider "master"
  686.  * vertex.
  687.  */
  688. xtalk_provider_register(hubv, &hub_provider);
  689. xtalk_provider_startup(hubv);
  690. /*
  691.  * Create a vertex to represent the crosstalk bus
  692.  * attached to this hub, and a vertex to be used
  693.  * as the connect point for whatever is out there
  694.  * on the other side of our crosstalk connection.
  695.  *
  696.  * Crosstalk Switch drivers "climb up" from their
  697.  * connection point to try and take over the switch
  698.  * point.
  699.  *
  700.  * Of course, the edges and verticies may already
  701.  * exist, in which case our net effect is just to
  702.  * associate the "xtalk_" driver with the connection
  703.  * point for the device.
  704.  */
  705. (void)hwgraph_path_add(hubv, EDGE_LBL_XTALK, &switchv);
  706. DBG("io_init_node: Created 'xtalk' entry to '../node/' xtalk vertex 0x%pn", switchv);
  707. ASSERT(switchv != GRAPH_VERTEX_NONE);
  708. (void)hwgraph_edge_add(hubv, switchv, EDGE_LBL_IO);
  709. DBG("io_init_node: Created symlink 'io' from ../node/io to ../node/xtalk n");
  710. /*
  711.  * We need to find the widget id and update the basew_id field
  712.  * accordingly. In particular, SN00 has direct connected bridge,
  713.  * and hence widget id is Not 0.
  714.  */
  715. widget_partnum = (((*(volatile int32_t *)(NODE_SWIN_BASE(COMPACT_TO_NASID_NODEID(cnodeid), 0) + WIDGET_ID))) & WIDGET_PART_NUM) >> WIDGET_PART_NUM_SHFT;
  716. if (widget_partnum == BRIDGE_WIDGET_PART_NUM ||
  717. widget_partnum == XBRIDGE_WIDGET_PART_NUM){
  718. npdap->basew_id = (((*(volatile int32_t *)(NODE_SWIN_BASE(COMPACT_TO_NASID_NODEID(cnodeid), 0) + BRIDGE_WID_CONTROL))) & WIDGET_WIDGET_ID);
  719. DBG("io_init_node: Found XBRIDGE widget_partnum= 0x%xn", widget_partnum);
  720. } else if (widget_partnum == XBOW_WIDGET_PART_NUM ||
  721. widget_partnum == XXBOW_WIDGET_PART_NUM) {
  722. /* 
  723.  * Xbow control register does not have the widget ID field.
  724.  * So, hard code the widget ID to be zero.
  725.  */
  726. DBG("io_init_node: Found XBOW widget_partnum= 0x%xn", widget_partnum);
  727. npdap->basew_id = 0;
  728. } else if (widget_partnum == XG_WIDGET_PART_NUM) {
  729. /* 
  730.  * OK, WTF do we do here if we have an XG direct connected to a HUB/Bedrock???
  731.  * So, hard code the widget ID to be zero?
  732.  */
  733. npdap->basew_id = 0;
  734. npdap->basew_id = (((*(volatile int32_t *)(NODE_SWIN_BASE(COMPACT_TO_NASID_NODEID(cnodeid), 0) + BRIDGE_WID_CONTROL))) & WIDGET_WIDGET_ID);
  735. } else { 
  736. npdap->basew_id = (((*(volatile int32_t *)(NODE_SWIN_BASE(COMPACT_TO_NASID_NODEID(cnodeid), 0) + BRIDGE_WID_CONTROL))) & WIDGET_WIDGET_ID);
  737. panic(" ****io_init_node: Unknown Widget Part Number 0x%x Widgt ID 0x%x attached to Hubv 0x%p ****n", widget_partnum, npdap->basew_id, (void *)hubv);
  738. /*NOTREACHED*/
  739. }
  740. {
  741. char widname[10];
  742. sprintf(widname, "%x", npdap->basew_id);
  743. (void)hwgraph_path_add(switchv, widname, &widgetv);
  744. DBG("io_init_node: Created '%s' to '..node/xtalk/' vertex 0x%pn", widname, widgetv);
  745. ASSERT(widgetv != GRAPH_VERTEX_NONE);
  746. }
  747. nodepda->basew_xc = widgetv;
  748. is_xswitch = xwidget_hwid_is_xswitch(&hwid);
  749. /* 
  750.  * Try to become the master of the widget.  If this is an xswitch
  751.  * with multiple hubs connected, only one will succeed.  Mastership
  752.  * of an xswitch is used only when touching registers on that xswitch.
  753.  * The slave xwidgets connected to the xswitch can be owned by various
  754.  * masters.
  755.  */
  756. if (device_master_set(widgetv, hubv) == 0) {
  757. /* Only one hub (thread) per Crosstalk device or switch makes
  758.  * it to here.
  759.  */
  760. /* 
  761.  * Initialize whatever xwidget is hanging off our hub.
  762.  * Whatever it is, it's accessible through widgetnum 0.
  763.  */
  764. hubinfo_get(hubv, &hubinfo);
  765. (void)xwidget_register(&hwid, widgetv, npdap->basew_id, hubv, hubinfo->h_widgetid, NULL);
  766. if (!is_xswitch) {
  767. /* io_init_done takes cpu cookie as 2nd argument 
  768.  * to do a restorenoderun for the setnoderun done 
  769.  * at the start of this thread 
  770.  */
  771. io_init_done(cnodeid,c);
  772. /* NOTREACHED */
  773. }
  774. /* 
  775.  * Special handling for Crosstalk Switches (e.g. xbow).
  776.  * We need to do things in roughly the following order:
  777.  * 1) Initialize xswitch hardware (done above)
  778.  * 2) Determine which hubs are available to be widget masters
  779.  * 3) Discover which links are active from the xswitch
  780.  * 4) Assign xwidgets hanging off the xswitch to hubs
  781.  * 5) Initialize all xwidgets on the xswitch
  782.  */
  783. volunteer_for_widgets(switchv, hubv);
  784. /* If there's someone else on this crossbow, recognize him */
  785. if (npdap->xbow_peer != INVALID_NASID) {
  786. nodepda_t *peer_npdap = NODEPDA(NASID_TO_COMPACT_NODEID(npdap->xbow_peer));
  787. peer_sema = &peer_npdap->xbow_sema;
  788. volunteer_for_widgets(switchv, peer_npdap->node_vertex);
  789. }
  790. assign_widgets_to_volunteers(switchv, hubv);
  791. /* Signal that we're done */
  792. if (peer_sema) {
  793. mutex_unlock(peer_sema);
  794. }
  795. }
  796. else {
  797.     /* Wait 'til master is done assigning widgets. */
  798.     mutex_lock(&npdap->xbow_sema);
  799. }
  800. #ifdef PROBE_TEST
  801. if ((cnodeid == 1) || (cnodeid == 2)) {
  802. int index;
  803. for (index = 0; index < 500; index++)
  804. DBG("Interfering with device probing!!!n");
  805. }
  806. #endif
  807. /* Now both nodes can safely inititialize widgets */
  808. io_init_xswitch_widgets(switchv, cnodeid);
  809. io_link_xswitch_widgets(switchv, cnodeid);
  810. /* io_init_done takes cpu cookie as 2nd argument 
  811.  * to do a restorenoderun for the setnoderun done 
  812.  * at the start of this thread 
  813.  */
  814. io_init_done(cnodeid,c);
  815. DBG("nio_init_node: DONE INITIALIZED ALL I/O FOR CNODEID %dnn", cnodeid);
  816. }
  817. #define IOINIT_STKSZ (16 * 1024)
  818. #define __DEVSTR1  "/../.master/"
  819. #define __DEVSTR2  "/target/"
  820. #define __DEVSTR3  "/lun/0/disk/partition/"
  821. #define __DEVSTR4 "/../ef"
  822. #if defined(CONFIG_IA64_SGI_SN1)
  823. /*
  824.  * Currently, we need to allow for 5 IBrick slots with 1 FC each
  825.  * plus an internal 1394.
  826.  *
  827.  * ioconfig starts numbering SCSI's at NUM_BASE_IO_SCSI_CTLR.
  828.  */
  829. #define NUM_BASE_IO_SCSI_CTLR 6
  830. #else
  831. #define NUM_BASE_IO_SCSI_CTLR 6
  832. #endif
  833. /*
  834.  * This tells ioconfig where it can start numbering scsi controllers.
  835.  * Below this base number, platform-specific handles the numbering.
  836.  * XXX Irix legacy..controller numbering should be part of devfsd's job
  837.  */
  838. int num_base_io_scsi_ctlr = 2; /* used by syssgi */
  839. devfs_handle_t base_io_scsi_ctlr_vhdl[NUM_BASE_IO_SCSI_CTLR];
  840. static devfs_handle_t baseio_enet_vhdl,baseio_console_vhdl;
  841. /*
  842.  * Put the logical controller number information in the 
  843.  * scsi controller vertices for each scsi controller that
  844.  * is in a "fixed position".
  845.  */
  846. static void
  847. scsi_ctlr_nums_add(devfs_handle_t pci_vhdl)
  848. {
  849. {
  850. int i;
  851. num_base_io_scsi_ctlr = NUM_BASE_IO_SCSI_CTLR;
  852. /* Initialize base_io_scsi_ctlr_vhdl array */
  853. for (i=0; i<NUM_BASE_IO_SCSI_CTLR; i++)
  854. base_io_scsi_ctlr_vhdl[i] = GRAPH_VERTEX_NONE;
  855. }
  856. {
  857. /*
  858.  * May want to consider changing the SN0 code, above, to work more like
  859.  * the way this works.
  860.  */
  861. devfs_handle_t base_ibrick_xbridge_vhdl;
  862. devfs_handle_t base_ibrick_xtalk_widget_vhdl;
  863. devfs_handle_t scsi_ctlr_vhdl;
  864. int i;
  865. graph_error_t rv;
  866. /*
  867.  * This is a table of "well-known" SCSI controllers and their well-known
  868.  * controller numbers.  The names in the table start from the base IBrick's
  869.  * Xbridge vertex, so the first component is the xtalk widget number.
  870.  */
  871. static struct {
  872. char *base_ibrick_scsi_path;
  873. int controller_number;
  874. } hardwired_scsi_controllers[] = {
  875. {"15/" EDGE_LBL_PCI "/1/" EDGE_LBL_SCSI_CTLR "/0", 0},
  876. {"15/" EDGE_LBL_PCI "/2/" EDGE_LBL_SCSI_CTLR "/0", 1},
  877. {"15/" EDGE_LBL_PCI "/3/" EDGE_LBL_SCSI_CTLR "/0", 2},
  878. {"14/" EDGE_LBL_PCI "/1/" EDGE_LBL_SCSI_CTLR "/0", 3},
  879. {"14/" EDGE_LBL_PCI "/2/" EDGE_LBL_SCSI_CTLR "/0", 4},
  880. {"15/" EDGE_LBL_PCI "/6/ohci/0/" EDGE_LBL_SCSI_CTLR "/0", 5},
  881. {NULL, -1} /* must be last */
  882. };
  883. base_ibrick_xtalk_widget_vhdl = hwgraph_connectpt_get(pci_vhdl);
  884. ASSERT_ALWAYS(base_ibrick_xtalk_widget_vhdl != GRAPH_VERTEX_NONE);
  885. base_ibrick_xbridge_vhdl = hwgraph_connectpt_get(base_ibrick_xtalk_widget_vhdl);
  886. ASSERT_ALWAYS(base_ibrick_xbridge_vhdl != GRAPH_VERTEX_NONE);
  887. hwgraph_vertex_unref(base_ibrick_xtalk_widget_vhdl);
  888. /*
  889.  * Iterate through the list of well-known SCSI controllers.
  890.  * For each controller found, set it's controller number according
  891.  * to the table.
  892.  */
  893. for (i=0; hardwired_scsi_controllers[i].base_ibrick_scsi_path != NULL; i++) {
  894. rv = hwgraph_path_lookup(base_ibrick_xbridge_vhdl,
  895. hardwired_scsi_controllers[i].base_ibrick_scsi_path, &scsi_ctlr_vhdl, NULL);
  896. if (rv != GRAPH_SUCCESS) /* No SCSI at this path */
  897. continue;
  898. ASSERT(hardwired_scsi_controllers[i].controller_number < NUM_BASE_IO_SCSI_CTLR);
  899. base_io_scsi_ctlr_vhdl[hardwired_scsi_controllers[i].controller_number] = scsi_ctlr_vhdl;
  900. device_controller_num_set(scsi_ctlr_vhdl, hardwired_scsi_controllers[i].controller_number);
  901. hwgraph_vertex_unref(scsi_ctlr_vhdl); /* (even though we're actually keeping a reference) */
  902. }
  903. hwgraph_vertex_unref(base_ibrick_xbridge_vhdl);
  904. }
  905. }
  906. #include <asm/sn/ioerror_handling.h>
  907. devfs_handle_t sys_critical_graph_root = GRAPH_VERTEX_NONE;
  908. /* Define the system critical vertices and connect them through
  909.  * a canonical parent-child relationships for easy traversal
  910.  * during io error handling.
  911.  */
  912. static void
  913. sys_critical_graph_init(void)
  914. {
  915. devfs_handle_t bridge_vhdl,master_node_vhdl;
  916. devfs_handle_t   xbow_vhdl = GRAPH_VERTEX_NONE;
  917. extern devfs_handle_t hwgraph_root;
  918. devfs_handle_t pci_slot_conn;
  919. int slot;
  920. devfs_handle_t baseio_console_conn;
  921. DBG("sys_critical_graph_init: FIXME.n");
  922. baseio_console_conn = hwgraph_connectpt_get(baseio_console_vhdl);
  923. if (baseio_console_conn == NULL) {
  924. return;
  925. }
  926. /* Get the vertex handle for the baseio bridge */
  927. bridge_vhdl = device_master_get(baseio_console_conn);
  928. /* Get the master node of the baseio card */
  929. master_node_vhdl = cnodeid_to_vertex(
  930. master_node_get(baseio_console_vhdl));
  931. /* Add the "root->node" part of the system critical graph */
  932. sys_critical_graph_vertex_add(hwgraph_root,master_node_vhdl);
  933. /* Check if we have a crossbow */
  934. if (hwgraph_traverse(master_node_vhdl,
  935.      EDGE_LBL_XTALK"/0",
  936.      &xbow_vhdl) == GRAPH_SUCCESS) {
  937. /* We have a crossbow.Add "node->xbow" part of the system 
  938.  * critical graph.
  939.  */
  940. sys_critical_graph_vertex_add(master_node_vhdl,xbow_vhdl);
  941. /* Add "xbow->baseio bridge" of the system critical graph */
  942. sys_critical_graph_vertex_add(xbow_vhdl,bridge_vhdl);
  943. hwgraph_vertex_unref(xbow_vhdl);
  944. } else 
  945. /* We donot have a crossbow. Add "node->baseio_bridge"
  946.  * part of the system critical graph.
  947.  */
  948. sys_critical_graph_vertex_add(master_node_vhdl,bridge_vhdl);
  949. /* Add all the populated PCI slot vertices to the system critical
  950.  * graph with the bridge vertex as the parent.
  951.  */
  952. for (slot = 0 ; slot < 8; slot++) {
  953. char slot_edge[10];
  954. sprintf(slot_edge,"%d",slot);
  955. if (hwgraph_traverse(bridge_vhdl,slot_edge, &pci_slot_conn)
  956.     != GRAPH_SUCCESS)
  957. continue;
  958. sys_critical_graph_vertex_add(bridge_vhdl,pci_slot_conn);
  959. hwgraph_vertex_unref(pci_slot_conn);
  960. }
  961. hwgraph_vertex_unref(bridge_vhdl);
  962. /* Add the "ioc3 pci connection point  -> console ioc3" part 
  963.  * of the system critical graph
  964.  */
  965. if (hwgraph_traverse(baseio_console_vhdl,"..",&pci_slot_conn) ==
  966.     GRAPH_SUCCESS) {
  967. sys_critical_graph_vertex_add(pci_slot_conn, 
  968.       baseio_console_vhdl);
  969. hwgraph_vertex_unref(pci_slot_conn);
  970. }
  971. /* Add the "ethernet pci connection point  -> base ethernet" part of 
  972.  * the system  critical graph
  973.  */
  974. if (hwgraph_traverse(baseio_enet_vhdl,"..",&pci_slot_conn) ==
  975.     GRAPH_SUCCESS) {
  976. sys_critical_graph_vertex_add(pci_slot_conn, 
  977.       baseio_enet_vhdl);
  978. hwgraph_vertex_unref(pci_slot_conn);
  979. }
  980. /* Add the "scsi controller pci connection point  -> base scsi 
  981.  * controller" part of the system critical graph
  982.  */
  983. if (hwgraph_traverse(base_io_scsi_ctlr_vhdl[0],
  984.      "../..",&pci_slot_conn) == GRAPH_SUCCESS) {
  985. sys_critical_graph_vertex_add(pci_slot_conn, 
  986.       base_io_scsi_ctlr_vhdl[0]);
  987. hwgraph_vertex_unref(pci_slot_conn);
  988. }
  989. if (hwgraph_traverse(base_io_scsi_ctlr_vhdl[1],
  990.      "../..",&pci_slot_conn) == GRAPH_SUCCESS) {
  991. sys_critical_graph_vertex_add(pci_slot_conn, 
  992.       base_io_scsi_ctlr_vhdl[1]);
  993. hwgraph_vertex_unref(pci_slot_conn);
  994. }
  995. hwgraph_vertex_unref(baseio_console_conn);
  996. }
  997. static void
  998. baseio_ctlr_num_set(void)
  999. {
  1000. char  name[MAXDEVNAME];
  1001. devfs_handle_t console_vhdl, pci_vhdl, enet_vhdl;
  1002. devfs_handle_t ioc3_console_vhdl_get(void);
  1003. DBG("baseio_ctlr_num_set; FIXMEn");
  1004. console_vhdl = ioc3_console_vhdl_get();
  1005. if (console_vhdl == GRAPH_VERTEX_NONE)
  1006. return;
  1007. /* Useful for setting up the system critical graph */
  1008. baseio_console_vhdl = console_vhdl;
  1009. vertex_to_name(console_vhdl,name,MAXDEVNAME);
  1010. strcat(name,__DEVSTR1);
  1011. pci_vhdl =  hwgraph_path_to_vertex(name);
  1012. scsi_ctlr_nums_add(pci_vhdl);
  1013. /* Unref the pci_vhdl due to the reference by hwgraph_path_to_vertex
  1014.  */
  1015. hwgraph_vertex_unref(pci_vhdl);
  1016. vertex_to_name(console_vhdl, name, MAXDEVNAME);
  1017. strcat(name, __DEVSTR4);
  1018. enet_vhdl = hwgraph_path_to_vertex(name);
  1019. /* Useful for setting up the system critical graph */
  1020. baseio_enet_vhdl = enet_vhdl;
  1021. device_controller_num_set(enet_vhdl, 0);
  1022. /* Unref the enet_vhdl due to the reference by hwgraph_path_to_vertex
  1023.  */
  1024. hwgraph_vertex_unref(enet_vhdl);
  1025. }
  1026. /* #endif */
  1027. void
  1028. sn00_rrb_alloc(devfs_handle_t vhdl, int *vendor_list)
  1029. {
  1030. /* REFERENCED */
  1031. int rtn_val;
  1032. /* 
  1033. ** sn00 population: errb orrb
  1034. ** 0- ql 3+?
  1035. ** 1- ql         2
  1036. ** 2- ioc3 ethernet 2+?
  1037. ** 3- ioc3 secondary         1
  1038. ** 4-                      0
  1039. **  5- PCI slot
  1040. **  6- PCI slot
  1041. **  7- PCI slot
  1042. */
  1043. /* The following code implements this heuristic for getting 
  1044.  * maximum usage out of the rrbs
  1045.  *
  1046.  * constraints:
  1047.  *  8 bit ql1 needs 1+1
  1048.  *  ql0 or ql5,6,7 wants 1+2
  1049.  *  ethernet wants 2 or more
  1050.  *
  1051.  * rules for even rrbs:
  1052.  *  if nothing in slot 6 
  1053.  *   4 rrbs to 0 and 2  (0xc8889999)
  1054.  *  else 
  1055.          *   3 2 3 to slots 0 2 6  (0xc8899bbb)
  1056.  *
  1057.          * rules for odd rrbs
  1058.  *  if nothing in slot 5 or 7  (0xc8889999)
  1059.  *   4 rrbs to 1 and 3
  1060.  *  else if 1 thing in 5 or 7  (0xc8899aaa) or (0xc8899bbb)
  1061.          *   3 2 3 to slots 1 3 5|7
  1062.          *  else
  1063.          *   2 1 3 2 to slots 1 3 5 7 (note: if there's a ql card in 7 this
  1064.  *           (0xc89aaabb)      may short what it wants therefore the
  1065.  *        rule should be to plug pci slots in order)
  1066.  */
  1067. if (vendor_list[6] != PCIIO_VENDOR_ID_NONE) {
  1068. /* something in slot 6 */
  1069. rtn_val = pcibr_alloc_all_rrbs(vhdl, 0, 3,1, 2,0, 0,0, 3,0);
  1070. }
  1071. else {
  1072. rtn_val = pcibr_alloc_all_rrbs(vhdl, 0, 4,1, 4,0, 0,0, 0,0);
  1073. }
  1074. if (rtn_val)
  1075. printk(KERN_WARNING  "sn00_rrb_alloc: pcibr_alloc_all_rrbs failed");
  1076. if ((vendor_list[5] != PCIIO_VENDOR_ID_NONE) && 
  1077.     (vendor_list[7] != PCIIO_VENDOR_ID_NONE)) {
  1078. /* soemthing in slot 5 and 7 */
  1079. rtn_val = pcibr_alloc_all_rrbs(vhdl, 1, 2,1, 1,0, 3,0, 2,0);
  1080. }
  1081. else if (vendor_list[5] != PCIIO_VENDOR_ID_NONE) {
  1082. /* soemthing in slot 5 but not 7 */
  1083. rtn_val = pcibr_alloc_all_rrbs(vhdl, 1, 3,1, 2,0, 3,0, 0,0);
  1084. }
  1085. else if (vendor_list[7] != PCIIO_VENDOR_ID_NONE) {
  1086. /* soemthing in slot 7 but not 5 */
  1087. rtn_val = pcibr_alloc_all_rrbs(vhdl, 1, 3,1, 2,0, 0,0, 3,0);
  1088. }
  1089. else {
  1090. /* nothing in slot 5 or 7 */
  1091. rtn_val = pcibr_alloc_all_rrbs(vhdl, 1, 4,1, 4,0, 0,0, 0,0);
  1092. }
  1093. if (rtn_val)
  1094. printk(KERN_WARNING  "sn00_rrb_alloc: pcibr_alloc_all_rrbs failed");
  1095. }
  1096. /*
  1097.  * Initialize all I/O devices.  Starting closest to nodes, probe and
  1098.  * initialize outward.
  1099.  */
  1100. void
  1101. init_all_devices(void)
  1102. {
  1103. /* Governor on init threads..bump up when safe 
  1104.  * (beware many devfs races) 
  1105.  */
  1106. #ifdef LATER
  1107. int io_init_node_threads = 2;
  1108. #endif
  1109. cnodeid_t cnodeid, active;
  1110. #ifdef LINUX_KERNEL_THREADS
  1111. sema_init(&io_init_sema, 0);
  1112. #endif
  1113. active = 0;
  1114. for (cnodeid = 0; cnodeid < numnodes; cnodeid++) {
  1115. #ifdef LINUX_KERNEL_THREADS
  1116. char thread_name[16];
  1117. extern int io_init_pri;
  1118. /*
  1119.  * Spawn a service thread for each node to initialize all
  1120.  * I/O on that node.  Each thread attempts to bind itself 
  1121.  * to the node whose I/O it's initializing.
  1122.  */
  1123. sprintf(thread_name, "IO_init[%d]", cnodeid);
  1124. (void)sthread_create(thread_name, 0, IOINIT_STKSZ, 0,
  1125. io_init_pri, KT_PS, (st_func_t *)io_init_node,
  1126. (void *)(long)cnodeid, 0, 0, 0);
  1127. #else
  1128.                 DBG("init_all_devices: Calling io_init_node() for cnode %dn", cnodeid);
  1129.                 io_init_node(cnodeid);
  1130. DBG("init_all_devices: Done io_init_node() for cnode %dn", cnodeid);
  1131. #endif /* LINUX_KERNEL_THREADS */
  1132. #ifdef LINUX_KERNEL_THREADS
  1133. /* Limit how many nodes go at once, to not overload hwgraph */
  1134. /* TBD: Should timeout */
  1135. DBG("started thread for cnode %dn", cnodeid);
  1136. active++;
  1137. if (io_init_node_threads && 
  1138. active >= io_init_node_threads) {
  1139. down(&io_init_sema);
  1140. active--;
  1141. }
  1142. #endif /* LINUX_KERNEL_THREADS */
  1143. }
  1144. #ifdef LINUX_KERNEL_THREADS
  1145. /* Wait until all IO_init threads are done */
  1146. while (active > 0) {
  1147. #ifdef AA_DEBUG
  1148.     DBG("waiting, %d still activen", active);
  1149. #endif
  1150.     down(&io_init_sema);
  1151.     active--;
  1152. }
  1153. #endif /* LINUX_KERNEL_THREADS */
  1154. for (cnodeid = 0; cnodeid < numnodes; cnodeid++)
  1155. /*
  1156.    * Update information generated by IO init.
  1157.  */
  1158. update_node_information(cnodeid);
  1159. baseio_ctlr_num_set();
  1160. /* Setup the system critical graph (which is a subgraph of the
  1161.  * main hwgraph). This information is useful during io error
  1162.  * handling.
  1163.  */
  1164. sys_critical_graph_init();
  1165. #if HWG_PRINT
  1166. hwgraph_print();
  1167. #endif
  1168. }
  1169. #define toint(x) ((int)(x) - (int)('0'))
  1170. void
  1171. devnamefromarcs(char *devnm)
  1172. {
  1173. int  val;
  1174. char  tmpnm[MAXDEVNAME];
  1175. char  *tmp1, *tmp2;
  1176. val = strncmp(devnm, "dks", 3);
  1177. if (val != 0) 
  1178. return;
  1179. tmp1 = devnm + 3;
  1180. if (!isdigit(*tmp1))
  1181. return;
  1182. val = 0;
  1183. while (isdigit(*tmp1)) {
  1184. val = 10*val+toint(*tmp1);
  1185. tmp1++;
  1186. }
  1187. if(*tmp1 != 'd')
  1188. return;
  1189. else
  1190. tmp1++;
  1191. if ((val < 0) || (val >= NUM_BASE_IO_SCSI_CTLR)) {
  1192. int i;
  1193. int viable_found = 0;
  1194. DBG("Only controller numbers 0..%d  are supported forn", NUM_BASE_IO_SCSI_CTLR-1);
  1195. DBG("prom "root" variables of the form dksXdXsX.n");
  1196. DBG("To use another disk you must use the full hardware graph pathnn");
  1197. DBG("Possible controller numbers for use in 'dksXdXsX' on this system: ");
  1198. for (i=0; i<NUM_BASE_IO_SCSI_CTLR; i++) {
  1199. if (base_io_scsi_ctlr_vhdl[i] != GRAPH_VERTEX_NONE) {
  1200. DBG("%d ", i);
  1201. viable_found=1;
  1202. }
  1203. }
  1204. if (viable_found)
  1205. DBG("n");
  1206. else
  1207. DBG("none found!n");
  1208. #ifdef LATER
  1209. if (kdebug)
  1210. debug("ring");
  1211. #endif
  1212. DELAY(15000000);
  1213. //prom_reboot();
  1214. panic("FIXME: devnamefromarcs: should call prom_reboot here.n");
  1215. /* NOTREACHED */
  1216. }
  1217. ASSERT(base_io_scsi_ctlr_vhdl[val] != GRAPH_VERTEX_NONE);
  1218. vertex_to_name(base_io_scsi_ctlr_vhdl[val],
  1219.        tmpnm,
  1220.        MAXDEVNAME);
  1221. tmp2 =  tmpnm + strlen(tmpnm);
  1222. strcpy(tmp2, __DEVSTR2);
  1223. tmp2 += strlen(__DEVSTR2);
  1224. while (*tmp1 != 's') {
  1225. if((*tmp2++ = *tmp1++) == '')
  1226. return;
  1227. }
  1228. tmp1++;
  1229. strcpy(tmp2, __DEVSTR3);
  1230. tmp2 += strlen(__DEVSTR3);
  1231. while ( (*tmp2++ = *tmp1++) )
  1232. ;
  1233. tmp2--;
  1234. *tmp2++ = '/';
  1235. strcpy(tmp2, EDGE_LBL_BLOCK);
  1236. strcpy(devnm,tmpnm);
  1237. }
  1238. static
  1239. struct io_brick_map_s io_brick_tab[] = {
  1240. /* Ibrick widget number to PCI bus number map */
  1241.   {
  1242.         'I',                                    /* Ibrick type    */ 
  1243.     /*  PCI Bus #                                  Widget #       */
  1244.      {  0, 0, 0, 0, 0, 0, 0, 0,                 /* 0x0 - 0x7      */
  1245.         0,                                      /* 0x8            */
  1246.         0,                                      /* 0x9            */
  1247.         0, 0,                                   /* 0xa - 0xb      */
  1248.         0,                                      /* 0xc            */
  1249.         0,                                      /* 0xd            */
  1250.         2,                                      /* 0xe            */
  1251.         1                                       /* 0xf            */
  1252.      }
  1253.   },
  1254. /* Pbrick widget number to PCI bus number map */
  1255.   {
  1256.         'P',                                    /* Pbrick type    */ 
  1257.     /*  PCI Bus #                                  Widget #       */
  1258.      {  0, 0, 0, 0, 0, 0, 0, 0,                 /* 0x0 - 0x7      */
  1259.         2,                                      /* 0x8            */
  1260.         1,                                      /* 0x9            */
  1261.         0, 0,                                   /* 0xa - 0xb      */
  1262.         5,                                      /* 0xc            */
  1263.         6,                                      /* 0xd            */
  1264.         4,                                      /* 0xe            */
  1265.         3                                       /* 0xf            */
  1266.      }
  1267.   },
  1268. /* Xbrick widget to XIO slot map */
  1269.   {
  1270.         'X',                                    /* Xbrick type    */ 
  1271.     /*  XIO Slot #                                 Widget #       */
  1272.      {  0, 0, 0, 0, 0, 0, 0, 0,                 /* 0x0 - 0x7      */
  1273.         1,                                      /* 0x8            */
  1274.         2,                                      /* 0x9            */
  1275.         0, 0,                                   /* 0xa - 0xb      */
  1276.         3,                                      /* 0xc            */
  1277.         4,                                      /* 0xd            */
  1278.         0,                                      /* 0xe            */
  1279.         0                                       /* 0xf            */
  1280.      }
  1281.   }
  1282. };
  1283. /*
  1284.  * Use the brick's type to map a widget number to a meaningful int
  1285.  */
  1286. int
  1287. io_brick_map_widget(char brick_type, int widget_num)
  1288. {
  1289.         int num_bricks, i;
  1290.         /* Calculate number of bricks in table */
  1291.         num_bricks = sizeof(io_brick_tab)/sizeof(io_brick_tab[0]);
  1292.         /* Look for brick prefix in table */
  1293.         for (i = 0; i < num_bricks; i++) {
  1294.                if (brick_type == io_brick_tab[i].ibm_type)
  1295.                        return(io_brick_tab[i].ibm_map_wid[widget_num]);
  1296.         }
  1297.         return 0;
  1298. }
  1299. /*
  1300.  * Use the device's vertex to map the device's widget to a meaningful int
  1301.  */
  1302. int
  1303. io_path_map_widget(devfs_handle_t vertex)
  1304. {
  1305.         char hw_path_name[MAXDEVNAME];
  1306.         char *wp, *bp, *sp = NULL;
  1307.         int  widget_num;
  1308. long atoi(char *);
  1309. int hwgraph_vertex_name_get(devfs_handle_t vhdl, char *buf, uint buflen);
  1310.         /* Get the full path name of the vertex */
  1311.         if (GRAPH_SUCCESS != hwgraph_vertex_name_get(vertex, hw_path_name,
  1312.                                                      MAXDEVNAME))
  1313.                 return 0;
  1314.         /* Find the widget number in the path name */
  1315.         wp = strstr(hw_path_name, "/"EDGE_LBL_XTALK"/");
  1316.         if (wp == NULL)
  1317.                 return 0;
  1318.         widget_num = atoi(wp+7);
  1319.         if (widget_num < XBOW_PORT_8 || widget_num > XBOW_PORT_F)
  1320.                 return 0;
  1321.         /* Find "brick" in the path name */
  1322.         bp = strstr(hw_path_name, "brick");
  1323.         if (bp == NULL)
  1324.                 return 0;
  1325.         /* Find preceding slash */
  1326.         sp = bp;
  1327.         while (sp > hw_path_name) {
  1328.                 sp--;
  1329.                 if (*sp == '/')
  1330.                         break;
  1331.         }
  1332.         /* Invalid if no preceding slash */
  1333.         if (!sp)
  1334.                 return 0;
  1335.         /* Bump slash pointer to "brick" prefix */
  1336.         sp++;
  1337.         /*
  1338.          * Verify "brick" prefix length;  valid exaples:
  1339.          * 'I' from "/Ibrick"
  1340.          * 'P' from "/Pbrick"
  1341.          * 'X' from "/Xbrick"
  1342.          */
  1343.          if ((bp - sp) != 1)
  1344.                 return 0;
  1345.         return (io_brick_map_widget(*sp, widget_num));
  1346. }