356836abddbfabdd2f8e9b0cb8e27024a34437ea
[dos_auplay] / src / dma.c
1 #include <conio.h>\r
2 #include "dma.h"\r
3 \r
4 /* 8bit DMA ports */\r
5 #define DMA_0_ADDR      0x00\r
6 #define DMA_0_COUNT     0x01\r
7 #define DMA_1_ADDR      0x02\r
8 #define DMA_1_COUNT     0x03\r
9 #define DMA_2_ADDR      0x04\r
10 #define DMA_2_COUNT     0x05\r
11 #define DMA_3_ADDR      0x06\r
12 #define DMA_3_COUNT     0x07\r
13 /* 16bit DMA ports */\r
14 #define DMA_4_ADDR      0xc0\r
15 #define DMA_4_COUNT     0xc2\r
16 #define DMA_5_ADDR      0xc4\r
17 #define DMA_5_COUNT     0xc6\r
18 #define DMA_6_ADDR      0xc8\r
19 #define DMA_6_COUNT     0xca\r
20 #define DMA_7_ADDR      0xcc\r
21 #define DMA_7_COUNT     0xce\r
22 \r
23 #define DMA_ADDR(c)     \\r
24         ((c < 4) ? DMA_0_ADDR + ((c) << 1) : (DMA_4_ADDR + ((c) << 2)))\r
25 #define DMA_COUNT(c) \\r
26         ((c < 4) ? DMA_0_COUNT + ((c) << 1) : (DMA_4_COUNT + ((c) << 2)))\r
27 \r
28 #define DMA8_MASK                       0x0a\r
29 #define DMA8_MODE                       0x0b\r
30 #define DMA8_CLR_FLIPFLOP       0x0c\r
31 #define DMA8_RESET                      0x0d\r
32 #define DMA8_MASK_RST           0x0e\r
33 #define DMA8_RMASK                      0x0f\r
34 #define DMA16_MASK                      0xd4\r
35 #define DMA16_MODE                      0xd6\r
36 #define DMA16_CLR_FLIPFLOP      0xd8\r
37 #define DMA16_RESET                     0xda\r
38 #define DMA16_MASK_RST          0xdc\r
39 #define DMA16_RMASK             0xde\r
40 \r
41 #define DMA_MASK(c)     ((c) < 4 ? DMA8_MASK : DMA16_MASK)\r
42 #define DMA_MODE(c)     ((c) < 4 ? DMA8_MODE : DMA16_MODE)\r
43 #define DMA_CLR_FLIPFLOP(c)     ((c) < 4 ? DMA8_CLR_FLIPFLOP : DMA16_CLR_FLIPFLOP)\r
44 #define DMA_RESET(c)    ((c) < 4 ? DMA8_RESET : DMA16_RESET)\r
45 #define DMA_MASK_RST(c) ((c) < 4 ? DMA8_MASK_RST : DMA16_MASK_RST)\r
46 #define DMA_RMASK(c)    ((c) < 4 ? DMA8_RMASK : DMA16_RMASK)\r
47 \r
48 #define DMA_0_PAGE              0x87\r
49 #define DMA_1_PAGE              0x83\r
50 #define DMA_2_PAGE              0x81\r
51 #define DMA_3_PAGE              0x82\r
52 #define DMA_4_PAGE              0x8f\r
53 #define DMA_5_PAGE              0x8b\r
54 #define DMA_6_PAGE              0x89\r
55 #define DMA_7_PAGE              0x8a\r
56 \r
57 #define MODE_CHAN(x)    ((x) & 3)\r
58 #define MODE_WRITE              0x04\r
59 #define MODE_READ               0x08\r
60 #define MODE_AUTO               0x10\r
61 #define MODE_DECR               0x20\r
62 #define MODE_SINGLE             0x40\r
63 #define MODE_BLOCK              0x80\r
64 #define MODE_CASCADE    0xc0\r
65 \r
66 #define MASK_CHAN(x)    ((x) & 3)\r
67 #define MASK_DISABLE    0x04\r
68 \r
69 #define RMASK_CHAN(x)   (1 << ((x) & 3))\r
70 \r
71 #define IS_16BIT(c)     ((c) >= 4)\r
72 \r
73 static void dma_io(int chan, uint32_t phyaddr, int size, unsigned int flags, unsigned int dir);\r
74 static __inline void mask(int chan);\r
75 static __inline void unmask(int chan);\r
76 \r
77 static int page_port[] = {\r
78         DMA_0_PAGE, DMA_1_PAGE, DMA_2_PAGE, DMA_3_PAGE,\r
79         DMA_4_PAGE, DMA_5_PAGE, DMA_6_PAGE, DMA_7_PAGE\r
80 };\r
81 \r
82 void dma_out(int chan, uint32_t phyaddr, int size, unsigned int flags)\r
83 {\r
84         dma_io(chan, phyaddr, size, flags, MODE_READ);\r
85 }\r
86 \r
87 void dma_in(int chan, uint32_t phyaddr, int size, unsigned int flags)\r
88 {\r
89         dma_io(chan, phyaddr, size, flags, MODE_WRITE);\r
90 }\r
91 \r
92 static void dma_io(int chan, uint32_t phyaddr, int size, unsigned int flags, unsigned int dir)\r
93 {\r
94         unsigned int mode;\r
95         int addr_port, count_port;\r
96 \r
97         addr_port = DMA_ADDR(chan);\r
98         count_port = DMA_COUNT(chan);\r
99 \r
100         mask(chan);\r
101         outp(DMA_CLR_FLIPFLOP(chan), 0);\r
102 \r
103         /* first 2 bits of flags correspond to the mode bits 6,7 */\r
104         mode = ((flags & 3) << 6) | dir | MODE_CHAN(chan);\r
105         if(flags & DMA_DECR) mode |= MODE_DECR;\r
106         if(flags & DMA_AUTO) mode |= MODE_AUTO;\r
107         outp(DMA_MODE(chan), mode);\r
108 \r
109         if(IS_16BIT(chan)) {\r
110                 phyaddr >>= 1;\r
111                 size >>= 1;\r
112         }\r
113 \r
114         outp(addr_port, phyaddr & 0xff);\r
115         outp(addr_port, (phyaddr >> 8) & 0xff);\r
116         outp(page_port[chan], (phyaddr >> 16) & 0xff);\r
117 \r
118         size--;\r
119         outp(count_port, size & 0xff);\r
120         outp(count_port, (size >> 8) & 0xff);\r
121 \r
122         unmask(chan);\r
123 }\r
124 \r
125 static __inline void mask(int chan)\r
126 {\r
127         outp(DMA_MASK(chan), MASK_CHAN(chan) | MASK_DISABLE);\r
128 }\r
129 \r
130 static __inline void unmask(int chan)\r
131 {\r
132         outp(DMA_MASK(chan), MASK_CHAN(chan));\r
133 }\r