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