CoolPotOS/driver/dma.c

63 lines
2.2 KiB
C
Raw Normal View History

2024-05-12 14:34:03 +08:00
#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");
}