📄 xbow.c
字号:
{ return 0;}/*ARGSUSED */intxbow_close(devfs_handle_t dev, int oflag, int otyp, cred_t *crp){ return 0;}/*ARGSUSED */intxbow_map(devfs_handle_t dev, vhandl_t *vt, off_t off, size_t len, uint prot){ devfs_handle_t vhdl = dev_to_vhdl(dev); xbow_soft_t soft = xbow_soft_get(vhdl); int error; ASSERT(soft); len = ctob(btoc(len)); /* XXX- this ignores the offset!!! */ error = v_mapphys(vt, (void *) soft->base, len); return error;}/*ARGSUSED */intxbow_unmap(devfs_handle_t dev, vhandl_t *vt){ return 0;}/* This contains special-case code for grio. There are plans to make * this general sometime in the future, but till then this should * be good enough. */xwidgetnum_txbow_widget_num_get(devfs_handle_t dev){ devfs_handle_t tdev; char devname[MAXDEVNAME]; xwidget_info_t xwidget_info; int i; vertex_to_name(dev, devname, MAXDEVNAME); /* If this is a pci controller vertex, traverse up using * the ".." links to get to the widget. */ if (strstr(devname, EDGE_LBL_PCI) && strstr(devname, EDGE_LBL_CONTROLLER)) { tdev = dev; for (i=0; i< 2; i++) { if (hwgraph_edge_get(tdev, HWGRAPH_EDGELBL_DOTDOT, &tdev) != GRAPH_SUCCESS) return XWIDGET_NONE; } if ((xwidget_info = xwidget_info_chk(tdev)) != NULL) { return (xwidget_info_id_get(xwidget_info)); } else { return XWIDGET_NONE; } } return XWIDGET_NONE;}intxbow_ioctl(devfs_handle_t dev, int cmd, void *arg, int flag, struct cred *cr, int *rvalp){ devfs_handle_t vhdl; int error = 0;#if defined (DEBUG) int rc; devfs_handle_t conn; struct xwidget_info_s *xwidget_info; xbow_soft_t xbow_soft;#endif *rvalp = 0; vhdl = dev_to_vhdl(dev);#if defined (DEBUG) xbow_soft = xbow_soft_get(vhdl); conn = xbow_soft->conn; xwidget_info = xwidget_info_get(conn); ASSERT_ALWAYS(xwidget_info != NULL); rc = xwidget_hwid_is_xswitch(&xwidget_info->w_hwid); ASSERT_ALWAYS(rc != 0);#endif switch (cmd) {#ifdef LATER case XBOWIOC_PERF_ENABLE: case XBOWIOC_PERF_DISABLE: { struct xbow_perfarg_t xbow_perf_en; if (!_CAP_CRABLE(cr, CAP_DEVICE_MGT)) { error = EPERM; break; } if ((flag & FWRITE) == 0) { error = EBADF; break; } if (COPYIN(arg, &xbow_perf_en, sizeof(xbow_perf_en))) { error = EFAULT; break; } if (error = xbow_enable_perf_counter(vhdl, xbow_perf_en.link, (cmd == XBOWIOC_PERF_DISABLE) ? 0 : xbow_perf_en.mode, xbow_perf_en.counter)) { error = EINVAL; break; } break; }#endif#ifdef LATER case XBOWIOC_PERF_GET: { xbow_perf_link_t *xbow_perf_cnt; if ((flag & FREAD) == 0) { error = EBADF; break; } xbow_perf_cnt = xbow_get_perf_counters(vhdl); ASSERT_ALWAYS(xbow_perf_cnt != NULL); if (COPYOUT((void *) xbow_perf_cnt, (void *) arg, MAX_XBOW_PORTS * sizeof(xbow_perf_link_t))) { error = EFAULT; break; } break; }#endif case XBOWIOC_LLP_ERROR_ENABLE: if ((error = xbow_enable_llp_monitor(vhdl)) != 0) error = EINVAL; break; case XBOWIOC_LLP_ERROR_DISABLE: if ((error = xbow_disable_llp_monitor(vhdl)) != 0) error = EINVAL; break;#ifdef LATER case XBOWIOC_LLP_ERROR_GET: { xbow_link_status_t *xbow_llp_status; if ((flag & FREAD) == 0) { error = EBADF; break; } xbow_llp_status = xbow_get_llp_status(vhdl); ASSERT_ALWAYS(xbow_llp_status != NULL); if (COPYOUT((void *) xbow_llp_status, (void *) arg, MAX_XBOW_PORTS * sizeof(xbow_link_status_t))) { error = EFAULT; break; } break; }#endif#ifdef LATER case GIOCSETBW: { grio_ioctl_info_t info; xwidgetnum_t src_widgetnum, dest_widgetnum; if (COPYIN(arg, &info, sizeof(grio_ioctl_info_t))) { error = EFAULT; break; }#ifdef GRIO_DEBUG printf("xbow:: prev_vhdl: %d next_vhdl: %d reqbw: %lld\n", info.prev_vhdl, info.next_vhdl, info.reqbw);#endif /* GRIO_DEBUG */ src_widgetnum = xbow_widget_num_get(info.prev_vhdl); dest_widgetnum = xbow_widget_num_get(info.next_vhdl); /* Bandwidth allocation is bi-directional. Since bandwidth * reservations have already been done at an earlier stage, * we cannot fail here for lack of bandwidth. */ xbow_prio_bw_alloc(dev, src_widgetnum, dest_widgetnum, 0, info.reqbw); xbow_prio_bw_alloc(dev, dest_widgetnum, src_widgetnum, 0, info.reqbw); break; } case GIOCRELEASEBW: { grio_ioctl_info_t info; xwidgetnum_t src_widgetnum, dest_widgetnum; if (!cap_able(CAP_DEVICE_MGT)) { error = EPERM; break; } if (COPYIN(arg, &info, sizeof(grio_ioctl_info_t))) { error = EFAULT; break; }#ifdef GRIO_DEBUG printf("xbow:: prev_vhdl: %d next_vhdl: %d reqbw: %lld\n", info.prev_vhdl, info.next_vhdl, info.reqbw);#endif /* GRIO_DEBUG */ src_widgetnum = xbow_widget_num_get(info.prev_vhdl); dest_widgetnum = xbow_widget_num_get(info.next_vhdl); /* Bandwidth reservation is bi-directional. Hence, remove * bandwidth reservations for both directions. */ xbow_prio_bw_alloc(dev, src_widgetnum, dest_widgetnum, info.reqbw, (-1 * info.reqbw)); xbow_prio_bw_alloc(dev, dest_widgetnum, src_widgetnum, info.reqbw, (-1 * info.reqbw)); break; }#endif default: break; } return error;}/* * xbow_widget_present: See if a device is present * on the specified port of this crossbow. */intxbow_widget_present(xbow_t * xbow, int port){ if ( IS_RUNNING_ON_SIMULATOR() ) { if ( (port == 14) || (port == 15) ) { return 1; } else { return 0; } } else { return xbow->xb_link(port).link_aux_status & XB_AUX_STAT_PRESENT; }}static intxbow_link_alive(xbow_t * xbow, int port){ xbwX_stat_t xbow_linkstat; xbow_linkstat.linkstatus = xbow->xb_link(port).link_status; return (xbow_linkstat.link_alive);}/* * xbow_widget_lookup * Lookup the edges connected to the xbow specified, and * retrieve the handle corresponding to the widgetnum * specified. * If not found, return 0. */devfs_handle_txbow_widget_lookup(devfs_handle_t vhdl, int widgetnum){ xswitch_info_t xswitch_info; devfs_handle_t conn; xswitch_info = xswitch_info_get(vhdl); conn = xswitch_info_vhdl_get(xswitch_info, widgetnum); return conn;}/* * xbow_setwidint: called when xtalk * is establishing or migrating our * interrupt service. */#ifdef LATERstatic voidxbow_setwidint(xtalk_intr_t intr){ xwidgetnum_t targ = xtalk_intr_target_get(intr); iopaddr_t addr = xtalk_intr_addr_get(intr); xtalk_intr_vector_t vect = xtalk_intr_vector_get(intr); xbow_t *xbow = (xbow_t *) xtalk_intr_sfarg_get(intr); xbow_intr_preset((void *) xbow, 0, targ, addr, vect);}#endif /* LATER *//* * xbow_intr_preset: called during mlreset time * if the platform specific code needs to route * an xbow interrupt before the xtalk infrastructure * is available for use. * * Also called from xbow_setwidint, so we don't * replicate the guts of the routine. * * XXX- probably should be renamed xbow_wid_intr_set or * something to reduce confusion. *//*ARGSUSED3 */voidxbow_intr_preset(void *which_widget, int which_widget_intr, xwidgetnum_t targ, iopaddr_t addr, xtalk_intr_vector_t vect){ xbow_t *xbow = (xbow_t *) which_widget; xbow->xb_wid_int_upper = ((0xFF000000 & (vect << 24)) | (0x000F0000 & (targ << 16)) | XTALK_ADDR_TO_UPPER(addr)); xbow->xb_wid_int_lower = XTALK_ADDR_TO_LOWER(addr);}#define XEM_ADD_STR(s) printk("%s", (s))#define XEM_ADD_NVAR(n,v) printk("\t%20s: 0x%x\n", (n), (v))#define XEM_ADD_VAR(v) XEM_ADD_NVAR(#v,(v))#define XEM_ADD_IOEF(n) if (IOERROR_FIELDVALID(ioe,n)) \ XEM_ADD_NVAR("ioe." #n, \ IOERROR_GETVALUE(ioe,n))#ifdef LATERstatic voidxem_add_ioe(ioerror_t *ioe){ XEM_ADD_IOEF(errortype); XEM_ADD_IOEF(widgetnum); XEM_ADD_IOEF(widgetdev); XEM_ADD_IOEF(srccpu); XEM_ADD_IOEF(srcnode); XEM_ADD_IOEF(errnode); XEM_ADD_IOEF(sysioaddr); XEM_ADD_IOEF(xtalkaddr); XEM_ADD_IOEF(busspace); XEM_ADD_IOEF(busaddr); XEM_ADD_IOEF(vaddr); XEM_ADD_IOEF(memaddr); XEM_ADD_IOEF(epc); XEM_ADD_IOEF(ef);}#define XEM_ADD_IOE() (xem_add_ioe(ioe))#endif /* LATER */int xbow_xmit_retry_errors = 0;intxbow_xmit_retry_error(xbow_soft_t soft, int port){ xswitch_info_t info; devfs_handle_t vhdl; widget_cfg_t *wid; widgetreg_t id; int part; int mfgr; wid = soft->wpio[port - BASE_XBOW_PORT]; if (wid == NULL) { /* If we can't track down a PIO * pointer to our widget yet, * leave our caller knowing that * we are interested in this * interrupt if it occurs in * the future. */ info = xswitch_info_get(soft->busv); if (!info) return 1; vhdl = xswitch_info_vhdl_get(info, port); if (vhdl == GRAPH_VERTEX_NONE) return 1; wid = (widget_cfg_t *) xtalk_piotrans_addr (vhdl, 0, 0, sizeof *wid, 0); if (!wid) return 1; soft->wpio[port - BASE_XBOW_PORT] = wid; } id = wid->w_id; part = XWIDGET_PART_NUM(id); mfgr = XWIDGET_MFG_NUM(id); /* If this thing is not a Bridge, * do not activate the WAR, and * tell our caller we do not need * to be called again. */ if ((part != BRIDGE_WIDGET_PART_NUM) || (mfgr != BRIDGE_WIDGET_MFGR_NUM)) { /* FIXME: add Xbridge to the WAR. * Shouldn't hurt anything. Later need to * check if we can remove this. */ if ((part != XBRIDGE_WIDGET_PART_NUM) || (mfgr != XBRIDGE_WIDGET_MFGR_NUM)) return 0; } /* count how many times we * have picked up after * LLP Transmit problems. */ xbow_xmit_retry_errors++; /* rewrite the control register
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -