ATAPIO Questions

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
zhiayang
Member
Member
Posts: 368
Joined: Tue Dec 27, 2011 7:57 am
Libera.chat IRC: zhiayang

ATAPIO Questions

Post 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
	}
}

User avatar
zhiayang
Member
Member
Posts: 368
Joined: Tue Dec 27, 2011 7:57 am
Libera.chat IRC: zhiayang

Re: ATAPIO Questions

Post 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?)
Post Reply