xbow.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:49k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /* $Id$
  2.  *
  3.  * This file is subject to the terms and conditions of the GNU General Public
  4.  * License.  See the file "COPYING" in the main directory of this archive
  5.  * for more details.
  6.  *
  7.  * Copyright (C) 1992 - 1997, 2000 Silicon Graphics, Inc.
  8.  * Copyright (C) 2000 by Colin Ngam
  9.  */
  10. #include <linux/types.h>
  11. #include <linux/slab.h>
  12. #include <linux/sched.h>
  13. #include <asm/sn/sgi.h>
  14. #include <asm/sn/iograph.h>
  15. #include <asm/sn/invent.h>
  16. #include <asm/sn/hcl.h>
  17. #include <asm/sn/labelcl.h>
  18. #include <asm/sn/hack.h>
  19. #include <asm/sn/pci/bridge.h>
  20. #include <asm/sn/xtalk/xtalk_private.h>
  21. /* #define DEBUG 1 */
  22. /* #define XBOW_DEBUG 1 */
  23. /*
  24.  * Files needed to get the device driver entry points
  25.  */
  26. #include <asm/sn/xtalk/xbow.h>
  27. #include <asm/sn/xtalk/xtalk.h>
  28. #include <asm/sn/xtalk/xswitch.h>
  29. #include <asm/sn/xtalk/xwidget.h>
  30. #include <asm/sn/prio.h>
  31. #include <asm/sn/hcl_util.h>
  32. #define NEW(ptr) (ptr = kmalloc(sizeof (*(ptr)), GFP_KERNEL))
  33. #define DEL(ptr) (kfree(ptr))
  34. int                     xbow_devflag = D_MP;
  35. /*
  36.  * This file supports the Xbow chip.  Main functions: initializtion,
  37.  * error handling, and GBR.
  38.  */
  39. /*
  40.  * each vertex corresponding to an xbow chip
  41.  * has a "fastinfo" pointer pointing at one
  42.  * of these things.
  43.  */
  44. typedef struct xbow_soft_s *xbow_soft_t;
  45. struct xbow_soft_s {
  46.     devfs_handle_t            conn; /* our connection point */
  47.     devfs_handle_t            vhdl; /* xbow's private vertex */
  48.     devfs_handle_t            busv; /* the xswitch vertex */
  49.     xbow_t                 *base; /* PIO pointer to crossbow chip */
  50.     char                   *name; /* hwgraph name */
  51.     xbow_perf_t             xbow_perfcnt[XBOW_PERF_COUNTERS];
  52.     xbow_perf_link_t        xbow_perflink[MAX_XBOW_PORTS];
  53.     xbow_link_status_t      xbow_link_status[MAX_XBOW_PORTS];
  54.     spinlock_t              xbow_perf_lock;
  55.     int                     link_monitor;
  56.     widget_cfg_t    *wpio[MAX_XBOW_PORTS]; /* cached PIO pointer */
  57.     /* Bandwidth allocation state. Bandwidth values are for the
  58.      * destination port since contention happens there.
  59.      * Implicit mapping from xbow ports (8..f) -> (0..7) array indices.
  60.      */
  61.     spinlock_t     xbow_bw_alloc_lock; /* bw allocation lock */
  62.     unsigned long long     bw_hiwm[MAX_XBOW_PORTS]; /* hiwater mark values */
  63.     unsigned long long      bw_cur_used[MAX_XBOW_PORTS]; /* bw used currently */
  64. };
  65. #define xbow_soft_set(v,i) hwgraph_fastinfo_set((v), (arbitrary_info_t)(i))
  66. #define xbow_soft_get(v) ((xbow_soft_t)hwgraph_fastinfo_get((v)))
  67. /*
  68.  * Function Table of Contents
  69.  */
  70. void                    xbow_mlreset(xbow_t *);
  71. void                    xbow_init(void);
  72. int                     xbow_attach(devfs_handle_t);
  73. int                     xbow_open(devfs_handle_t *, int, int, cred_t *);
  74. int                     xbow_close(devfs_handle_t, int, int, cred_t *);
  75. int                     xbow_map(devfs_handle_t, vhandl_t *, off_t, size_t, uint);
  76. int                     xbow_unmap(devfs_handle_t, vhandl_t *);
  77. int                     xbow_ioctl(devfs_handle_t, int, void *, int, struct cred *, int *);
  78. int                     xbow_widget_present(xbow_t *, int);
  79. static int              xbow_link_alive(xbow_t *, int);
  80. devfs_handle_t            xbow_widget_lookup(devfs_handle_t, int);
  81. #ifdef LATER
  82. static void             xbow_setwidint(xtalk_intr_t);
  83. static void             xbow_errintr_handler(intr_arg_t);
  84. static error_handler_f  xbow_error_handler;
  85. #endif
  86. void                    xbow_intr_preset(void *, int, xwidgetnum_t, iopaddr_t, xtalk_intr_vector_t);
  87. void                    xbow_update_perf_counters(devfs_handle_t);
  88. xbow_perf_link_t       *xbow_get_perf_counters(devfs_handle_t);
  89. int                     xbow_enable_perf_counter(devfs_handle_t, int, int, int);
  90. xbow_link_status_t     *xbow_get_llp_status(devfs_handle_t);
  91. void                    xbow_update_llp_status(devfs_handle_t);
  92. int                     xbow_disable_llp_monitor(devfs_handle_t);
  93. int                     xbow_enable_llp_monitor(devfs_handle_t);
  94. int                     xbow_prio_bw_alloc(devfs_handle_t, xwidgetnum_t, xwidgetnum_t,
  95.                                 unsigned long long, unsigned long long);
  96. xswitch_reset_link_f    xbow_reset_link;
  97. void                    idbg_xbowregs(int64_t);
  98. xswitch_provider_t      xbow_provider =
  99. {
  100.     xbow_reset_link,
  101. };
  102. /*
  103.  *    xbow_mlreset: called at mlreset time if the
  104.  *      platform specific code determines that there is
  105.  *      a crossbow in a critical path that must be
  106.  *      functional before the driver would normally get
  107.  *      the device properly set up.
  108.  *
  109.  *      what do we need to do, that the boot prom can
  110.  *      not be counted on to have already done, that is
  111.  *      generic across all platforms using crossbows?
  112.  */
  113. /*ARGSUSED */
  114. void
  115. xbow_mlreset(xbow_t * xbow)
  116. {
  117. }
  118. /*
  119.  *    xbow_init: called with the rest of the device
  120.  *      driver XXX_init routines. This platform *might*
  121.  *      have a Crossbow chip, or even several, but it
  122.  *      might have none. Register with the crosstalk
  123.  *      generic provider so when we encounter the chip
  124.  *      the right magic happens.
  125.  */
  126. void
  127. xbow_init(void)
  128. {
  129. #if DEBUG && ATTACH_DEBUG
  130.     printf("xbow_initn");
  131. #endif
  132.     xwidget_driver_register(XXBOW_WIDGET_PART_NUM,
  133.     0, /* XXBOW_WIDGET_MFGR_NUM, */
  134.     "xbow_",
  135.     CDL_PRI_HI); /* attach before friends */
  136.     xwidget_driver_register(XBOW_WIDGET_PART_NUM,
  137.     XBOW_WIDGET_MFGR_NUM,
  138.     "xbow_",
  139.     CDL_PRI_HI); /* attach before friends */
  140. }
  141. #ifdef XBRIDGE_REGS_SIM
  142. /*    xbow_set_simulated_regs: sets xbow regs as needed
  143.  * for powering through the boot
  144.  */
  145. void
  146. xbow_set_simulated_regs(xbow_t *xbow, int port)
  147. {
  148.     /*
  149.      * turn on link
  150.      */
  151.     xbow->xb_link(port).link_status = (1<<31);
  152.     /*
  153.      * and give it a live widget too
  154.      */
  155.     xbow->xb_link(port).link_aux_status = XB_AUX_STAT_PRESENT;
  156.     /*
  157.      * zero the link control reg
  158.      */
  159.     xbow->xb_link(port).link_control = 0x0;
  160. }
  161. #endif /* XBRIDGE_REGS_SIM */
  162. /*
  163.  *    xbow_attach: the crosstalk provider has
  164.  *      determined that there is a crossbow widget
  165.  *      present, and has handed us the connection
  166.  *      point for that vertex.
  167.  *
  168.  *      We not only add our own vertex, but add
  169.  *      some "xtalk switch" data to the switch
  170.  *      vertex (at the connect point's parent) if
  171.  *      it does not have any.
  172.  */
  173. /*ARGSUSED */
  174. int
  175. xbow_attach(devfs_handle_t conn)
  176. {
  177.     /*REFERENCED */
  178.     devfs_handle_t            vhdl;
  179.     devfs_handle_t            busv;
  180.     xbow_t                 *xbow;
  181.     xbow_soft_t             soft;
  182.     int                     port;
  183.     xswitch_info_t          info;
  184. #ifdef LATER
  185.     xtalk_intr_t            intr_hdl;
  186.     device_desc_t           dev_desc;
  187. #endif
  188.     char                    devnm[MAXDEVNAME], *s;
  189.     xbowreg_t               id;
  190.     int                     rev;
  191.     int     i;
  192.     int     xbow_num;
  193. #if DEBUG && ATTACH_DEBUG
  194. #if defined(SUPPORT_PRINTING_V_FORMAT
  195.     printk("%v: xbow_attachn", conn);
  196. #else
  197.     printk("0x%x: xbow_attachn", conn);
  198. #endif
  199. #endif
  200.     /*
  201.      * Get a PIO pointer to the base of the crossbow
  202.      * chip.
  203.      */
  204. #ifdef XBRIDGE_REGS_SIM
  205.     printk("xbow_attach: XBRIDGE_REGS_SIM FIXME: allocating %ld bytes for xbow_sn", sizeof(xbow_t));
  206.     xbow = (xbow_t *) kmalloc(sizeof(xbow_t), GFP_KERNEL);
  207.     /*
  208.      * turn on ports e and f like in a real live ibrick
  209.      */
  210.     xbow_set_simulated_regs(xbow, 0xe);
  211.     xbow_set_simulated_regs(xbow, 0xf);
  212. #else
  213.     xbow = (xbow_t *) xtalk_piotrans_addr(conn, 0, 0, sizeof(xbow_t), 0);
  214. #endif /* XBRIDGE_REGS_SIM */
  215.     /*
  216.      * Locate the "switch" vertex: it is the parent
  217.      * of our connection point.
  218.      */
  219.     busv = hwgraph_connectpt_get(conn);
  220. #if DEBUG && ATTACH_DEBUG
  221.     printk("xbow_attach: Bus Vertex 0x%p, conn 0x%p, xbow register 0x%p wid= 0x%xn", busv, conn, xbow, *(volatile u32 *)xbow);
  222. #endif
  223.     ASSERT(busv != GRAPH_VERTEX_NONE);
  224.     /*
  225.      * Create our private vertex, and connect our
  226.      * driver information to it. This makes it possible
  227.      * for diagnostic drivers to open the crossbow
  228.      * vertex for access to registers.
  229.      */
  230.     /*
  231.      * We need to teach xbow drivers to provide the right set of
  232.      * file ops.
  233.      */
  234.     vhdl = NULL;
  235.     vhdl = hwgraph_register(conn, EDGE_LBL_XBOW,
  236.                         0, DEVFS_FL_AUTO_DEVNUM,
  237.                         0, 0,
  238.                         S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, 0, 0,
  239.                         /* &hcl_fops */ (void *)&vhdl, NULL);
  240.     if (!vhdl) {
  241.         printk(KERN_WARNING "xbow_attach: Unable to create char device for xbow conn %pn",
  242.                 conn);
  243.     }
  244.     /*
  245.      * Allocate the soft state structure and attach
  246.      * it to the xbow's vertex
  247.      */
  248.     NEW(soft);
  249.     soft->conn = conn;
  250.     soft->vhdl = vhdl;
  251.     soft->busv = busv;
  252.     soft->base = xbow;
  253.     /* does the universe really need another macro?  */
  254.     /* xbow_soft_set(vhdl, (arbitrary_info_t) soft); */
  255.     hwgraph_fastinfo_set(vhdl, (arbitrary_info_t) soft);
  256. #define XBOW_NUM_SUFFIX_FORMAT "[xbow# %d]"
  257.     /* Add xbow number as a suffix to the hwgraph name of the xbow.
  258.      * This is helpful while looking at the error/warning messages.
  259.      */
  260.     xbow_num = 0;
  261.     /*
  262.      * get the name of this xbow vertex and keep the info.
  263.      * This is needed during errors and interrupts, but as
  264.      * long as we have it, we can use it elsewhere.
  265.      */
  266.     s = dev_to_name(vhdl, devnm, MAXDEVNAME);
  267.     soft->name = kmalloc(strlen(s) + strlen(XBOW_NUM_SUFFIX_FORMAT) + 1, 
  268.     GFP_KERNEL);
  269.     sprintf(soft->name,"%s"XBOW_NUM_SUFFIX_FORMAT, s,xbow_num);
  270. #ifdef XBRIDGE_REGS_SIM
  271.     /* my o200/ibrick has id=0x2d002049, but XXBOW_WIDGET_PART_NUM is defined
  272.      * as 0xd000, so I'm using that for the partnum bitfield.
  273.      */
  274.     printk("xbow_attach: XBRIDGE_REGS_SIM FIXME: need xb_wid_id value!!n");
  275.     id = 0x2d000049;
  276. #else
  277.     id = xbow->xb_wid_id;
  278. #endif /* XBRIDGE_REGS_SIM */
  279.     rev = XWIDGET_PART_REV_NUM(id);
  280.     /*
  281.      * Print the revision if DEBUG, or SHOW_REVS and kdebug,
  282.      * or the xbow is downrev.
  283.      *
  284.      * If xbow is downrev, make it a WARNING that the
  285.      * Crossbow is DOWNREV: these chips are not good
  286.      * to have around, and the operator should be told.
  287.      */
  288. #ifdef LATER
  289. #if !DEBUG
  290.     if (
  291. #if SHOW_REVS
  292.    (kdebug) ||
  293. #endif /* SHOW_REVS */
  294.    (rev < XBOW_REV_1_1))
  295. #endif /* !DEBUG  */
  296. printk("%sCrossbow ASIC: rev %s (code=%d) at %s%s",
  297. (rev < XBOW_REV_1_1) ? "DOWNREV " : "",
  298. (rev == XBOW_REV_1_0) ? "1.0" :
  299. (rev == XBOW_REV_1_1) ? "1.1" :
  300. (rev == XBOW_REV_1_2) ? "1.2" :
  301. (rev == XBOW_REV_1_3) ? "1.3" :
  302. (rev == XBOW_REV_2_0) ? "2.0" :
  303. (rev == XXBOW_PART_REV_1_0) ? "Xbridge 1.0" :
  304. (rev == XXBOW_PART_REV_2_0) ? "Xbridge 2.0" :
  305. "unknown",
  306. rev, soft->name,
  307. (rev < XBOW_REV_1_1) ? "" : "n");
  308. #endif /* LATER */
  309.     mutex_spinlock_init(&soft->xbow_perf_lock);
  310.     soft->xbow_perfcnt[0].xp_perf_reg = &xbow->xb_perf_ctr_a;
  311.     soft->xbow_perfcnt[1].xp_perf_reg = &xbow->xb_perf_ctr_b;
  312.     /* Initialization for GBR bw allocation */
  313.     mutex_spinlock_init(&soft->xbow_bw_alloc_lock);
  314. #define XBOW_8_BIT_PORT_BW_MAX (400 * 1000 * 1000) /* 400 MB/s */
  315. #define XBOW_16_BIT_PORT_BW_MAX (800 * 1000 * 1000) /* 800 MB/s */
  316.     /* Set bandwidth hiwatermark and current values */
  317.     for (i = 0; i < MAX_XBOW_PORTS; i++) {
  318. soft->bw_hiwm[i] = XBOW_16_BIT_PORT_BW_MAX; /* for now */
  319. soft->bw_cur_used[i] = 0;
  320.     }
  321.     /*
  322.      * attach the crossbow error interrupt.
  323.      */
  324. #ifdef LATER
  325.     dev_desc = device_desc_dup(vhdl);
  326.     device_desc_flags_set(dev_desc,
  327.   device_desc_flags_get(dev_desc) | D_INTR_ISERR);
  328.     device_desc_intr_name_set(dev_desc, "Crossbow error");
  329.     intr_hdl = xtalk_intr_alloc(conn, dev_desc, vhdl);
  330.     ASSERT(intr_hdl != NULL);
  331.     xtalk_intr_connect(intr_hdl,
  332.        (intr_func_t) xbow_errintr_handler,
  333.        (intr_arg_t) soft,
  334.        (xtalk_intr_setfunc_t) xbow_setwidint,
  335.        (void *) xbow,
  336.        (void *) 0);
  337.     device_desc_free(dev_desc);
  338.     xwidget_error_register(conn, xbow_error_handler, soft);
  339. #else
  340.     FIXME("xbow_attach: Fixme: we bypassed attaching xbow error interrupt.n");
  341. #endif /* LATER */
  342.     /*
  343.      * Enable xbow error interrupts
  344.      */
  345.     xbow->xb_wid_control = (XB_WID_CTRL_REG_ACC_IE |
  346.     XB_WID_CTRL_XTALK_IE);
  347.     /*
  348.      * take a census of the widgets present,
  349.      * leaving notes at the switch vertex.
  350.      */
  351.     info = xswitch_info_new(busv);
  352.     for (port = MAX_PORT_NUM - MAX_XBOW_PORTS;
  353.  port < MAX_PORT_NUM; ++port) {
  354. if (!xbow_link_alive(xbow, port)) {
  355. #if DEBUG && XBOW_DEBUG
  356.     printk(KERN_INFO "0x%p link %d is not aliven",
  357.     busv, port);
  358. #endif
  359.     continue;
  360. }
  361. if (!xbow_widget_present(xbow, port)) {
  362. #if DEBUG && XBOW_DEBUG
  363.     printk(KERN_INFO "0x%p link %d is alive but no widget is presentn", busv, port);
  364. #endif
  365.     continue;
  366. }
  367. #if DEBUG && XBOW_DEBUG
  368. printk(KERN_INFO "0x%p link %d has a widgetn",
  369. busv, port);
  370. #endif
  371. xswitch_info_link_is_ok(info, port);
  372. /*
  373.  * Turn some error interrupts on
  374.  * and turn others off. The PROM has
  375.  * some things turned on we don't
  376.  * want to see (bandwidth allocation
  377.  * errors for instance); so if it
  378.  * is not listed here, it is not on.
  379.  */
  380. xbow->xb_link(port).link_control =
  381.     ( (xbow->xb_link(port).link_control
  382. /*
  383.  * Turn off these bits; they are non-fatal,
  384.  * but we might want to save some statistics
  385.  * on the frequency of these errors.
  386.  * XXX FIXME XXX
  387.  */
  388.     & ~XB_CTRL_RCV_CNT_OFLOW_IE
  389.     & ~XB_CTRL_XMT_CNT_OFLOW_IE
  390.     & ~XB_CTRL_BNDWDTH_ALLOC_IE
  391.     & ~XB_CTRL_RCV_IE)
  392. /*
  393.  * These are the ones we want to turn on.
  394.  */
  395.     | (XB_CTRL_ILLEGAL_DST_IE
  396.     | XB_CTRL_OALLOC_IBUF_IE
  397.     | XB_CTRL_XMT_MAX_RTRY_IE
  398.     | XB_CTRL_MAXREQ_TOUT_IE
  399.     | XB_CTRL_XMT_RTRY_IE
  400.     | XB_CTRL_SRC_TOUT_IE) );
  401.     }
  402.     xswitch_provider_register(busv, &xbow_provider);
  403.     return 0; /* attach successful */
  404. }
  405. /*ARGSUSED */
  406. int
  407. xbow_open(devfs_handle_t *devp, int oflag, int otyp, cred_t *credp)
  408. {
  409.     return 0;
  410. }
  411. /*ARGSUSED */
  412. int
  413. xbow_close(devfs_handle_t dev, int oflag, int otyp, cred_t *crp)
  414. {
  415.     return 0;
  416. }
  417. /*ARGSUSED */
  418. int
  419. xbow_map(devfs_handle_t dev, vhandl_t *vt, off_t off, size_t len, uint prot)
  420. {
  421.     devfs_handle_t            vhdl = dev_to_vhdl(dev);
  422.     xbow_soft_t             soft = xbow_soft_get(vhdl);
  423.     int                     error;
  424.     ASSERT(soft);
  425.     len = ctob(btoc(len));
  426.     /* XXX- this ignores the offset!!! */
  427.     error = v_mapphys(vt, (void *) soft->base, len);
  428.     return error;
  429. }
  430. /*ARGSUSED */
  431. int
  432. xbow_unmap(devfs_handle_t dev, vhandl_t *vt)
  433. {
  434.     return 0;
  435. }
  436. /* This contains special-case code for grio. There are plans to make
  437.  * this general sometime in the future, but till then this should
  438.  * be good enough.
  439.  */
  440. xwidgetnum_t
  441. xbow_widget_num_get(devfs_handle_t dev)
  442. {
  443. devfs_handle_t tdev;
  444. char devname[MAXDEVNAME];
  445. xwidget_info_t xwidget_info;
  446. int i;
  447. vertex_to_name(dev, devname, MAXDEVNAME);
  448. /* If this is a pci controller vertex, traverse up using
  449.  * the ".." links to get to the widget.
  450.  */
  451. if (strstr(devname, EDGE_LBL_PCI) &&
  452. strstr(devname, EDGE_LBL_CONTROLLER)) {
  453. tdev = dev;
  454. for (i=0; i< 2; i++) {
  455. if (hwgraph_edge_get(tdev,
  456. HWGRAPH_EDGELBL_DOTDOT, &tdev) !=
  457. GRAPH_SUCCESS)
  458. return XWIDGET_NONE;
  459. }
  460. if ((xwidget_info = xwidget_info_chk(tdev)) != NULL) {
  461. return (xwidget_info_id_get(xwidget_info));
  462. } else {
  463. return XWIDGET_NONE;
  464. }
  465. }
  466. return XWIDGET_NONE;
  467. }
  468. int
  469. xbow_ioctl(devfs_handle_t dev,
  470.    int cmd,
  471.    void *arg,
  472.    int flag,
  473.    struct cred *cr,
  474.    int *rvalp)
  475. {
  476.     devfs_handle_t            vhdl;
  477.     int                     error = 0;
  478. #if defined (DEBUG)
  479.     int                     rc;
  480.     devfs_handle_t            conn;
  481.     struct xwidget_info_s  *xwidget_info;
  482.     xbow_soft_t             xbow_soft;
  483. #endif
  484.     *rvalp = 0;
  485.     vhdl = dev_to_vhdl(dev);
  486. #if defined (DEBUG)
  487.     xbow_soft = xbow_soft_get(vhdl);
  488.     conn = xbow_soft->conn;
  489.     xwidget_info = xwidget_info_get(conn);
  490.     ASSERT_ALWAYS(xwidget_info != NULL);
  491.     rc = xwidget_hwid_is_xswitch(&xwidget_info->w_hwid);
  492.     ASSERT_ALWAYS(rc != 0);
  493. #endif
  494.     switch (cmd) {
  495. #ifdef LATER
  496.     case XBOWIOC_PERF_ENABLE:
  497.     case XBOWIOC_PERF_DISABLE:
  498. {
  499.     struct xbow_perfarg_t   xbow_perf_en;
  500.     if (!_CAP_CRABLE(cr, CAP_DEVICE_MGT)) {
  501. error = EPERM;
  502. break;
  503.     }
  504.     if ((flag & FWRITE) == 0) {
  505. error = EBADF;
  506. break;
  507.     }
  508.     if (COPYIN(arg, &xbow_perf_en, sizeof(xbow_perf_en))) {
  509. error = EFAULT;
  510. break;
  511.     }
  512.     if (error = xbow_enable_perf_counter(vhdl,
  513.  xbow_perf_en.link,
  514.  (cmd == XBOWIOC_PERF_DISABLE) ? 0 : xbow_perf_en.mode,
  515.  xbow_perf_en.counter)) {
  516. error = EINVAL;
  517. break;
  518.     }
  519.     break;
  520. }
  521. #endif
  522. #ifdef LATER
  523.     case XBOWIOC_PERF_GET:
  524. {
  525.     xbow_perf_link_t       *xbow_perf_cnt;
  526.     if ((flag & FREAD) == 0) {
  527. error = EBADF;
  528. break;
  529.     }
  530.     xbow_perf_cnt = xbow_get_perf_counters(vhdl);
  531.     ASSERT_ALWAYS(xbow_perf_cnt != NULL);
  532.     if (COPYOUT((void *) xbow_perf_cnt, (void *) arg,
  533. MAX_XBOW_PORTS * sizeof(xbow_perf_link_t))) {
  534. error = EFAULT;
  535. break;
  536.     }
  537.     break;
  538. }
  539. #endif
  540.     case XBOWIOC_LLP_ERROR_ENABLE:
  541. if ((error = xbow_enable_llp_monitor(vhdl)) != 0)
  542.     error = EINVAL;
  543. break;
  544.     case XBOWIOC_LLP_ERROR_DISABLE:
  545. if ((error = xbow_disable_llp_monitor(vhdl)) != 0)
  546.     error = EINVAL;
  547. break;
  548. #ifdef LATER
  549.     case XBOWIOC_LLP_ERROR_GET:
  550. {
  551.     xbow_link_status_t     *xbow_llp_status;
  552.     if ((flag & FREAD) == 0) {
  553. error = EBADF;
  554. break;
  555.     }
  556.     xbow_llp_status = xbow_get_llp_status(vhdl);
  557.     ASSERT_ALWAYS(xbow_llp_status != NULL);
  558.     if (COPYOUT((void *) xbow_llp_status, (void *) arg,
  559. MAX_XBOW_PORTS * sizeof(xbow_link_status_t))) {
  560. error = EFAULT;
  561. break;
  562.     }
  563.     break;
  564. }
  565. #endif
  566. #ifdef LATER
  567.     case GIOCSETBW:
  568. {
  569.     grio_ioctl_info_t info;
  570.     xwidgetnum_t src_widgetnum, dest_widgetnum;
  571.     if (COPYIN(arg, &info, sizeof(grio_ioctl_info_t))) {
  572. error = EFAULT;
  573. break;
  574.     }
  575. #ifdef GRIO_DEBUG
  576.     printf("xbow:: prev_vhdl: %d next_vhdl: %d reqbw: %lldn",
  577. info.prev_vhdl, info.next_vhdl, info.reqbw);
  578. #endif /* GRIO_DEBUG */
  579.     src_widgetnum = xbow_widget_num_get(info.prev_vhdl);
  580.     dest_widgetnum = xbow_widget_num_get(info.next_vhdl);
  581.     /* Bandwidth allocation is bi-directional. Since bandwidth
  582.      * reservations have already been done at an earlier stage,
  583.      * we cannot fail here for lack of bandwidth.
  584.      */
  585.     xbow_prio_bw_alloc(dev, src_widgetnum, dest_widgetnum,
  586. 0, info.reqbw);
  587.     xbow_prio_bw_alloc(dev, dest_widgetnum, src_widgetnum,
  588. 0, info.reqbw);
  589.     break;
  590. }
  591.     case GIOCRELEASEBW:
  592. {
  593.     grio_ioctl_info_t info;
  594.     xwidgetnum_t src_widgetnum, dest_widgetnum;
  595.     if (!cap_able(CAP_DEVICE_MGT)) {
  596. error = EPERM;
  597. break;
  598.     }
  599.     if (COPYIN(arg, &info, sizeof(grio_ioctl_info_t))) {
  600. error = EFAULT;
  601. break;
  602.     }
  603. #ifdef GRIO_DEBUG
  604.     printf("xbow:: prev_vhdl: %d next_vhdl: %d reqbw: %lldn",
  605. info.prev_vhdl, info.next_vhdl, info.reqbw);
  606. #endif /* GRIO_DEBUG */
  607.     src_widgetnum = xbow_widget_num_get(info.prev_vhdl);
  608.     dest_widgetnum = xbow_widget_num_get(info.next_vhdl);
  609.     /* Bandwidth reservation is bi-directional. Hence, remove
  610.      * bandwidth reservations for both directions.
  611.      */
  612.     xbow_prio_bw_alloc(dev, src_widgetnum, dest_widgetnum,
  613. info.reqbw, (-1 * info.reqbw));
  614.     xbow_prio_bw_alloc(dev, dest_widgetnum, src_widgetnum,
  615. info.reqbw, (-1 * info.reqbw));
  616.     break;
  617. }
  618. #endif
  619.     default:
  620. break;
  621.     }
  622.     return error;
  623. }
  624. /*
  625.  * xbow_widget_present: See if a device is present
  626.  * on the specified port of this crossbow.
  627.  */
  628. int
  629. xbow_widget_present(xbow_t * xbow, int port)
  630. {
  631. if ( IS_RUNNING_ON_SIMULATOR() ) {
  632. if ( (port == 14) || (port == 15) ) {
  633. return 1;
  634. }
  635. else {
  636. return 0;
  637. }
  638. }
  639. else {
  640. return xbow->xb_link(port).link_aux_status & XB_AUX_STAT_PRESENT;
  641. }
  642. }
  643. static int
  644. xbow_link_alive(xbow_t * xbow, int port)
  645. {
  646.     xbwX_stat_t             xbow_linkstat;
  647.     xbow_linkstat.linkstatus = xbow->xb_link(port).link_status;
  648.     return (xbow_linkstat.link_alive);
  649. }
  650. /*
  651.  * xbow_widget_lookup
  652.  *      Lookup the edges connected to the xbow specified, and
  653.  *      retrieve the handle corresponding to the widgetnum
  654.  *      specified.
  655.  *      If not found, return 0.
  656.  */
  657. devfs_handle_t
  658. xbow_widget_lookup(devfs_handle_t vhdl,
  659.    int widgetnum)
  660. {
  661.     xswitch_info_t          xswitch_info;
  662.     devfs_handle_t            conn;
  663.     xswitch_info = xswitch_info_get(vhdl);
  664.     conn = xswitch_info_vhdl_get(xswitch_info, widgetnum);
  665.     return conn;
  666. }
  667. /*
  668.  * xbow_setwidint: called when xtalk
  669.  * is establishing or migrating our
  670.  * interrupt service.
  671.  */
  672. #ifdef LATER
  673. static void
  674. xbow_setwidint(xtalk_intr_t intr)
  675. {
  676.     xwidgetnum_t            targ = xtalk_intr_target_get(intr);
  677.     iopaddr_t               addr = xtalk_intr_addr_get(intr);
  678.     xtalk_intr_vector_t     vect = xtalk_intr_vector_get(intr);
  679.     xbow_t                 *xbow = (xbow_t *) xtalk_intr_sfarg_get(intr);
  680.     xbow_intr_preset((void *) xbow, 0, targ, addr, vect);
  681. }
  682. #endif /* LATER */
  683. /*
  684.  * xbow_intr_preset: called during mlreset time
  685.  * if the platform specific code needs to route
  686.  * an xbow interrupt before the xtalk infrastructure
  687.  * is available for use.
  688.  *
  689.  * Also called from xbow_setwidint, so we don't
  690.  * replicate the guts of the routine.
  691.  *
  692.  * XXX- probably should be renamed xbow_wid_intr_set or
  693.  * something to reduce confusion.
  694.  */
  695. /*ARGSUSED3 */
  696. void
  697. xbow_intr_preset(void *which_widget,
  698.  int which_widget_intr,
  699.  xwidgetnum_t targ,
  700.  iopaddr_t addr,
  701.  xtalk_intr_vector_t vect)
  702. {
  703.     xbow_t                 *xbow = (xbow_t *) which_widget;
  704.     xbow->xb_wid_int_upper = ((0xFF000000 & (vect << 24)) |
  705.       (0x000F0000 & (targ << 16)) |
  706.       XTALK_ADDR_TO_UPPER(addr));
  707.     xbow->xb_wid_int_lower = XTALK_ADDR_TO_LOWER(addr);
  708. }
  709. #define XEM_ADD_STR(s) printk("%s", (s))
  710. #define XEM_ADD_NVAR(n,v) printk("t%20s: 0x%xn", (n), (v))
  711. #define XEM_ADD_VAR(v) XEM_ADD_NVAR(#v,(v))
  712. #define XEM_ADD_IOEF(n)  if (IOERROR_FIELDVALID(ioe,n))     
  713.     XEM_ADD_NVAR("ioe." #n,     
  714.  IOERROR_GETVALUE(ioe,n))
  715. #ifdef LATER
  716. static void
  717. xem_add_ioe(ioerror_t *ioe)
  718. {
  719.     XEM_ADD_IOEF(errortype);
  720.     XEM_ADD_IOEF(widgetnum);
  721.     XEM_ADD_IOEF(widgetdev);
  722.     XEM_ADD_IOEF(srccpu);
  723.     XEM_ADD_IOEF(srcnode);
  724.     XEM_ADD_IOEF(errnode);
  725.     XEM_ADD_IOEF(sysioaddr);
  726.     XEM_ADD_IOEF(xtalkaddr);
  727.     XEM_ADD_IOEF(busspace);
  728.     XEM_ADD_IOEF(busaddr);
  729.     XEM_ADD_IOEF(vaddr);
  730.     XEM_ADD_IOEF(memaddr);
  731.     XEM_ADD_IOEF(epc);
  732.     XEM_ADD_IOEF(ef);
  733. }
  734. #define XEM_ADD_IOE() (xem_add_ioe(ioe))
  735. #endif /* LATER */
  736. int                     xbow_xmit_retry_errors = 0;
  737. int
  738. xbow_xmit_retry_error(xbow_soft_t soft,
  739.       int port)
  740. {
  741.     xswitch_info_t          info;
  742.     devfs_handle_t            vhdl;
  743.     widget_cfg_t           *wid;
  744.     widgetreg_t             id;
  745.     int                     part;
  746.     int                     mfgr;
  747.     wid = soft->wpio[port - BASE_XBOW_PORT];
  748.     if (wid == NULL) {
  749. /* If we can't track down a PIO
  750.  * pointer to our widget yet,
  751.  * leave our caller knowing that
  752.  * we are interested in this
  753.  * interrupt if it occurs in
  754.  * the future.
  755.  */
  756. info = xswitch_info_get(soft->busv);
  757. if (!info)
  758.     return 1;
  759. vhdl = xswitch_info_vhdl_get(info, port);
  760. if (vhdl == GRAPH_VERTEX_NONE)
  761.     return 1;
  762. wid = (widget_cfg_t *) xtalk_piotrans_addr
  763.     (vhdl, 0, 0, sizeof *wid, 0);
  764. if (!wid)
  765.     return 1;
  766. soft->wpio[port - BASE_XBOW_PORT] = wid;
  767.     }
  768.     id = wid->w_id;
  769.     part = XWIDGET_PART_NUM(id);
  770.     mfgr = XWIDGET_MFG_NUM(id);
  771.     /* If this thing is not a Bridge,
  772.      * do not activate the WAR, and
  773.      * tell our caller we do not need
  774.      * to be called again.
  775.      */
  776.     if ((part != BRIDGE_WIDGET_PART_NUM) ||
  777. (mfgr != BRIDGE_WIDGET_MFGR_NUM)) {
  778. /* FIXME: add Xbridge to the WAR.
  779.  * Shouldn't hurt anything.  Later need to
  780.  * check if we can remove this.
  781.                  */
  782.      if ((part != XBRIDGE_WIDGET_PART_NUM) ||
  783.     (mfgr != XBRIDGE_WIDGET_MFGR_NUM))
  784. return 0;
  785.     }
  786.     /* count how many times we
  787.      * have picked up after
  788.      * LLP Transmit problems.
  789.      */
  790.     xbow_xmit_retry_errors++;
  791.     /* rewrite the control register
  792.      * to fix things up.
  793.      */
  794.     wid->w_control = wid->w_control;
  795.     wid->w_control;
  796.     return 1;
  797. }
  798. /*
  799.  * xbow_errintr_handler will be called if the xbow
  800.  * sends an interrupt request to report an error.
  801.  */
  802. #ifdef LATER
  803. static void
  804. xbow_errintr_handler(intr_arg_t arg)
  805. {
  806.     ioerror_t               ioe[1];
  807.     xbow_soft_t             soft = (xbow_soft_t) arg;
  808.     xbow_t                 *xbow = soft->base;
  809.     xbowreg_t               wid_control;
  810.     xbowreg_t               wid_stat;
  811.     xbowreg_t               wid_err_cmdword;
  812.     xbowreg_t               wid_err_upper;
  813.     xbowreg_t               wid_err_lower;
  814.     w_err_cmd_word_u        wid_err;
  815.     uint64_t                 wid_err_addr;
  816.     int                     fatal = 0;
  817.     int                     dump_ioe = 0;
  818.     wid_control = xbow->xb_wid_control;
  819.     wid_stat = xbow->xb_wid_stat_clr;
  820.     wid_err_cmdword = xbow->xb_wid_err_cmdword;
  821.     wid_err_upper = xbow->xb_wid_err_upper;
  822.     wid_err_lower = xbow->xb_wid_err_lower;
  823.     xbow->xb_wid_err_cmdword = 0;
  824.     wid_err_addr =
  825. wid_err_lower
  826. | (((iopaddr_t) wid_err_upper
  827.     & WIDGET_ERR_UPPER_ADDR_ONLY)
  828.    << 32);
  829.     if (wid_stat & XB_WID_STAT_LINK_INTR_MASK) {
  830. int                     port;
  831. wid_err.r = wid_err_cmdword;
  832. for (port = MAX_PORT_NUM - MAX_XBOW_PORTS;
  833.      port < MAX_PORT_NUM; port++) {
  834.     if (wid_stat & XB_WID_STAT_LINK_INTR(port)) {
  835. xb_linkregs_t          *link = &(xbow->xb_link(port));
  836. xbowreg_t               link_control = link->link_control;
  837. xbowreg_t               link_status = link->link_status_clr;
  838. xbowreg_t               link_aux_status = link->link_aux_status;
  839. xbowreg_t               link_pend;
  840. link_pend = link_status & link_control &
  841.     (XB_STAT_ILLEGAL_DST_ERR
  842.      | XB_STAT_OALLOC_IBUF_ERR
  843.      | XB_STAT_RCV_CNT_OFLOW_ERR
  844.      | XB_STAT_XMT_CNT_OFLOW_ERR
  845.      | XB_STAT_XMT_MAX_RTRY_ERR
  846.      | XB_STAT_RCV_ERR
  847.      | XB_STAT_XMT_RTRY_ERR
  848.      | XB_STAT_MAXREQ_TOUT_ERR
  849.      | XB_STAT_SRC_TOUT_ERR
  850.     );
  851. if (link_pend & XB_STAT_ILLEGAL_DST_ERR) {
  852.     if (wid_err.f.sidn == port) {
  853. IOERROR_INIT(ioe);
  854. IOERROR_SETVALUE(ioe, widgetnum, port);
  855. IOERROR_SETVALUE(ioe, xtalkaddr, wid_err_addr);
  856. if (IOERROR_HANDLED ==
  857.     xbow_error_handler(soft,
  858.        IOECODE_DMA,
  859.        MODE_DEVERROR,
  860.        ioe)) {
  861.     link_pend &= ~XB_STAT_ILLEGAL_DST_ERR;
  862. } else {
  863.     dump_ioe++;
  864. }
  865.     }
  866. }
  867. /* Xbow/Bridge WAR:
  868.  * if the bridge signals an LLP Transmitter Retry,
  869.  * rewrite its control register.
  870.  * If someone else triggers this interrupt,
  871.  * ignore (and disable) the interrupt.
  872.  */
  873. if (link_pend & XB_STAT_XMT_RTRY_ERR) {
  874.     if (!xbow_xmit_retry_error(soft, port)) {
  875. link_control &= ~XB_CTRL_XMT_RTRY_IE;
  876. link->link_control = link_control;
  877. link->link_control; /* stall until written */
  878.     }
  879.     link_pend &= ~XB_STAT_XMT_RTRY_ERR;
  880. }
  881. if (link_pend) {
  882.     devfs_handle_t xwidget_vhdl;
  883.     char *xwidget_name;
  884.     
  885.     /* Get the widget name corresponding to the current
  886.      * xbow link.
  887.      */
  888.     xwidget_vhdl = xbow_widget_lookup(soft->busv,port);
  889.     xwidget_name = xwidget_name_get(xwidget_vhdl);
  890. #ifdef LATER
  891.     printk("%s port %X[%s] XIO Bus Error",
  892.     soft->name, port, xwidget_name);
  893.     if (link_status & XB_STAT_MULTI_ERR)
  894. XEM_ADD_STR("tMultiple Errorsn");
  895.     if (link_status & XB_STAT_ILLEGAL_DST_ERR)
  896. XEM_ADD_STR("tInvalid Packet Destinationn");
  897.     if (link_status & XB_STAT_OALLOC_IBUF_ERR)
  898. XEM_ADD_STR("tInput Overallocation Errorn");
  899.     if (link_status & XB_STAT_RCV_CNT_OFLOW_ERR)
  900. XEM_ADD_STR("tLLP receive error counter overflown");
  901.     if (link_status & XB_STAT_XMT_CNT_OFLOW_ERR)
  902. XEM_ADD_STR("tLLP transmit retry counter overflown");
  903.     if (link_status & XB_STAT_XMT_MAX_RTRY_ERR)
  904. XEM_ADD_STR("tLLP Max Transmitter Retryn");
  905.     if (link_status & XB_STAT_RCV_ERR)
  906. XEM_ADD_STR("tLLP Receiver errorn");
  907.     if (link_status & XB_STAT_XMT_RTRY_ERR)
  908. XEM_ADD_STR("tLLP Transmitter Retryn");
  909.     if (link_status & XB_STAT_MAXREQ_TOUT_ERR)
  910. XEM_ADD_STR("tMaximum Request Timeoutn");
  911.     if (link_status & XB_STAT_SRC_TOUT_ERR)
  912. XEM_ADD_STR("tSource Timeout Errorn");
  913. #endif /* LATER */
  914.     {
  915. int                     other_port;
  916. for (other_port = 8; other_port < 16; ++other_port) {
  917.     if (link_aux_status & (1 << other_port)) {
  918. /* XXX- need to go to "other_port"
  919.  * and clean up after the timeout?
  920.  */
  921. XEM_ADD_VAR(other_port);
  922.     }
  923. }
  924.     }
  925. #if !DEBUG
  926.     if (kdebug) {
  927. #endif
  928. XEM_ADD_VAR(link_control);
  929. XEM_ADD_VAR(link_status);
  930. XEM_ADD_VAR(link_aux_status);
  931. if (dump_ioe) {
  932.     XEM_ADD_IOE();
  933.     dump_ioe = 0;
  934. }
  935. #if !DEBUG
  936.     }
  937. #endif
  938.     fatal++;
  939. }
  940.     }
  941. }
  942.     }
  943.     if (wid_stat & wid_control & XB_WID_STAT_WIDGET0_INTR) {
  944. /* we have a "widget zero" problem */
  945. if (wid_stat & (XB_WID_STAT_MULTI_ERR
  946. | XB_WID_STAT_XTALK_ERR
  947. | XB_WID_STAT_REG_ACC_ERR)) {
  948.     printk("%s Port 0 XIO Bus Error",
  949.     soft->name);
  950.     if (wid_stat & XB_WID_STAT_MULTI_ERR)
  951. XEM_ADD_STR("tMultiple Errorn");
  952.     if (wid_stat & XB_WID_STAT_XTALK_ERR)
  953. XEM_ADD_STR("tXIO Errorn");
  954.     if (wid_stat & XB_WID_STAT_REG_ACC_ERR)
  955. XEM_ADD_STR("tRegister Access Errorn");
  956.     fatal++;
  957. }
  958.     }
  959.     if (fatal) {
  960. XEM_ADD_VAR(wid_stat);
  961. XEM_ADD_VAR(wid_control);
  962. XEM_ADD_VAR(wid_err_cmdword);
  963. XEM_ADD_VAR(wid_err_upper);
  964. XEM_ADD_VAR(wid_err_lower);
  965. XEM_ADD_VAR(wid_err_addr);
  966. PRINT_PANIC("XIO Bus Error");
  967.     }
  968. }
  969. #endif /* LATER */
  970. /*
  971.  * XBOW ERROR Handling routines.
  972.  * These get invoked as part of walking down the error handling path
  973.  * from hub/heart towards the I/O device that caused the error.
  974.  */
  975. /*
  976.  * xbow_error_handler
  977.  *      XBow error handling dispatch routine.
  978.  *      This is the primary interface used by external world to invoke
  979.  *      in case of an error related to a xbow.
  980.  *      Only functionality in this layer is to identify the widget handle
  981.  *      given the widgetnum. Otherwise, xbow does not gathers any error
  982.  *      data.
  983.  */
  984. #ifdef LATER
  985. static int
  986. xbow_error_handler(
  987.       void *einfo,
  988.       int error_code,
  989.       ioerror_mode_t mode,
  990.       ioerror_t *ioerror)
  991. {
  992.     int                     retval = IOERROR_WIDGETLEVEL;
  993.     xbow_soft_t             soft = (xbow_soft_t) einfo;
  994.     int                     port;
  995.     devfs_handle_t            conn;
  996.     devfs_handle_t            busv;
  997.     xbow_t                 *xbow = soft->base;
  998.     xbowreg_t               wid_stat;
  999.     xbowreg_t               wid_err_cmdword;
  1000.     xbowreg_t               wid_err_upper;
  1001.     xbowreg_t               wid_err_lower;
  1002.     uint64_t                 wid_err_addr;
  1003.     xb_linkregs_t          *link;
  1004.     xbowreg_t               link_control;
  1005.     xbowreg_t               link_status;
  1006.     xbowreg_t               link_aux_status;
  1007.     ASSERT(soft != 0);
  1008.     busv = soft->busv;
  1009. #if DEBUG && ERROR_DEBUG
  1010.     printk("%s: xbow_error_handlern", soft->name, busv);
  1011. #endif
  1012.     port = IOERROR_GETVALUE(ioerror, widgetnum);
  1013.     if (port == 0) {
  1014. /* error during access to xbow:
  1015.  * do NOT attempt to access xbow regs.
  1016.  */
  1017. if (mode == MODE_DEVPROBE)
  1018.     return IOERROR_HANDLED;
  1019. if (error_code & IOECODE_DMA) {
  1020.     PRINT_ALERT("DMA error blamed on Crossbow at %sn"
  1021.     "tbut Crosbow never initiates DMA!",
  1022.     soft->name);
  1023. }
  1024. if (error_code & IOECODE_PIO) {
  1025.     PRINT_ALERt("PIO Error on XIO Bus %sn"
  1026.     "tattempting to access XIO controllern"
  1027.     "twith offset 0x%X",
  1028.     soft->name,
  1029.     IOERROR_GETVALUE(ioerror, xtalkaddr));
  1030. }
  1031. /* caller will dump contents of ioerror
  1032.  * in DEBUG and kdebug kernels.
  1033.  */
  1034. return retval;
  1035.     }
  1036.     /*
  1037.      * error not on port zero:
  1038.      * safe to read xbow registers.
  1039.      */
  1040.     wid_stat = xbow->xb_wid_stat;
  1041.     wid_err_cmdword = xbow->xb_wid_err_cmdword;
  1042.     wid_err_upper = xbow->xb_wid_err_upper;
  1043.     wid_err_lower = xbow->xb_wid_err_lower;
  1044.     wid_err_addr =
  1045. wid_err_lower
  1046. | (((iopaddr_t) wid_err_upper
  1047.     & WIDGET_ERR_UPPER_ADDR_ONLY)
  1048.    << 32);
  1049.     if ((port < BASE_XBOW_PORT) ||
  1050. (port >= MAX_PORT_NUM)) {
  1051. if (mode == MODE_DEVPROBE)
  1052.     return IOERROR_HANDLED;
  1053. if (error_code & IOECODE_DMA) {
  1054.     PRINT_ALERT("DMA error blamed on XIO port at %s/%dn"
  1055.     "tbut Crossbow does not support that port",
  1056.     soft->name, port);
  1057. }
  1058. if (error_code & IOECODE_PIO) {
  1059.     PRINT_ALERT("PIO Error on XIO Bus %sn"
  1060.     "tattempting to access XIO port %dn"
  1061.     "t(which Crossbow does not support)"
  1062.     "twith offset 0x%X",
  1063.     soft->name, port,
  1064.     IOERROR_GETVALUE(ioerror, xtalkaddr));
  1065. }
  1066. #if !DEBUG
  1067. if (kdebug) {
  1068. #endif
  1069.     XEM_ADD_STR("Raw status values for Crossbow:n");
  1070.     XEM_ADD_VAR(wid_stat);
  1071.     XEM_ADD_VAR(wid_err_cmdword);
  1072.     XEM_ADD_VAR(wid_err_upper);
  1073.     XEM_ADD_VAR(wid_err_lower);
  1074.     XEM_ADD_VAR(wid_err_addr);
  1075. #if !DEBUG
  1076. }
  1077. #endif
  1078. /* caller will dump contents of ioerror
  1079.  * in DEBUG and kdebug kernels.
  1080.  */
  1081. return retval;
  1082.     }
  1083.     /* access to valid port:
  1084.      * ok to check port status.
  1085.      */
  1086.     link = &(xbow->xb_link(port));
  1087.     link_control = link->link_control;
  1088.     link_status = link->link_status;
  1089.     link_aux_status = link->link_aux_status;
  1090.     /* Check that there is something present
  1091.      * in that XIO port.
  1092.      */
  1093.     if (!(link_aux_status & XB_AUX_STAT_PRESENT)) {
  1094. /* nobody connected. */
  1095. if (mode == MODE_DEVPROBE)
  1096.     return IOERROR_HANDLED;
  1097. if (error_code & IOECODE_DMA) {
  1098.     PRINT_ALERT("DMA error blamed on XIO port at %s/%dn"
  1099.     "tbut there is no device connected there.",
  1100.     soft->name, port);
  1101. }
  1102. if (error_code & IOECODE_PIO) {
  1103.     PRINT_ALERT("PIO Error on XIO Bus %sn"
  1104.     "tattempting to access XIO port %dn"
  1105.     "t(which has no device connected)"
  1106.     "twith offset 0x%X",
  1107.     soft->name, port,
  1108.     IOERROR_GETVALUE(ioerror, xtalkaddr));
  1109. }
  1110. #if !DEBUG
  1111. if (kdebug) {
  1112. #endif
  1113.     XEM_ADD_STR("Raw status values for Crossbow:n");
  1114.     XEM_ADD_VAR(wid_stat);
  1115.     XEM_ADD_VAR(wid_err_cmdword);
  1116.     XEM_ADD_VAR(wid_err_upper);
  1117.     XEM_ADD_VAR(wid_err_lower);
  1118.     XEM_ADD_VAR(wid_err_addr);
  1119.     XEM_ADD_VAR(port);
  1120.     XEM_ADD_VAR(link_control);
  1121.     XEM_ADD_VAR(link_status);
  1122.     XEM_ADD_VAR(link_aux_status);
  1123. #if !DEBUG
  1124. }
  1125. #endif
  1126. return retval;
  1127.     }
  1128.     /* Check that the link is alive.
  1129.      */
  1130.     if (!(link_status & XB_STAT_LINKALIVE)) {
  1131. /* nobody connected. */
  1132. if (mode == MODE_DEVPROBE)
  1133.     return IOERROR_HANDLED;
  1134. PRINT_ALERT("%s%sError on XIO Bus %s port %d",
  1135. (error_code & IOECODE_DMA) ? "DMA " : "",
  1136. (error_code & IOECODE_PIO) ? "PIO " : "",
  1137. soft->name, port);
  1138. if ((error_code & IOECODE_PIO) &&
  1139.     (IOERROR_FIELDVALID(ioerror, xtalkaddr))) {
  1140.     printk("tAccess attempted to offset 0x%Xn",
  1141.     IOERROR_GETVALUE(ioerror, xtalkaddr));
  1142. }
  1143. if (link_aux_status & XB_AUX_LINKFAIL_RST_BAD)
  1144.     XEM_ADD_STR("tLink never came out of resetn");
  1145. else
  1146.     XEM_ADD_STR("tLink failed while transferring datan");
  1147.     }
  1148.     /* get the connection point for the widget
  1149.      * involved in this error; if it exists and
  1150.      * is not our connectpoint, cycle back through
  1151.      * xtalk_error_handler to deliver control to
  1152.      * the proper handler (or to report a generic
  1153.      * crosstalk error).
  1154.      *
  1155.      * If the downstream handler won't handle
  1156.      * the problem, we let our upstream caller
  1157.      * deal with it, after (in DEBUG and kdebug
  1158.      * kernels) dumping the xbow state for this
  1159.      * port.
  1160.      */
  1161.     conn = xbow_widget_lookup(busv, port);
  1162.     if ((conn != GRAPH_VERTEX_NONE) &&
  1163. (conn != soft->conn)) {
  1164. retval = xtalk_error_handler(conn, error_code, mode, ioerror);
  1165. if (retval == IOERROR_HANDLED)
  1166.     return IOERROR_HANDLED;
  1167.     }
  1168.     if (mode == MODE_DEVPROBE)
  1169. return IOERROR_HANDLED;
  1170.     if (retval == IOERROR_UNHANDLED) {
  1171. retval = IOERROR_PANIC;
  1172. PRINT_ALERT("%s%sError on XIO Bus %s port %d",
  1173. (error_code & IOECODE_DMA) ? "DMA " : "",
  1174. (error_code & IOECODE_PIO) ? "PIO " : "",
  1175. soft->name, port);
  1176. if ((error_code & IOECODE_PIO) &&
  1177.     (IOERROR_FIELDVALID(ioerror, xtalkaddr))) {
  1178.     printk("tAccess attempted to offset 0x%Xn",
  1179.     IOERROR_GETVALUE(ioerror, xtalkaddr));
  1180. }
  1181.     }
  1182. #if !DEBUG
  1183.     if (kdebug) {
  1184. #endif
  1185. XEM_ADD_STR("Raw status values for Crossbow:n");
  1186. XEM_ADD_VAR(wid_stat);
  1187. XEM_ADD_VAR(wid_err_cmdword);
  1188. XEM_ADD_VAR(wid_err_upper);
  1189. XEM_ADD_VAR(wid_err_lower);
  1190. XEM_ADD_VAR(wid_err_addr);
  1191. XEM_ADD_VAR(port);
  1192. XEM_ADD_VAR(link_control);
  1193. XEM_ADD_VAR(link_status);
  1194. XEM_ADD_VAR(link_aux_status);
  1195. #if !DEBUG
  1196.     }
  1197. #endif
  1198.     /* caller will dump raw ioerror data
  1199.      * in DEBUG and kdebug kernels.
  1200.      */
  1201.     return retval;
  1202. }
  1203. #endif /* LATER */
  1204. void
  1205. xbow_update_perf_counters(devfs_handle_t vhdl)
  1206. {
  1207.     xbow_soft_t             xbow_soft = xbow_soft_get(vhdl);
  1208.     xbow_perf_t            *xbow_perf = xbow_soft->xbow_perfcnt;
  1209.     xbow_perf_link_t       *xbow_plink = xbow_soft->xbow_perflink;
  1210.     xbow_perfcount_t        perf_reg;
  1211.     unsigned long           s;
  1212.     int                     link, i;
  1213.     for (i = 0; i < XBOW_PERF_COUNTERS; i++, xbow_perf++) {
  1214. if (xbow_perf->xp_mode == XBOW_MONITOR_NONE)
  1215.     continue;
  1216. s = mutex_spinlock(&xbow_soft->xbow_perf_lock);
  1217. perf_reg.xb_counter_val = *(xbowreg_t *) xbow_perf->xp_perf_reg;
  1218. link = perf_reg.xb_perf.link_select;
  1219. (xbow_plink + link)->xlp_cumulative[xbow_perf->xp_curmode] +=
  1220.     ((perf_reg.xb_perf.count - xbow_perf->xp_current) & XBOW_COUNTER_MASK);
  1221. xbow_perf->xp_current = perf_reg.xb_perf.count;
  1222. mutex_spinunlock(&xbow_soft->xbow_perf_lock, s);
  1223.     }
  1224.     /* Do port /mode multiplexing here */
  1225. #ifdef LATER
  1226.     (void) timeout(xbow_update_perf_counters,
  1227.    (void *) (__psunsigned_t) vhdl, XBOW_PERF_TIMEOUT);
  1228. #endif
  1229. }
  1230. xbow_perf_link_t       *
  1231. xbow_get_perf_counters(devfs_handle_t vhdl)
  1232. {
  1233.     xbow_soft_t             xbow_soft = xbow_soft_get(vhdl);
  1234.     xbow_perf_link_t       *xbow_perf_link = xbow_soft->xbow_perflink;
  1235.     return xbow_perf_link;
  1236. }
  1237. int
  1238. xbow_enable_perf_counter(devfs_handle_t vhdl, int link, int mode, int counter)
  1239. {
  1240.     xbow_soft_t             xbow_soft = xbow_soft_get(vhdl);
  1241.     xbow_perf_t            *xbow_perf = xbow_soft->xbow_perfcnt;
  1242.     xbow_linkctrl_t         xbow_link_ctrl;
  1243.     xbow_t                 *xbow = xbow_soft->base;
  1244.     xbow_perfcount_t        perf_reg;
  1245.     unsigned long           s;
  1246.     int                     i;
  1247.     link -= BASE_XBOW_PORT;
  1248.     if ((link < 0) || (link >= MAX_XBOW_PORTS))
  1249. return -1;
  1250.     if ((mode < XBOW_MONITOR_NONE) || (mode > XBOW_MONITOR_DEST_LINK))
  1251. return -1;
  1252.     if ((counter < 0) || (counter >= XBOW_PERF_COUNTERS))
  1253. return -1;
  1254.     s = mutex_spinlock(&xbow_soft->xbow_perf_lock);
  1255.     if ((xbow_perf + counter)->xp_mode && mode) {
  1256. mutex_spinunlock(&xbow_soft->xbow_perf_lock, s);
  1257. return -1;
  1258.     }
  1259.     for (i = 0; i < XBOW_PERF_COUNTERS; i++) {
  1260. if (i == counter)
  1261.     continue;
  1262. if (((xbow_perf + i)->xp_link == link) &&
  1263.     ((xbow_perf + i)->xp_mode)) {
  1264.     mutex_spinunlock(&xbow_soft->xbow_perf_lock, s);
  1265.     return -1;
  1266. }
  1267.     }
  1268.     xbow_perf += counter;
  1269.     xbow_perf->xp_curlink = xbow_perf->xp_link = link;
  1270.     xbow_perf->xp_curmode = xbow_perf->xp_mode = mode;
  1271.     xbow_link_ctrl.xbl_ctrlword = xbow->xb_link_raw[link].link_control;
  1272.     xbow_link_ctrl.xb_linkcontrol.perf_mode = mode;
  1273.     xbow->xb_link_raw[link].link_control = xbow_link_ctrl.xbl_ctrlword;
  1274.     perf_reg.xb_counter_val = *(xbowreg_t *) xbow_perf->xp_perf_reg;
  1275.     perf_reg.xb_perf.link_select = link;
  1276.     *(xbowreg_t *) xbow_perf->xp_perf_reg = perf_reg.xb_counter_val;
  1277.     xbow_perf->xp_current = perf_reg.xb_perf.count;
  1278. #ifdef LATER
  1279.     (void) timeout(xbow_update_perf_counters,
  1280.    (void *) (__psunsigned_t) vhdl, XBOW_PERF_TIMEOUT);
  1281. #endif
  1282.     mutex_spinunlock(&xbow_soft->xbow_perf_lock, s);
  1283.     return 0;
  1284. }
  1285. xbow_link_status_t     *
  1286. xbow_get_llp_status(devfs_handle_t vhdl)
  1287. {
  1288.     xbow_soft_t             xbow_soft = xbow_soft_get(vhdl);
  1289.     xbow_link_status_t     *xbow_llp_status = xbow_soft->xbow_link_status;
  1290.     return xbow_llp_status;
  1291. }
  1292. void
  1293. xbow_update_llp_status(devfs_handle_t vhdl)
  1294. {
  1295.     xbow_soft_t             xbow_soft = xbow_soft_get(vhdl);
  1296.     xbow_link_status_t     *xbow_llp_status = xbow_soft->xbow_link_status;
  1297.     xbow_t                 *xbow;
  1298.     xbwX_stat_t             lnk_sts;
  1299.     xbow_aux_link_status_t  aux_sts;
  1300.     int                     link;
  1301.     devfs_handle_t     xwidget_vhdl;
  1302.     char    *xwidget_name;
  1303.     xbow = (xbow_t *) xbow_soft->base;
  1304.     for (link = 0; link < MAX_XBOW_PORTS; link++, xbow_llp_status++) {
  1305. /* Get the widget name corresponding the current link.
  1306.  * Note : 0 <= link < MAX_XBOW_PORTS(8).
  1307.  *    BASE_XBOW_PORT(0x8) <= xwidget number < MAX_PORT_NUM (0x10)
  1308.  */
  1309. xwidget_vhdl = xbow_widget_lookup(xbow_soft->busv,link+BASE_XBOW_PORT);
  1310. xwidget_name = xwidget_name_get(xwidget_vhdl);
  1311. aux_sts.aux_linkstatus
  1312.     = xbow->xb_link_raw[link].link_aux_status;
  1313. lnk_sts.linkstatus = xbow->xb_link_raw[link].link_status_clr;
  1314. if (lnk_sts.link_alive == 0)
  1315.     continue;
  1316. xbow_llp_status->rx_err_count +=
  1317.     aux_sts.xb_aux_linkstatus.rx_err_cnt;
  1318. xbow_llp_status->tx_retry_count +=
  1319.     aux_sts.xb_aux_linkstatus.tx_retry_cnt;
  1320. if (lnk_sts.linkstatus & ~(XB_STAT_RCV_ERR | XB_STAT_XMT_RTRY_ERR | XB_STAT_LINKALIVE)) {
  1321. #ifdef LATER
  1322.     PRINT_WARNING("link %d[%s]: bad status 0x%xn",
  1323.     link, xwidget_name, lnk_sts.linkstatus);
  1324. #endif
  1325. }
  1326.     }
  1327. #ifdef LATER
  1328.     if (xbow_soft->link_monitor)
  1329. (void) timeout(xbow_update_llp_status,
  1330.        (void *) (__psunsigned_t) vhdl, XBOW_STATS_TIMEOUT);
  1331. #endif
  1332. }
  1333. int
  1334. xbow_disable_llp_monitor(devfs_handle_t vhdl)
  1335. {
  1336.     xbow_soft_t             xbow_soft = xbow_soft_get(vhdl);
  1337.     int                     port;
  1338.     for (port = 0; port < MAX_XBOW_PORTS; port++) {
  1339. xbow_soft->xbow_link_status[port].rx_err_count = 0;
  1340. xbow_soft->xbow_link_status[port].tx_retry_count = 0;
  1341.     }
  1342.     xbow_soft->link_monitor = 0;
  1343.     return 0;
  1344. }
  1345. int
  1346. xbow_enable_llp_monitor(devfs_handle_t vhdl)
  1347. {
  1348.     xbow_soft_t             xbow_soft = xbow_soft_get(vhdl);
  1349. #ifdef LATER
  1350.     (void) timeout(xbow_update_llp_status,
  1351.    (void *) (__psunsigned_t) vhdl, XBOW_STATS_TIMEOUT);
  1352. #endif
  1353.     xbow_soft->link_monitor = 1;
  1354.     return 0;
  1355. }
  1356. int
  1357. xbow_reset_link(devfs_handle_t xconn_vhdl)
  1358. {
  1359.     xwidget_info_t          widget_info;
  1360.     xwidgetnum_t            port;
  1361.     xbow_t                 *xbow;
  1362.     xbowreg_t               ctrl;
  1363.     xbwX_stat_t             stat;
  1364.     unsigned                itick;
  1365.     unsigned                dtick;
  1366.     static int              ticks_per_ms = 0;
  1367.     if (!ticks_per_ms) {
  1368. itick = get_timestamp();
  1369. us_delay(1000);
  1370. ticks_per_ms = get_timestamp() - itick;
  1371.     }
  1372.     widget_info = xwidget_info_get(xconn_vhdl);
  1373.     port = xwidget_info_id_get(widget_info);
  1374. #ifdef XBOW_K1PTR /* defined if we only have one xbow ... */
  1375.     xbow = XBOW_K1PTR;
  1376. #else
  1377.     {
  1378. devfs_handle_t            xbow_vhdl;
  1379. xbow_soft_t             xbow_soft;
  1380. hwgraph_traverse(xconn_vhdl, ".master/xtalk/0/xbow", &xbow_vhdl);
  1381. xbow_soft = xbow_soft_get(xbow_vhdl);
  1382. xbow = xbow_soft->base;
  1383.     }
  1384. #endif
  1385.     /*
  1386.      * This requires three PIOs (reset the link, check for the
  1387.      * reset, restore the control register for the link) plus
  1388.      * 10us to wait for the reset. We allow up to 1ms for the
  1389.      * widget to come out of reset before giving up and
  1390.      * returning a failure.
  1391.      */
  1392.     ctrl = xbow->xb_link(port).link_control;
  1393.     xbow->xb_link(port).link_reset = 0;
  1394.     itick = get_timestamp();
  1395.     while (1) {
  1396. stat.linkstatus = xbow->xb_link(port).link_status;
  1397. if (stat.link_alive)
  1398.     break;
  1399. dtick = get_timestamp() - itick;
  1400. if (dtick > ticks_per_ms) {
  1401.     return -1; /* never came out of reset */
  1402. }
  1403. DELAY(2); /* don't beat on link_status */
  1404.     }
  1405.     xbow->xb_link(port).link_control = ctrl;
  1406.     return 0;
  1407. }
  1408. /*
  1409.  * Dump xbow registers.
  1410.  * input parameter is either a pointer to
  1411.  * the xbow chip or the vertex handle for
  1412.  * an xbow vertex.
  1413.  */
  1414. void
  1415. idbg_xbowregs(int64_t regs)
  1416. {
  1417.     xbow_t                 *xbow;
  1418.     int                     i;
  1419.     xb_linkregs_t          *link;
  1420. #ifdef LATER
  1421.     if (dev_is_vertex((devfs_handle_t) regs)) {
  1422. devfs_handle_t            vhdl = (devfs_handle_t) regs;
  1423. xbow_soft_t             soft = xbow_soft_get(vhdl);
  1424. xbow = soft->base;
  1425.     } else
  1426. #endif
  1427.     {
  1428. xbow = (xbow_t *) regs;
  1429.     }
  1430. #ifdef LATER
  1431.     qprintf("Printing xbow registers starting at 0x%xn", xbow);
  1432.     qprintf("wid %x status %x erruppr %x errlower %x control %x timeout %xn",
  1433.     xbow->xb_wid_id, xbow->xb_wid_stat, xbow->xb_wid_err_upper,
  1434.     xbow->xb_wid_err_lower, xbow->xb_wid_control,
  1435.     xbow->xb_wid_req_timeout);
  1436.     qprintf("intr uppr %x lower %x errcmd %x llp ctrl %x arb_reload %xn",
  1437.     xbow->xb_wid_int_upper, xbow->xb_wid_int_lower,
  1438.     xbow->xb_wid_err_cmdword, xbow->xb_wid_llp,
  1439.     xbow->xb_wid_arb_reload);
  1440. #endif
  1441.     for (i = 8; i <= 0xf; i++) {
  1442. link = &xbow->xb_link(i);
  1443. #ifdef LATER
  1444. qprintf("Link %d registersn", i);
  1445. qprintf("tctrl %x stat %x arbuppr %x arblowr %x auxstat %xn",
  1446. link->link_control, link->link_status,
  1447. link->link_arb_upper, link->link_arb_lower,
  1448. link->link_aux_status);
  1449. #endif
  1450.     }
  1451. }
  1452. #define XBOW_ARB_RELOAD_TICKS 25
  1453. /* granularity: 4 MB/s, max: 124 MB/s */
  1454. #define GRANULARITY ((100 * 1000000) / XBOW_ARB_RELOAD_TICKS)
  1455. #define XBOW_BYTES_TO_GBR(BYTES_per_s) (int) (BYTES_per_s / GRANULARITY)
  1456. #define XBOW_GBR_TO_BYTES(cnt) (bandwidth_t) ((cnt) * GRANULARITY)
  1457. #define CEILING_BYTES_TO_GBR(gbr, bytes_per_sec)
  1458. ((XBOW_GBR_TO_BYTES(gbr) < bytes_per_sec) ? gbr+1 : gbr)
  1459. #define XBOW_ARB_GBR_MAX 31
  1460. #define ABS(x) ((x > 0) ? (x) : (-1 * x))
  1461. /* absolute value */
  1462. int
  1463. xbow_bytes_to_gbr(bandwidth_t old_bytes_per_sec, bandwidth_t bytes_per_sec)
  1464. {
  1465.     int                     gbr_granted;
  1466.     int                     new_total_gbr;
  1467.     int                     change_gbr;
  1468.     bandwidth_t             new_total_bw;
  1469. #ifdef GRIO_DEBUG
  1470.     printf("xbow_bytes_to_gbr: old_bytes_per_sec %lld bytes_per_sec %lldn",
  1471. old_bytes_per_sec, bytes_per_sec);
  1472. #endif /* GRIO_DEBUG */
  1473.     gbr_granted = CEILING_BYTES_TO_GBR((XBOW_BYTES_TO_GBR(old_bytes_per_sec)),
  1474. old_bytes_per_sec);
  1475.     new_total_bw = old_bytes_per_sec + bytes_per_sec;
  1476.     new_total_gbr = CEILING_BYTES_TO_GBR((XBOW_BYTES_TO_GBR(new_total_bw)),
  1477. new_total_bw);
  1478.     change_gbr = new_total_gbr - gbr_granted;
  1479. #ifdef GRIO_DEBUG
  1480.     printf("xbow_bytes_to_gbr: gbr_granted %d new_total_gbr %d change_gbr %dn",
  1481. gbr_granted, new_total_gbr, change_gbr);
  1482. #endif /* GRIO_DEBUG */
  1483.     return (change_gbr);
  1484. }
  1485. /* Conversion from GBR to bytes */
  1486. bandwidth_t
  1487. xbow_gbr_to_bytes(int gbr)
  1488. {
  1489.     return (XBOW_GBR_TO_BYTES(gbr));
  1490. }
  1491. /* Given the vhdl for the desired xbow, the src and dest. widget ids
  1492.  * and the req_bw value, this xbow driver entry point accesses the
  1493.  * xbow registers and allocates the desired bandwidth if available.
  1494.  *
  1495.  * If bandwidth allocation is successful, return success else return failure.
  1496.  */
  1497. int
  1498. xbow_prio_bw_alloc(devfs_handle_t vhdl,
  1499. xwidgetnum_t src_wid,
  1500. xwidgetnum_t dest_wid,
  1501. unsigned long long old_alloc_bw,
  1502. unsigned long long req_bw)
  1503. {
  1504.     xbow_soft_t             soft = xbow_soft_get(vhdl);
  1505.     volatile xbowreg_t     *xreg;
  1506.     xbowreg_t               mask;
  1507.     unsigned long           s;
  1508.     int                     error = 0;
  1509.     bandwidth_t             old_bw_BYTES, req_bw_BYTES;
  1510.     xbowreg_t               old_xreg;
  1511.     int                     old_bw_GBR, req_bw_GBR, new_bw_GBR;
  1512. #ifdef GRIO_DEBUG
  1513.     printf("xbow_prio_bw_alloc: vhdl %d src_wid %d dest_wid %d req_bw %lldn",
  1514. (int) vhdl, (int) src_wid, (int) dest_wid, req_bw);
  1515. #endif
  1516.     ASSERT(XBOW_WIDGET_IS_VALID(src_wid));
  1517.     ASSERT(XBOW_WIDGET_IS_VALID(dest_wid));
  1518.     s = mutex_spinlock(&soft->xbow_bw_alloc_lock);
  1519.     /* Get pointer to the correct register */
  1520.     xreg = XBOW_PRIO_ARBREG_PTR(soft->base, dest_wid, src_wid);
  1521.     /* Get mask for GBR count value */
  1522.     mask = XB_ARB_GBR_MSK << XB_ARB_GBR_SHFT(src_wid);
  1523.     req_bw_GBR = xbow_bytes_to_gbr(old_alloc_bw, req_bw);
  1524.     req_bw_BYTES = (req_bw_GBR < 0) ? (-1 * xbow_gbr_to_bytes(ABS(req_bw_GBR)))
  1525. : xbow_gbr_to_bytes(req_bw_GBR);
  1526. #ifdef GRIO_DEBUG
  1527.     printf("req_bw %lld req_bw_BYTES %lld req_bw_GBR %dn",
  1528. req_bw, req_bw_BYTES, req_bw_GBR);
  1529. #endif /* GRIO_DEBUG */
  1530.     old_bw_BYTES = soft->bw_cur_used[(int) dest_wid - MAX_XBOW_PORTS];
  1531.     old_xreg = *xreg;
  1532.     old_bw_GBR = (((*xreg) & mask) >> XB_ARB_GBR_SHFT(src_wid));
  1533. #ifdef GRIO_DEBUG
  1534.     ASSERT(XBOW_BYTES_TO_GBR(old_bw_BYTES) == old_bw_GBR);
  1535.     printf("old_bw_BYTES %lld old_bw_GBR %dn", old_bw_BYTES, old_bw_GBR);
  1536.     printf("req_bw_BYTES %lld old_bw_BYTES %lld soft->bw_hiwm %lldn",
  1537. req_bw_BYTES, old_bw_BYTES,
  1538. soft->bw_hiwm[(int) dest_wid - MAX_XBOW_PORTS]);
  1539.    
  1540. #endif /* GRIO_DEBUG */
  1541.     /* Accept the request only if we don't exceed the destination
  1542.      * port HIWATER_MARK *AND* the max. link GBR arbitration count
  1543.      */
  1544.     if (((old_bw_BYTES + req_bw_BYTES) <=
  1545. soft->bw_hiwm[(int) dest_wid - MAX_XBOW_PORTS]) &&
  1546. (req_bw_GBR + old_bw_GBR <= XBOW_ARB_GBR_MAX)) {
  1547. new_bw_GBR = (old_bw_GBR + req_bw_GBR);
  1548. /* Set this in the xbow link register */
  1549. *xreg = (old_xreg & ~mask) | 
  1550.     (new_bw_GBR << XB_ARB_GBR_SHFT(src_wid) & mask);
  1551. soft->bw_cur_used[(int) dest_wid - MAX_XBOW_PORTS] =
  1552. xbow_gbr_to_bytes(new_bw_GBR);
  1553.     } else {
  1554. error = 1;
  1555.     }
  1556.     mutex_spinunlock(&soft->xbow_bw_alloc_lock, s);
  1557.     return (error);
  1558. }