I can't read data using ATAPI
Posted: Fri Nov 16, 2018 8:25 am
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:
This is atapi_send_packet():
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++;
}
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]);
}