]>
Commit | Line | Data |
---|---|---|
1cd1031d JS |
1 | /* |
2 | * AHCI test cases | |
3 | * | |
4 | * Copyright (c) 2014 John Snow <[email protected]> | |
5 | * | |
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy | |
7 | * of this software and associated documentation files (the "Software"), to deal | |
8 | * in the Software without restriction, including without limitation the rights | |
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
10 | * copies of the Software, and to permit persons to whom the Software is | |
11 | * furnished to do so, subject to the following conditions: | |
12 | * | |
13 | * The above copyright notice and this permission notice shall be included in | |
14 | * all copies or substantial portions of the Software. | |
15 | * | |
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
22 | * THE SOFTWARE. | |
23 | */ | |
24 | ||
25 | #include <stdint.h> | |
26 | #include <string.h> | |
27 | #include <stdio.h> | |
8840a843 | 28 | #include <getopt.h> |
1cd1031d JS |
29 | #include <glib.h> |
30 | ||
31 | #include "libqtest.h" | |
32 | #include "libqos/pci-pc.h" | |
33 | #include "libqos/malloc-pc.h" | |
34 | ||
35 | #include "qemu-common.h" | |
36 | #include "qemu/host-utils.h" | |
37 | ||
38 | #include "hw/pci/pci_ids.h" | |
39 | #include "hw/pci/pci_regs.h" | |
40 | ||
41 | /* Test-specific defines. */ | |
42 | #define TEST_IMAGE_SIZE (64 * 1024 * 1024) | |
43 | ||
44 | /*** Supplementary PCI Config Space IDs & Masks ***/ | |
45 | #define PCI_DEVICE_ID_INTEL_Q35_AHCI (0x2922) | |
8840a843 JS |
46 | #define PCI_MSI_FLAGS_RESERVED (0xFF00) |
47 | #define PCI_PM_CTRL_RESERVED (0xFC) | |
48 | #define PCI_BCC(REG32) ((REG32) >> 24) | |
49 | #define PCI_PI(REG32) (((REG32) >> 8) & 0xFF) | |
50 | #define PCI_SCC(REG32) (((REG32) >> 16) & 0xFF) | |
51 | ||
52 | /*** Recognized AHCI Device Types ***/ | |
53 | #define AHCI_INTEL_ICH9 (PCI_DEVICE_ID_INTEL_Q35_AHCI << 16 | \ | |
54 | PCI_VENDOR_ID_INTEL) | |
1cd1031d | 55 | |
c2f3029f JS |
56 | /*** AHCI/HBA Register Offsets and Bitmasks ***/ |
57 | #define AHCI_CAP (0) | |
58 | #define AHCI_CAP_NP (0x1F) | |
59 | #define AHCI_CAP_SXS (0x20) | |
60 | #define AHCI_CAP_EMS (0x40) | |
61 | #define AHCI_CAP_CCCS (0x80) | |
62 | #define AHCI_CAP_NCS (0x1F00) | |
63 | #define AHCI_CAP_PSC (0x2000) | |
64 | #define AHCI_CAP_SSC (0x4000) | |
65 | #define AHCI_CAP_PMD (0x8000) | |
66 | #define AHCI_CAP_FBSS (0x10000) | |
67 | #define AHCI_CAP_SPM (0x20000) | |
68 | #define AHCI_CAP_SAM (0x40000) | |
69 | #define AHCI_CAP_RESERVED (0x80000) | |
70 | #define AHCI_CAP_ISS (0xF00000) | |
71 | #define AHCI_CAP_SCLO (0x1000000) | |
72 | #define AHCI_CAP_SAL (0x2000000) | |
73 | #define AHCI_CAP_SALP (0x4000000) | |
74 | #define AHCI_CAP_SSS (0x8000000) | |
75 | #define AHCI_CAP_SMPS (0x10000000) | |
76 | #define AHCI_CAP_SSNTF (0x20000000) | |
77 | #define AHCI_CAP_SNCQ (0x40000000) | |
78 | #define AHCI_CAP_S64A (0x80000000) | |
79 | ||
80 | #define AHCI_GHC (1) | |
81 | #define AHCI_GHC_HR (0x01) | |
82 | #define AHCI_GHC_IE (0x02) | |
83 | #define AHCI_GHC_MRSM (0x04) | |
84 | #define AHCI_GHC_RESERVED (0x7FFFFFF8) | |
85 | #define AHCI_GHC_AE (0x80000000) | |
86 | ||
87 | #define AHCI_IS (2) | |
88 | #define AHCI_PI (3) | |
89 | #define AHCI_VS (4) | |
90 | ||
91 | #define AHCI_CCCCTL (5) | |
92 | #define AHCI_CCCCTL_EN (0x01) | |
93 | #define AHCI_CCCCTL_RESERVED (0x06) | |
94 | #define AHCI_CCCCTL_CC (0xFF00) | |
95 | #define AHCI_CCCCTL_TV (0xFFFF0000) | |
96 | ||
97 | #define AHCI_CCCPORTS (6) | |
98 | #define AHCI_EMLOC (7) | |
99 | ||
100 | #define AHCI_EMCTL (8) | |
101 | #define AHCI_EMCTL_STSMR (0x01) | |
102 | #define AHCI_EMCTL_CTLTM (0x100) | |
103 | #define AHCI_EMCTL_CTLRST (0x200) | |
104 | #define AHCI_EMCTL_RESERVED (0xF0F0FCFE) | |
105 | ||
106 | #define AHCI_CAP2 (9) | |
107 | #define AHCI_CAP2_BOH (0x01) | |
108 | #define AHCI_CAP2_NVMP (0x02) | |
109 | #define AHCI_CAP2_APST (0x04) | |
110 | #define AHCI_CAP2_RESERVED (0xFFFFFFF8) | |
111 | ||
112 | #define AHCI_BOHC (10) | |
113 | #define AHCI_RESERVED (11) | |
114 | #define AHCI_NVMHCI (24) | |
115 | #define AHCI_VENDOR (40) | |
116 | #define AHCI_PORTS (64) | |
117 | ||
118 | /*** Port Memory Offsets & Bitmasks ***/ | |
119 | #define AHCI_PX_CLB (0) | |
120 | #define AHCI_PX_CLB_RESERVED (0x1FF) | |
121 | ||
122 | #define AHCI_PX_CLBU (1) | |
123 | ||
124 | #define AHCI_PX_FB (2) | |
125 | #define AHCI_PX_FB_RESERVED (0xFF) | |
126 | ||
127 | #define AHCI_PX_FBU (3) | |
128 | ||
129 | #define AHCI_PX_IS (4) | |
130 | #define AHCI_PX_IS_DHRS (0x1) | |
131 | #define AHCI_PX_IS_PSS (0x2) | |
132 | #define AHCI_PX_IS_DSS (0x4) | |
133 | #define AHCI_PX_IS_SDBS (0x8) | |
134 | #define AHCI_PX_IS_UFS (0x10) | |
135 | #define AHCI_PX_IS_DPS (0x20) | |
136 | #define AHCI_PX_IS_PCS (0x40) | |
137 | #define AHCI_PX_IS_DMPS (0x80) | |
138 | #define AHCI_PX_IS_RESERVED (0x23FFF00) | |
139 | #define AHCI_PX_IS_PRCS (0x400000) | |
140 | #define AHCI_PX_IS_IPMS (0x800000) | |
141 | #define AHCI_PX_IS_OFS (0x1000000) | |
142 | #define AHCI_PX_IS_INFS (0x4000000) | |
143 | #define AHCI_PX_IS_IFS (0x8000000) | |
144 | #define AHCI_PX_IS_HBDS (0x10000000) | |
145 | #define AHCI_PX_IS_HBFS (0x20000000) | |
146 | #define AHCI_PX_IS_TFES (0x40000000) | |
147 | #define AHCI_PX_IS_CPDS (0x80000000) | |
148 | ||
149 | #define AHCI_PX_IE (5) | |
150 | #define AHCI_PX_IE_DHRE (0x1) | |
151 | #define AHCI_PX_IE_PSE (0x2) | |
152 | #define AHCI_PX_IE_DSE (0x4) | |
153 | #define AHCI_PX_IE_SDBE (0x8) | |
154 | #define AHCI_PX_IE_UFE (0x10) | |
155 | #define AHCI_PX_IE_DPE (0x20) | |
156 | #define AHCI_PX_IE_PCE (0x40) | |
157 | #define AHCI_PX_IE_DMPE (0x80) | |
158 | #define AHCI_PX_IE_RESERVED (0x23FFF00) | |
159 | #define AHCI_PX_IE_PRCE (0x400000) | |
160 | #define AHCI_PX_IE_IPME (0x800000) | |
161 | #define AHCI_PX_IE_OFE (0x1000000) | |
162 | #define AHCI_PX_IE_INFE (0x4000000) | |
163 | #define AHCI_PX_IE_IFE (0x8000000) | |
164 | #define AHCI_PX_IE_HBDE (0x10000000) | |
165 | #define AHCI_PX_IE_HBFE (0x20000000) | |
166 | #define AHCI_PX_IE_TFEE (0x40000000) | |
167 | #define AHCI_PX_IE_CPDE (0x80000000) | |
168 | ||
169 | #define AHCI_PX_CMD (6) | |
170 | #define AHCI_PX_CMD_ST (0x1) | |
171 | #define AHCI_PX_CMD_SUD (0x2) | |
172 | #define AHCI_PX_CMD_POD (0x4) | |
173 | #define AHCI_PX_CMD_CLO (0x8) | |
174 | #define AHCI_PX_CMD_FRE (0x10) | |
175 | #define AHCI_PX_CMD_RESERVED (0xE0) | |
176 | #define AHCI_PX_CMD_CCS (0x1F00) | |
177 | #define AHCI_PX_CMD_MPSS (0x2000) | |
178 | #define AHCI_PX_CMD_FR (0x4000) | |
179 | #define AHCI_PX_CMD_CR (0x8000) | |
180 | #define AHCI_PX_CMD_CPS (0x10000) | |
181 | #define AHCI_PX_CMD_PMA (0x20000) | |
182 | #define AHCI_PX_CMD_HPCP (0x40000) | |
183 | #define AHCI_PX_CMD_MPSP (0x80000) | |
184 | #define AHCI_PX_CMD_CPD (0x100000) | |
185 | #define AHCI_PX_CMD_ESP (0x200000) | |
186 | #define AHCI_PX_CMD_FBSCP (0x400000) | |
187 | #define AHCI_PX_CMD_APSTE (0x800000) | |
188 | #define AHCI_PX_CMD_ATAPI (0x1000000) | |
189 | #define AHCI_PX_CMD_DLAE (0x2000000) | |
190 | #define AHCI_PX_CMD_ALPE (0x4000000) | |
191 | #define AHCI_PX_CMD_ASP (0x8000000) | |
192 | #define AHCI_PX_CMD_ICC (0xF0000000) | |
193 | ||
194 | #define AHCI_PX_RES1 (7) | |
195 | ||
196 | #define AHCI_PX_TFD (8) | |
197 | #define AHCI_PX_TFD_STS (0xFF) | |
198 | #define AHCI_PX_TFD_STS_ERR (0x01) | |
199 | #define AHCI_PX_TFD_STS_CS1 (0x06) | |
200 | #define AHCI_PX_TFD_STS_DRQ (0x08) | |
201 | #define AHCI_PX_TFD_STS_CS2 (0x70) | |
202 | #define AHCI_PX_TFD_STS_BSY (0x80) | |
203 | #define AHCI_PX_TFD_ERR (0xFF00) | |
204 | #define AHCI_PX_TFD_RESERVED (0xFFFF0000) | |
205 | ||
206 | #define AHCI_PX_SIG (9) | |
207 | #define AHCI_PX_SIG_SECTOR_COUNT (0xFF) | |
208 | #define AHCI_PX_SIG_LBA_LOW (0xFF00) | |
209 | #define AHCI_PX_SIG_LBA_MID (0xFF0000) | |
210 | #define AHCI_PX_SIG_LBA_HIGH (0xFF000000) | |
211 | ||
212 | #define AHCI_PX_SSTS (10) | |
213 | #define AHCI_PX_SSTS_DET (0x0F) | |
214 | #define AHCI_PX_SSTS_SPD (0xF0) | |
215 | #define AHCI_PX_SSTS_IPM (0xF00) | |
216 | #define AHCI_PX_SSTS_RESERVED (0xFFFFF000) | |
217 | #define SSTS_DET_NO_DEVICE (0x00) | |
218 | #define SSTS_DET_PRESENT (0x01) | |
219 | #define SSTS_DET_ESTABLISHED (0x03) | |
220 | #define SSTS_DET_OFFLINE (0x04) | |
221 | ||
222 | #define AHCI_PX_SCTL (11) | |
223 | ||
224 | #define AHCI_PX_SERR (12) | |
225 | #define AHCI_PX_SERR_ERR (0xFFFF) | |
226 | #define AHCI_PX_SERR_DIAG (0xFFFF0000) | |
227 | #define AHCI_PX_SERR_DIAG_X (0x04000000) | |
228 | ||
229 | #define AHCI_PX_SACT (13) | |
230 | #define AHCI_PX_CI (14) | |
231 | #define AHCI_PX_SNTF (15) | |
232 | ||
233 | #define AHCI_PX_FBS (16) | |
234 | #define AHCI_PX_FBS_EN (0x1) | |
235 | #define AHCI_PX_FBS_DEC (0x2) | |
236 | #define AHCI_PX_FBS_SDE (0x4) | |
237 | #define AHCI_PX_FBS_DEV (0xF00) | |
238 | #define AHCI_PX_FBS_ADO (0xF000) | |
239 | #define AHCI_PX_FBS_DWE (0xF0000) | |
240 | #define AHCI_PX_FBS_RESERVED (0xFFF000F8) | |
241 | ||
242 | #define AHCI_PX_RES2 (17) | |
243 | #define AHCI_PX_VS (28) | |
244 | ||
245 | #define HBA_DATA_REGION_SIZE (256) | |
246 | #define HBA_PORT_DATA_SIZE (128) | |
247 | #define HBA_PORT_NUM_REG (HBA_PORT_DATA_SIZE/4) | |
248 | ||
249 | #define AHCI_VERSION_0_95 (0x00000905) | |
250 | #define AHCI_VERSION_1_0 (0x00010000) | |
251 | #define AHCI_VERSION_1_1 (0x00010100) | |
252 | #define AHCI_VERSION_1_2 (0x00010200) | |
253 | #define AHCI_VERSION_1_3 (0x00010300) | |
254 | ||
0fa781e3 JS |
255 | /*** Structures ***/ |
256 | ||
257 | /** | |
258 | * Generic FIS structure. | |
259 | */ | |
260 | typedef struct FIS { | |
261 | uint8_t fis_type; | |
262 | uint8_t flags; | |
263 | char data[0]; | |
264 | } __attribute__((__packed__)) FIS; | |
265 | ||
266 | /** | |
267 | * Register device-to-host FIS structure. | |
268 | */ | |
269 | typedef struct RegD2HFIS { | |
270 | /* DW0 */ | |
271 | uint8_t fis_type; | |
272 | uint8_t flags; | |
273 | uint8_t status; | |
274 | uint8_t error; | |
275 | /* DW1 */ | |
276 | uint8_t lba_low; | |
277 | uint8_t lba_mid; | |
278 | uint8_t lba_high; | |
279 | uint8_t device; | |
280 | /* DW2 */ | |
281 | uint8_t lba3; | |
282 | uint8_t lba4; | |
283 | uint8_t lba5; | |
284 | uint8_t res1; | |
285 | /* DW3 */ | |
286 | uint16_t count; | |
287 | uint8_t res2; | |
288 | uint8_t res3; | |
289 | /* DW4 */ | |
290 | uint16_t res4; | |
291 | uint16_t res5; | |
292 | } __attribute__((__packed__)) RegD2HFIS; | |
293 | ||
294 | /** | |
295 | * Register host-to-device FIS structure. | |
296 | */ | |
297 | typedef struct RegH2DFIS { | |
298 | /* DW0 */ | |
299 | uint8_t fis_type; | |
300 | uint8_t flags; | |
301 | uint8_t command; | |
302 | uint8_t feature_low; | |
303 | /* DW1 */ | |
304 | uint8_t lba_low; | |
305 | uint8_t lba_mid; | |
306 | uint8_t lba_high; | |
307 | uint8_t device; | |
308 | /* DW2 */ | |
309 | uint8_t lba3; | |
310 | uint8_t lba4; | |
311 | uint8_t lba5; | |
312 | uint8_t feature_high; | |
313 | /* DW3 */ | |
314 | uint16_t count; | |
315 | uint8_t icc; | |
316 | uint8_t control; | |
317 | /* DW4 */ | |
318 | uint32_t aux; | |
319 | } __attribute__((__packed__)) RegH2DFIS; | |
320 | ||
321 | /** | |
322 | * Command List entry structure. | |
323 | * The command list contains between 1-32 of these structures. | |
324 | */ | |
325 | typedef struct AHCICommand { | |
326 | uint8_t b1; | |
327 | uint8_t b2; | |
328 | uint16_t prdtl; /* Phys Region Desc. Table Length */ | |
329 | uint32_t prdbc; /* Phys Region Desc. Byte Count */ | |
330 | uint32_t ctba; /* Command Table Descriptor Base Address */ | |
331 | uint32_t ctbau; /* '' Upper */ | |
332 | uint32_t res[4]; | |
333 | } __attribute__((__packed__)) AHCICommand; | |
334 | ||
335 | /** | |
336 | * Physical Region Descriptor; pointed to by the Command List Header, | |
337 | * struct ahci_command. | |
338 | */ | |
339 | typedef struct PRD { | |
340 | uint32_t dba; /* Data Base Address */ | |
341 | uint32_t dbau; /* Data Base Address Upper */ | |
342 | uint32_t res; /* Reserved */ | |
343 | uint32_t dbc; /* Data Byte Count (0-indexed) & Interrupt Flag (bit 2^31) */ | |
344 | } PRD; | |
345 | ||
c2f3029f JS |
346 | typedef struct HBACap { |
347 | uint32_t cap; | |
348 | uint32_t cap2; | |
349 | } HBACap; | |
350 | ||
1cd1031d JS |
351 | /*** Globals ***/ |
352 | static QGuestAllocator *guest_malloc; | |
353 | static QPCIBus *pcibus; | |
c2f3029f | 354 | static uint64_t barsize; |
1cd1031d | 355 | static char tmp_path[] = "/tmp/qtest.XXXXXX"; |
8840a843 JS |
356 | static bool ahci_pedantic; |
357 | static uint32_t ahci_fingerprint; | |
358 | ||
359 | /*** Macro Utilities ***/ | |
c2f3029f JS |
360 | #define BITANY(data, mask) (((data) & (mask)) != 0) |
361 | #define BITSET(data, mask) (((data) & (mask)) == (mask)) | |
362 | #define BITCLR(data, mask) (((data) & (mask)) == 0) | |
8840a843 JS |
363 | #define ASSERT_BIT_SET(data, mask) g_assert_cmphex((data) & (mask), ==, (mask)) |
364 | #define ASSERT_BIT_CLEAR(data, mask) g_assert_cmphex((data) & (mask), ==, 0) | |
1cd1031d | 365 | |
c2f3029f JS |
366 | /*** IO macros for the AHCI memory registers. ***/ |
367 | #define AHCI_READ(OFST) qpci_io_readl(ahci, hba_base + (OFST)) | |
368 | #define AHCI_WRITE(OFST, VAL) qpci_io_writel(ahci, hba_base + (OFST), (VAL)) | |
369 | #define AHCI_RREG(regno) AHCI_READ(4 * (regno)) | |
370 | #define AHCI_WREG(regno, val) AHCI_WRITE(4 * (regno), (val)) | |
dbc180e5 JS |
371 | #define AHCI_SET(regno, mask) AHCI_WREG((regno), AHCI_RREG(regno) | (mask)) |
372 | #define AHCI_CLR(regno, mask) AHCI_WREG((regno), AHCI_RREG(regno) & ~(mask)) | |
c2f3029f JS |
373 | |
374 | /*** IO macros for port-specific offsets inside of AHCI memory. ***/ | |
375 | #define PX_OFST(port, regno) (HBA_PORT_NUM_REG * (port) + AHCI_PORTS + (regno)) | |
376 | #define PX_RREG(port, regno) AHCI_RREG(PX_OFST((port), (regno))) | |
377 | #define PX_WREG(port, regno, val) AHCI_WREG(PX_OFST((port), (regno)), (val)) | |
dbc180e5 JS |
378 | #define PX_SET(port, reg, mask) PX_WREG((port), (reg), \ |
379 | PX_RREG((port), (reg)) | (mask)); | |
380 | #define PX_CLR(port, reg, mask) PX_WREG((port), (reg), \ | |
381 | PX_RREG((port), (reg)) & ~(mask)); | |
c2f3029f | 382 | |
0fa781e3 JS |
383 | /* For calculating how big the PRD table needs to be: */ |
384 | #define CMD_TBL_SIZ(n) ((0x80 + ((n) * sizeof(PRD)) + 0x7F) & ~0x7F) | |
385 | ||
386 | ||
1cd1031d JS |
387 | /*** Function Declarations ***/ |
388 | static QPCIDevice *get_ahci_device(void); | |
96d6d3ba | 389 | static QPCIDevice *start_ahci_device(QPCIDevice *dev, void **hba_base); |
1cd1031d | 390 | static void free_ahci_device(QPCIDevice *dev); |
c2f3029f JS |
391 | static void ahci_test_port_spec(QPCIDevice *ahci, void *hba_base, |
392 | HBACap *hcap, uint8_t port); | |
8840a843 JS |
393 | static void ahci_test_pci_spec(QPCIDevice *ahci); |
394 | static void ahci_test_pci_caps(QPCIDevice *ahci, uint16_t header, | |
395 | uint8_t offset); | |
396 | static void ahci_test_satacap(QPCIDevice *ahci, uint8_t offset); | |
397 | static void ahci_test_msicap(QPCIDevice *ahci, uint8_t offset); | |
398 | static void ahci_test_pmcap(QPCIDevice *ahci, uint8_t offset); | |
1cd1031d JS |
399 | |
400 | /*** Utilities ***/ | |
401 | ||
0fa781e3 JS |
402 | static void string_bswap16(uint16_t *s, size_t bytes) |
403 | { | |
404 | g_assert_cmphex((bytes & 1), ==, 0); | |
405 | bytes /= 2; | |
406 | ||
407 | while (bytes--) { | |
408 | *s = bswap16(*s); | |
409 | s++; | |
410 | } | |
411 | } | |
412 | ||
1cd1031d JS |
413 | /** |
414 | * Locate, verify, and return a handle to the AHCI device. | |
415 | */ | |
416 | static QPCIDevice *get_ahci_device(void) | |
417 | { | |
418 | QPCIDevice *ahci; | |
1cd1031d JS |
419 | |
420 | pcibus = qpci_init_pc(); | |
421 | ||
422 | /* Find the AHCI PCI device and verify it's the right one. */ | |
423 | ahci = qpci_device_find(pcibus, QPCI_DEVFN(0x1F, 0x02)); | |
424 | g_assert(ahci != NULL); | |
425 | ||
8840a843 | 426 | ahci_fingerprint = qpci_config_readl(ahci, PCI_VENDOR_ID); |
1cd1031d | 427 | |
8840a843 JS |
428 | switch (ahci_fingerprint) { |
429 | case AHCI_INTEL_ICH9: | |
430 | break; | |
431 | default: | |
432 | /* Unknown device. */ | |
433 | g_assert_not_reached(); | |
434 | } | |
1cd1031d JS |
435 | |
436 | return ahci; | |
437 | } | |
438 | ||
439 | static void free_ahci_device(QPCIDevice *ahci) | |
440 | { | |
441 | /* libqos doesn't have a function for this, so free it manually */ | |
442 | g_free(ahci); | |
443 | ||
444 | if (pcibus) { | |
445 | qpci_free_pc(pcibus); | |
446 | pcibus = NULL; | |
447 | } | |
c2f3029f JS |
448 | |
449 | /* Clear our cached barsize information. */ | |
450 | barsize = 0; | |
1cd1031d JS |
451 | } |
452 | ||
453 | /*** Test Setup & Teardown ***/ | |
454 | ||
455 | /** | |
456 | * Launch QEMU with the given command line, | |
457 | * and then set up interrupts and our guest malloc interface. | |
458 | */ | |
459 | static void qtest_boot(const char *cmdline_fmt, ...) | |
460 | { | |
461 | va_list ap; | |
462 | char *cmdline; | |
463 | ||
464 | va_start(ap, cmdline_fmt); | |
465 | cmdline = g_strdup_vprintf(cmdline_fmt, ap); | |
466 | va_end(ap); | |
467 | ||
468 | qtest_start(cmdline); | |
469 | qtest_irq_intercept_in(global_qtest, "ioapic"); | |
470 | guest_malloc = pc_alloc_init(); | |
471 | ||
472 | g_free(cmdline); | |
473 | } | |
474 | ||
475 | /** | |
476 | * Tear down the QEMU instance. | |
477 | */ | |
478 | static void qtest_shutdown(void) | |
479 | { | |
480 | g_free(guest_malloc); | |
481 | guest_malloc = NULL; | |
482 | qtest_end(); | |
483 | } | |
484 | ||
485 | /** | |
486 | * Start a Q35 machine and bookmark a handle to the AHCI device. | |
487 | */ | |
488 | static QPCIDevice *ahci_boot(void) | |
489 | { | |
b8e665e4 KW |
490 | qtest_boot("-drive if=none,id=drive0,file=%s,cache=writeback,serial=%s," |
491 | "format=raw" | |
1cd1031d JS |
492 | " -M q35 " |
493 | "-device ide-hd,drive=drive0 " | |
494 | "-global ide-hd.ver=%s", | |
495 | tmp_path, "testdisk", "version"); | |
496 | ||
497 | /* Verify that we have an AHCI device present. */ | |
498 | return get_ahci_device(); | |
499 | } | |
500 | ||
501 | /** | |
502 | * Clean up the PCI device, then terminate the QEMU instance. | |
503 | */ | |
504 | static void ahci_shutdown(QPCIDevice *ahci) | |
505 | { | |
506 | free_ahci_device(ahci); | |
507 | qtest_shutdown(); | |
508 | } | |
509 | ||
96d6d3ba JS |
510 | /*** Logical Device Initialization ***/ |
511 | ||
512 | /** | |
513 | * Start the PCI device and sanity-check default operation. | |
514 | */ | |
515 | static void ahci_pci_enable(QPCIDevice *ahci, void **hba_base) | |
516 | { | |
517 | uint8_t reg; | |
518 | ||
519 | start_ahci_device(ahci, hba_base); | |
520 | ||
521 | switch (ahci_fingerprint) { | |
522 | case AHCI_INTEL_ICH9: | |
523 | /* ICH9 has a register at PCI 0x92 that | |
524 | * acts as a master port enabler mask. */ | |
525 | reg = qpci_config_readb(ahci, 0x92); | |
526 | reg |= 0x3F; | |
527 | qpci_config_writeb(ahci, 0x92, reg); | |
0fa781e3 | 528 | /* 0...0111111b -- bit significant, ports 0-5 enabled. */ |
96d6d3ba JS |
529 | ASSERT_BIT_SET(qpci_config_readb(ahci, 0x92), 0x3F); |
530 | break; | |
531 | } | |
532 | ||
533 | } | |
534 | ||
535 | /** | |
536 | * Map BAR5/ABAR, and engage the PCI device. | |
537 | */ | |
538 | static QPCIDevice *start_ahci_device(QPCIDevice *ahci, void **hba_base) | |
539 | { | |
540 | /* Map AHCI's ABAR (BAR5) */ | |
c2f3029f | 541 | *hba_base = qpci_iomap(ahci, 5, &barsize); |
96d6d3ba JS |
542 | |
543 | /* turns on pci.cmd.iose, pci.cmd.mse and pci.cmd.bme */ | |
544 | qpci_device_enable(ahci); | |
545 | ||
546 | return ahci; | |
547 | } | |
548 | ||
dbc180e5 JS |
549 | /** |
550 | * Test and initialize the AHCI's HBA memory areas. | |
551 | * Initialize and start any ports with devices attached. | |
552 | * Bring the HBA into the idle state. | |
553 | */ | |
554 | static void ahci_hba_enable(QPCIDevice *ahci, void *hba_base) | |
555 | { | |
556 | /* Bits of interest in this section: | |
557 | * GHC.AE Global Host Control / AHCI Enable | |
558 | * PxCMD.ST Port Command: Start | |
559 | * PxCMD.SUD "Spin Up Device" | |
560 | * PxCMD.POD "Power On Device" | |
561 | * PxCMD.FRE "FIS Receive Enable" | |
562 | * PxCMD.FR "FIS Receive Running" | |
563 | * PxCMD.CR "Command List Running" | |
564 | */ | |
565 | ||
566 | g_assert(ahci != NULL); | |
567 | g_assert(hba_base != NULL); | |
568 | ||
569 | uint32_t reg, ports_impl, clb, fb; | |
570 | uint16_t i; | |
571 | uint8_t num_cmd_slots; | |
572 | ||
573 | g_assert(hba_base != 0); | |
574 | ||
575 | /* Set GHC.AE to 1 */ | |
576 | AHCI_SET(AHCI_GHC, AHCI_GHC_AE); | |
577 | reg = AHCI_RREG(AHCI_GHC); | |
578 | ASSERT_BIT_SET(reg, AHCI_GHC_AE); | |
579 | ||
580 | /* Read CAP.NCS, how many command slots do we have? */ | |
581 | reg = AHCI_RREG(AHCI_CAP); | |
582 | num_cmd_slots = ((reg & AHCI_CAP_NCS) >> ctzl(AHCI_CAP_NCS)) + 1; | |
583 | g_test_message("Number of Command Slots: %u", num_cmd_slots); | |
584 | ||
585 | /* Determine which ports are implemented. */ | |
586 | ports_impl = AHCI_RREG(AHCI_PI); | |
587 | ||
588 | for (i = 0; ports_impl; ports_impl >>= 1, ++i) { | |
589 | if (!(ports_impl & 0x01)) { | |
590 | continue; | |
591 | } | |
592 | ||
593 | g_test_message("Initializing port %u", i); | |
594 | ||
595 | reg = PX_RREG(i, AHCI_PX_CMD); | |
596 | if (BITCLR(reg, AHCI_PX_CMD_ST | AHCI_PX_CMD_CR | | |
597 | AHCI_PX_CMD_FRE | AHCI_PX_CMD_FR)) { | |
598 | g_test_message("port is idle"); | |
599 | } else { | |
600 | g_test_message("port needs to be idled"); | |
601 | PX_CLR(i, AHCI_PX_CMD, (AHCI_PX_CMD_ST | AHCI_PX_CMD_FRE)); | |
602 | /* The port has 500ms to disengage. */ | |
603 | usleep(500000); | |
604 | reg = PX_RREG(i, AHCI_PX_CMD); | |
605 | ASSERT_BIT_CLEAR(reg, AHCI_PX_CMD_CR); | |
606 | ASSERT_BIT_CLEAR(reg, AHCI_PX_CMD_FR); | |
607 | g_test_message("port is now idle"); | |
608 | /* The spec does allow for possibly needing a PORT RESET | |
609 | * or HBA reset if we fail to idle the port. */ | |
610 | } | |
611 | ||
612 | /* Allocate Memory for the Command List Buffer & FIS Buffer */ | |
613 | /* PxCLB space ... 0x20 per command, as in 4.2.2 p 36 */ | |
614 | clb = guest_alloc(guest_malloc, num_cmd_slots * 0x20); | |
615 | g_test_message("CLB: 0x%08x", clb); | |
616 | PX_WREG(i, AHCI_PX_CLB, clb); | |
617 | g_assert_cmphex(clb, ==, PX_RREG(i, AHCI_PX_CLB)); | |
618 | ||
619 | /* PxFB space ... 0x100, as in 4.2.1 p 35 */ | |
620 | fb = guest_alloc(guest_malloc, 0x100); | |
621 | g_test_message("FB: 0x%08x", fb); | |
622 | PX_WREG(i, AHCI_PX_FB, fb); | |
623 | g_assert_cmphex(fb, ==, PX_RREG(i, AHCI_PX_FB)); | |
624 | ||
625 | /* Clear PxSERR, PxIS, then IS.IPS[x] by writing '1's. */ | |
626 | PX_WREG(i, AHCI_PX_SERR, 0xFFFFFFFF); | |
627 | PX_WREG(i, AHCI_PX_IS, 0xFFFFFFFF); | |
628 | AHCI_WREG(AHCI_IS, (1 << i)); | |
629 | ||
630 | /* Verify Interrupts Cleared */ | |
631 | reg = PX_RREG(i, AHCI_PX_SERR); | |
632 | g_assert_cmphex(reg, ==, 0); | |
633 | ||
634 | reg = PX_RREG(i, AHCI_PX_IS); | |
635 | g_assert_cmphex(reg, ==, 0); | |
636 | ||
637 | reg = AHCI_RREG(AHCI_IS); | |
638 | ASSERT_BIT_CLEAR(reg, (1 << i)); | |
639 | ||
640 | /* Enable All Interrupts: */ | |
641 | PX_WREG(i, AHCI_PX_IE, 0xFFFFFFFF); | |
642 | reg = PX_RREG(i, AHCI_PX_IE); | |
643 | g_assert_cmphex(reg, ==, ~((uint32_t)AHCI_PX_IE_RESERVED)); | |
644 | ||
645 | /* Enable the FIS Receive Engine. */ | |
646 | PX_SET(i, AHCI_PX_CMD, AHCI_PX_CMD_FRE); | |
647 | reg = PX_RREG(i, AHCI_PX_CMD); | |
648 | ASSERT_BIT_SET(reg, AHCI_PX_CMD_FR); | |
649 | ||
650 | /* AHCI 1.3 spec: if !STS.BSY, !STS.DRQ and PxSSTS.DET indicates | |
651 | * physical presence, a device is present and may be started. However, | |
652 | * PxSERR.DIAG.X /may/ need to be cleared a priori. */ | |
653 | reg = PX_RREG(i, AHCI_PX_SERR); | |
654 | if (BITSET(reg, AHCI_PX_SERR_DIAG_X)) { | |
655 | PX_SET(i, AHCI_PX_SERR, AHCI_PX_SERR_DIAG_X); | |
656 | } | |
657 | ||
658 | reg = PX_RREG(i, AHCI_PX_TFD); | |
659 | if (BITCLR(reg, AHCI_PX_TFD_STS_BSY | AHCI_PX_TFD_STS_DRQ)) { | |
660 | reg = PX_RREG(i, AHCI_PX_SSTS); | |
661 | if ((reg & AHCI_PX_SSTS_DET) == SSTS_DET_ESTABLISHED) { | |
662 | /* Device Found: set PxCMD.ST := 1 */ | |
663 | PX_SET(i, AHCI_PX_CMD, AHCI_PX_CMD_ST); | |
664 | ASSERT_BIT_SET(PX_RREG(i, AHCI_PX_CMD), AHCI_PX_CMD_CR); | |
665 | g_test_message("Started Device %u", i); | |
666 | } else if ((reg & AHCI_PX_SSTS_DET)) { | |
667 | /* Device present, but in some unknown state. */ | |
668 | g_assert_not_reached(); | |
669 | } | |
670 | } | |
671 | } | |
672 | ||
673 | /* Enable GHC.IE */ | |
674 | AHCI_SET(AHCI_GHC, AHCI_GHC_IE); | |
675 | reg = AHCI_RREG(AHCI_GHC); | |
676 | ASSERT_BIT_SET(reg, AHCI_GHC_IE); | |
677 | ||
678 | /* TODO: The device should now be idling and waiting for commands. | |
679 | * In the future, a small test-case to inspect the Register D2H FIS | |
680 | * and clear the initial interrupts might be good. */ | |
681 | } | |
682 | ||
8840a843 JS |
683 | /*** Specification Adherence Tests ***/ |
684 | ||
685 | /** | |
686 | * Implementation for test_pci_spec. Ensures PCI configuration space is sane. | |
687 | */ | |
688 | static void ahci_test_pci_spec(QPCIDevice *ahci) | |
689 | { | |
690 | uint8_t datab; | |
691 | uint16_t data; | |
692 | uint32_t datal; | |
693 | ||
694 | /* Most of these bits should start cleared until we turn them on. */ | |
695 | data = qpci_config_readw(ahci, PCI_COMMAND); | |
696 | ASSERT_BIT_CLEAR(data, PCI_COMMAND_MEMORY); | |
697 | ASSERT_BIT_CLEAR(data, PCI_COMMAND_MASTER); | |
698 | ASSERT_BIT_CLEAR(data, PCI_COMMAND_SPECIAL); /* Reserved */ | |
699 | ASSERT_BIT_CLEAR(data, PCI_COMMAND_VGA_PALETTE); /* Reserved */ | |
700 | ASSERT_BIT_CLEAR(data, PCI_COMMAND_PARITY); | |
701 | ASSERT_BIT_CLEAR(data, PCI_COMMAND_WAIT); /* Reserved */ | |
702 | ASSERT_BIT_CLEAR(data, PCI_COMMAND_SERR); | |
703 | ASSERT_BIT_CLEAR(data, PCI_COMMAND_FAST_BACK); | |
704 | ASSERT_BIT_CLEAR(data, PCI_COMMAND_INTX_DISABLE); | |
705 | ASSERT_BIT_CLEAR(data, 0xF800); /* Reserved */ | |
706 | ||
707 | data = qpci_config_readw(ahci, PCI_STATUS); | |
708 | ASSERT_BIT_CLEAR(data, 0x01 | 0x02 | 0x04); /* Reserved */ | |
709 | ASSERT_BIT_CLEAR(data, PCI_STATUS_INTERRUPT); | |
710 | ASSERT_BIT_SET(data, PCI_STATUS_CAP_LIST); /* must be set */ | |
711 | ASSERT_BIT_CLEAR(data, PCI_STATUS_UDF); /* Reserved */ | |
712 | ASSERT_BIT_CLEAR(data, PCI_STATUS_PARITY); | |
713 | ASSERT_BIT_CLEAR(data, PCI_STATUS_SIG_TARGET_ABORT); | |
714 | ASSERT_BIT_CLEAR(data, PCI_STATUS_REC_TARGET_ABORT); | |
715 | ASSERT_BIT_CLEAR(data, PCI_STATUS_REC_MASTER_ABORT); | |
716 | ASSERT_BIT_CLEAR(data, PCI_STATUS_SIG_SYSTEM_ERROR); | |
717 | ASSERT_BIT_CLEAR(data, PCI_STATUS_DETECTED_PARITY); | |
718 | ||
719 | /* RID occupies the low byte, CCs occupy the high three. */ | |
720 | datal = qpci_config_readl(ahci, PCI_CLASS_REVISION); | |
721 | if (ahci_pedantic) { | |
722 | /* AHCI 1.3 specifies that at-boot, the RID should reset to 0x00, | |
723 | * Though in practice this is likely seldom true. */ | |
724 | ASSERT_BIT_CLEAR(datal, 0xFF); | |
725 | } | |
726 | ||
727 | /* BCC *must* equal 0x01. */ | |
728 | g_assert_cmphex(PCI_BCC(datal), ==, 0x01); | |
729 | if (PCI_SCC(datal) == 0x01) { | |
730 | /* IDE */ | |
731 | ASSERT_BIT_SET(0x80000000, datal); | |
732 | ASSERT_BIT_CLEAR(0x60000000, datal); | |
733 | } else if (PCI_SCC(datal) == 0x04) { | |
734 | /* RAID */ | |
735 | g_assert_cmphex(PCI_PI(datal), ==, 0); | |
736 | } else if (PCI_SCC(datal) == 0x06) { | |
737 | /* AHCI */ | |
738 | g_assert_cmphex(PCI_PI(datal), ==, 0x01); | |
739 | } else { | |
740 | g_assert_not_reached(); | |
741 | } | |
742 | ||
743 | datab = qpci_config_readb(ahci, PCI_CACHE_LINE_SIZE); | |
744 | g_assert_cmphex(datab, ==, 0); | |
745 | ||
746 | datab = qpci_config_readb(ahci, PCI_LATENCY_TIMER); | |
747 | g_assert_cmphex(datab, ==, 0); | |
748 | ||
749 | /* Only the bottom 7 bits must be off. */ | |
750 | datab = qpci_config_readb(ahci, PCI_HEADER_TYPE); | |
751 | ASSERT_BIT_CLEAR(datab, 0x7F); | |
752 | ||
753 | /* BIST is optional, but the low 7 bits must always start off regardless. */ | |
754 | datab = qpci_config_readb(ahci, PCI_BIST); | |
755 | ASSERT_BIT_CLEAR(datab, 0x7F); | |
756 | ||
757 | /* BARS 0-4 do not have a boot spec, but ABAR/BAR5 must be clean. */ | |
758 | datal = qpci_config_readl(ahci, PCI_BASE_ADDRESS_5); | |
759 | g_assert_cmphex(datal, ==, 0); | |
760 | ||
761 | qpci_config_writel(ahci, PCI_BASE_ADDRESS_5, 0xFFFFFFFF); | |
762 | datal = qpci_config_readl(ahci, PCI_BASE_ADDRESS_5); | |
763 | /* ABAR must be 32-bit, memory mapped, non-prefetchable and | |
764 | * must be >= 512 bytes. To that end, bits 0-8 must be off. */ | |
765 | ASSERT_BIT_CLEAR(datal, 0xFF); | |
766 | ||
767 | /* Capability list MUST be present, */ | |
768 | datal = qpci_config_readl(ahci, PCI_CAPABILITY_LIST); | |
769 | /* But these bits are reserved. */ | |
770 | ASSERT_BIT_CLEAR(datal, ~0xFF); | |
771 | g_assert_cmphex(datal, !=, 0); | |
772 | ||
773 | /* Check specification adherence for capability extenstions. */ | |
774 | data = qpci_config_readw(ahci, datal); | |
775 | ||
776 | switch (ahci_fingerprint) { | |
777 | case AHCI_INTEL_ICH9: | |
778 | /* Intel ICH9 Family Datasheet 14.1.19 p.550 */ | |
779 | g_assert_cmphex((data & 0xFF), ==, PCI_CAP_ID_MSI); | |
780 | break; | |
781 | default: | |
782 | /* AHCI 1.3, Section 2.1.14 -- CAP must point to PMCAP. */ | |
783 | g_assert_cmphex((data & 0xFF), ==, PCI_CAP_ID_PM); | |
784 | } | |
785 | ||
786 | ahci_test_pci_caps(ahci, data, (uint8_t)datal); | |
787 | ||
788 | /* Reserved. */ | |
789 | datal = qpci_config_readl(ahci, PCI_CAPABILITY_LIST + 4); | |
790 | g_assert_cmphex(datal, ==, 0); | |
791 | ||
792 | /* IPIN might vary, but ILINE must be off. */ | |
793 | datab = qpci_config_readb(ahci, PCI_INTERRUPT_LINE); | |
794 | g_assert_cmphex(datab, ==, 0); | |
795 | } | |
796 | ||
797 | /** | |
798 | * Test PCI capabilities for AHCI specification adherence. | |
799 | */ | |
800 | static void ahci_test_pci_caps(QPCIDevice *ahci, uint16_t header, | |
801 | uint8_t offset) | |
802 | { | |
803 | uint8_t cid = header & 0xFF; | |
804 | uint8_t next = header >> 8; | |
805 | ||
806 | g_test_message("CID: %02x; next: %02x", cid, next); | |
807 | ||
808 | switch (cid) { | |
809 | case PCI_CAP_ID_PM: | |
810 | ahci_test_pmcap(ahci, offset); | |
811 | break; | |
812 | case PCI_CAP_ID_MSI: | |
813 | ahci_test_msicap(ahci, offset); | |
814 | break; | |
815 | case PCI_CAP_ID_SATA: | |
816 | ahci_test_satacap(ahci, offset); | |
817 | break; | |
818 | ||
819 | default: | |
820 | g_test_message("Unknown CAP 0x%02x", cid); | |
821 | } | |
822 | ||
823 | if (next) { | |
824 | ahci_test_pci_caps(ahci, qpci_config_readw(ahci, next), next); | |
825 | } | |
826 | } | |
827 | ||
828 | /** | |
829 | * Test SATA PCI capabilitity for AHCI specification adherence. | |
830 | */ | |
831 | static void ahci_test_satacap(QPCIDevice *ahci, uint8_t offset) | |
832 | { | |
833 | uint16_t dataw; | |
834 | uint32_t datal; | |
835 | ||
836 | g_test_message("Verifying SATACAP"); | |
837 | ||
838 | /* Assert that the SATACAP version is 1.0, And reserved bits are empty. */ | |
839 | dataw = qpci_config_readw(ahci, offset + 2); | |
840 | g_assert_cmphex(dataw, ==, 0x10); | |
841 | ||
842 | /* Grab the SATACR1 register. */ | |
843 | datal = qpci_config_readw(ahci, offset + 4); | |
844 | ||
845 | switch (datal & 0x0F) { | |
846 | case 0x04: /* BAR0 */ | |
847 | case 0x05: /* BAR1 */ | |
848 | case 0x06: | |
849 | case 0x07: | |
850 | case 0x08: | |
851 | case 0x09: /* BAR5 */ | |
852 | case 0x0F: /* Immediately following SATACR1 in PCI config space. */ | |
853 | break; | |
854 | default: | |
855 | /* Invalid BARLOC for the Index Data Pair. */ | |
856 | g_assert_not_reached(); | |
857 | } | |
858 | ||
859 | /* Reserved. */ | |
860 | g_assert_cmphex((datal >> 24), ==, 0x00); | |
861 | } | |
862 | ||
863 | /** | |
864 | * Test MSI PCI capability for AHCI specification adherence. | |
865 | */ | |
866 | static void ahci_test_msicap(QPCIDevice *ahci, uint8_t offset) | |
867 | { | |
868 | uint16_t dataw; | |
869 | uint32_t datal; | |
870 | ||
871 | g_test_message("Verifying MSICAP"); | |
872 | ||
873 | dataw = qpci_config_readw(ahci, offset + PCI_MSI_FLAGS); | |
874 | ASSERT_BIT_CLEAR(dataw, PCI_MSI_FLAGS_ENABLE); | |
875 | ASSERT_BIT_CLEAR(dataw, PCI_MSI_FLAGS_QSIZE); | |
876 | ASSERT_BIT_CLEAR(dataw, PCI_MSI_FLAGS_RESERVED); | |
877 | ||
878 | datal = qpci_config_readl(ahci, offset + PCI_MSI_ADDRESS_LO); | |
879 | g_assert_cmphex(datal, ==, 0); | |
880 | ||
881 | if (dataw & PCI_MSI_FLAGS_64BIT) { | |
882 | g_test_message("MSICAP is 64bit"); | |
883 | datal = qpci_config_readl(ahci, offset + PCI_MSI_ADDRESS_HI); | |
884 | g_assert_cmphex(datal, ==, 0); | |
885 | dataw = qpci_config_readw(ahci, offset + PCI_MSI_DATA_64); | |
886 | g_assert_cmphex(dataw, ==, 0); | |
887 | } else { | |
888 | g_test_message("MSICAP is 32bit"); | |
889 | dataw = qpci_config_readw(ahci, offset + PCI_MSI_DATA_32); | |
890 | g_assert_cmphex(dataw, ==, 0); | |
891 | } | |
892 | } | |
893 | ||
894 | /** | |
895 | * Test Power Management PCI capability for AHCI specification adherence. | |
896 | */ | |
897 | static void ahci_test_pmcap(QPCIDevice *ahci, uint8_t offset) | |
898 | { | |
899 | uint16_t dataw; | |
900 | ||
901 | g_test_message("Verifying PMCAP"); | |
902 | ||
903 | dataw = qpci_config_readw(ahci, offset + PCI_PM_PMC); | |
904 | ASSERT_BIT_CLEAR(dataw, PCI_PM_CAP_PME_CLOCK); | |
905 | ASSERT_BIT_CLEAR(dataw, PCI_PM_CAP_RESERVED); | |
906 | ASSERT_BIT_CLEAR(dataw, PCI_PM_CAP_D1); | |
907 | ASSERT_BIT_CLEAR(dataw, PCI_PM_CAP_D2); | |
908 | ||
909 | dataw = qpci_config_readw(ahci, offset + PCI_PM_CTRL); | |
910 | ASSERT_BIT_CLEAR(dataw, PCI_PM_CTRL_STATE_MASK); | |
911 | ASSERT_BIT_CLEAR(dataw, PCI_PM_CTRL_RESERVED); | |
912 | ASSERT_BIT_CLEAR(dataw, PCI_PM_CTRL_DATA_SEL_MASK); | |
913 | ASSERT_BIT_CLEAR(dataw, PCI_PM_CTRL_DATA_SCALE_MASK); | |
914 | } | |
915 | ||
c2f3029f JS |
916 | static void ahci_test_hba_spec(QPCIDevice *ahci, void *hba_base) |
917 | { | |
918 | HBACap hcap; | |
919 | unsigned i; | |
920 | uint32_t cap, cap2, reg; | |
921 | uint32_t ports; | |
922 | uint8_t nports_impl; | |
923 | uint8_t maxports; | |
924 | ||
925 | g_assert(ahci != 0); | |
926 | g_assert(hba_base != 0); | |
927 | ||
928 | /* | |
929 | * Note that the AHCI spec does expect the BIOS to set up a few things: | |
930 | * CAP.SSS - Support for staggered spin-up (t/f) | |
931 | * CAP.SMPS - Support for mechanical presence switches (t/f) | |
932 | * PI - Ports Implemented (1-32) | |
933 | * PxCMD.HPCP - Hot Plug Capable Port | |
934 | * PxCMD.MPSP - Mechanical Presence Switch Present | |
935 | * PxCMD.CPD - Cold Presence Detection support | |
936 | * | |
937 | * Additional items are touched if CAP.SSS is on, see AHCI 10.1.1 p.97: | |
938 | * Foreach Port Implemented: | |
939 | * -PxCMD.ST, PxCMD.CR, PxCMD.FRE, PxCMD.FR, PxSCTL.DET are 0 | |
940 | * -PxCLB/U and PxFB/U are set to valid regions in memory | |
941 | * -PxSUD is set to 1. | |
942 | * -PxSSTS.DET is polled for presence; if detected, we continue: | |
943 | * -PxSERR is cleared with 1's. | |
944 | * -If PxTFD.STS.BSY, PxTFD.STS.DRQ, and PxTFD.STS.ERR are all zero, | |
945 | * the device is ready. | |
946 | */ | |
947 | ||
948 | /* 1 CAP - Capabilities Register */ | |
949 | cap = AHCI_RREG(AHCI_CAP); | |
950 | ASSERT_BIT_CLEAR(cap, AHCI_CAP_RESERVED); | |
951 | ||
952 | /* 2 GHC - Global Host Control */ | |
953 | reg = AHCI_RREG(AHCI_GHC); | |
954 | ASSERT_BIT_CLEAR(reg, AHCI_GHC_HR); | |
955 | ASSERT_BIT_CLEAR(reg, AHCI_GHC_IE); | |
956 | ASSERT_BIT_CLEAR(reg, AHCI_GHC_MRSM); | |
957 | if (BITSET(cap, AHCI_CAP_SAM)) { | |
958 | g_test_message("Supports AHCI-Only Mode: GHC_AE is Read-Only."); | |
959 | ASSERT_BIT_SET(reg, AHCI_GHC_AE); | |
960 | } else { | |
961 | g_test_message("Supports AHCI/Legacy mix."); | |
962 | ASSERT_BIT_CLEAR(reg, AHCI_GHC_AE); | |
963 | } | |
964 | ||
965 | /* 3 IS - Interrupt Status */ | |
966 | reg = AHCI_RREG(AHCI_IS); | |
967 | g_assert_cmphex(reg, ==, 0); | |
968 | ||
969 | /* 4 PI - Ports Implemented */ | |
970 | ports = AHCI_RREG(AHCI_PI); | |
971 | /* Ports Implemented must be non-zero. */ | |
972 | g_assert_cmphex(ports, !=, 0); | |
973 | /* Ports Implemented must be <= Number of Ports. */ | |
974 | nports_impl = ctpopl(ports); | |
975 | g_assert_cmpuint(((AHCI_CAP_NP & cap) + 1), >=, nports_impl); | |
976 | ||
977 | g_assert_cmphex(barsize, >, 0); | |
978 | /* Ports must be within the proper range. Given a mapping of SIZE, | |
979 | * 256 bytes are used for global HBA control, and the rest is used | |
980 | * for ports data, at 0x80 bytes each. */ | |
981 | maxports = (barsize - HBA_DATA_REGION_SIZE) / HBA_PORT_DATA_SIZE; | |
982 | /* e.g, 30 ports for 4K of memory. (4096 - 256) / 128 = 30 */ | |
983 | g_assert_cmphex((reg >> maxports), ==, 0); | |
984 | ||
985 | /* 5 AHCI Version */ | |
986 | reg = AHCI_RREG(AHCI_VS); | |
987 | switch (reg) { | |
988 | case AHCI_VERSION_0_95: | |
989 | case AHCI_VERSION_1_0: | |
990 | case AHCI_VERSION_1_1: | |
991 | case AHCI_VERSION_1_2: | |
992 | case AHCI_VERSION_1_3: | |
993 | break; | |
994 | default: | |
995 | g_assert_not_reached(); | |
996 | } | |
997 | ||
998 | /* 6 Command Completion Coalescing Control: depends on CAP.CCCS. */ | |
999 | reg = AHCI_RREG(AHCI_CCCCTL); | |
1000 | if (BITSET(cap, AHCI_CAP_CCCS)) { | |
1001 | ASSERT_BIT_CLEAR(reg, AHCI_CCCCTL_EN); | |
1002 | ASSERT_BIT_CLEAR(reg, AHCI_CCCCTL_RESERVED); | |
1003 | ASSERT_BIT_SET(reg, AHCI_CCCCTL_CC); | |
1004 | ASSERT_BIT_SET(reg, AHCI_CCCCTL_TV); | |
1005 | } else { | |
1006 | g_assert_cmphex(reg, ==, 0); | |
1007 | } | |
1008 | ||
1009 | /* 7 CCC_PORTS */ | |
1010 | reg = AHCI_RREG(AHCI_CCCPORTS); | |
1011 | /* Must be zeroes initially regardless of CAP.CCCS */ | |
1012 | g_assert_cmphex(reg, ==, 0); | |
1013 | ||
1014 | /* 8 EM_LOC */ | |
1015 | reg = AHCI_RREG(AHCI_EMLOC); | |
1016 | if (BITCLR(cap, AHCI_CAP_EMS)) { | |
1017 | g_assert_cmphex(reg, ==, 0); | |
1018 | } | |
1019 | ||
1020 | /* 9 EM_CTL */ | |
1021 | reg = AHCI_RREG(AHCI_EMCTL); | |
1022 | if (BITSET(cap, AHCI_CAP_EMS)) { | |
1023 | ASSERT_BIT_CLEAR(reg, AHCI_EMCTL_STSMR); | |
1024 | ASSERT_BIT_CLEAR(reg, AHCI_EMCTL_CTLTM); | |
1025 | ASSERT_BIT_CLEAR(reg, AHCI_EMCTL_CTLRST); | |
1026 | ASSERT_BIT_CLEAR(reg, AHCI_EMCTL_RESERVED); | |
1027 | } else { | |
1028 | g_assert_cmphex(reg, ==, 0); | |
1029 | } | |
1030 | ||
1031 | /* 10 CAP2 -- Capabilities Extended */ | |
1032 | cap2 = AHCI_RREG(AHCI_CAP2); | |
1033 | ASSERT_BIT_CLEAR(cap2, AHCI_CAP2_RESERVED); | |
1034 | ||
1035 | /* 11 BOHC -- Bios/OS Handoff Control */ | |
1036 | reg = AHCI_RREG(AHCI_BOHC); | |
1037 | g_assert_cmphex(reg, ==, 0); | |
1038 | ||
1039 | /* 12 -- 23: Reserved */ | |
1040 | g_test_message("Verifying HBA reserved area is empty."); | |
1041 | for (i = AHCI_RESERVED; i < AHCI_NVMHCI; ++i) { | |
1042 | reg = AHCI_RREG(i); | |
1043 | g_assert_cmphex(reg, ==, 0); | |
1044 | } | |
1045 | ||
1046 | /* 24 -- 39: NVMHCI */ | |
1047 | if (BITCLR(cap2, AHCI_CAP2_NVMP)) { | |
1048 | g_test_message("Verifying HBA/NVMHCI area is empty."); | |
1049 | for (i = AHCI_NVMHCI; i < AHCI_VENDOR; ++i) { | |
1050 | reg = AHCI_RREG(i); | |
1051 | g_assert_cmphex(reg, ==, 0); | |
1052 | } | |
1053 | } | |
1054 | ||
1055 | /* 40 -- 63: Vendor */ | |
1056 | g_test_message("Verifying HBA/Vendor area is empty."); | |
1057 | for (i = AHCI_VENDOR; i < AHCI_PORTS; ++i) { | |
1058 | reg = AHCI_RREG(i); | |
1059 | g_assert_cmphex(reg, ==, 0); | |
1060 | } | |
1061 | ||
1062 | /* 64 -- XX: Port Space */ | |
1063 | hcap.cap = cap; | |
1064 | hcap.cap2 = cap2; | |
1065 | for (i = 0; ports || (i < maxports); ports >>= 1, ++i) { | |
1066 | if (BITSET(ports, 0x1)) { | |
1067 | g_test_message("Testing port %u for spec", i); | |
1068 | ahci_test_port_spec(ahci, hba_base, &hcap, i); | |
1069 | } else { | |
1070 | uint16_t j; | |
1071 | uint16_t low = AHCI_PORTS + (32 * i); | |
1072 | uint16_t high = AHCI_PORTS + (32 * (i + 1)); | |
1073 | g_test_message("Asserting unimplemented port %u " | |
1074 | "(reg [%u-%u]) is empty.", | |
1075 | i, low, high - 1); | |
1076 | for (j = low; j < high; ++j) { | |
1077 | reg = AHCI_RREG(j); | |
1078 | g_assert_cmphex(reg, ==, 0); | |
1079 | } | |
1080 | } | |
1081 | } | |
1082 | } | |
1083 | ||
1084 | /** | |
1085 | * Test the memory space for one port for specification adherence. | |
1086 | */ | |
1087 | static void ahci_test_port_spec(QPCIDevice *ahci, void *hba_base, | |
1088 | HBACap *hcap, uint8_t port) | |
1089 | { | |
1090 | uint32_t reg; | |
1091 | unsigned i; | |
1092 | ||
1093 | /* (0) CLB */ | |
1094 | reg = PX_RREG(port, AHCI_PX_CLB); | |
1095 | ASSERT_BIT_CLEAR(reg, AHCI_PX_CLB_RESERVED); | |
1096 | ||
1097 | /* (1) CLBU */ | |
1098 | if (BITCLR(hcap->cap, AHCI_CAP_S64A)) { | |
1099 | reg = PX_RREG(port, AHCI_PX_CLBU); | |
1100 | g_assert_cmphex(reg, ==, 0); | |
1101 | } | |
1102 | ||
1103 | /* (2) FB */ | |
1104 | reg = PX_RREG(port, AHCI_PX_FB); | |
1105 | ASSERT_BIT_CLEAR(reg, AHCI_PX_FB_RESERVED); | |
1106 | ||
1107 | /* (3) FBU */ | |
1108 | if (BITCLR(hcap->cap, AHCI_CAP_S64A)) { | |
1109 | reg = PX_RREG(port, AHCI_PX_FBU); | |
1110 | g_assert_cmphex(reg, ==, 0); | |
1111 | } | |
1112 | ||
1113 | /* (4) IS */ | |
1114 | reg = PX_RREG(port, AHCI_PX_IS); | |
1115 | g_assert_cmphex(reg, ==, 0); | |
1116 | ||
1117 | /* (5) IE */ | |
1118 | reg = PX_RREG(port, AHCI_PX_IE); | |
1119 | g_assert_cmphex(reg, ==, 0); | |
1120 | ||
1121 | /* (6) CMD */ | |
1122 | reg = PX_RREG(port, AHCI_PX_CMD); | |
1123 | ASSERT_BIT_CLEAR(reg, AHCI_PX_CMD_FRE); | |
1124 | ASSERT_BIT_CLEAR(reg, AHCI_PX_CMD_RESERVED); | |
1125 | ASSERT_BIT_CLEAR(reg, AHCI_PX_CMD_CCS); | |
1126 | ASSERT_BIT_CLEAR(reg, AHCI_PX_CMD_FR); | |
1127 | ASSERT_BIT_CLEAR(reg, AHCI_PX_CMD_CR); | |
1128 | ASSERT_BIT_CLEAR(reg, AHCI_PX_CMD_PMA); /* And RW only if CAP.SPM */ | |
1129 | ASSERT_BIT_CLEAR(reg, AHCI_PX_CMD_APSTE); /* RW only if CAP2.APST */ | |
1130 | ASSERT_BIT_CLEAR(reg, AHCI_PX_CMD_ATAPI); | |
1131 | ASSERT_BIT_CLEAR(reg, AHCI_PX_CMD_DLAE); | |
1132 | ASSERT_BIT_CLEAR(reg, AHCI_PX_CMD_ALPE); /* RW only if CAP.SALP */ | |
1133 | ASSERT_BIT_CLEAR(reg, AHCI_PX_CMD_ASP); /* RW only if CAP.SALP */ | |
1134 | ASSERT_BIT_CLEAR(reg, AHCI_PX_CMD_ICC); | |
1135 | /* If CPDetect support does not exist, CPState must be off. */ | |
1136 | if (BITCLR(reg, AHCI_PX_CMD_CPD)) { | |
1137 | ASSERT_BIT_CLEAR(reg, AHCI_PX_CMD_CPS); | |
1138 | } | |
1139 | /* If MPSPresence is not set, MPSState must be off. */ | |
1140 | if (BITCLR(reg, AHCI_PX_CMD_MPSP)) { | |
1141 | ASSERT_BIT_CLEAR(reg, AHCI_PX_CMD_MPSS); | |
1142 | } | |
1143 | /* If we do not support MPS, MPSS and MPSP must be off. */ | |
1144 | if (BITCLR(hcap->cap, AHCI_CAP_SMPS)) { | |
1145 | ASSERT_BIT_CLEAR(reg, AHCI_PX_CMD_MPSS); | |
1146 | ASSERT_BIT_CLEAR(reg, AHCI_PX_CMD_MPSP); | |
1147 | } | |
1148 | /* If, via CPD or MPSP we detect a drive, HPCP must be on. */ | |
1149 | if (BITANY(reg, AHCI_PX_CMD_CPD || AHCI_PX_CMD_MPSP)) { | |
1150 | ASSERT_BIT_SET(reg, AHCI_PX_CMD_HPCP); | |
1151 | } | |
1152 | /* HPCP and ESP cannot both be active. */ | |
1153 | g_assert(!BITSET(reg, AHCI_PX_CMD_HPCP | AHCI_PX_CMD_ESP)); | |
1154 | /* If CAP.FBSS is not set, FBSCP must not be set. */ | |
1155 | if (BITCLR(hcap->cap, AHCI_CAP_FBSS)) { | |
1156 | ASSERT_BIT_CLEAR(reg, AHCI_PX_CMD_FBSCP); | |
1157 | } | |
1158 | ||
1159 | /* (7) RESERVED */ | |
1160 | reg = PX_RREG(port, AHCI_PX_RES1); | |
1161 | g_assert_cmphex(reg, ==, 0); | |
1162 | ||
1163 | /* (8) TFD */ | |
1164 | reg = PX_RREG(port, AHCI_PX_TFD); | |
1165 | /* At boot, prior to an FIS being received, the TFD register should be 0x7F, | |
1166 | * which breaks down as follows, as seen in AHCI 1.3 sec 3.3.8, p. 27. */ | |
1167 | ASSERT_BIT_SET(reg, AHCI_PX_TFD_STS_ERR); | |
1168 | ASSERT_BIT_SET(reg, AHCI_PX_TFD_STS_CS1); | |
1169 | ASSERT_BIT_SET(reg, AHCI_PX_TFD_STS_DRQ); | |
1170 | ASSERT_BIT_SET(reg, AHCI_PX_TFD_STS_CS2); | |
1171 | ASSERT_BIT_CLEAR(reg, AHCI_PX_TFD_STS_BSY); | |
1172 | ASSERT_BIT_CLEAR(reg, AHCI_PX_TFD_ERR); | |
1173 | ASSERT_BIT_CLEAR(reg, AHCI_PX_TFD_RESERVED); | |
1174 | ||
1175 | /* (9) SIG */ | |
1176 | /* Though AHCI specifies the boot value should be 0xFFFFFFFF, | |
1177 | * Even when GHC.ST is zero, the AHCI HBA may receive the initial | |
1178 | * D2H register FIS and update the signature asynchronously, | |
1179 | * so we cannot expect a value here. AHCI 1.3, sec 3.3.9, pp 27-28 */ | |
1180 | ||
1181 | /* (10) SSTS / SCR0: SStatus */ | |
1182 | reg = PX_RREG(port, AHCI_PX_SSTS); | |
1183 | ASSERT_BIT_CLEAR(reg, AHCI_PX_SSTS_RESERVED); | |
1184 | /* Even though the register should be 0 at boot, it is asynchronous and | |
1185 | * prone to change, so we cannot test any well known value. */ | |
1186 | ||
1187 | /* (11) SCTL / SCR2: SControl */ | |
1188 | reg = PX_RREG(port, AHCI_PX_SCTL); | |
1189 | g_assert_cmphex(reg, ==, 0); | |
1190 | ||
1191 | /* (12) SERR / SCR1: SError */ | |
1192 | reg = PX_RREG(port, AHCI_PX_SERR); | |
1193 | g_assert_cmphex(reg, ==, 0); | |
1194 | ||
1195 | /* (13) SACT / SCR3: SActive */ | |
1196 | reg = PX_RREG(port, AHCI_PX_SACT); | |
1197 | g_assert_cmphex(reg, ==, 0); | |
1198 | ||
1199 | /* (14) CI */ | |
1200 | reg = PX_RREG(port, AHCI_PX_CI); | |
1201 | g_assert_cmphex(reg, ==, 0); | |
1202 | ||
1203 | /* (15) SNTF */ | |
1204 | reg = PX_RREG(port, AHCI_PX_SNTF); | |
1205 | g_assert_cmphex(reg, ==, 0); | |
1206 | ||
1207 | /* (16) FBS */ | |
1208 | reg = PX_RREG(port, AHCI_PX_FBS); | |
1209 | ASSERT_BIT_CLEAR(reg, AHCI_PX_FBS_EN); | |
1210 | ASSERT_BIT_CLEAR(reg, AHCI_PX_FBS_DEC); | |
1211 | ASSERT_BIT_CLEAR(reg, AHCI_PX_FBS_SDE); | |
1212 | ASSERT_BIT_CLEAR(reg, AHCI_PX_FBS_DEV); | |
1213 | ASSERT_BIT_CLEAR(reg, AHCI_PX_FBS_DWE); | |
1214 | ASSERT_BIT_CLEAR(reg, AHCI_PX_FBS_RESERVED); | |
1215 | if (BITSET(hcap->cap, AHCI_CAP_FBSS)) { | |
1216 | /* if Port-Multiplier FIS-based switching avail, ADO must >= 2 */ | |
1217 | g_assert((reg & AHCI_PX_FBS_ADO) >> ctzl(AHCI_PX_FBS_ADO) >= 2); | |
1218 | } | |
1219 | ||
1220 | /* [17 -- 27] RESERVED */ | |
1221 | for (i = AHCI_PX_RES2; i < AHCI_PX_VS; ++i) { | |
1222 | reg = PX_RREG(port, i); | |
1223 | g_assert_cmphex(reg, ==, 0); | |
1224 | } | |
1225 | ||
1226 | /* [28 -- 31] Vendor-Specific */ | |
1227 | for (i = AHCI_PX_VS; i < 32; ++i) { | |
1228 | reg = PX_RREG(port, i); | |
1229 | if (reg) { | |
1230 | g_test_message("INFO: Vendor register %u non-empty", i); | |
1231 | } | |
1232 | } | |
1233 | } | |
1234 | ||
0fa781e3 JS |
1235 | /** |
1236 | * Utilizing an initialized AHCI HBA, issue an IDENTIFY command to the first | |
1237 | * device we see, then read and check the response. | |
1238 | */ | |
1239 | static void ahci_test_identify(QPCIDevice *ahci, void *hba_base) | |
1240 | { | |
1241 | RegD2HFIS *d2h = g_malloc0(0x20); | |
1242 | RegD2HFIS *pio = g_malloc0(0x20); | |
1243 | RegH2DFIS fis; | |
1244 | AHCICommand cmd; | |
1245 | PRD prd; | |
1246 | uint32_t ports, reg, clb, table, fb, data_ptr; | |
1247 | uint16_t buff[256]; | |
1248 | unsigned i; | |
1249 | int rc; | |
1250 | ||
1251 | g_assert(ahci != NULL); | |
1252 | g_assert(hba_base != NULL); | |
1253 | ||
1254 | /* We need to: | |
1255 | * (1) Create a Command Table Buffer and update the Command List Slot #0 | |
1256 | * to point to this buffer. | |
1257 | * (2) Construct an FIS host-to-device command structure, and write it to | |
1258 | * the top of the command table buffer. | |
1259 | * (3) Create a data buffer for the IDENTIFY response to be sent to | |
1260 | * (4) Create a Physical Region Descriptor that points to the data buffer, | |
1261 | * and write it to the bottom (offset 0x80) of the command table. | |
1262 | * (5) Now, PxCLB points to the command list, command 0 points to | |
1263 | * our table, and our table contains an FIS instruction and a | |
1264 | * PRD that points to our rx buffer. | |
1265 | * (6) We inform the HBA via PxCI that there is a command ready in slot #0. | |
1266 | */ | |
1267 | ||
1268 | /* Pick the first implemented and running port */ | |
1269 | ports = AHCI_RREG(AHCI_PI); | |
1270 | for (i = 0; i < 32; ports >>= 1, ++i) { | |
1271 | if (ports == 0) { | |
1272 | i = 32; | |
1273 | } | |
1274 | ||
1275 | if (!(ports & 0x01)) { | |
1276 | continue; | |
1277 | } | |
1278 | ||
1279 | reg = PX_RREG(i, AHCI_PX_CMD); | |
1280 | if (BITSET(reg, AHCI_PX_CMD_ST)) { | |
1281 | break; | |
1282 | } | |
1283 | } | |
1284 | g_assert_cmphex(i, <, 32); | |
1285 | g_test_message("Selected port %u for test", i); | |
1286 | ||
1287 | /* Clear out this port's interrupts (ignore the init register d2h fis) */ | |
1288 | reg = PX_RREG(i, AHCI_PX_IS); | |
1289 | PX_WREG(i, AHCI_PX_IS, reg); | |
1290 | g_assert_cmphex(PX_RREG(i, AHCI_PX_IS), ==, 0); | |
1291 | ||
1292 | /* Wipe the FIS-Recieve Buffer */ | |
1293 | fb = PX_RREG(i, AHCI_PX_FB); | |
1294 | g_assert_cmphex(fb, !=, 0); | |
1295 | qmemset(fb, 0x00, 0x100); | |
1296 | ||
1297 | /* Create a Command Table buffer. 0x80 is the smallest with a PRDTL of 0. */ | |
1298 | /* We need at least one PRD, so round up to the nearest 0x80 multiple. */ | |
1299 | table = guest_alloc(guest_malloc, CMD_TBL_SIZ(1)); | |
1300 | g_assert(table); | |
1301 | ASSERT_BIT_CLEAR(table, 0x7F); | |
1302 | ||
1303 | /* Create a data buffer ... where we will dump the IDENTIFY data to. */ | |
1304 | data_ptr = guest_alloc(guest_malloc, 512); | |
1305 | g_assert(data_ptr); | |
1306 | ||
1307 | /* Grab the Command List Buffer pointer */ | |
1308 | clb = PX_RREG(i, AHCI_PX_CLB); | |
1309 | g_assert(clb); | |
1310 | ||
1311 | /* Copy the existing Command #0 structure from the CLB into local memory, | |
1312 | * and build a new command #0. */ | |
1313 | memread(clb, &cmd, sizeof(cmd)); | |
1314 | cmd.b1 = 5; /* reg_h2d_fis is 5 double-words long */ | |
1315 | cmd.b2 = 0x04; /* clear PxTFD.STS.BSY when done */ | |
1316 | cmd.prdtl = cpu_to_le16(1); /* One PRD table entry. */ | |
1317 | cmd.prdbc = 0; | |
1318 | cmd.ctba = cpu_to_le32(table); | |
1319 | cmd.ctbau = 0; | |
1320 | ||
1321 | /* Construct our PRD, noting that DBC is 0-indexed. */ | |
1322 | prd.dba = cpu_to_le32(data_ptr); | |
1323 | prd.dbau = 0; | |
1324 | prd.res = 0; | |
1325 | /* 511+1 bytes, request DPS interrupt */ | |
1326 | prd.dbc = cpu_to_le32(511 | 0x80000000); | |
1327 | ||
1328 | /* Construct our Command FIS, Based on http://wiki.osdev.org/AHCI */ | |
1329 | memset(&fis, 0x00, sizeof(fis)); | |
1330 | fis.fis_type = 0x27; /* Register Host-to-Device FIS */ | |
1331 | fis.command = 0xEC; /* IDENTIFY */ | |
1332 | fis.device = 0; | |
1333 | fis.flags = 0x80; /* Indicate this is a command FIS */ | |
1334 | ||
1335 | /* We've committed nothing yet, no interrupts should be posted yet. */ | |
1336 | g_assert_cmphex(PX_RREG(i, AHCI_PX_IS), ==, 0); | |
1337 | ||
1338 | /* Commit the Command FIS to the Command Table */ | |
1339 | memwrite(table, &fis, sizeof(fis)); | |
1340 | ||
1341 | /* Commit the PRD entry to the Command Table */ | |
1342 | memwrite(table + 0x80, &prd, sizeof(prd)); | |
1343 | ||
1344 | /* Commit Command #0, pointing to the Table, to the Command List Buffer. */ | |
1345 | memwrite(clb, &cmd, sizeof(cmd)); | |
1346 | ||
1347 | /* Everything is in place, but we haven't given the go-ahead yet. */ | |
1348 | g_assert_cmphex(PX_RREG(i, AHCI_PX_IS), ==, 0); | |
1349 | ||
1350 | /* Issue Command #0 via PxCI */ | |
1351 | PX_WREG(i, AHCI_PX_CI, (1 << 0)); | |
1352 | while (BITSET(PX_RREG(i, AHCI_PX_TFD), AHCI_PX_TFD_STS_BSY)) { | |
1353 | usleep(50); | |
1354 | } | |
1355 | ||
1356 | /* Check for expected interrupts */ | |
1357 | reg = PX_RREG(i, AHCI_PX_IS); | |
1358 | ASSERT_BIT_SET(reg, AHCI_PX_IS_DHRS); | |
1359 | ASSERT_BIT_SET(reg, AHCI_PX_IS_PSS); | |
1360 | /* BUG: we expect AHCI_PX_IS_DPS to be set. */ | |
1361 | ASSERT_BIT_CLEAR(reg, AHCI_PX_IS_DPS); | |
1362 | ||
1363 | /* Clear expected interrupts and assert all interrupts now cleared. */ | |
1364 | PX_WREG(i, AHCI_PX_IS, AHCI_PX_IS_DHRS | AHCI_PX_IS_PSS | AHCI_PX_IS_DPS); | |
1365 | g_assert_cmphex(PX_RREG(i, AHCI_PX_IS), ==, 0); | |
1366 | ||
1367 | /* Check for errors. */ | |
1368 | reg = PX_RREG(i, AHCI_PX_SERR); | |
1369 | g_assert_cmphex(reg, ==, 0); | |
1370 | reg = PX_RREG(i, AHCI_PX_TFD); | |
1371 | ASSERT_BIT_CLEAR(reg, AHCI_PX_TFD_STS_ERR); | |
1372 | ASSERT_BIT_CLEAR(reg, AHCI_PX_TFD_ERR); | |
1373 | ||
1374 | /* Investigate CMD #0, assert that we read 512 bytes */ | |
1375 | memread(clb, &cmd, sizeof(cmd)); | |
1376 | g_assert_cmphex(512, ==, le32_to_cpu(cmd.prdbc)); | |
1377 | ||
1378 | /* Investigate FIS responses */ | |
1379 | memread(fb + 0x20, pio, 0x20); | |
1380 | memread(fb + 0x40, d2h, 0x20); | |
1381 | g_assert_cmphex(pio->fis_type, ==, 0x5f); | |
1382 | g_assert_cmphex(d2h->fis_type, ==, 0x34); | |
1383 | g_assert_cmphex(pio->flags, ==, d2h->flags); | |
1384 | g_assert_cmphex(pio->status, ==, d2h->status); | |
1385 | g_assert_cmphex(pio->error, ==, d2h->error); | |
1386 | ||
1387 | reg = PX_RREG(i, AHCI_PX_TFD); | |
1388 | g_assert_cmphex((reg & AHCI_PX_TFD_ERR), ==, pio->error); | |
1389 | g_assert_cmphex((reg & AHCI_PX_TFD_STS), ==, pio->status); | |
1390 | /* The PIO Setup FIS contains a "bytes read" field, which is a | |
1391 | * 16-bit value. The Physical Region Descriptor Byte Count is | |
1392 | * 32-bit, but for small transfers using one PRD, it should match. */ | |
1393 | g_assert_cmphex(le16_to_cpu(pio->res4), ==, le32_to_cpu(cmd.prdbc)); | |
1394 | ||
1395 | /* Last, but not least: Investigate the IDENTIFY response data. */ | |
1396 | memread(data_ptr, &buff, 512); | |
1397 | ||
1398 | /* Check serial number/version in the buffer */ | |
1399 | /* NB: IDENTIFY strings are packed in 16bit little endian chunks. | |
1400 | * Since we copy byte-for-byte in ahci-test, on both LE and BE, we need to | |
1401 | * unchunk this data. By contrast, ide-test copies 2 bytes at a time, and | |
1402 | * as a consequence, only needs to unchunk the data on LE machines. */ | |
1403 | string_bswap16(&buff[10], 20); | |
1404 | rc = memcmp(&buff[10], "testdisk ", 20); | |
1405 | g_assert_cmphex(rc, ==, 0); | |
1406 | ||
1407 | string_bswap16(&buff[23], 8); | |
1408 | rc = memcmp(&buff[23], "version ", 8); | |
1409 | g_assert_cmphex(rc, ==, 0); | |
1410 | ||
1411 | g_free(d2h); | |
1412 | g_free(pio); | |
1413 | } | |
1414 | ||
1cd1031d JS |
1415 | /******************************************************************************/ |
1416 | /* Test Interfaces */ | |
1417 | /******************************************************************************/ | |
1418 | ||
1419 | /** | |
1420 | * Basic sanity test to boot a machine, find an AHCI device, and shutdown. | |
1421 | */ | |
1422 | static void test_sanity(void) | |
1423 | { | |
1424 | QPCIDevice *ahci; | |
1425 | ahci = ahci_boot(); | |
1426 | ahci_shutdown(ahci); | |
1427 | } | |
1428 | ||
8840a843 JS |
1429 | /** |
1430 | * Ensure that the PCI configuration space for the AHCI device is in-line with | |
1431 | * the AHCI 1.3 specification for initial values. | |
1432 | */ | |
1433 | static void test_pci_spec(void) | |
1434 | { | |
1435 | QPCIDevice *ahci; | |
1436 | ahci = ahci_boot(); | |
1437 | ahci_test_pci_spec(ahci); | |
1438 | ahci_shutdown(ahci); | |
1439 | } | |
1440 | ||
96d6d3ba JS |
1441 | /** |
1442 | * Engage the PCI AHCI device and sanity check the response. | |
1443 | * Perform additional PCI config space bringup for the HBA. | |
1444 | */ | |
1445 | static void test_pci_enable(void) | |
1446 | { | |
1447 | QPCIDevice *ahci; | |
1448 | void *hba_base; | |
1449 | ahci = ahci_boot(); | |
1450 | ahci_pci_enable(ahci, &hba_base); | |
1451 | ahci_shutdown(ahci); | |
1452 | } | |
1453 | ||
c2f3029f JS |
1454 | /** |
1455 | * Investigate the memory mapped regions of the HBA, | |
1456 | * and test them for AHCI specification adherence. | |
1457 | */ | |
1458 | static void test_hba_spec(void) | |
1459 | { | |
1460 | QPCIDevice *ahci; | |
1461 | void *hba_base; | |
1462 | ||
1463 | ahci = ahci_boot(); | |
1464 | ahci_pci_enable(ahci, &hba_base); | |
1465 | ahci_test_hba_spec(ahci, hba_base); | |
1466 | ahci_shutdown(ahci); | |
1467 | } | |
1468 | ||
dbc180e5 JS |
1469 | /** |
1470 | * Engage the HBA functionality of the AHCI PCI device, | |
1471 | * and bring it into a functional idle state. | |
1472 | */ | |
1473 | static void test_hba_enable(void) | |
1474 | { | |
1475 | QPCIDevice *ahci; | |
1476 | void *hba_base; | |
1477 | ||
1478 | ahci = ahci_boot(); | |
1479 | ahci_pci_enable(ahci, &hba_base); | |
1480 | ahci_hba_enable(ahci, hba_base); | |
1481 | ahci_shutdown(ahci); | |
1482 | } | |
1483 | ||
0fa781e3 JS |
1484 | /** |
1485 | * Bring up the device and issue an IDENTIFY command. | |
1486 | * Inspect the state of the HBA device and the data returned. | |
1487 | */ | |
1488 | static void test_identify(void) | |
1489 | { | |
1490 | QPCIDevice *ahci; | |
1491 | void *hba_base; | |
1492 | ||
1493 | ahci = ahci_boot(); | |
1494 | ahci_pci_enable(ahci, &hba_base); | |
1495 | ahci_hba_enable(ahci, hba_base); | |
1496 | ahci_test_identify(ahci, hba_base); | |
1497 | ahci_shutdown(ahci); | |
1498 | } | |
1499 | ||
1cd1031d JS |
1500 | /******************************************************************************/ |
1501 | ||
1502 | int main(int argc, char **argv) | |
1503 | { | |
1504 | const char *arch; | |
1505 | int fd; | |
1506 | int ret; | |
8840a843 JS |
1507 | int c; |
1508 | ||
1509 | static struct option long_options[] = { | |
1510 | {"pedantic", no_argument, 0, 'p' }, | |
1511 | {0, 0, 0, 0}, | |
1512 | }; | |
1cd1031d JS |
1513 | |
1514 | /* Should be first to utilize g_test functionality, So we can see errors. */ | |
1515 | g_test_init(&argc, &argv, NULL); | |
1516 | ||
8840a843 JS |
1517 | while (1) { |
1518 | c = getopt_long(argc, argv, "", long_options, NULL); | |
1519 | if (c == -1) { | |
1520 | break; | |
1521 | } | |
1522 | switch (c) { | |
1523 | case -1: | |
1524 | break; | |
1525 | case 'p': | |
1526 | ahci_pedantic = 1; | |
1527 | break; | |
1528 | default: | |
1529 | fprintf(stderr, "Unrecognized ahci_test option.\n"); | |
1530 | g_assert_not_reached(); | |
1531 | } | |
1532 | } | |
1533 | ||
1cd1031d JS |
1534 | /* Check architecture */ |
1535 | arch = qtest_get_arch(); | |
1536 | if (strcmp(arch, "i386") && strcmp(arch, "x86_64")) { | |
1537 | g_test_message("Skipping test for non-x86"); | |
1538 | return 0; | |
1539 | } | |
1540 | ||
1541 | /* Create a temporary raw image */ | |
1542 | fd = mkstemp(tmp_path); | |
1543 | g_assert(fd >= 0); | |
1544 | ret = ftruncate(fd, TEST_IMAGE_SIZE); | |
1545 | g_assert(ret == 0); | |
1546 | close(fd); | |
1547 | ||
1548 | /* Run the tests */ | |
1549 | qtest_add_func("/ahci/sanity", test_sanity); | |
8840a843 | 1550 | qtest_add_func("/ahci/pci_spec", test_pci_spec); |
96d6d3ba | 1551 | qtest_add_func("/ahci/pci_enable", test_pci_enable); |
c2f3029f | 1552 | qtest_add_func("/ahci/hba_spec", test_hba_spec); |
dbc180e5 | 1553 | qtest_add_func("/ahci/hba_enable", test_hba_enable); |
0fa781e3 | 1554 | qtest_add_func("/ahci/identify", test_identify); |
1cd1031d JS |
1555 | |
1556 | ret = g_test_run(); | |
1557 | ||
1558 | /* Cleanup */ | |
1559 | unlink(tmp_path); | |
1560 | ||
1561 | return ret; | |
1562 | } |