home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / KERNEL-S / V1.0 / LINUX-1.0 / LINUX-1 / linux / kernel / dma.c next >
Encoding:
C/C++ Source or Header  |  1993-12-01  |  2.4 KB  |  88 lines

  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)
  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)
  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)
  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.  
  88.