Back to home page

LXR

 
 

    


0001 /*
0002  * linux/kernel/dma.c: A DMA channel allocator. Inspired by linux/kernel/irq.c.
0003  *
0004  * Written by Hennus Bergman, 1992.
0005  *
0006  * 1994/12/26: Changes by Alex Nash to fix a minor bug in /proc/dma.
0007  *   In the previous version the reported device could end up being wrong,
0008  *   if a device requested a DMA channel that was already in use.
0009  *   [It also happened to remove the sizeof(char *) == sizeof(int)
0010  *   assumption introduced because of those /proc/dma patches. -- Hennus]
0011  */
0012 #include <linux/export.h>
0013 #include <linux/kernel.h>
0014 #include <linux/errno.h>
0015 #include <linux/spinlock.h>
0016 #include <linux/string.h>
0017 #include <linux/seq_file.h>
0018 #include <linux/proc_fs.h>
0019 #include <linux/init.h>
0020 #include <asm/dma.h>
0021 
0022 
0023 
0024 /* A note on resource allocation:
0025  *
0026  * All drivers needing DMA channels, should allocate and release them
0027  * through the public routines `request_dma()' and `free_dma()'.
0028  *
0029  * In order to avoid problems, all processes should allocate resources in
0030  * the same sequence and release them in the reverse order.
0031  *
0032  * So, when allocating DMAs and IRQs, first allocate the IRQ, then the DMA.
0033  * When releasing them, first release the DMA, then release the IRQ.
0034  * If you don't, you may cause allocation requests to fail unnecessarily.
0035  * This doesn't really matter now, but it will once we get real semaphores
0036  * in the kernel.
0037  */
0038 
0039 
0040 DEFINE_SPINLOCK(dma_spin_lock);
0041 
0042 /*
0043  *  If our port doesn't define this it has no PC like DMA
0044  */
0045 
0046 #ifdef MAX_DMA_CHANNELS
0047 
0048 
0049 /* Channel n is busy iff dma_chan_busy[n].lock != 0.
0050  * DMA0 used to be reserved for DRAM refresh, but apparently not any more...
0051  * DMA4 is reserved for cascading.
0052  */
0053 
0054 struct dma_chan {
0055     int  lock;
0056     const char *device_id;
0057 };
0058 
0059 static struct dma_chan dma_chan_busy[MAX_DMA_CHANNELS] = {
0060     [4] = { 1, "cascade" },
0061 };
0062 
0063 
0064 /**
0065  * request_dma - request and reserve a system DMA channel
0066  * @dmanr: DMA channel number
0067  * @device_id: reserving device ID string, used in /proc/dma
0068  */
0069 int request_dma(unsigned int dmanr, const char * device_id)
0070 {
0071     if (dmanr >= MAX_DMA_CHANNELS)
0072         return -EINVAL;
0073 
0074     if (xchg(&dma_chan_busy[dmanr].lock, 1) != 0)
0075         return -EBUSY;
0076 
0077     dma_chan_busy[dmanr].device_id = device_id;
0078 
0079     /* old flag was 0, now contains 1 to indicate busy */
0080     return 0;
0081 } /* request_dma */
0082 
0083 /**
0084  * free_dma - free a reserved system DMA channel
0085  * @dmanr: DMA channel number
0086  */
0087 void free_dma(unsigned int dmanr)
0088 {
0089     if (dmanr >= MAX_DMA_CHANNELS) {
0090         printk(KERN_WARNING "Trying to free DMA%d\n", dmanr);
0091         return;
0092     }
0093 
0094     if (xchg(&dma_chan_busy[dmanr].lock, 0) == 0) {
0095         printk(KERN_WARNING "Trying to free free DMA%d\n", dmanr);
0096         return;
0097     }
0098 
0099 } /* free_dma */
0100 
0101 #else
0102 
0103 int request_dma(unsigned int dmanr, const char *device_id)
0104 {
0105     return -EINVAL;
0106 }
0107 
0108 void free_dma(unsigned int dmanr)
0109 {
0110 }
0111 
0112 #endif
0113 
0114 #ifdef CONFIG_PROC_FS
0115 
0116 #ifdef MAX_DMA_CHANNELS
0117 static int proc_dma_show(struct seq_file *m, void *v)
0118 {
0119     int i;
0120 
0121     for (i = 0 ; i < MAX_DMA_CHANNELS ; i++) {
0122         if (dma_chan_busy[i].lock) {
0123             seq_printf(m, "%2d: %s\n", i,
0124                    dma_chan_busy[i].device_id);
0125         }
0126     }
0127     return 0;
0128 }
0129 #else
0130 static int proc_dma_show(struct seq_file *m, void *v)
0131 {
0132     seq_puts(m, "No DMA\n");
0133     return 0;
0134 }
0135 #endif /* MAX_DMA_CHANNELS */
0136 
0137 static int proc_dma_open(struct inode *inode, struct file *file)
0138 {
0139     return single_open(file, proc_dma_show, NULL);
0140 }
0141 
0142 static const struct file_operations proc_dma_operations = {
0143     .open       = proc_dma_open,
0144     .read       = seq_read,
0145     .llseek     = seq_lseek,
0146     .release    = single_release,
0147 };
0148 
0149 static int __init proc_dma_init(void)
0150 {
0151     proc_create("dma", 0, NULL, &proc_dma_operations);
0152     return 0;
0153 }
0154 
0155 __initcall(proc_dma_init);
0156 #endif
0157 
0158 EXPORT_SYMBOL(request_dma);
0159 EXPORT_SYMBOL(free_dma);
0160 EXPORT_SYMBOL(dma_spin_lock);