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

📄 xbow.c

📁 linux-2.4.29操作系统的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
{    xswitch_info_t          xswitch_info;    vertex_hdl_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);}#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);		\				}int                     xbow_xmit_retry_errors;intxbow_xmit_retry_error(xbow_soft_t soft,		      int port){    xswitch_info_t          info;    vertex_hdl_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;		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) {		    vertex_hdl_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);		    printk("%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");		    {			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 !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)) {	    printk("%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);	panic("XIO Bus Error");    }}/* * 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. */static intxbow_error_handler(		      void *einfo,		      int error_code,		      ioerror_mode_t mode,		      ioerror_t *ioerror){    int                     retval = IOERROR_WIDGETLEVEL;    xbow_soft_t             soft = (xbow_soft_t) einfo;    int                     port;    vertex_hdl_t          conn;    vertex_hdl_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;    unsigned long long      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    printk("%s: xbow_error_handler\n", soft->name, busv);#endif    IOERROR_GETVALUE(port, 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) {	    printk(KERN_ALERT		    "DMA error blamed on Crossbow at %s\n"		    "\tbut Crosbow never initiates DMA!",		    soft->name);	}	if (error_code & IOECODE_PIO) {	    iopaddr_t tmp;	    IOERROR_GETVALUE(tmp, ioerror, xtalkaddr);	    printk(KERN_ALERT "PIO Error on XIO Bus %s\n"		    "\tattempting to access XIO controller\n"		    "\twith offset 0x%lx",		    soft->name, tmp);	}	/* 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) {	    printk(KERN_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) {	    iopaddr_t tmp;	    IOERROR_GETVALUE(tmp, ioerror, xtalkaddr);	    printk(KERN_ALERT		    "PIO Error on XIO Bus %s\n"		    "\tattempting to access XIO port %d\n"		    "\t(which Crossbow does not support)"		    "\twith offset 0x%lx",		    soft->name, port, tmp);	}#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.     */    /* WAR: PIC widget 0xf is missing prescense bit */    if (XBOW_WAR_ENABLED(PV854827, xbow->xb_wid_id) &&		IS_PIC_XBOW(xbow->xb_wid_id) && (port==0xf))		;    else if (IS_PIC_XBOW(xbow->xb_wid_id) && (port==0xb))		;	/* WAR for opus this is missing on 0xb */    else if (!(link_aux_status & XB_AUX_STAT_PRESENT)) {	/* nobody connected. */	if (mode == MODE_DEVPROBE)	    return IOERROR_HANDLED;	if (error_code & IOECODE_DMA) {	    printk(KERN_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) {

⌨️ 快捷键说明

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