📄 pcibr_dvr.c
字号:
while (tdev != GRAPH_VERTEX_NONE) { pciio_info = pciio_info_chk(tdev); if (pciio_info) { slot = PCIBR_INFO_SLOT_GET_INT(pciio_info); break; } hwgraph_vertex_unref(tdev); tdev = hwgraph_connectpt_get(tdev); } hwgraph_vertex_unref(tdev); return slot;}/*ARGSUSED */intpcibr_ioctl(devfs_handle_t dev, int cmd, void *arg, int flag, struct cred *cr, int *rvalp){ return 0;}pcibr_info_tpcibr_info_get(devfs_handle_t vhdl){ return (pcibr_info_t) pciio_info_get(vhdl);}pcibr_info_tpcibr_device_info_new( pcibr_soft_t pcibr_soft, pciio_slot_t slot, pciio_function_t rfunc, pciio_vendor_id_t vendor, pciio_device_id_t device){ pcibr_info_t pcibr_info; pciio_function_t func; int ibit; func = (rfunc == PCIIO_FUNC_NONE) ? 0 : rfunc; /* * Create a pciio_info_s for this device. pciio_device_info_new() * will set the c_slot (which is suppose to represent the external * slot (i.e the slot number silk screened on the back of the I/O * brick)). So for PIC we need to adjust this "internal slot" num * passed into us, into it's external representation. See comment * for the PCIBR_DEVICE_TO_SLOT macro for more information. */ NEW(pcibr_info); pciio_device_info_new(&pcibr_info->f_c, pcibr_soft->bs_vhdl, PCIBR_DEVICE_TO_SLOT(pcibr_soft, slot), rfunc, vendor, device); pcibr_info->f_dev = slot; /* Set PCI bus number */ pcibr_info->f_bus = pcibr_widget_to_bus(pcibr_soft->bs_vhdl); if (slot != PCIIO_SLOT_NONE) { /* * Currently favored mapping from PCI * slot number and INTA/B/C/D to Bridge * PCI Interrupt Bit Number: * * SLOT A B C D * 0 0 4 0 4 * 1 1 5 1 5 * 2 2 6 2 6 * 3 3 7 3 7 * 4 4 0 4 0 * 5 5 1 5 1 * 6 6 2 6 2 * 7 7 3 7 3 * * XXX- allow pcibr_hints to override default * XXX- allow ADMIN to override pcibr_hints */ for (ibit = 0; ibit < 4; ++ibit) pcibr_info->f_ibit[ibit] = (slot + 4 * ibit) & 7; /* * Record the info in the sparse func info space. */ if (func < pcibr_soft->bs_slot[slot].bss_ninfo) pcibr_soft->bs_slot[slot].bss_infos[func] = pcibr_info; } return pcibr_info;}/* * pcibr_device_unregister * This frees up any hardware resources reserved for this PCI device * and removes any PCI infrastructural information setup for it. * This is usually used at the time of shutting down of the PCI card. */intpcibr_device_unregister(devfs_handle_t pconn_vhdl){ pciio_info_t pciio_info; devfs_handle_t pcibr_vhdl; pciio_slot_t slot; pcibr_soft_t pcibr_soft; bridge_t *bridge; int count_vchan0, count_vchan1; unsigned s; int error_call; int error = 0; pciio_info = pciio_info_get(pconn_vhdl); pcibr_vhdl = pciio_info_master_get(pciio_info); slot = PCIBR_INFO_SLOT_GET_INT(pciio_info); pcibr_soft = pcibr_soft_get(pcibr_vhdl); bridge = pcibr_soft->bs_base; /* Clear all the hardware xtalk resources for this device */ xtalk_widgetdev_shutdown(pcibr_soft->bs_conn, slot); /* Flush all the rrbs */ pcibr_rrb_flush(pconn_vhdl); /* * If the RRB configuration for this slot has changed, set it * back to the boot-time default */ if (pcibr_soft->bs_rrb_valid_dflt[slot][VCHAN0] >= 0) { s = pcibr_lock(pcibr_soft); /* PIC NOTE: If this is a BRIDGE, VCHAN2 & VCHAN3 will be zero so * no need to conditionalize this (ie. "if (IS_PIC_SOFT())" ). */ pcibr_soft->bs_rrb_res[slot] = pcibr_soft->bs_rrb_res[slot] + pcibr_soft->bs_rrb_valid[slot][VCHAN0] + pcibr_soft->bs_rrb_valid[slot][VCHAN1] + pcibr_soft->bs_rrb_valid[slot][VCHAN2] + pcibr_soft->bs_rrb_valid[slot][VCHAN3]; /* Free the rrbs allocated to this slot, both the normal & virtual */ do_pcibr_rrb_free_all(pcibr_soft, bridge, slot); count_vchan0 = pcibr_soft->bs_rrb_valid_dflt[slot][VCHAN0]; count_vchan1 = pcibr_soft->bs_rrb_valid_dflt[slot][VCHAN1]; pcibr_unlock(pcibr_soft, s); pcibr_rrb_alloc(pconn_vhdl, &count_vchan0, &count_vchan1); } /* Flush the write buffers !! */ error_call = pcibr_wrb_flush(pconn_vhdl); if (error_call) error = error_call; /* Clear the information specific to the slot */ error_call = pcibr_slot_info_free(pcibr_vhdl, slot); if (error_call) error = error_call; return(error); }/* * pcibr_driver_reg_callback * CDL will call this function for each device found in the PCI * registry that matches the vendor/device IDs supported by * the driver being registered. The device's connection vertex * and the driver's attach function return status enable the * slot's device status to be set. */voidpcibr_driver_reg_callback(devfs_handle_t pconn_vhdl, int key1, int key2, int error){ pciio_info_t pciio_info; pcibr_info_t pcibr_info; devfs_handle_t pcibr_vhdl; pciio_slot_t slot; pcibr_soft_t pcibr_soft; /* Do not set slot status for vendor/device ID wildcard drivers */ if ((key1 == -1) || (key2 == -1)) return; pciio_info = pciio_info_get(pconn_vhdl); pcibr_info = pcibr_info_get(pconn_vhdl); pcibr_vhdl = pciio_info_master_get(pciio_info); slot = PCIBR_INFO_SLOT_GET_INT(pciio_info); pcibr_soft = pcibr_soft_get(pcibr_vhdl);#ifdef PIC_LATER /* This may be a loadable driver so lock out any pciconfig actions */ mrlock(pcibr_soft->bs_bus_lock, MR_UPDATE, PZERO);#endif pcibr_info->f_att_det_error = error; pcibr_soft->bs_slot[slot].slot_status &= ~SLOT_STATUS_MASK; if (error) { pcibr_soft->bs_slot[slot].slot_status |= SLOT_STARTUP_INCMPLT; } else { pcibr_soft->bs_slot[slot].slot_status |= SLOT_STARTUP_CMPLT; } #ifdef PIC_LATER /* Release the bus lock */ mrunlock(pcibr_soft->bs_bus_lock);#endif}/* * pcibr_driver_unreg_callback * CDL will call this function for each device found in the PCI * registry that matches the vendor/device IDs supported by * the driver being unregistered. The device's connection vertex * and the driver's detach function return status enable the * slot's device status to be set. */voidpcibr_driver_unreg_callback(devfs_handle_t pconn_vhdl, int key1, int key2, int error){ pciio_info_t pciio_info; pcibr_info_t pcibr_info; devfs_handle_t pcibr_vhdl; pciio_slot_t slot; pcibr_soft_t pcibr_soft; /* Do not set slot status for vendor/device ID wildcard drivers */ if ((key1 == -1) || (key2 == -1)) return; pciio_info = pciio_info_get(pconn_vhdl); pcibr_info = pcibr_info_get(pconn_vhdl); pcibr_vhdl = pciio_info_master_get(pciio_info); slot = PCIBR_INFO_SLOT_GET_INT(pciio_info); pcibr_soft = pcibr_soft_get(pcibr_vhdl);#ifdef PIC_LATER /* This may be a loadable driver so lock out any pciconfig actions */ mrlock(pcibr_soft->bs_bus_lock, MR_UPDATE, PZERO);#endif pcibr_info->f_att_det_error = error; pcibr_soft->bs_slot[slot].slot_status &= ~SLOT_STATUS_MASK; if (error) { pcibr_soft->bs_slot[slot].slot_status |= SLOT_SHUTDOWN_INCMPLT; } else { pcibr_soft->bs_slot[slot].slot_status |= SLOT_SHUTDOWN_CMPLT; }#ifdef PIC_LATER /* Release the bus lock */ mrunlock(pcibr_soft->bs_bus_lock);#endif}/* * build a convenience link path in the * form of ".../<iobrick>/bus/<busnum>" * * returns 1 on success, 0 otherwise * * depends on hwgraph separator == '/' */intpcibr_bus_cnvlink(devfs_handle_t f_c){ char dst[MAXDEVNAME]; char *dp = dst; char *cp, *xp; int widgetnum; char pcibus[8]; devfs_handle_t nvtx, svtx; int rv; PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, f_c, "pcibr_bus_cnvlink\n")); if (GRAPH_SUCCESS != hwgraph_vertex_name_get(f_c, dst, MAXDEVNAME)) return 0; /* dst example == /hw/module/001c02/Pbrick/xtalk/8/pci/direct */ /* find the widget number */ xp = strstr(dst, "/"EDGE_LBL_XTALK"/"); if (xp == NULL) return 0; widgetnum = atoi(xp+7); if (widgetnum < XBOW_PORT_8 || widgetnum > XBOW_PORT_F) return 0; /* remove "/pci/direct" from path */ cp = strstr(dst, "/" EDGE_LBL_PCI "/" EDGE_LBL_DIRECT); if (cp == NULL) return 0; *cp = (char)NULL; /* get the vertex for the widget */ if (GRAPH_SUCCESS != hwgraph_traverse(NULL, dp, &svtx)) return 0; *xp = (char)NULL; /* remove "/xtalk/..." from path */ /* dst example now == /hw/module/001c02/Pbrick */ /* get the bus number */ strcat(dst, "/"); strcat(dst, EDGE_LBL_BUS); sprintf(pcibus, "%d", p_busnum[widgetnum]); /* link to bus to widget */ rv = hwgraph_path_add(NULL, dp, &nvtx); if (GRAPH_SUCCESS == rv) rv = hwgraph_edge_add(nvtx, svtx, pcibus); return (rv == GRAPH_SUCCESS);}/* * pcibr_attach: called every time the crosstalk * infrastructure is asked to initialize a widget * that matches the part number we handed to the * registration routine above. *//*ARGSUSED */intpcibr_attach(devfs_handle_t xconn_vhdl){ /* REFERENCED */ graph_error_t rc; devfs_handle_t pcibr_vhdl; bridge_t *bridge; PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, xconn_vhdl, "pcibr_attach\n")); bridge = (bridge_t *) xtalk_piotrans_addr(xconn_vhdl, NULL, 0, sizeof(bridge_t), 0); /* * Create the vertex for the PCI bus, 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. */ rc = hwgraph_path_add(xconn_vhdl, EDGE_LBL_PCI, &pcibr_vhdl); ASSERT(rc == GRAPH_SUCCESS); pciio_provider_register(pcibr_vhdl, &pcibr_provider); pciio_provider_startup(pcibr_vhdl); return pcibr_attach2(xconn_vhdl, bridge, pcibr_vhdl, 0, NULL);}/*ARGSUSED */intpcibr_attach2(devfs_handle_t xconn_vhdl, bridge_t *bridge, devfs_handle_t pcibr_vhdl, int busnum, pcibr_soft_t *ret_softp){ /* REFERENCED */ devfs_handle_t ctlr_vhdl; bridgereg_t id; int rev; pcibr_soft_t pcibr_soft; pcibr_info_t pcibr_info; xwidget_info_t info; xtalk_intr_t xtalk_intr; int slot; int ibit; devfs_handle_t noslot_conn; char devnm[MAXDEVNAME], *s; pcibr_hints_t pcibr_hints; uint64_t int_enable; bridgereg_t int_enable_32;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -