63 lines
2.2 KiB
C
63 lines
2.2 KiB
C
|
#include "../include/dma.h"
|
|||
|
#include "../include/io.h"
|
|||
|
|
|||
|
unsigned char MaskReg[8] = {0x0A, 0x0A, 0x0A, 0x0A, 0xD4, 0xD4, 0xD4, 0xD4};
|
|||
|
unsigned char ModeReg[8] = {0x0B, 0x0B, 0x0B, 0x0B, 0xD6, 0xD6, 0xD6, 0xD6};
|
|||
|
unsigned char ClearReg[8] = {0x0C, 0x0C, 0x0C, 0x0C, 0xD8, 0xD8, 0xD8, 0xD8};
|
|||
|
|
|||
|
unsigned char PagePort[8] = {0x87, 0x83, 0x81, 0x82, 0x8F, 0x8B, 0x89, 0x8A};
|
|||
|
unsigned char AddrPort[8] = {0x00, 0x02, 0x04, 0x06, 0xC0, 0xC4, 0xC8, 0xCC};
|
|||
|
unsigned char CountPort[8] = {0x01, 0x03, 0x05, 0x07, 0xC2, 0xC6, 0xCA, 0xCE};
|
|||
|
|
|||
|
void dma_xfer(unsigned char channel, unsigned long address, unsigned int length,
|
|||
|
unsigned char read) {
|
|||
|
unsigned char page = 0, mode = 0;
|
|||
|
unsigned int offset = 0;
|
|||
|
|
|||
|
if (read)
|
|||
|
mode = 0x48 + channel;
|
|||
|
else
|
|||
|
mode = 0x44 + channel;
|
|||
|
|
|||
|
page = address >> 16;
|
|||
|
offset = address & 0xFFFF;
|
|||
|
length--;
|
|||
|
|
|||
|
_dma_xfer(channel, page, offset, length, mode);
|
|||
|
}
|
|||
|
|
|||
|
void _dma_xfer(unsigned char DMA_channel, unsigned char page,
|
|||
|
unsigned int offset, unsigned int length, unsigned char mode) {
|
|||
|
/* 我们不想别的事情来打扰 */
|
|||
|
asm("cli");
|
|||
|
|
|||
|
/* 设置DMA通道,以便我们可以正确传输数据,这很简单,只要我们用I/O操作告诉DMA控制器就行了
|
|||
|
*/
|
|||
|
/* 我们将使用这个通道(DMA_channel)*/
|
|||
|
io_out8(MaskReg[DMA_channel], 0x04 | DMA_channel);
|
|||
|
|
|||
|
/* 我们先得解除DMA对这个通道的屏蔽,不然用不了 */
|
|||
|
io_out8(ClearReg[DMA_channel], 0x00);
|
|||
|
|
|||
|
/* 向DMA发送指定的模式 */
|
|||
|
io_out8(ModeReg[DMA_channel], mode);
|
|||
|
|
|||
|
/* 发送偏移量地址,先发送高八位,再发送低八位(因为一次性最多只能发送一个byte)
|
|||
|
*/
|
|||
|
io_out8(AddrPort[DMA_channel], LOW_BYTE(offset));
|
|||
|
io_out8(AddrPort[DMA_channel], HI_BYTE(offset));
|
|||
|
|
|||
|
/* 发送数据所在的物理页 */
|
|||
|
io_out8(PagePort[DMA_channel], page);
|
|||
|
|
|||
|
/* 发送数据的长度 跟之前一样,先发送低八位,再发送高八位*/
|
|||
|
io_out8(CountPort[DMA_channel], LOW_BYTE(length));
|
|||
|
io_out8(CountPort[DMA_channel], HI_BYTE(length));
|
|||
|
|
|||
|
/* 现在我们该做的东西已经全部做完了,所以启用DMA_channel */
|
|||
|
io_out8(MaskReg[DMA_channel], DMA_channel);
|
|||
|
|
|||
|
/* 重新让CPU能够接收到中断 */
|
|||
|
asm("sti");
|
|||
|
}
|