📄 pcibr_slot.c
字号:
&scsi_vhdl, NULL); if (hwg_err == GRAPH_SUCCESS) scsi_ctlr_nums_add(baseio_pci_vhdl, scsi_vhdl); /* scsi_vhdl will be the final vertex in either the complete path * on success or a partial path on failure; in either case, * unreference that vertex. */ hwgraph_vertex_unref(scsi_vhdl); hwg_err = hwgraph_path_lookup(conn_vhdl, EDGE_LBL_SCSI_CTLR "/1", &scsi_vhdl, NULL); if (hwg_err == GRAPH_SUCCESS) scsi_ctlr_nums_add(baseio_pci_vhdl, scsi_vhdl); /* scsi_vhdl will be the final vertex in either the complete path * on success or a partial path on failure; in either case, * unreference that vertex. */ hwgraph_vertex_unref(scsi_vhdl); }#endif /* PIC_LATER */ pcibr_info->f_att_det_error = error_func; if (error_func) error_slot = error_func; error = error_slot; } /* next func */ if (error) { if ((error != ENODEV) && (error != EUNATCH) && (error != EPERM)) { pcibr_soft->bs_slot[slot].slot_status &= ~SLOT_STATUS_MASK; pcibr_soft->bs_slot[slot].slot_status |= SLOT_STARTUP_INCMPLT; } } else { pcibr_soft->bs_slot[slot].slot_status &= ~SLOT_STATUS_MASK; pcibr_soft->bs_slot[slot].slot_status |= SLOT_STARTUP_CMPLT; } return(error);}/* * pcibr_slot_call_device_detach * This calls the associated driver detach routine for the PCI * card in this slot. */intpcibr_slot_call_device_detach(devfs_handle_t pcibr_vhdl, pciio_slot_t slot, int drv_flags){ pcibr_soft_t pcibr_soft; pcibr_info_h pcibr_infoh; pcibr_info_t pcibr_info; int func; devfs_handle_t conn_vhdl = GRAPH_VERTEX_NONE; int nfunc; int error_func; int error_slot = 0; int error = ENODEV; pcibr_soft = pcibr_soft_get(pcibr_vhdl); if (!pcibr_soft) return(EINVAL); if (!PCIBR_VALID_SLOT(pcibr_soft, slot)) return(EINVAL); if (pcibr_soft->bs_slot[slot].has_host) return(EPERM); nfunc = pcibr_soft->bs_slot[slot].bss_ninfo; pcibr_infoh = pcibr_soft->bs_slot[slot].bss_infos; for (func = 0; func < nfunc; ++func) { pcibr_info = pcibr_infoh[func]; if (!pcibr_info) continue; if (pcibr_info->f_vendor == PCIIO_VENDOR_ID_NONE) continue; if (IS_PCIX(pcibr_soft) && pcibr_info->f_pcix_cap) { int max_out; pcibr_soft->bs_pcix_num_funcs--; max_out = pcibr_info->f_pcix_cap->pcix_type0_status.max_out_split; pcibr_soft->bs_pcix_split_tot -= max_splittrans_to_numbuf[max_out]; } conn_vhdl = pcibr_info->f_vertex; error_func = pciio_device_detach(conn_vhdl, drv_flags); pcibr_info->f_att_det_error = error_func; if (error_func) error_slot = error_func; error = error_slot; } /* next func */ if (error) { if ((error != ENODEV) && (error != EUNATCH) && (error != EPERM)) { pcibr_soft->bs_slot[slot].slot_status &= ~SLOT_STATUS_MASK; pcibr_soft->bs_slot[slot].slot_status |= SLOT_SHUTDOWN_INCMPLT; } } else { if (conn_vhdl != GRAPH_VERTEX_NONE) pcibr_device_unregister(conn_vhdl); pcibr_soft->bs_slot[slot].slot_status &= ~SLOT_STATUS_MASK; pcibr_soft->bs_slot[slot].slot_status |= SLOT_SHUTDOWN_CMPLT; } return(error);}/* * pcibr_slot_attach * This is a place holder routine to keep track of all the * slot-specific initialization that needs to be done. * This is usually called when we want to initialize a new * PCI card on the bus. */intpcibr_slot_attach(devfs_handle_t pcibr_vhdl, pciio_slot_t slot, int drv_flags, char *l1_msg, int *sub_errorp){ pcibr_soft_t pcibr_soft = pcibr_soft_get(pcibr_vhdl);#ifdef PIC_LATER timespec_t ts;#endif int error; /* Do not allow a multi-function card to be hot-plug inserted */ if (pcibr_soft->bs_slot[slot].bss_ninfo > 1) { if (sub_errorp) *sub_errorp = EPERM; return(PCI_MULTI_FUNC_ERR); } /* Call the device attach */ error = pcibr_slot_call_device_attach(pcibr_vhdl, slot, drv_flags); if (error) { if (sub_errorp) *sub_errorp = error; if (error == EUNATCH) return(PCI_NO_DRIVER); else return(PCI_SLOT_DRV_ATTACH_ERR); } return(0);}/* * pcibr_slot_detach * This is a place holder routine to keep track of all the * slot-specific freeing that needs to be done. */intpcibr_slot_detach(devfs_handle_t pcibr_vhdl, pciio_slot_t slot, int drv_flags, char *l1_msg, int *sub_errorp){ pcibr_soft_t pcibr_soft = pcibr_soft_get(pcibr_vhdl); int error; /* Make sure that we do not detach a system critical function vertex */ if(pcibr_is_slot_sys_critical(pcibr_vhdl, slot)) return(PCI_IS_SYS_CRITICAL); /* Call the device detach function */ error = (pcibr_slot_call_device_detach(pcibr_vhdl, slot, drv_flags)); if (error) { if (sub_errorp) *sub_errorp = error; return(PCI_SLOT_DRV_DETACH_ERR); } /* Recalculate the RBARs for all the devices on the bus since we've * just freed some up and some of the devices could use them. */ if (IS_PCIX(pcibr_soft)) { int tmp_slot; pcibr_soft->bs_pcix_rbar_inuse = 0; pcibr_soft->bs_pcix_rbar_avail = NUM_RBAR; pcibr_soft->bs_pcix_rbar_percent_allowed = pcibr_pcix_rbars_calc(pcibr_soft); for (tmp_slot = pcibr_soft->bs_min_slot; tmp_slot < PCIBR_NUM_SLOTS(pcibr_soft); ++tmp_slot) (void)pcibr_slot_pcix_rbar_init(pcibr_soft, tmp_slot); } return (0);}/* * pcibr_is_slot_sys_critical * Check slot for any functions that are system critical. * Return 1 if any are system critical or 0 otherwise. * * This function will always return 0 when called by * pcibr_attach() because the system critical vertices * have not yet been set in the hwgraph. */intpcibr_is_slot_sys_critical(devfs_handle_t pcibr_vhdl, pciio_slot_t slot){ pcibr_soft_t pcibr_soft; pcibr_info_h pcibr_infoh; pcibr_info_t pcibr_info; devfs_handle_t conn_vhdl = GRAPH_VERTEX_NONE; int nfunc; int func; boolean_t is_sys_critical_vertex(devfs_handle_t); pcibr_soft = pcibr_soft_get(pcibr_vhdl); if (!pcibr_soft) return(EINVAL); if (!PCIBR_VALID_SLOT(pcibr_soft, slot)) return(EINVAL); nfunc = pcibr_soft->bs_slot[slot].bss_ninfo; pcibr_infoh = pcibr_soft->bs_slot[slot].bss_infos; for (func = 0; func < nfunc; ++func) { pcibr_info = pcibr_infoh[func]; if (!pcibr_info) continue; if (pcibr_info->f_vendor == PCIIO_VENDOR_ID_NONE) continue; conn_vhdl = pcibr_info->f_vertex; if (is_sys_critical_vertex(conn_vhdl)) { #if defined(SUPPORT_PRINTING_V_FORMAT) printk(KERN_WARNING "%v is a system critical device vertex\n", conn_vhdl);#else printk(KERN_WARNING "%p is a system critical device vertex\n", (void *)conn_vhdl);#endif return(1); } } return(0);}/* * pcibr_probe_slot_pic: read a config space word * while trapping any errors; return zero if * all went OK, or nonzero if there was an error. * The value read, if any, is passed back * through the valp parameter. */static intpcibr_probe_slot_pic(bridge_t *bridge, cfg_p cfg, unsigned *valp){ int rv; picreg_t p_old_enable = (picreg_t)0, p_new_enable; extern int badaddr_val(volatile void *, int, volatile void *); p_old_enable = bridge->p_int_enable_64; p_new_enable = p_old_enable & ~(BRIDGE_IMR_PCI_MST_TIMEOUT | PIC_ISR_PCIX_MTOUT); bridge->p_int_enable_64 = p_new_enable; if (bridge->p_err_int_view_64 & (BRIDGE_ISR_PCI_MST_TIMEOUT | PIC_ISR_PCIX_MTOUT)) bridge->p_int_rst_stat_64 = BRIDGE_IRR_MULTI_CLR; if (bridge->p_int_status_64 & (BRIDGE_IRR_PCI_GRP | PIC_PCIX_GRP_CLR)) { bridge->p_int_rst_stat_64 = (BRIDGE_IRR_PCI_GRP_CLR | PIC_PCIX_GRP_CLR); (void) bridge->b_wid_tflush; /* flushbus */ } rv = badaddr_val((void *) cfg, 4, valp); if (bridge->p_err_int_view_64 & (BRIDGE_ISR_PCI_MST_TIMEOUT | PIC_ISR_PCIX_MTOUT)) { bridge->p_int_rst_stat_64 = BRIDGE_IRR_MULTI_CLR; rv = 1; /* unoccupied slot */ } bridge->p_int_enable_64 = p_old_enable; bridge->b_wid_tflush; /* wait until Bridge PIO complete */ return(rv);}/* * pcibr_probe_slot_non_pic: read a config space word * while trapping any errors; return zero if * all went OK, or nonzero if there was an error. * The value read, if any, is passed back * through the valp parameter. */static intpcibr_probe_slot_non_pic(bridge_t *bridge, cfg_p cfg, unsigned *valp){ int rv; bridgereg_t b_old_enable = (bridgereg_t)0, b_new_enable = (bridgereg_t)0; extern int badaddr_val(volatile void *, int, volatile void *); b_old_enable = bridge->b_int_enable; b_new_enable = b_old_enable & ~BRIDGE_IMR_PCI_MST_TIMEOUT; bridge->b_int_enable = b_new_enable; /* * The xbridge doesn't clear b_err_int_view unless * multi-err is cleared... */ if (is_xbridge(bridge)) { if (bridge->b_err_int_view & BRIDGE_ISR_PCI_MST_TIMEOUT) bridge->b_int_rst_stat = BRIDGE_IRR_MULTI_CLR; } if (bridge->b_int_status & BRIDGE_IRR_PCI_GRP) { bridge->b_int_rst_stat = BRIDGE_IRR_PCI_GRP_CLR; (void) bridge->b_wid_tflush; /* flushbus */ } rv = badaddr_val((void *) (((uint64_t)cfg) ^ 4), 4, valp); /* * The xbridge doesn't set master timeout in b_int_status * here. Fortunately it's in error_interrupt_view. */ if (is_xbridge(bridge)) { if (bridge->b_err_int_view & BRIDGE_ISR_PCI_MST_TIMEOUT) { bridge->b_int_rst_stat = BRIDGE_IRR_MULTI_CLR; rv = 1; /* unoccupied slot */ } } bridge->b_int_enable = b_old_enable; bridge->b_wid_tflush; /* wait until Bridge PIO complete */ return(rv);}/* * pcibr_probe_slot: read a config space word * while trapping any errors; return zero if * all went OK, or nonzero if there was an error. * The value read, if any, is passed back * through the valp parameter. */static intpcibr_probe_slot(bridge_t *bridge, cfg_p cfg, unsigned *valp){ if ( is_pic(bridge) ) return(pcibr_probe_slot_pic(bridge, cfg, valp)); else return(pcibr_probe_slot_non_pic(bridge, cfg, valp));}voidpcibr_device_info_free(devfs_handle_t pcibr_vhdl, pciio_slot_t slot){ pcibr_soft_t pcibr_soft = pcibr_soft_get(pcibr_vhdl); pcibr_info_t pcibr_info; pciio_function_t func; pcibr_soft_slot_t slotp = &pcibr_soft->bs_slot[slot]; bridge_t *bridge = pcibr_soft->bs_base; cfg_p cfgw; int nfunc = slotp->bss_ninfo; int bar; int devio_index; int s; unsigned cmd_reg; for (func = 0; func < nfunc; func++) { pcibr_info = slotp->bss_infos[func]; if (!pcibr_info) continue; s = pcibr_lock(pcibr_soft); /* Disable memory and I/O BARs */ cfgw = pcibr_func_config_addr(bridge, 0, slot, func, 0); cmd_reg = do_pcibr_config_get(IS_PIC_SOFT(pcibr_soft), cfgw, PCI_CFG_COMMAND, 4); cmd_reg &= (PCI_CMD_MEM_SPACE | PCI_CMD_IO_SPACE); do_pcibr_config_set(IS_PIC_SOFT(pcibr_soft), cfgw, PCI_CFG_COMMAND, 4, cmd_reg); for (bar = 0; bar < PCI_CFG_BASE_ADDRS; bar++) { if (pcibr_info->f_window[bar].w_space == PCIIO_SPACE_NONE) continue; /* Free the PCI bus space */ pciibr_bus_addr_free(pcibr_soft, &pcibr_info->f_window[bar]); /* Get index of the DevIO(x) register used to access this BAR */ devio_index = pcibr_info->f_window[bar].w_devio_index;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -