nckernel  0.1
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
dma.c
Go to the documentation of this file.
1 #include <sys/types.h>
2 #include <sys/io.h>
3 #include <stdio.h>
4 #include <stddef.h>
5 
6 #include <dma.h>
7 #include <interrupt.h>
8 
9 #include <list.h>
10 
14 #define DMA_DISABLE(ch) do { \
15  outb(dma_ctrl[(ch)>>2].single_mask, DMA_MASK_DISABLE_CH|(ch)); \
16 } while (0)
17 
21 #define DMA_ENABLE(ch) do { \
22  outb(dma_ctrl[(ch)>>2].single_mask, (ch)); \
23 } while (0)
24 
28 #define DMA_RESET_PTR(ch) do { \
29  outb(dma_ctrl[(ch) >> 2].byte_ptr, 0x00); \
30 } while (0)
31 
37 #define DMA_SET_PAGE(ch, addr) do { \
38  outb(dma_port[ch].page, (((addr) & 0x00FF0000) >> 16)); \
39 } while (0)
40 
41 #define DMA_SET_ADDRESS(ch, addr) do { \
42  outb(dma_port[ch].address, ((addr) & 0x000000FF)); \
43  outb(dma_port[ch].address, ((addr) & 0x0000FF00) >> 8); \
44 } while (0)
45 
49 #define DMA_SET_MODE(ch, mode) do { \
50  outb(dma_ctrl[(ch)>>2].write_mode, (mode) | (ch)); \
51 } while (0)
52 
56 #define DMA_SET_TX_SIZE(ch, cnt) do { \
57  outb(dma_port[ch].count, ((unsigned short)(cnt) & 0x00FF)); \
58  outb(dma_port[ch].count, ((unsigned short)(cnt) & 0xFF00) >> 8); \
59 } while (0)
60 
61 #define DMA_CTRL_FROM_CH(ch) (((ch) >> 2) ? DMA_16BIT : DMA_8BIT)
62 
63 static struct dma_ctrl_port_entry_t dma_ctrl[DMA_MAX_TYPE] = {
64  {
65  .write_mode = 0x0B,
66  .single_mask = 0x0A,
67  .byte_ptr = 0x0C,
68 
69  .status = 0x08,
70  .command = 0x08,
71  .request = 0x09,
72  .intermediate = 0x0D,
73  .dma_mask = 0x0F,
74  },
75  {
76  .write_mode = 0xD6,
77  .single_mask = 0xD4,
78  .byte_ptr = 0xD8,
79 
80  .status = 0xD0,
81  .command = 0xD0,
82  .request = 0xD2,
83  .intermediate = 0xDA,
84  .dma_mask = 0xDE,
85  },
86 };
87 
88 static struct dma_port_entry_t dma_port[DMA_MAX_CHANNEL] = {
90  {
91  .page = 0x87,
92  .address = 0x00,
93  .count = 0x01,
94  },
95  {
96  .page = 0x83,
97  .address = 0x02,
98  .count = 0x03,
99  },
100  {
101  .page = 0x81,
102  .address = 0x04,
103  .count = 0x05,
104  },
105  {
106  .page = 0x82,
107  .address = 0x06,
108  .count = 0x07,
109  },
110 
112  {
113  .page = 0x8F,
114  .address = 0xC0,
115  .count = 0xC2,
116  },
117  {
118  .page = 0x8B,
119  .address = 0xC4,
120  .count = 0xC6,
121  },
122  {
123  .page = 0x89,
124  .address = 0xC8,
125  .count = 0xCA,
126  },
127  {
128  .page = 0x8A,
129  .address = 0xCC,
130  .count = 0xCE,
131  },
132 };
133 
135 {
136  if (type < 0 || type >= DMA_MAX_TYPE) {
137  return NULL;
138  }
139 
140  return dma_ctrl + type;
141 }
142 
143 struct dma_port_entry_t *dma_get_port(int channel)
144 {
145  if (channel < 0 || channel >= DMA_MAX_CHANNEL) {
146  return NULL;
147  }
148 
149  return dma_port + channel;
150 }
151 
152 void dma_init(int ch, int mode, unsigned long address, int count)
153 {
154  unsigned long flags;
155 
156  irq_local_save(&flags);
157  DMA_DISABLE(ch);
158  DMA_RESET_PTR(ch);
159 
160  DMA_SET_ADDRESS(ch, address);
161  DMA_RESET_PTR(ch);
162 
163  DMA_SET_TX_SIZE(ch, count - 1);
164 
165  DMA_SET_MODE(ch, mode);
166  DMA_SET_PAGE(ch, address);
167 
168  DMA_ENABLE(ch);
169  irq_local_restore(flags);
170 }
171 
172 int dma_is_done(int ch)
173 {
174  unsigned char ret;
175 
176  ret = inb(dma_ctrl[DMA_CTRL_FROM_CH(ch)].status);
177  return (ret & (0x01 << ch)) ? 0 : -1;
178 }
179 
180 /* End of a file */