I can't read data using ATAPI

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
itsmevjnk
Member
Member
Posts: 32
Joined: Fri Apr 13, 2018 10:18 am
Location: Melbourne, VIC, Australia

I can't read data using ATAPI

Post by itsmevjnk »

Hi all,
I decided to write an ATAPI driver for my operating system. Currently I am having some issues with reading data. After sending the packet, there's no IRQ from the IDE controller. Any ideas why that happened, and how can I fix it?
This is the code that does the reading:

Code: Select all

for(uint32_t i = 0; i < size; i++) {
	uint8_t packet[12] = {ATAPI_COMMAND_READ_12, 0, ((lba >> 0x18) & 0xFF), ((lba >> 0x10) & 0xFF), ((lba >> 0x08) & 0xFF), (lba & 0xFF), 0, 0, 0, 1, 0, 0};
	uint16_t bufsize = 2048; // standard ATAPI sector size
	ide_irqrecv = 0;
	outb(ide_channels[drive / 2].iobase + ATA_DRIVE_HEAD, ((drive % 2) ? (1 << 4) : 0));
	ide_delay(drive / 2);
	outb(ide_channels[drive / 2].iobase + ATA_FEATURES, 0);
	outb(ide_channels[drive / 2].iobase + ATA_LBA_MID, (bufsize & 0xFF));
	outb(ide_channels[drive / 2].iobase + ATA_LBA_HI, (bufsize >> 8));
	outb(ide_channels[drive / 2].iobase + ATA_COMMAND, ATA_COMMAND_PACKET);
	while(ide_get_status(drive / 2) & ATA_STATUS_BSY);
	while(!(ide_get_status(drive / 2) & ATA_STATUS_DRQ) && !(ide_get_status(drive / 2) & ATA_STATUS_ERR)) printf("waiting for either drq or err to set\n");
	if(ide_get_status(drive / 2) & (1 << 0)) return -3; // error
	ide_irqrecv = 0; // prepare to receive IRQ
	atapi_send_packet(drive, &packet);
	while(!ide_irqrecv);
	ide_irqrecv = 0; // there will be one more IRQ
	bufsize = (inb(ide_channels[drive / 2].iobase + ATA_LBA_HI) << 8) | inb(ide_channels[drive / 2].iobase + ATA_LBA_MID);
	for(uint16_t j = 0; j < bufsize / 2; j++) buf[i * 1024 + j] = inw(ide_channels[drive / 2].iobase + ATA_DATA);
	while(!ide_irqrecv);
	while(ide_get_status(drive / 2) & ((1 << 7) | (1 << 3))); // wait until both BSY and DRQ are clear
	lba++;
}
This is atapi_send_packet():

Code: Select all

static inline void atapi_send_packet(uint8_t drive, uint16_t *packet) {
	for(uint8_t i = 0; i < 6; i++) outw(ide_channels[drive / 2].iobase + ATA_DATA, packet[i]);
}
Just a procrastinating uni student doing stupid things (or not doing them at all)...

SysX: https://github.com/itsmevjnk/sysx.git
User avatar
SpyderTL
Member
Member
Posts: 1074
Joined: Sun Sep 19, 2010 10:05 pm

Re: I can't read data using ATAPI

Post by SpyderTL »

First, check that all of your constants are defined properly. They aren't listed here, so I just have to assume they are correct.

Second, depending on how your IRQ handler is set up, you may have a race condition after the first wait for IRQ. You may want to set your counter to zero, then wait for it to increment to one, read the buffer size, then wait for it to increment to 2, instead of resetting it to zero again.
Project: OZone
Source: GitHub
Current Task: LIB/OBJ file support
"The more they overthink the plumbing, the easier it is to stop up the drain." - Montgomery Scott
itsmevjnk
Member
Member
Posts: 32
Joined: Fri Apr 13, 2018 10:18 am
Location: Melbourne, VIC, Australia

Re: I can't read data using ATAPI

Post by itsmevjnk »

SpyderTL wrote:First, check that all of your constants are defined properly. They aren't listed here, so I just have to assume they are correct.

Second, depending on how your IRQ handler is set up, you may have a race condition after the first wait for IRQ. You may want to set your counter to zero, then wait for it to increment to one, read the buffer size, then wait for it to increment to 2, instead of resetting it to zero again.
First of all, my constants are all correct. Secondly, the whole thing gets stuck at the while loop right after sending the packet (and yes the counter is volatile). I even put a debug message in the IRQ handler and it didn't even show up, so I'm sure it's not a race condition problem.
Just a procrastinating uni student doing stupid things (or not doing them at all)...

SysX: https://github.com/itsmevjnk/sysx.git
itsmevjnk
Member
Member
Posts: 32
Joined: Fri Apr 13, 2018 10:18 am
Location: Melbourne, VIC, Australia

Re: I can't read data using ATAPI

Post by itsmevjnk »

I just discovered that my code works under Bochs and only Bochs.
Just a procrastinating uni student doing stupid things (or not doing them at all)...

SysX: https://github.com/itsmevjnk/sysx.git
User avatar
SpyderTL
Member
Member
Posts: 1074
Joined: Sun Sep 19, 2010 10:05 pm

Re: I can't read data using ATAPI

Post by SpyderTL »

Try removing the ide_irqrecv = 0 lines, and just print the value of this variable at each step, and inside of your while loop to make sure the IRQ counter is acting as expected. This will at least tell you where to look for the problem.

Also, you may get different IRQ numbers for different drives, and definitely for different controllers, so make sure your one IDE counter is hooked up to the correct IRQ, or set up multiple counters and check the correct counter in your code above.

If your code above works on BOCHS, then what other hardware/VMs have you tested that do not work?
Project: OZone
Source: GitHub
Current Task: LIB/OBJ file support
"The more they overthink the plumbing, the easier it is to stop up the drain." - Montgomery Scott
Post Reply