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