This source file includes following definitions.
- vdma_init
- vdma_alloc
- vdma_free
- vdma_remap
- vdma_phys2log
- vdma_log2phys
- vdma_pgtbl_init
- vdma_stats
- vdma_enable
- vdma_disable
- vdma_set_mode
- vdma_set_addr
- vdma_set_count
- vdma_get_residue
1
2
3
4
5
6
7
8
9
10
11
12
13 #include <linux/kernel.h>
14 #include <linux/errno.h>
15 #include <asm/mipsregs.h>
16 #include <asm/mipsconfig.h>
17 #include <asm/jazz.h>
18 #include <asm/io.h>
19 #include <asm/segment.h>
20 #include <asm/dma.h>
21 #include <asm/jazzdma.h>
22
23
24 static unsigned long vdma_pagetable_start = 0;
25 static unsigned long vdma_pagetable_end = 0;
26
27
28
29
30 #define vdma_debug ((CONF_DEBUG_VDMA) ? debuglvl : 0)
31
32 static int debuglvl = 3;
33
34
35
36
37 static void vdma_pgtbl_init(void);
38
39
40
41
42 unsigned long vdma_init(unsigned long memory_start, unsigned long memory_end)
43 {
44
45
46
47
48
49
50 vdma_pagetable_start = KSEG1ADDR((memory_start + 4095) & ~4095);
51 vdma_pagetable_end = vdma_pagetable_start + VDMA_PGTBL_SIZE;
52
53
54
55
56 vdma_pgtbl_init();
57
58 r4030_write_reg32(JAZZ_R4030_TRSTBL_BASE,PHYSADDR(vdma_pagetable_start));
59 r4030_write_reg32(JAZZ_R4030_TRSTBL_LIM,VDMA_PGTBL_SIZE);
60 r4030_write_reg32(JAZZ_R4030_TRSTBL_INV,0);
61
62 printk("VDMA: R4030 DMA pagetables initialized.\n");
63 return KSEG0ADDR(vdma_pagetable_end);
64 }
65
66
67
68
69 unsigned long vdma_alloc(unsigned long paddr, unsigned long size)
70 {
71 VDMA_PGTBL_ENTRY *entry = (VDMA_PGTBL_ENTRY *)vdma_pagetable_start;
72 int first;
73 int last;
74 int pages;
75 unsigned int frame;
76 unsigned long laddr;
77 int i;
78
79
80
81 if (paddr > 0x1fffffff)
82 {
83 if (vdma_debug)
84 printk("vdma_alloc: Invalid physical address: %08lx\n",paddr);
85 return VDMA_ERROR;
86 }
87 if (size > 0x400000 || size == 0)
88 {
89 if (vdma_debug)
90 printk("vdma_alloc: Invalid size: %08lx\n",size);
91 return VDMA_ERROR;
92 }
93
94
95 pages = (size + 4095) >> 12;
96 first = 0;
97 while (1)
98 {
99 while (entry[first].owner != VDMA_PAGE_EMPTY &&
100 first < VDMA_PGTBL_ENTRIES)
101 first++;
102 if (first+pages > VDMA_PGTBL_ENTRIES)
103 return VDMA_ERROR;
104
105 last = first+1;
106 while (entry[last].owner == VDMA_PAGE_EMPTY && last-first < pages)
107 last++;
108
109 if (last-first == pages)
110 break;
111 }
112
113
114
115 laddr = (first << 12) + (paddr & (VDMA_PAGESIZE-1));
116 frame = paddr & ~(VDMA_PAGESIZE-1);
117
118 for (i=first; i<last; i++)
119 {
120 entry[i].frame = frame;
121 entry[i].owner = laddr;
122 frame += VDMA_PAGESIZE;
123 }
124
125
126
127
128
129 r4030_write_reg32(JAZZ_R4030_TRSTBL_INV,0);
130
131 if (vdma_debug > 1)
132 printk("vdma_alloc: Allocated %d pages starting from %08lx\n",
133 pages,laddr);
134
135 if (vdma_debug > 2)
136 {
137 printk("LADDR: ");
138 for (i=first; i<last; i++)
139 printk("%08x ",i<<12);
140 printk("\nPADDR: ");
141 for (i=first; i<last; i++)
142 printk("%08x ",entry[i].frame);
143 printk("\nOWNER: ");
144 for (i=first; i<last; i++)
145 printk("%08x ",entry[i].owner);
146 printk("\n");
147 }
148
149 return laddr;
150 }
151
152
153
154
155
156
157 int vdma_free(unsigned long laddr)
158 {
159 VDMA_PGTBL_ENTRY *pgtbl = (VDMA_PGTBL_ENTRY *)vdma_pagetable_start;
160 int i;
161
162 i = laddr >> 12;
163
164 if (pgtbl[i].owner != laddr)
165 {
166 printk("vdma_free: trying to free other's dma pages, laddr=%8lx\n",
167 laddr);
168 return -1;
169 }
170
171 while (pgtbl[i].owner == laddr && i < VDMA_PGTBL_ENTRIES)
172 {
173 pgtbl[i].owner = VDMA_PAGE_EMPTY;
174 i++;
175 }
176
177 if (vdma_debug > 1)
178 printk("vdma_free: freed %ld pages starting from %08lx\n",
179 i-(laddr>>12),laddr);
180
181 return 0;
182 }
183
184
185
186
187
188 int vdma_remap(unsigned long laddr, unsigned long paddr, unsigned long size)
189 {
190 VDMA_PGTBL_ENTRY *pgtbl = (VDMA_PGTBL_ENTRY *)vdma_pagetable_start;
191 int first;
192 int pages;
193
194 if (laddr > 0xffffff)
195 {
196 if (vdma_debug)
197 printk("vdma_map: Invalid logical address: %08lx\n",laddr);
198 return -EINVAL;
199 }
200 if (paddr > 0x1fffffff)
201 {
202 if (vdma_debug)
203 printk("vdma_map: Invalid physical address: %08lx\n",paddr);
204 return -EINVAL;
205 }
206
207 pages = (((paddr & (VDMA_PAGESIZE-1)) + size) >> 12) + 1;
208 first = laddr >> 12;
209 if (vdma_debug)
210 printk("vdma_remap: first=%x, pages=%x\n",first,pages);
211 if (first+pages > VDMA_PGTBL_ENTRIES)
212 {
213 if (vdma_debug)
214 printk("vdma_alloc: Invalid size: %08lx\n",size);
215 return -EINVAL;
216 }
217
218 paddr &= ~(VDMA_PAGESIZE-1);
219 while (pages > 0 && first < VDMA_PGTBL_ENTRIES)
220 {
221 if (pgtbl[first].owner != laddr)
222 {
223 if (vdma_debug)
224 printk("Trying to remap other's pages.\n");
225 return -EPERM;
226 }
227 pgtbl[first].frame = paddr;
228 paddr += VDMA_PAGESIZE;
229 first++;
230 pages--;
231 }
232
233
234
235 r4030_write_reg32(JAZZ_R4030_TRSTBL_INV,0);
236
237 if (vdma_debug > 2)
238 {
239 int i;
240 pages = (((paddr & (VDMA_PAGESIZE-1)) + size) >> 12) + 1;
241 first = laddr >> 12;
242 printk("LADDR: ");
243 for (i=first; i<first+pages; i++)
244 printk("%08x ",i<<12);
245 printk("\nPADDR: ");
246 for (i=first; i<first+pages; i++)
247 printk("%08x ",pgtbl[i].frame);
248 printk("\nOWNER: ");
249 for (i=first; i<first+pages; i++)
250 printk("%08x ",pgtbl[i].owner);
251 printk("\n");
252 }
253
254 return 0;
255 }
256
257
258
259
260
261
262 unsigned long vdma_phys2log(unsigned long paddr)
263 {
264 int i;
265 int frame;
266 VDMA_PGTBL_ENTRY *pgtbl = (VDMA_PGTBL_ENTRY *)vdma_pagetable_start;
267
268 frame = paddr & ~(VDMA_PAGESIZE-1);
269
270 for (i=0; i<VDMA_PGTBL_ENTRIES; i++)
271 {
272 if (pgtbl[i].frame == frame)
273 break;
274 }
275
276 if (i == VDMA_PGTBL_ENTRIES)
277 return 0xffffffff;
278
279 return (i<<12) + (paddr & (VDMA_PAGESIZE-1));
280 }
281
282
283
284
285 unsigned long vdma_log2phys(unsigned long laddr)
286 {
287 VDMA_PGTBL_ENTRY *pgtbl = (VDMA_PGTBL_ENTRY *)vdma_pagetable_start;
288
289 return pgtbl[laddr >> 12].frame + (laddr & (VDMA_PAGESIZE-1));
290 }
291
292
293
294
295
296
297
298 static void vdma_pgtbl_init(void)
299 {
300 int i;
301 unsigned long paddr = 0;
302 VDMA_PGTBL_ENTRY *pgtbl = (VDMA_PGTBL_ENTRY *)vdma_pagetable_start;
303
304 for (i=0; i<VDMA_PGTBL_ENTRIES; i++)
305 {
306 pgtbl[i].frame = paddr;
307 pgtbl[i].owner = VDMA_PAGE_EMPTY;
308 paddr += VDMA_PAGESIZE;
309 }
310
311
312 }
313
314
315
316
317 void vdma_stats(void)
318 {
319 int i;
320
321 printk("vdma_stats: CONFIG: %08x\n",
322 r4030_read_reg32(JAZZ_R4030_CONFIG));
323 printk("R4030 translation table base: %08x\n",
324 r4030_read_reg32(JAZZ_R4030_TRSTBL_BASE));
325 printk("R4030 translation table limit: %08x\n",
326 r4030_read_reg32(JAZZ_R4030_TRSTBL_LIM));
327 printk("vdma_stats: INV_ADDR: %08x\n",
328 r4030_read_reg32(JAZZ_R4030_INV_ADDR));
329 printk("vdma_stats: R_FAIL_ADDR: %08x\n",
330 r4030_read_reg32(JAZZ_R4030_R_FAIL_ADDR));
331 printk("vdma_stats: M_FAIL_ADDR: %08x\n",
332 r4030_read_reg32(JAZZ_R4030_M_FAIL_ADDR));
333 printk("vdma_stats: IRQ_SOURCE: %08x\n",
334 r4030_read_reg32(JAZZ_R4030_IRQ_SOURCE));
335 printk("vdma_stats: I386_ERROR: %08x\n",
336 r4030_read_reg32(JAZZ_R4030_I386_ERROR));
337 printk("vdma_chnl_modes: ");
338 for (i=0; i<8; i++)
339 printk("%04x ",
340 (unsigned)r4030_read_reg32(JAZZ_R4030_CHNL_MODE+(i<<5)));
341 printk("\n");
342 printk("vdma_chnl_enables: ");
343 for (i=0; i<8; i++)
344 printk("%04x ",
345 (unsigned)r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE+(i<<5)));
346 printk("\n");
347 }
348
349
350
351
352
353
354
355
356 void vdma_enable(int channel)
357 {
358 int status;
359
360 if (vdma_debug)
361 printk("vdma_enable: channel %d\n",channel);
362
363
364
365
366 status = r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5));
367 if (status & 0x400)
368 printk("VDMA: Channel %d: Address error!\n",channel);
369 if (status & 0x200)
370 printk("VDMA: Channel %d: Memory error!\n",channel);
371
372
373
374
375 r4030_write_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5),
376 R4030_TC_INTR | R4030_MEM_INTR | R4030_ADDR_INTR);
377
378
379
380
381 r4030_write_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5),
382 r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5)) |
383 R4030_CHNL_ENABLE);
384 }
385
386
387
388
389 void vdma_disable(int channel)
390 {
391 if (vdma_debug)
392 {
393 int status = r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5));
394
395 printk("vdma_disable: channel %d\n",channel);
396 printk("VDMA: channel %d status: %04x (%s) mode: "
397 "%02x addr: %06x count: %06x\n",
398 channel,status,((status & 0x600) ? "ERROR" : "OK"),
399 (unsigned)r4030_read_reg32(JAZZ_R4030_CHNL_MODE+(channel<<5)),
400 (unsigned)r4030_read_reg32(JAZZ_R4030_CHNL_ADDR+(channel<<5)),
401 (unsigned)r4030_read_reg32(JAZZ_R4030_CHNL_COUNT+(channel<<5)));
402 }
403
404 r4030_write_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5),
405 r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5)) &
406 ~R4030_CHNL_ENABLE);
407
408
409
410
411
412 *((volatile unsigned int *)JAZZ_DUMMY_DEVICE);
413 }
414
415
416
417
418
419
420
421
422
423
424 void vdma_set_mode(int channel, int mode)
425 {
426 if (vdma_debug)
427 printk("vdma_set_mode: channel %d, mode 0x%x\n",channel,mode);
428
429 switch(channel)
430 {
431 case JAZZ_SCSI_DMA:
432 r4030_write_reg32(JAZZ_R4030_CHNL_MODE+(channel<<5),
433
434
435 R4030_MODE_INTR_EN |
436 R4030_MODE_WIDTH_16 |
437 R4030_MODE_ATIME_80);
438 break;
439
440 case JAZZ_FLOPPY_DMA:
441 r4030_write_reg32(JAZZ_R4030_CHNL_MODE+(channel<<5),
442
443
444 R4030_MODE_INTR_EN |
445 R4030_MODE_WIDTH_8 |
446 R4030_MODE_ATIME_120);
447 break;
448
449 case JAZZ_AUDIOL_DMA:
450 case JAZZ_AUDIOR_DMA:
451 printk("VDMA: Audio DMA not supported yet.\n");
452 break;
453
454 default:
455 printk("VDMA: vdma_set_mode() called with unsupported channel %d!\n",
456 channel);
457 }
458
459 switch(mode)
460 {
461 case DMA_MODE_READ:
462 r4030_write_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5),
463 r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5)) &
464 ~R4030_CHNL_WRITE);
465 break;
466
467 case DMA_MODE_WRITE:
468 r4030_write_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5),
469 r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE+(channel<<5)) |
470 R4030_CHNL_WRITE);
471 break;
472
473 default:
474 printk("VDMA: vdma_set_mode() called with unknown dma mode 0x%x\n",mode);
475 }
476 }
477
478
479
480
481 void vdma_set_addr(int channel, long addr)
482 {
483 if (vdma_debug)
484 printk("vdma_set_addr: channel %d, addr %lx\n",channel,addr);
485
486 r4030_write_reg32(JAZZ_R4030_CHNL_ADDR+(channel<<5),addr);
487 }
488
489
490
491
492 void vdma_set_count(int channel, int count)
493 {
494 if (vdma_debug)
495 printk("vdma_set_count: channel %d, count %08x\n",channel,(unsigned)count);
496
497 r4030_write_reg32(JAZZ_R4030_CHNL_COUNT+(channel<<5),count);
498 }
499
500
501
502
503 int vdma_get_residue(int channel)
504 {
505 int residual;
506
507 residual = r4030_read_reg32(JAZZ_R4030_CHNL_COUNT+(channel<<5));
508
509 if (vdma_debug)
510 printk("vdma_get_residual: channel %d: residual=%d\n",channel,residual);
511
512 return residual;
513 }