⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xbow.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
     * 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. */#ifdef LATERstatic voidxbow_errintr_handler(intr_arg_t arg){#ifdef IRIX    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;    uint64_t                 wid_err_addr;    int                     fatal = 0;    int                     dump_ioe = 0;    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;		xbowreg_t               link_pend;		link_pend = link_status & link_control &		    (XB_STAT_ILLEGAL_DST_ERR		     | XB_STAT_OALLOC_IBUF_ERR		     | XB_STAT_RCV_CNT_OFLOW_ERR		     | XB_STAT_XMT_CNT_OFLOW_ERR		     | XB_STAT_XMT_MAX_RTRY_ERR		     | XB_STAT_RCV_ERR		     | XB_STAT_XMT_RTRY_ERR		     | XB_STAT_MAXREQ_TOUT_ERR		     | XB_STAT_SRC_TOUT_ERR		    );		if (link_pend & XB_STAT_ILLEGAL_DST_ERR) {		    if (wid_err.f.sidn == port) {			IOERROR_INIT(ioe);			IOERROR_SETVALUE(ioe, widgetnum, port);			IOERROR_SETVALUE(ioe, xtalkaddr, wid_err_addr);			if (IOERROR_HANDLED ==			    xbow_error_handler(soft,					       IOECODE_DMA,					       MODE_DEVERROR,					       ioe)) {			    link_pend &= ~XB_STAT_ILLEGAL_DST_ERR;			} else {			    dump_ioe++;			}		    }		}		/* Xbow/Bridge WAR:		 * if the bridge signals an LLP Transmitter Retry,		 * rewrite its control register.		 * If someone else triggers this interrupt,		 * ignore (and disable) the interrupt.		 */		if (link_pend & XB_STAT_XMT_RTRY_ERR) {		    if (!xbow_xmit_retry_error(soft, port)) {			link_control &= ~XB_CTRL_XMT_RTRY_IE;			link->link_control = link_control;			link->link_control;	/* stall until written */		    }		    link_pend &= ~XB_STAT_XMT_RTRY_ERR;		}		if (link_pend) {		    devfs_handle_t	xwidget_vhdl;		    char		*xwidget_name;		    		    /* Get the widget name corresponding to the current		     * xbow link.		     */		    xwidget_vhdl = xbow_widget_lookup(soft->busv,port);		    xwidget_name = xwidget_name_get(xwidget_vhdl);#ifdef IRIX		    cmn_err(CE_CONT,			    "%s port %X[%s] XIO Bus Error",			    soft->name, port, xwidget_name);		    if (link_status & XB_STAT_MULTI_ERR)			XEM_ADD_STR("\tMultiple Errors\n");		    if (link_status & XB_STAT_ILLEGAL_DST_ERR)			XEM_ADD_STR("\tInvalid Packet Destination\n");		    if (link_status & XB_STAT_OALLOC_IBUF_ERR)			XEM_ADD_STR("\tInput Overallocation Error\n");		    if (link_status & XB_STAT_RCV_CNT_OFLOW_ERR)			XEM_ADD_STR("\tLLP receive error counter overflow\n");		    if (link_status & XB_STAT_XMT_CNT_OFLOW_ERR)			XEM_ADD_STR("\tLLP transmit retry counter overflow\n");		    if (link_status & XB_STAT_XMT_MAX_RTRY_ERR)			XEM_ADD_STR("\tLLP Max Transmitter Retry\n");		    if (link_status & XB_STAT_RCV_ERR)			XEM_ADD_STR("\tLLP Receiver error\n");		    if (link_status & XB_STAT_XMT_RTRY_ERR)			XEM_ADD_STR("\tLLP Transmitter Retry\n");		    if (link_status & XB_STAT_MAXREQ_TOUT_ERR)			XEM_ADD_STR("\tMaximum Request Timeout\n");		    if (link_status & XB_STAT_SRC_TOUT_ERR)			XEM_ADD_STR("\tSource Timeout Error\n");#endif		    {			int                     other_port;			for (other_port = 8; other_port < 16; ++other_port) {			    if (link_aux_status & (1 << other_port)) {				/* XXX- need to go to "other_port"				 * and clean up after the timeout?				 */				XEM_ADD_VAR(other_port);			    }			}		    }#if !DEBUG		    if (kdebug) {#endif			XEM_ADD_VAR(link_control);			XEM_ADD_VAR(link_status);			XEM_ADD_VAR(link_aux_status);			if (dump_ioe) {			    XEM_ADD_IOE();			    dump_ioe = 0;			}#if !DEBUG		    }#endif		    fatal++;		}	    }	}    }    if (wid_stat & wid_control & XB_WID_STAT_WIDGET0_INTR) {	/* we have a "widget zero" problem */	if (wid_stat & (XB_WID_STAT_MULTI_ERR			| XB_WID_STAT_XTALK_ERR			| XB_WID_STAT_REG_ACC_ERR)) {	    cmn_err(CE_CONT,		    "%s Port 0 XIO Bus Error",		    soft->name);	    if (wid_stat & XB_WID_STAT_MULTI_ERR)		XEM_ADD_STR("\tMultiple Error\n");	    if (wid_stat & XB_WID_STAT_XTALK_ERR)		XEM_ADD_STR("\tXIO Error\n");	    if (wid_stat & XB_WID_STAT_REG_ACC_ERR)		XEM_ADD_STR("\tRegister Access Error\n");	    fatal++;	}    }    if (fatal) {	XEM_ADD_VAR(wid_stat);	XEM_ADD_VAR(wid_control);	XEM_ADD_VAR(wid_err_cmdword);	XEM_ADD_VAR(wid_err_upper);	XEM_ADD_VAR(wid_err_lower);	XEM_ADD_VAR(wid_err_addr);	cmn_err_tag(8, CE_PANIC, "XIO Bus Error");    }#endif}#endif	/* LATER *//* * XBOW ERROR Handling routines. * These get invoked as part of walking down the error handling path * from hub/heart towards the I/O device that caused the error. *//* * xbow_error_handler *      XBow error handling dispatch routine. *      This is the primary interface used by external world to invoke *      in case of an error related to a xbow. *      Only functionality in this layer is to identify the widget handle *      given the widgetnum. Otherwise, xbow does not gathers any error *      data. */#ifdef LATERstatic intxbow_error_handler(		      void *einfo,		      int error_code,		      ioerror_mode_t mode,		      ioerror_t *ioerror){#ifdef IRIX    int                     retval = IOERROR_WIDGETLEVEL;    xbow_soft_t             soft = (xbow_soft_t) einfo;    int                     port;    devfs_handle_t            conn;    devfs_handle_t            busv;    xbow_t                 *xbow = soft->base;    xbowreg_t               wid_stat;    xbowreg_t               wid_err_cmdword;    xbowreg_t               wid_err_upper;    xbowreg_t               wid_err_lower;    uint64_t                 wid_err_addr;    xb_linkregs_t          *link;    xbowreg_t               link_control;    xbowreg_t               link_status;    xbowreg_t               link_aux_status;    ASSERT(soft != 0);    busv = soft->busv;#if DEBUG && ERROR_DEBUG    cmn_err(CE_CONT, "%s: xbow_error_handler\n", soft->name, busv);#endif    port = IOERROR_GETVALUE(ioerror, widgetnum);    if (port == 0) {	/* error during access to xbow:	 * do NOT attempt to access xbow regs.	 */	if (mode == MODE_DEVPROBE)	    return IOERROR_HANDLED;	if (error_code & IOECODE_DMA) {	    cmn_err(CE_ALERT,		    "DMA error blamed on Crossbow at %s\n"		    "\tbut Crosbow never initiates DMA!",		    soft->name);	}	if (error_code & IOECODE_PIO) {	    cmn_err(CE_ALERT,		    "PIO Error on XIO Bus %s\n"		    "\tattempting to access XIO controller\n"		    "\twith offset 0x%X",		    soft->name,		    IOERROR_GETVALUE(ioerror, xtalkaddr));	}	/* caller will dump contents of ioerror	 * in DEBUG and kdebug kernels.	 */	return retval;    }    /*     * error not on port zero:     * safe to read xbow registers.     */    wid_stat = xbow->xb_wid_stat;    wid_err_cmdword = xbow->xb_wid_err_cmdword;    wid_err_upper = xbow->xb_wid_err_upper;    wid_err_lower = xbow->xb_wid_err_lower;    wid_err_addr =	wid_err_lower	| (((iopaddr_t) wid_err_upper	    & WIDGET_ERR_UPPER_ADDR_ONLY)	   << 32);    if ((port < BASE_XBOW_PORT) ||	(port >= MAX_PORT_NUM)) {	if (mode == MODE_DEVPROBE)	    return IOERROR_HANDLED;	if (error_code & IOECODE_DMA) {	    cmn_err(CE_ALERT,		    "DMA error blamed on XIO port at %s/%d\n"		    "\tbut Crossbow does not support that port",		    soft->name, port);	}	if (error_code & IOECODE_PIO) {	    cmn_err(CE_ALERT,		    "PIO Error on XIO Bus %s\n"		    "\tattempting to access XIO port %d\n"		    "\t(which Crossbow does not support)"		    "\twith offset 0x%X",		    soft->name, port,		    IOERROR_GETVALUE(ioerror, xtalkaddr));	}#if !DEBUG	if (kdebug) {#endif	    XEM_ADD_STR("Raw status values for Crossbow:\n");	    XEM_ADD_VAR(wid_stat);	    XEM_ADD_VAR(wid_err_cmdword);	    XEM_ADD_VAR(wid_err_upper);	    XEM_ADD_VAR(wid_err_lower);	    XEM_ADD_VAR(wid_err_addr);#if !DEBUG	}#endif	/* caller will dump contents of ioerror	 * in DEBUG and kdebug kernels.	 */	return retval;    }    /* access to valid port:     * ok to check port status.     */    link = &(xbow->xb_link(port));    link_control = link->link_control;    link_status = link->link_status;    link_aux_status = link->link_aux_status;    /* Check that there is something present     * in that XIO port.     */    if (!(link_aux_status & XB_AUX_STAT_PRESENT)) {	/* nobody connected. */	if (mode == MODE_DEVPROBE)	    return IOERROR_HANDLED;	if (error_code & IOECODE_DMA) {	    cmn_err(CE_ALERT,		    "DMA error blamed on XIO port at %s/%d\n"		    "\tbut there is no device connected there.",		    soft->name, port);	}	if (error_code & IOECODE_PIO) {	    cmn_err(CE_ALERT,		    "PIO Error on XIO Bus %s\n"		    "\tattempting to access XIO port %d\n"		    "\t(which has no device connected)"		    "\twith offset 0x%X",		    soft->name, port,		    IOERROR_GETVALUE(ioerror, xtalkaddr));	}#if !DEBUG	if (kdebug) {#endif	    XEM_ADD_STR("Raw status values for Crossbow:\n");	    XEM_ADD_VAR(wid_stat);	    XEM_ADD_VAR(wid_err_cmdword);	    XEM_ADD_VAR(wid_err_upper);	    XEM_ADD_VAR(wid_err_lower);	    XEM_ADD_VAR(wid_err_addr);	    XEM_ADD_VAR(port);	    XEM_ADD_VAR(link_control);	    XEM_ADD_VAR(link_status);	    XEM_ADD_VAR(link_aux_status);#if !DEBUG	}#endif	return retval;    }    /* Check that the link is alive.     */    if (!(link_status & XB_STAT_LINKALIVE)) {	/* nobody connected. */	if (mode == MODE_DEVPROBE)	    return IOERROR_HANDLED;	cmn_err(CE_ALERT,		"%s%sError on XIO Bus %s port %d",		(error_code & IOECODE_DMA) ? "DMA " : "",		(error_code & IOECODE_PIO) ? "PIO " : "",		soft->name, port);	if ((error_code & IOECODE_PIO) &&	    (IOERROR_FIELDVALID(ioerror, xtalkaddr))) {	    cmn_err(CE_CONT,		    "\tAccess attempted to offset 0x%X\n",		    IOERROR_GETVALUE(ioerror, xtalkaddr));	}	if (link_aux_status & XB_AUX_LINKFAIL_RST_BAD)	    XEM_ADD_STR("\tLink never came out of reset\n");	else	    XEM_ADD_STR("\tLink failed while transferring data\n");    }    /* get the connection point for the widget     * involved in this error; if it exists and     * is not our connectpoint, cycle back through     * xtalk_error_handler to deliver control to     * the proper handler (or to report a generic     * crosstalk error).     *     * If the downstream handler won't handle     * the problem, we let our upstream caller     * deal with it, after (in DEBUG and kdebug     * kernels) dumping the xbow state for this     * port.     */    conn = xbow_widget_lookup(busv, port);    if ((conn != GRAPH_VERTEX_NONE) &&	(conn != soft->conn)) {	retval = xtalk_error_handler(conn, error_code, mode, ioerror);	if (retval == IOERROR_HANDLED)	    return IOERROR_HANDLED;    }    if (mode == MODE_DEVPROBE)	return IOERROR_HANDLED;    if (retval == IOERROR_UNHANDLED) {	retval = IOERROR_PANIC;	cmn_err(CE_ALERT,		"%s%sError on XIO Bus %s port %d",		(error_code & IOECODE_DMA) ? "DMA " : "",		(error_code & IOECODE_PIO) ? "PIO " : "",		soft->name, port);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -