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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  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) 2001-2002 Silicon Graphics, Inc. All rights reserved.
  8.  */
  9. #include <linux/types.h>
  10. #include <linux/slab.h>
  11. #include <linux/module.h>
  12. #include <asm/sn/sgi.h>
  13. #include <asm/sn/sn_cpuid.h>
  14. #include <asm/sn/addrs.h>
  15. #include <asm/sn/arch.h>
  16. #include <asm/sn/iograph.h>
  17. #include <asm/sn/invent.h>
  18. #include <asm/sn/hcl.h>
  19. #include <asm/sn/labelcl.h>
  20. #include <asm/sn/xtalk/xwidget.h>
  21. #include <asm/sn/pci/bridge.h>
  22. #include <asm/sn/pci/pciio.h>
  23. #include <asm/sn/pci/pcibr.h>
  24. #include <asm/sn/pci/pcibr_private.h>
  25. #include <asm/sn/pci/pci_defs.h>
  26. #include <asm/sn/prio.h>
  27. #include <asm/sn/xtalk/xbow.h>
  28. #include <asm/sn/ioc3.h>
  29. #include <asm/sn/eeprom.h>
  30. #include <asm/sn/io.h>
  31. #include <asm/sn/sn_private.h>
  32. void              do_pcibr_rrb_clear(bridge_t *, int);
  33. void              do_pcibr_rrb_flush(bridge_t *, int);
  34. int               do_pcibr_rrb_count_valid(bridge_t *, pciio_slot_t);
  35. int               do_pcibr_rrb_count_avail(bridge_t *, pciio_slot_t);
  36. int               do_pcibr_rrb_alloc(bridge_t *, pciio_slot_t, int);
  37. int               do_pcibr_rrb_free(bridge_t *, pciio_slot_t, int);
  38. void              do_pcibr_rrb_autoalloc(pcibr_soft_t, int, int);
  39. int   pcibr_wrb_flush(devfs_handle_t);
  40. int               pcibr_rrb_alloc(devfs_handle_t, int *, int *);
  41. int               pcibr_rrb_check(devfs_handle_t, int *, int *, int *, int *);
  42. int               pcibr_alloc_all_rrbs(devfs_handle_t, int, int, int, int, int, int, int, int, int);
  43. void              pcibr_rrb_flush(devfs_handle_t);
  44. int   pcibr_slot_initial_rrb_alloc(devfs_handle_t,pciio_slot_t);
  45. /* 
  46.  *    RRB Management
  47.  */
  48. #define LSBIT(word) ((word) &~ ((word)-1))
  49. void
  50. do_pcibr_rrb_clear(bridge_t *bridge, int rrb)
  51. {
  52.     bridgereg_t             status;
  53.     /* bridge_lock must be held;
  54.      * this RRB must be disabled.
  55.      */
  56.     /* wait until RRB has no outstanduing XIO packets. */
  57.     while ((status = bridge->b_resp_status) & BRIDGE_RRB_INUSE(rrb)) {
  58. ; /* XXX- beats on bridge. bad idea? */
  59.     }
  60.     /* if the RRB has data, drain it. */
  61.     if (status & BRIDGE_RRB_VALID(rrb)) {
  62. bridge->b_resp_clear = BRIDGE_RRB_CLEAR(rrb);
  63. /* wait until RRB is no longer valid. */
  64. while ((status = bridge->b_resp_status) & BRIDGE_RRB_VALID(rrb)) {
  65.     ; /* XXX- beats on bridge. bad idea? */
  66. }
  67.     }
  68. }
  69. void
  70. do_pcibr_rrb_flush(bridge_t *bridge, int rrbn)
  71. {
  72.     reg_p                   rrbp = &bridge->b_rrb_map[rrbn & 1].reg;
  73.     bridgereg_t             rrbv;
  74.     int                     shft = 4 * (rrbn >> 1);
  75.     unsigned                ebit = BRIDGE_RRB_EN << shft;
  76.     rrbv = *rrbp;
  77.     if (rrbv & ebit)
  78. *rrbp = rrbv & ~ebit;
  79.     do_pcibr_rrb_clear(bridge, rrbn);
  80.     if (rrbv & ebit)
  81. *rrbp = rrbv;
  82. }
  83. /*
  84.  *    pcibr_rrb_count_valid: count how many RRBs are
  85.  *      marked valid for the specified PCI slot on this
  86.  *      bridge.
  87.  *
  88.  *      NOTE: The "slot" parameter for all pcibr_rrb
  89.  *      management routines must include the "virtual"
  90.  *      bit; when manageing both the normal and the
  91.  *      virtual channel, separate calls to these
  92.  *      routines must be made. To denote the virtual
  93.  *      channel, add PCIBR_RRB_SLOT_VIRTUAL to the slot
  94.  *      number.
  95.  *
  96.  *      IMPL NOTE: The obvious algorithm is to iterate
  97.  *      through the RRB fields, incrementing a count if
  98.  *      the RRB is valid and matches the slot. However,
  99.  *      it is much simpler to use an algorithm derived
  100.  *      from the "partitioned add" idea. First, XOR in a
  101.  *      pattern such that the fields that match this
  102.  *      slot come up "all ones" and all other fields
  103.  *      have zeros in the mismatching bits. Then AND
  104.  *      together the bits in the field, so we end up
  105.  *      with one bit turned on for each field that
  106.  *      matched. Now we need to count these bits. This
  107.  *      can be done either with a series of shift/add
  108.  *      instructions or by using "tmp % 15"; I expect
  109.  *      that the cascaded shift/add will be faster.
  110.  */
  111. int
  112. do_pcibr_rrb_count_valid(bridge_t *bridge,
  113.  pciio_slot_t slot)
  114. {
  115.     bridgereg_t             tmp;
  116.     tmp = bridge->b_rrb_map[slot & 1].reg;
  117.     tmp ^= 0x11111111 * (7 - slot / 2);
  118.     tmp &= (0xCCCCCCCC & tmp) >> 2;
  119.     tmp &= (0x22222222 & tmp) >> 1;
  120.     tmp += tmp >> 4;
  121.     tmp += tmp >> 8;
  122.     tmp += tmp >> 16;
  123.     return tmp & 15;
  124. }
  125. /*
  126.  *    do_pcibr_rrb_count_avail: count how many RRBs are
  127.  *      available to be allocated for the specified slot.
  128.  *
  129.  *      IMPL NOTE: similar to the above, except we are
  130.  *      just counting how many fields have the valid bit
  131.  *      turned off.
  132.  */
  133. int
  134. do_pcibr_rrb_count_avail(bridge_t *bridge,
  135.  pciio_slot_t slot)
  136. {
  137.     bridgereg_t             tmp;
  138.     tmp = bridge->b_rrb_map[slot & 1].reg;
  139.     tmp = (0x88888888 & ~tmp) >> 3;
  140.     tmp += tmp >> 4;
  141.     tmp += tmp >> 8;
  142.     tmp += tmp >> 16;
  143.     return tmp & 15;
  144. }
  145. /*
  146.  *    do_pcibr_rrb_alloc: allocate some additional RRBs
  147.  *      for the specified slot. Returns -1 if there were
  148.  *      insufficient free RRBs to satisfy the request,
  149.  *      or 0 if the request was fulfilled.
  150.  *
  151.  *      Note that if a request can be partially filled,
  152.  *      it will be, even if we return failure.
  153.  *
  154.  *      IMPL NOTE: again we avoid iterating across all
  155.  *      the RRBs; instead, we form up a word containing
  156.  *      one bit for each free RRB, then peel the bits
  157.  *      off from the low end.
  158.  */
  159. int
  160. do_pcibr_rrb_alloc(bridge_t *bridge,
  161.    pciio_slot_t slot,
  162.    int more)
  163. {
  164.     int                     rv = 0;
  165.     bridgereg_t             reg, tmp, bit;
  166.     reg = bridge->b_rrb_map[slot & 1].reg;
  167.     tmp = (0x88888888 & ~reg) >> 3;
  168.     while (more-- > 0) {
  169. bit = LSBIT(tmp);
  170. if (!bit) {
  171.     rv = -1;
  172.     break;
  173. }
  174. tmp &= ~bit;
  175. reg = ((reg & ~(bit * 15)) | (bit * (8 + slot / 2)));
  176.     }
  177.     bridge->b_rrb_map[slot & 1].reg = reg;
  178.     return rv;
  179. }
  180. /*
  181.  *    do_pcibr_rrb_free: release some of the RRBs that
  182.  *      have been allocated for the specified
  183.  *      slot. Returns zero for success, or negative if
  184.  *      it was unable to free that many RRBs.
  185.  *
  186.  *      IMPL NOTE: We form up a bit for each RRB
  187.  *      allocated to the slot, aligned with the VALID
  188.  *      bitfield this time; then we peel bits off one at
  189.  *      a time, releasing the corresponding RRB.
  190.  */
  191. int
  192. do_pcibr_rrb_free(bridge_t *bridge,
  193.   pciio_slot_t slot,
  194.   int less)
  195. {
  196.     int                     rv = 0;
  197.     bridgereg_t             reg, tmp, clr, bit;
  198.     int                     i;
  199.     clr = 0;
  200.     reg = bridge->b_rrb_map[slot & 1].reg;
  201.     /* This needs to be done otherwise the rrb's on the virtual channel
  202.      * for this slot won't be freed !!
  203.      */
  204.     tmp = reg & 0xbbbbbbbb;
  205.     tmp ^= (0x11111111 * (7 - slot / 2));
  206.     tmp &= (0x33333333 & tmp) << 2;
  207.     tmp &= (0x44444444 & tmp) << 1;
  208.     while (less-- > 0) {
  209. bit = LSBIT(tmp);
  210. if (!bit) {
  211.     rv = -1;
  212.     break;
  213. }
  214. tmp &= ~bit;
  215. reg &= ~bit;
  216. clr |= bit;
  217.     }
  218.     bridge->b_rrb_map[slot & 1].reg = reg;
  219.     for (i = 0; i < 8; i++)
  220. if (clr & (8 << (4 * i)))
  221.     do_pcibr_rrb_clear(bridge, (2 * i) + (slot & 1));
  222.     return rv;
  223. }
  224. void
  225. do_pcibr_rrb_autoalloc(pcibr_soft_t pcibr_soft,
  226.        int slot,
  227.        int more_rrbs)
  228. {
  229.     bridge_t               *bridge = pcibr_soft->bs_base;
  230.     int                     got;
  231.     for (got = 0; got < more_rrbs; ++got) {
  232. if (pcibr_soft->bs_rrb_res[slot & 7] > 0)
  233.     pcibr_soft->bs_rrb_res[slot & 7]--;
  234. else if (pcibr_soft->bs_rrb_avail[slot & 1] > 0)
  235.     pcibr_soft->bs_rrb_avail[slot & 1]--;
  236. else
  237.     break;
  238. if (do_pcibr_rrb_alloc(bridge, slot, 1) < 0)
  239.     break;
  240. #if PCIBR_RRB_DEBUG
  241. printk("do_pcibr_rrb_autoalloc: add one to slot %d%sn",
  242. slot & 7, slot & 8 ? "v" : "");
  243. #endif
  244. pcibr_soft->bs_rrb_valid[slot]++;
  245.     }
  246. #if PCIBR_RRB_DEBUG
  247.     printk("%s: %d+%d free RRBs. Allocation list:n", pcibr_soft->bs_name,
  248.     pcibr_soft->bs_rrb_avail[0],
  249.     pcibr_soft->bs_rrb_avail[1]);
  250.     for (slot = 0; slot < 8; ++slot)
  251. printk("t%d+%d+%d",
  252. 0xFFF & pcibr_soft->bs_rrb_valid[slot],
  253. 0xFFF & pcibr_soft->bs_rrb_valid[slot + PCIBR_RRB_SLOT_VIRTUAL],
  254. pcibr_soft->bs_rrb_res[slot]);
  255.     printk("n");
  256. #endif
  257. }
  258. /*
  259.  * Device driver interface to flush the write buffers for a specified
  260.  * device hanging off the bridge.
  261.  */
  262. int
  263. pcibr_wrb_flush(devfs_handle_t pconn_vhdl)
  264. {
  265.     pciio_info_t            pciio_info = pciio_info_get(pconn_vhdl);
  266.     pciio_slot_t            pciio_slot = pciio_info_slot_get(pciio_info);
  267.     pcibr_soft_t            pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info);
  268.     bridge_t               *bridge = pcibr_soft->bs_base;
  269.     volatile bridgereg_t   *wrb_flush;
  270.     wrb_flush = &(bridge->b_wr_req_buf[pciio_slot].reg);
  271.     while (*wrb_flush);
  272.     return(0);
  273. }
  274. /*
  275.  * Device driver interface to request RRBs for a specified device
  276.  * hanging off a Bridge.  The driver requests the total number of
  277.  * RRBs it would like for the normal channel (vchan0) and for the
  278.  * "virtual channel" (vchan1).  The actual number allocated to each
  279.  * channel is returned.
  280.  *
  281.  * If we cannot allocate at least one RRB to a channel that needs
  282.  * at least one, return -1 (failure).  Otherwise, satisfy the request
  283.  * as best we can and return 0.
  284.  */
  285. int
  286. pcibr_rrb_alloc(devfs_handle_t pconn_vhdl,
  287. int *count_vchan0,
  288. int *count_vchan1)
  289. {
  290.     pciio_info_t            pciio_info = pciio_info_get(pconn_vhdl);
  291.     pciio_slot_t            pciio_slot = pciio_info_slot_get(pciio_info);
  292.     pcibr_soft_t            pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info);
  293.     bridge_t               *bridge = pcibr_soft->bs_base;
  294.     int                     desired_vchan0;
  295.     int                     desired_vchan1;
  296.     int                     orig_vchan0;
  297.     int                     orig_vchan1;
  298.     int                     delta_vchan0;
  299.     int                     delta_vchan1;
  300.     int                     final_vchan0;
  301.     int                     final_vchan1;
  302.     int                     avail_rrbs;
  303.     int                     res_rrbs;
  304.     unsigned long           s;
  305.     int                     error;
  306.     /*
  307.      * TBD: temper request with admin info about RRB allocation,
  308.      * and according to demand from other devices on this Bridge.
  309.      *
  310.      * One way of doing this would be to allocate two RRBs
  311.      * for each device on the bus, before any drivers start
  312.      * asking for extras. This has the weakness that one
  313.      * driver might not give back an "extra" RRB until after
  314.      * another driver has already failed to get one that
  315.      * it wanted.
  316.      */
  317.     s = pcibr_lock(pcibr_soft);
  318.     /* Save the boot-time RRB configuration for this slot */
  319.     if (pcibr_soft->bs_rrb_valid_dflt[pciio_slot] < 0) {
  320.         pcibr_soft->bs_rrb_valid_dflt[pciio_slot] =
  321.                 pcibr_soft->bs_rrb_valid[pciio_slot]; 
  322.         pcibr_soft->bs_rrb_valid_dflt[pciio_slot + PCIBR_RRB_SLOT_VIRTUAL] =
  323.                 pcibr_soft->bs_rrb_valid[pciio_slot + PCIBR_RRB_SLOT_VIRTUAL];
  324.         pcibr_soft->bs_rrb_res_dflt[pciio_slot] =
  325.                 pcibr_soft->bs_rrb_res[pciio_slot];
  326.                   
  327.     }
  328.     /* How many RRBs do we own? */
  329.     orig_vchan0 = pcibr_soft->bs_rrb_valid[pciio_slot];
  330.     orig_vchan1 = pcibr_soft->bs_rrb_valid[pciio_slot + PCIBR_RRB_SLOT_VIRTUAL];
  331.     /* How many RRBs do we want? */
  332.     desired_vchan0 = count_vchan0 ? *count_vchan0 : orig_vchan0;
  333.     desired_vchan1 = count_vchan1 ? *count_vchan1 : orig_vchan1;
  334.     /* How many RRBs are free? */
  335.     avail_rrbs = pcibr_soft->bs_rrb_avail[pciio_slot & 1]
  336. + pcibr_soft->bs_rrb_res[pciio_slot];
  337.     /* Figure desired deltas */
  338.     delta_vchan0 = desired_vchan0 - orig_vchan0;
  339.     delta_vchan1 = desired_vchan1 - orig_vchan1;
  340.     /* Trim back deltas to something
  341.      * that we can actually meet, by
  342.      * decreasing the ending allocation
  343.      * for whichever channel wants
  344.      * more RRBs. If both want the same
  345.      * number, cut the second channel.
  346.      * NOTE: do not change the allocation for
  347.      * a channel that was passed as NULL.
  348.      */
  349.     while ((delta_vchan0 + delta_vchan1) > avail_rrbs) {
  350. if (count_vchan0 &&
  351.     (!count_vchan1 ||
  352.      ((orig_vchan0 + delta_vchan0) >
  353.       (orig_vchan1 + delta_vchan1))))
  354.     delta_vchan0--;
  355. else
  356.     delta_vchan1--;
  357.     }
  358.     /* Figure final RRB allocations
  359.      */
  360.     final_vchan0 = orig_vchan0 + delta_vchan0;
  361.     final_vchan1 = orig_vchan1 + delta_vchan1;
  362.     /* If either channel wants RRBs but our actions
  363.      * would leave it with none, declare an error,
  364.      * but DO NOT change any RRB allocations.
  365.      */
  366.     if ((desired_vchan0 && !final_vchan0) ||
  367. (desired_vchan1 && !final_vchan1)) {
  368. error = -1;
  369.     } else {
  370. /* Commit the allocations: free, then alloc.
  371.  */
  372. if (delta_vchan0 < 0)
  373.     (void) do_pcibr_rrb_free(bridge, pciio_slot, -delta_vchan0);
  374. if (delta_vchan1 < 0)
  375.     (void) do_pcibr_rrb_free(bridge, PCIBR_RRB_SLOT_VIRTUAL + pciio_slot, -delta_vchan1);
  376. if (delta_vchan0 > 0)
  377.     (void) do_pcibr_rrb_alloc(bridge, pciio_slot, delta_vchan0);
  378. if (delta_vchan1 > 0)
  379.     (void) do_pcibr_rrb_alloc(bridge, PCIBR_RRB_SLOT_VIRTUAL + pciio_slot, delta_vchan1);
  380. /* Return final values to caller.
  381.  */
  382. if (count_vchan0)
  383.     *count_vchan0 = final_vchan0;
  384. if (count_vchan1)
  385.     *count_vchan1 = final_vchan1;
  386. /* prevent automatic changes to this slot's RRBs
  387.  */
  388. pcibr_soft->bs_rrb_fixed |= 1 << pciio_slot;
  389. /* Track the actual allocations, release
  390.  * any further reservations, and update the
  391.  * number of available RRBs.
  392.  */
  393. pcibr_soft->bs_rrb_valid[pciio_slot] = final_vchan0;
  394. pcibr_soft->bs_rrb_valid[pciio_slot + PCIBR_RRB_SLOT_VIRTUAL] = final_vchan1;
  395. pcibr_soft->bs_rrb_avail[pciio_slot & 1] =
  396.     pcibr_soft->bs_rrb_avail[pciio_slot & 1]
  397.     + pcibr_soft->bs_rrb_res[pciio_slot]
  398.     - delta_vchan0
  399.     - delta_vchan1;
  400. pcibr_soft->bs_rrb_res[pciio_slot] = 0;
  401.         /*
  402.          * Reserve enough RRBs so this slot's RRB configuration can be
  403.          * reset to its boot-time default following a hot-plug shut-down
  404.          */
  405.         res_rrbs =   (pcibr_soft->bs_rrb_valid_dflt[pciio_slot] -
  406.                       pcibr_soft->bs_rrb_valid[pciio_slot]) 
  407.                    + (pcibr_soft->bs_rrb_valid_dflt[pciio_slot +
  408.                                                     PCIBR_RRB_SLOT_VIRTUAL] -
  409.                       pcibr_soft->bs_rrb_valid[pciio_slot +
  410.                                                PCIBR_RRB_SLOT_VIRTUAL])
  411.                    + (pcibr_soft->bs_rrb_res_dflt[pciio_slot] -
  412.                       pcibr_soft->bs_rrb_res[pciio_slot]);
  413.          if (res_rrbs > 0) {
  414.              pcibr_soft->bs_rrb_res[pciio_slot] = res_rrbs;
  415.              pcibr_soft->bs_rrb_avail[pciio_slot & 1] =
  416.                  pcibr_soft->bs_rrb_avail[pciio_slot & 1]
  417.                  - res_rrbs;
  418.          }
  419.  
  420. #if PCIBR_RRB_DEBUG
  421. printk("pcibr_rrb_alloc: slot %d set to %d+%d; %d+%d freen",
  422. pciio_slot, final_vchan0, final_vchan1,
  423. pcibr_soft->bs_rrb_avail[0],
  424. pcibr_soft->bs_rrb_avail[1]);
  425. for (pciio_slot = 0; pciio_slot < 8; ++pciio_slot)
  426.     printk("t%d+%d+%d",
  427.     0xFFF & pcibr_soft->bs_rrb_valid[pciio_slot],
  428.     0xFFF & pcibr_soft->bs_rrb_valid[pciio_slot + PCIBR_RRB_SLOT_VIRTUAL],
  429.     pcibr_soft->bs_rrb_res[pciio_slot]);
  430. printk("n");
  431. #endif
  432. error = 0;
  433.     }
  434.     pcibr_unlock(pcibr_soft, s);
  435.     return error;
  436. }
  437. /*
  438.  * Device driver interface to check the current state
  439.  * of the RRB allocations.
  440.  *
  441.  *   pconn_vhdl is your PCI connection point (specifies which
  442.  *      PCI bus and which slot).
  443.  *
  444.  *   count_vchan0 points to where to return the number of RRBs
  445.  *      assigned to the primary DMA channel, used by all DMA
  446.  *      that does not explicitly ask for the alternate virtual
  447.  *      channel.
  448.  *
  449.  *   count_vchan1 points to where to return the number of RRBs
  450.  *      assigned to the secondary DMA channel, used when
  451.  *      PCIBR_VCHAN1 and PCIIO_DMA_A64 are specified.
  452.  *
  453.  *   count_reserved points to where to return the number of RRBs
  454.  *      that have been automatically reserved for your device at
  455.  *      startup, but which have not been assigned to a
  456.  *      channel. RRBs must be assigned to a channel to be used;
  457.  *      this can be done either with an explicit pcibr_rrb_alloc
  458.  *      call, or automatically by the infrastructure when a DMA
  459.  *      translation is constructed. Any call to pcibr_rrb_alloc
  460.  *      will release any unassigned reserved RRBs back to the
  461.  *      free pool.
  462.  *
  463.  *   count_pool points to where to return the number of RRBs
  464.  *      that are currently unassigned and unreserved. This
  465.  *      number can (and will) change as other drivers make calls
  466.  *      to pcibr_rrb_alloc, or automatically allocate RRBs for
  467.  *      DMA beyond their initial reservation.
  468.  *
  469.  * NULL may be passed for any of the return value pointers
  470.  * the caller is not interested in.
  471.  *
  472.  * The return value is "0" if all went well, or "-1" if
  473.  * there is a problem. Additionally, if the wrong vertex
  474.  * is passed in, one of the subsidiary support functions
  475.  * could panic with a "bad pciio fingerprint."
  476.  */
  477. int
  478. pcibr_rrb_check(devfs_handle_t pconn_vhdl,
  479. int *count_vchan0,
  480. int *count_vchan1,
  481. int *count_reserved,
  482. int *count_pool)
  483. {
  484.     pciio_info_t            pciio_info;
  485.     pciio_slot_t            pciio_slot;
  486.     pcibr_soft_t            pcibr_soft;
  487.     unsigned long           s;
  488.     int                     error = -1;
  489.     if ((pciio_info = pciio_info_get(pconn_vhdl)) &&
  490. (pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info)) &&
  491. ((pciio_slot = pciio_info_slot_get(pciio_info)) < 8)) {
  492. s = pcibr_lock(pcibr_soft);
  493. if (count_vchan0)
  494.     *count_vchan0 =
  495. pcibr_soft->bs_rrb_valid[pciio_slot];
  496. if (count_vchan1)
  497.     *count_vchan1 =
  498. pcibr_soft->bs_rrb_valid[pciio_slot + PCIBR_RRB_SLOT_VIRTUAL];
  499. if (count_reserved)
  500.     *count_reserved =
  501. pcibr_soft->bs_rrb_res[pciio_slot];
  502. if (count_pool)
  503.     *count_pool =
  504. pcibr_soft->bs_rrb_avail[pciio_slot & 1];
  505. error = 0;
  506. pcibr_unlock(pcibr_soft, s);
  507.     }
  508.     return error;
  509. }
  510. /* pcibr_alloc_all_rrbs allocates all the rrbs available in the quantities
  511.  * requested for each of the devices.  The evn_odd argument indicates whether
  512.  * allocation is for the odd or even rrbs. The next group of four argument
  513.  * pairs indicate the amount of rrbs to be assigned to each device. The first
  514.  * argument of each pair indicate the total number of rrbs to allocate for that
  515.  * device. The second argument of each pair indicates how many rrb's from the
  516.  * first argument should be assigned to the virtual channel. The total of all
  517.  * of the first arguments should be <= 8. The second argument should be <= the
  518.  * first argument.
  519.  * if even_odd = 0 the devices in order are 0, 2, 4, 6 
  520.  * if even_odd = 1 the devices in order are 1, 3, 5, 7
  521.  * returns 0 if no errors else returns -1
  522.  */
  523. int
  524. pcibr_alloc_all_rrbs(devfs_handle_t vhdl, int even_odd,
  525.      int dev_1_rrbs, int virt1, int dev_2_rrbs, int virt2,
  526.      int dev_3_rrbs, int virt3, int dev_4_rrbs, int virt4)
  527. {
  528.     devfs_handle_t          pcibr_vhdl;
  529.     pcibr_soft_t            pcibr_soft = (pcibr_soft_t)0;
  530.     bridge_t               *bridge = NULL;
  531.     uint32_t                rrb_setting = 0;
  532.     int                     rrb_shift = 7;
  533.     uint32_t                cur_rrb;
  534.     int                     dev_rrbs[4];
  535.     int                     virt[4];
  536.     int                     i, j;
  537.     unsigned long           s;
  538.     if (GRAPH_SUCCESS ==
  539. hwgraph_traverse(vhdl, EDGE_LBL_PCI, &pcibr_vhdl)) {
  540. pcibr_soft = pcibr_soft_get(pcibr_vhdl);
  541. if (pcibr_soft)
  542.     bridge = pcibr_soft->bs_base;
  543. hwgraph_vertex_unref(pcibr_vhdl);
  544.     }
  545.     if (bridge == NULL)
  546. bridge = (bridge_t *) xtalk_piotrans_addr
  547.     (vhdl, NULL, 0, sizeof(bridge_t), 0);
  548.     even_odd &= 1;
  549.     dev_rrbs[0] = dev_1_rrbs;
  550.     dev_rrbs[1] = dev_2_rrbs;
  551.     dev_rrbs[2] = dev_3_rrbs;
  552.     dev_rrbs[3] = dev_4_rrbs;
  553.     virt[0] = virt1;
  554.     virt[1] = virt2;
  555.     virt[2] = virt3;
  556.     virt[3] = virt4;
  557.     if ((dev_1_rrbs + dev_2_rrbs + dev_3_rrbs + dev_4_rrbs) > 8) {
  558. return -1;
  559.     }
  560.     if ((dev_1_rrbs < 0) || (dev_2_rrbs < 0) || (dev_3_rrbs < 0) || (dev_4_rrbs < 0)) {
  561. return -1;
  562.     }
  563.     /* walk through rrbs */
  564.     for (i = 0; i < 4; i++) {
  565. if (virt[i]) {
  566. for( j = 0; j < virt[i]; j++) {
  567. cur_rrb = i | 0xc;
  568. cur_rrb = cur_rrb << (rrb_shift * 4);
  569. rrb_shift--;
  570. rrb_setting = rrb_setting | cur_rrb;
  571. dev_rrbs[i] = dev_rrbs[i] - 1;
  572. }
  573. }
  574. for (j = 0; j < dev_rrbs[i]; j++) {
  575.     cur_rrb = i | 0x8;
  576.     cur_rrb = cur_rrb << (rrb_shift * 4);
  577.     rrb_shift--;
  578.     rrb_setting = rrb_setting | cur_rrb;
  579. }
  580.     }
  581.     if (pcibr_soft)
  582. s = pcibr_lock(pcibr_soft);
  583.     bridge->b_rrb_map[even_odd].reg = rrb_setting;
  584.     if (pcibr_soft) {
  585. pcibr_soft->bs_rrb_fixed |= 0x55 << even_odd;
  586. /* since we've "FIXED" the allocations
  587.  * for these slots, we probably can dispense
  588.  * with tracking avail/res/valid data, but
  589.  * keeping it up to date helps debugging.
  590.  */
  591. pcibr_soft->bs_rrb_avail[even_odd] =
  592.     8 - (dev_1_rrbs + dev_2_rrbs + dev_3_rrbs + dev_4_rrbs);
  593. pcibr_soft->bs_rrb_res[even_odd + 0] = 0;
  594. pcibr_soft->bs_rrb_res[even_odd + 2] = 0;
  595. pcibr_soft->bs_rrb_res[even_odd + 4] = 0;
  596. pcibr_soft->bs_rrb_res[even_odd + 6] = 0;
  597. pcibr_soft->bs_rrb_valid[even_odd + 0] = dev_1_rrbs - virt1;
  598. pcibr_soft->bs_rrb_valid[even_odd + 2] = dev_2_rrbs - virt2;
  599. pcibr_soft->bs_rrb_valid[even_odd + 4] = dev_3_rrbs - virt3;
  600. pcibr_soft->bs_rrb_valid[even_odd + 6] = dev_4_rrbs - virt4;
  601. pcibr_soft->bs_rrb_valid[even_odd + 0 + PCIBR_RRB_SLOT_VIRTUAL] = virt1;
  602. pcibr_soft->bs_rrb_valid[even_odd + 2 + PCIBR_RRB_SLOT_VIRTUAL] = virt2;
  603. pcibr_soft->bs_rrb_valid[even_odd + 4 + PCIBR_RRB_SLOT_VIRTUAL] = virt3;
  604. pcibr_soft->bs_rrb_valid[even_odd + 6 + PCIBR_RRB_SLOT_VIRTUAL] = virt4;
  605. pcibr_unlock(pcibr_soft, s);
  606.     }
  607.     return 0;
  608. }
  609. /*
  610.  *    pcibr_rrb_flush: chase down all the RRBs assigned
  611.  *      to the specified connection point, and flush
  612.  *      them.
  613.  */
  614. void
  615. pcibr_rrb_flush(devfs_handle_t pconn_vhdl)
  616. {
  617.     pciio_info_t            pciio_info = pciio_info_get(pconn_vhdl);
  618.     pcibr_soft_t            pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info);
  619.     pciio_slot_t            pciio_slot = pciio_info_slot_get(pciio_info);
  620.     bridge_t               *bridge = pcibr_soft->bs_base;
  621.     unsigned long           s;
  622.     reg_p                   rrbp;
  623.     unsigned                rrbm;
  624.     int                     i;
  625.     int                     rrbn;
  626.     unsigned                sval;
  627.     unsigned                mask;
  628.     sval = BRIDGE_RRB_EN | (pciio_slot >> 1);
  629.     mask = BRIDGE_RRB_EN | BRIDGE_RRB_PDEV;
  630.     rrbn = pciio_slot & 1;
  631.     rrbp = &bridge->b_rrb_map[rrbn].reg;
  632.     s = pcibr_lock(pcibr_soft);
  633.     rrbm = *rrbp;
  634.     for (i = 0; i < 8; ++i) {
  635. if ((rrbm & mask) == sval)
  636.     do_pcibr_rrb_flush(bridge, rrbn);
  637. rrbm >>= 4;
  638. rrbn += 2;
  639.     }
  640.     pcibr_unlock(pcibr_soft, s);
  641. }
  642. /*
  643.  * pcibr_slot_initial_rrb_alloc
  644.  * Allocate a default number of rrbs for this slot on 
  645.  *  the two channels.  This is dictated by the rrb allocation
  646.  *  strategy routine defined per platform.
  647.  */
  648. int
  649. pcibr_slot_initial_rrb_alloc(devfs_handle_t pcibr_vhdl,
  650.      pciio_slot_t slot)
  651. {
  652.     pcibr_soft_t  pcibr_soft;
  653.     pcibr_info_h  pcibr_infoh;
  654.     pcibr_info_t  pcibr_info;
  655.     bridge_t *bridge;
  656.     int                  c0, c1, r;
  657.     pcibr_soft = pcibr_soft_get(pcibr_vhdl);
  658.     if (!pcibr_soft || !PCIBR_VALID_SLOT(slot))
  659. return(EINVAL);
  660.     bridge = pcibr_soft->bs_base;
  661.     /* How may RRBs are on this slot?
  662.      */
  663.     c0 = do_pcibr_rrb_count_valid(bridge, slot);
  664.     c1 = do_pcibr_rrb_count_valid(bridge, slot + PCIBR_RRB_SLOT_VIRTUAL);
  665. #if PCIBR_RRB_DEBUG
  666.     printk(
  667.     "pcibr_slot_initial_rrb_alloc: slot %d started with %d+%dn",
  668.             slot, c0, c1);
  669. #endif
  670.     /* Do we really need any?
  671.      */
  672.     pcibr_infoh = pcibr_soft->bs_slot[slot].bss_infos;
  673.     pcibr_info = pcibr_infoh[0];
  674.     if ((pcibr_info->f_vendor == PCIIO_VENDOR_ID_NONE) &&
  675. !pcibr_soft->bs_slot[slot].has_host) {
  676. if (c0 > 0)
  677.     do_pcibr_rrb_free(bridge, slot, c0);
  678. if (c1 > 0)
  679.     do_pcibr_rrb_free(bridge, slot + PCIBR_RRB_SLOT_VIRTUAL, c1);
  680. pcibr_soft->bs_rrb_valid[slot] = 0x1000;
  681. pcibr_soft->bs_rrb_valid[slot + PCIBR_RRB_SLOT_VIRTUAL] = 0x1000;
  682. return(ENODEV);
  683.     }
  684.     pcibr_soft->bs_rrb_avail[slot & 1] -= c0 + c1;
  685.     pcibr_soft->bs_rrb_valid[slot] = c0;
  686.     pcibr_soft->bs_rrb_valid[slot + PCIBR_RRB_SLOT_VIRTUAL] = c1;
  687.     pcibr_soft->bs_rrb_avail[0] = do_pcibr_rrb_count_avail(bridge, 0);
  688.     pcibr_soft->bs_rrb_avail[1] = do_pcibr_rrb_count_avail(bridge, 1);
  689.     r = 3 - (c0 + c1);
  690.     if (r > 0) {
  691. pcibr_soft->bs_rrb_res[slot] = r;
  692. pcibr_soft->bs_rrb_avail[slot & 1] -= r;
  693.     }
  694. #if PCIBR_RRB_DEBUG
  695.     printk("t%d+%d+%d",
  696.     0xFFF & pcibr_soft->bs_rrb_valid[slot],
  697.     0xFFF & pcibr_soft->bs_rrb_valid[slot + PCIBR_RRB_SLOT_VIRTUAL],
  698.     pcibr_soft->bs_rrb_res[slot]);
  699.     printk("n");
  700. #endif
  701.     return(0);
  702. }
  703. /*
  704.  * pcibr_initial_rrb
  705.  *      Assign an equal total number of RRBs to all candidate slots, 
  706.  *      where the total is the sum of the number of RRBs assigned to
  707.  *      the normal channel, the number of RRBs assigned to the virtual
  708.  *      channel, and the number of RRBs assigned as reserved. 
  709.  *
  710.  *      A candidate slot is a populated slot on a non-SN1 system or 
  711.  *      any existing (populated or empty) slot on an SN1 system.
  712.  *      Empty SN1 slots need RRBs to support hot-plug operations.
  713.  */
  714. int
  715. pcibr_initial_rrb(devfs_handle_t pcibr_vhdl,
  716.      pciio_slot_t first, pciio_slot_t last)
  717. {
  718.     pcibr_soft_t            pcibr_soft = pcibr_soft_get(pcibr_vhdl);
  719.     bridge_t               *bridge = pcibr_soft->bs_base;
  720.     pciio_slot_t            slot;
  721.     int                     c0, c1;
  722.     int                     have[2][3];
  723.     int                     res[2];
  724.     int                     eo;
  725.     have[0][0] = have[0][1] = have[0][2] = 0;
  726.     have[1][0] = have[1][1] = have[1][2] = 0;
  727.     res[0] = res[1] = 0;
  728.     for (slot = 0; slot < 8; ++slot) {
  729.         /* Initial RRB management; give back RRBs in all non-existent slots */
  730.         (void) pcibr_slot_initial_rrb_alloc(pcibr_vhdl, slot);
  731.         /* Base calculations only on existing slots */
  732.         if ((slot >= first) && (slot <= last)) {
  733.             c0 = pcibr_soft->bs_rrb_valid[slot];
  734.             c1 = pcibr_soft->bs_rrb_valid[slot + PCIBR_RRB_SLOT_VIRTUAL];
  735.             if ((c0 + c1) < 3)
  736.                 have[slot & 1][c0 + c1]++;
  737.         }
  738.     }
  739.     /* Initialize even/odd slot available RRB counts */
  740.     pcibr_soft->bs_rrb_avail[0] = do_pcibr_rrb_count_avail(bridge, 0);
  741.     pcibr_soft->bs_rrb_avail[1] = do_pcibr_rrb_count_avail(bridge, 1);
  742.     /*
  743.      * Calculate reserved RRBs for slots based on current RRB usage
  744.      */
  745.     for (eo = 0; eo < 2; eo++) {
  746.         if ((3 * have[eo][0] + 2 * have[eo][1] + have[eo][2]) <= pcibr_soft->bs_rrb_avail[eo])
  747.             res[eo] = 3;
  748.         else if ((2 * have[eo][0] + have[eo][1]) <= pcibr_soft->bs_rrb_avail[eo])
  749.             res[eo] = 2;
  750.         else if (have[eo][0] <= pcibr_soft->bs_rrb_avail[eo])
  751.             res[eo] = 1;
  752.         else
  753.             res[eo] = 0;
  754.     }
  755.     /* Assign reserved RRBs to existing slots */
  756.     for (slot = first; slot <= last; ++slot) {
  757.         int                     r;
  758.         c0 = pcibr_soft->bs_rrb_valid[slot];
  759.         c1 = pcibr_soft->bs_rrb_valid[slot + PCIBR_RRB_SLOT_VIRTUAL];
  760.         r = res[slot & 1] - (c0 + c1);
  761.         if (r > 0) {
  762.             pcibr_soft->bs_rrb_res[slot] = r;
  763.             pcibr_soft->bs_rrb_avail[slot & 1] -= r;
  764.             }
  765.     }
  766. #if PCIBR_RRB_DEBUG
  767.     printk("%v RRB MANAGEMENT: %d+%d freen",
  768.             pcibr_vhdl,
  769.             pcibr_soft->bs_rrb_avail[0],
  770.             pcibr_soft->bs_rrb_avail[1]);
  771.     for (slot = first; slot <= last; ++slot)
  772.         printk("tslot %d: %d+%d+%d", slot,
  773.                 0xFFF & pcibr_soft->bs_rrb_valid[slot],
  774.                 0xFFF & pcibr_soft->bs_rrb_valid[slot + PCIBR_RRB_SLOT_VIRTUAL],
  775.                 pcibr_soft->bs_rrb_res[slot]);
  776.     printk("n");
  777. #endif
  778.     return 0;
  779. }