root / hw / ide / ahci.h @ bc4caf49
History | View | Annotate | Download (12.9 kB)
1 | f83a40dc | Alexander Graf | /*
|
---|---|---|---|
2 | f83a40dc | Alexander Graf | * QEMU AHCI Emulation
|
3 | f83a40dc | Alexander Graf | *
|
4 | f83a40dc | Alexander Graf | * Copyright (c) 2010 qiaochong@loongson.cn
|
5 | f83a40dc | Alexander Graf | * Copyright (c) 2010 Roland Elek <elek.roland@gmail.com>
|
6 | f83a40dc | Alexander Graf | * Copyright (c) 2010 Sebastian Herbszt <herbszt@gmx.de>
|
7 | f83a40dc | Alexander Graf | * Copyright (c) 2010 Alexander Graf <agraf@suse.de>
|
8 | f83a40dc | Alexander Graf | *
|
9 | f83a40dc | Alexander Graf | * This library is free software; you can redistribute it and/or
|
10 | f83a40dc | Alexander Graf | * modify it under the terms of the GNU Lesser General Public
|
11 | f83a40dc | Alexander Graf | * License as published by the Free Software Foundation; either
|
12 | f83a40dc | Alexander Graf | * version 2 of the License, or (at your option) any later version.
|
13 | f83a40dc | Alexander Graf | *
|
14 | f83a40dc | Alexander Graf | * This library is distributed in the hope that it will be useful,
|
15 | f83a40dc | Alexander Graf | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
16 | f83a40dc | Alexander Graf | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
17 | f83a40dc | Alexander Graf | * Lesser General Public License for more details.
|
18 | f83a40dc | Alexander Graf | *
|
19 | f83a40dc | Alexander Graf | * You should have received a copy of the GNU Lesser General Public
|
20 | f83a40dc | Alexander Graf | * License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
21 | f83a40dc | Alexander Graf | *
|
22 | f83a40dc | Alexander Graf | */
|
23 | f83a40dc | Alexander Graf | |
24 | 03c7a6a8 | Sebastian Herbszt | #ifndef HW_IDE_AHCI_H
|
25 | 03c7a6a8 | Sebastian Herbszt | #define HW_IDE_AHCI_H
|
26 | 03c7a6a8 | Sebastian Herbszt | |
27 | 465f1ab1 | Daniel Verkamp | #define AHCI_MEM_BAR_SIZE 0x1000 |
28 | 03c7a6a8 | Sebastian Herbszt | #define AHCI_MAX_PORTS 32 |
29 | 03c7a6a8 | Sebastian Herbszt | #define AHCI_MAX_SG 168 /* hardware max is 64K */ |
30 | 03c7a6a8 | Sebastian Herbszt | #define AHCI_DMA_BOUNDARY 0xffffffff |
31 | 03c7a6a8 | Sebastian Herbszt | #define AHCI_USE_CLUSTERING 0 |
32 | 03c7a6a8 | Sebastian Herbszt | #define AHCI_MAX_CMDS 32 |
33 | 03c7a6a8 | Sebastian Herbszt | #define AHCI_CMD_SZ 32 |
34 | 03c7a6a8 | Sebastian Herbszt | #define AHCI_CMD_SLOT_SZ (AHCI_MAX_CMDS * AHCI_CMD_SZ)
|
35 | 03c7a6a8 | Sebastian Herbszt | #define AHCI_RX_FIS_SZ 256 |
36 | 03c7a6a8 | Sebastian Herbszt | #define AHCI_CMD_TBL_CDB 0x40 |
37 | 03c7a6a8 | Sebastian Herbszt | #define AHCI_CMD_TBL_HDR_SZ 0x80 |
38 | 03c7a6a8 | Sebastian Herbszt | #define AHCI_CMD_TBL_SZ (AHCI_CMD_TBL_HDR_SZ + (AHCI_MAX_SG * 16)) |
39 | 03c7a6a8 | Sebastian Herbszt | #define AHCI_CMD_TBL_AR_SZ (AHCI_CMD_TBL_SZ * AHCI_MAX_CMDS)
|
40 | 03c7a6a8 | Sebastian Herbszt | #define AHCI_PORT_PRIV_DMA_SZ (AHCI_CMD_SLOT_SZ + AHCI_CMD_TBL_AR_SZ + \
|
41 | 03c7a6a8 | Sebastian Herbszt | AHCI_RX_FIS_SZ) |
42 | 03c7a6a8 | Sebastian Herbszt | |
43 | 03c7a6a8 | Sebastian Herbszt | #define AHCI_IRQ_ON_SG (1 << 31) |
44 | 03c7a6a8 | Sebastian Herbszt | #define AHCI_CMD_ATAPI (1 << 5) |
45 | 03c7a6a8 | Sebastian Herbszt | #define AHCI_CMD_WRITE (1 << 6) |
46 | 03c7a6a8 | Sebastian Herbszt | #define AHCI_CMD_PREFETCH (1 << 7) |
47 | 03c7a6a8 | Sebastian Herbszt | #define AHCI_CMD_RESET (1 << 8) |
48 | 03c7a6a8 | Sebastian Herbszt | #define AHCI_CMD_CLR_BUSY (1 << 10) |
49 | 03c7a6a8 | Sebastian Herbszt | |
50 | 03c7a6a8 | Sebastian Herbszt | #define RX_FIS_D2H_REG 0x40 /* offset of D2H Register FIS data */ |
51 | 03c7a6a8 | Sebastian Herbszt | #define RX_FIS_SDB 0x58 /* offset of SDB FIS data */ |
52 | 03c7a6a8 | Sebastian Herbszt | #define RX_FIS_UNK 0x60 /* offset of Unknown FIS data */ |
53 | 03c7a6a8 | Sebastian Herbszt | |
54 | 03c7a6a8 | Sebastian Herbszt | /* global controller registers */
|
55 | 03c7a6a8 | Sebastian Herbszt | #define HOST_CAP 0x00 /* host capabilities */ |
56 | 03c7a6a8 | Sebastian Herbszt | #define HOST_CTL 0x04 /* global host control */ |
57 | 03c7a6a8 | Sebastian Herbszt | #define HOST_IRQ_STAT 0x08 /* interrupt status */ |
58 | 03c7a6a8 | Sebastian Herbszt | #define HOST_PORTS_IMPL 0x0c /* bitmap of implemented ports */ |
59 | 03c7a6a8 | Sebastian Herbszt | #define HOST_VERSION 0x10 /* AHCI spec. version compliancy */ |
60 | 03c7a6a8 | Sebastian Herbszt | |
61 | 03c7a6a8 | Sebastian Herbszt | /* HOST_CTL bits */
|
62 | 03c7a6a8 | Sebastian Herbszt | #define HOST_CTL_RESET (1 << 0) /* reset controller; self-clear */ |
63 | 03c7a6a8 | Sebastian Herbszt | #define HOST_CTL_IRQ_EN (1 << 1) /* global IRQ enable */ |
64 | 03c7a6a8 | Sebastian Herbszt | #define HOST_CTL_AHCI_EN (1 << 31) /* AHCI enabled */ |
65 | 03c7a6a8 | Sebastian Herbszt | |
66 | 03c7a6a8 | Sebastian Herbszt | /* HOST_CAP bits */
|
67 | 03c7a6a8 | Sebastian Herbszt | #define HOST_CAP_SSC (1 << 14) /* Slumber capable */ |
68 | 03c7a6a8 | Sebastian Herbszt | #define HOST_CAP_AHCI (1 << 18) /* AHCI only */ |
69 | 03c7a6a8 | Sebastian Herbszt | #define HOST_CAP_CLO (1 << 24) /* Command List Override support */ |
70 | 03c7a6a8 | Sebastian Herbszt | #define HOST_CAP_SSS (1 << 27) /* Staggered Spin-up */ |
71 | 03c7a6a8 | Sebastian Herbszt | #define HOST_CAP_NCQ (1 << 30) /* Native Command Queueing */ |
72 | 03c7a6a8 | Sebastian Herbszt | #define HOST_CAP_64 (1 << 31) /* PCI DAC (64-bit DMA) support */ |
73 | 03c7a6a8 | Sebastian Herbszt | |
74 | 03c7a6a8 | Sebastian Herbszt | /* registers for each SATA port */
|
75 | 03c7a6a8 | Sebastian Herbszt | #define PORT_LST_ADDR 0x00 /* command list DMA addr */ |
76 | 03c7a6a8 | Sebastian Herbszt | #define PORT_LST_ADDR_HI 0x04 /* command list DMA addr hi */ |
77 | 03c7a6a8 | Sebastian Herbszt | #define PORT_FIS_ADDR 0x08 /* FIS rx buf addr */ |
78 | 03c7a6a8 | Sebastian Herbszt | #define PORT_FIS_ADDR_HI 0x0c /* FIS rx buf addr hi */ |
79 | 03c7a6a8 | Sebastian Herbszt | #define PORT_IRQ_STAT 0x10 /* interrupt status */ |
80 | 03c7a6a8 | Sebastian Herbszt | #define PORT_IRQ_MASK 0x14 /* interrupt enable/disable mask */ |
81 | 03c7a6a8 | Sebastian Herbszt | #define PORT_CMD 0x18 /* port command */ |
82 | 03c7a6a8 | Sebastian Herbszt | #define PORT_TFDATA 0x20 /* taskfile data */ |
83 | 03c7a6a8 | Sebastian Herbszt | #define PORT_SIG 0x24 /* device TF signature */ |
84 | 03c7a6a8 | Sebastian Herbszt | #define PORT_SCR_STAT 0x28 /* SATA phy register: SStatus */ |
85 | 03c7a6a8 | Sebastian Herbszt | #define PORT_SCR_CTL 0x2c /* SATA phy register: SControl */ |
86 | 03c7a6a8 | Sebastian Herbszt | #define PORT_SCR_ERR 0x30 /* SATA phy register: SError */ |
87 | 03c7a6a8 | Sebastian Herbszt | #define PORT_SCR_ACT 0x34 /* SATA phy register: SActive */ |
88 | 03c7a6a8 | Sebastian Herbszt | #define PORT_CMD_ISSUE 0x38 /* command issue */ |
89 | 03c7a6a8 | Sebastian Herbszt | #define PORT_RESERVED 0x3c /* reserved */ |
90 | 03c7a6a8 | Sebastian Herbszt | |
91 | 03c7a6a8 | Sebastian Herbszt | /* PORT_IRQ_{STAT,MASK} bits */
|
92 | 03c7a6a8 | Sebastian Herbszt | #define PORT_IRQ_COLD_PRES (1 << 31) /* cold presence detect */ |
93 | 03c7a6a8 | Sebastian Herbszt | #define PORT_IRQ_TF_ERR (1 << 30) /* task file error */ |
94 | 03c7a6a8 | Sebastian Herbszt | #define PORT_IRQ_HBUS_ERR (1 << 29) /* host bus fatal error */ |
95 | 03c7a6a8 | Sebastian Herbszt | #define PORT_IRQ_HBUS_DATA_ERR (1 << 28) /* host bus data error */ |
96 | 03c7a6a8 | Sebastian Herbszt | #define PORT_IRQ_IF_ERR (1 << 27) /* interface fatal error */ |
97 | 03c7a6a8 | Sebastian Herbszt | #define PORT_IRQ_IF_NONFATAL (1 << 26) /* interface non-fatal error */ |
98 | 03c7a6a8 | Sebastian Herbszt | #define PORT_IRQ_OVERFLOW (1 << 24) /* xfer exhausted available S/G */ |
99 | 03c7a6a8 | Sebastian Herbszt | #define PORT_IRQ_BAD_PMP (1 << 23) /* incorrect port multiplier */ |
100 | 03c7a6a8 | Sebastian Herbszt | |
101 | 03c7a6a8 | Sebastian Herbszt | #define PORT_IRQ_PHYRDY (1 << 22) /* PhyRdy changed */ |
102 | 03c7a6a8 | Sebastian Herbszt | #define PORT_IRQ_DEV_ILCK (1 << 7) /* device interlock */ |
103 | 03c7a6a8 | Sebastian Herbszt | #define PORT_IRQ_CONNECT (1 << 6) /* port connect change status */ |
104 | 03c7a6a8 | Sebastian Herbszt | #define PORT_IRQ_SG_DONE (1 << 5) /* descriptor processed */ |
105 | 03c7a6a8 | Sebastian Herbszt | #define PORT_IRQ_UNK_FIS (1 << 4) /* unknown FIS rx'd */ |
106 | 03c7a6a8 | Sebastian Herbszt | #define PORT_IRQ_SDB_FIS (1 << 3) /* Set Device Bits FIS rx'd */ |
107 | 03c7a6a8 | Sebastian Herbszt | #define PORT_IRQ_DMAS_FIS (1 << 2) /* DMA Setup FIS rx'd */ |
108 | 03c7a6a8 | Sebastian Herbszt | #define PORT_IRQ_PIOS_FIS (1 << 1) /* PIO Setup FIS rx'd */ |
109 | 03c7a6a8 | Sebastian Herbszt | #define PORT_IRQ_D2H_REG_FIS (1 << 0) /* D2H Register FIS rx'd */ |
110 | 03c7a6a8 | Sebastian Herbszt | |
111 | 03c7a6a8 | Sebastian Herbszt | #define PORT_IRQ_FREEZE (PORT_IRQ_HBUS_ERR | PORT_IRQ_IF_ERR | \
|
112 | 03c7a6a8 | Sebastian Herbszt | PORT_IRQ_CONNECT | PORT_IRQ_PHYRDY | \ |
113 | 03c7a6a8 | Sebastian Herbszt | PORT_IRQ_UNK_FIS) |
114 | 03c7a6a8 | Sebastian Herbszt | #define PORT_IRQ_ERROR (PORT_IRQ_FREEZE | PORT_IRQ_TF_ERR | \
|
115 | 03c7a6a8 | Sebastian Herbszt | PORT_IRQ_HBUS_DATA_ERR) |
116 | 03c7a6a8 | Sebastian Herbszt | #define DEF_PORT_IRQ (PORT_IRQ_ERROR | PORT_IRQ_SG_DONE | \
|
117 | 03c7a6a8 | Sebastian Herbszt | PORT_IRQ_SDB_FIS | PORT_IRQ_DMAS_FIS | \ |
118 | 03c7a6a8 | Sebastian Herbszt | PORT_IRQ_PIOS_FIS | PORT_IRQ_D2H_REG_FIS) |
119 | 03c7a6a8 | Sebastian Herbszt | |
120 | 03c7a6a8 | Sebastian Herbszt | /* PORT_CMD bits */
|
121 | 03c7a6a8 | Sebastian Herbszt | #define PORT_CMD_ATAPI (1 << 24) /* Device is ATAPI */ |
122 | 03c7a6a8 | Sebastian Herbszt | #define PORT_CMD_LIST_ON (1 << 15) /* cmd list DMA engine running */ |
123 | 03c7a6a8 | Sebastian Herbszt | #define PORT_CMD_FIS_ON (1 << 14) /* FIS DMA engine running */ |
124 | 03c7a6a8 | Sebastian Herbszt | #define PORT_CMD_FIS_RX (1 << 4) /* Enable FIS receive DMA engine */ |
125 | 03c7a6a8 | Sebastian Herbszt | #define PORT_CMD_CLO (1 << 3) /* Command list override */ |
126 | 03c7a6a8 | Sebastian Herbszt | #define PORT_CMD_POWER_ON (1 << 2) /* Power up device */ |
127 | 03c7a6a8 | Sebastian Herbszt | #define PORT_CMD_SPIN_UP (1 << 1) /* Spin up device */ |
128 | 03c7a6a8 | Sebastian Herbszt | #define PORT_CMD_START (1 << 0) /* Enable port DMA engine */ |
129 | 03c7a6a8 | Sebastian Herbszt | |
130 | 03c7a6a8 | Sebastian Herbszt | #define PORT_CMD_ICC_MASK (0xf << 28) /* i/f ICC state mask */ |
131 | 03c7a6a8 | Sebastian Herbszt | #define PORT_CMD_ICC_ACTIVE (0x1 << 28) /* Put i/f in active state */ |
132 | 03c7a6a8 | Sebastian Herbszt | #define PORT_CMD_ICC_PARTIAL (0x2 << 28) /* Put i/f in partial state */ |
133 | 03c7a6a8 | Sebastian Herbszt | #define PORT_CMD_ICC_SLUMBER (0x6 << 28) /* Put i/f in slumber state */ |
134 | 03c7a6a8 | Sebastian Herbszt | |
135 | 03c7a6a8 | Sebastian Herbszt | #define PORT_IRQ_STAT_DHRS (1 << 0) /* Device to Host Register FIS */ |
136 | 03c7a6a8 | Sebastian Herbszt | #define PORT_IRQ_STAT_PSS (1 << 1) /* PIO Setup FIS */ |
137 | 03c7a6a8 | Sebastian Herbszt | #define PORT_IRQ_STAT_DSS (1 << 2) /* DMA Setup FIS */ |
138 | 03c7a6a8 | Sebastian Herbszt | #define PORT_IRQ_STAT_SDBS (1 << 3) /* Set Device Bits */ |
139 | 03c7a6a8 | Sebastian Herbszt | #define PORT_IRQ_STAT_UFS (1 << 4) /* Unknown FIS */ |
140 | 03c7a6a8 | Sebastian Herbszt | #define PORT_IRQ_STAT_DPS (1 << 5) /* Descriptor Processed */ |
141 | 03c7a6a8 | Sebastian Herbszt | #define PORT_IRQ_STAT_PCS (1 << 6) /* Port Connect Change Status */ |
142 | 03c7a6a8 | Sebastian Herbszt | #define PORT_IRQ_STAT_DMPS (1 << 7) /* Device Mechanical Presence |
143 | 03c7a6a8 | Sebastian Herbszt | Status */
|
144 | 03c7a6a8 | Sebastian Herbszt | #define PORT_IRQ_STAT_PRCS (1 << 22) /* File Ready Status */ |
145 | 03c7a6a8 | Sebastian Herbszt | #define PORT_IRQ_STAT_IPMS (1 << 23) /* Incorrect Port Multiplier |
146 | 03c7a6a8 | Sebastian Herbszt | Status */
|
147 | 03c7a6a8 | Sebastian Herbszt | #define PORT_IRQ_STAT_OFS (1 << 24) /* Overflow Status */ |
148 | 03c7a6a8 | Sebastian Herbszt | #define PORT_IRQ_STAT_INFS (1 << 26) /* Interface Non-Fatal Error |
149 | 03c7a6a8 | Sebastian Herbszt | Status */
|
150 | 03c7a6a8 | Sebastian Herbszt | #define PORT_IRQ_STAT_IFS (1 << 27) /* Interface Fatal Error */ |
151 | 03c7a6a8 | Sebastian Herbszt | #define PORT_IRQ_STAT_HBDS (1 << 28) /* Host Bus Data Error Status */ |
152 | 03c7a6a8 | Sebastian Herbszt | #define PORT_IRQ_STAT_HBFS (1 << 29) /* Host Bus Fatal Error Status */ |
153 | 03c7a6a8 | Sebastian Herbszt | #define PORT_IRQ_STAT_TFES (1 << 30) /* Task File Error Status */ |
154 | 03c7a6a8 | Sebastian Herbszt | #define PORT_IRQ_STAT_CPDS (1 << 31) /* Code Port Detect Status */ |
155 | 03c7a6a8 | Sebastian Herbszt | |
156 | 03c7a6a8 | Sebastian Herbszt | /* ap->flags bits */
|
157 | 03c7a6a8 | Sebastian Herbszt | #define AHCI_FLAG_NO_NCQ (1 << 24) |
158 | 03c7a6a8 | Sebastian Herbszt | #define AHCI_FLAG_IGN_IRQ_IF_ERR (1 << 25) /* ignore IRQ_IF_ERR */ |
159 | 03c7a6a8 | Sebastian Herbszt | #define AHCI_FLAG_HONOR_PI (1 << 26) /* honor PORTS_IMPL */ |
160 | 03c7a6a8 | Sebastian Herbszt | #define AHCI_FLAG_IGN_SERR_INTERNAL (1 << 27) /* ignore SERR_INTERNAL */ |
161 | 03c7a6a8 | Sebastian Herbszt | #define AHCI_FLAG_32BIT_ONLY (1 << 28) /* force 32bit */ |
162 | 03c7a6a8 | Sebastian Herbszt | |
163 | 03c7a6a8 | Sebastian Herbszt | #define ATA_SRST (1 << 2) /* software reset */ |
164 | 03c7a6a8 | Sebastian Herbszt | |
165 | 03c7a6a8 | Sebastian Herbszt | #define STATE_RUN 0 |
166 | 03c7a6a8 | Sebastian Herbszt | #define STATE_RESET 1 |
167 | 03c7a6a8 | Sebastian Herbszt | |
168 | 03c7a6a8 | Sebastian Herbszt | #define SATA_SCR_SSTATUS_DET_NODEV 0x0 |
169 | 03c7a6a8 | Sebastian Herbszt | #define SATA_SCR_SSTATUS_DET_DEV_PRESENT_PHY_UP 0x3 |
170 | 03c7a6a8 | Sebastian Herbszt | |
171 | 03c7a6a8 | Sebastian Herbszt | #define SATA_SCR_SSTATUS_SPD_NODEV 0x00 |
172 | 03c7a6a8 | Sebastian Herbszt | #define SATA_SCR_SSTATUS_SPD_GEN1 0x10 |
173 | 03c7a6a8 | Sebastian Herbszt | |
174 | 03c7a6a8 | Sebastian Herbszt | #define SATA_SCR_SSTATUS_IPM_NODEV 0x000 |
175 | 03c7a6a8 | Sebastian Herbszt | #define SATA_SCR_SSTATUS_IPM_ACTIVE 0X100 |
176 | 03c7a6a8 | Sebastian Herbszt | |
177 | 03c7a6a8 | Sebastian Herbszt | #define AHCI_SCR_SCTL_DET 0xf |
178 | 03c7a6a8 | Sebastian Herbszt | |
179 | 03c7a6a8 | Sebastian Herbszt | #define SATA_FIS_TYPE_REGISTER_H2D 0x27 |
180 | 03c7a6a8 | Sebastian Herbszt | #define SATA_FIS_REG_H2D_UPDATE_COMMAND_REGISTER 0x80 |
181 | 03c7a6a8 | Sebastian Herbszt | |
182 | 03c7a6a8 | Sebastian Herbszt | #define AHCI_CMD_HDR_CMD_FIS_LEN 0x1f |
183 | 03c7a6a8 | Sebastian Herbszt | #define AHCI_CMD_HDR_PRDT_LEN 16 |
184 | 03c7a6a8 | Sebastian Herbszt | |
185 | 03c7a6a8 | Sebastian Herbszt | #define SATA_SIGNATURE_CDROM 0xeb140000 |
186 | 03c7a6a8 | Sebastian Herbszt | #define SATA_SIGNATURE_DISK 0x00000101 |
187 | 03c7a6a8 | Sebastian Herbszt | |
188 | 03c7a6a8 | Sebastian Herbszt | #define AHCI_GENERIC_HOST_CONTROL_REGS_MAX_ADDR 0x20 |
189 | 03c7a6a8 | Sebastian Herbszt | /* Shouldn't this be 0x2c? */
|
190 | 03c7a6a8 | Sebastian Herbszt | |
191 | 03c7a6a8 | Sebastian Herbszt | #define AHCI_PORT_REGS_START_ADDR 0x100 |
192 | 03c7a6a8 | Sebastian Herbszt | #define AHCI_PORT_ADDR_OFFSET_MASK 0x7f |
193 | 2c4b9d0e | Alexander Graf | #define AHCI_PORT_ADDR_OFFSET_LEN 0x80 |
194 | 03c7a6a8 | Sebastian Herbszt | |
195 | 03c7a6a8 | Sebastian Herbszt | #define AHCI_NUM_COMMAND_SLOTS 31 |
196 | 03c7a6a8 | Sebastian Herbszt | #define AHCI_SUPPORTED_SPEED 20 |
197 | 03c7a6a8 | Sebastian Herbszt | #define AHCI_SUPPORTED_SPEED_GEN1 1 |
198 | 03c7a6a8 | Sebastian Herbszt | #define AHCI_VERSION_1_0 0x10000 |
199 | 03c7a6a8 | Sebastian Herbszt | |
200 | 03c7a6a8 | Sebastian Herbszt | #define AHCI_PROGMODE_MAJOR_REV_1 1 |
201 | 03c7a6a8 | Sebastian Herbszt | |
202 | 03c7a6a8 | Sebastian Herbszt | #define AHCI_COMMAND_TABLE_ACMD 0x40 |
203 | 03c7a6a8 | Sebastian Herbszt | |
204 | 03c7a6a8 | Sebastian Herbszt | #define IDE_FEATURE_DMA 1 |
205 | 03c7a6a8 | Sebastian Herbszt | |
206 | 03c7a6a8 | Sebastian Herbszt | #define READ_FPDMA_QUEUED 0x60 |
207 | 03c7a6a8 | Sebastian Herbszt | #define WRITE_FPDMA_QUEUED 0x61 |
208 | 03c7a6a8 | Sebastian Herbszt | |
209 | 03c7a6a8 | Sebastian Herbszt | #define RES_FIS_DSFIS 0x00 |
210 | 03c7a6a8 | Sebastian Herbszt | #define RES_FIS_PSFIS 0x20 |
211 | 03c7a6a8 | Sebastian Herbszt | #define RES_FIS_RFIS 0x40 |
212 | 03c7a6a8 | Sebastian Herbszt | #define RES_FIS_SDBFIS 0x58 |
213 | 03c7a6a8 | Sebastian Herbszt | #define RES_FIS_UFIS 0x60 |
214 | 03c7a6a8 | Sebastian Herbszt | |
215 | 465f1ab1 | Daniel Verkamp | #define SATA_CAP_SIZE 0x8 |
216 | 465f1ab1 | Daniel Verkamp | #define SATA_CAP_REV 0x2 |
217 | 465f1ab1 | Daniel Verkamp | #define SATA_CAP_BAR 0x4 |
218 | 465f1ab1 | Daniel Verkamp | |
219 | 03c7a6a8 | Sebastian Herbszt | typedef struct AHCIControlRegs { |
220 | 03c7a6a8 | Sebastian Herbszt | uint32_t cap; |
221 | 03c7a6a8 | Sebastian Herbszt | uint32_t ghc; |
222 | 03c7a6a8 | Sebastian Herbszt | uint32_t irqstatus; |
223 | 03c7a6a8 | Sebastian Herbszt | uint32_t impl; |
224 | 03c7a6a8 | Sebastian Herbszt | uint32_t version; |
225 | 03c7a6a8 | Sebastian Herbszt | } AHCIControlRegs; |
226 | 03c7a6a8 | Sebastian Herbszt | |
227 | 03c7a6a8 | Sebastian Herbszt | typedef struct AHCIPortRegs { |
228 | 03c7a6a8 | Sebastian Herbszt | uint32_t lst_addr; |
229 | 03c7a6a8 | Sebastian Herbszt | uint32_t lst_addr_hi; |
230 | 03c7a6a8 | Sebastian Herbszt | uint32_t fis_addr; |
231 | 03c7a6a8 | Sebastian Herbszt | uint32_t fis_addr_hi; |
232 | 03c7a6a8 | Sebastian Herbszt | uint32_t irq_stat; |
233 | 03c7a6a8 | Sebastian Herbszt | uint32_t irq_mask; |
234 | 03c7a6a8 | Sebastian Herbszt | uint32_t cmd; |
235 | 03c7a6a8 | Sebastian Herbszt | uint32_t unused0; |
236 | 03c7a6a8 | Sebastian Herbszt | uint32_t tfdata; |
237 | 03c7a6a8 | Sebastian Herbszt | uint32_t sig; |
238 | 03c7a6a8 | Sebastian Herbszt | uint32_t scr_stat; |
239 | 03c7a6a8 | Sebastian Herbszt | uint32_t scr_ctl; |
240 | 03c7a6a8 | Sebastian Herbszt | uint32_t scr_err; |
241 | 03c7a6a8 | Sebastian Herbszt | uint32_t scr_act; |
242 | 03c7a6a8 | Sebastian Herbszt | uint32_t cmd_issue; |
243 | 03c7a6a8 | Sebastian Herbszt | uint32_t reserved; |
244 | 03c7a6a8 | Sebastian Herbszt | } AHCIPortRegs; |
245 | 03c7a6a8 | Sebastian Herbszt | |
246 | 03c7a6a8 | Sebastian Herbszt | typedef struct AHCICmdHdr { |
247 | 03c7a6a8 | Sebastian Herbszt | uint32_t opts; |
248 | 03c7a6a8 | Sebastian Herbszt | uint32_t status; |
249 | 03c7a6a8 | Sebastian Herbszt | uint64_t tbl_addr; |
250 | 03c7a6a8 | Sebastian Herbszt | uint32_t reserved[4];
|
251 | 541dc0d4 | Stefan Weil | } QEMU_PACKED AHCICmdHdr; |
252 | 03c7a6a8 | Sebastian Herbszt | |
253 | 03c7a6a8 | Sebastian Herbszt | typedef struct AHCI_SG { |
254 | 03c7a6a8 | Sebastian Herbszt | uint64_t addr; |
255 | 03c7a6a8 | Sebastian Herbszt | uint32_t reserved; |
256 | 03c7a6a8 | Sebastian Herbszt | uint32_t flags_size; |
257 | 541dc0d4 | Stefan Weil | } QEMU_PACKED AHCI_SG; |
258 | 03c7a6a8 | Sebastian Herbszt | |
259 | 03c7a6a8 | Sebastian Herbszt | typedef struct AHCIDevice AHCIDevice; |
260 | 03c7a6a8 | Sebastian Herbszt | |
261 | 03c7a6a8 | Sebastian Herbszt | typedef struct NCQTransferState { |
262 | 03c7a6a8 | Sebastian Herbszt | AHCIDevice *drive; |
263 | 03c7a6a8 | Sebastian Herbszt | BlockDriverAIOCB *aiocb; |
264 | 03c7a6a8 | Sebastian Herbszt | QEMUSGList sglist; |
265 | a597e79c | Christoph Hellwig | BlockAcctCookie acct; |
266 | 03c7a6a8 | Sebastian Herbszt | uint16_t sector_count; |
267 | 03c7a6a8 | Sebastian Herbszt | uint64_t lba; |
268 | 03c7a6a8 | Sebastian Herbszt | uint8_t tag; |
269 | 03c7a6a8 | Sebastian Herbszt | int slot;
|
270 | 03c7a6a8 | Sebastian Herbszt | int used;
|
271 | 03c7a6a8 | Sebastian Herbszt | } NCQTransferState; |
272 | 03c7a6a8 | Sebastian Herbszt | |
273 | 03c7a6a8 | Sebastian Herbszt | struct AHCIDevice {
|
274 | 03c7a6a8 | Sebastian Herbszt | IDEDMA dma; |
275 | 03c7a6a8 | Sebastian Herbszt | IDEBus port; |
276 | 03c7a6a8 | Sebastian Herbszt | int port_no;
|
277 | 03c7a6a8 | Sebastian Herbszt | uint32_t port_state; |
278 | 03c7a6a8 | Sebastian Herbszt | uint32_t finished; |
279 | 03c7a6a8 | Sebastian Herbszt | AHCIPortRegs port_regs; |
280 | 03c7a6a8 | Sebastian Herbszt | struct AHCIState *hba;
|
281 | 03c7a6a8 | Sebastian Herbszt | QEMUBH *check_bh; |
282 | 03c7a6a8 | Sebastian Herbszt | uint8_t *lst; |
283 | 03c7a6a8 | Sebastian Herbszt | uint8_t *res_fis; |
284 | 03c7a6a8 | Sebastian Herbszt | int dma_status;
|
285 | 03c7a6a8 | Sebastian Herbszt | int done_atapi_packet;
|
286 | 03c7a6a8 | Sebastian Herbszt | int busy_slot;
|
287 | 87e62065 | Alexander Graf | int init_d2h_sent;
|
288 | 03c7a6a8 | Sebastian Herbszt | BlockDriverCompletionFunc *dma_cb; |
289 | 03c7a6a8 | Sebastian Herbszt | AHCICmdHdr *cur_cmd; |
290 | 03c7a6a8 | Sebastian Herbszt | NCQTransferState ncq_tfs[AHCI_MAX_CMDS]; |
291 | 03c7a6a8 | Sebastian Herbszt | }; |
292 | 03c7a6a8 | Sebastian Herbszt | |
293 | 03c7a6a8 | Sebastian Herbszt | typedef struct AHCIState { |
294 | 2c4b9d0e | Alexander Graf | AHCIDevice *dev; |
295 | 03c7a6a8 | Sebastian Herbszt | AHCIControlRegs control_regs; |
296 | 67e576c2 | Avi Kivity | MemoryRegion mem; |
297 | 465f1ab1 | Daniel Verkamp | MemoryRegion idp; /* Index-Data Pair I/O port space */
|
298 | 465f1ab1 | Daniel Verkamp | unsigned idp_offset; /* Offset of index in I/O port space */ |
299 | 465f1ab1 | Daniel Verkamp | uint32_t idp_index; /* Current IDP index */
|
300 | 2c4b9d0e | Alexander Graf | int ports;
|
301 | 03c7a6a8 | Sebastian Herbszt | qemu_irq irq; |
302 | 03c7a6a8 | Sebastian Herbszt | } AHCIState; |
303 | 03c7a6a8 | Sebastian Herbszt | |
304 | 03c7a6a8 | Sebastian Herbszt | typedef struct AHCIPCIState { |
305 | 03c7a6a8 | Sebastian Herbszt | PCIDevice card; |
306 | 03c7a6a8 | Sebastian Herbszt | AHCIState ahci; |
307 | 03c7a6a8 | Sebastian Herbszt | } AHCIPCIState; |
308 | 03c7a6a8 | Sebastian Herbszt | |
309 | 03c7a6a8 | Sebastian Herbszt | typedef struct NCQFrame { |
310 | 03c7a6a8 | Sebastian Herbszt | uint8_t fis_type; |
311 | 03c7a6a8 | Sebastian Herbszt | uint8_t c; |
312 | 03c7a6a8 | Sebastian Herbszt | uint8_t command; |
313 | 03c7a6a8 | Sebastian Herbszt | uint8_t sector_count_low; |
314 | 03c7a6a8 | Sebastian Herbszt | uint8_t lba0; |
315 | 03c7a6a8 | Sebastian Herbszt | uint8_t lba1; |
316 | 03c7a6a8 | Sebastian Herbszt | uint8_t lba2; |
317 | 03c7a6a8 | Sebastian Herbszt | uint8_t fua; |
318 | 03c7a6a8 | Sebastian Herbszt | uint8_t lba3; |
319 | 03c7a6a8 | Sebastian Herbszt | uint8_t lba4; |
320 | 03c7a6a8 | Sebastian Herbszt | uint8_t lba5; |
321 | 03c7a6a8 | Sebastian Herbszt | uint8_t sector_count_high; |
322 | 03c7a6a8 | Sebastian Herbszt | uint8_t tag; |
323 | 03c7a6a8 | Sebastian Herbszt | uint8_t reserved5; |
324 | 03c7a6a8 | Sebastian Herbszt | uint8_t reserved6; |
325 | 03c7a6a8 | Sebastian Herbszt | uint8_t control; |
326 | 03c7a6a8 | Sebastian Herbszt | uint8_t reserved7; |
327 | 03c7a6a8 | Sebastian Herbszt | uint8_t reserved8; |
328 | 03c7a6a8 | Sebastian Herbszt | uint8_t reserved9; |
329 | 03c7a6a8 | Sebastian Herbszt | uint8_t reserved10; |
330 | 541dc0d4 | Stefan Weil | } QEMU_PACKED NCQFrame; |
331 | 03c7a6a8 | Sebastian Herbszt | |
332 | 2c4b9d0e | Alexander Graf | void ahci_init(AHCIState *s, DeviceState *qdev, int ports); |
333 | 2c4b9d0e | Alexander Graf | void ahci_uninit(AHCIState *s);
|
334 | 03c7a6a8 | Sebastian Herbszt | |
335 | 03c7a6a8 | Sebastian Herbszt | void ahci_reset(void *opaque); |
336 | 03c7a6a8 | Sebastian Herbszt | |
337 | 03c7a6a8 | Sebastian Herbszt | #endif /* HW_IDE_AHCI_H */ |