Page 1 of 1

ATAPIO Questions

Posted: Sun Apr 29, 2012 4:46 am
by zhiayang
Hello! I've been working a bit on my OS, and I figured that disk support would be good early on (Even raw read/write sectors can be good, FS can come later). I've been following the tutorial here: http://www.osdever.net/tutorials/view/l ... ss-via-pio, However it is quite vague. I get to this part:

Code: Select all


		outb(0x1F3, (unsigned char)addr);
		outb(0x1F4, (unsigned char)(addr >> 8));
		outb(0x1F5, (unsigned char)(addr >> 16));
		outb(0x1F6, 0xE0 | (drive << 4) | ((addr >> 24) & 0x0F)));

Now:

I assume addr is the LBA address, correct?

The main problem: the tutorial says to "Send the drive indicator, some magic bits, and highest 4 bits of the block address", which is the last line there.

What in the world is the drive indicator? I've searched around, but the only topic I found had the author "Figure it out" without telling how. Is it 0xA0/0xB0, or 0x1F6/0x176?



PS: You can actually read/write meaningful data to raw sectors, right? Just a bunch of 1s/0s would be good enough at this stage to save simple information.







EDIT: This is my current code, if it will help

Code: Select all


char* ata_read_sector(unsigned int sectors, unsigned int lba)
{
	if(lbamode == 1)
	{
			//LBA28
		outb(0x1F1, 0x00);
		outb(0x1F2, 0x01);
		outb(0x1F3, (unsigned char)lba);
		outb(0x1F4, (unsigned char)(lba >> 8));
		outb(0x1F5, (unsigned char)(lba >> 16));
		outb(0x1F6, 0xE0 | (drive << 4) | ((lba >> 24) & 0x0F)));
		outb(0x1F7, 0x20);
		
		while(!(inb(0x1F7) & 0x08));
		
		short tmpword = 0;
		
		char *buffer = kmalloc(sizeof(char) * 128);
		
		for(int idx = 0; idx < 256; idx++)
		{			
			tmpword = inw(0x1F0);			
			buffer[idx * 2] = (unsigned char)tmpword;			
			buffer[idx * 2 + 1] = (unsigned char)(tmpword >> 8);			
		}
		
		kprintf(buffer);
	}
	else if(lbamode == 2)
	{
			//LBA48
	}
	else
	{
			//CHS
	}
}

void ata_write_sector(unsigned int sectors, unsigned int lba)
{
	if(lbamode == 1)
	{
			//LBA28
		outb(0x1F1, 0x00);
		outb(0x1F2, 0x01);
		outb(0x1F3, (unsigned char)lba);
		outb(0x1F4, (unsigned char)(lba >> 8));
		outb(0x1F5, (unsigned char)(lba >> 16));
		outb(0x1F6, 0xE0 | (drive << 4) | ((lba >> 24) & 0x0F)));
		outb(0x1F7, 0x30);
		while(!(inb(0x1F7) & 0x08));
		
		short tmpword = 0;
		char *buffer = kmalloc(sizeof(char) * 128);
		strcpy(buffer, "testing 111");
		
		for(int i = 0; i < 256; i++)			
		{			
			tmpword = buffer[8 + i * 2] | (buffer[8 + i * 2 + 1] << 8);			
			outw(0x1F0, tmpword);
		}
	}
	else if(lbamode == 2)
	{
			//LBA48
	}
	else
	{
			//CHS
	}
}


Re: ATAPIO Questions

Posted: Sun Apr 29, 2012 5:08 am
by zhiayang
Ok, I figured it out. You gotta use 0xA0 or 0xB0.

Also, can someone tell me

1. Why I have to quit vmware (using it for hdd, cannot figure out/can't be bothered to figure out qemu) and start it again for the changes to reflect when reading?

2. Is there some kind of delay (Well of course there is, but how much?)