IDE drives on emulators

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
KodyKinzel
Posts: 7
Joined: Tue Jan 05, 2010 7:37 pm
Contact:

IDE drives on emulators

Post by KodyKinzel »

Do emulators (namely Bochs and VirtualBox) support Bus Master IDE and DMA? I have tried to detect IDE drives in my OS project and it always comes up saying that there are none. Are there special settings that need to be set in order to make it work properly? The class code, subclass code, and vendor ID repeatedly come back as xFFFF. I have it loop through each bus and each device with numbers 1 and 2. Is this what I'm doing wrong? I have read through all the wiki articles on the topic and read the Intel specification, but none were any help in the direction of detecting IDEs.
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: IDE drives on emulators

Post by Combuster »

Bochs does support PCI IDE, but I couldn't find success stories about DMA even though google suggests it is supported.

In any case, you need to provide bochs with the settings to enable an IDE controller and the i440fx chipset before trying to use PCI otherwise it will indeed shout at you that there are no plug-and-play devices. Check the documentation and sample bochsrc for the settings you want.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
xyzzy
Member
Member
Posts: 391
Joined: Wed Jul 25, 2007 8:45 am
Libera.chat IRC: aejsmith
Location: London, UK
Contact:

Re: IDE drives on emulators

Post by xyzzy »

KodyKinzel wrote:Do emulators (namely Bochs and VirtualBox) support Bus Master IDE and DMA?
VirtualBox does, DMA works with my ATA driver on it.
KodyKinzel wrote:I have it loop through each bus and each device with numbers 1 and 2. Is this what I'm doing wrong?
Do you mean you're only looking at 2 devices on each bus? There's a maximum of 32 devices per bus. For me, on VirtualBox the IDE controller is on bus 0, device 1, function 1. Are you sure your PCI detection code is correct?
KodyKinzel
Posts: 7
Joined: Tue Jan 05, 2010 7:37 pm
Contact:

Re: IDE drives on emulators

Post by KodyKinzel »

Code: Select all

u32int pciConfigReadDword(u16int bus, u16int device, u16int func, u16int register_number) //read a dword of configuration
{
	u32int lbus = (u32int)bus;
	u32int ldevice = (u32int)device;
	u32int lfunc = (u32int)func;
	u32int lregister = (u32int)register_number;

	u32int address = ((0x1<<31) | (lbus<<16) | (ldevice<<11) | (lfunc<<8) | (lregister<<2)); //create the address

	outl(0xCF8, address); //send it out to port CF8

	return inl(0xCFC); //read and return port CFC
}

u8int checkForIDE(u16int bus, u16int device, u16int func) //check if a particular bus, device, function combination is an IDE
{
	u32int rawRegister = pciConfigReadDword(bus, device, func, 0x8); //read in the raw data
	u16int classword = (u16int)(rawRegister>>16); //get the word with the class information
	u8int classcode = (u8int)(classword>>8); //get the class
	u8int subclasscode = (u8int)(classword<<8); //get the subclass
	if (classcode == 0x1 && subclasscode == 0x1) //check if they are 0x1
		return 1; //if so, it's an IDE
}

void detectIDEs() //detect any IDEs present
{
	u16int busIndex, deviceIndex, funcIndex; //declar the index variables
	for (busIndex; busIndex <= 32; busIndex++) //loop through the buses
	{
		for (deviceIndex; deviceIndex <= 32; deviceIndex++) //loop through the devices
		{
			for (funcIndex; funcIndex <= 32; funcIndex++) //loop through the functions
			{
				if (checkForIDE(busIndex, deviceIndex, funcIndex)) //check for an IDE
				{
					//for now, print a message if there is one
					kprint("IDE detected: ");
					kprint_hex(busIndex);
					kput(':');
					kprint_hex(deviceIndex);
					kput(';');
					kprint_hex(funcIndex);
					kput('\n');
				}
			}
			funcIndex = 0x0; //ready the function number to be used again
		}
		deviceIndex = 0x0; //ready the device number to be used again
	}
}
This is my IDE code. It looks fine to me. I'm sorry if I totally messed it up, I've had trouble finding good documentation. Can anyone see anything clearly wrong with it?
xyzzy
Member
Member
Posts: 391
Joined: Wed Jul 25, 2007 8:45 am
Libera.chat IRC: aejsmith
Location: London, UK
Contact:

Re: IDE drives on emulators

Post by xyzzy »

Code: Select all

u32int address = ((0x1<<31) | (lbus<<16) | (ldevice<<11) | (lfunc<<8) | (lregister<<2));
The left shift for the register is incorrect - the register must be in the low 8 bits of the address, but the lowest 2 bits must be cleared (4-byte aligned).

Also, why are you not initialising the indexes variables to 0 in your for loop initialiser?
I'm sorry if I totally messed it up
No need to apologise :)
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: IDE drives on emulators

Post by Combuster »

AlexExtreme wrote:

Code: Select all

u32int address = ((0x1<<31) | (lbus<<16) | (ldevice<<11) | (lfunc<<8) | (lregister<<2));
The left shift for the register is incorrect - the register must be in the low 8 bits of the address, but the lowest 2 bits must be cleared (4-byte aligned).
Actually, it does not need to be wrong. Both offset << 2 and offset & 0xfc are used in practice. The only difference is that in the first case you will need to supply the index of the word (0-63) instead of the byte (0-255) to read. Downside to the first option is that the offsets will not match the ones you see in official documentation, the second one fails to suggest that you are doing dword reads and you should mask out the correct byte after reading. In any case, I will agree that seeing the opposite of what you are used to can screw with your mind, and in this case it is indeed used wrong.

My personal approach is to have a read byte/word/dword version of this function to hide such murky details. Of course, taste matters. The bottom line is to always check that it works as expected. If you're getting a vendor:device but no classcode, your first place to check is there.


On another note:

Code: Select all

u8int subclasscode = (u8int)(classword<<8); //get the subclass
You do realize that that is not a rotate?
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
Post Reply