📄 pcibr_slot.c
字号:
if (pcibr_soft->bs_slot[slot].has_host) { return(EPERM); } xconn_vhdl = pcibr_soft->bs_conn; aa = async_attach_get_info(xconn_vhdl); 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;#ifdef LATER /* * Activate if and when we support cdl. */ if (aa) async_attach_add_info(conn_vhdl, aa);#endif /* LATER */ error_func = pciio_device_attach(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)) pcibr_soft->bs_slot[slot].slot_status |= SLOT_STARTUP_INCMPLT; } else { 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 || !PCIBR_VALID_SLOT(slot)) return(EINVAL); if (pcibr_soft->bs_slot[slot].has_host) return(EPERM); /* Make sure that we do not detach a system critical function vertex */ if(pcibr_is_slot_sys_critical(pcibr_vhdl, slot)) 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; 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 */ pcibr_soft->bs_slot[slot].slot_status &= ~SLOT_STATUS_MASK; if (error) { if ((error != ENODEV) && (error != EUNATCH)) 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_SHUTDOWN_CMPLT; } return(error);}#ifdef LATER/* * 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); timespec_t ts; int error; if (!(pcibr_soft->bs_slot[slot].slot_status & SLOT_POWER_UP)) { /* Power-up the slot */ error = pcibr_slot_pwr(pcibr_vhdl, slot, L1_REQ_PCI_UP, l1_msg); if (error) { if (sub_errorp) *sub_errorp = error; return(PCI_L1_ERR); } else { pcibr_soft->bs_slot[slot].slot_status &= ~SLOT_POWER_MASK; pcibr_soft->bs_slot[slot].slot_status |= SLOT_POWER_UP; }#ifdef LATER /* * Allow cards like the Alteon Gigabit Ethernet Adapter to complete * on-card initialization following the slot reset */ ts.tv_sec = 0; /* 0 secs */ ts.tv_nsec = 500 * (1000 * 1000); /* 500 msecs */ nano_delay(&ts);#else#endif#if 0 /* Reset the slot */ error = pcibr_slot_reset(pcibr_vhdl, slot) if (error) { if (sub_errorp) *sub_errorp = error; return(PCI_SLOT_RESET_ERR); }#endif /* Find out what is out there */ error = pcibr_slot_info_init(pcibr_vhdl, slot); if (error) { if (sub_errorp) *sub_errorp = error; return(PCI_SLOT_INFO_INIT_ERR); } /* Set up the address space for this slot in the PCI land */ error = pcibr_slot_addr_space_init(pcibr_vhdl, slot); if (error) { if (sub_errorp) *sub_errorp = error; return(PCI_SLOT_ADDR_INIT_ERR); } /* Setup the device register */ error = pcibr_slot_device_init(pcibr_vhdl, slot); if (error) { if (sub_errorp) *sub_errorp = error; return(PCI_SLOT_DEV_INIT_ERR); } /* Setup host/guest relations */ error = pcibr_slot_guest_info_init(pcibr_vhdl, slot); if (error) { if (sub_errorp) *sub_errorp = error; return(PCI_SLOT_GUEST_INIT_ERR); } /* Initial RRB management */ error = pcibr_slot_initial_rrb_alloc(pcibr_vhdl, slot); if (error) { if (sub_errorp) *sub_errorp = error; return(PCI_SLOT_RRB_ALLOC_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);}#endif /* LATER *//* * 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){ int error; /* Call the device detach function */ error = (pcibr_slot_call_device_detach(pcibr_vhdl, slot, drv_flags)); return (error);}/* * 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 || !PCIBR_VALID_SLOT(slot)) return(0); 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: read a config space word * while trapping any errors; reutrn zero if * all went OK, or nonzero if there was an error. * The value read, if any, is passed back * through the valp parameter. */intpcibr_probe_slot(bridge_t *bridge, cfg_p cfg, unsigned *valp){ int rv; bridgereg_t old_enable, new_enable; int badaddr_val(volatile void *, int, volatile void *); old_enable = bridge->b_int_enable; new_enable = old_enable & ~BRIDGE_IMR_PCI_MST_TIMEOUT; bridge->b_int_enable = 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 *) cfg, 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 = old_enable; bridge->b_wid_tflush; /* wait until Bridge PIO complete */ return rv;}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]; int nfunc = slotp->bss_ninfo; int bar; int devio_index; int s; for (func = 0; func < nfunc; func++) { pcibr_info = slotp->bss_infos[func]; if (!pcibr_info) continue; s = pcibr_lock(pcibr_soft); for (bar = 0; bar < PCI_CFG_BASE_ADDRS; bar++) { if (pcibr_info->f_window[bar].w_space == PCIIO_SPACE_NONE) continue; /* Get index of the DevIO(x) register used to access this BAR */ devio_index = pcibr_info->f_window[bar].w_devio_index; /* On last use, clear the DevIO(x) used to access this BAR */ if (! --pcibr_soft->bs_slot[devio_index].bss_devio.bssd_ref_cnt) { pcibr_soft->bs_slot[devio_index].bss_devio.bssd_space = PCIIO_SPACE_NONE; pcibr_soft->bs_slot[devio_index].bss_devio.bssd_base = PCIBR_D32_BASE_UNSET; pcibr_soft->bs_slot[devio_index].bss_device = 0; } } pcibr_unlock(pcibr_soft, s); slotp->bss_infos[func] = 0; pciio_device_info_unregister(pcibr_vhdl, &pcibr_info->f_c); pciio_device_info_free(&pcibr_info->f_c); DEL(pcibr_info); } /* Reset the mapping usage counters */ slotp->bss_pmu_uctr = 0; slotp->bss_d32_uctr = 0; slotp->bss_d64_uctr = 0; /* Clear the Direct translation info */ slotp->bss_d64_base = PCIBR_D64_BASE_UNSET; slotp->bss_d64_flags = 0; slotp->bss_d32_base = PCIBR_D32_BASE_UNSET; slotp->bss_d32_flags = 0; /* Clear out shadow info necessary for the external SSRAM workaround */ slotp->bss_ext_ates_active = ATOMIC_INIT(0); slotp->bss_cmd_pointer = 0; slotp->bss_cmd_shadow = 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -