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

📄 xbow.c

📁 上传linux-jx2410的源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* $Id: xbow.c,v 1.1.1.1 2004/02/04 12:55:34 laputa Exp $ * * This file is subject to the terms and conditions of the GNU General Public * License.  See the file "COPYING" in the main directory of this archive * for more details. * * Copyright (C) 1992 - 1997, 2000 Silicon Graphics, Inc. * Copyright (C) 2000 by Colin Ngam */#include <linux/types.h>#include <linux/slab.h>#include <linux/sched.h>#include <asm/sn/sgi.h>#include <asm/sn/iograph.h>#include <asm/sn/invent.h>#include <asm/sn/hcl.h>#include <asm/sn/labelcl.h>#include <asm/sn/hack.h>#include <asm/sn/pci/bridge.h>#include <asm/sn/xtalk/xtalk_private.h>/* #define DEBUG		1 *//* #define XBOW_DEBUG	1 *//* * Files needed to get the device driver entry points */#include <asm/sn/xtalk/xbow.h>#include <asm/sn/xtalk/xtalk.h>#include <asm/sn/xtalk/xswitch.h>#include <asm/sn/xtalk/xwidget.h>#include <asm/sn/prio.h>#include <asm/sn/hcl_util.h>#define NEW(ptr)	(ptr = kmalloc(sizeof (*(ptr)), GFP_KERNEL))#define DEL(ptr)	(kfree(ptr))int                     xbow_devflag = D_MP;/* * This file supports the Xbow chip.  Main functions: initializtion, * error handling, and GBR. *//* * each vertex corresponding to an xbow chip * has a "fastinfo" pointer pointing at one * of these things. */typedef struct xbow_soft_s *xbow_soft_t;struct xbow_soft_s {    devfs_handle_t            conn;	/* our connection point */    devfs_handle_t            vhdl;	/* xbow's private vertex */    devfs_handle_t            busv;	/* the xswitch vertex */    xbow_t                 *base;	/* PIO pointer to crossbow chip */    char                   *name;	/* hwgraph name */    xbow_perf_t             xbow_perfcnt[XBOW_PERF_COUNTERS];    xbow_perf_link_t        xbow_perflink[MAX_XBOW_PORTS];    xbow_link_status_t      xbow_link_status[MAX_XBOW_PORTS];    spinlock_t              xbow_perf_lock;    int                     link_monitor;    widget_cfg_t	   *wpio[MAX_XBOW_PORTS];	/* cached PIO pointer */    /* Bandwidth allocation state. Bandwidth values are for the     * destination port since contention happens there.     * Implicit mapping from xbow ports (8..f) -> (0..7) array indices.     */    spinlock_t		    xbow_bw_alloc_lock;		/* bw allocation lock */    unsigned long long	    bw_hiwm[MAX_XBOW_PORTS];	/* hiwater mark values */    unsigned long long      bw_cur_used[MAX_XBOW_PORTS]; /* bw used currently */};#define xbow_soft_set(v,i)	hwgraph_fastinfo_set((v), (arbitrary_info_t)(i))#define xbow_soft_get(v)	((xbow_soft_t)hwgraph_fastinfo_get((v)))/* * Function Table of Contents */void                    xbow_mlreset(xbow_t *);void                    xbow_init(void);int                     xbow_attach(devfs_handle_t);int                     xbow_open(devfs_handle_t *, int, int, cred_t *);int                     xbow_close(devfs_handle_t, int, int, cred_t *);int                     xbow_map(devfs_handle_t, vhandl_t *, off_t, size_t, uint);int                     xbow_unmap(devfs_handle_t, vhandl_t *);int                     xbow_ioctl(devfs_handle_t, int, void *, int, struct cred *, int *);int                     xbow_widget_present(xbow_t *, int);static int              xbow_link_alive(xbow_t *, int);devfs_handle_t            xbow_widget_lookup(devfs_handle_t, int);#ifdef LATERstatic void             xbow_setwidint(xtalk_intr_t);static void             xbow_errintr_handler(intr_arg_t);static error_handler_f  xbow_error_handler;#endifvoid                    xbow_intr_preset(void *, int, xwidgetnum_t, iopaddr_t, xtalk_intr_vector_t);void                    xbow_update_perf_counters(devfs_handle_t);xbow_perf_link_t       *xbow_get_perf_counters(devfs_handle_t);int                     xbow_enable_perf_counter(devfs_handle_t, int, int, int);xbow_link_status_t     *xbow_get_llp_status(devfs_handle_t);void                    xbow_update_llp_status(devfs_handle_t);int                     xbow_disable_llp_monitor(devfs_handle_t);int                     xbow_enable_llp_monitor(devfs_handle_t);int                     xbow_prio_bw_alloc(devfs_handle_t, xwidgetnum_t, xwidgetnum_t,                                unsigned long long, unsigned long long);xswitch_reset_link_f    xbow_reset_link;void                    idbg_xbowregs(int64_t);xswitch_provider_t      xbow_provider ={    xbow_reset_link,};/* *    xbow_mlreset: called at mlreset time if the *      platform specific code determines that there is *      a crossbow in a critical path that must be *      functional before the driver would normally get *      the device properly set up. * *      what do we need to do, that the boot prom can *      not be counted on to have already done, that is *      generic across all platforms using crossbows? *//*ARGSUSED */voidxbow_mlreset(xbow_t * xbow){}/* *    xbow_init: called with the rest of the device *      driver XXX_init routines. This platform *might* *      have a Crossbow chip, or even several, but it *      might have none. Register with the crosstalk *      generic provider so when we encounter the chip *      the right magic happens. */voidxbow_init(void){#if DEBUG && ATTACH_DEBUG    printf("xbow_init\n");#endif    xwidget_driver_register(XXBOW_WIDGET_PART_NUM,			    0, /* XXBOW_WIDGET_MFGR_NUM, */			    "xbow_",			    CDL_PRI_HI);	/* attach before friends */    xwidget_driver_register(XBOW_WIDGET_PART_NUM,			    XBOW_WIDGET_MFGR_NUM,			    "xbow_",			    CDL_PRI_HI);	/* attach before friends */}#ifdef XBRIDGE_REGS_SIM/*    xbow_set_simulated_regs: sets xbow regs as needed *	for powering through the boot */voidxbow_set_simulated_regs(xbow_t *xbow, int port){    /*     * turn on link     */    xbow->xb_link(port).link_status = (1<<31);    /*     * and give it a live widget too     */    xbow->xb_link(port).link_aux_status = XB_AUX_STAT_PRESENT;    /*     * zero the link control reg     */    xbow->xb_link(port).link_control = 0x0;}#endif /* XBRIDGE_REGS_SIM *//* *    xbow_attach: the crosstalk provider has *      determined that there is a crossbow widget *      present, and has handed us the connection *      point for that vertex. * *      We not only add our own vertex, but add *      some "xtalk switch" data to the switch *      vertex (at the connect point's parent) if *      it does not have any. *//*ARGSUSED */intxbow_attach(devfs_handle_t conn){    /*REFERENCED */    devfs_handle_t            vhdl;    devfs_handle_t            busv;    xbow_t                 *xbow;    xbow_soft_t             soft;    int                     port;    xswitch_info_t          info;#ifdef LATER    xtalk_intr_t            intr_hdl;    device_desc_t           dev_desc;#endif    char                    devnm[MAXDEVNAME], *s;    xbowreg_t               id;    int                     rev;    int			    i;    int			    xbow_num;	#if DEBUG && ATTACH_DEBUG#if defined(SUPPORT_PRINTING_V_FORMAT    printk("%v: xbow_attach\n", conn);#else    printk("0x%x: xbow_attach\n", conn);#endif#endif    /*     * Get a PIO pointer to the base of the crossbow     * chip.     */#ifdef XBRIDGE_REGS_SIM    printk("xbow_attach: XBRIDGE_REGS_SIM FIXME: allocating %ld bytes for xbow_s\n", sizeof(xbow_t));    xbow = (xbow_t *) kmalloc(sizeof(xbow_t), GFP_KERNEL);    /*     * turn on ports e and f like in a real live ibrick     */    xbow_set_simulated_regs(xbow, 0xe);    xbow_set_simulated_regs(xbow, 0xf);#else    xbow = (xbow_t *) xtalk_piotrans_addr(conn, 0, 0, sizeof(xbow_t), 0);#endif /* XBRIDGE_REGS_SIM */    /*     * Locate the "switch" vertex: it is the parent     * of our connection point.     */    busv = hwgraph_connectpt_get(conn);#if DEBUG && ATTACH_DEBUG    printk("xbow_attach: Bus Vertex 0x%p, conn 0x%p, xbow register 0x%p wid= 0x%x\n", busv, conn, xbow, *(volatile u32 *)xbow);#endif    ASSERT(busv != GRAPH_VERTEX_NONE);    /*     * Create our private vertex, and connect our     * driver information to it. This makes it possible     * for diagnostic drivers to open the crossbow     * vertex for access to registers.     */    /*     * We need to teach xbow drivers to provide the right set of     * file ops.     */    vhdl = NULL;    vhdl = hwgraph_register(conn, EDGE_LBL_XBOW,                        0, DEVFS_FL_AUTO_DEVNUM,                        0, 0,                        S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, 0, 0,                        /* &hcl_fops */ (void *)&vhdl, NULL);    if (!vhdl) {        printk(KERN_WARNING "xbow_attach: Unable to create char device for xbow conn %p\n",                conn);    }    /*     * Allocate the soft state structure and attach     * it to the xbow's vertex     */    NEW(soft);    soft->conn = conn;    soft->vhdl = vhdl;    soft->busv = busv;    soft->base = xbow;    /* does the universe really need another macro?  */    /* xbow_soft_set(vhdl, (arbitrary_info_t) soft); */    hwgraph_fastinfo_set(vhdl, (arbitrary_info_t) soft);#define XBOW_NUM_SUFFIX_FORMAT	"[xbow# %d]"    /* Add xbow number as a suffix to the hwgraph name of the xbow.     * This is helpful while looking at the error/warning messages.     */    xbow_num = 0;    /*     * get the name of this xbow vertex and keep the info.     * This is needed during errors and interrupts, but as     * long as we have it, we can use it elsewhere.     */    s = dev_to_name(vhdl, devnm, MAXDEVNAME);    soft->name = kmalloc(strlen(s) + strlen(XBOW_NUM_SUFFIX_FORMAT) + 1, 			    GFP_KERNEL);    sprintf(soft->name,"%s"XBOW_NUM_SUFFIX_FORMAT, s,xbow_num);#ifdef XBRIDGE_REGS_SIM    /* my o200/ibrick has id=0x2d002049, but XXBOW_WIDGET_PART_NUM is defined     * as 0xd000, so I'm using that for the partnum bitfield.     */    printk("xbow_attach: XBRIDGE_REGS_SIM FIXME: need xb_wid_id value!!\n");    id = 0x2d000049;#else    id = xbow->xb_wid_id;#endif /* XBRIDGE_REGS_SIM */    rev = XWIDGET_PART_REV_NUM(id);    /*     * Print the revision if DEBUG, or SHOW_REVS and kdebug,     * or the xbow is downrev.     *     * If xbow is downrev, make it a WARNING that the     * Crossbow is DOWNREV: these chips are not good     * to have around, and the operator should be told.     */#ifdef	LATER#if !DEBUG    if (#if SHOW_REVS	   (kdebug) ||#endif	/* SHOW_REVS */	   (rev < XBOW_REV_1_1))#endif	/* !DEBUG  */	printk("%sCrossbow ASIC: rev %s (code=%d) at %s%s",		(rev < XBOW_REV_1_1) ? "DOWNREV " : "",		(rev == XBOW_REV_1_0) ? "1.0" :		(rev == XBOW_REV_1_1) ? "1.1" :		(rev == XBOW_REV_1_2) ? "1.2" :		(rev == XBOW_REV_1_3) ? "1.3" :		(rev == XBOW_REV_2_0) ? "2.0" :		(rev == XXBOW_PART_REV_1_0) ? "Xbridge 1.0" :		(rev == XXBOW_PART_REV_2_0) ? "Xbridge 2.0" :		"unknown",		rev, soft->name,		(rev < XBOW_REV_1_1) ? "" : "\n");#endif	/* LATER */    mutex_spinlock_init(&soft->xbow_perf_lock);    soft->xbow_perfcnt[0].xp_perf_reg = &xbow->xb_perf_ctr_a;    soft->xbow_perfcnt[1].xp_perf_reg = &xbow->xb_perf_ctr_b;    /* Initialization for GBR bw allocation */    mutex_spinlock_init(&soft->xbow_bw_alloc_lock);#define	XBOW_8_BIT_PORT_BW_MAX		(400 * 1000 * 1000)	/* 400 MB/s */#define XBOW_16_BIT_PORT_BW_MAX		(800 * 1000 * 1000)	/* 800 MB/s */    /* Set bandwidth hiwatermark and current values */    for (i = 0; i < MAX_XBOW_PORTS; i++) {	soft->bw_hiwm[i] = XBOW_16_BIT_PORT_BW_MAX;	/* for now */	soft->bw_cur_used[i] = 0;    }    /*     * attach the crossbow error interrupt.     */#ifdef LATER    dev_desc = device_desc_dup(vhdl);    device_desc_flags_set(dev_desc,			  device_desc_flags_get(dev_desc) | D_INTR_ISERR);    device_desc_intr_name_set(dev_desc, "Crossbow error");    intr_hdl = xtalk_intr_alloc(conn, dev_desc, vhdl);    ASSERT(intr_hdl != NULL);    xtalk_intr_connect(intr_hdl,		       (intr_func_t) xbow_errintr_handler,		       (intr_arg_t) soft,		       (xtalk_intr_setfunc_t) xbow_setwidint,		       (void *) xbow,		       (void *) 0);    device_desc_free(dev_desc);    xwidget_error_register(conn, xbow_error_handler, soft);#else    FIXME("xbow_attach: Fixme: we bypassed attaching xbow error interrupt.\n");#endif /* LATER */    /*     * Enable xbow error interrupts     */    xbow->xb_wid_control = (XB_WID_CTRL_REG_ACC_IE |			    XB_WID_CTRL_XTALK_IE);    /*     * take a census of the widgets present,     * leaving notes at the switch vertex.     */    info = xswitch_info_new(busv);    for (port = MAX_PORT_NUM - MAX_XBOW_PORTS;	 port < MAX_PORT_NUM; ++port) {	if (!xbow_link_alive(xbow, port)) {#if DEBUG && XBOW_DEBUG	    printk(KERN_INFO "0x%p link %d is not alive\n",		    busv, port);#endif	    continue;	}	if (!xbow_widget_present(xbow, port)) {#if DEBUG && XBOW_DEBUG	    printk(KERN_INFO "0x%p link %d is alive but no widget is present\n", busv, port);#endif	    continue;	}#if DEBUG && XBOW_DEBUG	printk(KERN_INFO "0x%p link %d has a widget\n",		busv, port);#endif	xswitch_info_link_is_ok(info, port);	/*	 * Turn some error interrupts on	 * and turn others off. The PROM has	 * some things turned on we don't	 * want to see (bandwidth allocation	 * errors for instance); so if it	 * 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)	/*

⌨️ 快捷键说明

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