|
|
1.1 ! root 1: /* $Id: dma.c,v 1.1 1999/04/26 05:49:35 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: #define MACH_INCLUDE ! 14: #include <linux/kernel.h> ! 15: #include <linux/errno.h> ! 16: #include <asm/dma.h> ! 17: #include <asm/system.h> ! 18: ! 19: ! 20: /* A note on resource allocation: ! 21: * ! 22: * All drivers needing DMA channels, should allocate and release them ! 23: * through the public routines `request_dma()' and `free_dma()'. ! 24: * ! 25: * In order to avoid problems, all processes should allocate resources in ! 26: * the same sequence and release them in the reverse order. ! 27: * ! 28: * So, when allocating DMAs and IRQs, first allocate the IRQ, then the DMA. ! 29: * When releasing them, first release the DMA, then release the IRQ. ! 30: * If you don't, you may cause allocation requests to fail unnecessarily. ! 31: * This doesn't really matter now, but it will once we get real semaphores ! 32: * in the kernel. ! 33: */ ! 34: ! 35: ! 36: ! 37: /* Channel n is busy iff dma_chan_busy[n].lock != 0. ! 38: * DMA0 used to be reserved for DRAM refresh, but apparently not any more... ! 39: * DMA4 is reserved for cascading. ! 40: */ ! 41: ! 42: struct dma_chan ! 43: { ! 44: int lock; ! 45: const char *device_id; ! 46: }; ! 47: ! 48: static struct dma_chan dma_chan_busy[MAX_DMA_CHANNELS] = ! 49: { ! 50: { 0, 0 }, ! 51: { 0, 0 }, ! 52: { 0, 0 }, ! 53: { 0, 0 }, ! 54: { 1, "cascade" }, ! 55: { 0, 0 }, ! 56: { 0, 0 }, ! 57: { 0, 0 } ! 58: }; ! 59: ! 60: #ifndef MACH ! 61: int ! 62: get_dma_list (char *buf) ! 63: { ! 64: int i, len = 0; ! 65: ! 66: for (i = 0 ; i < MAX_DMA_CHANNELS ; i++) ! 67: { ! 68: if (dma_chan_busy[i].lock) ! 69: { ! 70: len += linux_sprintf (buf+len, "%2d: %s\n", ! 71: i, ! 72: dma_chan_busy[i].device_id); ! 73: } ! 74: } ! 75: return len; ! 76: } /* get_dma_list */ ! 77: #endif ! 78: ! 79: int ! 80: request_dma (unsigned int dmanr, const char *device_id) ! 81: { ! 82: if (dmanr >= MAX_DMA_CHANNELS) ! 83: return -LINUX_EINVAL; ! 84: ! 85: if (xchg (&dma_chan_busy[dmanr].lock, 1) != 0) ! 86: return -LINUX_EBUSY; ! 87: ! 88: dma_chan_busy[dmanr].device_id = device_id; ! 89: ! 90: /* old flag was 0, now contains 1 to indicate busy */ ! 91: return 0; ! 92: } /* request_dma */ ! 93: ! 94: ! 95: void ! 96: free_dma (unsigned int dmanr) ! 97: { ! 98: if (dmanr >= MAX_DMA_CHANNELS) ! 99: { ! 100: printk ("Trying to free DMA%d\n", dmanr); ! 101: return; ! 102: } ! 103: ! 104: if (xchg (&dma_chan_busy[dmanr].lock, 0) == 0) ! 105: { ! 106: printk ("Trying to free free DMA%d\n", dmanr); ! 107: return; ! 108: } ! 109: } /* free_dma */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.