This source file includes following definitions.
- dma_channel
- isa_dma_add
- request_dma
- free_dma
- set_dma_sg
- __set_dma_addr
- set_dma_count
- set_dma_mode
- enable_dma
- disable_dma
- dma_channel_active
- set_dma_page
- set_dma_speed
- get_dma_residue
- proc_dma_show
- proc_dma_init
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 
  11 #include <linux/module.h>
  12 #include <linux/init.h>
  13 #include <linux/spinlock.h>
  14 #include <linux/errno.h>
  15 #include <linux/scatterlist.h>
  16 #include <linux/seq_file.h>
  17 #include <linux/proc_fs.h>
  18 
  19 #include <asm/dma.h>
  20 
  21 #include <asm/mach/dma.h>
  22 
  23 DEFINE_RAW_SPINLOCK(dma_spin_lock);
  24 EXPORT_SYMBOL(dma_spin_lock);
  25 
  26 static dma_t *dma_chan[MAX_DMA_CHANNELS];
  27 
  28 static inline dma_t *dma_channel(unsigned int chan)
  29 {
  30         if (chan >= MAX_DMA_CHANNELS)
  31                 return NULL;
  32 
  33         return dma_chan[chan];
  34 }
  35 
  36 int __init isa_dma_add(unsigned int chan, dma_t *dma)
  37 {
  38         if (!dma->d_ops)
  39                 return -EINVAL;
  40 
  41         sg_init_table(&dma->buf, 1);
  42 
  43         if (dma_chan[chan])
  44                 return -EBUSY;
  45         dma_chan[chan] = dma;
  46         return 0;
  47 }
  48 
  49 
  50 
  51 
  52 
  53 
  54 int request_dma(unsigned int chan, const char *device_id)
  55 {
  56         dma_t *dma = dma_channel(chan);
  57         int ret;
  58 
  59         if (!dma)
  60                 goto bad_dma;
  61 
  62         if (xchg(&dma->lock, 1) != 0)
  63                 goto busy;
  64 
  65         dma->device_id = device_id;
  66         dma->active    = 0;
  67         dma->invalid   = 1;
  68 
  69         ret = 0;
  70         if (dma->d_ops->request)
  71                 ret = dma->d_ops->request(chan, dma);
  72 
  73         if (ret)
  74                 xchg(&dma->lock, 0);
  75 
  76         return ret;
  77 
  78 bad_dma:
  79         pr_err("dma: trying to allocate DMA%d\n", chan);
  80         return -EINVAL;
  81 
  82 busy:
  83         return -EBUSY;
  84 }
  85 EXPORT_SYMBOL(request_dma);
  86 
  87 
  88 
  89 
  90 
  91 
  92 void free_dma(unsigned int chan)
  93 {
  94         dma_t *dma = dma_channel(chan);
  95 
  96         if (!dma)
  97                 goto bad_dma;
  98 
  99         if (dma->active) {
 100                 pr_err("dma%d: freeing active DMA\n", chan);
 101                 dma->d_ops->disable(chan, dma);
 102                 dma->active = 0;
 103         }
 104 
 105         if (xchg(&dma->lock, 0) != 0) {
 106                 if (dma->d_ops->free)
 107                         dma->d_ops->free(chan, dma);
 108                 return;
 109         }
 110 
 111         pr_err("dma%d: trying to free free DMA\n", chan);
 112         return;
 113 
 114 bad_dma:
 115         pr_err("dma: trying to free DMA%d\n", chan);
 116 }
 117 EXPORT_SYMBOL(free_dma);
 118 
 119 
 120 
 121 void set_dma_sg (unsigned int chan, struct scatterlist *sg, int nr_sg)
 122 {
 123         dma_t *dma = dma_channel(chan);
 124 
 125         if (dma->active)
 126                 pr_err("dma%d: altering DMA SG while DMA active\n", chan);
 127 
 128         dma->sg = sg;
 129         dma->sgcount = nr_sg;
 130         dma->invalid = 1;
 131 }
 132 EXPORT_SYMBOL(set_dma_sg);
 133 
 134 
 135 
 136 
 137 
 138 void __set_dma_addr (unsigned int chan, void *addr)
 139 {
 140         dma_t *dma = dma_channel(chan);
 141 
 142         if (dma->active)
 143                 pr_err("dma%d: altering DMA address while DMA active\n", chan);
 144 
 145         dma->sg = NULL;
 146         dma->addr = addr;
 147         dma->invalid = 1;
 148 }
 149 EXPORT_SYMBOL(__set_dma_addr);
 150 
 151 
 152 
 153 
 154 
 155 void set_dma_count (unsigned int chan, unsigned long count)
 156 {
 157         dma_t *dma = dma_channel(chan);
 158 
 159         if (dma->active)
 160                 pr_err("dma%d: altering DMA count while DMA active\n", chan);
 161 
 162         dma->sg = NULL;
 163         dma->count = count;
 164         dma->invalid = 1;
 165 }
 166 EXPORT_SYMBOL(set_dma_count);
 167 
 168 
 169 
 170 void set_dma_mode (unsigned int chan, unsigned int mode)
 171 {
 172         dma_t *dma = dma_channel(chan);
 173 
 174         if (dma->active)
 175                 pr_err("dma%d: altering DMA mode while DMA active\n", chan);
 176 
 177         dma->dma_mode = mode;
 178         dma->invalid = 1;
 179 }
 180 EXPORT_SYMBOL(set_dma_mode);
 181 
 182 
 183 
 184 void enable_dma (unsigned int chan)
 185 {
 186         dma_t *dma = dma_channel(chan);
 187 
 188         if (!dma->lock)
 189                 goto free_dma;
 190 
 191         if (dma->active == 0) {
 192                 dma->active = 1;
 193                 dma->d_ops->enable(chan, dma);
 194         }
 195         return;
 196 
 197 free_dma:
 198         pr_err("dma%d: trying to enable free DMA\n", chan);
 199         BUG();
 200 }
 201 EXPORT_SYMBOL(enable_dma);
 202 
 203 
 204 
 205 void disable_dma (unsigned int chan)
 206 {
 207         dma_t *dma = dma_channel(chan);
 208 
 209         if (!dma->lock)
 210                 goto free_dma;
 211 
 212         if (dma->active == 1) {
 213                 dma->active = 0;
 214                 dma->d_ops->disable(chan, dma);
 215         }
 216         return;
 217 
 218 free_dma:
 219         pr_err("dma%d: trying to disable free DMA\n", chan);
 220         BUG();
 221 }
 222 EXPORT_SYMBOL(disable_dma);
 223 
 224 
 225 
 226 
 227 int dma_channel_active(unsigned int chan)
 228 {
 229         dma_t *dma = dma_channel(chan);
 230         return dma->active;
 231 }
 232 EXPORT_SYMBOL(dma_channel_active);
 233 
 234 void set_dma_page(unsigned int chan, char pagenr)
 235 {
 236         pr_err("dma%d: trying to set_dma_page\n", chan);
 237 }
 238 EXPORT_SYMBOL(set_dma_page);
 239 
 240 void set_dma_speed(unsigned int chan, int cycle_ns)
 241 {
 242         dma_t *dma = dma_channel(chan);
 243         int ret = 0;
 244 
 245         if (dma->d_ops->setspeed)
 246                 ret = dma->d_ops->setspeed(chan, dma, cycle_ns);
 247         dma->speed = ret;
 248 }
 249 EXPORT_SYMBOL(set_dma_speed);
 250 
 251 int get_dma_residue(unsigned int chan)
 252 {
 253         dma_t *dma = dma_channel(chan);
 254         int ret = 0;
 255 
 256         if (dma->d_ops->residue)
 257                 ret = dma->d_ops->residue(chan, dma);
 258 
 259         return ret;
 260 }
 261 EXPORT_SYMBOL(get_dma_residue);
 262 
 263 #ifdef CONFIG_PROC_FS
 264 static int proc_dma_show(struct seq_file *m, void *v)
 265 {
 266         int i;
 267 
 268         for (i = 0 ; i < MAX_DMA_CHANNELS ; i++) {
 269                 dma_t *dma = dma_channel(i);
 270                 if (dma && dma->lock)
 271                         seq_printf(m, "%2d: %s\n", i, dma->device_id);
 272         }
 273         return 0;
 274 }
 275 
 276 static int __init proc_dma_init(void)
 277 {
 278         proc_create_single("dma", 0, NULL, proc_dma_show);
 279         return 0;
 280 }
 281 
 282 __initcall(proc_dma_init);
 283 #endif