Re: AHCI initialization sequence for real hardware
Posted: Sat Sep 03, 2022 2:41 pm
There are general pointers programming hardware devices:
1. You spin for 0xffff times then you use delay function in 1ms increments or less then you setup a timer and quit you process. Delay function is like spin (it blocks) but at least you know exact time.
2. PHY terminology is used in many devices. Its lowest possible thing that must be verified first.
3. If you got initial functionality working on emulator then test it on real hardware before going futher.
Ata ahci related
0. Uefi based motherboard dont generally have bios handoff in bios mode.
0. Make sure bits 0,4,14,15 =0 inside PxCMD for all implemented ports.
1. You do hba reset - it’ll be lightning fast on real hardware if you did prev step. Disable main and port interrupts. Make sure PxCMD BITS 2,1=1 and make sure PxSCTL =0 for all implemented ports.
2. Setup PxFB with valid phys addr. PxCLB is optional, I like 0 in there.
3. Your third loop thru implemented ports: write 0x701 into PxSCTL. The 7 disables power management - you dont need this without super clear understanding how ahci works.
4. Wait 2 ms. You must know its 2ms. Its not 0xffff loops.
5. 4th loop thru implemented ports: clear PxSERR by writing -1, and enable all per port interrupts.
6. Enable global intertupts - GHE = 0x80000002
7. please stop any futher loop spinning - its slower and less predictable
8. 5th loop thru implemented ports: write 0x700 into PxSCTL
9. quit you main process and wait for interrupt.
A) PxFB is Receive FISes. Used when device wants to send you very small data like status or setting. On most motherboards (but not all) this mem content can be 0 for device to send you data
Interrupt:
1) Inside interrupt you check if triggered port is your already established port. If not you proceed to messy very messy initialization - you need to reach 0x1_3 in PxSSTS. Its all inside single interrupt if BSY doesnt timeout and PxSSTS doesnt drop to 0x0_0
2) For established ports: on every irq you check that value of PxSSTS=0x1_3
3) then you check that 24+ bits inside PxIS are not set, if set you need to set PxCMD bits 0,15 to 0 and then back to 1. If during this process BSY remains 0 then you can continue even if prev command set error bit in PxTFD. Its insde 6.2 chapter of ahci 1.3.1 docs.
4) then you can check original PxTFD to see if prev command returned error
A) 2byte PxTFD is copy of certain bytes of a Receive FIS
B) forget about FRE and FR - they will always remain set.
1. You spin for 0xffff times then you use delay function in 1ms increments or less then you setup a timer and quit you process. Delay function is like spin (it blocks) but at least you know exact time.
2. PHY terminology is used in many devices. Its lowest possible thing that must be verified first.
3. If you got initial functionality working on emulator then test it on real hardware before going futher.
Ata ahci related
0. Uefi based motherboard dont generally have bios handoff in bios mode.
0. Make sure bits 0,4,14,15 =0 inside PxCMD for all implemented ports.
1. You do hba reset - it’ll be lightning fast on real hardware if you did prev step. Disable main and port interrupts. Make sure PxCMD BITS 2,1=1 and make sure PxSCTL =0 for all implemented ports.
2. Setup PxFB with valid phys addr. PxCLB is optional, I like 0 in there.
3. Your third loop thru implemented ports: write 0x701 into PxSCTL. The 7 disables power management - you dont need this without super clear understanding how ahci works.
4. Wait 2 ms. You must know its 2ms. Its not 0xffff loops.
5. 4th loop thru implemented ports: clear PxSERR by writing -1, and enable all per port interrupts.
6. Enable global intertupts - GHE = 0x80000002
7. please stop any futher loop spinning - its slower and less predictable
8. 5th loop thru implemented ports: write 0x700 into PxSCTL
9. quit you main process and wait for interrupt.
A) PxFB is Receive FISes. Used when device wants to send you very small data like status or setting. On most motherboards (but not all) this mem content can be 0 for device to send you data
Interrupt:
1) Inside interrupt you check if triggered port is your already established port. If not you proceed to messy very messy initialization - you need to reach 0x1_3 in PxSSTS. Its all inside single interrupt if BSY doesnt timeout and PxSSTS doesnt drop to 0x0_0
2) For established ports: on every irq you check that value of PxSSTS=0x1_3
3) then you check that 24+ bits inside PxIS are not set, if set you need to set PxCMD bits 0,15 to 0 and then back to 1. If during this process BSY remains 0 then you can continue even if prev command set error bit in PxTFD. Its insde 6.2 chapter of ahci 1.3.1 docs.
4) then you can check original PxTFD to see if prev command returned error
A) 2byte PxTFD is copy of certain bytes of a Receive FIS
B) forget about FRE and FR - they will always remain set.