]>
Commit | Line | Data |
---|---|---|
f83a40dc AG |
1 | /* |
2 | * QEMU AHCI Emulation | |
3 | * | |
4 | * Copyright (c) 2010 qiaochong@loongson.cn | |
5 | * Copyright (c) 2010 Roland Elek <elek.roland@gmail.com> | |
6 | * Copyright (c) 2010 Sebastian Herbszt <herbszt@gmx.de> | |
7 | * Copyright (c) 2010 Alexander Graf <agraf@suse.de> | |
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 | ||
27 | #define AHCI_PCI_BAR 5 | |
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 | ||
215 | typedef struct AHCIControlRegs { | |
216 | uint32_t cap; | |
217 | uint32_t ghc; | |
218 | uint32_t irqstatus; | |
219 | uint32_t impl; | |
220 | uint32_t version; | |
221 | } AHCIControlRegs; | |
222 | ||
223 | typedef struct AHCIPortRegs { | |
224 | uint32_t lst_addr; | |
225 | uint32_t lst_addr_hi; | |
226 | uint32_t fis_addr; | |
227 | uint32_t fis_addr_hi; | |
228 | uint32_t irq_stat; | |
229 | uint32_t irq_mask; | |
230 | uint32_t cmd; | |
231 | uint32_t unused0; | |
232 | uint32_t tfdata; | |
233 | uint32_t sig; | |
234 | uint32_t scr_stat; | |
235 | uint32_t scr_ctl; | |
236 | uint32_t scr_err; | |
237 | uint32_t scr_act; | |
238 | uint32_t cmd_issue; | |
239 | uint32_t reserved; | |
240 | } AHCIPortRegs; | |
241 | ||
242 | typedef struct AHCICmdHdr { | |
243 | uint32_t opts; | |
244 | uint32_t status; | |
245 | uint64_t tbl_addr; | |
246 | uint32_t reserved[4]; | |
541dc0d4 | 247 | } QEMU_PACKED AHCICmdHdr; |
03c7a6a8 SH |
248 | |
249 | typedef struct AHCI_SG { | |
250 | uint64_t addr; | |
251 | uint32_t reserved; | |
252 | uint32_t flags_size; | |
541dc0d4 | 253 | } QEMU_PACKED AHCI_SG; |
03c7a6a8 SH |
254 | |
255 | typedef struct AHCIDevice AHCIDevice; | |
256 | ||
257 | typedef struct NCQTransferState { | |
258 | AHCIDevice *drive; | |
259 | BlockDriverAIOCB *aiocb; | |
260 | QEMUSGList sglist; | |
a597e79c | 261 | BlockAcctCookie acct; |
03c7a6a8 SH |
262 | uint16_t sector_count; |
263 | uint64_t lba; | |
264 | uint8_t tag; | |
265 | int slot; | |
266 | int used; | |
267 | } NCQTransferState; | |
268 | ||
269 | struct AHCIDevice { | |
270 | IDEDMA dma; | |
271 | IDEBus port; | |
272 | int port_no; | |
273 | uint32_t port_state; | |
274 | uint32_t finished; | |
275 | AHCIPortRegs port_regs; | |
276 | struct AHCIState *hba; | |
277 | QEMUBH *check_bh; | |
278 | uint8_t *lst; | |
279 | uint8_t *res_fis; | |
280 | int dma_status; | |
281 | int done_atapi_packet; | |
282 | int busy_slot; | |
87e62065 | 283 | int init_d2h_sent; |
03c7a6a8 SH |
284 | BlockDriverCompletionFunc *dma_cb; |
285 | AHCICmdHdr *cur_cmd; | |
286 | NCQTransferState ncq_tfs[AHCI_MAX_CMDS]; | |
287 | }; | |
288 | ||
289 | typedef struct AHCIState { | |
2c4b9d0e | 290 | AHCIDevice *dev; |
03c7a6a8 | 291 | AHCIControlRegs control_regs; |
67e576c2 | 292 | MemoryRegion mem; |
2c4b9d0e | 293 | int ports; |
03c7a6a8 SH |
294 | qemu_irq irq; |
295 | } AHCIState; | |
296 | ||
297 | typedef struct AHCIPCIState { | |
298 | PCIDevice card; | |
299 | AHCIState ahci; | |
300 | } AHCIPCIState; | |
301 | ||
302 | typedef struct NCQFrame { | |
303 | uint8_t fis_type; | |
304 | uint8_t c; | |
305 | uint8_t command; | |
306 | uint8_t sector_count_low; | |
307 | uint8_t lba0; | |
308 | uint8_t lba1; | |
309 | uint8_t lba2; | |
310 | uint8_t fua; | |
311 | uint8_t lba3; | |
312 | uint8_t lba4; | |
313 | uint8_t lba5; | |
314 | uint8_t sector_count_high; | |
315 | uint8_t tag; | |
316 | uint8_t reserved5; | |
317 | uint8_t reserved6; | |
318 | uint8_t control; | |
319 | uint8_t reserved7; | |
320 | uint8_t reserved8; | |
321 | uint8_t reserved9; | |
322 | uint8_t reserved10; | |
541dc0d4 | 323 | } QEMU_PACKED NCQFrame; |
03c7a6a8 | 324 | |
2c4b9d0e AG |
325 | void ahci_init(AHCIState *s, DeviceState *qdev, int ports); |
326 | void ahci_uninit(AHCIState *s); | |
03c7a6a8 | 327 | |
03c7a6a8 SH |
328 | void ahci_reset(void *opaque); |
329 | ||
330 | #endif /* HW_IDE_AHCI_H */ |