📄 ml_iograph.c
字号:
/* * Change iobrick to correct i/o brick */#ifdef SUPPORT_PRINTING_M_FORMAT sprintf(pathname, EDGE_LBL_MODULE "/%M/"#else sprintf(pathname, EDGE_LBL_MODULE "/%x/"#endif "iobrick" "/%s/%d", NODEPDA(cnode)->module_id, EDGE_LBL_XTALK, widgetnum); } else { slot = get_widget_slotnum(0, widgetnum); board = get_board_name(nasid, module, slot, new_name); /* * Create the vertex for the widget, * using the decimal * widgetnum as the name of the primary edge. */#ifdef SUPPORT_PRINTING_M_FORMAT sprintf(pathname, EDGE_LBL_MODULE "/%M/" EDGE_LBL_SLOT "/%s/%s", NODEPDA(cnode)->module_id, slotname, new_name);#else memset(buffer, 0, 16); format_module_id(buffer, NODEPDA(cnode)->module_id, MODULE_FORMAT_BRIEF); sprintf(pathname, EDGE_LBL_MODULE "/%s/" EDGE_LBL_SLOT "/%s/%s", buffer, slotname, new_name);#endif } rc = hwgraph_path_add(hwgraph_root, pathname, &widgetv); DBG("io_xswitch_widget_init: (2) path= %s\n", pathname); /* * This is a weird ass code needed for error injection * purposes. */ rc = device_master_set(hwgraph_connectpt_get(widgetv), hubv); klhwg_baseio_inventory_add(widgetv,cnode); } sprintf(name, "%d", widgetnum); DBG("io_xswitch_widget_init: FIXME hwgraph_edge_add %s xswitchv 0x%p, widgetv 0x%p\n", name, xswitchv, widgetv); rc = hwgraph_edge_add(xswitchv, widgetv, name); /* * crosstalk switch code tracks which * widget is attached to each link. */ xswitch_info_vhdl_set(xswitch_info, widgetnum, widgetv); /* * Peek at the widget to get its crosstalk part and * mfgr numbers, then present it to the generic xtalk * bus provider to have its driver attach routine * called (or not). */#ifdef XBRIDGE_REGS_SIM widget_id = 0x2d000049; DBG("io_xswitch_widget_init: XBRIDGE_REGS_SIM FIXME: id hardwired to widget_id\n");#else widget_id = XWIDGET_ID_READ(nasid, widgetnum);#endif /* XBRIDGE_REGS_SIM */ hwid.part_num = XWIDGET_PART_NUM(widget_id); hwid.rev_num = XWIDGET_REV_NUM(widget_id); hwid.mfg_num = XWIDGET_MFG_NUM(widget_id); /* Store some inventory information about * the xwidget in the hardware graph. */ xwidget_inventory_add(widgetv,board,hwid); (void)xwidget_register(&hwid, widgetv, widgetnum, hubv, hub_widgetid, aa);#ifdef SN0_USE_BTE bte_bpush_war(cnode, (void *)board);#endif }}static voidio_init_xswitch_widgets(devfs_handle_t xswitchv, cnodeid_t cnode){ xwidgetnum_t widgetnum; async_attach_t aa; aa = async_attach_new(); DBG("io_init_xswitch_widgets: xswitchv 0x%p for cnode %d\n", xswitchv, cnode); for (widgetnum = HUB_WIDGET_ID_MIN; widgetnum <= HUB_WIDGET_ID_MAX; widgetnum++) { io_xswitch_widget_init(xswitchv, cnodeid_to_vertex(cnode), widgetnum, aa); } /* * Wait for parallel attach threads, if any, to complete. */ async_attach_waitall(aa); async_attach_free(aa);}/* * For each PCI bridge connected to the xswitch, add a link from the * board's klconfig info to the bridge's hwgraph vertex. This lets * the FRU analyzer find the bridge without traversing the hardware * graph and risking hangs. */static voidio_link_xswitch_widgets(devfs_handle_t xswitchv, cnodeid_t cnodeid){ xwidgetnum_t widgetnum; char pathname[128]; devfs_handle_t vhdl; nasid_t nasid, peer_nasid; lboard_t *board; /* And its connected hub's nasids */ nasid = COMPACT_TO_NASID_NODEID(cnodeid); peer_nasid = NODEPDA(cnodeid)->xbow_peer; /* * Look for paths matching "<widgetnum>/pci" under xswitchv. * For every widget, init. its lboard's hwgraph link. If the * board has a PCI bridge, point the link to it. */ for (widgetnum = HUB_WIDGET_ID_MIN; widgetnum <= HUB_WIDGET_ID_MAX; widgetnum++) { sprintf(pathname, "%d", widgetnum); if (hwgraph_traverse(xswitchv, pathname, &vhdl) != GRAPH_SUCCESS) continue; board = find_lboard_module((lboard_t *)KL_CONFIG_INFO(nasid), NODEPDA(cnodeid)->module_id); if (board == NULL && peer_nasid != INVALID_NASID) { /* * Try to find the board on our peer */ board = find_lboard_module( (lboard_t *)KL_CONFIG_INFO(peer_nasid), NODEPDA(cnodeid)->module_id); } if (board == NULL) {#if defined(SUPPORT_PRINTING_V_FORMAT) printk(KERN_WARNING "Could not find PROM info for vertex %v, " "FRU analyzer may fail", vhdl);#else printk(KERN_WARNING "Could not find PROM info for vertex 0x%p, " "FRU analyzer may fail", (void *)vhdl);#endif return; } sprintf(pathname, "%d/"EDGE_LBL_PCI, widgetnum); if (hwgraph_traverse(xswitchv, pathname, &vhdl) == GRAPH_SUCCESS) board->brd_graph_link = vhdl; else board->brd_graph_link = GRAPH_VERTEX_NONE; }}/* * Initialize all I/O on the specified node. */static voidio_init_node(cnodeid_t cnodeid){ /*REFERENCED*/ devfs_handle_t hubv, switchv, widgetv; struct xwidget_hwid_s hwid; hubinfo_t hubinfo; int is_xswitch; nodepda_t *npdap; struct semaphore *peer_sema = 0; uint32_t widget_partnum; nodepda_router_info_t *npda_rip; cpu_cookie_t c = 0; extern int hubdev_docallouts(devfs_handle_t);#ifdef LATER /* Try to execute on the node that we're initializing. */ c = setnoderun(cnodeid);#endif npdap = NODEPDA(cnodeid); /* * Get the "top" vertex for this node's hardware * graph; it will carry the per-hub hub-specific * data, and act as the crosstalk provider master. * It's canonical path is probably something of the * form /hw/module/%M/slot/%d/node */ hubv = cnodeid_to_vertex(cnodeid); DBG("io_init_node: Initialize IO for cnode %d hubv(node) 0x%p npdap 0x%p\n", cnodeid, hubv, npdap); ASSERT(hubv != GRAPH_VERTEX_NONE); hubdev_docallouts(hubv); /* * Set up the dependent routers if we have any. */ npda_rip = npdap->npda_rip_first; while(npda_rip) { /* If the router info has not been initialized * then we need to do the router initialization */ if (!npda_rip->router_infop) { router_init(cnodeid,0,npda_rip); } npda_rip = npda_rip->router_next; } /* * Read mfg info on this hub */#ifdef LATER printk("io_init_node: FIXME need to implement HUB_VERTEX_MFG_INFO\n"); HUB_VERTEX_MFG_INFO(hubv);#endif /* LATER */ /* * If nothing connected to this hub's xtalk port, we're done. */ early_probe_for_widget(hubv, &hwid); if (hwid.part_num == XWIDGET_PART_NUM_NONE) {#ifdef PROBE_TEST if ((cnodeid == 1) || (cnodeid == 2)) { int index; for (index = 0; index < 600; index++) DBG("Interfering with device probing!!!\n"); }#endif /* io_init_done takes cpu cookie as 2nd argument * to do a restorenoderun for the setnoderun done * at the start of this thread */ DBG("**** io_init_node: Node's 0x%p hub widget has XWIDGET_PART_NUM_NONE ****\n", hubv); return; /* NOTREACHED */ } /* * attach our hub_provider information to hubv, * so we can use it as a crosstalk provider "master" * vertex. */ xtalk_provider_register(hubv, &hub_provider); xtalk_provider_startup(hubv); /* * Create a vertex to represent the crosstalk bus * attached to this hub, and a vertex to be used * as the connect point for whatever is out there * on the other side of our crosstalk connection. * * Crosstalk Switch drivers "climb up" from their * connection point to try and take over the switch * point. * * Of course, the edges and verticies may already * exist, in which case our net effect is just to * associate the "xtalk_" driver with the connection * point for the device. */ (void)hwgraph_path_add(hubv, EDGE_LBL_XTALK, &switchv); DBG("io_init_node: Created 'xtalk' entry to '../node/' xtalk vertex 0x%p\n", switchv); ASSERT(switchv != GRAPH_VERTEX_NONE); (void)hwgraph_edge_add(hubv, switchv, EDGE_LBL_IO); DBG("io_init_node: Created symlink 'io' from ../node/io to ../node/xtalk \n"); /* * We need to find the widget id and update the basew_id field * accordingly. In particular, SN00 has direct connected bridge, * and hence widget id is Not 0. */ widget_partnum = (((*(volatile int32_t *)(NODE_SWIN_BASE(COMPACT_TO_NASID_NODEID(cnodeid), 0) + WIDGET_ID))) & WIDGET_PART_NUM) >> WIDGET_PART_NUM_SHFT; if (widget_partnum == BRIDGE_WIDGET_PART_NUM || widget_partnum == XBRIDGE_WIDGET_PART_NUM){ npdap->basew_id = (((*(volatile int32_t *)(NODE_SWIN_BASE(COMPACT_TO_NASID_NODEID(cnodeid), 0) + BRIDGE_WID_CONTROL))) & WIDGET_WIDGET_ID); DBG("io_init_node: Found XBRIDGE widget_partnum= 0x%x\n", widget_partnum); } else if (widget_partnum == XBOW_WIDGET_PART_NUM || widget_partnum == XXBOW_WIDGET_PART_NUM) { /* * Xbow control register does not have the widget ID field. * So, hard code the widget ID to be zero. */ DBG("io_init_node: Found XBOW widget_partnum= 0x%x\n", widget_partnum); npdap->basew_id = 0; } else if (widget_partnum == XG_WIDGET_PART_NUM) { /* * OK, WTF do we do here if we have an XG direct connected to a HUB/Bedrock??? * So, hard code the widget ID to be zero? */ npdap->basew_id = 0; npdap->basew_id = (((*(volatile int32_t *)(NODE_SWIN_BASE(COMPACT_TO_NASID_NODEID(cnodeid), 0) + BRIDGE_WID_CONTROL))) & WIDGET_WIDGET_ID); } else { npdap->basew_id = (((*(volatile int32_t *)(NODE_SWIN_BASE(COMPACT_TO_NASID_NODEID(cnodeid), 0) + BRIDGE_WID_CONTROL))) & WIDGET_WIDGET_ID); 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); /*NOTREACHED*/ } { char widname[10]; sprintf(widname, "%x", npdap->basew_id); (void)hwgraph_path_add(switchv, widname, &widgetv); DBG("io_init_node: Created '%s' to '..node/xtalk/' vertex 0x%p\n", widname, widgetv); ASSERT(widgetv != GRAPH_VERTEX_NONE); } nodepda->basew_xc = widgetv; is_xswitch = xwidget_hwid_is_xswitch(&hwid); /* * Try to become the master of the widget. If this is an xswitch * with multiple hubs connected, only one will succeed. Mastership * of an xswitch is used only when touching registers on that xswitch. * The slave xwidgets connected to the xswitch can be owned by various * masters. */ if (device_master_set(widgetv, hubv) == 0) { /* Only one hub (thread) per Crosstalk device or switch makes * it to here. */ /* * Initialize whatever xwidget is hanging off our hub. * Whatever it is, it's accessible through widgetnum 0. */ hubinfo_get(hubv, &hubinfo); (void)xwidget_register(&hwid, widgetv, npdap->basew_id, hubv, hubinfo->h_widgetid, NULL); if (!is_xswitch) { /* io_init_done takes cpu cookie as 2nd argument * to do a restorenoderun for the setnoderun done * at the start of this thread */ io_init_done(cnodeid,c); /* NOTREACHED */ } /* * Special handling for Crosstalk Switches (e.g. xbow). * We need to do things in roughly the following order: * 1) Initialize xswitch hardware (done above) * 2) Determine which hubs are available to be widget masters * 3) Discover which links are active from the xswitch * 4) Assign xwidgets hanging off the xswitch to hubs * 5) Initialize all xwidgets on the xswitch */ volunteer_for_widgets(switchv, hubv); /* If there's someone else on this crossbow, recognize him */ if (npdap->xbow_peer != INVALID_NASID) { nodepda_t *peer_npdap = NODEPDA(NASID_TO_COMPACT_NODEID(npdap->xbow_peer)); peer_sema = &peer_npdap->xbow_sema; volunteer_for_widgets(switchv, peer_npdap->node_vertex); } assign_widgets_to_volunteers(switchv, hubv); /* Signal that we're done */ if (peer_sema) { mutex_unlock(peer_sema); } } else { /* Wait 'til master is done assigning widgets. */ mutex_lock(&npdap->xbow_sema); }#ifdef PROBE_TEST if ((cnodeid == 1) || (cnodeid == 2)) { int index; for (index = 0; index < 500; index++) DBG("Interfering with device probing!!!\n"); }#endif /* Now both nodes can safely inititialize widgets */ io_init_xswitch_widgets(switchv, cnodeid); io_link_xswitch_widgets(switchv, cnodeid); /* io_init_done takes cpu cookie as 2nd argument * to do a restorenoderun for the setnoderun done * at the start of this thread */ io_init_done(cnodeid,c); DBG("\nio_init_node: DONE INITIALIZED ALL I/O FOR CNODEID %d\n\n", cnodeid);}#define IOINIT_STKSZ (16 * 1024)#define __DEVSTR1 "/../.master/"#define __DEVSTR2 "/target/"#define __DEVSTR3 "/lun/0/disk/partition/"#define __DEVSTR4 "/../ef"#if defined(CONFIG_IA64_SGI_SN1)/* * Currently, we need to allow for 5 IBrick slots with 1 FC each * plus an internal 1394. * * ioconfig starts numbering SCSI's at NUM_BASE_IO_SCSI_CTLR. */#define NUM_BASE_IO_SCSI_CTLR 6#else#define NUM_BASE_IO_SCSI_CTLR 6#endif/* * This tells ioconfig where it can start numbering scsi controllers. * Below this base number, platform-specific handles the numbering. * XXX Irix legacy..controller numbering should be part of devfsd's job */int num_base_io_scsi_ctlr = 2; /* used by syssgi */devfs_handle_t base_io_scsi_ctlr_vhdl[NUM_BASE_IO_SCSI_CTLR];static devfs_handle_t baseio_enet_vhdl,baseio_console_vhdl;/* * Put the logical controller number information in the * scsi controller vertices for each scsi controller that * is in a "fixed position". */static voidscsi_ctlr_nums_add(devfs_handle_t pci_vhdl){ { int i; num_base_io_scsi_ctlr = NUM_BASE_IO_SCSI_CTLR; /* Initialize base_io_scsi_ctlr_vhdl array */ for (i=0; i<NUM_BASE_IO_SCSI_CTLR; i++) base_io_scsi_ctlr_vhdl[i] = GRAPH_VERTEX_NONE; } { /* * May want to consider changing the SN0 code, above, to work more like * the way this works. */ devfs_handle_t base_ibrick_xbridge_vhdl; devfs_handle_t base_ibrick_xtalk_widget_vhdl; devfs_handle_t scsi_ctlr_vhdl; int i; graph_error_t rv; /* * This is a table of "well-known" SCSI controllers and their well-known * controller numbers. The names in the table start from the base IBrick's * Xbridge vertex, so the first component is the xtalk widget number. */ static struct { char *base_ibrick_scsi_path; int controller_number; } hardwired_scsi_controllers[] = { {"15/" EDGE_LBL_PCI "/1/" EDGE_LBL_SCSI_CTLR "/0", 0}, {"15/" EDGE_LBL_PCI "/2/" EDGE_LBL_SCSI_CTLR "/0", 1}, {"15/" EDGE_LBL_PCI "/3/" EDGE_LBL_SCSI_CTLR "/0", 2}, {"14/" EDGE_LBL_PCI "/1/" EDGE_LBL_SCSI_CTLR "/0", 3}, {"14/" EDGE_LBL_PCI "/2/" EDGE_LBL_SCSI_CTLR "/0", 4}, {"15/" EDGE_LBL_PCI "/6/ohci/0/" EDGE_LBL_SCSI_CTLR "/0", 5}, {NULL, -1} /* must be last */ }; base_ibrick_xtalk_widget_vhdl = hwgraph_connectpt_get(pci_vhdl); ASSERT_ALWAYS(base_ibrick_xtalk_widget_vhdl != GRAPH_VERTEX_NONE); base_ibrick_xbridge_vhdl = hwgraph_connectpt_get(base_ibrick_xtalk_widget_vhdl); ASSERT_ALWAYS(base_ibrick_xbridge_vhdl != GRAPH_VERTEX_NONE); hwgraph_vertex_unref(base_ibrick_xtalk_widget_vhdl); /* * Iterate through the list of well-known SCSI controllers. * For each controller found, set it's controller number according * to the table. */ for (i=0; hardwired_scsi_controllers[i].base_ibrick_scsi_path != NULL; i++) { rv = hwgraph_path_lookup(base_ibrick_xbridge_vhdl, hardwired_scsi_controllers[i].base_ibrick_scsi_path, &scsi_ctlr_vhdl, NULL); if (rv != GRAPH_SUCCESS) /* No SCSI at this path */ continue; ASSERT(hardwired_scsi_controllers[i].controller_number < NUM_BASE_IO_SCSI_CTLR); base_io_scsi_ctlr_vhdl[hardwired_scsi_controllers[i].controller_number] = scsi_ctlr_vhdl; device_controller_num_set(scsi_ctlr_vhdl, hardwired_scsi_controllers[i].controller_number); hwgraph_vertex_unref(scsi_ctlr_vhdl); /* (even though we're actually keeping a reference) */ }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -