ATA driver fails to read

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
alethiophile
Member
Member
Posts: 90
Joined: Sat May 30, 2009 10:28 am

ATA driver fails to read

Post by alethiophile »

I am currently working on an ATA driver to read data in PIO mode. The driver is as simple as possible; it simply sends the appropriate values, then polls for data-ready and reads. The code is below.

Code: Select all

s32int ata_read(struct ata_drive *d, u32int segment, u8int segnum, void *buf) {
  u8int stat;
  segment &= 0x0fffffff; // 28-bit LBA                                                                                                                       
  outportb(d->io_base + ATA_PORT_SECTORS, segnum);
  outportb(d->io_base + ATA_PORT_ADDR1, (u8int) segment);
  outportb(d->io_base + ATA_PORT_ADDR2, (u8int) (segment >> 8));
  outportb(d->io_base + ATA_PORT_ADDR3, (u8int) (segment >> 16));
  outportb(d->io_base + ATA_PORT_DSELECT, 0xe0 | segment >> 24);
  outportb(d->io_base + ATA_PORT_CMD, 0x20);
  inportb(d->io_base + ATA_PORT_CMD); // 400 ns delay                                                                                                        
  inportb(d->io_ctrl + ATA_PORT_CMD);
  inportb(d->io_ctrl + ATA_PORT_CMD);
  inportb(d->io_ctrl + ATA_PORT_CMD);
  u16int i = 0;
  u8int j = 0;
  u16int k = 0;
  u16int *b = (u16int *) buf;
  while (j < segnum) {
    /* wait = 0; */
    /* while (!wait); // spin on the wait lock */
  while ((stat = inportb(d->io_ctrl))) {
    if (stat & 0x80) {
      continue;
    }
    if (stat & 0x21) {
      printf("error: %x", stat);
      return 1;
    }
    if (stat & 0x08) {
      break;
    }
  }
    for (i = 0; i < 256; i++,k++) {
      b[k] = inportw(d->io_base + ATA_PORT_DATA);
    }
  }
  return 0;
}
In this context, the value d->io_base is 0x1f0, and the constants are:

Code: Select all

#define ATA_PORT_DATA 0x0
#define ATA_PORT_ERRINF 0x1
#define ATA_PORT_SECTORS 0x2
#define ATA_PORT_ADDR1 0x3
#define ATA_PORT_ADDR2 0x4
#define ATA_PORT_ADDR3 0x5
#define ATA_PORT_DSELECT 0x6
#define ATA_PORT_CMD 0x7
As far as I can tell, this is semantically identical to the (presumably working) asm driver on the ATA_PIO_Mode page. However, when I run it, it hangs in the polling loop (DRQ is never set). An earlier version that used an interrupt that set a spinlock variable did the same (the interrupt never arrived). The use case calls the function using a stock ata_drive structure created by the function:

Code: Select all

void ata_init(struct ata_drive **d) {
  /* if (inportb(0x1f7) == 0xff) { // floating bus; no drives */
  /*   *d = 0; */
  /*   return; */
  /* } */
  *d = kmalloc(sizeof(struct ata_drive));
  struct ata_drive *da = *d;
  da[0].bus = 0;
  da[0].port = 1;
  da[0].func = 1;
  da[0].io_base = 0x1f0;
  da[0].io_ctrl = 0x3f6;
  da[0].irq = IRQ14;
  register_interrupt_handler(IRQ14, ata_interrupt_handler);
  return;
}
with only one segment and a segment number of 1. Is there any obvious problem that I am failing to see? (I have tested this in Qemu; Bochs page faults every time in unrelated code, and I have not tested it on hardware).
If I had an OS, there would be a link here.
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: ATA driver fails to read

Post by Combuster »

Bochs page faults every time in unrelated code
If you have a memory issue, it might show differently everytime. I suggest you locate and fix it to make sure it's not interfering with whatever else you want to test.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
User avatar
bewing
Member
Member
Posts: 1401
Joined: Wed Feb 07, 2007 1:45 pm
Location: Eugene, OR, US

Re: ATA driver fails to read

Post by bewing »

Also, on bochs: are you certain that the ata0 bus exists, and ata0-master exists (and is a hard disk) in your bochsrc file?
User avatar
alethiophile
Member
Member
Posts: 90
Joined: Sat May 30, 2009 10:28 am

Re: ATA driver fails to read

Post by alethiophile »

I have found Bochs to be somewhat annoyingly sensitive; earlier versions that worked fine both in Qemu and on hardware tended to fail in Bochs, as well. I might eventually try to debug the Bochs memory issues, but I have a feeling that I might just run into a fault in Bochs. Right now it's a lower priority.
If I had an OS, there would be a link here.
User avatar
bewing
Member
Member
Posts: 1401
Joined: Wed Feb 07, 2007 1:45 pm
Location: Eugene, OR, US

Re: ATA driver fails to read

Post by bewing »

I agree about the "sensitivity" of bochs -- in fact I am actively looking for examples of code that act that way. If you still have some of your previous examples that fail on bochs but nowhere else, I'd love to get a copy of the image file, if possible.
User avatar
alethiophile
Member
Member
Posts: 90
Joined: Sat May 30, 2009 10:28 am

Re: ATA driver fails to read

Post by alethiophile »

bewing: The current image version page faults occasionally under Qemu, and every time under Bochs. I have never seen it page fault on hardware. The forum is being troublesome; if you want I'll email you an image.

Does anyone have any input as to the ATA driver?
If I had an OS, there would be a link here.
User avatar
bewing
Member
Member
Posts: 1401
Joined: Wed Feb 07, 2007 1:45 pm
Location: Eugene, OR, US

Re: ATA driver fails to read

Post by bewing »

I've PMed you my email addy.
The point about the driver is that it looks right. So your error is probably somewhere else. This makes it very hard to find. If you send me the image, I will attempt to find your bug as I examine the page fault issue with my own emulator.
Post Reply