3 * Copyright (C) 2007 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
4 * Copyright (C) 2008 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
28 /* Defines for accessing the upper and lower byte of an integer. */
29 #define LOW_BYTE(x) (x & 0x00FF)
30 #define HI_BYTE(x) ((x & 0xFF00) >> 8)
32 /* Quick-access registers and ports for each DMA channel. */
33 unsigned char MaskReg
[8] = { 0x0A, 0x0A, 0x0A, 0x0A, 0xD4, 0xD4, 0xD4, 0xD4 };
34 unsigned char ModeReg
[8] = { 0x0B, 0x0B, 0x0B, 0x0B, 0xD6, 0xD6, 0xD6, 0xD6 };
35 unsigned char ClearReg
[8] = { 0x0C, 0x0C, 0x0C, 0x0C, 0xD8, 0xD8, 0xD8, 0xD8 };
37 unsigned char PagePort
[8] = { 0x87, 0x83, 0x81, 0x82, 0x8F, 0x8B, 0x89, 0x8A };
38 unsigned char AddrPort
[8] = { 0x00, 0x02, 0x04, 0x06, 0xC0, 0xC4, 0xC8, 0xCC };
39 unsigned char CountPort
[8] = { 0x01, 0x03, 0x05, 0x07, 0xC2, 0xC6, 0xCA, 0xCE };
41 void _dma_xfer (unsigned char DMA_channel
, unsigned char page
, unsigned int offset
, unsigned int length
, unsigned char mode
);
43 void dma_xfer (unsigned char channel
, unsigned long address
, unsigned int length
, unsigned char read
)
45 unsigned char page
=0, mode
=0;
46 unsigned int offset
= 0;
49 mode
= 0x48 + channel
;
51 mode
= 0x44 + channel
;
54 offset
= address
& 0xFFFF;
57 _dma_xfer (channel
, page
, offset
, length
, mode
);
60 void _dma_xfer (unsigned char DMA_channel
, unsigned char page
, unsigned int offset
, unsigned int length
, unsigned char mode
)
62 /* Don't let anyone else mess up what we're doing. */
65 /* Set up the DMA channel so we can use it. This tells the DMA */
66 /* that we're going to be using this channel. (It's masked) */
67 outb (MaskReg
[DMA_channel
], 0x04 | DMA_channel
);
69 /* Clear any data transfers that are currently executing. */
70 outb (ClearReg
[DMA_channel
], 0x00);
72 /* Send the specified mode to the DMA. */
73 outb (ModeReg
[DMA_channel
], mode
);
75 /* Send the offset address. The first byte is the low base offset, the */
76 /* second byte is the high offset. */
77 outb (AddrPort
[DMA_channel
], LOW_BYTE(offset
));
78 outb (AddrPort
[DMA_channel
], HI_BYTE(offset
));
80 /* Send the physical page that the data lies on. */
81 outb (PagePort
[DMA_channel
], page
);
83 /* Send the length of the data. Again, low byte first. */
84 outb (CountPort
[DMA_channel
], LOW_BYTE(length
));
85 outb (CountPort
[DMA_channel
], HI_BYTE(length
));
87 /* Ok, we're done. Enable the DMA channel (clear the mask). */
88 outb (MaskReg
[DMA_channel
], DMA_channel
);
90 /* Re-enable interrupts before we leave. */