* Christmas edition *; fixed irc /os command; small cleanup in fd.c; improvements...
[ZeXOS.git] / libc / x86 / dma.c
blob1b61b5b63d176c90cae2afc7d9f3dcf1f0a09f83
1 /*
2 * ZeX/OS
3 * Copyright (C) 2007 Tomas 'ZeXx86' Jedrzejek (zexx86@gmail.com)
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * This program 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
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "x86.h"
21 #include "dma.h"
23 /* Just helps in making things look cleaner. :) */
24 typedef unsigned char uchar;
25 typedef unsigned int uint;
27 /* Defines for accessing the upper and lower byte of an integer. */
28 #define LOW_BYTE(x) (x & 0x00FF)
29 #define HI_BYTE(x) ((x & 0xFF00) >> 8)
31 /* Quick-access registers and ports for each DMA channel. */
32 uchar MaskReg[8] = { 0x0A, 0x0A, 0x0A, 0x0A, 0xD4, 0xD4, 0xD4, 0xD4 };
33 uchar ModeReg[8] = { 0x0B, 0x0B, 0x0B, 0x0B, 0xD6, 0xD6, 0xD6, 0xD6 };
34 uchar ClearReg[8] = { 0x0C, 0x0C, 0x0C, 0x0C, 0xD8, 0xD8, 0xD8, 0xD8 };
36 uchar PagePort[8] = { 0x87, 0x83, 0x81, 0x82, 0x8F, 0x8B, 0x89, 0x8A };
37 uchar AddrPort[8] = { 0x00, 0x02, 0x04, 0x06, 0xC0, 0xC4, 0xC8, 0xCC };
38 uchar CountPort[8] = { 0x01, 0x03, 0x05, 0x07, 0xC2, 0xC6, 0xCA, 0xCE };
40 void _dma_xfer(uchar DMA_channel, unsigned char page, unsigned int offset, unsigned int length, uchar mode);
42 void dma_xfer(uchar channel, unsigned long address, unsigned int length, unsigned char read)
44 unsigned char page=0, mode=0;
45 unsigned int offset = 0;
47 if(read)
48 mode = 0x48 + channel;
49 else
50 mode = 0x44 + channel;
52 page = address >> 16;
53 offset = address & 0xFFFF;
54 length--;
56 _dma_xfer(channel, page, offset, length, mode);
60 void _dma_xfer(uchar DMA_channel, unsigned char page, unsigned int offset, unsigned int length, uchar mode)
62 /* Don't let anyone else mess up what we're doing. */
63 asm("cli");
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 outportb(MaskReg[DMA_channel], 0x04 | DMA_channel);
69 /* Clear any data transfers that are currently executing. */
70 outportb(ClearReg[DMA_channel], 0x00);
72 /* Send the specified mode to the DMA. */
73 outportb(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 outportb(AddrPort[DMA_channel], LOW_BYTE(offset));
78 outportb(AddrPort[DMA_channel], HI_BYTE(offset));
80 /* Send the physical page that the data lies on. */
81 outportb(PagePort[DMA_channel], page);
83 /* Send the length of the data. Again, low byte first. */
84 outportb(CountPort[DMA_channel], LOW_BYTE(length));
85 outportb(CountPort[DMA_channel], HI_BYTE(length));
87 /* Ok, we're done. Enable the DMA channel (clear the mask). */
88 outportb(MaskReg[DMA_channel], DMA_channel);
90 /* Re-enable interrupts before we leave. */
91 asm("sti");