/* * PIC has two buses under a single widget. pic_attach() calls pic_attach2() * to attach each of those buses. */ int pic_attach(vertex_hdl_t conn_v) { int rc; void *bridge0, *bridge1 = (void *)0; vertex_hdl_t pcibr_vhdl0, pcibr_vhdl1 = (vertex_hdl_t)0; pcibr_soft_t bus0_soft, bus1_soft = (pcibr_soft_t)0; vertex_hdl_t conn_v0, conn_v1, peer_conn_v; int bricktype; int iobrick_type_get_nasid(nasid_t nasid); PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, conn_v, "pic_attach()\n")); bridge0 = pcibr_bridge_ptr_get(conn_v, 0); bridge1 = pcibr_bridge_ptr_get(conn_v, 1); PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, conn_v, "pic_attach: bridge0=0x%lx, bridge1=0x%lx\n", bridge0, bridge1)); conn_v0 = conn_v1 = conn_v; /* If dual-ported then split the two PIC buses across both Cbricks */ peer_conn_v = pic_bus1_redist(NASID_GET(bridge0), conn_v); if (peer_conn_v) conn_v1 = peer_conn_v; /* * Create the vertex for the PCI buses, which we * will also use to hold the pcibr_soft and * which will be the "master" vertex for all the * pciio connection points we will hang off it. * This needs to happen before we call nic_bridge_vertex_info * as we are some of the *_vmc functions need access to the edges. * * Opening this vertex will provide access to * the Bridge registers themselves. */ bricktype = iobrick_type_get_nasid(NASID_GET(bridge0)); if ( bricktype == MODULE_CGBRICK ) { rc = hwgraph_path_add(conn_v0, EDGE_LBL_AGP_0, &pcibr_vhdl0); ASSERT(rc == GRAPH_SUCCESS); rc = hwgraph_path_add(conn_v1, EDGE_LBL_AGP_1, &pcibr_vhdl1); ASSERT(rc == GRAPH_SUCCESS); } else { rc = hwgraph_path_add(conn_v0, EDGE_LBL_PCIX_0, &pcibr_vhdl0); ASSERT(rc == GRAPH_SUCCESS); rc = hwgraph_path_add(conn_v1, EDGE_LBL_PCIX_1, &pcibr_vhdl1); ASSERT(rc == GRAPH_SUCCESS); } PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, conn_v, "pic_attach: pcibr_vhdl0=0x%lx, pcibr_vhdl1=0x%lx\n", pcibr_vhdl0, pcibr_vhdl1)); /* register pci provider array */ pciio_provider_register(pcibr_vhdl0, &pci_pic_provider); pciio_provider_register(pcibr_vhdl1, &pci_pic_provider); pciio_provider_startup(pcibr_vhdl0); pciio_provider_startup(pcibr_vhdl1); pic_attach2(conn_v0, bridge0, pcibr_vhdl0, 0, &bus0_soft); pic_attach2(conn_v1, bridge1, pcibr_vhdl1, 1, &bus1_soft); { /* If we're dual-ported finish duplicating the peer info structure. * The error handler and arg are done in pic_attach2(). */ xwidget_info_t info0, info1; if (conn_v0 != conn_v1) { /* dual ported */ info0 = xwidget_info_get(conn_v0); info1 = xwidget_info_get(conn_v1); if (info1->w_efunc == (error_handler_f *)NULL) info1->w_efunc = info0->w_efunc; if (info1->w_einfo == (error_handler_arg_t)0) info1->w_einfo = bus1_soft; } } /* save a pointer to the PIC's other bus's soft struct */ bus0_soft->bs_peers_soft = bus1_soft; bus1_soft->bs_peers_soft = bus0_soft; PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, conn_v, "pic_attach: bus0_soft=0x%lx, bus1_soft=0x%lx\n", bus0_soft, bus1_soft)); return 0; }
int pic_attach(vertex_hdl_t conn_v) { int rc; bridge_t *bridge0, *bridge1 = (bridge_t *)0; vertex_hdl_t pcibr_vhdl0, pcibr_vhdl1 = (vertex_hdl_t)0; pcibr_soft_t bus0_soft, bus1_soft = (pcibr_soft_t)0; vertex_hdl_t conn_v0, conn_v1, peer_conn_v; PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, conn_v, "pic_attach()\n")); bridge0 = (bridge_t *) xtalk_piotrans_addr(conn_v, NULL, 0, sizeof(bridge_t), 0); bridge1 = (bridge_t *)((char *)bridge0 + PIC_BUS1_OFFSET); PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, conn_v, "pic_attach: bridge0=0x%x, bridge1=0x%x\n", bridge0, bridge1)); conn_v0 = conn_v1 = conn_v; /* If dual-ported then split the two PIC buses across both Cbricks */ if ((peer_conn_v = (pic_bus1_redist(NASID_GET(bridge0), conn_v)))) conn_v1 = peer_conn_v; /* * Create the vertex for the PCI buses, which we * will also use to hold the pcibr_soft and * which will be the "master" vertex for all the * pciio connection points we will hang off it. * This needs to happen before we call nic_bridge_vertex_info * as we are some of the *_vmc functions need access to the edges. * * Opening this vertex will provide access to * the Bridge registers themselves. */ /* FIXME: what should the hwgraph path look like ? */ rc = hwgraph_path_add(conn_v0, EDGE_LBL_PCIX_0, &pcibr_vhdl0); ASSERT(rc == GRAPH_SUCCESS); rc = hwgraph_path_add(conn_v1, EDGE_LBL_PCIX_1, &pcibr_vhdl1); ASSERT(rc == GRAPH_SUCCESS); PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, conn_v, "pic_attach: pcibr_vhdl0=%v, pcibr_vhdl1=%v\n", pcibr_vhdl0, pcibr_vhdl1)); /* register pci provider array */ pciio_provider_register(pcibr_vhdl0, &pci_pic_provider); pciio_provider_register(pcibr_vhdl1, &pci_pic_provider); pciio_provider_startup(pcibr_vhdl0); pciio_provider_startup(pcibr_vhdl1); pcibr_attach2(conn_v0, bridge0, pcibr_vhdl0, 0, &bus0_soft); pcibr_attach2(conn_v1, bridge1, pcibr_vhdl1, 1, &bus1_soft); /* save a pointer to the PIC's other bus's soft struct */ bus0_soft->bs_peers_soft = bus1_soft; bus1_soft->bs_peers_soft = bus0_soft; PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, conn_v, "pic_attach: bus0_soft=0x%x, bus1_soft=0x%x\n", bus0_soft, bus1_soft)); return 0; }