xbow.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:36k
源码类别:

Linux/Unix编程

开发平台:

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-2001 Silicon Graphics, Inc. All rights reserved.
  8.  */
  9. #include <linux/types.h>
  10. #include <linux/slab.h>
  11. #include <linux/sched.h>
  12. #include <asm/sn/sgi.h>
  13. #include <asm/sn/iograph.h>
  14. #include <asm/sn/invent.h>
  15. #include <asm/sn/hcl.h>
  16. #include <asm/sn/labelcl.h>
  17. #include <asm/sn/hack.h>
  18. #include <asm/sn/pci/bridge.h>
  19. #include <asm/sn/xtalk/xtalk_private.h>
  20. #include <asm/sn/simulator.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. #endif
  85. void                    xbow_intr_preset(void *, int, xwidgetnum_t, iopaddr_t, xtalk_intr_vector_t);
  86. void                    xbow_update_perf_counters(devfs_handle_t);
  87. xbow_perf_link_t       *xbow_get_perf_counters(devfs_handle_t);
  88. int                     xbow_enable_perf_counter(devfs_handle_t, int, int, int);
  89. xbow_link_status_t     *xbow_get_llp_status(devfs_handle_t);
  90. void                    xbow_update_llp_status(devfs_handle_t);
  91. int                     xbow_disable_llp_monitor(devfs_handle_t);
  92. int                     xbow_enable_llp_monitor(devfs_handle_t);
  93. int                     xbow_prio_bw_alloc(devfs_handle_t, xwidgetnum_t, xwidgetnum_t,
  94.                                 unsigned long long, unsigned long long);
  95. xswitch_reset_link_f    xbow_reset_link;
  96. void                    idbg_xbowregs(int64_t);
  97. xswitch_provider_t      xbow_provider =
  98. {
  99.     xbow_reset_link,
  100. };
  101. /*
  102.  *    xbow_mlreset: called at mlreset time if the
  103.  *      platform specific code determines that there is
  104.  *      a crossbow in a critical path that must be
  105.  *      functional before the driver would normally get
  106.  *      the device properly set up.
  107.  *
  108.  *      what do we need to do, that the boot prom can
  109.  *      not be counted on to have already done, that is
  110.  *      generic across all platforms using crossbows?
  111.  */
  112. /*ARGSUSED */
  113. void
  114. xbow_mlreset(xbow_t * xbow)
  115. {
  116. }
  117. /*
  118.  *    xbow_init: called with the rest of the device
  119.  *      driver XXX_init routines. This platform *might*
  120.  *      have a Crossbow chip, or even several, but it
  121.  *      might have none. Register with the crosstalk
  122.  *      generic provider so when we encounter the chip
  123.  *      the right magic happens.
  124.  */
  125. void
  126. xbow_init(void)
  127. {
  128. #if DEBUG && ATTACH_DEBUG
  129.     printf("xbow_initn");
  130. #endif
  131.     xwidget_driver_register(XXBOW_WIDGET_PART_NUM,
  132.     0, /* XXBOW_WIDGET_MFGR_NUM, */
  133.     "xbow_",
  134.     CDL_PRI_HI); /* attach before friends */
  135.     xwidget_driver_register(XBOW_WIDGET_PART_NUM,
  136.     XBOW_WIDGET_MFGR_NUM,
  137.     "xbow_",
  138.     CDL_PRI_HI); /* attach before friends */
  139. }
  140. #ifdef XBRIDGE_REGS_SIM
  141. /*    xbow_set_simulated_regs: sets xbow regs as needed
  142.  * for powering through the boot
  143.  */
  144. void
  145. xbow_set_simulated_regs(xbow_t *xbow, int port)
  146. {
  147.     /*
  148.      * turn on link
  149.      */
  150.     xbow->xb_link(port).link_status = (1<<31);
  151.     /*
  152.      * and give it a live widget too
  153.      */
  154.     xbow->xb_link(port).link_aux_status = XB_AUX_STAT_PRESENT;
  155.     /*
  156.      * zero the link control reg
  157.      */
  158.     xbow->xb_link(port).link_control = 0x0;
  159. }
  160. #endif /* XBRIDGE_REGS_SIM */
  161. /*
  162.  *    xbow_attach: the crosstalk provider has
  163.  *      determined that there is a crossbow widget
  164.  *      present, and has handed us the connection
  165.  *      point for that vertex.
  166.  *
  167.  *      We not only add our own vertex, but add
  168.  *      some "xtalk switch" data to the switch
  169.  *      vertex (at the connect point's parent) if
  170.  *      it does not have any.
  171.  */
  172. /*ARGSUSED */
  173. int
  174. xbow_attach(devfs_handle_t conn)
  175. {
  176.     /*REFERENCED */
  177.     devfs_handle_t            vhdl;
  178.     devfs_handle_t            busv;
  179.     xbow_t                 *xbow;
  180.     xbow_soft_t             soft;
  181.     int                     port;
  182.     xswitch_info_t          info;
  183. #ifdef LATER
  184.     xtalk_intr_t            intr_hdl;
  185.     device_desc_t           dev_desc;
  186. #endif
  187.     char                    devnm[MAXDEVNAME], *s;
  188.     xbowreg_t               id;
  189.     int                     rev;
  190.     int     i;
  191.     int     xbow_num;
  192. #if DEBUG && ATTACH_DEBUG
  193. #if defined(SUPPORT_PRINTING_V_FORMAT
  194.     printk("%v: xbow_attachn", conn);
  195. #else
  196.     printk("0x%x: xbow_attachn", conn);
  197. #endif
  198. #endif
  199.     /*
  200.      * Get a PIO pointer to the base of the crossbow
  201.      * chip.
  202.      */
  203. #ifdef XBRIDGE_REGS_SIM
  204.     printk("xbow_attach: XBRIDGE_REGS_SIM FIXME: allocating %ld bytes for xbow_sn", sizeof(xbow_t));
  205.     xbow = (xbow_t *) kmalloc(sizeof(xbow_t), GFP_KERNEL);
  206.     /*
  207.      * turn on ports e and f like in a real live ibrick
  208.      */
  209.     xbow_set_simulated_regs(xbow, 0xe);
  210.     xbow_set_simulated_regs(xbow, 0xf);
  211. #else
  212.     xbow = (xbow_t *) xtalk_piotrans_addr(conn, 0, 0, sizeof(xbow_t), 0);
  213. #endif /* XBRIDGE_REGS_SIM */
  214.     /*
  215.      * Locate the "switch" vertex: it is the parent
  216.      * of our connection point.
  217.      */
  218.     busv = hwgraph_connectpt_get(conn);
  219. #if DEBUG && ATTACH_DEBUG
  220.     printk("xbow_attach: Bus Vertex 0x%p, conn 0x%p, xbow register 0x%p wid= 0x%xn", busv, conn, xbow, *(volatile u32 *)xbow);
  221. #endif
  222.     ASSERT(busv != GRAPH_VERTEX_NONE);
  223.     /*
  224.      * Create our private vertex, and connect our
  225.      * driver information to it. This makes it possible
  226.      * for diagnostic drivers to open the crossbow
  227.      * vertex for access to registers.
  228.      */
  229.     /*
  230.      * We need to teach xbow drivers to provide the right set of
  231.      * file ops.
  232.      */
  233.     vhdl = NULL;
  234.     vhdl = hwgraph_register(conn, EDGE_LBL_XBOW,
  235.                         0, DEVFS_FL_AUTO_DEVNUM,
  236.                         0, 0,
  237.                         S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, 0, 0,
  238.                         /* &hcl_fops */ (void *)&vhdl, NULL);
  239.     if (!vhdl) {
  240.         printk(KERN_WARNING "xbow_attach: Unable to create char device for xbow conn %pn",
  241.                 (void *)conn);
  242.     }
  243.     /*
  244.      * Allocate the soft state structure and attach
  245.      * it to the xbow's vertex
  246.      */
  247.     NEW(soft);
  248.     soft->conn = conn;
  249.     soft->vhdl = vhdl;
  250.     soft->busv = busv;
  251.     soft->base = xbow;
  252.     /* does the universe really need another macro?  */
  253.     /* xbow_soft_set(vhdl, (arbitrary_info_t) soft); */
  254.     hwgraph_fastinfo_set(vhdl, (arbitrary_info_t) soft);
  255. #define XBOW_NUM_SUFFIX_FORMAT "[xbow# %d]"
  256.     /* Add xbow number as a suffix to the hwgraph name of the xbow.
  257.      * This is helpful while looking at the error/warning messages.
  258.      */
  259.     xbow_num = 0;
  260.     /*
  261.      * get the name of this xbow vertex and keep the info.
  262.      * This is needed during errors and interupts, but as
  263.      * long as we have it, we can use it elsewhere.
  264.      */
  265.     s = dev_to_name(vhdl, devnm, MAXDEVNAME);
  266.     soft->name = kmalloc(strlen(s) + strlen(XBOW_NUM_SUFFIX_FORMAT) + 1, 
  267.     GFP_KERNEL);
  268.     sprintf(soft->name,"%s"XBOW_NUM_SUFFIX_FORMAT, s,xbow_num);
  269. #ifdef XBRIDGE_REGS_SIM
  270.     /* my o200/ibrick has id=0x2d002049, but XXBOW_WIDGET_PART_NUM is defined
  271.      * as 0xd000, so I'm using that for the partnum bitfield.
  272.      */
  273.     printk("xbow_attach: XBRIDGE_REGS_SIM FIXME: need xb_wid_id value!!n");
  274.     id = 0x2d000049;
  275. #else
  276.     id = xbow->xb_wid_id;
  277. #endif /* XBRIDGE_REGS_SIM */
  278.     rev = XWIDGET_PART_REV_NUM(id);
  279.     /*
  280.      * Print the revision if DEBUG, or SHOW_REVS and kdebug,
  281.      * or the xbow is downrev.
  282.      *
  283.      * If xbow is downrev, make it a WARNING that the
  284.      * Crossbow is DOWNREV: these chips are not good
  285.      * to have around, and the operator should be told.
  286.      */
  287. #ifdef LATER
  288. #if !DEBUG
  289.     if (
  290. #if SHOW_REVS
  291.    (kdebug) ||
  292. #endif /* SHOW_REVS */
  293.    (rev < XBOW_REV_1_1))
  294. #endif /* !DEBUG  */
  295. printk("%sCrossbow ASIC: rev %s (code=%d) at %s%s",
  296. (rev < XBOW_REV_1_1) ? "DOWNREV " : "",
  297. (rev == XBOW_REV_1_0) ? "1.0" :
  298. (rev == XBOW_REV_1_1) ? "1.1" :
  299. (rev == XBOW_REV_1_2) ? "1.2" :
  300. (rev == XBOW_REV_1_3) ? "1.3" :
  301. (rev == XBOW_REV_2_0) ? "2.0" :
  302. (rev == XXBOW_PART_REV_1_0) ? "Xbridge 1.0" :
  303. (rev == XXBOW_PART_REV_2_0) ? "Xbridge 2.0" :
  304. "unknown",
  305. rev, soft->name,
  306. (rev < XBOW_REV_1_1) ? "" : "n");
  307. #endif /* LATER */
  308.     mutex_spinlock_init(&soft->xbow_perf_lock);
  309.     soft->xbow_perfcnt[0].xp_perf_reg = &xbow->xb_perf_ctr_a;
  310.     soft->xbow_perfcnt[1].xp_perf_reg = &xbow->xb_perf_ctr_b;
  311.     /* Initialization for GBR bw allocation */
  312.     mutex_spinlock_init(&soft->xbow_bw_alloc_lock);
  313. #define XBOW_8_BIT_PORT_BW_MAX (400 * 1000 * 1000) /* 400 MB/s */
  314. #define XBOW_16_BIT_PORT_BW_MAX (800 * 1000 * 1000) /* 800 MB/s */
  315.     /* Set bandwidth hiwatermark and current values */
  316.     for (i = 0; i < MAX_XBOW_PORTS; i++) {
  317. soft->bw_hiwm[i] = XBOW_16_BIT_PORT_BW_MAX; /* for now */
  318. soft->bw_cur_used[i] = 0;
  319.     }
  320.     /*
  321.      * Enable xbow error interrupts
  322.      */
  323.     xbow->xb_wid_control = (XB_WID_CTRL_REG_ACC_IE | XB_WID_CTRL_XTALK_IE);
  324.     /*
  325.      * take a census of the widgets present,
  326.      * leaving notes at the switch vertex.
  327.      */
  328.     info = xswitch_info_new(busv);
  329.     for (port = MAX_PORT_NUM - MAX_XBOW_PORTS;
  330.  port < MAX_PORT_NUM; ++port) {
  331. if (!xbow_link_alive(xbow, port)) {
  332. #if DEBUG && XBOW_DEBUG
  333.     printk(KERN_INFO "0x%p link %d is not aliven",
  334.     busv, port);
  335. #endif
  336.     continue;
  337. }
  338. if (!xbow_widget_present(xbow, port)) {
  339. #if DEBUG && XBOW_DEBUG
  340.     printk(KERN_INFO "0x%p link %d is alive but no widget is presentn", busv, port);
  341. #endif
  342.     continue;
  343. }
  344. #if DEBUG && XBOW_DEBUG
  345. printk(KERN_INFO "0x%p link %d has a widgetn",
  346. busv, port);
  347. #endif
  348. xswitch_info_link_is_ok(info, port);
  349. /*
  350.  * Turn some error interrupts on
  351.  * and turn others off. The PROM has
  352.  * some things turned on we don't
  353.  * want to see (bandwidth allocation
  354.  * errors for instance); so if it
  355.  * is not listed here, it is not on.
  356.  */
  357. xbow->xb_link(port).link_control =
  358.     ( (xbow->xb_link(port).link_control
  359. /*
  360.  * Turn off these bits; they are non-fatal,
  361.  * but we might want to save some statistics
  362.  * on the frequency of these errors.
  363.  * XXX FIXME XXX
  364.  */
  365.     & ~XB_CTRL_RCV_CNT_OFLOW_IE
  366.     & ~XB_CTRL_XMT_CNT_OFLOW_IE
  367.     & ~XB_CTRL_BNDWDTH_ALLOC_IE
  368.     & ~XB_CTRL_RCV_IE)
  369. /*
  370.  * These are the ones we want to turn on.
  371.  */
  372.     | (XB_CTRL_ILLEGAL_DST_IE
  373.     | XB_CTRL_OALLOC_IBUF_IE
  374.     | XB_CTRL_XMT_MAX_RTRY_IE
  375.     | XB_CTRL_MAXREQ_TOUT_IE
  376.     | XB_CTRL_XMT_RTRY_IE
  377.     | XB_CTRL_SRC_TOUT_IE) );
  378.     }
  379.     xswitch_provider_register(busv, &xbow_provider);
  380.     return 0; /* attach successful */
  381. }
  382. /*ARGSUSED */
  383. int
  384. xbow_open(devfs_handle_t *devp, int oflag, int otyp, cred_t *credp)
  385. {
  386.     return 0;
  387. }
  388. /*ARGSUSED */
  389. int
  390. xbow_close(devfs_handle_t dev, int oflag, int otyp, cred_t *crp)
  391. {
  392.     return 0;
  393. }
  394. /*ARGSUSED */
  395. int
  396. xbow_map(devfs_handle_t dev, vhandl_t *vt, off_t off, size_t len, uint prot)
  397. {
  398.     devfs_handle_t            vhdl = dev_to_vhdl(dev);
  399.     xbow_soft_t             soft = xbow_soft_get(vhdl);
  400.     int                     error;
  401.     ASSERT(soft);
  402.     len = ctob(btoc(len));
  403.     /* XXX- this ignores the offset!!! */
  404.     error = v_mapphys(vt, (void *) soft->base, len);
  405.     return error;
  406. }
  407. /*ARGSUSED */
  408. int
  409. xbow_unmap(devfs_handle_t dev, vhandl_t *vt)
  410. {
  411.     return 0;
  412. }
  413. /* This contains special-case code for grio. There are plans to make
  414.  * this general sometime in the future, but till then this should
  415.  * be good enough.
  416.  */
  417. xwidgetnum_t
  418. xbow_widget_num_get(devfs_handle_t dev)
  419. {
  420. devfs_handle_t tdev;
  421. char devname[MAXDEVNAME];
  422. xwidget_info_t xwidget_info;
  423. int i;
  424. vertex_to_name(dev, devname, MAXDEVNAME);
  425. /* If this is a pci controller vertex, traverse up using
  426.  * the ".." links to get to the widget.
  427.  */
  428. if (strstr(devname, EDGE_LBL_PCI) &&
  429. strstr(devname, EDGE_LBL_CONTROLLER)) {
  430. tdev = dev;
  431. for (i=0; i< 2; i++) {
  432. if (hwgraph_edge_get(tdev,
  433. HWGRAPH_EDGELBL_DOTDOT, &tdev) !=
  434. GRAPH_SUCCESS)
  435. return XWIDGET_NONE;
  436. }
  437. if ((xwidget_info = xwidget_info_chk(tdev)) != NULL) {
  438. return (xwidget_info_id_get(xwidget_info));
  439. } else {
  440. return XWIDGET_NONE;
  441. }
  442. }
  443. return XWIDGET_NONE;
  444. }
  445. int
  446. xbow_ioctl(devfs_handle_t dev,
  447.    int cmd,
  448.    void *arg,
  449.    int flag,
  450.    struct cred *cr,
  451.    int *rvalp)
  452. {
  453.     devfs_handle_t            vhdl;
  454.     int                     error = 0;
  455. #if defined (DEBUG)
  456.     int                     rc;
  457.     devfs_handle_t            conn;
  458.     struct xwidget_info_s  *xwidget_info;
  459.     xbow_soft_t             xbow_soft;
  460. #endif
  461.     *rvalp = 0;
  462.     vhdl = dev_to_vhdl(dev);
  463. #if defined (DEBUG)
  464.     xbow_soft = xbow_soft_get(vhdl);
  465.     conn = xbow_soft->conn;
  466.     xwidget_info = xwidget_info_get(conn);
  467.     ASSERT_ALWAYS(xwidget_info != NULL);
  468.     rc = xwidget_hwid_is_xswitch(&xwidget_info->w_hwid);
  469.     ASSERT_ALWAYS(rc != 0);
  470. #endif
  471.     switch (cmd) {
  472. #ifdef LATER
  473.     case XBOWIOC_PERF_ENABLE:
  474.     case XBOWIOC_PERF_DISABLE:
  475. {
  476.     struct xbow_perfarg_t   xbow_perf_en;
  477.     if (!_CAP_CRABLE(cr, CAP_DEVICE_MGT)) {
  478. error = EPERM;
  479. break;
  480.     }
  481.     if ((flag & FWRITE) == 0) {
  482. error = EBADF;
  483. break;
  484.     }
  485.     if (COPYIN(arg, &xbow_perf_en, sizeof(xbow_perf_en))) {
  486. error = EFAULT;
  487. break;
  488.     }
  489.     if (error = xbow_enable_perf_counter(vhdl,
  490.  xbow_perf_en.link,
  491.  (cmd == XBOWIOC_PERF_DISABLE) ? 0 : xbow_perf_en.mode,
  492.  xbow_perf_en.counter)) {
  493. error = EINVAL;
  494. break;
  495.     }
  496.     break;
  497. }
  498. #endif
  499. #ifdef LATER
  500.     case XBOWIOC_PERF_GET:
  501. {
  502.     xbow_perf_link_t       *xbow_perf_cnt;
  503.     if ((flag & FREAD) == 0) {
  504. error = EBADF;
  505. break;
  506.     }
  507.     xbow_perf_cnt = xbow_get_perf_counters(vhdl);
  508.     ASSERT_ALWAYS(xbow_perf_cnt != NULL);
  509.     if (COPYOUT((void *) xbow_perf_cnt, (void *) arg,
  510. MAX_XBOW_PORTS * sizeof(xbow_perf_link_t))) {
  511. error = EFAULT;
  512. break;
  513.     }
  514.     break;
  515. }
  516. #endif
  517.     case XBOWIOC_LLP_ERROR_ENABLE:
  518. if ((error = xbow_enable_llp_monitor(vhdl)) != 0)
  519.     error = EINVAL;
  520. break;
  521.     case XBOWIOC_LLP_ERROR_DISABLE:
  522. if ((error = xbow_disable_llp_monitor(vhdl)) != 0)
  523.     error = EINVAL;
  524. break;
  525. #ifdef LATER
  526.     case XBOWIOC_LLP_ERROR_GET:
  527. {
  528.     xbow_link_status_t     *xbow_llp_status;
  529.     if ((flag & FREAD) == 0) {
  530. error = EBADF;
  531. break;
  532.     }
  533.     xbow_llp_status = xbow_get_llp_status(vhdl);
  534.     ASSERT_ALWAYS(xbow_llp_status != NULL);
  535.     if (COPYOUT((void *) xbow_llp_status, (void *) arg,
  536. MAX_XBOW_PORTS * sizeof(xbow_link_status_t))) {
  537. error = EFAULT;
  538. break;
  539.     }
  540.     break;
  541. }
  542. #endif
  543. #ifdef LATER
  544.     case GIOCSETBW:
  545. {
  546.     grio_ioctl_info_t info;
  547.     xwidgetnum_t src_widgetnum, dest_widgetnum;
  548.     if (COPYIN(arg, &info, sizeof(grio_ioctl_info_t))) {
  549. error = EFAULT;
  550. break;
  551.     }
  552. #ifdef GRIO_DEBUG
  553.     printf("xbow:: prev_vhdl: %d next_vhdl: %d reqbw: %lldn",
  554. info.prev_vhdl, info.next_vhdl, info.reqbw);
  555. #endif /* GRIO_DEBUG */
  556.     src_widgetnum = xbow_widget_num_get(info.prev_vhdl);
  557.     dest_widgetnum = xbow_widget_num_get(info.next_vhdl);
  558.     /* Bandwidth allocation is bi-directional. Since bandwidth
  559.      * reservations have already been done at an earlier stage,
  560.      * we cannot fail here for lack of bandwidth.
  561.      */
  562.     xbow_prio_bw_alloc(dev, src_widgetnum, dest_widgetnum,
  563. 0, info.reqbw);
  564.     xbow_prio_bw_alloc(dev, dest_widgetnum, src_widgetnum,
  565. 0, info.reqbw);
  566.     break;
  567. }
  568.     case GIOCRELEASEBW:
  569. {
  570.     grio_ioctl_info_t info;
  571.     xwidgetnum_t src_widgetnum, dest_widgetnum;
  572.     if (!cap_able(CAP_DEVICE_MGT)) {
  573. error = EPERM;
  574. break;
  575.     }
  576.     if (COPYIN(arg, &info, sizeof(grio_ioctl_info_t))) {
  577. error = EFAULT;
  578. break;
  579.     }
  580. #ifdef GRIO_DEBUG
  581.     printf("xbow:: prev_vhdl: %d next_vhdl: %d reqbw: %lldn",
  582. info.prev_vhdl, info.next_vhdl, info.reqbw);
  583. #endif /* GRIO_DEBUG */
  584.     src_widgetnum = xbow_widget_num_get(info.prev_vhdl);
  585.     dest_widgetnum = xbow_widget_num_get(info.next_vhdl);
  586.     /* Bandwidth reservation is bi-directional. Hence, remove
  587.      * bandwidth reservations for both directions.
  588.      */
  589.     xbow_prio_bw_alloc(dev, src_widgetnum, dest_widgetnum,
  590. info.reqbw, (-1 * info.reqbw));
  591.     xbow_prio_bw_alloc(dev, dest_widgetnum, src_widgetnum,
  592. info.reqbw, (-1 * info.reqbw));
  593.     break;
  594. }
  595. #endif
  596.     default:
  597. break;
  598.     }
  599.     return error;
  600. }
  601. /*
  602.  * xbow_widget_present: See if a device is present
  603.  * on the specified port of this crossbow.
  604.  */
  605. int
  606. xbow_widget_present(xbow_t * xbow, int port)
  607. {
  608. if ( IS_RUNNING_ON_SIMULATOR() ) {
  609. if ( (port == 14) || (port == 15) ) {
  610. return 1;
  611. }
  612. else {
  613. return 0;
  614. }
  615. }
  616. else {
  617. return xbow->xb_link(port).link_aux_status & XB_AUX_STAT_PRESENT;
  618. }
  619. }
  620. static int
  621. xbow_link_alive(xbow_t * xbow, int port)
  622. {
  623.     xbwX_stat_t             xbow_linkstat;
  624.     xbow_linkstat.linkstatus = xbow->xb_link(port).link_status;
  625.     return (xbow_linkstat.link_alive);
  626. }
  627. /*
  628.  * xbow_widget_lookup
  629.  *      Lookup the edges connected to the xbow specified, and
  630.  *      retrieve the handle corresponding to the widgetnum
  631.  *      specified.
  632.  *      If not found, return 0.
  633.  */
  634. devfs_handle_t
  635. xbow_widget_lookup(devfs_handle_t vhdl,
  636.    int widgetnum)
  637. {
  638.     xswitch_info_t          xswitch_info;
  639.     devfs_handle_t            conn;
  640.     xswitch_info = xswitch_info_get(vhdl);
  641.     conn = xswitch_info_vhdl_get(xswitch_info, widgetnum);
  642.     return conn;
  643. }
  644. /*
  645.  * xbow_setwidint: called when xtalk
  646.  * is establishing or migrating our
  647.  * interrupt service.
  648.  */
  649. #ifdef LATER
  650. static void
  651. xbow_setwidint(xtalk_intr_t intr)
  652. {
  653.     xwidgetnum_t            targ = xtalk_intr_target_get(intr);
  654.     iopaddr_t               addr = xtalk_intr_addr_get(intr);
  655.     xtalk_intr_vector_t     vect = xtalk_intr_vector_get(intr);
  656.     xbow_t                 *xbow = (xbow_t *) xtalk_intr_sfarg_get(intr);
  657.     xbow_intr_preset((void *) xbow, 0, targ, addr, vect);
  658. }
  659. #endif /* LATER */
  660. /*
  661.  * xbow_intr_preset: called during mlreset time
  662.  * if the platform specific code needs to route
  663.  * an xbow interrupt before the xtalk infrastructure
  664.  * is available for use.
  665.  *
  666.  * Also called from xbow_setwidint, so we don't
  667.  * replicate the guts of the routine.
  668.  *
  669.  * XXX- probably should be renamed xbow_wid_intr_set or
  670.  * something to reduce confusion.
  671.  */
  672. /*ARGSUSED3 */
  673. void
  674. xbow_intr_preset(void *which_widget,
  675.  int which_widget_intr,
  676.  xwidgetnum_t targ,
  677.  iopaddr_t addr,
  678.  xtalk_intr_vector_t vect)
  679. {
  680.     xbow_t                 *xbow = (xbow_t *) which_widget;
  681.     xbow->xb_wid_int_upper = ((0xFF000000 & (vect << 24)) |
  682.       (0x000F0000 & (targ << 16)) |
  683.       XTALK_ADDR_TO_UPPER(addr));
  684.     xbow->xb_wid_int_lower = XTALK_ADDR_TO_LOWER(addr);
  685. }
  686. #define XEM_ADD_STR(s) printk("%s", (s))
  687. #define XEM_ADD_NVAR(n,v) printk("t%20s: 0x%xn", (n), (v))
  688. #define XEM_ADD_VAR(v) XEM_ADD_NVAR(#v,(v))
  689. #define XEM_ADD_IOEF(n)  if (IOERROR_FIELDVALID(ioe,n))     
  690.     XEM_ADD_NVAR("ioe." #n,     
  691.  IOERROR_GETVALUE(ioe,n))
  692. #ifdef LATER
  693. static void
  694. xem_add_ioe(ioerror_t *ioe)
  695. {
  696.     XEM_ADD_IOEF(errortype);
  697.     XEM_ADD_IOEF(widgetnum);
  698.     XEM_ADD_IOEF(widgetdev);
  699.     XEM_ADD_IOEF(srccpu);
  700.     XEM_ADD_IOEF(srcnode);
  701.     XEM_ADD_IOEF(errnode);
  702.     XEM_ADD_IOEF(sysioaddr);
  703.     XEM_ADD_IOEF(xtalkaddr);
  704.     XEM_ADD_IOEF(busspace);
  705.     XEM_ADD_IOEF(busaddr);
  706.     XEM_ADD_IOEF(vaddr);
  707.     XEM_ADD_IOEF(memaddr);
  708.     XEM_ADD_IOEF(epc);
  709.     XEM_ADD_IOEF(ef);
  710. }
  711. #define XEM_ADD_IOE() (xem_add_ioe(ioe))
  712. #endif /* LATER */
  713. int                     xbow_xmit_retry_errors = 0;
  714. int
  715. xbow_xmit_retry_error(xbow_soft_t soft,
  716.       int port)
  717. {
  718.     xswitch_info_t          info;
  719.     devfs_handle_t            vhdl;
  720.     widget_cfg_t           *wid;
  721.     widgetreg_t             id;
  722.     int                     part;
  723.     int                     mfgr;
  724.     wid = soft->wpio[port - BASE_XBOW_PORT];
  725.     if (wid == NULL) {
  726. /* If we can't track down a PIO
  727.  * pointer to our widget yet,
  728.  * leave our caller knowing that
  729.  * we are interested in this
  730.  * interrupt if it occurs in
  731.  * the future.
  732.  */
  733. info = xswitch_info_get(soft->busv);
  734. if (!info)
  735.     return 1;
  736. vhdl = xswitch_info_vhdl_get(info, port);
  737. if (vhdl == GRAPH_VERTEX_NONE)
  738.     return 1;
  739. wid = (widget_cfg_t *) xtalk_piotrans_addr
  740.     (vhdl, 0, 0, sizeof *wid, 0);
  741. if (!wid)
  742.     return 1;
  743. soft->wpio[port - BASE_XBOW_PORT] = wid;
  744.     }
  745.     id = wid->w_id;
  746.     part = XWIDGET_PART_NUM(id);
  747.     mfgr = XWIDGET_MFG_NUM(id);
  748.     /* If this thing is not a Bridge,
  749.      * do not activate the WAR, and
  750.      * tell our caller we do not need
  751.      * to be called again.
  752.      */
  753.     if ((part != BRIDGE_WIDGET_PART_NUM) ||
  754. (mfgr != BRIDGE_WIDGET_MFGR_NUM)) {
  755. /* FIXME: add Xbridge to the WAR.
  756.  * Shouldn't hurt anything.  Later need to
  757.  * check if we can remove this.
  758.                  */
  759.      if ((part != XBRIDGE_WIDGET_PART_NUM) ||
  760.     (mfgr != XBRIDGE_WIDGET_MFGR_NUM))
  761. return 0;
  762.     }
  763.     /* count how many times we
  764.      * have picked up after
  765.      * LLP Transmit problems.
  766.      */
  767.     xbow_xmit_retry_errors++;
  768.     /* rewrite the control register
  769.      * to fix things up.
  770.      */
  771.     wid->w_control = wid->w_control;
  772.     wid->w_control;
  773.     return 1;
  774. }
  775. void
  776. xbow_update_perf_counters(devfs_handle_t vhdl)
  777. {
  778.     xbow_soft_t             xbow_soft = xbow_soft_get(vhdl);
  779.     xbow_perf_t            *xbow_perf = xbow_soft->xbow_perfcnt;
  780.     xbow_perf_link_t       *xbow_plink = xbow_soft->xbow_perflink;
  781.     xbow_perfcount_t        perf_reg;
  782.     unsigned long           s;
  783.     int                     link, i;
  784.     for (i = 0; i < XBOW_PERF_COUNTERS; i++, xbow_perf++) {
  785. if (xbow_perf->xp_mode == XBOW_MONITOR_NONE)
  786.     continue;
  787. s = mutex_spinlock(&xbow_soft->xbow_perf_lock);
  788. perf_reg.xb_counter_val = *(xbowreg_t *) xbow_perf->xp_perf_reg;
  789. link = perf_reg.xb_perf.link_select;
  790. (xbow_plink + link)->xlp_cumulative[xbow_perf->xp_curmode] +=
  791.     ((perf_reg.xb_perf.count - xbow_perf->xp_current) & XBOW_COUNTER_MASK);
  792. xbow_perf->xp_current = perf_reg.xb_perf.count;
  793. mutex_spinunlock(&xbow_soft->xbow_perf_lock, s);
  794.     }
  795.     /* Do port /mode multiplexing here */
  796. #ifdef LATER
  797.     (void) timeout(xbow_update_perf_counters,
  798.    (void *) (__psunsigned_t) vhdl, XBOW_PERF_TIMEOUT);
  799. #endif
  800. }
  801. xbow_perf_link_t       *
  802. xbow_get_perf_counters(devfs_handle_t vhdl)
  803. {
  804.     xbow_soft_t             xbow_soft = xbow_soft_get(vhdl);
  805.     xbow_perf_link_t       *xbow_perf_link = xbow_soft->xbow_perflink;
  806.     return xbow_perf_link;
  807. }
  808. int
  809. xbow_enable_perf_counter(devfs_handle_t vhdl, int link, int mode, int counter)
  810. {
  811.     xbow_soft_t             xbow_soft = xbow_soft_get(vhdl);
  812.     xbow_perf_t            *xbow_perf = xbow_soft->xbow_perfcnt;
  813.     xbow_linkctrl_t         xbow_link_ctrl;
  814.     xbow_t                 *xbow = xbow_soft->base;
  815.     xbow_perfcount_t        perf_reg;
  816.     unsigned long           s;
  817.     int                     i;
  818.     link -= BASE_XBOW_PORT;
  819.     if ((link < 0) || (link >= MAX_XBOW_PORTS))
  820. return -1;
  821.     if ((mode < XBOW_MONITOR_NONE) || (mode > XBOW_MONITOR_DEST_LINK))
  822. return -1;
  823.     if ((counter < 0) || (counter >= XBOW_PERF_COUNTERS))
  824. return -1;
  825.     s = mutex_spinlock(&xbow_soft->xbow_perf_lock);
  826.     if ((xbow_perf + counter)->xp_mode && mode) {
  827. mutex_spinunlock(&xbow_soft->xbow_perf_lock, s);
  828. return -1;
  829.     }
  830.     for (i = 0; i < XBOW_PERF_COUNTERS; i++) {
  831. if (i == counter)
  832.     continue;
  833. if (((xbow_perf + i)->xp_link == link) &&
  834.     ((xbow_perf + i)->xp_mode)) {
  835.     mutex_spinunlock(&xbow_soft->xbow_perf_lock, s);
  836.     return -1;
  837. }
  838.     }
  839.     xbow_perf += counter;
  840.     xbow_perf->xp_curlink = xbow_perf->xp_link = link;
  841.     xbow_perf->xp_curmode = xbow_perf->xp_mode = mode;
  842.     xbow_link_ctrl.xbl_ctrlword = xbow->xb_link_raw[link].link_control;
  843.     xbow_link_ctrl.xb_linkcontrol.perf_mode = mode;
  844.     xbow->xb_link_raw[link].link_control = xbow_link_ctrl.xbl_ctrlword;
  845.     perf_reg.xb_counter_val = *(xbowreg_t *) xbow_perf->xp_perf_reg;
  846.     perf_reg.xb_perf.link_select = link;
  847.     *(xbowreg_t *) xbow_perf->xp_perf_reg = perf_reg.xb_counter_val;
  848.     xbow_perf->xp_current = perf_reg.xb_perf.count;
  849. #ifdef LATER
  850.     (void) timeout(xbow_update_perf_counters,
  851.    (void *) (__psunsigned_t) vhdl, XBOW_PERF_TIMEOUT);
  852. #endif
  853.     mutex_spinunlock(&xbow_soft->xbow_perf_lock, s);
  854.     return 0;
  855. }
  856. xbow_link_status_t     *
  857. xbow_get_llp_status(devfs_handle_t vhdl)
  858. {
  859.     xbow_soft_t             xbow_soft = xbow_soft_get(vhdl);
  860.     xbow_link_status_t     *xbow_llp_status = xbow_soft->xbow_link_status;
  861.     return xbow_llp_status;
  862. }
  863. void
  864. xbow_update_llp_status(devfs_handle_t vhdl)
  865. {
  866.     xbow_soft_t             xbow_soft = xbow_soft_get(vhdl);
  867.     xbow_link_status_t     *xbow_llp_status = xbow_soft->xbow_link_status;
  868.     xbow_t                 *xbow;
  869.     xbwX_stat_t             lnk_sts;
  870.     xbow_aux_link_status_t  aux_sts;
  871.     int                     link;
  872.     devfs_handle_t     xwidget_vhdl;
  873.     char    *xwidget_name;
  874.     xbow = (xbow_t *) xbow_soft->base;
  875.     for (link = 0; link < MAX_XBOW_PORTS; link++, xbow_llp_status++) {
  876. /* Get the widget name corresponding the current link.
  877.  * Note : 0 <= link < MAX_XBOW_PORTS(8).
  878.  *    BASE_XBOW_PORT(0x8) <= xwidget number < MAX_PORT_NUM (0x10)
  879.  */
  880. xwidget_vhdl = xbow_widget_lookup(xbow_soft->busv,link+BASE_XBOW_PORT);
  881. xwidget_name = xwidget_name_get(xwidget_vhdl);
  882. aux_sts.aux_linkstatus
  883.     = xbow->xb_link_raw[link].link_aux_status;
  884. lnk_sts.linkstatus = xbow->xb_link_raw[link].link_status_clr;
  885. if (lnk_sts.link_alive == 0)
  886.     continue;
  887. xbow_llp_status->rx_err_count +=
  888.     aux_sts.xb_aux_linkstatus.rx_err_cnt;
  889. xbow_llp_status->tx_retry_count +=
  890.     aux_sts.xb_aux_linkstatus.tx_retry_cnt;
  891. if (lnk_sts.linkstatus & ~(XB_STAT_RCV_ERR | XB_STAT_XMT_RTRY_ERR | XB_STAT_LINKALIVE)) {
  892. #ifdef LATER
  893.     printk(KERN_WARNING  "link %d[%s]: bad status 0x%xn",
  894.     link, xwidget_name, lnk_sts.linkstatus);
  895. #endif
  896. }
  897.     }
  898. #ifdef LATER
  899.     if (xbow_soft->link_monitor)
  900. (void) timeout(xbow_update_llp_status,
  901.        (void *) (__psunsigned_t) vhdl, XBOW_STATS_TIMEOUT);
  902. #endif
  903. }
  904. int
  905. xbow_disable_llp_monitor(devfs_handle_t vhdl)
  906. {
  907.     xbow_soft_t             xbow_soft = xbow_soft_get(vhdl);
  908.     int                     port;
  909.     for (port = 0; port < MAX_XBOW_PORTS; port++) {
  910. xbow_soft->xbow_link_status[port].rx_err_count = 0;
  911. xbow_soft->xbow_link_status[port].tx_retry_count = 0;
  912.     }
  913.     xbow_soft->link_monitor = 0;
  914.     return 0;
  915. }
  916. int
  917. xbow_enable_llp_monitor(devfs_handle_t vhdl)
  918. {
  919.     xbow_soft_t             xbow_soft = xbow_soft_get(vhdl);
  920. #ifdef LATER
  921.     (void) timeout(xbow_update_llp_status,
  922.    (void *) (__psunsigned_t) vhdl, XBOW_STATS_TIMEOUT);
  923. #endif
  924.     xbow_soft->link_monitor = 1;
  925.     return 0;
  926. }
  927. int
  928. xbow_reset_link(devfs_handle_t xconn_vhdl)
  929. {
  930.     xwidget_info_t          widget_info;
  931.     xwidgetnum_t            port;
  932.     xbow_t                 *xbow;
  933.     xbowreg_t               ctrl;
  934.     xbwX_stat_t             stat;
  935.     unsigned                itick;
  936.     unsigned                dtick;
  937.     static int              ticks_per_ms = 0;
  938.     if (!ticks_per_ms) {
  939. itick = get_timestamp();
  940. us_delay(1000);
  941. ticks_per_ms = get_timestamp() - itick;
  942.     }
  943.     widget_info = xwidget_info_get(xconn_vhdl);
  944.     port = xwidget_info_id_get(widget_info);
  945. #ifdef XBOW_K1PTR /* defined if we only have one xbow ... */
  946.     xbow = XBOW_K1PTR;
  947. #else
  948.     {
  949. devfs_handle_t            xbow_vhdl;
  950. xbow_soft_t             xbow_soft;
  951. hwgraph_traverse(xconn_vhdl, ".master/xtalk/0/xbow", &xbow_vhdl);
  952. xbow_soft = xbow_soft_get(xbow_vhdl);
  953. xbow = xbow_soft->base;
  954.     }
  955. #endif
  956.     /*
  957.      * This requires three PIOs (reset the link, check for the
  958.      * reset, restore the control register for the link) plus
  959.      * 10us to wait for the reset. We allow up to 1ms for the
  960.      * widget to come out of reset before giving up and
  961.      * returning a failure.
  962.      */
  963.     ctrl = xbow->xb_link(port).link_control;
  964.     xbow->xb_link(port).link_reset = 0;
  965.     itick = get_timestamp();
  966.     while (1) {
  967. stat.linkstatus = xbow->xb_link(port).link_status;
  968. if (stat.link_alive)
  969.     break;
  970. dtick = get_timestamp() - itick;
  971. if (dtick > ticks_per_ms) {
  972.     return -1; /* never came out of reset */
  973. }
  974. DELAY(2); /* don't beat on link_status */
  975.     }
  976.     xbow->xb_link(port).link_control = ctrl;
  977.     return 0;
  978. }
  979. /*
  980.  * Dump xbow registers.
  981.  * input parameter is either a pointer to
  982.  * the xbow chip or the vertex handle for
  983.  * an xbow vertex.
  984.  */
  985. void
  986. idbg_xbowregs(int64_t regs)
  987. {
  988.     xbow_t                 *xbow;
  989.     int                     i;
  990.     xb_linkregs_t          *link;
  991. #ifdef LATER
  992.     if (dev_is_vertex((devfs_handle_t) regs)) {
  993. devfs_handle_t            vhdl = (devfs_handle_t) regs;
  994. xbow_soft_t             soft = xbow_soft_get(vhdl);
  995. xbow = soft->base;
  996.     } else
  997. #endif
  998.     {
  999. xbow = (xbow_t *) regs;
  1000.     }
  1001. #ifdef LATER
  1002.     qprintf("Printing xbow registers starting at 0x%xn", xbow);
  1003.     qprintf("wid %x status %x erruppr %x errlower %x control %x timeout %xn",
  1004.     xbow->xb_wid_id, xbow->xb_wid_stat, xbow->xb_wid_err_upper,
  1005.     xbow->xb_wid_err_lower, xbow->xb_wid_control,
  1006.     xbow->xb_wid_req_timeout);
  1007.     qprintf("intr uppr %x lower %x errcmd %x llp ctrl %x arb_reload %xn",
  1008.     xbow->xb_wid_int_upper, xbow->xb_wid_int_lower,
  1009.     xbow->xb_wid_err_cmdword, xbow->xb_wid_llp,
  1010.     xbow->xb_wid_arb_reload);
  1011. #endif
  1012.     for (i = 8; i <= 0xf; i++) {
  1013. link = &xbow->xb_link(i);
  1014. #ifdef LATER
  1015. qprintf("Link %d registersn", i);
  1016. qprintf("tctrl %x stat %x arbuppr %x arblowr %x auxstat %xn",
  1017. link->link_control, link->link_status,
  1018. link->link_arb_upper, link->link_arb_lower,
  1019. link->link_aux_status);
  1020. #endif
  1021.     }
  1022. }
  1023. #define XBOW_ARB_RELOAD_TICKS 25
  1024. /* granularity: 4 MB/s, max: 124 MB/s */
  1025. #define GRANULARITY ((100 * 1000000) / XBOW_ARB_RELOAD_TICKS)
  1026. #define XBOW_BYTES_TO_GBR(BYTES_per_s) (int) (BYTES_per_s / GRANULARITY)
  1027. #define XBOW_GBR_TO_BYTES(cnt) (bandwidth_t) ((cnt) * GRANULARITY)
  1028. #define CEILING_BYTES_TO_GBR(gbr, bytes_per_sec)
  1029. ((XBOW_GBR_TO_BYTES(gbr) < bytes_per_sec) ? gbr+1 : gbr)
  1030. #define XBOW_ARB_GBR_MAX 31
  1031. #define ABS(x) ((x > 0) ? (x) : (-1 * x))
  1032. /* absolute value */
  1033. int
  1034. xbow_bytes_to_gbr(bandwidth_t old_bytes_per_sec, bandwidth_t bytes_per_sec)
  1035. {
  1036.     int                     gbr_granted;
  1037.     int                     new_total_gbr;
  1038.     int                     change_gbr;
  1039.     bandwidth_t             new_total_bw;
  1040. #ifdef GRIO_DEBUG
  1041.     printf("xbow_bytes_to_gbr: old_bytes_per_sec %lld bytes_per_sec %lldn",
  1042. old_bytes_per_sec, bytes_per_sec);
  1043. #endif /* GRIO_DEBUG */
  1044.     gbr_granted = CEILING_BYTES_TO_GBR((XBOW_BYTES_TO_GBR(old_bytes_per_sec)),
  1045. old_bytes_per_sec);
  1046.     new_total_bw = old_bytes_per_sec + bytes_per_sec;
  1047.     new_total_gbr = CEILING_BYTES_TO_GBR((XBOW_BYTES_TO_GBR(new_total_bw)),
  1048. new_total_bw);
  1049.     change_gbr = new_total_gbr - gbr_granted;
  1050. #ifdef GRIO_DEBUG
  1051.     printf("xbow_bytes_to_gbr: gbr_granted %d new_total_gbr %d change_gbr %dn",
  1052. gbr_granted, new_total_gbr, change_gbr);
  1053. #endif /* GRIO_DEBUG */
  1054.     return (change_gbr);
  1055. }
  1056. /* Conversion from GBR to bytes */
  1057. bandwidth_t
  1058. xbow_gbr_to_bytes(int gbr)
  1059. {
  1060.     return (XBOW_GBR_TO_BYTES(gbr));
  1061. }
  1062. /* Given the vhdl for the desired xbow, the src and dest. widget ids
  1063.  * and the req_bw value, this xbow driver entry point accesses the
  1064.  * xbow registers and allocates the desired bandwidth if available.
  1065.  *
  1066.  * If bandwidth allocation is successful, return success else return failure.
  1067.  */
  1068. int
  1069. xbow_prio_bw_alloc(devfs_handle_t vhdl,
  1070. xwidgetnum_t src_wid,
  1071. xwidgetnum_t dest_wid,
  1072. unsigned long long old_alloc_bw,
  1073. unsigned long long req_bw)
  1074. {
  1075.     xbow_soft_t             soft = xbow_soft_get(vhdl);
  1076.     volatile xbowreg_t     *xreg;
  1077.     xbowreg_t               mask;
  1078.     unsigned long           s;
  1079.     int                     error = 0;
  1080.     bandwidth_t             old_bw_BYTES, req_bw_BYTES;
  1081.     xbowreg_t               old_xreg;
  1082.     int                     old_bw_GBR, req_bw_GBR, new_bw_GBR;
  1083. #ifdef GRIO_DEBUG
  1084.     printf("xbow_prio_bw_alloc: vhdl %d src_wid %d dest_wid %d req_bw %lldn",
  1085. (int) vhdl, (int) src_wid, (int) dest_wid, req_bw);
  1086. #endif
  1087.     ASSERT(XBOW_WIDGET_IS_VALID(src_wid));
  1088.     ASSERT(XBOW_WIDGET_IS_VALID(dest_wid));
  1089.     s = mutex_spinlock(&soft->xbow_bw_alloc_lock);
  1090.     /* Get pointer to the correct register */
  1091.     xreg = XBOW_PRIO_ARBREG_PTR(soft->base, dest_wid, src_wid);
  1092.     /* Get mask for GBR count value */
  1093.     mask = XB_ARB_GBR_MSK << XB_ARB_GBR_SHFT(src_wid);
  1094.     req_bw_GBR = xbow_bytes_to_gbr(old_alloc_bw, req_bw);
  1095.     req_bw_BYTES = (req_bw_GBR < 0) ? (-1 * xbow_gbr_to_bytes(ABS(req_bw_GBR)))
  1096. : xbow_gbr_to_bytes(req_bw_GBR);
  1097. #ifdef GRIO_DEBUG
  1098.     printf("req_bw %lld req_bw_BYTES %lld req_bw_GBR %dn",
  1099. req_bw, req_bw_BYTES, req_bw_GBR);
  1100. #endif /* GRIO_DEBUG */
  1101.     old_bw_BYTES = soft->bw_cur_used[(int) dest_wid - MAX_XBOW_PORTS];
  1102.     old_xreg = *xreg;
  1103.     old_bw_GBR = (((*xreg) & mask) >> XB_ARB_GBR_SHFT(src_wid));
  1104. #ifdef GRIO_DEBUG
  1105.     ASSERT(XBOW_BYTES_TO_GBR(old_bw_BYTES) == old_bw_GBR);
  1106.     printf("old_bw_BYTES %lld old_bw_GBR %dn", old_bw_BYTES, old_bw_GBR);
  1107.     printf("req_bw_BYTES %lld old_bw_BYTES %lld soft->bw_hiwm %lldn",
  1108. req_bw_BYTES, old_bw_BYTES,
  1109. soft->bw_hiwm[(int) dest_wid - MAX_XBOW_PORTS]);
  1110.    
  1111. #endif /* GRIO_DEBUG */
  1112.     /* Accept the request only if we don't exceed the destination
  1113.      * port HIWATER_MARK *AND* the max. link GBR arbitration count
  1114.      */
  1115.     if (((old_bw_BYTES + req_bw_BYTES) <=
  1116. soft->bw_hiwm[(int) dest_wid - MAX_XBOW_PORTS]) &&
  1117. (req_bw_GBR + old_bw_GBR <= XBOW_ARB_GBR_MAX)) {
  1118. new_bw_GBR = (old_bw_GBR + req_bw_GBR);
  1119. /* Set this in the xbow link register */
  1120. *xreg = (old_xreg & ~mask) | 
  1121.     (new_bw_GBR << XB_ARB_GBR_SHFT(src_wid) & mask);
  1122. soft->bw_cur_used[(int) dest_wid - MAX_XBOW_PORTS] =
  1123. xbow_gbr_to_bytes(new_bw_GBR);
  1124.     } else {
  1125. error = 1;
  1126.     }
  1127.     mutex_spinunlock(&soft->xbow_bw_alloc_lock, s);
  1128.     return (error);
  1129. }