Cleanup in elf.c with .bss section clean; adm command mounts cdrom instead of floppy...
[ZeXOS.git] / kernel / lib / x86 / dma.c
blobd24dd7efb1f4ee4576dab6abde05c8fdb69f28e2
1 /*
2 * ZeX/OS
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/>.
21 #include <system.h>
22 #include <arch/io.h>
23 #include <dma.h>
24 #include <build.h>
26 #ifdef ARCH_i386
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;
48 if(read)
49 mode = 0x48 + channel;
50 else
51 mode = 0x44 + channel;
53 page = address >> 16;
54 offset = address & 0xFFFF;
55 length--;
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. */
63 int_disable ();
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. */
91 int_enable ();
93 #endif