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

嵌入式Linux

开发平台:

Unix_Linux

  1. /* $Id: io-unit.c,v 1.23 2001/02/13 01:16:43 davem Exp $
  2.  * io-unit.c:  IO-UNIT specific routines for memory management.
  3.  *
  4.  * Copyright (C) 1997,1998 Jakub Jelinek    (jj@sunsite.mff.cuni.cz)
  5.  */
  6.  
  7. #include <linux/config.h>
  8. #include <linux/kernel.h>
  9. #include <linux/init.h>
  10. #include <linux/slab.h>
  11. #include <linux/spinlock.h>
  12. #include <asm/scatterlist.h>
  13. #include <asm/pgalloc.h>
  14. #include <asm/pgtable.h>
  15. #include <asm/sbus.h>
  16. #include <asm/io.h>
  17. #include <asm/io-unit.h>
  18. #include <asm/mxcc.h>
  19. #include <asm/bitops.h>
  20. /* #define IOUNIT_DEBUG */
  21. #ifdef IOUNIT_DEBUG
  22. #define IOD(x) printk(x)
  23. #else
  24. #define IOD(x) do { } while (0)
  25. #endif
  26. #define IOPERM        (IOUPTE_CACHE | IOUPTE_WRITE | IOUPTE_VALID)
  27. #define MKIOPTE(phys) __iopte((((phys)>>4) & IOUPTE_PAGE) | IOPERM)
  28. void __init
  29. iounit_init(int sbi_node, int io_node, struct sbus_bus *sbus)
  30. {
  31. iopte_t *xpt, *xptend;
  32. struct iounit_struct *iounit;
  33. struct linux_prom_registers iommu_promregs[PROMREG_MAX];
  34. struct resource r;
  35. iounit = kmalloc(sizeof(struct iounit_struct), GFP_ATOMIC);
  36. memset(iounit, 0, sizeof(*iounit));
  37. iounit->limit[0] = IOUNIT_BMAP1_START;
  38. iounit->limit[1] = IOUNIT_BMAP2_START;
  39. iounit->limit[2] = IOUNIT_BMAPM_START;
  40. iounit->limit[3] = IOUNIT_BMAPM_END;
  41. iounit->rotor[1] = IOUNIT_BMAP2_START;
  42. iounit->rotor[2] = IOUNIT_BMAPM_START;
  43. prom_getproperty(sbi_node, "reg", (void *) iommu_promregs,
  44.  sizeof(iommu_promregs));
  45. prom_apply_generic_ranges(io_node, 0, iommu_promregs, 3);
  46. memset(&r, 0, sizeof(r));
  47. r.flags = iommu_promregs[2].which_io;
  48. r.start = iommu_promregs[2].phys_addr;
  49. xpt = (iopte_t *) sbus_ioremap(&r, 0, PAGE_SIZE * 16, "XPT");
  50. if(!xpt) panic("Cannot map External Page Table.");
  51. sbus->iommu = (struct iommu_struct *)iounit;
  52. iounit->page_table = xpt;
  53. for (xptend = iounit->page_table + (16 * PAGE_SIZE) / sizeof(iopte_t);
  54.      xpt < xptend;)
  55.       *xpt++ = 0;
  56. }
  57. /* One has to hold iounit->lock to call this */
  58. static unsigned long iounit_get_area(struct iounit_struct *iounit, unsigned long vaddr, int size)
  59. {
  60. int i, j, k, npages;
  61. unsigned long rotor, scan, limit;
  62. iopte_t iopte;
  63.         npages = ((vaddr & ~PAGE_MASK) + size + (PAGE_SIZE-1)) >> PAGE_SHIFT;
  64. /* A tiny bit of magic ingredience :) */
  65. switch (npages) {
  66. case 1: i = 0x0231; break;
  67. case 2: i = 0x0132; break;
  68. default: i = 0x0213; break;
  69. }
  70. IOD(("iounit_get_area(%08lx,%d[%d])=", vaddr, size, npages));
  71. next: j = (i & 15);
  72. rotor = iounit->rotor[j - 1];
  73. limit = iounit->limit[j];
  74. scan = rotor;
  75. nexti: scan = find_next_zero_bit(iounit->bmap, limit, scan);
  76. if (scan + npages > limit) {
  77. if (limit != rotor) {
  78. limit = rotor;
  79. scan = iounit->limit[j - 1];
  80. goto nexti;
  81. }
  82. i >>= 4;
  83. if (!(i & 15))
  84. panic("iounit_get_area: Couldn't find free iopte slots for (%08lx,%d)n", vaddr, size);
  85. goto next;
  86. }
  87. for (k = 1, scan++; k < npages; k++)
  88. if (test_bit(scan++, iounit->bmap))
  89. goto nexti;
  90. iounit->rotor[j - 1] = (scan < limit) ? scan : iounit->limit[j - 1];
  91. scan -= npages;
  92. iopte = MKIOPTE(__pa(vaddr & PAGE_MASK));
  93. vaddr = IOUNIT_DMA_BASE + (scan << PAGE_SHIFT) + (vaddr & ~PAGE_MASK);
  94. for (k = 0; k < npages; k++, iopte = __iopte(iopte_val(iopte) + 0x100), scan++) {
  95. set_bit(scan, iounit->bmap);
  96. iounit->page_table[scan] = iopte;
  97. }
  98. IOD(("%08lxn", vaddr));
  99. return vaddr;
  100. }
  101. static __u32 iounit_get_scsi_one(char *vaddr, unsigned long len, struct sbus_bus *sbus)
  102. {
  103. unsigned long ret, flags;
  104. struct iounit_struct *iounit = (struct iounit_struct *)sbus->iommu;
  105. spin_lock_irqsave(&iounit->lock, flags);
  106. ret = iounit_get_area(iounit, (unsigned long)vaddr, len);
  107. spin_unlock_irqrestore(&iounit->lock, flags);
  108. return ret;
  109. }
  110. static void iounit_get_scsi_sgl(struct scatterlist *sg, int sz, struct sbus_bus *sbus)
  111. {
  112. unsigned long flags;
  113. struct iounit_struct *iounit = (struct iounit_struct *)sbus->iommu;
  114. /* FIXME: Cache some resolved pages - often several sg entries are to the same page */
  115. spin_lock_irqsave(&iounit->lock, flags);
  116. for (; sz >= 0; sz--) {
  117. sg[sz].dvma_address = iounit_get_area(iounit, (unsigned long)sg[sz].address, sg[sz].length);
  118. sg[sz].dvma_length = sg[sz].length;
  119. }
  120. spin_unlock_irqrestore(&iounit->lock, flags);
  121. }
  122. static void iounit_release_scsi_one(__u32 vaddr, unsigned long len, struct sbus_bus *sbus)
  123. {
  124. unsigned long flags;
  125. struct iounit_struct *iounit = (struct iounit_struct *)sbus->iommu;
  126. spin_lock_irqsave(&iounit->lock, flags);
  127. len = ((vaddr & ~PAGE_MASK) + len + (PAGE_SIZE-1)) >> PAGE_SHIFT;
  128. vaddr = (vaddr - IOUNIT_DMA_BASE) >> PAGE_SHIFT;
  129. IOD(("iounit_release %08lx-%08lxn", (long)vaddr, (long)len+vaddr));
  130. for (len += vaddr; vaddr < len; vaddr++)
  131. clear_bit(vaddr, iounit->bmap);
  132. spin_unlock_irqrestore(&iounit->lock, flags);
  133. }
  134. static void iounit_release_scsi_sgl(struct scatterlist *sg, int sz, struct sbus_bus *sbus)
  135. {
  136. unsigned long flags;
  137. unsigned long vaddr, len;
  138. struct iounit_struct *iounit = (struct iounit_struct *)sbus->iommu;
  139. spin_lock_irqsave(&iounit->lock, flags);
  140. for (; sz >= 0; sz--) {
  141. len = ((sg[sz].dvma_address & ~PAGE_MASK) + sg[sz].length + (PAGE_SIZE-1)) >> PAGE_SHIFT;
  142. vaddr = (sg[sz].dvma_address - IOUNIT_DMA_BASE) >> PAGE_SHIFT;
  143. IOD(("iounit_release %08lx-%08lxn", (long)vaddr, (long)len+vaddr));
  144. for (len += vaddr; vaddr < len; vaddr++)
  145. clear_bit(vaddr, iounit->bmap);
  146. }
  147. spin_unlock_irqrestore(&iounit->lock, flags);
  148. }
  149. #ifdef CONFIG_SBUS
  150. static void iounit_map_dma_area(unsigned long va, __u32 addr, int len)
  151. {
  152. unsigned long page, end;
  153. pgprot_t dvma_prot;
  154. iopte_t *iopte;
  155. struct sbus_bus *sbus;
  156. dvma_prot = __pgprot(SRMMU_CACHE | SRMMU_ET_PTE | SRMMU_PRIV);
  157. end = PAGE_ALIGN((addr + len));
  158. while(addr < end) {
  159. page = va;
  160. {
  161. pgd_t *pgdp;
  162. pmd_t *pmdp;
  163. pte_t *ptep;
  164. long i;
  165. pgdp = pgd_offset(init_task.mm, addr);
  166. pmdp = pmd_offset(pgdp, addr);
  167. ptep = pte_offset(pmdp, addr);
  168. set_pte(ptep, pte_val(mk_pte(virt_to_page(page), dvma_prot)));
  169. i = ((addr - IOUNIT_DMA_BASE) >> PAGE_SHIFT);
  170. for_each_sbus(sbus) {
  171. struct iounit_struct *iounit = (struct iounit_struct *)sbus->iommu;
  172. iopte = (iopte_t *)(iounit->page_table + i);
  173. *iopte = __iopte(MKIOPTE(__pa(page)));
  174. }
  175. }
  176. addr += PAGE_SIZE;
  177. va += PAGE_SIZE;
  178. }
  179. flush_cache_all();
  180. flush_tlb_all();
  181. }
  182. static void iounit_unmap_dma_area(unsigned long addr, int len)
  183. {
  184. /* XXX Somebody please fill this in */
  185. }
  186. /* XXX We do not pass sbus device here, bad. */
  187. static unsigned long iounit_translate_dvma(unsigned long addr)
  188. {
  189. struct sbus_bus *sbus = sbus_root; /* They are all the same */
  190. struct iounit_struct *iounit = (struct iounit_struct *)sbus->iommu;
  191. int i;
  192. iopte_t *iopte;
  193. i = ((addr - IOUNIT_DMA_BASE) >> PAGE_SHIFT);
  194. iopte = (iopte_t *)(iounit->page_table + i);
  195. return (iopte_val(*iopte) & 0xFFFFFFF0) << 4; /* XXX sun4d guru, help */
  196. }
  197. #endif
  198. static char *iounit_lockarea(char *vaddr, unsigned long len)
  199. {
  200. /* FIXME: Write this */
  201. return vaddr;
  202. }
  203. static void iounit_unlockarea(char *vaddr, unsigned long len)
  204. {
  205. /* FIXME: Write this */
  206. }
  207. void __init ld_mmu_iounit(void)
  208. {
  209. BTFIXUPSET_CALL(mmu_lockarea, iounit_lockarea, BTFIXUPCALL_RETO0);
  210. BTFIXUPSET_CALL(mmu_unlockarea, iounit_unlockarea, BTFIXUPCALL_NOP);
  211. BTFIXUPSET_CALL(mmu_get_scsi_one, iounit_get_scsi_one, BTFIXUPCALL_NORM);
  212. BTFIXUPSET_CALL(mmu_get_scsi_sgl, iounit_get_scsi_sgl, BTFIXUPCALL_NORM);
  213. BTFIXUPSET_CALL(mmu_release_scsi_one, iounit_release_scsi_one, BTFIXUPCALL_NORM);
  214. BTFIXUPSET_CALL(mmu_release_scsi_sgl, iounit_release_scsi_sgl, BTFIXUPCALL_NORM);
  215. #ifdef CONFIG_SBUS
  216. BTFIXUPSET_CALL(mmu_map_dma_area, iounit_map_dma_area, BTFIXUPCALL_NORM);
  217. BTFIXUPSET_CALL(mmu_unmap_dma_area, iounit_unmap_dma_area, BTFIXUPCALL_NORM);
  218. BTFIXUPSET_CALL(mmu_translate_dvma, iounit_translate_dvma, BTFIXUPCALL_NORM);
  219. #endif
  220. }
  221. __u32 iounit_map_dma_init(struct sbus_bus *sbus, int size)
  222. {
  223. int i, j, k, npages;
  224. unsigned long rotor, scan, limit;
  225. unsigned long flags;
  226. __u32 ret;
  227. struct iounit_struct *iounit = (struct iounit_struct *)sbus->iommu;
  228.         npages = (size + (PAGE_SIZE-1)) >> PAGE_SHIFT;
  229. i = 0x0213;
  230. spin_lock_irqsave(&iounit->lock, flags);
  231. next: j = (i & 15);
  232. rotor = iounit->rotor[j - 1];
  233. limit = iounit->limit[j];
  234. scan = rotor;
  235. nexti: scan = find_next_zero_bit(iounit->bmap, limit, scan);
  236. if (scan + npages > limit) {
  237. if (limit != rotor) {
  238. limit = rotor;
  239. scan = iounit->limit[j - 1];
  240. goto nexti;
  241. }
  242. i >>= 4;
  243. if (!(i & 15))
  244. panic("iounit_map_dma_init: Couldn't find free iopte slots for %d bytesn", size);
  245. goto next;
  246. }
  247. for (k = 1, scan++; k < npages; k++)
  248. if (test_bit(scan++, iounit->bmap))
  249. goto nexti;
  250. iounit->rotor[j - 1] = (scan < limit) ? scan : iounit->limit[j - 1];
  251. scan -= npages;
  252. ret = IOUNIT_DMA_BASE + (scan << PAGE_SHIFT);
  253. for (k = 0; k < npages; k++, scan++)
  254. set_bit(scan, iounit->bmap);
  255. spin_unlock_irqrestore(&iounit->lock, flags);
  256. return ret;
  257. }
  258. __u32 iounit_map_dma_page(__u32 vaddr, void *addr, struct sbus_bus *sbus)
  259. {
  260. int scan = (vaddr - IOUNIT_DMA_BASE) >> PAGE_SHIFT;
  261. struct iounit_struct *iounit = (struct iounit_struct *)sbus->iommu;
  262. iounit->page_table[scan] = MKIOPTE(__pa(((unsigned long)addr) & PAGE_MASK));
  263. return vaddr + (((unsigned long)addr) & ~PAGE_MASK);
  264. }