Emulation of CHS hard drives [Solved]

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
User avatar
Stevo14
Member
Member
Posts: 179
Joined: Fri Mar 07, 2008 3:40 am
Location: Arad, Romania

Emulation of CHS hard drives [Solved]

Post 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.
Last edited by Stevo14 on Thu Jun 12, 2008 12:42 pm, edited 1 time in total.
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: Emulation of CHS hard drives

Post 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
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
User avatar
Stevo14
Member
Member
Posts: 179
Joined: Fri Mar 07, 2008 3:40 am
Location: Arad, Romania

Re: Emulation of CHS hard drives

Post 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.
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: Emulation of CHS hard drives

Post 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
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
svdmeer
Member
Member
Posts: 87
Joined: Tue May 06, 2008 9:32 am
Location: The Netherlands

Post by svdmeer »

Can't you buildin an option at boot or driver-load to force the use of CHS?
User avatar
Stevo14
Member
Member
Posts: 179
Joined: Fri Mar 07, 2008 3:40 am
Location: Arad, Romania

Re: Emulation of CHS hard drives

Post 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?
User avatar
bewing
Member
Member
Posts: 1401
Joined: Wed Feb 07, 2007 1:45 pm
Location: Eugene, OR, US

Post 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.
User avatar
Stevo14
Member
Member
Posts: 179
Joined: Fri Mar 07, 2008 3:40 am
Location: Arad, Romania

Post 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).
User avatar
bewing
Member
Member
Posts: 1401
Joined: Wed Feb 07, 2007 1:45 pm
Location: Eugene, OR, US

Post 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.
User avatar
Stevo14
Member
Member
Posts: 179
Joined: Fri Mar 07, 2008 3:40 am
Location: Arad, Romania

Post 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.
Post Reply