[Solved] Weird bug about qemu disk r/w
Posted: Thu May 05, 2022 2:11 pm
I've inserted a full 0 raw disk image file into qemu as hdd with parameter -hda disk.img. Then, I use following codes to test whether my driver works or not:
The code runs well under any condition, output is always 512 bytes full 1 array no matter which address I choose to start. But when I check my image file (using hexedit disk.img), I cannot find any changes on it. After that I comment the write operation on the code and reload my kernel, the screen still shows 512 bytes full 1 array, but there're nothing changes on the image file.
PS: The only one exception this code works well is when LBA address start with 0, screen can print 512 bytes full 1 array and image file can also preserve the modifications on the first sector.
Here is core code for function transfer:
Here is the definition of function transfer:
Code: Select all
unsigned char buf[512];
memset(buf,1,512);
transfer(ATA_WRITE_CMD,0x200,1,(unsigned char*)buf);//write one sector data from buf to LBA: 0x200 in disk
memset(buf,0,512);
transfer(ATA_READ_CMD,0x200,1,(unsigned char*)buf);//read one sector data from LBA: 0x200 to buf
for(int i=0;i<512;i++){
printk(RED,YELLOW,"%x ",buf[i]);
}
PS: The only one exception this code works well is when LBA address start with 0, screen can print 512 bytes full 1 array and image file can also preserve the modifications on the first sector.
Here is core code for function transfer:
Code: Select all
switch(node->cmd){
case ATA_WRITE_CMD:
io_out8(PORT_DISK0_DEVICE,0x40);
// 48 bits LBA address, should divide in to two part and send each of them
io_out8(PORT_DISK0_ERR_FEATURE,0);
io_out8(PORT_DISK0_SECTOR_CNT, (node->count>>8) &0xff);
io_out8(PORT_DISK0_SECTOR_LOW, (node->LBA>>24) &0xff);
io_out8(PORT_DISK0_SECTOR_MID, (node->LBA>>32) &0xff);
io_out8(PORT_DISK0_SECTOR_HIGH, (node->LBA>>40) &0xff);
io_out8(PORT_DISK0_ERR_FEATURE,0);
io_out8(PORT_DISK0_SECTOR_CNT, (node->count) &0xff);
io_out8(PORT_DISK0_SECTOR_LOW, (node->LBA) &0xff);
io_out8(PORT_DISK0_SECTOR_MID, (node->LBA>>8) &0xff);
io_out8(PORT_DISK0_SECTOR_HIGH, (node->LBA>>16) &0xff);
//if disk not ready, wait
while(!(io_in8(PORT_DISK0_STATUS_CMD)&DISK_STATUS_READY)){
nop();
}
io_out8(PORT_DISK0_STATUS_CMD,node->cmd);
//if disk not require for data, wait
while(!(io_in8(PORT_DISK0_STATUS_CMD)&DISK_STATUS_REQ)){
nop();
}
port_outsw(PORT_DISK0_DATA,node->buffer,256);
break;
case ATA_READ_CMD:
io_out8(PORT_DISK0_DEVICE,0x40);
io_out8(PORT_DISK0_ERR_FEATURE,0);
io_out8(PORT_DISK0_SECTOR_CNT, (node->count>>8) &0xff);
io_out8(PORT_DISK0_SECTOR_LOW, (node->LBA>>24) &0xff);
io_out8(PORT_DISK0_SECTOR_MID, (node->LBA>>32) &0xff);
io_out8(PORT_DISK0_SECTOR_HIGH, (node->LBA>>40) &0xff);
io_out8(PORT_DISK0_ERR_FEATURE,0);
io_out8(PORT_DISK0_SECTOR_CNT, (node->count) &0xff);
io_out8(PORT_DISK0_SECTOR_LOW, (node->LBA) &0xff);
io_out8(PORT_DISK0_SECTOR_MID, (node->LBA>>8) &0xff);
io_out8(PORT_DISK0_SECTOR_HIGH, (node->LBA>>16) &0xff);
//if disk not ready, wait
while(!io_in8(PORT_DISK0_STATUS_CMD)&DISK_STATUS_READY){
nop();
}
io_out8(PORT_DISK0_STATUS_CMD,node->cmd);
break;
default:
printk(BLACK,WHITE,"ATA CMD ERROR\n");
break;
}
Code: Select all
/*
cmd: ATA_READ_CMD or ATA_WRITE_CMD
blocks: LBA address
count: number of sectors
*buffer: I/O buffer address
*/
unsigned long transfer(long cmd, unsigned long blocks, long count, unsigned char *buffer){