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