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

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. #ifdef __ia64
  33. uint64_t atealloc(struct map *mp, size_t size);
  34. void atefree(struct map *mp, size_t size, uint64_t a);
  35. void atemapfree(struct map *mp);
  36. struct map *atemapalloc(uint64_t mapsiz);
  37. #define rmallocmap atemapalloc
  38. #define rmfreemap atemapfree
  39. #define rmfree atefree
  40. #define rmalloc atealloc
  41. #endif
  42. #ifdef LATER
  43. #if (PCIBR_FREEZE_TIME) || PCIBR_ATE_DEBUG
  44. LOCAL struct reg_desc   ate_bits[] =
  45. {
  46.     {0xFFFF000000000000ull, -48, "RMF", "%x"},
  47.     {~(IOPGSIZE - 1) & /* may trim off some low bits */
  48.      0x0000FFFFFFFFF000ull, 0, "XIO", "%x"},
  49.     {0x0000000000000F00ull, -8, "port", "%x"},
  50.     {0x0000000000000010ull, 0, "Barrier"},
  51.     {0x0000000000000008ull, 0, "Prefetch"},
  52.     {0x0000000000000004ull, 0, "Precise"},
  53.     {0x0000000000000002ull, 0, "Coherent"},
  54.     {0x0000000000000001ull, 0, "Valid"},
  55.     {0}
  56. };
  57. #endif
  58. #endif /* LATER */
  59. #ifndef LOCAL
  60. #define LOCAL           static
  61. #endif
  62. /*
  63.  * functions
  64.  */
  65. int               pcibr_init_ext_ate_ram(bridge_t *);
  66. int               pcibr_ate_alloc(pcibr_soft_t, int);
  67. void              pcibr_ate_free(pcibr_soft_t, int, int);
  68. bridge_ate_t      pcibr_flags_to_ate(unsigned);
  69. bridge_ate_p      pcibr_ate_addr(pcibr_soft_t, int);
  70. unsigned    ate_freeze(pcibr_dmamap_t pcibr_dmamap,
  71. #if PCIBR_FREEZE_TIME
  72.     unsigned *freeze_time_ptr,
  73. #endif
  74.     unsigned *cmd_regs);
  75. void    ate_write(bridge_ate_p ate_ptr, int ate_count, bridge_ate_t ate);
  76. void ate_thaw(pcibr_dmamap_t pcibr_dmamap,
  77.   int ate_index,
  78. #if PCIBR_FREEZE_TIME
  79.   bridge_ate_t ate,
  80.   int ate_total,
  81.   unsigned freeze_time_start,
  82. #endif
  83.   unsigned *cmd_regs,
  84.   unsigned s);
  85. /* Convert from ssram_bits in control register to number of SSRAM entries */
  86. #define ATE_NUM_ENTRIES(n) _ate_info[n]
  87. /* Possible choices for number of ATE entries in Bridge's SSRAM */
  88. LOCAL int               _ate_info[] =
  89. {
  90.     0, /* 0 entries */
  91.     8 * 1024, /* 8K entries */
  92.     16 * 1024, /* 16K entries */
  93.     64 * 1024 /* 64K entries */
  94. };
  95. #define ATE_NUM_SIZES (sizeof(_ate_info) / sizeof(int))
  96. #define ATE_PROBE_VALUE 0x0123456789abcdefULL
  97. /*
  98.  * Determine the size of this bridge's external mapping SSRAM, and set
  99.  * the control register appropriately to reflect this size, and initialize
  100.  * the external SSRAM.
  101.  */
  102. int
  103. pcibr_init_ext_ate_ram(bridge_t *bridge)
  104. {
  105.     int                     largest_working_size = 0;
  106.     int                     num_entries, entry;
  107.     int                     i, j;
  108.     bridgereg_t             old_enable, new_enable;
  109.     int                     s;
  110.     /* Probe SSRAM to determine its size. */
  111.     old_enable = bridge->b_int_enable;
  112.     new_enable = old_enable & ~BRIDGE_IMR_PCI_MST_TIMEOUT;
  113.     bridge->b_int_enable = new_enable;
  114.     for (i = 1; i < ATE_NUM_SIZES; i++) {
  115. /* Try writing a value */
  116. bridge->b_ext_ate_ram[ATE_NUM_ENTRIES(i) - 1] = ATE_PROBE_VALUE;
  117. /* Guard against wrap */
  118. for (j = 1; j < i; j++)
  119.     bridge->b_ext_ate_ram[ATE_NUM_ENTRIES(j) - 1] = 0;
  120. /* See if value was written */
  121. if (bridge->b_ext_ate_ram[ATE_NUM_ENTRIES(i) - 1] == ATE_PROBE_VALUE)
  122.     largest_working_size = i;
  123.     }
  124.     bridge->b_int_enable = old_enable;
  125.     bridge->b_wid_tflush; /* wait until Bridge PIO complete */
  126.     /*
  127.      * ensure that we write and read without any interruption.
  128.      * The read following the write is required for the Bridge war
  129.      */
  130.     s = splhi();
  131.     bridge->b_wid_control = (bridge->b_wid_control
  132. & ~BRIDGE_CTRL_SSRAM_SIZE_MASK)
  133. | BRIDGE_CTRL_SSRAM_SIZE(largest_working_size);
  134.     bridge->b_wid_control; /* inval addr bug war */
  135.     splx(s);
  136.     num_entries = ATE_NUM_ENTRIES(largest_working_size);
  137. #if PCIBR_ATE_DEBUG
  138.     if (num_entries)
  139. printk("bridge at 0x%x: clearing %d external ATEsn", bridge, num_entries);
  140.     else
  141. printk("bridge at 0x%x: no external ATE RAM foundn", bridge);
  142. #endif
  143.     /* Initialize external mapping entries */
  144.     for (entry = 0; entry < num_entries; entry++)
  145. bridge->b_ext_ate_ram[entry] = 0;
  146.     return (num_entries);
  147. }
  148. /*
  149.  * Allocate "count" contiguous Bridge Address Translation Entries
  150.  * on the specified bridge to be used for PCI to XTALK mappings.
  151.  * Indices in rm map range from 1..num_entries.  Indicies returned
  152.  * to caller range from 0..num_entries-1.
  153.  *
  154.  * Return the start index on success, -1 on failure.
  155.  */
  156. int
  157. pcibr_ate_alloc(pcibr_soft_t pcibr_soft, int count)
  158. {
  159.     int                     index = 0;
  160.     index = (int) rmalloc(pcibr_soft->bs_int_ate_map, (size_t) count);
  161.     if (!index && pcibr_soft->bs_ext_ate_map)
  162. index = (int) rmalloc(pcibr_soft->bs_ext_ate_map, (size_t) count);
  163.     /* rmalloc manages resources in the 1..n
  164.      * range, with 0 being failure.
  165.      * pcibr_ate_alloc manages resources
  166.      * in the 0..n-1 range, with -1 being failure.
  167.      */
  168.     return index - 1;
  169. }
  170. void
  171. pcibr_ate_free(pcibr_soft_t pcibr_soft, int index, int count)
  172. /* Who says there's no such thing as a free meal? :-) */
  173. {
  174.     /* note the "+1" since rmalloc handles 1..n but
  175.      * we start counting ATEs at zero.
  176.      */
  177.     rmfree((index < pcibr_soft->bs_int_ate_size)
  178.    ? pcibr_soft->bs_int_ate_map
  179.    : pcibr_soft->bs_ext_ate_map,
  180.    count, index + 1);
  181. }
  182. /*
  183.  * Convert PCI-generic software flags and Bridge-specific software flags
  184.  * into Bridge-specific Address Translation Entry attribute bits.
  185.  */
  186. bridge_ate_t
  187. pcibr_flags_to_ate(unsigned flags)
  188. {
  189.     bridge_ate_t            attributes;
  190.     /* default if nothing specified:
  191.      * NOBARRIER
  192.      * NOPREFETCH
  193.      * NOPRECISE
  194.      * COHERENT
  195.      * Plus the valid bit
  196.      */
  197.     attributes = ATE_CO | ATE_V;
  198.     /* Generic macro flags
  199.      */
  200.     if (flags & PCIIO_DMA_DATA) { /* standard data channel */
  201. attributes &= ~ATE_BAR; /* no barrier */
  202. attributes |= ATE_PREF; /* prefetch on */
  203.     }
  204.     if (flags & PCIIO_DMA_CMD) { /* standard command channel */
  205. attributes |= ATE_BAR; /* barrier bit on */
  206. attributes &= ~ATE_PREF; /* disable prefetch */
  207.     }
  208.     /* Generic detail flags
  209.      */
  210.     if (flags & PCIIO_PREFETCH)
  211. attributes |= ATE_PREF;
  212.     if (flags & PCIIO_NOPREFETCH)
  213. attributes &= ~ATE_PREF;
  214.     /* Provider-specific flags
  215.      */
  216.     if (flags & PCIBR_BARRIER)
  217. attributes |= ATE_BAR;
  218.     if (flags & PCIBR_NOBARRIER)
  219. attributes &= ~ATE_BAR;
  220.     if (flags & PCIBR_PREFETCH)
  221. attributes |= ATE_PREF;
  222.     if (flags & PCIBR_NOPREFETCH)
  223. attributes &= ~ATE_PREF;
  224.     if (flags & PCIBR_PRECISE)
  225. attributes |= ATE_PREC;
  226.     if (flags & PCIBR_NOPRECISE)
  227. attributes &= ~ATE_PREC;
  228.     return (attributes);
  229. }
  230. /*
  231.  * Setup an Address Translation Entry as specified.  Use either the Bridge
  232.  * internal maps or the external map RAM, as appropriate.
  233.  */
  234. bridge_ate_p
  235. pcibr_ate_addr(pcibr_soft_t pcibr_soft,
  236.        int ate_index)
  237. {
  238.     bridge_t *bridge = pcibr_soft->bs_base;
  239.     return (ate_index < pcibr_soft->bs_int_ate_size)
  240. ? &(bridge->b_int_ate_ram[ate_index].wr)
  241. : &(bridge->b_ext_ate_ram[ate_index]);
  242. }
  243. /* We are starting to get more complexity
  244.  * surrounding writing ATEs, so pull
  245.  * the writing code into this new function.
  246.  */
  247. #if PCIBR_FREEZE_TIME
  248. #define ATE_FREEZE() s = ate_freeze(pcibr_dmamap, &freeze_time, cmd_regs)
  249. #else
  250. #define ATE_FREEZE() s = ate_freeze(pcibr_dmamap, cmd_regs)
  251. #endif
  252. unsigned
  253. ate_freeze(pcibr_dmamap_t pcibr_dmamap,
  254. #if PCIBR_FREEZE_TIME
  255.    unsigned *freeze_time_ptr,
  256. #endif
  257.    unsigned *cmd_regs)
  258. {
  259.     pcibr_soft_t            pcibr_soft = pcibr_dmamap->bd_soft;
  260. #ifdef LATER
  261.     int                     dma_slot = pcibr_dmamap->bd_slot;
  262. #endif
  263.     int                     ext_ates = pcibr_dmamap->bd_flags & PCIBR_DMAMAP_SSRAM;
  264.     int                     slot;
  265.     unsigned long           s;
  266.     unsigned                cmd_reg;
  267.     volatile unsigned      *cmd_lwa;
  268.     unsigned                cmd_lwd;
  269.     if (!ext_ates)
  270. return 0;
  271.     /* Bridge Hardware Bug WAR #484930:
  272.      * Bridge can't handle updating External ATEs
  273.      * while DMA is occuring that uses External ATEs,
  274.      * even if the particular ATEs involved are disjoint.
  275.      */
  276.     /* need to prevent anyone else from
  277.      * unfreezing the grant while we
  278.      * are working; also need to prevent
  279.      * this thread from being interrupted
  280.      * to keep PCI grant freeze time
  281.      * at an absolute minimum.
  282.      */
  283.     s = pcibr_lock(pcibr_soft);
  284. #ifdef LATER
  285.     /* just in case pcibr_dmamap_done was not called */
  286.     if (pcibr_dmamap->bd_flags & PCIBR_DMAMAP_BUSY) {
  287. pcibr_dmamap->bd_flags &= ~PCIBR_DMAMAP_BUSY;
  288. if (pcibr_dmamap->bd_flags & PCIBR_DMAMAP_SSRAM)
  289.     atomic_dec(&(pcibr_soft->bs_slot[dma_slot]. bss_ext_ates_active));
  290. xtalk_dmamap_done(pcibr_dmamap->bd_xtalk);
  291.     }
  292. #endif /* LATER */
  293. #if PCIBR_FREEZE_TIME
  294.     *freeze_time_ptr = get_timestamp();
  295. #endif
  296.     cmd_lwa = 0;
  297.     for (slot = 0; slot < 8; ++slot)
  298. if (atomic_read(&pcibr_soft->bs_slot[slot].bss_ext_ates_active)) {
  299.     cmd_reg = pcibr_soft->
  300. bs_slot[slot].
  301. bss_cmd_shadow;
  302.     if (cmd_reg & PCI_CMD_BUS_MASTER) {
  303. cmd_lwa = pcibr_soft->
  304.     bs_slot[slot].
  305.     bss_cmd_pointer;
  306. cmd_lwd = cmd_reg ^ PCI_CMD_BUS_MASTER;
  307. cmd_lwa[0] = cmd_lwd;
  308.     }
  309.     cmd_regs[slot] = cmd_reg;
  310. } else
  311.     cmd_regs[slot] = 0;
  312.     if (cmd_lwa) {
  313.     bridge_t *bridge = pcibr_soft->bs_base;
  314.     /* Read the last master bit that has been cleared. This PIO read
  315.      * on the PCI bus is to ensure the completion of any DMAs that
  316.      * are due to bus requests issued by PCI devices before the
  317.      * clearing of master bits.
  318.      */
  319.     cmd_lwa[0];
  320.     /* Flush all the write buffers in the bridge */
  321.     for (slot = 0; slot < 8; ++slot)
  322.     if (atomic_read(&pcibr_soft->bs_slot[slot].bss_ext_ates_active)) {
  323.     /* Flush the write buffer associated with this
  324.      * PCI device which might be using dma map RAM.
  325.      */
  326.     bridge->b_wr_req_buf[slot].reg;
  327.     }
  328.     }
  329.     return s;
  330. }
  331. #define ATE_WRITE()    ate_write(ate_ptr, ate_count, ate)
  332. void
  333. ate_write(bridge_ate_p ate_ptr,
  334.   int ate_count,
  335.   bridge_ate_t ate)
  336. {
  337.     while (ate_count-- > 0) {
  338. *ate_ptr++ = ate;
  339. ate += IOPGSIZE;
  340.     }
  341. }
  342. #if PCIBR_FREEZE_TIME
  343. #define ATE_THAW() ate_thaw(pcibr_dmamap, ate_index, ate, ate_total, freeze_time, cmd_regs, s)
  344. #else
  345. #define ATE_THAW() ate_thaw(pcibr_dmamap, ate_index, cmd_regs, s)
  346. #endif
  347. void
  348. ate_thaw(pcibr_dmamap_t pcibr_dmamap,
  349.  int ate_index,
  350. #if PCIBR_FREEZE_TIME
  351.  bridge_ate_t ate,
  352.  int ate_total,
  353.  unsigned freeze_time_start,
  354. #endif
  355.  unsigned *cmd_regs,
  356.  unsigned s)
  357. {
  358.     pcibr_soft_t            pcibr_soft = pcibr_dmamap->bd_soft;
  359.     int                     dma_slot = pcibr_dmamap->bd_slot;
  360.     int                     slot;
  361.     bridge_t               *bridge = pcibr_soft->bs_base;
  362.     int                     ext_ates = pcibr_dmamap->bd_flags & PCIBR_DMAMAP_SSRAM;
  363.     unsigned                cmd_reg;
  364. #if PCIBR_FREEZE_TIME
  365.     unsigned                freeze_time;
  366.     static unsigned         max_freeze_time = 0;
  367.     static unsigned         max_ate_total;
  368. #endif
  369.     if (!ext_ates)
  370. return;
  371.     /* restore cmd regs */
  372.     for (slot = 0; slot < 8; ++slot)
  373. if ((cmd_reg = cmd_regs[slot]) & PCI_CMD_BUS_MASTER)
  374.     bridge->b_type0_cfg_dev[slot].l[PCI_CFG_COMMAND / 4] = cmd_reg;
  375.     pcibr_dmamap->bd_flags |= PCIBR_DMAMAP_BUSY;
  376.     atomic_inc(&(pcibr_soft->bs_slot[dma_slot]. bss_ext_ates_active));
  377. #if PCIBR_FREEZE_TIME
  378.     freeze_time = get_timestamp() - freeze_time_start;
  379.     if ((max_freeze_time < freeze_time) ||
  380. (max_ate_total < ate_total)) {
  381. if (max_freeze_time < freeze_time)
  382.     max_freeze_time = freeze_time;
  383. if (max_ate_total < ate_total)
  384.     max_ate_total = ate_total;
  385. pcibr_unlock(pcibr_soft, s);
  386. printk("%s: pci freeze time %d usec for %d ATEsn"
  387. "tfirst ate: %Rn",
  388. pcibr_soft->bs_name,
  389. freeze_time * 1000 / 1250,
  390. ate_total,
  391. ate, ate_bits);
  392.     } else
  393. #endif
  394. pcibr_unlock(pcibr_soft, s);
  395. }