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 unaligned offset
16 #define AHCI_MAX_BYTES    (2 * 1024 * 1024)
17 
18 #define AHCI_PRD_MAX_SIZE 0x400000 // 4mb
19 static_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 
68 typedef 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 
96 typedef 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 
113 typedef 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 
135 typedef 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 
147 typedef 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 
153 typedef 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 
160 static_assert(sizeof(ahci_cl_t) == 0x20, "unexpected command list size");
161 static_assert(sizeof(ahci_fis_t) == 0x100, "unexpected fis size");
162 static_assert(sizeof(ahci_ct_t) == 0x80, "unexpected command table header size");
163 static_assert(sizeof(ahci_prd_t) == 0x10, "unexpected prd entry size");
164