1// Copyright 2016 The Fuchsia Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#pragma once 6 7#include <ddk/device.h> 8#include <ddk/driver.h> 9#include <ddk/protocol/pci.h> 10 11#define AHCI_MAX_PORTS 32 12#define AHCI_MAX_COMMANDS 32 13#define AHCI_MAX_PRDS ((PAGE_SIZE / sizeof(zx_paddr_t)) + 1) 14#define AHCI_MAX_PAGES AHCI_MAX_PRDS 15// one page less of 2M because of unnaligned offset 16#define AHCI_MAX_BYTES (2 * 1024 * 1024) 17 18#define AHCI_PRD_MAX_SIZE 0x400000 // 4mb 19static_assert(PAGE_SIZE <= AHCI_PRD_MAX_SIZE, "page size must be less than PRD max size\n"); 20 21#define AHCI_PORT_INT_CPD (1 << 31) 22#define AHCI_PORT_INT_TFE (1 << 30) 23#define AHCI_PORT_INT_HBF (1 << 29) 24#define AHCI_PORT_INT_HBD (1 << 28) 25#define AHCI_PORT_INT_IF (1 << 27) 26#define AHCI_PORT_INT_INF (1 << 26) 27#define AHCI_PORT_INT_OF (1 << 24) 28#define AHCI_PORT_INT_IPM (1 << 23) 29#define AHCI_PORT_INT_PRC (1 << 22) 30#define AHCI_PORT_INT_DI (1 << 7) 31#define AHCI_PORT_INT_PC (1 << 6) 32#define AHCI_PORT_INT_DP (1 << 5) 33#define AHCI_PORT_INT_UF (1 << 4) 34#define AHCI_PORT_INT_SDB (1 << 3) 35#define AHCI_PORT_INT_DS (1 << 2) 36#define AHCI_PORT_INT_PS (1 << 1) 37#define AHCI_PORT_INT_DHR (1 << 0) 38 39#define AHCI_PORT_INT_ERROR (AHCI_PORT_INT_TFE | AHCI_PORT_INT_HBF | AHCI_PORT_INT_HBD | \ 40 AHCI_PORT_INT_IF | AHCI_PORT_INT_INF | AHCI_PORT_INT_OF | \ 41 AHCI_PORT_INT_IPM | AHCI_PORT_INT_PRC | AHCI_PORT_INT_PC | \ 42 AHCI_PORT_INT_UF) 43#define AHCI_PORT_INT_MASK (AHCI_PORT_INT_ERROR | AHCI_PORT_INT_DP | AHCI_PORT_INT_SDB | \ 44 AHCI_PORT_INT_DS | AHCI_PORT_INT_PS | AHCI_PORT_INT_DHR) 45 46#define AHCI_PORT_CMD_ST (1 << 0) 47#define AHCI_PORT_CMD_SUD (1 << 1) 48#define AHCI_PORT_CMD_POD (1 << 2) 49#define AHCI_PORT_CMD_FRE (1 << 4) 50#define AHCI_PORT_CMD_FR (1 << 14) 51#define AHCI_PORT_CMD_CR (1 << 15) 52#define AHCI_PORT_CMD_ATAPI (1 << 24) 53#define AHCI_PORT_CMD_ICC_ACTIVE (1 << 28) 54#define AHCI_PORT_CMD_ICC_MASK (0xf << 28) 55 56#define AHCI_PORT_TFD_DATA_REQUEST (1 << 3) 57#define AHCI_PORT_TFD_BUSY (1 << 7) 58 59#define AHCI_PORT_SIG_SATA 0x101 60 61#define AHCI_PORT_SSTS_DET_PRESENT 3 62 63#define AHCI_PORT_SCTL_IPM_ACTIVE (1 << 8) 64#define AHCI_PORT_SCTL_IPM_PARTIAL (2 << 8) 65#define AHCI_PORT_SCTL_DET_MASK 0xf 66#define AHCI_PORT_SCTL_DET_INIT 1 67 68typedef struct { 69 uint32_t clb; // command list base address 1024-byte aligned 70 uint32_t clbu; // command list base address upper 32 bits 71 uint32_t fb; // FIS base address 256-byte aligned 72 uint32_t fbu; // FIS base address upper 32 bits 73 uint32_t is; // interrupt status 74 uint32_t ie; // interrupt enable 75 uint32_t cmd; // command and status 76 uint32_t reserved0; // reserved 77 uint32_t tfd; // task file data 78 uint32_t sig; // signature 79 uint32_t ssts; // SATA status 80 uint32_t sctl; // SATA control 81 uint32_t serr; // SATA error 82 uint32_t sact; // SATA active 83 uint32_t ci; // command issue 84 uint32_t sntf; // SATA notification 85 uint32_t fbs; // FIS-based switching control 86 uint32_t devslp; // device sleep 87 uint32_t reserved1[10]; // reserved 88 uint32_t vendor[4]; // vendor specific 89} __attribute__((packed)) ahci_port_reg_t; 90 91#define AHCI_CAP_NCQ (1 << 30) 92#define AHCI_GHC_HR (1 << 0) 93#define AHCI_GHC_IE (1 << 1) 94#define AHCI_GHC_AE (1 << 31) 95 96typedef struct { 97 uint32_t cap; // host capabilities 98 uint32_t ghc; // global host control 99 uint32_t is; // interrupt status 100 uint32_t pi; // ports implemented 101 uint32_t vs; // version 102 uint32_t ccc_ctl; // command completion coalescing control 103 uint32_t ccc_ports; // command completion coalescing ports 104 uint32_t em_loc; // enclosure management location 105 uint32_t em_ctl; // enclosure management control 106 uint32_t cap2; // host capabilities extended 107 uint32_t bohc; // BIOS/OS handoff control and status 108 uint32_t reserved[29]; // reserved 109 uint32_t vendor[24]; // vendor specific registers 110 ahci_port_reg_t ports[32]; // port control registers 111} __attribute__((packed)) ahci_hba_t; 112 113typedef struct { 114 union { 115 struct { 116 uint16_t cfl : 5; // command FIS length 117 uint16_t a : 1; // ATAPI 118 uint16_t w : 1; // write 119 uint16_t p : 1; // prefetchable 120 uint16_t r : 1; // reset 121 uint16_t b : 1; // build in self test 122 uint16_t c : 1; // clear busy upon R_OK 123 uint16_t rsvd : 1; 124 uint16_t pmp : 4; // port multiplier port 125 uint16_t prdtl; // PRDT length 126 } __attribute__((packed)); 127 uint32_t prdtl_flags_cfl; 128 } __attribute__((packed)); 129 uint32_t prdbc; // PRD byte count 130 uint32_t ctba; // command table base address 128-byte aligned 131 uint32_t ctbau; // command table base address upper 32 bits 132 uint32_t reserved[4]; // reserved 133} __attribute__((packed)) ahci_cl_t; 134 135typedef struct { 136 uint8_t dsfis[0x1c]; // DMA setup FIS 137 uint8_t reserved1[0x4]; 138 uint8_t psfis[0x14]; // PIO setup FIS 139 uint8_t reserved2[0x0c]; 140 uint8_t rfis[0x14]; // D2H register FIS 141 uint8_t reserved3[0x4]; 142 uint8_t sdbfis[0x8]; // set device bits FIS 143 uint8_t ufis[0x40]; // unknown FIS 144 uint8_t reserved4[0x60]; 145} __attribute__((packed)) ahci_fis_t; 146 147typedef struct { 148 uint8_t cfis[0x40]; // command FIS 149 uint8_t acmd[0x20]; // ATAPI command 150 uint8_t reserved[0x20]; // reserved 151} __attribute__((packed)) ahci_ct_t; 152 153typedef struct { 154 uint32_t dba; // data base address 2-byte aligned 155 uint32_t dbau; // data base address upper 32 bits 156 uint32_t reserved; // reserved 157 uint32_t dbc; // byte count max 4mb 158} __attribute__((packed)) ahci_prd_t; 159 160static_assert(sizeof(ahci_cl_t) == 0x20, "unexpected command list size"); 161static_assert(sizeof(ahci_fis_t) == 0x100, "unexpected fis size"); 162static_assert(sizeof(ahci_ct_t) == 0x80, "unexpected command table header size"); 163static_assert(sizeof(ahci_prd_t) == 0x10, "unexpected prd entry size"); 164