📄 pcibr_dvr.c
字号:
struct pcibr_slot_req_s req; if (!cap_able(CAP_DEVICE_MGT)) { error = EPERM; break; } if (COPYIN(arg, &req, sizeof(req))) { error = EFAULT; break; } error = pcibr_slot_startup(pcibr_vhdl, &req); break; } case PCIBR_SLOT_SHUTDOWN: { struct pcibr_slot_req_s req; if (!cap_able(CAP_DEVICE_MGT)) { error = EPERM; break; } if (COPYIN(arg, &req, sizeof(req))) { error = EFAULT; break; } error = pcibr_slot_shutdown(pcibr_vhdl, &req); break; } case PCIBR_SLOT_QUERY: { struct pcibr_slot_req_s req; if (!cap_able(CAP_DEVICE_MGT)) { error = EPERM; break; } if (COPYIN(arg, &req, sizeof(req))) { error = EFAULT; break; } error = pcibr_slot_query(pcibr_vhdl, &req); break; }#endif /* LATER */ default: break; } return error;}voidpcibr_freeblock_sub(iopaddr_t *free_basep, iopaddr_t *free_lastp, iopaddr_t base, size_t size){ iopaddr_t free_base = *free_basep; iopaddr_t free_last = *free_lastp; iopaddr_t last = base + size - 1; if ((last < free_base) || (base > free_last)); /* free block outside arena */ else if ((base <= free_base) && (last >= free_last)) /* free block contains entire arena */ *free_basep = *free_lastp = 0; else if (base <= free_base) /* free block is head of arena */ *free_basep = last + 1; else if (last >= free_last) /* free block is tail of arena */ *free_lastp = base - 1; /* * We are left with two regions: the free area * in the arena "below" the block, and the free * area in the arena "above" the block. Keep * the one that is bigger. */ else if ((base - free_base) > (free_last - last)) *free_lastp = base - 1; /* keep lower chunk */ else *free_basep = last + 1; /* keep upper chunk */}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; NEW(pcibr_info); pciio_device_info_new(&pcibr_info->f_c, pcibr_soft->bs_vhdl, slot, rfunc, vendor, device);/* pfg - this is new ..... */ /* Set PCI bus number */ pcibr_info->f_bus = io_path_map_widget(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;}/* FIXME: for now this is needed by both pcibr.c and * pcibr_slot.c. Need to find a better way, the least * of which would be to move it to pcibr_private.h *//* * PCI_ADDR_SPACE_LIMITS_STORE * Sets the current values of * pci io base, * pci io last, * pci low memory base, * pci low memory last, * pci high memory base, * pci high memory last */#define PCI_ADDR_SPACE_LIMITS_STORE() \ pcibr_soft->bs_spinfo.pci_io_base = pci_io_fb; \ pcibr_soft->bs_spinfo.pci_io_last = pci_io_fl; \ pcibr_soft->bs_spinfo.pci_swin_base = pci_lo_fb; \ pcibr_soft->bs_spinfo.pci_swin_last = pci_lo_fl; \ pcibr_soft->bs_spinfo.pci_mem_base = pci_hi_fb; \ pcibr_soft->bs_spinfo.pci_mem_last = pci_hi_fl;/* * 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 = pciio_info_slot_get(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] >= 0) { s = pcibr_lock(pcibr_soft); /* Free the rrbs allocated to this slot */ error_call = do_pcibr_rrb_free(bridge, slot, pcibr_soft->bs_rrb_valid[slot] + pcibr_soft->bs_rrb_valid[slot + PCIBR_RRB_SLOT_VIRTUAL]); if (error_call) error = ERANGE; pcibr_soft->bs_rrb_res[slot] = pcibr_soft->bs_rrb_res[slot] + pcibr_soft->bs_rrb_valid[slot] + pcibr_soft->bs_rrb_valid[slot + PCIBR_RRB_SLOT_VIRTUAL]; count_vchan0 = pcibr_soft->bs_rrb_valid_dflt[slot]; count_vchan1 = pcibr_soft->bs_rrb_valid_dflt[slot + PCIBR_RRB_SLOT_VIRTUAL]; 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 = pciio_info_slot_get(pciio_info); pcibr_soft = pcibr_soft_get(pcibr_vhdl); /* This may be a loadable driver so lock out any pciconfig actions */ mrlock(pcibr_soft->bs_bus_lock, MR_UPDATE, PZERO); 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; } /* Release the bus lock */ mrunlock(pcibr_soft->bs_bus_lock);}/* * 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 = pciio_info_slot_get(pciio_info); pcibr_soft = pcibr_soft_get(pcibr_vhdl); /* This may be a loadable driver so lock out any pciconfig actions */ mrlock(pcibr_soft->bs_bus_lock, MR_UPDATE, PZERO); 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; } /* Release the bus lock */ mrunlock(pcibr_soft->bs_bus_lock);}/* * 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, int slot){ char dst[MAXDEVNAME]; char *dp = dst; char *cp, *xp; int widgetnum; char pcibus[8]; devfs_handle_t nvtx, svtx; int rv;#if DEBUG printk("pcibr_bus_cnvlink: slot= %d f_c= %p\n", slot, f_c); { int pos; char dname[256]; pos = devfs_generate_path(f_c, dname, 256); printk("%s : path= %s\n", __FUNCTION__, &dname[pos]); }#endif 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 "/" "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, "/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);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -