|
|
1.1 ! root 1: /* $Id: dma.c,v 1.1 1999/04/26 05:58:29 tb Exp $ ! 2: * linux/kernel/dma.c: A DMA channel allocator. Inspired by linux/kernel/irq.c. ! 3: * ! 4: * Written by Hennus Bergman, 1992. ! 5: * ! 6: * 1994/12/26: Changes by Alex Nash to fix a minor bug in /proc/dma. ! 7: * In the previous version the reported device could end up being wrong, ! 8: * if a device requested a DMA channel that was already in use. ! 9: * [It also happened to remove the sizeof(char *) == sizeof(int) ! 10: * assumption introduced because of those /proc/dma patches. -- Hennus] ! 11: */ ! 12: ! 13: #include <linux/kernel.h> ! 14: #include <linux/errno.h> ! 15: #include <asm/dma.h> ! 16: #include <asm/system.h> ! 17: ! 18: ! 19: /* A note on resource allocation: ! 20: * ! 21: * All drivers needing DMA channels, should allocate and release them ! 22: * through the public routines `request_dma()' and `free_dma()'. ! 23: * ! 24: * In order to avoid problems, all processes should allocate resources in ! 25: * the same sequence and release them in the reverse order. ! 26: * ! 27: * So, when allocating DMAs and IRQs, first allocate the IRQ, then the DMA. ! 28: * When releasing them, first release the DMA, then release the IRQ. ! 29: * If you don't, you may cause allocation requests to fail unnecessarily. ! 30: * This doesn't really matter now, but it will once we get real semaphores ! 31: * in the kernel. ! 32: */ ! 33: ! 34: ! 35: ! 36: /* Channel n is busy iff dma_chan_busy[n].lock != 0. ! 37: * DMA0 used to be reserved for DRAM refresh, but apparently not any more... ! 38: * DMA4 is reserved for cascading. ! 39: */ ! 40: ! 41: struct dma_chan { ! 42: int lock; ! 43: const char *device_id; ! 44: }; ! 45: ! 46: static struct dma_chan dma_chan_busy[MAX_DMA_CHANNELS] = { ! 47: { 0, 0 }, ! 48: { 0, 0 }, ! 49: { 0, 0 }, ! 50: { 0, 0 }, ! 51: { 1, "cascade" }, ! 52: { 0, 0 }, ! 53: { 0, 0 }, ! 54: { 0, 0 } ! 55: }; ! 56: ! 57: int get_dma_list(char *buf) ! 58: { ! 59: int i, len = 0; ! 60: ! 61: for (i = 0 ; i < MAX_DMA_CHANNELS ; i++) { ! 62: if (dma_chan_busy[i].lock) { ! 63: len += sprintf(buf+len, "%2d: %s\n", ! 64: i, ! 65: dma_chan_busy[i].device_id); ! 66: } ! 67: } ! 68: return len; ! 69: } /* get_dma_list */ ! 70: ! 71: ! 72: int request_dma(unsigned int dmanr, const char * device_id) ! 73: { ! 74: if (dmanr >= MAX_DMA_CHANNELS) ! 75: return -EINVAL; ! 76: ! 77: if (xchg(&dma_chan_busy[dmanr].lock, 1) != 0) ! 78: return -EBUSY; ! 79: ! 80: dma_chan_busy[dmanr].device_id = device_id; ! 81: ! 82: /* old flag was 0, now contains 1 to indicate busy */ ! 83: return 0; ! 84: } /* request_dma */ ! 85: ! 86: ! 87: void free_dma(unsigned int dmanr) ! 88: { ! 89: if (dmanr >= MAX_DMA_CHANNELS) { ! 90: printk("Trying to free DMA%d\n", dmanr); ! 91: return; ! 92: } ! 93: ! 94: if (xchg(&dma_chan_busy[dmanr].lock, 0) == 0) { ! 95: printk("Trying to free free DMA%d\n", dmanr); ! 96: return; ! 97: } ! 98: ! 99: } /* free_dma */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.