duren12345
驱动牛犊
驱动牛犊
  • 注册日期2005-02-21
  • 最后登录2005-05-22
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
阅读:1102回复:0

IDE DMA 驱动问题(大虾帮忙洛)

楼主#
更多 发布于:2005-04-05 10:05
DOS下的IDE DMA驱动,不知为什么启动后就给出
BUS MASATER ABORT的错误
我用的芯片是82801DB ICH4

所有的芯片的设置是BIOS自动设置,启动DMA流程如下:
1) Software prepares a PRD Table in system memory. Each PRD is 8 bytes long and consists of an
address pointer to the starting address and the transfer count of the memory buffer to be
transferred. In any given PRD Table, two consecutive PRDs are offset by 8-bytes and are aligned
on a 4-byte boundary.
2) Software provides the starting address of the PRD Table by loading the PRD Table Pointer
Register . The direction of the data transfer is specified by setting the Read/Write Control bit.
Clear the Interrupt bit and Error bit in the Status register.
3) Software issues the appropriate DMA transfer command to the disk device.
4) Engage the bus master function by writing a \'1\' to the Start bit in the Bus Master IDE Command
Register for the appropriate channel.
5) The controller transfers data to/from memory responding to DMA requests from the IDE device.
6) At the end of the transfer the IDE device signals an interrupt.
7) In response to the interrupt, software resets the Start/Stop bit in the command register. It then
reads the controller status and then the drive status to determine if the transfer completed
successfully.

程序:

void start_dma_transfer(unsigned int channel,unsigned char dir,unsigned long transfer_length)
{


 unsigned char *p_tmp;
 unsigned long addr_tmp;

 p_tmp =prd;
 addr_tmp =(unsigned long)prd;

 switch(addr_tmp &0x3)
 {
    case 3:
    p_tmp ++;
    break;
    case 2:
    p_tmp +=2;
    break;
    case 1:
    p_tmp +=3;
    break;
    default:
    break;
 }


 //prd table
 p_tmp[0] =0x10;//((unsigned long)data)&0xf0;
 p_tmp[1] =0xfc;//((unsigned long)data>>8)&0xff;
 p_tmp[2] =0xbf;//((unsigned long)data>>16)&0xff;
 p_tmp[3] =0xfe;//((unsigned long)data>>24)&0xff;

 p_tmp[4] =3;//transfer_length &0xfe;
 p_tmp[5] =0xff;//(transfer_length>>8)&0xff;
 p_tmp[6] =0;
 p_tmp[7] =0x80;

          addr_tmp =((unsigned long) p_tmp)&0xff;
 outportb(ide_dma_base +4,addr_tmp);
 addr_tmp =((unsigned long)(p_tmp)>>8)&0xff;
 outportb(ide_dma_base +5,addr_tmp);
 addr_tmp =((unsigned long)(p_tmp)>>16)&0xff;
 outportb(ide_dma_base +6,addr_tmp);
 addr_tmp =((unsigned long)(p_tmp)>>24)&0xff;
 outportb(ide_dma_base +7,addr_tmp);

 outportb(ide_dma_base +0x0c,((unsigned long)p_tmp)&0xff);
 outportb(ide_dma_base +0x0d,(((unsigned long)p_tmp)>>8)&0xff);
 outportb(ide_dma_base +0x0e,(((unsigned long)p_tmp)>>16)&0xff);
 outportb(ide_dma_base +0x0f,(((unsigned long)p_tmp)>>24)&0xff);

addr_tmp =inportb(ide_dma_base +7) ;
addr_tmp =(addr_tmp <<8) +inportb(ide_dma_base +6) ;
addr_tmp =(addr_tmp <<8) +inportb(ide_dma_base +5) ;
addr_tmp =(addr_tmp <<8) +inportb(ide_dma_base +4) ;
 //clear interrupt and error bit in the status register
 if(channel ==dma_channel_pri)
 {
if(dir ==dma_write)
{
outportb(cmd_reg_pri,8);
outportb(status_reg_pri,inportb(status_reg_pri)|0x6);
set_ide_config_byte(7,0x28);
cprintf(\"the status register is: %xh\\r\\n\",inportb(status_reg_pri));
outportb(cmd_reg_pri,9);
}
else if(dir==dma_read)
{
outportb(cmd_reg_pri,0);
outportb(status_reg_pri,inportb(status_reg_pri)|0x6);
set_pci_config_byte(0,30,0,0x3e,get_pci_config_byte(0,30,0,0x3e)|0x02);
set_ide_config_byte(7,0x28);
outportb(cmd_reg_pri,1);
}
}
else if(channel ==dma_channel_second)
{
if(dir ==dma_write)
{
outportb(cmd_reg_second,8);
outportb(status_reg_second,inportb(status_reg_second)|0x6);
set_ide_config_byte(7,0x28);
outportb(cmd_reg_second,9);
}
else if(dir ==dma_read)
{
outportb(cmd_reg_second,0);
outportb(status_reg_second,inportb(status_reg_second)|0x6);
set_ide_config_byte(7,0x28);
outportb(cmd_reg_second,1);
}
}
outportb(status_reg_second,inportb(status_reg_second)|0x6);
outportb(status_reg_pri,inportb(status_reg_pri)|0x6);
}



游客

返回顶部