Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  1 /*
  2  *  linux/arch/arm/kernel/dma.c
  3  *
  4  *  Copyright (C) 1995-2000 Russell King
  5  *
  6  * This program is free software; you can redistribute it and/or modify
  7  * it under the terms of the GNU General Public License version 2 as
  8  * published by the Free Software Foundation.
  9  *
 10  *  Front-end to the DMA handling.  This handles the allocation/freeing
 11  *  of DMA channels, and provides a unified interface to the machines
 12  *  DMA facilities.
 13  */
 14 #include <linux/module.h>
 15 #include <linux/init.h>
 16 #include <linux/spinlock.h>
 17 #include <linux/errno.h>
 18 #include <linux/scatterlist.h>
 19 
 20 #include <asm/dma.h>
 21 
 22 #include <asm/mach/dma.h>
 23 
 24 DEFINE_SPINLOCK(dma_spin_lock);
 25 EXPORT_SYMBOL(dma_spin_lock);
 26 
 27 static dma_t *dma_chan[MAX_DMA_CHANNELS];
 28 
 29 static inline dma_t *dma_channel(unsigned int chan)
 30 {
 31         if (chan >= MAX_DMA_CHANNELS)
 32                 return NULL;
 33 
 34         return dma_chan[chan];
 35 }
 36 
 37 int __init isa_dma_add(unsigned int chan, dma_t *dma)
 38 {
 39         if (!dma->d_ops)
 40                 return -EINVAL;
 41 
 42         sg_init_table(&dma->buf, 1);
 43 
 44         if (dma_chan[chan])
 45                 return -EBUSY;
 46         dma_chan[chan] = dma;
 47         return 0;
 48 }
 49 
 50 /*
 51  * Request DMA channel
 52  *
 53  * On certain platforms, we have to allocate an interrupt as well...
 54  */
 55 int request_dma(unsigned int chan, const char *device_id)
 56 {
 57         dma_t *dma = dma_channel(chan);
 58         int ret;
 59 
 60         if (!dma)
 61                 goto bad_dma;
 62 
 63         if (xchg(&dma->lock, 1) != 0)
 64                 goto busy;
 65 
 66         dma->device_id = device_id;
 67         dma->active    = 0;
 68         dma->invalid   = 1;
 69 
 70         ret = 0;
 71         if (dma->d_ops->request)
 72                 ret = dma->d_ops->request(chan, dma);
 73 
 74         if (ret)
 75                 xchg(&dma->lock, 0);
 76 
 77         return ret;
 78 
 79 bad_dma:
 80         printk(KERN_ERR "dma: trying to allocate DMA%d\n", chan);
 81         return -EINVAL;
 82 
 83 busy:
 84         return -EBUSY;
 85 }
 86 EXPORT_SYMBOL(request_dma);
 87 
 88 /*
 89  * Free DMA channel
 90  *
 91  * On certain platforms, we have to free interrupt as well...
 92  */
 93 void free_dma(unsigned int chan)
 94 {
 95         dma_t *dma = dma_channel(chan);
 96 
 97         if (!dma)
 98                 goto bad_dma;
 99 
100         if (dma->active) {
101                 printk(KERN_ERR "dma%d: freeing active DMA\n", chan);
102                 dma->d_ops->disable(chan, dma);
103                 dma->active = 0;
104         }
105 
106         if (xchg(&dma->lock, 0) != 0) {
107                 if (dma->d_ops->free)
108                         dma->d_ops->free(chan, dma);
109                 return;
110         }
111 
112         printk(KERN_ERR "dma%d: trying to free free DMA\n", chan);
113         return;
114 
115 bad_dma:
116         printk(KERN_ERR "dma: trying to free DMA%d\n", chan);
117 }
118 EXPORT_SYMBOL(free_dma);
119 
120 /* Set DMA Scatter-Gather list
121  */
122 void set_dma_sg (unsigned int chan, struct scatterlist *sg, int nr_sg)
123 {
124         dma_t *dma = dma_channel(chan);
125 
126         if (dma->active)
127                 printk(KERN_ERR "dma%d: altering DMA SG while "
128                        "DMA active\n", chan);
129 
130         dma->sg = sg;
131         dma->sgcount = nr_sg;
132         dma->invalid = 1;
133 }
134 EXPORT_SYMBOL(set_dma_sg);
135 
136 /* Set DMA address
137  *
138  * Copy address to the structure, and set the invalid bit
139  */
140 void __set_dma_addr (unsigned int chan, void *addr)
141 {
142         dma_t *dma = dma_channel(chan);
143 
144         if (dma->active)
145                 printk(KERN_ERR "dma%d: altering DMA address while "
146                        "DMA active\n", chan);
147 
148         dma->sg = NULL;
149         dma->addr = addr;
150         dma->invalid = 1;
151 }
152 EXPORT_SYMBOL(__set_dma_addr);
153 
154 /* Set DMA byte count
155  *
156  * Copy address to the structure, and set the invalid bit
157  */
158 void set_dma_count (unsigned int chan, unsigned long count)
159 {
160         dma_t *dma = dma_channel(chan);
161 
162         if (dma->active)
163                 printk(KERN_ERR "dma%d: altering DMA count while "
164                        "DMA active\n", chan);
165 
166         dma->sg = NULL;
167         dma->count = count;
168         dma->invalid = 1;
169 }
170 EXPORT_SYMBOL(set_dma_count);
171 
172 /* Set DMA direction mode
173  */
174 void set_dma_mode (unsigned int chan, unsigned int mode)
175 {
176         dma_t *dma = dma_channel(chan);
177 
178         if (dma->active)
179                 printk(KERN_ERR "dma%d: altering DMA mode while "
180                        "DMA active\n", chan);
181 
182         dma->dma_mode = mode;
183         dma->invalid = 1;
184 }
185 EXPORT_SYMBOL(set_dma_mode);
186 
187 /* Enable DMA channel
188  */
189 void enable_dma (unsigned int chan)
190 {
191         dma_t *dma = dma_channel(chan);
192 
193         if (!dma->lock)
194                 goto free_dma;
195 
196         if (dma->active == 0) {
197                 dma->active = 1;
198                 dma->d_ops->enable(chan, dma);
199         }
200         return;
201 
202 free_dma:
203         printk(KERN_ERR "dma%d: trying to enable free DMA\n", chan);
204         BUG();
205 }
206 EXPORT_SYMBOL(enable_dma);
207 
208 /* Disable DMA channel
209  */
210 void disable_dma (unsigned int chan)
211 {
212         dma_t *dma = dma_channel(chan);
213 
214         if (!dma->lock)
215                 goto free_dma;
216 
217         if (dma->active == 1) {
218                 dma->active = 0;
219                 dma->d_ops->disable(chan, dma);
220         }
221         return;
222 
223 free_dma:
224         printk(KERN_ERR "dma%d: trying to disable free DMA\n", chan);
225         BUG();
226 }
227 EXPORT_SYMBOL(disable_dma);
228 
229 /*
230  * Is the specified DMA channel active?
231  */
232 int dma_channel_active(unsigned int chan)
233 {
234         dma_t *dma = dma_channel(chan);
235         return dma->active;
236 }
237 EXPORT_SYMBOL(dma_channel_active);
238 
239 void set_dma_page(unsigned int chan, char pagenr)
240 {
241         printk(KERN_ERR "dma%d: trying to set_dma_page\n", chan);
242 }
243 EXPORT_SYMBOL(set_dma_page);
244 
245 void set_dma_speed(unsigned int chan, int cycle_ns)
246 {
247         dma_t *dma = dma_channel(chan);
248         int ret = 0;
249 
250         if (dma->d_ops->setspeed)
251                 ret = dma->d_ops->setspeed(chan, dma, cycle_ns);
252         dma->speed = ret;
253 }
254 EXPORT_SYMBOL(set_dma_speed);
255 
256 int get_dma_residue(unsigned int chan)
257 {
258         dma_t *dma = dma_channel(chan);
259         int ret = 0;
260 
261         if (dma->d_ops->residue)
262                 ret = dma->d_ops->residue(chan, dma);
263 
264         return ret;
265 }
266 EXPORT_SYMBOL(get_dma_residue);
267 
  This page was automatically generated by the LXR engine.