porting the demo to miniglut
[dosdemo] / libs / mikmod / drivers / dos / dosdma.h
1 /*
2     Interface for DMA routines on DOS
3     Copyright (C) 1999 by Andrew Zabolotny, <bit@eltech.ru>
4
5     This library is free software; you can redistribute it and/or
6     modify it under the terms of the GNU Library General Public
7     License as published by the Free Software Foundation; either
8     version 2 of the License, or (at your option) any later version.
9
10     This library is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13     Library General Public License for more details.
14
15     You should have received a copy of the GNU Library General Public
16     License along with this library; if not, write to the Free
17     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20 #ifndef __DOSDMA_H__
21 #define __DOSDMA_H__
22
23 #include <pc.h>
24
25 #define DMA1_BASE               0x00    /* 8 bit slave DMA, channels 0..3 */
26 #define DMA2_BASE               0xC0    /* 16 bit master DMA, ch 4(=slave input)..7 */
27
28 #define DMA1_CMD_REG            0x08    /* command register (w) */
29 #define DMA1_STAT_REG           0x08    /* status register (r) */
30 #define DMA1_REQ_REG            0x09    /* request register (w) */
31 #define DMA1_MASK_REG           0x0A    /* single-channel mask (w) */
32 #define DMA1_MODE_REG           0x0B    /* mode register (w) */
33 #define DMA1_CLEAR_FF_REG       0x0C    /* clear pointer flip-flop (w) */
34 #define DMA1_TEMP_REG           0x0D    /* Temporary Register (r) */
35 #define DMA1_RESET_REG          0x0D    /* Master Clear (w) */
36 #define DMA1_CLR_MASK_REG       0x0E    /* Clear Mask */
37 #define DMA1_MASK_ALL_REG       0x0F    /* all-channels mask (w) */
38
39 #define DMA2_CMD_REG            0xD0    /* command register (w) */
40 #define DMA2_STAT_REG           0xD0    /* status register (r) */
41 #define DMA2_REQ_REG            0xD2    /* request register (w) */
42 #define DMA2_MASK_REG           0xD4    /* single-channel mask (w) */
43 #define DMA2_MODE_REG           0xD6    /* mode register (w) */
44 #define DMA2_CLEAR_FF_REG       0xD8    /* clear pointer flip-flop (w) */
45 #define DMA2_TEMP_REG           0xDA    /* Temporary Register (r) */
46 #define DMA2_RESET_REG          0xDA    /* Master Clear (w) */
47 #define DMA2_CLR_MASK_REG       0xDC    /* Clear Mask */
48 #define DMA2_MASK_ALL_REG       0xDE    /* all-channels mask (w) */
49
50 #define DMA_ADDR_0      0x00    /* DMA address registers */
51 #define DMA_ADDR_1      0x02
52 #define DMA_ADDR_2      0x04
53 #define DMA_ADDR_3      0x06
54 #define DMA_ADDR_4      0xC0
55 #define DMA_ADDR_5      0xC4
56 #define DMA_ADDR_6      0xC8
57 #define DMA_ADDR_7      0xCC
58
59 #define DMA_SIZE_0              0x01    /* DMA transfer size registers */
60 #define DMA_SIZE_1              0x03
61 #define DMA_SIZE_2              0x05
62 #define DMA_SIZE_3              0x07
63 #define DMA_SIZE_4              0xC2
64 #define DMA_SIZE_5              0xC6
65 #define DMA_SIZE_6              0xCA
66 #define DMA_SIZE_7              0xCE
67
68 #define DMA_PAGE_0      0x87    /* DMA page registers */
69 #define DMA_PAGE_1      0x83
70 #define DMA_PAGE_2      0x81
71 #define DMA_PAGE_3      0x82
72 #define DMA_PAGE_5      0x8B
73 #define DMA_PAGE_6      0x89
74 #define DMA_PAGE_7      0x8A
75
76 #define DMA_MODE_AUTOINIT       0x10    /* Auto-init mode bit */
77 #define DMA_MODE_READ           0x44    /* I/O to memory, no autoinit, increment, single mode */
78 #define DMA_MODE_WRITE          0x48    /* memory to I/O, no autoinit, increment, single mode */
79 #define DMA_MODE_CASCADE        0xC0    /* pass thru DREQ->HRQ, DACK<-HLDA only */
80
81 /* Indexable specific DMA registers */
82 typedef struct __dma_regs_s {
83         unsigned char addr;                     /* DMA transfer address register */
84         unsigned char page;                     /* DMA page register */
85         unsigned char size;                     /* DMA transfer size register */
86         unsigned char mask;                     /* DMA mask/unmask register */
87         unsigned char flip;                     /* DMA flip-flop reset register */
88         unsigned char mode;                     /* DMA mode register */
89 } __dma_regs;
90
91 extern __dma_regs dma[8];
92
93 /* Enable a specific DMA channel */
94 static inline void dma_enable(unsigned int channel)
95 {
96         outportb(dma[channel].mask, channel & 3);
97 }
98
99 /* Disable a specific DMA channel */
100 static inline void dma_disable(unsigned int channel)
101 {
102         outportb(dma[channel].mask, (channel & 3) | 0x04);
103 }
104
105 /* Clear the 'DMA Flip Flop' flag */
106 static inline void dma_clear_ff(unsigned int channel)
107 {
108         outportb(dma[channel].flip, 0);
109 }
110
111 /* Set mode for a specific DMA channel */
112 static inline void dma_set_mode(unsigned int channel, char mode)
113 {
114         outportb(dma[channel].mode, mode | (channel & 3));
115 }
116
117 /* Set DMA page register */
118 static inline void dma_set_page(unsigned int channel, char page)
119 {
120         if (channel > 3)
121                 page &= 0xfe;
122         outportb(dma[channel].page, page);
123 }
124
125 /*
126   Set transfer address & page bits for specific DMA channel.
127   Assumes dma flipflop is clear.
128 */
129 static inline void dma_set_addr(unsigned int channel, unsigned int address)
130 {
131         unsigned char dma_reg = dma[channel].addr;
132         dma_set_page(channel, address >> 16);
133         if (channel <= 3) {
134                 outportb(dma_reg, (address) & 0xff);
135                 outportb(dma_reg, (address >> 8) & 0xff);
136         } else {
137                 outportb(dma_reg, (address >> 1) & 0xff);
138                 outportb(dma_reg, (address >> 9) & 0xff);
139         }
140 }
141
142 /*
143   Set transfer size for a specific DMA channel.
144   Assumes dma flip-flop is clear.
145 */
146 static inline void dma_set_count(unsigned int channel, unsigned int count)
147 {
148         unsigned char dma_reg = dma[channel].size;
149         count--;                                        /* number of DMA transfers is bigger by one */
150         if (channel > 3)
151                 count >>= 1;
152         outportb(dma_reg, (count) & 0xff);
153         outportb(dma_reg, (count >> 8) & 0xff);
154 }
155
156 /*
157   Query the number of bytes left to transfer.
158   Assumes DMA flip-flop is clear.
159 */
160 static inline int dma_get_count(unsigned int channel)
161 {
162         unsigned char dma_reg = dma[channel].size;
163
164         /* using short to get 16-bit wrap around */
165         unsigned short count;
166         count = inportb(dma_reg);
167         count |= inportb(dma_reg) << 8;
168         count++;
169         return (channel <= 3) ? count : (count << 1);
170 }
171
172 typedef struct dma_buffer_s {
173         unsigned char *linear;          /* Linear address */
174         unsigned long physical;         /* Physical address */
175         unsigned long size;                     /* Buffer size */
176         unsigned short selector;        /* The selector assigned to this memory */
177         unsigned char channel;          /* The DMA channel */
178 } dma_buffer;
179
180 /* Allocate a block of memory suitable for using as a DMA buffer */
181 extern dma_buffer *dma_allocate(unsigned int channel, unsigned int size);
182 /* Deallocate a DMA buffer */
183 extern void dma_free(dma_buffer * buffer);
184 /* Start DMA transfer to or from given buffer */
185 extern void dma_start(dma_buffer * buffer, unsigned long count,
186                                           unsigned char mode);
187
188 #endif /* __DOSDMA_H__ */
189
190 /* ex:set ts=4: */