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?
AHCI HBA appears to be doing absolutely nothing
-
- Posts: 2
- Joined: Fri Nov 12, 2021 8:52 pm
Re: AHCI HBA appears to be doing absolutely nothing
compiler optimizations, perhaps.
Re: AHCI HBA appears to be doing absolutely nothing
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:
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.
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));
}
Carpe diem!
-
- Posts: 2
- Joined: Fri Nov 12, 2021 8:52 pm
Re: AHCI HBA appears to be doing absolutely nothing
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?
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?
-
- Member
- Posts: 5563
- Joined: Mon Mar 25, 2013 7:01 pm
Re: AHCI HBA appears to be doing absolutely nothing
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.
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.