root/include/asm/dma.h

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

INCLUDED FROM


DEFINITIONS

This source file includes following definitions.
  1. enable_dma
  2. disable_dma
  3. clear_dma_ff
  4. set_dma_mode
  5. set_dma_page
  6. set_dma_addr
  7. set_dma_count
  8. get_dma_residue

   1 /* $Header: /sys/linux-0.97/include/asm/RCS/dma.h,v 1.4 1992/09/21 03:15:46 root Exp root $
   2  * linux/include/asm/dma.h: Defines for using and allocating dma channels.
   3  * Written by Hennus Bergman, 1992.
   4  */
   5 
   6 #ifndef _ASM_DMA_H
   7 #define _ASM_DMA_H
   8 
   9 #include <asm/io.h>             /* need byte IO */
  10 #include <linux/kernel.h>       /* need panic() [FIXME] */
  11 
  12 
  13 #ifdef HAVE_REALLY_SLOW_DMA_CONTROLLER
  14 #define outb    outb_p
  15 #endif
  16 
  17 /* FIXME: better fix this code for dma channels>3!!!!!!! */
  18 
  19 /*
  20  * The routines below should in most cases (with optimizing on) result
  21  * in equal or better code than similar code using macros.
  22  *
  23  * NOTE about DMA transfers: The DMA controller cannot handle transfers
  24  * that cross a 64k boundary. When the address reaches 0xNffff, it will wrap
  25  * around to 0xN0000, rather than increment to 0x(N+1)0000 !
  26  * Make sure you align your buffers properly! Runtime check recommended.
  27  *
  28  * NOTE2: DMA1..3 can only use the lower 1MB of physical memory. DMA4..7
  29  * can access the lower 16MB. There are people with >16MB, so beware!
  30  */
  31 
  32 
  33 #define MAX_DMA_CHANNELS        8
  34 
  35 /* SOMEBODY should check the following:
  36  * Channels 0..3 are on the first DMA controller, channels 4..7 are
  37  * on the second. Channel 0 is for refresh, 4 is for cascading.
  38  * The first DMA controller uses bytes, the second words.
  39  *
  40  * Where are the page regs for the second DMA controller?????
  41  */
  42 
  43 
  44 /* 8237 DMA controllers */
  45 #define IO_DMA1_BASE    0x00    /* 8 bit slave DMA, channels 0..3 */
  46 #define IO_DMA2_BASE    0xC0    /* 16 bit master DMA, ch 4(=slave input)..7 */
  47 
  48 /* DMA controller registers */
  49 #define DMA1_CMD_REG            0x08    /* DMA command register */
  50 #define DMA1_STAT_REG           0x08    /* DMA status register */
  51 #define DMA1_MASK_REG           0x0A    /* mask individual channels */
  52 #define DMA1_MODE_REG           0x0B    /* set modes for individual channels */
  53 #define DMA1_CLEAR_FF_REG       0x0C    /* Write 0 for LSB, 1 for MSB */
  54 #define DMA1_RESET_REG          0x0D    /* Write here to reset DMA controller */
  55 /* don't have much info on the second DMA controller... */
  56 #define DMA2_MASK_REG           0xD4
  57 #define DMA2_MODE_REG           0xD6
  58 /* #define DMA2_CLEAR_FF_REG 0xD8 -- pure guessing.... */
  59 
  60 /************* #error This needs more work!!!!!!!*************/
  61 
  62 #define DMA_MODE_READ   0x44    /* I/O to memory, no autoinit, increment, single mode */
  63 #define DMA_MODE_WRITE  0x48    /* memory to I/O, no autoinit, increment, single mode */
  64 #define DMA_MODE_CASCADE        0xC0    /* cascade mode (for DMA2 controller only) */
  65 
  66 
  67 /* enable/disable a specific DMA channel */
  68 static __inline__ void enable_dma(unsigned int dmanr)
     /* [previous][next][first][last][top][bottom][index][help] */
  69 {
  70         if (dmanr<=3)
  71                 outb(dmanr,  DMA1_MASK_REG);
  72         else
  73                 outb(dmanr & 3,  DMA2_MASK_REG);
  74 }
  75 
  76 static __inline__ void disable_dma(unsigned int dmanr)
     /* [previous][next][first][last][top][bottom][index][help] */
  77 {
  78         if (dmanr<=3)
  79                 outb(dmanr | 4,  DMA1_MASK_REG);
  80         else
  81                 outb((dmanr & 3) | 4,  DMA2_MASK_REG);
  82 }
  83 
  84 /* Clear the 'DMA Pointer Flip Flop'.
  85  * Write 0 for LSB/MSB, 1 for MSB/LSB access.
  86  * Use this once to initialize the FF to a know state.
  87  * After that, keep track of it. :-) In order to do that,
  88  * dma_set_addr() and dma_set_count() should only be used wile
  89  * interrupts are disbled.
  90  */
  91 static __inline__ void clear_dma_ff(unsigned int dmanr)
     /* [previous][next][first][last][top][bottom][index][help] */
  92 {
  93         if (dmanr<=3)
  94                 outb(0,  DMA1_CLEAR_FF_REG);
  95         else
  96 #ifdef DMA2_CLEAR_FF_REG
  97                 outb(0,  DMA2_CLEAR_FF_REG);
  98 #else
  99                 panic("dma.h: Don't have CLEAR_FF for high dma channels!\n");
 100 #endif
 101 }
 102 
 103 /* set mode (above) for a specific DMA channel */
 104 static __inline__ void set_dma_mode(unsigned int dmanr, char mode)
     /* [previous][next][first][last][top][bottom][index][help] */
 105 {
 106         if (dmanr<=3)
 107                 outb(mode | dmanr,  DMA1_MODE_REG);
 108         else
 109                 outb(DMA_MODE_CASCADE | mode | (dmanr&3),  DMA2_MODE_REG);
 110 }
 111 
 112 /* Set only the page register bits of the transfer address.
 113  * This is used for successive transfers when we know the contents of
 114  * the lower 16 bits of the DMA current address register, but a 64k boundary
 115  * may have been crossed.
 116  */
 117 static __inline__ void set_dma_page(unsigned int dmanr, char pagenr)
     /* [previous][next][first][last][top][bottom][index][help] */
 118 {
 119         switch(dmanr) {
 120                 case 0:
 121                         outb(pagenr, 0x80);
 122                         break;
 123                 case 1:
 124                         outb(pagenr, 0x83);
 125                         break;
 126                 case 2:
 127                         outb(pagenr, 0x81);
 128                         break;
 129                 case 3:
 130                         outb(pagenr, 0x82);
 131                         break;
 132                 case 4:
 133                 case 5:
 134                 case 6:
 135                 case 7:
 136                         panic("dma.h: don't know how to set DMA page regs for channels>3");
 137                         break;
 138         }
 139 }
 140 
 141 
 142 /* Set transfer address & page bits for specific DMA channel.
 143  * Assumes dma flipflop is clear.
 144  */
 145 static __inline__ void set_dma_addr(unsigned int dmanr, unsigned int a)
     /* [previous][next][first][last][top][bottom][index][help] */
 146 {
 147         unsigned int io_base = (dmanr<=3)? IO_DMA1_BASE : IO_DMA2_BASE;
 148 
 149         set_dma_page(dmanr, a>>16);
 150         outb(a & 0xff, ((dmanr&3)<<1) + io_base);
 151         outb((a>>8) & 0xff, ((dmanr&3)<<1) + io_base);
 152 }
 153 
 154 
 155 /* Set transfer size (max 64k) for a specific DMA channel.
 156  * You must ensure the parameters are valid.
 157  * NOTE: from a manual: "the number of transfers is one more 
 158  * than the initial word count"! This is taken into account.
 159  * Assumes dma flip-flop is clear.
 160  */
 161 static __inline__ void set_dma_count(unsigned int dmanr, unsigned int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 162 {
 163         unsigned int dc = count - 1;
 164         unsigned int io_base = (dmanr<=3)? IO_DMA1_BASE : IO_DMA2_BASE;
 165 
 166         outb(dc & 0xff, ((dmanr&3)<<1) + 1 + io_base);
 167         outb((dc>>8) & 0xff, ((dmanr&3)<<1) + 1 + io_base);
 168 }
 169 
 170 
 171 /* Get DMA residue count. After a DMA transfer, this
 172  * should return zero. Reading this while a DMA transfer is
 173  * still in progress will return unpredictable results.
 174  * If called before the channel has been used, it may return 1.
 175  * Otherwise, it returns the number of bytes left to transfer,
 176  * minus 1, modulo 64k.
 177  * Assumes DMA flip-flop is clear.
 178  */
 179 static __inline__ short int get_dma_residue(unsigned int dmanr)
     /* [previous][next][first][last][top][bottom][index][help] */
 180 {
 181         unsigned int io_base = (dmanr<=3)? IO_DMA1_BASE : IO_DMA2_BASE;
 182 
 183         return 1 + inb( ((dmanr&3)<<1) + 1 + io_base ) +
 184                 ( inb( ((dmanr&3)<<1) + 1 + io_base ) << 8 );
 185 }
 186 
 187 /* These are in kernel/dma.c: */
 188 extern int request_dma(unsigned int dmanr);     /* reserve a DMA channel */
 189 extern void free_dma(unsigned int dmanr);       /* release it again */
 190 
 191 
 192 #endif /* _ASM_DMA_H */

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