Newer
Older
AMI-Aptio-BIOS-Reversed / AmiModulePkg / AHCI / Ahci / Ahci.h
@Ajax Dong Ajax Dong 2 days ago 28 KB Restructure the repo
/** @file
  Ahci.h - AHCI Driver private data structures and definitions.

  Derived from Ahci.efi (AMI AmiModulePkg/AHCI).
  Source path: e:\hs\AmiModulePkg\AHCI\AhciBus.c
  Build: DEBUG_VS2015 X64
  Module GUID (EFI_ATA_PASS_THRU_PROTOCOL): 18A031AB-B443-4D1A-A5C0-0C09261E9F71
**/

#ifndef __AHCI_H__
#define __AHCI_H__

#include <Uefi.h>
#include <Protocol/BlockIo.h>
#include <Protocol/BlockIo2.h>
#include <Protocol/AtaPassThru.h>
#include <Protocol/PciIo.h>
#include <Protocol/IdeControllerInit.h>
#include <Protocol/DevicePath.h>
#include <Protocol/ComponentName2.h>

//
// Protocol GUIDs consumed by this driver
//
#define AHCI_DRIVER_BINDING_PROTOCOL_GUID \
  { 0xC88B0B6D, 0x0DFC, 0x49A7, { 0x9C, 0xB4, 0x49, 0x07, 0x4B, 0x4C, 0x3A, 0x78 } }

//
// AHCI Register offsets (per port, stride 0x80)
//
#define AHCI_PORT_REG_CLB     0x00  // Command List Base Address (lower 32 bits)
#define AHCI_PORT_REG_CLBU    0x04  // Command List Base Address (upper 32 bits)
#define AHCI_PORT_REG_FB      0x08  // FIS Base Address (lower 32 bits)
#define AHCI_PORT_REG_FBU     0x0C  // FIS Base Address (upper 32 bits)
#define AHCI_PORT_REG_IS      0x10  // Interrupt Status
#define AHCI_PORT_REG_IE      0x14  // Interrupt Enable
#define AHCI_PORT_REG_CMD     0x18  // Command and Status
#define AHCI_PORT_REG_TFD     0x1C  // Task File Data
#define AHCI_PORT_REG_SIG     0x20  // Signature
#define AHCI_PORT_REG_SSTS    0x24  // Serial ATA Status (SCR0)
#define AHCI_PORT_REG_SCTL    0x28  // Serial ATA Control (SCR2)
#define AHCI_PORT_REG_SERR    0x2C  // Serial ATA Error (SCR1)
#define AHCI_PORT_REG_SACT    0x30  // Serial ATA Active (SCR3)
#define AHCI_PORT_REG_CI      0x34  // Command Issue
#define AHCI_PORT_REG_SNTF    0x38  // Serial ATA Notification (SCR4)
#define AHCI_PORT_REG_FBS     0x3C  // FIS-Based Switching

//
// AHCI Generic Host Controller registers
//
#define AHCI_GHC_CAP          0x00  // Host Capabilities
#define AHCI_GHC_GHC          0x04  // Global Host Control
#define AHCI_GHC_IS           0x08  // Interrupt Status
#define AHCI_GHC_PI           0x0C  // Ports Implemented
#define AHCI_GHC_VS           0x10  // Version
#define AHCI_GHC_CCC_CTL      0x14  // Command Completion Coalescing Control
#define AHCI_GHC_CCC_PORTS    0x18  // Command Completion Coalescing Ports
#define AHCI_GHC_EM_LOC       0x1C  // Enclosure Management Location
#define AHCI_GHC_EM_CTL       0x20  // Enclosure Management Control
#define AHCI_GHC_CAP2         0x24  // Host Capabilities Extended
#define AHCI_GHC_BOHC         0x28  // BIOS/OS Handoff Control and Status

//
// Port command register (PxCMD) bits
//
#define AHCI_PXCMD_ST         0x0001   // Start
#define AHCI_PXCMD_SUD        0x0002   // Spin-Up Device
#define AHCI_PXCMD_POD        0x0004   // Power On Device
#define AHCI_PXCMD_CLO        0x0008   // Command List Override
#define AHCI_PXCMD_FRE        0x0010   // FIS Receive Enable
#define AHCI_PXCMD_CCS_MASK   0x1F00   // Current Command Slot
#define AHCI_PXCMD_CCS_SHIFT  8
#define AHCI_PXCMD_MPSS       0x2000   // Mechanical Presence Switch
#define AHCI_PXCMD_FR         0x4000   // FIS Receive Running
#define AHCI_PXCMD_CR         0x8000   // Command List Running
#define AHCI_PXCMD_CPD        0x010000 // Cold Presence Detection
#define AHCI_PXCMD_ESP        0x020000 // External SATA Port
#define AHCI_PXCMD_FBSCP      0x040000 // FIS-Based Switching Capable Port
#define AHCI_PXCMD_APSTE      0x080000 // Automatic Partial to Slumber
#define AHCI_PXCMD_ATAPI      0x100000 // Device is ATAPI
#define AHCI_PXCMD_DLAE       0x400000 // Drive LED on ATAPI Enable
#define AHCI_PXCMD_ALPE       0x800000 // Aggressive Link PM Enable
#define AHCI_PXCMD_ASP        0x1000000 // Aggressive Slumber/Partial
#define AHCI_PXCMD_ICC_MASK   0xF0000000 // Interface Communication Control
#define AHCI_PXCMD_ICC_SHIFT  28

//
// Port interrupt status bits
//
#define AHCI_PXIS_DHRS        0x00000001  // Device to Host Register FIS
#define AHCI_PXIS_PSS         0x00000002  // PIO Setup FIS
#define AHCI_PXIS_DSS         0x00000004  // DMA Setup FIS
#define AHCI_PXIS_SDBS        0x00000008  // Set Device Bits
#define AHCI_PXIS_UFS         0x00000010  // Unknown FIS
#define AHCI_PXIS_DPS         0x00000020  // Descriptor Processed
#define AHCI_PXIS_PCS         0x00000040  // Port Connect Change
#define AHCI_PXIS_DMP         0x00000080  // Device Mechanical Presence
#define AHCI_PXIS_PRCS        0x00000100  // PhyRdy Change Status
#define AHCI_PXIS_IPMS        0x00000400  // Incorrect Port Multiplier
#define AHCI_PXIS_OFS         0x00001000  // Overflow Status
#define AHCI_PXIS_INFS        0x00020000  // Interface Non-Fatal Error
#define AHCI_PXIS_IFS         0x00040000  // Interface Fatal Error
#define AHCI_PXIS_HBDS        0x00100000  // Host Bus Data Error
#define AHCI_PXIS_HBFS        0x00200000  // Host Bus Fatal Error
#define AHCI_PXIS_TFES        0x00400000  // Task File Error Status
#define AHCI_PXIS_CPDS        0x00800000  // Cold Port Detect
#define AHCI_PXIS_MASK        0xFFFFFC00  // Reserved bits

//
// ATA Command Block register offsets within task file
//
#define ATA_REG_DATA          0x00
#define ATA_REG_FEATURES      0x01
#define ATA_REG_SECTOR_COUNT  0x02
#define ATA_REG_LBA_LOW       0x03
#define ATA_REG_LBA_MID       0x04
#define ATA_REG_LBA_HIGH      0x05
#define ATA_REG_DEVICE        0x06
#define ATA_REG_COMMAND       0x07
#define ATA_REG_CONTROL       0x0C
#define ATA_REG_ERROR         0x11
#define ATA_REG_SECTOR_COUNT2 0x12
#define ATA_REG_LBA_LOW2      0x13
#define ATA_REG_LBA_MID2      0x14
#define ATA_REG_LBA_HIGH2     0x15

//
// DMA / Packet transfer directions
//
#define AHCI_DIR_READ         0
#define AHCI_DIR_WRITE        1
#define AHCI_DIR_NO_DATA      2

//
// AHCI Command Header structure (32 bytes)
//
typedef struct {
  UINT32   Prdtl        : 16;  // Physical Region Descriptor Table Length
  UINT32   P        : 1;      // Prefetchable
  UINT32   W        : 1;      // Write (0=read from device, 1=write to device)
  UINT32   A        : 1;      // ATAPI
  UINT32   Reserved0: 4;      // Reserved
  UINT32   Cfl      : 5;      // Command FIS Length (in DWORDS)
  UINT32   Reserved1: 4;      // Reserved
  UINT32   Prdbc;             // Physical Region Descriptor Byte Count
  UINT32   Ctba;              // Command Table Base Address (lower 32 bits)
  UINT32   Ctbau;             // Command Table Base Address (upper 32 bits)
  UINT32   Reserved2[4];      // Reserved
} AHCI_CMD_HEADER;

//
// AHCI Command Table (144 bytes header + PRD entries)
//
typedef struct {
  UINT8    Cfis[64];          // Command FIS
  UINT8    Acmd[16];          // ATAPI Command
  UINT8    Reserved[48];      // Reserved
  // PRD entries follow at offset 128
} AHCI_CMD_TABLE;

//
// Physical Region Descriptor (PRD) entry (16 bytes)
//
typedef struct {
  UINT32   Dba;               // Data Base Address (lower 32 bits)
  UINT32   Dbau;              // Data Base Address (upper 32 bits)
  UINT32   Reserved0;
  UINT32   Dbc       : 22;   // Data Byte Count (max 4MB)
  UINT32   Reserved1 : 9;
  UINT32   I         : 1;    // Interrupt on Completion
} AHCI_PRD_ENTRY;

//
// FIS - Register Host to Device (FIS type 0x27)
//
typedef struct {
  UINT8    FisType;           // 0x27
  UINT8    PmPort : 4;       // Port Multiplier Port
  UINT8    Rsv0   : 1;
  UINT8    C      : 1;       // Indicates register FIS is a command
  UINT8    Rsv1   : 2;
  UINT8    Command;           // ATA command register
  UINT8    Features;          // ATA features register
  UINT8    LbaLow;            // LBA low
  UINT8    LbaMid;            // LBA mid
  UINT8    LbaHigh;           // LBA high
  UINT8    Device;            // Device register
  UINT8    LbaLow2;           // LBA low extended
  UINT8    LbaMid2;           // LBA mid extended
  UINT8    LbaHigh2;          // LBA high extended
  UINT8    Features2;         // Features extended
  UINT8    Count;             // Sector count
  UINT8    Count2;            // Sector count extended
  UINT8    Reserved[8];
  UINT8    Control;           // Control register
  UINT8    Reserved2[7];
} AHCI_REG_H2D_FIS;

//
// FIS - Register Device to Host (FIS type 0x34)
//
typedef struct {
  UINT8    FisType;           // 0x34
  UINT8    PmPort : 4;
  UINT8    Rsv0   : 2;
  UINT8    I      : 1;
  UINT8    Rsv1   : 1;
  UINT8    Status;
  UINT8    Error;
  UINT8    LbaLow;
  UINT8    LbaMid;
  UINT8    LbaHigh;
  UINT8    Device;
  UINT8    LbaLow2;
  UINT8    LbaMid2;
  UINT8    LbaHigh2;
  UINT8    Count;
  UINT8    Count2;
  UINT8    Reserved[6];
} AHCI_REG_D2H_FIS;

//
// FIS - DMA Setup (FIS type 0x41)
//
typedef struct {
  UINT8    FisType;           // 0x41
  UINT8    PmPort : 4;
  UINT8    Rsv0   : 1;
  UINT8    D      : 1;
  UINT8    Rsv1   : 2;
  UINT8    Rsv2;
  UINT8    DmaBufferIdLow;
  UINT8    DmaBufferIdHigh;
  UINT32   Rsv3;
  UINT32   DmaBufOffset;
  UINT32   TransferCount;
  UINT32   Rsv4;
} AHCI_DMA_SETUP_FIS;

//
// FIS - PIO Setup (FIS type 0x5F)
//
typedef struct {
  UINT8    FisType;           // 0x5F
  UINT8    PmPort : 4;
  UINT8    Rsv0   : 1;
  UINT8    D      : 1;
  UINT8    Rsv1   : 2;
  UINT8    Status;
  UINT8    Error;
  UINT8    LbaLow;
  UINT8    LbaMid;
  UINT8    LbaHigh;
  UINT8    Device;
  UINT8    LbaLow2;
  UINT8    LbaMid2;
  UINT8    LbaHigh2;
  UINT8    Count;
  UINT8    Count2;
  UINT8    Rsv2;
  UINT8    E_Status;
  UINT16   TransferCount;
  UINT8    Rsv3[2];
} AHCI_PIO_SETUP_FIS;

//
// AHCI PORT state machine
//
#define AHCI_PORT_STATE_CREATED     1   // Port structure allocated
#define AHCI_PORT_STATE_ERROR       2   // Device detection failed
#define AHCI_PORT_STATE_CONFIGURED  3   // Device configured (identify done)
#define AHCI_PORT_STATE_READY       4   // Device ready for I/O

//
// AHCI Port media types (from ATA IDENTIFY word 0)
//
#define AHCI_MEDIA_TYPE_NONE    0
#define AHCI_MEDIA_TYPE_HDD     1
#define AHCI_MEDIA_TYPE_ATAPI   2

//
// AHCI Port signature types (from PxSIG)
//
#define AHCI_SIG_ATA            0x00000101  // ATA drive (SATA)
#define AHCI_SIG_ATAPI          0xEB140101  // ATAPI drive (SATA)
#define AHCI_SIG_PM_PORT        0x96690101  // Port Multiplier
#define AHCI_SIG_SEMB           0xC33C0101  // Enclosure Management Bridge
#define AHCI_SIG_PM             0xFFFFFFFF  // Port Multiplier (inverted)

//
// Private AHCI PORT structure (allocated per detected SATA port)
// Total size: 0x3D0 (976) bytes
//
typedef struct _AHCI_PORT {
  //
  // +0x0000: Port identification and state
  //
  UINT8                   Port;                // +0x00: SATA port number
  UINT8                   PmPort;              // +0x01: Port multiplier port (0xFF = direct)
  UINT8                   PmType;              // +0x02: PM type from SATA Phy command
  UINT8                   State;              // +0x03: Port state (AHCI_PORT_STATE_*)
  //
  // +0x0004: Padding / reserved
  //
  UINT8                   Reserved04[4];
  //
  // +0x0008: Device information
  //
  UINT32                  PortType;            // +0x08: Port type from PxSIG register
  UINT32                  MediaType;           // +0x0C: Media type (0/1/2)
  //
  // +0x0010: ATA IDENTIFY data buffer (512 bytes)
  //
  UINT16                  IdentifyData[256];   // +0x10: ATA IDENTIFY DEVICE data
  //
  // +0x0210: Extended identify or scratch space (304 bytes)
  //
  UINT8                   Reserved210[0x130];  // +0x0210 - 0x0340: reserved
  //
  // +0x0340: AHCI MMIO register info
  //
  UINT64                  AhciBarBase;         // +0x340: Mapped AHCI BAR base address for this port
  UINT64                  AhciBarSize;         // +0x348: Mapped AHCI BAR size for this port
  //
  // +0x0350: Back-pointer to controller
  //
  struct _AHCI_CONTROLLER *Controller;         // +0x350: Owning AHCI_CONTROLLER
  //
  // +0x0358: Protocol interfaces
  //
  EFI_BLOCK_IO_MEDIA      *BlockIoMedia;       // +0x358: EFI_BLOCK_IO_MEDIA pointer
  VOID                    *BlockIo;            // +0x360: EFI_BLOCK_IO_PROTOCOL
  VOID                    *BlockIo2;           // +0x368: EFI_BLOCK_IO2_PROTOCOL
  //
  // +0x0370: Reserved for additional protocol pointers
  //
  UINT8                   Reserved370[0x28];   // +0x370 - 0x398: reserved
  //
  // +0x0398: Linked list entry (embedded LIST_ENTRY)
  //
  LIST_ENTRY              Link;                // +0x398: Port list link structure (16 bytes)
} AHCI_PORT;

#define AHCI_PORT_FROM_LIST_ENTRY(Entry) \
  CR (Entry, AHCI_PORT, Link, AHCI_PORT_SIGNATURE)

#define AHCI_PORT_SIGNATURE SIGNATURE_32 ('A','H','C','I')

//
// AHCI CONTROLLER private structure
// Stores per-controller state for AHCI HBAs
//
typedef struct _AHCI_CONTROLLER {
  //
  // +0x0000: Controller identification
  //
  UINT64                  Signature;           // +0x00: Signature
  //
  // +0x0008: AHCI register base (MMIO remapped)
  //
  UINT64                  AhciRegBase;         // +0x08: AHCI MMIO register base
  //
  // +0x0010 - 0x0050: AHCI HBA register space
  //
  UINT32                  Capability;          // +0x10: CAP register value
  UINT32                  PortsImplemented;    // +0x14: PI register value
  UINT32                  AhciVersion;         // +0x18: VS register value
  UINT32                  Capability2;         // +0x1C: CAP2 register value
  UINT8                   Reserved20[0x30];    // +0x20 - 0x50: reserved
  //
  // +0x0050: Port management
  //
  UINT64                  PortBarInfo;         // +0x50: Port BAR pointer
  UINT64                  PortCount;           // +0x58: Number of ports
  //
  // +0x0060: Port linked list
  //
  LIST_ENTRY              PortListHead;        // +0x60: Head of AHCI_PORT linked list
  //
  // +0x0070: Additional controller state
  //
  VOID                    *ControllerRegs;     // +0x70: Controller register block
  VOID                    *PortListTail;       // +0x78: Tail pointer for port list
} AHCI_CONTROLLER;

//
// Port register offset calculation
// AHCI maps each port at: AhciRegBase + (Port + 2) * 0x80
//
#define AHCI_PORT_REG_BASE(Controller, Port) \
  ((Controller)->AhciRegBase + ((UINT64)(Port) + 2) * 0x80)

#define AHCI_PORT_READ_DWORD(Controller, Port, RegOffset) \
  MmioRead32 (AHCI_PORT_REG_BASE (Controller, Port) + (RegOffset))

#define AHCI_PORT_WRITE_DWORD(Controller, Port, RegOffset, Value) \
  MmioWrite32 (AHCI_PORT_REG_BASE (Controller, Port) + (RegOffset), (Value))

//
// AHCI command timeout values (in microseconds)
//
#define AHCI_MMIO_POLL_TIMEOUT      50000   // 50ms
#define AHCI_COMMAND_TIMEOUT        30000   // 30ms
#define AHCI_SPINUP_TIMEOUT         1000000 // 1s
#define AHCI_PORT_RESET_TIMEOUT     10000   // 10ms

//
// ATA commands used by this driver
//
#define ATA_CMD_IDENTIFY_DEVICE            0xEC
#define ATA_CMD_READ_DMA                   0xC8
#define ATA_CMD_READ_DMA_EXT               0x25
#define ATA_CMD_WRITE_DMA                  0xCA
#define ATA_CMD_WRITE_DMA_EXT              0x35
#define ATA_CMD_READ_SECTORS               0x20
#define ATA_CMD_WRITE_SECTORS              0x30
#define ATA_CMD_READ_FPDMA_QUEUED          0x60
#define ATA_CMD_WRITE_FPDMA_QUEUED         0x61
#define ATA_CMD_PACKET                     0xA0
#define ATA_CMD_IDENTIFY_PACKET_DEVICE     0xA1
#define ATA_CMD_READ_BUFFER                0xE4
#define ATA_CMD_WRITE_BUFFER               0xE8
#define ATA_CMD_SET_FEATURES               0xEF
#define ATA_CMD_SET_MAX                    0xF9
#define ATA_CMD_FLUSH_CACHE                0xE7
#define ATA_CMD_FLUSH_CACHE_EXT            0xEA
#define ATA_CMD_STANDBY_IMMEDIATE          0xE0
#define ATA_CMD_IDLE_IMMEDIATE             0xE1
#define ATA_CMD_CHECK_POWER_MODE           0xE5
#define ATA_CMD_READ_VERIFY                0x40
#define ATA_CMD_READ_LOG_EXT               0x2F
#define ATA_CMD_WRITE_LOG_EXT              0x3F

//
// ATA SET FEATURES subcommands
//
#define ATA_SET_FEATURES_TRANSFER_MODE     0x03
#define ATA_SET_FEATURES_SET_TRANSFER_MODE 0x03
#define ATA_SET_FEATURES_ENABLE_RW_DMA_SETUP 0x07
#define ATA_SET_FEATURES_DISABLE_RW_DMA_SETUP 0x47
#define ATA_SET_FEATURES_ENABLE_APM        0x05
#define ATA_SET_FEATURES_DISABLE_APM       0x85
#define ATA_SET_FEATURES_PUI_SET           0x06
#define ATA_SET_FEATURES_PUI_CLEAR         0x86

//
// Transfer modes
//
#define ATA_TRANSFER_MODE_PIO_DEFAULT      0x00
#define ATA_TRANSFER_MODE_MULTI_DMA        0x20
#define ATA_TRANSFER_MODE_UDMA             0x40

//
// ATA Set Features - RW DMA Setup subcommands
//
#define ATA_RW_DMA_SETUP_ENABLE            0x07
#define ATA_RW_DMA_SETUP_DISABLE           0x47

//
// ATA Status register bits
//
#define ATA_STS_BUSY      0x80
#define ATA_STS_DRDY      0x40
#define ATA_STS_DWF       0x20
#define ATA_STS_DSC       0x10
#define ATA_STS_DRQ       0x08
#define ATA_STS_CORR      0x04
#define ATA_STS_ERROR     0x01

//
// ATA Device register bits
//
#define ATA_DEVICE_LBA    0x40
#define ATA_DEVICE_SLAVE  0x10

//
// ATA Control register bits
//
#define ATA_CTL_SRST      0x04  // Software Reset
#define ATA_CTL_RESET     0x02  // nIEN

//
// CRC-16 constants for ATA identify data verification
//
#define ATA_IDENTIFY_CRC16_POLY  0x1021
#define ATA_IDENTIFY_CRC16_INIT  0x0000

//
// Max ATA transfer length in blocks (for 48-bit LBA)
//
#define AHCI_MAX_BLOCKS_PER_CMD  0x10000  // 65536 blocks

//
// AHCI Debug Level definitions
//
#define AHCI_DEBUG_ERROR    0x80000000
#define AHCI_DEBUG_WARN     0x40000000
#define AHCI_DEBUG_INFO     0x20000000
#define AHCI_DEBUG_VERBOSE  0x10000000

//
// AHCI Debug Trace masks
//
#define AHCI_TRACE_ENTRY    0x00000001
#define AHCI_TRACE_EXIT     0x00000002
#define AHCI_TRACE_IO       0x00000100

//
// Function prototypes
//

//
// Driver entry point and binding
//
EFI_STATUS
EFIAPI
AhciDriverEntryPoint (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
  );

EFI_STATUS
EFIAPI
AhciDriverBindingSupported (
  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
  IN EFI_HANDLE                   ControllerHandle,
  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL
  );

EFI_STATUS
EFIAPI
AhciDriverBindingStart (
  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
  IN EFI_HANDLE                   ControllerHandle,
  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL
  );

EFI_STATUS
EFIAPI
AhciDriverBindingStop (
  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
  IN EFI_HANDLE                   ControllerHandle,
  IN UINTN                        NumberOfChildren,
  IN EFI_HANDLE                   *ChildHandleBuffer OPTIONAL
  );

//
// Component name protocol
//
EFI_STATUS
EFIAPI
AhciGetDriverName (
  IN  EFI_COMPONENT_NAME2_PROTOCOL  *This,
  IN  CHAR8                         *Language,
  OUT CHAR16                        **DriverName
  );

EFI_STATUS
EFIAPI
AhciGetComponentName (
  IN  EFI_COMPONENT_NAME2_PROTOCOL  *This,
  IN  EFI_HANDLE                    ControllerHandle,
  IN  EFI_HANDLE                    ChildHandle OPTIONAL,
  IN  CHAR8                         *Language,
  OUT CHAR16                        **ComponentName
  );

//
// Controller initialization
//
EFI_STATUS
AhciInitController (
  IN AHCI_CONTROLLER  *Controller,
  IN EFI_PCI_IO_PROTOCOL   *PciIo,
  IN EFI_DEVICE_PATH_PROTOCOL  *DevicePath,
  IN EFI_HANDLE           ControllerHandle
  );

VOID
AhciStopController (
  IN AHCI_CONTROLLER  *Controller
  );

//
// Port management
//
EFI_STATUS
AhciInitializePortRegisters (
  IN AHCI_CONTROLLER  *Controller,
  IN UINT8            Port
  );

EFI_STATUS
AhciCreatePort (
  IN OUT AHCI_CONTROLLER  *Controller,
  IN     EFI_PCI_IO_PROTOCOL   *PciIo,
  IN     UINT8             Port,
  IN     UINT8             PmPort
  );

EFI_STATUS
AhciEnumerateDevice (
  IN EFI_HANDLE           ImageHandle,
  IN EFI_HANDLE           ControllerHandle,
  IN AHCI_CONTROLLER      *Controller,
  IN VOID                 *AhciBarInfo,
  IN EFI_PCI_IO_PROTOCOL  *PciIo,
  IN UINT8                Port,
  IN UINT8                PmPort
  );

EFI_STATUS
AhciConfigureDevice (
  IN AHCI_PORT    *Port,
  OUT UINT64      *Capacity
  );

EFI_STATUS
AhciIdentifySataPort (
  IN AHCI_PORT    *Port,
  IN EFI_PCI_IO_PROTOCOL  *PciIo,
  IN UINT8        PortNumber,
  IN UINT8        PmPortNumber
  );

EFI_STATUS
AhciIdentifyPmPort (
  IN AHCI_PORT    *Port,
  IN EFI_PCI_IO_PROTOCOL   *PciIo,
  IN UINT8        Port,
  IN UINT8        PmPort
  );

EFI_STATUS
AhciSetPortInterfacePower (
  IN AHCI_PORT    *Port
  );

EFI_STATUS
AhciSetDeviceFeature (
  IN AHCI_PORT    *Port,
  IN UINT64       Capacity
  );

//
// Block I/O interface functions
//
EFI_STATUS
EFIAPI
AhciBlockIoGetMediaInfo (
  IN  EFI_BLOCK_IO_PROTOCOL  *This,
  IN  EFI_HANDLE             ControllerHandle,
  OUT UINT32                 *MediaId
  );

EFI_STATUS
EFIAPI
AhciBlockIoGetDevicePath (
  IN  EFI_BLOCK_IO_PROTOCOL  *This,
  IN  EFI_HANDLE             ControllerHandle,
  OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath
  );

EFI_STATUS
EFIAPI
AhciBlockIoFlush (
  IN EFI_BLOCK_IO_PROTOCOL  *This
  );

EFI_STATUS
EFIAPI
AhciBlockIoReadBlocks (
  IN EFI_BLOCK_IO_PROTOCOL  *This,
  IN UINT32                 MediaId,
  IN EFI_LBA                Lba,
  IN UINTN                  BufferSize,
  OUT VOID                  *Buffer
  );

EFI_STATUS
EFIAPI
AhciBlockIoRead (
  IN EFI_BLOCK_IO_PROTOCOL   *This,
  IN UINT32                  MediaId,
  IN EFI_LBA                 Lba,
  IN UINTN                   BufferSize,
  OUT VOID                   *Buffer
  );

EFI_STATUS
EFIAPI
AhciBlockIoWrite (
  IN EFI_BLOCK_IO_PROTOCOL   *This,
  IN UINT32                  MediaId,
  IN EFI_LBA                 Lba,
  IN UINTN                   BufferSize,
  OUT VOID                   *Buffer
  );

EFI_STATUS
EFIAPI
AhciNonBlockingRead (
  IN EFI_BLOCK_IO2_PROTOCOL  *This,
  IN UINT32                  MediaId,
  IN EFI_LBA                 Lba,
  IN EFI_BLOCK_IO2_TOKEN     *Token,
  IN UINTN                   BufferSize,
  OUT VOID                   *Buffer
  );

EFI_STATUS
EFIAPI
AhciNonBlockingWrite (
  IN EFI_BLOCK_IO2_PROTOCOL  *This,
  IN UINT32                  MediaId,
  IN EFI_LBA                 Lba,
  IN EFI_BLOCK_IO2_TOKEN     *Token,
  IN UINTN                   BufferSize,
  OUT VOID                   *Buffer
  );

EFI_STATUS
EFIAPI
AhciBlockIo2Read (
  IN EFI_BLOCK_IO2_PROTOCOL  *This,
  IN UINT32                  MediaId,
  IN EFI_LBA                 Lba,
  IN EFI_BLOCK_IO2_TOKEN     *Token,
  IN UINTN                   BufferSize,
  OUT VOID                   *Buffer
  );

EFI_STATUS
EFIAPI
AhciBlockIo2Write (
  IN EFI_BLOCK_IO2_PROTOCOL  *This,
  IN UINT32                  MediaId,
  IN EFI_LBA                 Lba,
  IN EFI_BLOCK_IO2_TOKEN     *Token,
  IN UINTN                   BufferSize,
  OUT VOID                   *Buffer
  );

EFI_STATUS
EFIAPI
AhciBlockIoRwDispatch (
  IN EFI_BLOCK_IO_PROTOCOL   *This,
  IN UINT32                  MediaId,
  IN EFI_LBA                 Lba,
  IN UINTN                   BufferSize,
  OUT VOID                   *Buffer,
  IN BOOLEAN                 IsWrite
  );

EFI_STATUS
EFIAPI
AhciBlockIoRwExDispatch (
  IN EFI_BLOCK_IO2_PROTOCOL  *This,
  IN UINT32                  MediaId,
  IN EFI_LBA                 Lba,
  IN EFI_BLOCK_IO2_TOKEN     *Token,
  IN UINTN                   BufferSize,
  OUT VOID                   *Buffer,
  IN BOOLEAN                 IsWrite
  );

//
// Media detection and setup
//
EFI_STATUS
AhciSetupBlockIoMedia (
  IN AHCI_PORT    *Port
  );

EFI_STATUS
AhciGetMediaInfo (
  IN AHCI_PORT    *Port
  );

EFI_STATUS
AhciDetectPartitionType (
  IN AHCI_PORT    *Port
  );

EFI_STATUS
AhciParsePartitionEntry (
  IN UINT32       *Mbr,
  IN UINTN        PartitionIndex,
  OUT UINT16      *PartitionType
  );

//
// Command path: ATA command building and execution
//
EFI_STATUS
AhciInitTaskFile (
  IN AHCI_PORT            *Port,
  IN EFI_PCI_IO_PROTOCOL  *PciIo,
  IN UINT8                *TaskFile,
  IN UINTN                TaskFileSize,
  ...
  );

UINT16
AhciCalcCrc16 (
  OUT UINT16     *CrcOut,
  IN  UINT8      *Data,
  IN  UINTN      Length
  );

VOID
AhciCopyMem (
  OUT VOID       *Destination,
  IN  VOID       *Source,
  IN  UINTN      Length
  );

EFI_STATUS
AhciSetupCmdHeader (
  IN AHCI_PORT        *Port,
  IN AHCI_CMD_HEADER  *CmdHeader,
  IN UINT64           CommandTableBase
  );

EFI_STATUS
AhciSetupCmdTable (
  IN AHCI_PORT        *Port,
  IN UINT8            *TaskFile,
  IN UINT32           *CmdSlot,
  IN AHCI_CMD_TABLE   *CmdTable
  );

EFI_STATUS
AhciSetupPrdTable (
  IN AHCI_PORT    *Port,
  IN UINT64       *DataBuffer,
  IN UINT64       DataBufferSize,
  IN VOID         *PrdTableBase
  );

EFI_STATUS
AhciStartCommand (
  IN AHCI_CONTROLLER  *Controller,
  IN AHCI_PORT        *Port
  );

EFI_STATUS
AhciWaitCommandComplete (
  IN AHCI_PORT    *Port,
  IN UINT32       TimeoutMs,
  IN BOOLEAN      IsBlocking
  );

//
// Port reset and control
//
EFI_STATUS
AhciPortReset (
  IN AHCI_CONTROLLER  *Controller,
  IN EFI_PCI_IO_PROTOCOL   *PciIo,
  IN UINT8            Port,
  IN UINT8            PmPort,
  IN UINT8            ResetType,
  IN UINT8            ResetFlags
  );

EFI_STATUS
AhciSoftReset (
  IN AHCI_PORT    *Port,
  IN UINT8        ResetType
  );

EFI_STATUS
AhciResetPort (
  IN AHCI_PORT    *Port
  );

EFI_STATUS
AhciResetPmPorts (
  IN AHCI_PORT    *Port
  );

EFI_STATUS
AhciPollPortReady (
  IN AHCI_PORT    *Port,
  IN OUT UINT64   *PortStatus,
  IN UINT8        Timeout,
  IN UINT8        Flags
  );

EFI_STATUS
AhciReadPortStatus (
  IN AHCI_PORT    *Port,
  IN OUT UINT64   *PortStatus,
  IN UINT8        Timeout,
  IN UINT8        Flags,
  IN UINT8        ReadType
  );

EFI_STATUS
AhciClearPortError (
  IN AHCI_PORT    *Port,
  IN OUT UINT64   *PortStatus,
  IN UINT8        Flags,
  IN UINT8        ClearType
  );

EFI_STATUS
AhciSetAhciMode (
  IN AHCI_CONTROLLER  *Controller,
  IN UINT8            Port,
  IN UINT64           AhciBarBase
  );

//
// ATA command execution
//
EFI_STATUS
AhciAtaSoftReset (
  IN AHCI_PORT    *Port,
  IN UINT8        *TaskFile
  );

EFI_STATUS
AhciNonDataCommand (
  IN AHCI_PORT    *Port,
  IN UINT8        *TaskFile,
  IN UINT64       Timeout
  );

EFI_STATUS
AhciDmaCommand (
  IN AHCI_PORT    *Port,
  IN UINT8        *TaskFile,
  IN UINT64       Timeout
  );

EFI_STATUS
AhciPacketCommand (
  IN AHCI_PORT    *Port,
  IN UINT64       *TaskFile,
  IN UINT64       Timeout
  );

EFI_STATUS
AhciSataPhyCommand (
  IN AHCI_PORT    *Port,
  IN UINT8        PhyCmd,
  IN UINT8        PhyArg,
  OUT UINT16      *Result,
  IN UINT8        Flags
  );

EFI_STATUS
AhciCheckMediaType (
  IN AHCI_PORT    *Port
  );

EFI_STATUS
AhciDetectMedia (
  IN AHCI_PORT    *Port
  );

//
// Read/Write LBA operations
//
EFI_STATUS
AhciReadLba (
  IN AHCI_PORT    *Port,
  IN UINT64       Lba,
  IN UINTN        BlockCount,
  OUT VOID        *Buffer,
  IN UINT8        ReadType,
  IN BOOLEAN      IsVerified
  );

EFI_STATUS
AhciWriteLba (
  IN AHCI_PORT    *Port,
  IN UINT64       Lba,
  IN UINTN        BlockCount,
  OUT VOID        *Buffer,
  IN UINT8        WriteType,
  IN BOOLEAN      Fua
  );

EFI_STATUS
AhciReadVerify (
  IN AHCI_PORT    *Port,
  IN UINT64       Lba,
  IN UINTN        BlockCount
  );

//
// Feature configuration
//
EFI_STATUS
AhciSetTransferMode (
  IN AHCI_PORT    *Port
  );

EFI_STATUS
AhciSetFeatureRwDmaSetup (
  IN AHCI_PORT    *Port
  );

EFI_STATUS
AhciReadCapacity (
  IN AHCI_PORT    *Port
  );

//
// Memory and debug support
//
VOID *
AhciAllocateMemory (
  IN UINTN  Size
  );

VOID *
AhciAllocateZeroPool (
  IN UINTN  Size
  );

VOID
AhciZeroMem (
  OUT VOID   *Buffer,
  IN  UINTN  Length
  );

VOID
AhciDebugPrint (
  IN UINTN        ErrorLevel,
  IN CONST CHAR8  *Format,
  ...
  );

VOID
AhciDebugPrint2 (
  IN UINTN        ErrorLevel
  );

VOID
AhciDebugTrace (
  IN UINT32   EntryType,
  IN UINT32   TraceId
  );

VOID
AhciAssert (
  IN CONST CHAR8  *FileName,
  IN UINTN        LineNumber,
  IN CONST CHAR8  *Description
  );

BOOLEAN
AhciDebugLevelEnabled (
  VOID
  );

//
// Protocol helpers
//
BOOLEAN
AhciIsDevicePathNode (
  IN CHAR8   *DevicePath
  );

BOOLEAN
AhciCompareDevicePath (
  IN EFI_DEVICE_PATH_PROTOCOL  *DevicePath1,
  IN EFI_DEVICE_PATH_PROTOCOL  *DevicePath2
  );

UINT32
AhciReadUint32Le (
  IN VOID   *Buffer
  );

//
// HOB / boot services helpers
//
EFI_PHYSICAL_ADDRESS
AhciGetHobList (
  IN EFI_HANDLE  ImageHandle
  );

EFI_STATUS
AhciTestProtocol (
  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
  IN EFI_HANDLE                   ControllerHandle,
  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL
  );

EFI_STATUS
AhciAcquirePortAccess (
  IN AHCI_PORT    *Port,
  IN UINT8        *TaskFile,
  IN BOOLEAN      IsWrite
  );

EFI_STATUS
AhciPreparePortAccess (
  IN AHCI_PORT    *Port
  );

//
// Debug protocol cache
//
VOID
AhciCacheDebugProtocol (
  VOID
  );

EFI_STATUS
AhciGetDebugInterface (
  VOID
  );

//
// MMIO polling
//
EFI_STATUS
AhciMmioPollReady (
  IN AHCI_CONTROLLER  *Controller,
  IN UINT8            Port,
  IN UINT8            RegOffset,
  IN UINT32           Mask,
  IN UINT32           Timeout
  );

EFI_STATUS
AhciMmioPollRead (
  IN AHCI_CONTROLLER  *Controller,
  IN UINT8            Port,
  IN UINT32           RegOffset,
  IN UINT32           ExpectedMask,
  IN UINT32           ExpectedValue
  );

//
// Global variables
//
extern EFI_HANDLE                    gImageHandle;
extern EFI_SYSTEM_TABLE              *gST;
extern EFI_BOOT_SERVICES             *gBS;
extern EFI_RUNTIME_SERVICES          *gRT;

extern AHCI_CONTROLLER               *gAhciController;

#endif // __AHCI_H__