📄 pcibr_slot.c
字号:
nfunc = pcibr_soft->bs_slot[slot].bss_ninfo; if (nfunc < 1) return(EINVAL); pcibr_infoh = pcibr_soft->bs_slot[slot].bss_infos; if (!pcibr_infoh) return(EINVAL); /* * Try to make the DevIO windows not * overlap by pushing the "io" and "hi" * allocation areas up to the next one * or two megabyte bound. This also * keeps them from being zero. * * DO NOT do this with "pci_lo" since * the entire "lo" area is only a * megabyte, total ... */ align_slot = (slot < 2) ? 0x200000 : 0x100000; for (func = 0; func < nfunc; ++func) { cfg_p cfgw; cfg_p wptr; pciio_space_t space; iopaddr_t base; size_t size;#ifdef PCI_LATER char tmp_str[256];#endif unsigned pci_cfg_cmd_reg; unsigned pci_cfg_cmd_reg_add = 0; pcibr_info = pcibr_infoh[func]; if (!pcibr_info) continue; if (pcibr_info->f_vendor == PCIIO_VENDOR_ID_NONE) continue; cfgw = pcibr_func_config_addr(bridge, 0, slot, func, 0); wptr = cfgw + PCI_CFG_BASE_ADDR_0 / 4; if ((do_pcibr_config_get(IS_PIC_SOFT(pcibr_soft), cfgw, PCI_CFG_HEADER_TYPE, 1) & 0x7f) != 0) nbars = 2; else nbars = PCI_CFG_BASE_ADDRS; for (win = 0; win < nbars; ++win) { space = pcibr_info->f_window[win].w_space; base = pcibr_info->f_window[win].w_base; size = pcibr_info->f_window[win].w_size; if (size < 1) continue; if (base >= size) { /* * The kernel only allows functions to have so many variable * args attempting to call PCIBR_DEBUG_ALWAYS() with more than * 5 printf arguments fails so sprintf() it into a temporary * string (tmp_str). */#if defined(SUPPORT_PRINTING_R_FORMAT) if (pcibr_debug_mask & PCIBR_DEBUG_BAR) { sprintf(tmp_str, "pcibr_slot_addr_space_init: slot=%d, " "func=%d win %d is in %r [0x%x..0x%x], allocated by " "prom\n", PCIBR_DEVICE_TO_SLOT(pcibr_soft, slot), func, win, space, space_desc, base, base + size - 1); PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_BAR, pcibr_vhdl, "%s",tmp_str)); }#endif /* SUPPORT_PRINTING_R_FORMAT */ continue; /* already allocated */ } switch (space) { case PCIIO_SPACE_IO: base = pcibr_bus_addr_alloc(pcibr_soft, &pcibr_info->f_window[win], PCIIO_SPACE_IO, 0, size, align_slot); if (!base) rc = ENOSPC; break; case PCIIO_SPACE_MEM: if ((do_pcibr_config_get(IS_PIC_SOFT(pcibr_soft), wptr, (win * 4), 4) & PCI_BA_MEM_LOCATION) == PCI_BA_MEM_1MEG) { int align = size; /* ie. 0x00001000 */ if (align < _PAGESZ) align = _PAGESZ; /* ie. 0x00004000 */ /* allocate from 20-bit PCI space */ base = pcibr_bus_addr_alloc(pcibr_soft, &pcibr_info->f_window[win], PCIIO_SPACE_MEM, 0, size, align); if (!base) rc = ENOSPC; } else { /* allocate from 32-bit or 64-bit PCI space */ base = pcibr_bus_addr_alloc(pcibr_soft, &pcibr_info->f_window[win], PCIIO_SPACE_MEM32, 0, size, align_slot); if (!base) rc = ENOSPC; } break; default: base = 0; PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_BAR, pcibr_vhdl, "pcibr_slot_addr_space_init: slot=%d, window %d " "had bad space code %d\n", PCIBR_DEVICE_TO_SLOT(pcibr_soft,slot), win, space)); } pcibr_info->f_window[win].w_base = base; do_pcibr_config_set(IS_PIC_SOFT(pcibr_soft), wptr, (win * 4), 4, base);#if defined(SUPPORT_PRINTING_R_FORMAT) if (pcibr_debug_mask & PCIBR_DEBUG_BAR) { if (base >= size) { sprintf(tmp_str,"pcibr_slot_addr_space_init: slot=%d, func=" "%d, win %d is in %r[0x%x..0x%x], " "allocated by pcibr\n", PCIBR_DEVICE_TO_SLOT(pcibr_soft, slot), func, win, space, space_desc, base, base + size - 1); PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_BAR, pcibr_vhdl, "%s",tmp_str)); } else { sprintf(tmp_str,"pcibr_slot_addr_space_init: slot=%d, func=" "%d, win %d, unable to alloc 0x%x in %r\n", PCIBR_DEVICE_TO_SLOT(pcibr_soft, slot), func, win, size, space, space_desc); PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_BAR, pcibr_vhdl, "%s",tmp_str)); } }#endif /* SUPPORT_PRINTING_R_FORMAT */ } /* next base */ /* * Allocate space for the EXPANSION ROM * NOTE: DO NOT DO THIS ON AN IOC3, * as it blows the system away. */ base = size = 0; if ((pcibr_soft->bs_slot[slot].bss_vendor_id != IOC3_VENDOR_ID_NUM) || (pcibr_soft->bs_slot[slot].bss_device_id != IOC3_DEVICE_ID_NUM)) { wptr = cfgw + PCI_EXPANSION_ROM / 4; do_pcibr_config_set(IS_PIC_SOFT(pcibr_soft), wptr, 0, 4, 0xFFFFF000); mask = do_pcibr_config_get(IS_PIC_SOFT(pcibr_soft), wptr, 0, 4); if (mask & 0xFFFFF000) { size = mask & -mask; base = pcibr_bus_addr_alloc(pcibr_soft, &pcibr_info->f_rwindow, PCIIO_SPACE_MEM32, 0, size, align_slot); if (!base) rc = ENOSPC; else { do_pcibr_config_set(IS_PIC_SOFT(pcibr_soft), wptr, 0, 4, base); PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_BAR, pcibr_vhdl, "pcibr_slot_addr_space_init: slot=%d, func=%d, " "ROM in [0x%X..0x%X], allocated by pcibr\n", PCIBR_DEVICE_TO_SLOT(pcibr_soft, slot), func, base, base + size - 1)); } } } pcibr_info->f_rbase = base; pcibr_info->f_rsize = size; /* * if necessary, update the board's * command register to enable decoding * in the windows we added. * * There are some bits we always want to * be sure are set. */ pci_cfg_cmd_reg_add |= PCI_CMD_IO_SPACE; /* * The Adaptec 1160 FC Controller WAR #767995: * The part incorrectly ignores the upper 32 bits of a 64 bit * address when decoding references to it's registers so to * keep it from responding to a bus cycle that it shouldn't * we only use I/O space to get at it's registers. Don't * enable memory space accesses on that PCI device. */ #define FCADP_VENDID 0x9004 /* Adaptec Vendor ID from fcadp.h */ #define FCADP_DEVID 0x1160 /* Adaptec 1160 Device ID from fcadp.h */ if ((pcibr_info->f_vendor != FCADP_VENDID) || (pcibr_info->f_device != FCADP_DEVID)) pci_cfg_cmd_reg_add |= PCI_CMD_MEM_SPACE; pci_cfg_cmd_reg_add |= PCI_CMD_BUS_MASTER; pci_cfg_cmd_reg = do_pcibr_config_get(IS_PIC_SOFT(pcibr_soft), cfgw, PCI_CFG_COMMAND, 4);#if PCI_FBBE /* XXX- check here to see if dev can do fast-back-to-back */ if (!((pci_cfg_cmd_reg >> 16) & PCI_STAT_F_BK_BK_CAP)) fast_back_to_back_enable = 0;#endif pci_cfg_cmd_reg &= 0xFFFF; if (pci_cfg_cmd_reg_add & ~pci_cfg_cmd_reg) do_pcibr_config_set(IS_PIC_SOFT(pcibr_soft), cfgw, PCI_CFG_COMMAND, 4, pci_cfg_cmd_reg | pci_cfg_cmd_reg_add); } /* next func */ return(rc);}/* * pcibr_slot_device_init * Setup the device register in the bridge for this PCI slot. */intpcibr_slot_device_init(devfs_handle_t pcibr_vhdl, pciio_slot_t slot){ pcibr_soft_t pcibr_soft; bridge_t *bridge; bridgereg_t devreg; pcibr_soft = pcibr_soft_get(pcibr_vhdl); if (!pcibr_soft) return(EINVAL); if (!PCIBR_VALID_SLOT(pcibr_soft, slot)) return(EINVAL); bridge = pcibr_soft->bs_base; /* * Adjustments to Device(x) * and init of bss_device shadow */ devreg = bridge->b_device[slot].reg; devreg &= ~BRIDGE_DEV_PAGE_CHK_DIS; /* * PIC WAR. PV# 855271 * Don't enable virtual channels in the PIC by default. * Can cause problems with 32-bit devices. (The bit is only intended * for 64-bit devices). We set the bit in pcibr_try_set_device() * if we're 64-bit and requesting virtual channels. */ if (IS_PIC_SOFT(pcibr_soft) && PCIBR_WAR_ENABLED(PV855271, pcibr_soft)) devreg |= BRIDGE_DEV_COH; else devreg |= BRIDGE_DEV_COH | BRIDGE_DEV_VIRTUAL_EN; pcibr_soft->bs_slot[slot].bss_device = devreg; bridge->b_device[slot].reg = devreg;#ifdef PIC_LATER PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_DEVREG, pcibr_vhdl, "pcibr_slot_device_init: Device(%d): %R\n", slot, devreg, device_bits));#else printk("pcibr_slot_device_init: Device(%d) 0x%x\n", slot, devreg);#endif return(0);}/* * pcibr_slot_guest_info_init * Setup the host/guest relations for a PCI slot. */intpcibr_slot_guest_info_init(devfs_handle_t pcibr_vhdl, pciio_slot_t slot){ pcibr_soft_t pcibr_soft; pcibr_info_h pcibr_infoh; pcibr_info_t pcibr_info; pcibr_soft_slot_t slotp; pcibr_soft = pcibr_soft_get(pcibr_vhdl); if (!pcibr_soft) return(EINVAL); if (!PCIBR_VALID_SLOT(pcibr_soft, slot)) return(EINVAL); slotp = &pcibr_soft->bs_slot[slot]; /* create info and verticies for guest slots; * for compatibilitiy macros, create info * for even unpopulated slots (but do not * build verticies for them). */ if (pcibr_soft->bs_slot[slot].bss_ninfo < 1) { NEWA(pcibr_infoh, 1); pcibr_soft->bs_slot[slot].bss_ninfo = 1; pcibr_soft->bs_slot[slot].bss_infos = pcibr_infoh; pcibr_info = pcibr_device_info_new (pcibr_soft, slot, PCIIO_FUNC_NONE, PCIIO_VENDOR_ID_NONE, PCIIO_DEVICE_ID_NONE); if (pcibr_soft->bs_slot[slot].has_host) { slotp->slot_conn = pciio_device_info_register (pcibr_vhdl, &pcibr_info->f_c); } } /* generate host/guest relations */ if (pcibr_soft->bs_slot[slot].has_host) { int host = pcibr_soft->bs_slot[slot].host_slot; pcibr_soft_slot_t host_slotp = &pcibr_soft->bs_slot[host]; hwgraph_edge_add(slotp->slot_conn, host_slotp->slot_conn, EDGE_LBL_HOST); /* XXX- only gives us one guest edge per * host. If/when we have a host with more than * one guest, we will need to figure out how * the host finds all its guests, and sorts * out which one is which. */ hwgraph_edge_add(host_slotp->slot_conn, slotp->slot_conn, EDGE_LBL_GUEST); } return(0);}/* * pcibr_slot_call_device_attach * This calls the associated driver attach routine for the PCI * card in this slot. */intpcibr_slot_call_device_attach(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; async_attach_t aa = NULL; int func; devfs_handle_t xconn_vhdl, conn_vhdl;#ifdef PIC_LATER devfs_handle_t scsi_vhdl;#endif int nfunc; int error_func; int error_slot = 0; int error = ENODEV;#ifdef PIC_LATER int hwg_err;#endif 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); } 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);#ifdef PIC_LATER /* * Try to assign well-known SCSI controller numbers for hot-plug * insert */ if (drv_flags) { hwg_err = hwgraph_path_lookup(conn_vhdl, EDGE_LBL_SCSI_CTLR "/0",
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -