blob: a60e99556be92aae0aa7344d19cdd5e3e76ec025 [file] [log] [blame]
// Copyright 2016 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#pragma once
#include <ddk/device.h>
#include <ddk/driver.h>
#include <ddk/protocol/pci.h>
#define AHCI_MAX_PORTS 32
#define AHCI_MAX_COMMANDS 32
#define AHCI_MAX_PRDS ((PAGE_SIZE / sizeof(zx_paddr_t)) + 1)
#define AHCI_MAX_PAGES AHCI_MAX_PRDS
// one page less of 2M because of unaligned offset
#define AHCI_MAX_BYTES (2 * 1024 * 1024)
#define AHCI_PRD_MAX_SIZE 0x400000 // 4mb
static_assert(PAGE_SIZE <= AHCI_PRD_MAX_SIZE, "page size must be less than PRD max size\n");
#define AHCI_PORT_INT_CPD (1 << 31)
#define AHCI_PORT_INT_TFE (1 << 30)
#define AHCI_PORT_INT_HBF (1 << 29)
#define AHCI_PORT_INT_HBD (1 << 28)
#define AHCI_PORT_INT_IF (1 << 27)
#define AHCI_PORT_INT_INF (1 << 26)
#define AHCI_PORT_INT_OF (1 << 24)
#define AHCI_PORT_INT_IPM (1 << 23)
#define AHCI_PORT_INT_PRC (1 << 22)
#define AHCI_PORT_INT_DI (1 << 7)
#define AHCI_PORT_INT_PC (1 << 6)
#define AHCI_PORT_INT_DP (1 << 5)
#define AHCI_PORT_INT_UF (1 << 4)
#define AHCI_PORT_INT_SDB (1 << 3)
#define AHCI_PORT_INT_DS (1 << 2)
#define AHCI_PORT_INT_PS (1 << 1)
#define AHCI_PORT_INT_DHR (1 << 0)
#define AHCI_PORT_INT_ERROR (AHCI_PORT_INT_TFE | AHCI_PORT_INT_HBF | AHCI_PORT_INT_HBD | \
AHCI_PORT_INT_IF | AHCI_PORT_INT_INF | AHCI_PORT_INT_OF | \
AHCI_PORT_INT_IPM | AHCI_PORT_INT_PRC | AHCI_PORT_INT_PC | \
AHCI_PORT_INT_UF)
#define AHCI_PORT_INT_MASK (AHCI_PORT_INT_ERROR | AHCI_PORT_INT_DP | AHCI_PORT_INT_SDB | \
AHCI_PORT_INT_DS | AHCI_PORT_INT_PS | AHCI_PORT_INT_DHR)
#define AHCI_PORT_CMD_ST (1 << 0)
#define AHCI_PORT_CMD_SUD (1 << 1)
#define AHCI_PORT_CMD_POD (1 << 2)
#define AHCI_PORT_CMD_FRE (1 << 4)
#define AHCI_PORT_CMD_FR (1 << 14)
#define AHCI_PORT_CMD_CR (1 << 15)
#define AHCI_PORT_CMD_ATAPI (1 << 24)
#define AHCI_PORT_CMD_ICC_ACTIVE (1 << 28)
#define AHCI_PORT_CMD_ICC_MASK (0xf << 28)
#define AHCI_PORT_TFD_DATA_REQUEST (1 << 3)
#define AHCI_PORT_TFD_BUSY (1 << 7)
#define AHCI_PORT_SIG_SATA 0x101
#define AHCI_PORT_SSTS_DET_PRESENT 3
#define AHCI_PORT_SCTL_IPM_ACTIVE (1 << 8)
#define AHCI_PORT_SCTL_IPM_PARTIAL (2 << 8)
#define AHCI_PORT_SCTL_DET_MASK 0xf
#define AHCI_PORT_SCTL_DET_INIT 1
typedef struct {
uint32_t clb; // command list base address 1024-byte aligned
uint32_t clbu; // command list base address upper 32 bits
uint32_t fb; // FIS base address 256-byte aligned
uint32_t fbu; // FIS base address upper 32 bits
uint32_t is; // interrupt status
uint32_t ie; // interrupt enable
uint32_t cmd; // command and status
uint32_t reserved0; // reserved
uint32_t tfd; // task file data
uint32_t sig; // signature
uint32_t ssts; // SATA status
uint32_t sctl; // SATA control
uint32_t serr; // SATA error
uint32_t sact; // SATA active
uint32_t ci; // command issue
uint32_t sntf; // SATA notification
uint32_t fbs; // FIS-based switching control
uint32_t devslp; // device sleep
uint32_t reserved1[10]; // reserved
uint32_t vendor[4]; // vendor specific
} __attribute__((packed)) ahci_port_reg_t;
#define AHCI_CAP_NCQ (1 << 30)
#define AHCI_GHC_HR (1 << 0)
#define AHCI_GHC_IE (1 << 1)
#define AHCI_GHC_AE (1 << 31)
typedef struct {
uint32_t cap; // host capabilities
uint32_t ghc; // global host control
uint32_t is; // interrupt status
uint32_t pi; // ports implemented
uint32_t vs; // version
uint32_t ccc_ctl; // command completion coalescing control
uint32_t ccc_ports; // command completion coalescing ports
uint32_t em_loc; // enclosure management location
uint32_t em_ctl; // enclosure management control
uint32_t cap2; // host capabilities extended
uint32_t bohc; // BIOS/OS handoff control and status
uint32_t reserved[29]; // reserved
uint32_t vendor[24]; // vendor specific registers
ahci_port_reg_t ports[32]; // port control registers
} __attribute__((packed)) ahci_hba_t;
typedef struct {
union {
struct {
uint16_t cfl : 5; // command FIS length
uint16_t a : 1; // ATAPI
uint16_t w : 1; // write
uint16_t p : 1; // prefetchable
uint16_t r : 1; // reset
uint16_t b : 1; // build in self test
uint16_t c : 1; // clear busy upon R_OK
uint16_t rsvd : 1;
uint16_t pmp : 4; // port multiplier port
uint16_t prdtl; // PRDT length
} __attribute__((packed));
uint32_t prdtl_flags_cfl;
} __attribute__((packed));
uint32_t prdbc; // PRD byte count
uint32_t ctba; // command table base address 128-byte aligned
uint32_t ctbau; // command table base address upper 32 bits
uint32_t reserved[4]; // reserved
} __attribute__((packed)) ahci_cl_t;
typedef struct {
uint8_t dsfis[0x1c]; // DMA setup FIS
uint8_t reserved1[0x4];
uint8_t psfis[0x14]; // PIO setup FIS
uint8_t reserved2[0x0c];
uint8_t rfis[0x14]; // D2H register FIS
uint8_t reserved3[0x4];
uint8_t sdbfis[0x8]; // set device bits FIS
uint8_t ufis[0x40]; // unknown FIS
uint8_t reserved4[0x60];
} __attribute__((packed)) ahci_fis_t;
typedef struct {
uint8_t cfis[0x40]; // command FIS
uint8_t acmd[0x20]; // ATAPI command
uint8_t reserved[0x20]; // reserved
} __attribute__((packed)) ahci_ct_t;
typedef struct {
uint32_t dba; // data base address 2-byte aligned
uint32_t dbau; // data base address upper 32 bits
uint32_t reserved; // reserved
uint32_t dbc; // byte count max 4mb
} __attribute__((packed)) ahci_prd_t;
static_assert(sizeof(ahci_cl_t) == 0x20, "unexpected command list size");
static_assert(sizeof(ahci_fis_t) == 0x100, "unexpected fis size");
static_assert(sizeof(ahci_ct_t) == 0x80, "unexpected command table header size");
static_assert(sizeof(ahci_prd_t) == 0x10, "unexpected prd entry size");