Page 1 of 1

I can't read data using ATAPI

Posted: Fri Nov 16, 2018 8:25 am
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]);
}

Re: I can't read data using ATAPI

Posted: Fri Nov 16, 2018 10:21 am
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.

Re: I can't read data using ATAPI

Posted: Fri Nov 16, 2018 10:47 am
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.

Re: I can't read data using ATAPI

Posted: Sat Nov 17, 2018 7:52 am
by itsmevjnk
I just discovered that my code works under Bochs and only Bochs.

Re: I can't read data using ATAPI

Posted: Mon Nov 26, 2018 3:44 pm
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?