OSDev.org

The Place to Start for Operating System Developers
It is currently Thu Mar 28, 2024 2:34 am

All times are UTC - 6 hours




Post new topic Reply to topic  [ 5 posts ] 
Author Message
 Post subject: [Solved] Weird bug about qemu disk r/w
PostPosted: Thu May 05, 2022 2:11 pm 
Offline

Joined: Fri Nov 12, 2021 1:09 am
Posts: 12
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:
Code:
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]);
}

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:
Code:
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;
   }


Here is the definition of function transfer:
Code:
/*

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){


Last edited by michael on Sat May 14, 2022 4:34 pm, edited 1 time in total.

Top
 Profile  
 
 Post subject: Re: Weird bug about qemu disk r/w
PostPosted: Thu May 05, 2022 2:44 pm 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 5099
Your code to read the disk is missing the part that reads the disk.

How exactly do you calculate node->LBA?


Top
 Profile  
 
 Post subject: Re: Weird bug about qemu disk r/w
PostPosted: Thu May 05, 2022 5:09 pm 
Offline

Joined: Fri Nov 12, 2021 1:09 am
Posts: 12
Octocontrabass wrote:
How exactly do you calculate node->LBA?

I directly put the "block" parameter from transfer into node->LBA.

Octocontrabass wrote:
Your code to read the disk is missing the part that reads the disk.

The code to read the disk is here:
Code:
void read_handler(unsigned long nr, unsigned long parameter){
   struct block_buffer_node *node=((struct request_queue*)parameter)->in_using;

   if(io_in8(PORT_DISK0_STATUS_CMD)&DISK_STATUS_ERROR){
      printk(RED,BLACK,"read_handler: %x\n",io_in8(PORT_DISK0_ERR_FEATURE));
   }else{
      port_insw(PORT_DISK0_DATA,node->buffer,256);
   }

   end_request(node);
}


And here is the disk interrupt handler:
Code:
//Interrupt handler program for disk
void disk_handler(unsigned long nr, unsigned long parameter, struct pt_regs *regs){
    struct block_buffer_node *node=((struct request_queue*)parameter)->in_using;
   disk_request.queue_status=QUEUE_READY_4_NXT;
   node->end_handler(nr,parameter);//call read_handler() for disk here
}

This interrupt code should only be awakened after disk puts all the data into its buffer and send an interrupt.

I've already verified that it is the same node in disk_handler and the core code of transfer. I supposed it is the problem of some internal setting inside the qemu. Since the output is always correct, the only problem is that the changes on the disk doesn't seems like to "synchronized" with image file(except first sector).


Top
 Profile  
 
 Post subject: Re: Weird bug about qemu disk r/w
PostPosted: Thu May 05, 2022 5:18 pm 
Offline
Member
Member

Joined: Mon Mar 25, 2013 7:01 pm
Posts: 5099
michael wrote:
I directly put the "block" parameter from transfer into node->LBA.

How big is your disk image?

michael wrote:
This interrupt code should only be awakened after disk puts all the data into its buffer and send an interrupt.

Where do you wait for the interrupt handler to fill the buffer before you print the buffer? Why aren't you using interrupts to write to the disk? How does your interrupt handler know that the interrupt is due to a read and not some other command?


Top
 Profile  
 
 Post subject: Re: Weird bug about qemu disk r/w
PostPosted: Thu May 05, 2022 5:21 pm 
Offline

Joined: Fri Nov 12, 2021 1:09 am
Posts: 12
Octocontrabass wrote:
michael wrote:
I directly put the "block" parameter from transfer into node->LBA.

How big is your disk image?

michael wrote:
This interrupt code should only be awakened after disk puts all the data into its buffer and send an interrupt.

Where do you wait for the interrupt handler to fill the buffer before you print the buffer? Why aren't you using interrupts to write to the disk? How does your interrupt handler know that the interrupt is due to a read and not some other command?


I've just found the data supposed to be written in 0x200 appear in 0x20000, probably know the reason
Sorry for disturb :)


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 5 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: DotBot [Bot] and 72 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group