阅读:1102回复:0
IDE DMA 驱动问题(大虾帮忙洛)
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); } |
|