AHCI HBA appears to be doing absolutely nothing

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
mstachowsky
Posts: 2
Joined: Fri Nov 12, 2021 8:52 pm

AHCI HBA appears to be doing absolutely nothing

Post by mstachowsky »

I've been fighting my AHCI driver for...months, honestly, and I'm at a total loss. I am able to find the HBA on the PCI bus and read ABAR5 to get the base address of the HBA. I can read and set a bunch of registers, but when I try to set a register that is supposed to actually do something nothing happens. I'll explain:

I am developing an x86 operating system and running it on Virtualbox.

When doing a minimal setup, I understand that I need to follow the steps in this post: viewtopic.php?f=1&t=40969 (I actually figured out most of that from the docs, but some stuff I didn't know). Specifically, I:

1. Enable AHCI mode by setting GHC.AE
2. It appears that I do NOT have bios handoff enabled (The entirety of HBA's CAP2 register is 0, meaning I have no bios handoff ability?)
3. I set all ports to idle by clearing ST and FRE, and waiting for CR and FR to change. Interestingly, either these are already zero or they are being reset, because this part works
4. Now we get to the problem. If I try to perform an HBA reset by setting GHC.HR to 1, it never becomes 0 again. It hangs. If I ignore this (that is, if I don't do the reset), then trying to reset anything else fails. For example, I can't reset Px.SERR by writing all 1s and waiting for it to clear because it never clears.

I have no idea what I did or didn't do to make the HBA just straight up not respond. I'd expect that a bunch of error bits would be set or something but I see *no changes at all*. I can see the changes I make (so if I set a bit then print the register that bit is set), but it appears that the HBA does nothing with those settings.

Any thoughts?
linuxyne
Member
Member
Posts: 211
Joined: Sat Jul 02, 2016 7:02 am

Re: AHCI HBA appears to be doing absolutely nothing

Post by linuxyne »

compiler optimizations, perhaps.
nullplan
Member
Member
Posts: 1790
Joined: Wed Aug 30, 2017 8:24 am

Re: AHCI HBA appears to be doing absolutely nothing

Post by nullplan »

Without access to the code, it is a bit hard to know what is going on, but if linuxyne is on the right track, the following may help you write the code better:

Code: Select all

static inline uint32_t readl(volatile uint32_t* a) {
  uint32_t r;
  asm volatile("movl %1,%0" : "=r"(r) : "m"(*a));
}

static inline void writel(volatile uint32_t *a, uint32_t v) {
  asm("movl %0,%1" :: "r"(v), "m"(*a));
}
Then replace direct MMIO with calls to these (and similar) functions. This circumvents unwanted optimization where the compiler reorders and removes things because it doesn't know that reading and writing MMIO registers actually has important side effects.
Carpe diem!
mstachowsky
Posts: 2
Joined: Fri Nov 12, 2021 8:52 pm

Re: AHCI HBA appears to be doing absolutely nothing

Post by mstachowsky »

Yes! It was compiler optimizations making the HBA do nothing, thank you! After turning the compiler optimizations off (compiling my AHCI.c and ATA.c libraries with -O0 using gcc), I am finally able to get it to DO something. It fails, and it fails hard, but this is a great step.

I currently see the bits being reset - for instance when I set PxSERR to 0xF...F It turns it all back to zero. Now my PxTFD bits 15:08 show 0b1, which I believe means I have an error somewhere, but this is a HUGE step. Any clues on where I can find the task data error register, or at least what it means?
Octocontrabass
Member
Member
Posts: 5563
Joined: Mon Mar 25, 2013 7:01 pm

Re: AHCI HBA appears to be doing absolutely nothing

Post by Octocontrabass »

The interpretation of the drive's task file registers are defined according to the command, so you have to look up an appropriate draft of the ATA command set according to the command you're using.

But the only command I know of that can possibly return 0x01 in the error register is EXECUTE DEVICE DIAGNOSTIC (0x90), where 0x01 in the error register indicates all diagnostics passed.

Also, at some point you'll want to fix your code so it works with optimizations enabled.
Post Reply