root/kernel/dma.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. mutex_atomic_swap
  2. request_dma
  3. free_dma

   1 /* $Id: dma.c,v 1.5 1992/11/18 02:49:05 root Exp root $
   2  * linux/kernel/dma.c: A DMA channel allocator. Inspired by linux/kernel/irq.c.
   3  * Written by Hennus Bergman, 1992. 
   4  */
   5 
   6 #include <linux/kernel.h>
   7 #include <linux/errno.h>
   8 #include <asm/dma.h>
   9 
  10 
  11 /* A note on resource allocation:
  12  *
  13  * All drivers needing DMA channels, should allocate and release them
  14  * through the public routines `request_dma()' and `free_dma()'.
  15  *
  16  * In order to avoid problems, all processes should allocate resources in
  17  * the same sequence and release them in the reverse order.
  18  * 
  19  * So, when allocating DMAs and IRQs, first allocate the IRQ, then the DMA.
  20  * When releasing them, first release the DMA, then release the IRQ.
  21  * If you don't, you may cause allocation requests to fail unnecessarily.
  22  * This doesn't really matter now, but it will once we get real semaphores
  23  * in the kernel.
  24  */
  25 
  26 
  27 
  28 /* Channel n is busy iff dma_chan_busy[n] != 0.
  29  * DMA0 is reserved for DRAM refresh, I think.
  30  * DMA4 is reserved for cascading (?).
  31  */
  32 static volatile unsigned int dma_chan_busy[MAX_DMA_CHANNELS] = {
  33         1, 0, 0, 0, 1, 0, 0, 0
  34 };
  35 
  36 
  37 
  38 /* Atomically swap memory location [32 bits] with `newval'.
  39  * This avoid the cli()/sti() junk and related problems.
  40  * [And it's faster too :-)]
  41  * Maybe this should be in include/asm/mutex.h and be used for
  42  * implementing kernel-semaphores as well.
  43  */
  44 static __inline__ unsigned int mutex_atomic_swap(volatile unsigned int * p, unsigned int newval)
     /* [previous][next][first][last][top][bottom][index][help] */
  45 {
  46         unsigned int semval = newval;
  47 
  48         /* If one of the operands for the XCHG instructions is a memory ref,
  49          * it makes the swap an uninterruptible RMW cycle.
  50          *
  51          * One operand must be in memory, the other in a register, otherwise
  52          * the swap may not be atomic.
  53          */
  54 
  55         asm __volatile__ ("xchgl %2, %0\n"
  56                         : /* outputs: semval   */ "=r" (semval)
  57                         : /* inputs: newval, p */ "0" (semval), "m" (*p)
  58                         );      /* p is a var, containing an address */
  59         return semval;
  60 } /* mutex_atomic_swap */
  61 
  62 
  63 
  64 int request_dma(unsigned int dmanr)
     /* [previous][next][first][last][top][bottom][index][help] */
  65 {
  66         if (dmanr >= MAX_DMA_CHANNELS)
  67                 return -EINVAL;
  68 
  69         if (mutex_atomic_swap(&dma_chan_busy[dmanr], 1) != 0)
  70                 return -EBUSY;
  71         else
  72                 /* old flag was 0, now contains 1 to indicate busy */
  73                 return 0;
  74 } /* request_dma */
  75 
  76 
  77 void free_dma(unsigned int dmanr)
     /* [previous][next][first][last][top][bottom][index][help] */
  78 {
  79         if (dmanr >= MAX_DMA_CHANNELS) {
  80                 printk("Trying to free DMA%d\n", dmanr);
  81                 return;
  82         }
  83 
  84         if (mutex_atomic_swap(&dma_chan_busy[dmanr], 0) == 0)
  85                 printk("Trying to free free DMA%d\n", dmanr);
  86 } /* free_dma */
  87 

/* [previous][next][first][last][top][bottom][index][help] */