📄 dma.cpp
字号:
/*
* Copyright (C) 2004, Thejesh AP. All rights reserved.
*/
#include <sys\types.h>
#include <stdlib.h>
#include <string.h>
#include <fs\devmgr.h>
#include <drivers\console.h>
#include <drivers\dma.h>
extern device_manager _dev_mgr;
byte DMA::ADDR_REG[8] = {0x00,0x02,0x04,0x06,0xc0,0xc2,0xc4,0xc6};
byte DMA::COUNT_REG[8] = {0x01,0x03,0x05,0x07,0xc1,0xc3,0xc5,0xc7};
byte DMA::PAGE_REG[8] = {0x87,0x83,0x81,0x82,0x8f,0x8b,0x89,0x8a};
DMA::DMA(char *name):driver(name)
{
int err;
if(err = _dev_mgr.register_driver(1,this->name,0,dma_main)<0)
{
cout<<"register_driver ERROR : "<<this->name<<" "<<err<<endl;
return;
}
cout<<"DMA driver succesfully registered [name] = "<<this->name<<endl;
outportb(COMMAND_REG(1),0x14); //fixed prio,disable DMA1
outportb(COMMAND_REG(2),0x14); //fixed prio,disable DMA2
outportb(MASTER_CLR_REG(1),0x00); //reset DMA1
outportb(MASTER_CLR_REG(2),0x00); //reset DMA2
outportb(COMMAND_REG(1),0x10); //enable DMA1
outportb(COMMAND_REG(2),0x10); //enable DMA2
for(int i=0;i<4;i++) //for all channels
{
outportb(MODE_REG(1),(0x40+i)); //mode : single transfer
outportb(MODE_REG(2),(0x40+i)); //type : verify transfer
}
outportb(CLR_MASK_REG(1),0x00); //enable channels 0-3
outportb(CLR_MASK_REG(2),0x00); //enable channels 4-7
}
DMA::~DMA()
{
int err;
if((err = _dev_mgr.deregister_driver(this->name))<0)
{
cout<<"deregister driver ERROR : "<<this->name<<" "<<err<<endl;
return;
}
}
int DMA::set_DMA(DMA_req *req)
{
byte mode_val = 0;
mode_val = req->mode | req->type;
mode_val |= (req->channel <= 3) ? req->channel : (req->channel-4);
DMA_mem mem;
make_DMA_addrs(mem,(uint)req->buf,req->size-1);
cli();
if(req->channel <= 3)
{
outportb(CHAN_MASK_REG(1),(0x04 | req->channel));
outportb(MODE_REG(1),mode_val);
outportb(RES_FF_REG(1),0x00);
}
else
{
outportb(CHAN_MASK_REG(2),(0x04 | (req->channel-4)));
outportb(MODE_REG(2),mode_val);
outportb(RES_FF_REG(2),0x00);
}
outportb(ADDR_REG[req->channel],mem.lbyte);
outportb(ADDR_REG[req->channel],mem.hbyte);
outportb(PAGE_REG[req->channel],mem.page);
(req->channel <= 3) ? outportb(RES_FF_REG(1),0x00) : outportb(RES_FF_REG(2),0x00);
outportb(COUNT_REG[req->channel],LO_BYTE(mem.length));
outportb(COUNT_REG[req->channel],HI_BYTE(mem.length));
(req->channel <= 3) ? outportb(CHAN_MASK_REG(1),req->channel)
: outportb(CHAN_MASK_REG(2),req->channel-4);
sti();
return 0;
}
void DMA::make_DMA_addrs(DMA_mem &mem,uint addrs,ushort size)
{
mem.page = (addrs>>16) & 0xFF;
mem.hbyte = (addrs>>8) & 0xFF;
mem.lbyte = addrs & 0xFF;
mem.length = size;
}
DMA _DMA_obj("DMA");
int dma_main(void *req)
{
return _DMA_obj.set_DMA((DMA_req*)req);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -