sparc32: Make mmu_map_dma_area and mmu_unmap_dma_area take a device pointer.
[linux-2.6-block.git] / arch / sparc / mm / io-unit.c
1 /*
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/kernel.h>
8 #include <linux/init.h>
9 #include <linux/slab.h>
10 #include <linux/spinlock.h>
11 #include <linux/mm.h>
12 #include <linux/highmem.h>      /* pte_offset_map => kmap_atomic */
13 #include <linux/bitops.h>
14 #include <linux/scatterlist.h>
15
16 #include <asm/pgalloc.h>
17 #include <asm/pgtable.h>
18 #include <asm/sbus.h>
19 #include <asm/io.h>
20 #include <asm/io-unit.h>
21 #include <asm/mxcc.h>
22 #include <asm/cacheflush.h>
23 #include <asm/tlbflush.h>
24 #include <asm/dma.h>
25 #include <asm/oplib.h>
26
27 /* #define IOUNIT_DEBUG */
28 #ifdef IOUNIT_DEBUG
29 #define IOD(x) printk(x)
30 #else
31 #define IOD(x) do { } while (0)
32 #endif
33
34 #define IOPERM        (IOUPTE_CACHE | IOUPTE_WRITE | IOUPTE_VALID)
35 #define MKIOPTE(phys) __iopte((((phys)>>4) & IOUPTE_PAGE) | IOPERM)
36
37 void __init iounit_init(struct sbus_bus *sbus)
38 {
39         struct device_node *dp = sbus->ofdev.node;
40         struct iounit_struct *iounit;
41         iopte_t *xpt, *xptend;
42         struct of_device *op;
43
44         op = of_find_device_by_node(dp);
45         if (!op) {
46                 prom_printf("SUN4D: Cannot find SBI of_device.\n");
47                 prom_halt();
48         }
49
50         iounit = kzalloc(sizeof(struct iounit_struct), GFP_ATOMIC);
51         if (!iounit) {
52                 prom_printf("SUN4D: Cannot alloc iounit, halting.\n");
53                 prom_halt();
54         }
55
56         iounit->limit[0] = IOUNIT_BMAP1_START;
57         iounit->limit[1] = IOUNIT_BMAP2_START;
58         iounit->limit[2] = IOUNIT_BMAPM_START;
59         iounit->limit[3] = IOUNIT_BMAPM_END;
60         iounit->rotor[1] = IOUNIT_BMAP2_START;
61         iounit->rotor[2] = IOUNIT_BMAPM_START;
62
63         xpt = of_ioremap(&op->resource[2], 0, PAGE_SIZE * 16, "XPT");
64         if (!xpt) {
65                 prom_printf("SUN4D: Cannot map External Page Table.");
66                 prom_halt();
67         }
68         
69         sbus->ofdev.dev.archdata.iommu = iounit;
70         op->dev.archdata.iommu = iounit;
71         iounit->page_table = xpt;
72         spin_lock_init(&iounit->lock);
73         
74         for (xptend = iounit->page_table + (16 * PAGE_SIZE) / sizeof(iopte_t);
75              xpt < xptend;)
76                 iopte_val(*xpt++) = 0;
77 }
78
79 /* One has to hold iounit->lock to call this */
80 static unsigned long iounit_get_area(struct iounit_struct *iounit, unsigned long vaddr, int size)
81 {
82         int i, j, k, npages;
83         unsigned long rotor, scan, limit;
84         iopte_t iopte;
85
86         npages = ((vaddr & ~PAGE_MASK) + size + (PAGE_SIZE-1)) >> PAGE_SHIFT;
87
88         /* A tiny bit of magic ingredience :) */
89         switch (npages) {
90         case 1: i = 0x0231; break;
91         case 2: i = 0x0132; break;
92         default: i = 0x0213; break;
93         }
94         
95         IOD(("iounit_get_area(%08lx,%d[%d])=", vaddr, size, npages));
96         
97 next:   j = (i & 15);
98         rotor = iounit->rotor[j - 1];
99         limit = iounit->limit[j];
100         scan = rotor;
101 nexti:  scan = find_next_zero_bit(iounit->bmap, limit, scan);
102         if (scan + npages > limit) {
103                 if (limit != rotor) {
104                         limit = rotor;
105                         scan = iounit->limit[j - 1];
106                         goto nexti;
107                 }
108                 i >>= 4;
109                 if (!(i & 15))
110                         panic("iounit_get_area: Couldn't find free iopte slots for (%08lx,%d)\n", vaddr, size);
111                 goto next;
112         }
113         for (k = 1, scan++; k < npages; k++)
114                 if (test_bit(scan++, iounit->bmap))
115                         goto nexti;
116         iounit->rotor[j - 1] = (scan < limit) ? scan : iounit->limit[j - 1];
117         scan -= npages;
118         iopte = MKIOPTE(__pa(vaddr & PAGE_MASK));
119         vaddr = IOUNIT_DMA_BASE + (scan << PAGE_SHIFT) + (vaddr & ~PAGE_MASK);
120         for (k = 0; k < npages; k++, iopte = __iopte(iopte_val(iopte) + 0x100), scan++) {
121                 set_bit(scan, iounit->bmap);
122                 iounit->page_table[scan] = iopte;
123         }
124         IOD(("%08lx\n", vaddr));
125         return vaddr;
126 }
127
128 static __u32 iounit_get_scsi_one(struct device *dev, char *vaddr, unsigned long len)
129 {
130         struct iounit_struct *iounit = dev->archdata.iommu;
131         unsigned long ret, flags;
132         
133         spin_lock_irqsave(&iounit->lock, flags);
134         ret = iounit_get_area(iounit, (unsigned long)vaddr, len);
135         spin_unlock_irqrestore(&iounit->lock, flags);
136         return ret;
137 }
138
139 static void iounit_get_scsi_sgl(struct device *dev, struct scatterlist *sg, int sz)
140 {
141         struct iounit_struct *iounit = dev->archdata.iommu;
142         unsigned long flags;
143
144         /* FIXME: Cache some resolved pages - often several sg entries are to the same page */
145         spin_lock_irqsave(&iounit->lock, flags);
146         while (sz != 0) {
147                 --sz;
148                 sg->dvma_address = iounit_get_area(iounit, (unsigned long) sg_virt(sg), sg->length);
149                 sg->dvma_length = sg->length;
150                 sg = sg_next(sg);
151         }
152         spin_unlock_irqrestore(&iounit->lock, flags);
153 }
154
155 static void iounit_release_scsi_one(struct device *dev, __u32 vaddr, unsigned long len)
156 {
157         struct iounit_struct *iounit = dev->archdata.iommu;
158         unsigned long flags;
159         
160         spin_lock_irqsave(&iounit->lock, flags);
161         len = ((vaddr & ~PAGE_MASK) + len + (PAGE_SIZE-1)) >> PAGE_SHIFT;
162         vaddr = (vaddr - IOUNIT_DMA_BASE) >> PAGE_SHIFT;
163         IOD(("iounit_release %08lx-%08lx\n", (long)vaddr, (long)len+vaddr));
164         for (len += vaddr; vaddr < len; vaddr++)
165                 clear_bit(vaddr, iounit->bmap);
166         spin_unlock_irqrestore(&iounit->lock, flags);
167 }
168
169 static void iounit_release_scsi_sgl(struct device *dev, struct scatterlist *sg, int sz)
170 {
171         struct iounit_struct *iounit = dev->archdata.iommu;
172         unsigned long flags;
173         unsigned long vaddr, len;
174
175         spin_lock_irqsave(&iounit->lock, flags);
176         while (sz != 0) {
177                 --sz;
178                 len = ((sg->dvma_address & ~PAGE_MASK) + sg->length + (PAGE_SIZE-1)) >> PAGE_SHIFT;
179                 vaddr = (sg->dvma_address - IOUNIT_DMA_BASE) >> PAGE_SHIFT;
180                 IOD(("iounit_release %08lx-%08lx\n", (long)vaddr, (long)len+vaddr));
181                 for (len += vaddr; vaddr < len; vaddr++)
182                         clear_bit(vaddr, iounit->bmap);
183                 sg = sg_next(sg);
184         }
185         spin_unlock_irqrestore(&iounit->lock, flags);
186 }
187
188 #ifdef CONFIG_SBUS
189 static int iounit_map_dma_area(struct device *dev, dma_addr_t *pba, unsigned long va, __u32 addr, int len)
190 {
191         struct iounit_struct *iounit = dev->archdata.iommu;
192         unsigned long page, end;
193         pgprot_t dvma_prot;
194         iopte_t *iopte;
195
196         *pba = addr;
197
198         dvma_prot = __pgprot(SRMMU_CACHE | SRMMU_ET_PTE | SRMMU_PRIV);
199         end = PAGE_ALIGN((addr + len));
200         while(addr < end) {
201                 page = va;
202                 {
203                         pgd_t *pgdp;
204                         pmd_t *pmdp;
205                         pte_t *ptep;
206                         long i;
207
208                         pgdp = pgd_offset(&init_mm, addr);
209                         pmdp = pmd_offset(pgdp, addr);
210                         ptep = pte_offset_map(pmdp, addr);
211
212                         set_pte(ptep, mk_pte(virt_to_page(page), dvma_prot));
213                         
214                         i = ((addr - IOUNIT_DMA_BASE) >> PAGE_SHIFT);
215
216                         iopte = (iopte_t *)(iounit->page_table + i);
217                         *iopte = MKIOPTE(__pa(page));
218                 }
219                 addr += PAGE_SIZE;
220                 va += PAGE_SIZE;
221         }
222         flush_cache_all();
223         flush_tlb_all();
224
225         return 0;
226 }
227
228 static void iounit_unmap_dma_area(struct device *dev, unsigned long addr, int len)
229 {
230         /* XXX Somebody please fill this in */
231 }
232 #endif
233
234 static char *iounit_lockarea(char *vaddr, unsigned long len)
235 {
236 /* FIXME: Write this */
237         return vaddr;
238 }
239
240 static void iounit_unlockarea(char *vaddr, unsigned long len)
241 {
242 /* FIXME: Write this */
243 }
244
245 void __init ld_mmu_iounit(void)
246 {
247         BTFIXUPSET_CALL(mmu_lockarea, iounit_lockarea, BTFIXUPCALL_RETO0);
248         BTFIXUPSET_CALL(mmu_unlockarea, iounit_unlockarea, BTFIXUPCALL_NOP);
249
250         BTFIXUPSET_CALL(mmu_get_scsi_one, iounit_get_scsi_one, BTFIXUPCALL_NORM);
251         BTFIXUPSET_CALL(mmu_get_scsi_sgl, iounit_get_scsi_sgl, BTFIXUPCALL_NORM);
252         BTFIXUPSET_CALL(mmu_release_scsi_one, iounit_release_scsi_one, BTFIXUPCALL_NORM);
253         BTFIXUPSET_CALL(mmu_release_scsi_sgl, iounit_release_scsi_sgl, BTFIXUPCALL_NORM);
254
255 #ifdef CONFIG_SBUS
256         BTFIXUPSET_CALL(mmu_map_dma_area, iounit_map_dma_area, BTFIXUPCALL_NORM);
257         BTFIXUPSET_CALL(mmu_unmap_dma_area, iounit_unmap_dma_area, BTFIXUPCALL_NORM);
258 #endif
259 }
260
261 __u32 iounit_map_dma_init(struct sbus_bus *sbus, int size)
262 {
263         int i, j, k, npages;
264         unsigned long rotor, scan, limit;
265         unsigned long flags;
266         __u32 ret;
267         struct iounit_struct *iounit = sbus->ofdev.dev.archdata.iommu;
268
269         npages = (size + (PAGE_SIZE-1)) >> PAGE_SHIFT;
270         i = 0x0213;
271         spin_lock_irqsave(&iounit->lock, flags);
272 next:   j = (i & 15);
273         rotor = iounit->rotor[j - 1];
274         limit = iounit->limit[j];
275         scan = rotor;
276 nexti:  scan = find_next_zero_bit(iounit->bmap, limit, scan);
277         if (scan + npages > limit) {
278                 if (limit != rotor) {
279                         limit = rotor;
280                         scan = iounit->limit[j - 1];
281                         goto nexti;
282                 }
283                 i >>= 4;
284                 if (!(i & 15))
285                         panic("iounit_map_dma_init: Couldn't find free iopte slots for %d bytes\n", size);
286                 goto next;
287         }
288         for (k = 1, scan++; k < npages; k++)
289                 if (test_bit(scan++, iounit->bmap))
290                         goto nexti;
291         iounit->rotor[j - 1] = (scan < limit) ? scan : iounit->limit[j - 1];
292         scan -= npages;
293         ret = IOUNIT_DMA_BASE + (scan << PAGE_SHIFT);
294         for (k = 0; k < npages; k++, scan++)
295                 set_bit(scan, iounit->bmap);
296         spin_unlock_irqrestore(&iounit->lock, flags);
297         return ret;
298 }
299
300 __u32 iounit_map_dma_page(__u32 vaddr, void *addr, struct sbus_bus *sbus)
301 {
302         int scan = (vaddr - IOUNIT_DMA_BASE) >> PAGE_SHIFT;
303         struct iounit_struct *iounit = sbus->ofdev.dev.archdata.iommu;
304         
305         iounit->page_table[scan] = MKIOPTE(__pa(((unsigned long)addr) & PAGE_MASK));
306         return vaddr + (((unsigned long)addr) & ~PAGE_MASK);
307 }