4 #define MODE_CHAN(x) ((x) & 3)
\r
5 #define MODE_WRITE 0x04
\r
6 #define MODE_READ 0x08
\r
7 #define MODE_AUTO 0x10
\r
8 #define MODE_DECR 0x20
\r
9 #define MODE_SINGLE 0x40
\r
10 #define MODE_BLOCK 0x80
\r
11 #define MODE_CASCADE 0xc0
\r
13 #define MASK_CHAN(x) ((x) & 3)
\r
14 #define MASK_DISABLE 0x04
\r
16 #define RMASK_CHAN(x) (1 << ((x) & 3))
\r
18 #define IS_16BIT(c) ((c) >= 4)
\r
20 static void dma_io(int chan, uint32_t phyaddr, int size, unsigned int flags, unsigned int dir);
\r
21 static __inline void mask(int chan);
\r
22 static __inline void unmask(int chan);
\r
24 /* DMA register I/O ports for all channels */
\r
25 static const int addr_port[] = { 0x00, 0x02, 0x04, 0x06, 0xc0, 0xc4, 0xc8, 0xcc };
\r
26 static const int count_port[] = { 0x01, 0x03, 0x05, 0x07, 0xc2, 0xc6, 0xca, 0xce };
\r
27 static const int page_port[] = { 0x87, 0x83, 0x81, 0x82, 0x8f, 0x8b, 0x89, 0x8a };
\r
28 static const int mask_port[] = { 0x0a, 0x0a, 0x0a, 0x0a, 0xd4, 0xd4, 0xd4, 0xd4 };
\r
29 static const int mode_port[] = { 0x0b, 0x0b, 0x0b, 0x0b, 0xd6, 0xd6, 0xd6, 0xd6 };
\r
30 static const int clrff_port[] = { 0x0c, 0x0c, 0x0c, 0x0c, 0xd8, 0xd8, 0xd8, 0xd8 };
\r
32 void dma_out(int chan, uint32_t phyaddr, int size, unsigned int flags)
\r
34 dma_io(chan, phyaddr, size, flags, MODE_READ);
\r
37 void dma_in(int chan, uint32_t phyaddr, int size, unsigned int flags)
\r
39 dma_io(chan, phyaddr, size, flags, MODE_WRITE);
\r
42 static void dma_io(int chan, uint32_t phyaddr, int size, unsigned int flags, unsigned int dir)
\r
48 outp(clrff_port[chan], 0);
\r
50 /* first 2 bits of flags correspond to the mode bits 6,7 */
\r
51 mode = ((flags & 3) << 6) | dir | MODE_CHAN(chan);
\r
52 if(flags & DMA_DECR) mode |= MODE_DECR;
\r
53 if(flags & DMA_AUTO) mode |= MODE_AUTO;
\r
54 outp(mode_port[chan], mode);
\r
56 page = (phyaddr >> 16) & 0xff;
\r
58 if(IS_16BIT(chan)) {
\r
63 outp(addr_port[chan], phyaddr & 0xff);
\r
64 outp(addr_port[chan], (phyaddr >> 8) & 0xff);
\r
65 outp(page_port[chan], page);
\r
68 outp(count_port[chan], size & 0xff);
\r
69 outp(count_port[chan], (size >> 8) & 0xff);
\r
74 static __inline void mask(int chan)
\r
76 outp(mask_port[chan], MASK_CHAN(chan) | MASK_DISABLE);
\r
79 static __inline void unmask(int chan)
\r
81 outp(mask_port[chan], MASK_CHAN(chan));
\r