3

I am trying to setup simple PIO access to my hard drive but I've hit a wall on the very first step towards the goal.

First step to working with ATA device is to read it's state register and wait until it's BSY (7th) bit is low. I've got the program doing that, but for some reason when reading the state register it always gives me 0xFF instead. Here is the program sample written in C++:

#include <stdio.h>
#include <stdlib.h>
#include <sys/io.h>

#define DRDY_OFFSET   6
#define BSY_OFFSET    7

const int STATE[2] = { 0x1F7, 0x177 };

bool requestPrivilege() {
  if (iopl(3) == -1) {
    printf("Unable to request privilege level III. Exiting.\n");
    exit(1);
  }
}

bool wait(auto lambda) {
  int maxAttempts = 30 * 1000;

  while((maxAttempts--)) {
    if (lambda()) return true;
  }
  return false;
}

bool waitIdle(int channel) {
  auto lambda = [=]() -> bool {
    printf("%x\n", inb_p(STATE[channel]));
    return !(inb_p(STATE[channel]) & (1 << BSY_OFFSET));
  };
  return wait(lambda);
}

bool waitReady(int channel) {
  auto lambda = [=]() -> bool {
    return inb_p(STATE[channel]) & (1 << DRDY_OFFSET);
  };
  return wait(lambda);
}

int main() {
  requestPrivilege();

  if (!waitIdle(0)) {
    printf("BSY waiting timeout.\n");
    exit(1);
  };

  if (!waitReady(0)) {
    printf("DRDY waiting timeout.\n");
    exit(1);
  };

  //                                     //
  // DO SOMETHING WITH READY DEVICE HERE //
  //                                     //

  return 0;
}

Would you please look at the snippet and tell me what's wrong?

MarengoHue
  • 1,789
  • 13
  • 34
  • 1
    Are you sure nothing else is trying to manage that interface? Are you talking to the correct interface? Hypothetically speaking, if really have direct progammed I/O access to the IDE cable, you theoretically should be able to change the voltage level by disconnecting the drive and connecting the other side of a resistor to the appropriate supply voltage or ground, and see the read value change. – Chris Stratton Apr 27 '15 at 17:59
  • How do I check whether the interface is managed by something else? I am unable to interact with the device physically though. I am not sure I got any other interface on my machine, so I must be talking to the correct one. – MarengoHue Apr 27 '15 at 18:06
  • 1
    Basically, you should assume the kernel owns this interface, unless you have taken **explicit** measures to make sure the kernel doesn't manage it. If this is your hard drive, you *definitely* do not want to be trying to do this as trying to use it behind the kernel's back sounds like an excellent way to cause corruption. And even if it is a CDROM drive hanging off a secondary interface, expect trouble until you get the kernel to explicitly ignore it. You might have more luck playing around in a virtual machine, with code running off an initrd and a kernel built without any ATA/IDE drivers. – Chris Stratton Apr 27 '15 at 18:09
  • Thank you sir. I might then try using such kernel. The task I am trying to accomplish is pretty easy though. I just wanted to run an Identify Device command, I do not believe this will cause any corruption. – MarengoHue Apr 27 '15 at 18:13
  • 1
    If your computer and hard drive are using a SATA interface, then ATA / IDE emulation may not be enabled (this is usually a BIOS setting, and should not be changed once you're installed an OS). – rcgldr Apr 27 '15 at 18:17
  • "I just wanted to run an Identify Device command, I do not believe this will cause any corruption" - it's not the command you use that will cause corruption, it's the fact that the I/O sequence may get interleaved with that from the kernel driver. You might inadvertently alter a command that the kernel driver issues, causing corruption. – davmac Jun 18 '15 at 10:50
  • @MokonaModoki Did you ever get this working? I'm having a similar problem. – Zack Apr 03 '17 at 19:59
  • I didn't, unfortunately. Like Chris told, you might have better luck with VM. – MarengoHue Apr 05 '17 at 18:19

0 Answers0