56ec5d91c350310c0cc491455f08dab3a2ff1164
[dos_auplay] / src / dma.c
1 #include <conio.h>\r
2 #include "dma.h"\r
3 \r
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
12 \r
13 #define MASK_CHAN(x)    ((x) & 3)\r
14 #define MASK_DISABLE    0x04\r
15 \r
16 #define RMASK_CHAN(x)   (1 << ((x) & 3))\r
17 \r
18 #define IS_16BIT(c)     ((c) >= 4)\r
19 \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
23 \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
31 \r
32 void dma_out(int chan, uint32_t phyaddr, int size, unsigned int flags)\r
33 {\r
34         dma_io(chan, phyaddr, size, flags, MODE_READ);\r
35 }\r
36 \r
37 void dma_in(int chan, uint32_t phyaddr, int size, unsigned int flags)\r
38 {\r
39         dma_io(chan, phyaddr, size, flags, MODE_WRITE);\r
40 }\r
41 \r
42 static void dma_io(int chan, uint32_t phyaddr, int size, unsigned int flags, unsigned int dir)\r
43 {\r
44         unsigned int mode;\r
45 \r
46         mask(chan);\r
47         outp(clrff_port[chan], 0);\r
48 \r
49         /* first 2 bits of flags correspond to the mode bits 6,7 */\r
50         mode = ((flags & 3) << 6) | dir | MODE_CHAN(chan);\r
51         if(flags & DMA_DECR) mode |= MODE_DECR;\r
52         if(flags & DMA_AUTO) mode |= MODE_AUTO;\r
53         outp(mode_port[chan], mode);\r
54 \r
55         if(IS_16BIT(chan)) {\r
56                 phyaddr >>= 1;\r
57                 size >>= 1;\r
58         }\r
59 \r
60         outp(addr_port[chan], phyaddr & 0xff);\r
61         outp(addr_port[chan], (phyaddr >> 8) & 0xff);\r
62         outp(page_port[chan], (phyaddr >> 16) & 0xff);\r
63 \r
64         size--;\r
65         outp(count_port[chan], size & 0xff);\r
66         outp(count_port[chan], (size >> 8) & 0xff);\r
67 \r
68         unmask(chan);\r
69 }\r
70 \r
71 static __inline void mask(int chan)\r
72 {\r
73         outp(mask_port[chan], MASK_CHAN(chan) | MASK_DISABLE);\r
74 }\r
75 \r
76 static __inline void unmask(int chan)\r
77 {\r
78         outp(mask_port[chan], MASK_CHAN(chan));\r
79 }\r