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