欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 教育 > 锐评 > 硬盘dma读写过程

硬盘dma读写过程

2025/11/8 17:59:04 来源:https://blog.csdn.net/enrique11/article/details/144637220  浏览:    关键词:硬盘dma读写过程

pci初始化时,遍历pci上的设置,如果BaseClassCode==1,则为大容量存储控制器,包括硬盘控制器、固态硬盘控制器、光盘驱动控制器、RAID控制器等。

BaseAdder4为DMA控制器基地址,包含两个控制器,主控制器,次控制器,每个占8字节。

dma只能使用物理地址,最好开启硬盘状态中断。

具体过程见代码

//主控制器占8位,次控制器占用8字节,意义相同
#define DMA_COMMAND_REG     0            // dma主控命令寄存器的偏移 1字节,第1、3字节保留,没有用途
//第3位置为0时,表示读扇区,DMA传送方向为从IDE设备到内存;为1时,表示写扇区,方向为从内存到IDE设备。
//第0位置为0时,表示停止DMA传输;为1时表示启动DMA传输
//
#define DMA_STATUS_REG      2            // dma主控状态寄存器的偏移
//第0位置为1时,正在进行DMA传输;第1位置为1时,表示DMA传送出现了一个错误;
//第2位置为1时,IDE设备已产生一个中断请求(DMA传输已完成);
//第5位置为1时,表示设备0(主盘)能够执行DMA操作;
//第6位置为1时,表示设备1(从盘)能够执行DMA操作;
//第7位置为1时,表示设备0和设备1不能同时执行DMA操作。#define DMA_PRD_ADDR_REG     4            // 物理区域描述符指针寄存器的偏移
//物理区域描述符表,连续排列,每个项占8字节,typedef struct {DWORD addr; //前4位为缓存区物理地址,WORD len; 	//当前块长度,WORD EOT; 	//只使用最高位
}__attribute__((packed)) PRD_ADD;
#define pio_base_addr1      0x01F0        // 主ATA设备控制块寄存器基地址
#define pio_base_addr2      0x03F0        // 主ATA命令命令块寄存器基地址
void dma_read_sectors(DWORD bmcr_base_addr, DWORD lbaSector, PVOID buf,WORD len) {PRD_ADD prdBufAddr;             //物理区域描述符地址//	bufferaddr               // 内存缓冲区地址// Start/Stop=0, 停止以前的DMA传输WritePortByte(bmcr_base_addr + DMA_COMMAND_REG, 0x00);// 清除主控状态寄存器的Interrupt和Error位WritePortByte(bmcr_base_addr + DMA_STATUS_REG, 6);//物理区域描述符表,连续排列	EOT=1 表示为最后一个prdBufAddr.addr = (DWORD) buf;	//这里应为物理地址prdBufAddr.len= len; //len应小于或等于0x200prdBufAddr.EOT = 0x8000; //最高位为EOT// 物理区域描述符的地址写入PRDTRWritePortDword(bmcr_base_addr + DMA_PRD_ADDR_REG,MiGetPhysics(&prdBufAddr));// 主控命令寄存器的R/W=1, 表示写入内存(读取硬盘)WritePortByte(bmcr_base_addr + DMA_COMMAND_REG, 8);// 等待硬盘BSY=0和DRQ=0//busy_wait();// 设置设备/磁头寄存器的DEV=0WritePortByte( pio_base_addr1 + 6, 00);// 等待硬盘BSY=0和DRQ=0//busy_wait();// 设备控制寄存器的nIEN=0, 允许中断WritePortByte( pio_base_addr2 + 6, 00);// 设置ATA寄存器WritePortByte( pio_base_addr1 + 1, 00);	// =00WritePortByte( pio_base_addr1 + 2, 1);	// numSect扇区数量WritePortByte( pio_base_addr1 + 3, lbaSector >> 0);	// LBA第7~0位WritePortByte( pio_base_addr1 + 4, lbaSector >> 8);	// LBA第15~8位WritePortByte( pio_base_addr1 + 5, lbaSector >> 16);	// LBA第23~16位// 设备/磁头寄存器:LBA=1, DEV=0, LBA第27~24位WritePortByte( pio_base_addr1 + 6, 0x40 | (lbaSector >> 24));// 设置ATA命令寄存器WritePortByte( pio_base_addr1 + 7, 0x0C8);	// 0C8h=Read DMA// 读取主控命令寄存器和主控状态寄存器ReadPortByte(bmcr_base_addr + DMA_COMMAND_REG);ReadPortByte(bmcr_base_addr + DMA_STATUS_REG);// 主控命令寄存器的R/W=1,Start/Stop=1, 启动DMA传输WritePortByte(bmcr_base_addr + DMA_COMMAND_REG, 9);// 现在开始DMA数据传送// 检查主控状态寄存器, Interrupt=1时,传送结束//mov 	ecx, 4000hnotAsserted: while (!(ReadPortByte(bmcr_base_addr + DMA_STATUS_REG) & 4)) {hlt();};// 清除主控状态寄存器的Interrupt位WritePortByte(bmcr_base_addr + DMA_STATUS_REG, 4);// 读取主控状态寄存器ReadPortByte(bmcr_base_addr + DMA_STATUS_REG);// 主控命令寄存器的Start/Stop=0, 结束DMA传输WritePortByte(bmcr_base_addr + DMA_COMMAND_REG, 00);
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词