📄 xbow.c
字号:
* is not listed here, it is not on. */ xbow->xb_link(port).link_control = ( (xbow->xb_link(port).link_control /* * Turn off these bits; they are non-fatal, * but we might want to save some statistics * on the frequency of these errors. * XXX FIXME XXX */ & ~XB_CTRL_RCV_CNT_OFLOW_IE & ~XB_CTRL_XMT_CNT_OFLOW_IE & ~XB_CTRL_BNDWDTH_ALLOC_IE & ~XB_CTRL_RCV_IE) /* * These are the ones we want to turn on. */ | (XB_CTRL_ILLEGAL_DST_IE | XB_CTRL_OALLOC_IBUF_IE | XB_CTRL_XMT_MAX_RTRY_IE | XB_CTRL_MAXREQ_TOUT_IE | XB_CTRL_XMT_RTRY_IE | XB_CTRL_SRC_TOUT_IE) ); } xswitch_provider_register(busv, &xbow_provider); return 0; /* attach successful */}/*ARGSUSED */intxbow_open(devfs_handle_t *devp, int oflag, int otyp, cred_t *credp){ 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) { 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; 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 { /* WAR: port 0xf on PIC is missing present bit */ if (XBOW_WAR_ENABLED(PV854827, xbow->xb_wid_id) && IS_PIC_XBOW(xbow->xb_wid_id) && port==0xf) { return 1; } 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. */static 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);}/* * 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);#ifdef BRINGUP2printk("xbow_intr_preset: xb_wid_int_upper 0x%lx xb_wid_int_lower 0x%lx\n", (long)(((0xFF000000 & (vect << 24)) | (0x000F0000 & (targ << 16)) |XTALK_ADDR_TO_UPPER(addr))), (long)XTALK_ADDR_TO_LOWER(addr));#endif}#define XEM_ADD_STR(s) printk("%s", (s))#define XEM_ADD_NVAR(n,v) printk("\t%20s: 0x%llx\n", (n), ((unsigned long long)v))#define XEM_ADD_VAR(v) XEM_ADD_NVAR(#v,(v))#define XEM_ADD_IOEF(p,n) if (IOERROR_FIELDVALID(ioe,n)) { \ IOERROR_GETVALUE(p,ioe,n); \ XEM_ADD_NVAR("ioe." #n, p); \ }#ifdef LATERstatic voidxem_add_ioe(ioerror_t *ioe){ union tmp { ushort stmp; unsigned long long lltmp; cpuid_t cputmp; cnodeid_t cntmp; iopaddr_t iotmp; caddr_t catmp; paddr_t patmp; } tmp; XEM_ADD_IOEF(tmp.stmp, errortype); XEM_ADD_IOEF(tmp.stmp, widgetnum); XEM_ADD_IOEF(tmp.stmp, widgetdev); XEM_ADD_IOEF(tmp.cputmp, srccpu); XEM_ADD_IOEF(tmp.cntmp, srcnode); XEM_ADD_IOEF(tmp.cntmp, errnode); XEM_ADD_IOEF(tmp.iotmp, sysioaddr); XEM_ADD_IOEF(tmp.iotmp, xtalkaddr); XEM_ADD_IOEF(tmp.iotmp, busspace); XEM_ADD_IOEF(tmp.iotmp, busaddr); XEM_ADD_IOEF(tmp.catmp, vaddr); XEM_ADD_IOEF(tmp.patmp, memaddr); XEM_ADD_IOEF(tmp.catmp, epc); XEM_ADD_IOEF(tmp.catmp, ef); XEM_ADD_IOEF(tmp.stmp, tnum);}#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 * to fix things up. */ wid->w_control = wid->w_control; wid->w_control; return 1;}/* * xbow_errintr_handler will be called if the xbow * sends an interrupt request to report an error. */static voidxbow_errintr_handler(int irq, void *arg, struct pt_regs *ep){ ioerror_t ioe[1]; xbow_soft_t soft = (xbow_soft_t) arg; xbow_t *xbow = soft->base; xbowreg_t wid_control; xbowreg_t wid_stat; xbowreg_t wid_err_cmdword; xbowreg_t wid_err_upper; xbowreg_t wid_err_lower; w_err_cmd_word_u wid_err; unsigned long long wid_err_addr; int fatal = 0; int dump_ioe = 0; static int xbow_error_handler(void *, int, ioerror_mode_t, ioerror_t *); wid_control = xbow->xb_wid_control; wid_stat = xbow->xb_wid_stat_clr; wid_err_cmdword = xbow->xb_wid_err_cmdword; wid_err_upper = xbow->xb_wid_err_upper; wid_err_lower = xbow->xb_wid_err_lower; xbow->xb_wid_err_cmdword = 0; wid_err_addr = wid_err_lower | (((iopaddr_t) wid_err_upper & WIDGET_ERR_UPPER_ADDR_ONLY) << 32); if (wid_stat & XB_WID_STAT_LINK_INTR_MASK) { int port; wid_err.r = wid_err_cmdword; for (port = MAX_PORT_NUM - MAX_XBOW_PORTS; port < MAX_PORT_NUM; port++) { if (wid_stat & XB_WID_STAT_LINK_INTR(port)) { xb_linkregs_t *link = &(xbow->xb_link(port)); xbowreg_t link_control = link->link_control; xbowreg_t link_status = link->link_status_clr; xbowreg_t link_aux_status = link->link_aux_status;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -