Page 1 of 1

Emulation of CHS hard drives [Solved]

Posted: Mon Jun 09, 2008 2:36 pm
by Stevo14
Does anyone know if it is possible to get either Qemu or Bochs to emulate a hard drive that only supports CHS? I was testing my OS on an old (ancient) computer and realized that its hard drive didn't support LBA (or at least that is what it told me from the identify command). My kernel only supports LBA right now so I though this would be a good opportunity to add support for legacy CHS addressing. Now what I need is a proper way (hopefully in an emulator) to test the CHS -> LBA and LBA -> CHS conversion code.

Re: Emulation of CHS hard drives

Posted: Mon Jun 09, 2008 7:02 pm
by Brendan
Hi,
Stevo14 wrote:Does anyone know if it is possible to get either Qemu or Bochs to emulate a hard drive that only supports CHS? I was testing my OS on an old (ancient) computer and realized that its hard drive didn't support LBA (or at least that is what it told me from the identify command). My kernel only supports LBA right now so I though this would be a good opportunity to add support for legacy CHS addressing. Now what I need is a proper way (hopefully in an emulator) to test the CHS -> LBA and LBA -> CHS conversion code.
Could you simply modify your code that detects if the hard drive supports LBA, so that the rest of the OS thinks the hard drive doesn't support LBA when it actually does?

Cheers,

Brendan

Re: Emulation of CHS hard drives

Posted: Mon Jun 09, 2008 11:43 pm
by Stevo14
Brendan wrote:Hi,
Stevo14 wrote:Does anyone know if it is possible to get either Qemu or Bochs to emulate a hard drive that only supports CHS? I was testing my OS on an old (ancient) computer and realized that its hard drive didn't support LBA (or at least that is what it told me from the identify command). My kernel only supports LBA right now so I though this would be a good opportunity to add support for legacy CHS addressing. Now what I need is a proper way (hopefully in an emulator) to test the CHS -> LBA and LBA -> CHS conversion code.
Could you simply modify your code that detects if the hard drive supports LBA, so that the rest of the OS thinks the hard drive doesn't support LBA when it actually does?
I've done something similar to that already. All reads and writes are addressed in LBA but if the drive doesn't support LBA, the address is converted to CHS on the fly before being sent to the drive. The code is already written, but now I need a way to test it and debug it without constantly transferring the kernel and rebooting.

Re: Emulation of CHS hard drives

Posted: Tue Jun 10, 2008 3:32 am
by Brendan
Hi,
Stevo14 wrote:
Brendan wrote:Could you simply modify your code that detects if the hard drive supports LBA, so that the rest of the OS thinks the hard drive doesn't support LBA when it actually does?
I've done something similar to that already. All reads and writes are addressed in LBA but if the drive doesn't support LBA, the address is converted to CHS on the fly before being sent to the drive. The code is already written, but now I need a way to test it and debug it without constantly transferring the kernel and rebooting.
Let me rephrase:
"All reads and writes are addressed in LBA but if the drive doesn't support LBA (or if you modify the code to pretend that LBA isn't supported), the address is converted to CHS on the fly before being sent to the drive."

I checked the source code for Bochs, and it's hard drive interface does support both LBA and CHS. Your code detects that LBA is supported and then chooses to use LBA for the hard drive interface, but it could choose to use CHS for the hard drive interface instead.


Cheers,

Brendan

Posted: Tue Jun 10, 2008 5:50 am
by svdmeer
Can't you buildin an option at boot or driver-load to force the use of CHS?

Re: Emulation of CHS hard drives

Posted: Tue Jun 10, 2008 1:56 pm
by Stevo14
Brendan wrote: (or if you modify the code to pretend that LBA isn't supported)
Ah, ok. Sorry I mis-understood you before. I just did this. It seems to work in Qemu and Bochs (EDIT: I was wrong, it doesn't work after all) but errors on the real hardware. I will look into this more. Here is how I translate and send the CHS values to the drive:

Code: Select all

int ata_seek(ata_drive_t *d, unsigned int block)
{
	//null pointer
	if(d == 0)
		return -1;

	d->current_block = block;

	if(d->mode == ATA_LBA )
	{//lba addressing
		outportb(d->ports.LBA_low, d->current_block);
  		outportb(d->ports.LBA_mid,  d->current_block >> 8);
   	outportb(d->ports.LBA_high,  d->current_block >> 16);
   	outportb(d->ports.drive_head, d->id | ((d->current_block >> 24) & 0x0F));
	}
	else
	{//CHS addressing

		unsigned int cyl = d->current_block / (d->heads * d->sectors);
		unsigned int tmp = d->current_block % (d->heads * d->sectors);
		unsigned int head = tmp / d->sectors;
		unsigned int sect = tmp % d->sectors + 1;
	
		outportb(d->ports.LBA_low, sect);
  		outportb(d->ports.LBA_mid, cyl);
   	outportb(d->ports.LBA_high, cyl >> 8);
   	outportb(d->ports.drive_head, d->id | head);
	}
	
	return 0;
}
(note that d->id would be 0xA0 for the master CHS drive)
Is this correct?

Posted: Tue Jun 10, 2008 3:57 pm
by bewing
Yes, the code you posted looks right (when using an id of 0xA0, as you say) -- but make sure that you note that timing issues are MUCH more vital on real hardware when you are dealing with a CHS-only drive.

Posted: Wed Jun 11, 2008 12:05 am
by Stevo14
bewing wrote:but make sure that you note that timing issues are MUCH more vital on real hardware when you are dealing with a CHS-only drive.
Thanks for looking over the code. I made some changes elsewhere in the ATA detection code and it now seems to work in emulators but not on real hardware (again...). Probably due to timing issues like you said (as the command doesn't error but bogus data is read/returned).

Posted: Wed Jun 11, 2008 6:49 pm
by bewing
Well, if timing is the issue then be sure to check the wiki. I put quite a bit of timing info in there, for PIO mode stuff like this.

Posted: Thu Jun 12, 2008 12:39 pm
by Stevo14
Ok, so I solved the problem. A good look through the ATA spec showed me that I was not waiting for the proper flags in the status register at the correct times. It worked on the emulated drives (and on real hard drives if they were new) because they just happened to have the data ready before I started reading it. :roll: But regardless, I now have a (more) standards-compliant ATA hard disk driver! :)

Thanks everyone for your help.