2 * libqos AHCI functions
4 * Copyright (c) 2014 John Snow <jsnow@redhat.com>
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:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
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
25 #include "qemu/osdep.h"
28 #include "libqos/ahci.h"
29 #include "libqos/pci-pc.h"
31 #include "qemu-common.h"
32 #include "qemu/host-utils.h"
34 #include "hw/pci/pci_ids.h"
35 #include "hw/pci/pci_regs.h"
37 typedef struct AHCICommandProp
{
38 uint8_t cmd
; /* Command Code */
39 bool data
; /* Data transfer command? */
48 uint64_t size
; /* Static transfer size, for commands like IDENTIFY. */
49 uint32_t interrupts
; /* Expected interrupts for this command. */
52 AHCICommandProp ahci_command_properties
[] = {
53 { .cmd
= CMD_READ_PIO
, .data
= true, .pio
= true,
54 .lba28
= true, .read
= true },
55 { .cmd
= CMD_WRITE_PIO
, .data
= true, .pio
= true,
56 .lba28
= true, .write
= true },
57 { .cmd
= CMD_READ_PIO_EXT
, .data
= true, .pio
= true,
58 .lba48
= true, .read
= true },
59 { .cmd
= CMD_WRITE_PIO_EXT
, .data
= true, .pio
= true,
60 .lba48
= true, .write
= true },
61 { .cmd
= CMD_READ_DMA
, .data
= true, .dma
= true,
62 .lba28
= true, .read
= true },
63 { .cmd
= CMD_WRITE_DMA
, .data
= true, .dma
= true,
64 .lba28
= true, .write
= true },
65 { .cmd
= CMD_READ_DMA_EXT
, .data
= true, .dma
= true,
66 .lba48
= true, .read
= true },
67 { .cmd
= CMD_WRITE_DMA_EXT
, .data
= true, .dma
= true,
68 .lba48
= true, .write
= true },
69 { .cmd
= CMD_IDENTIFY
, .data
= true, .pio
= true,
70 .size
= 512, .read
= true },
71 { .cmd
= READ_FPDMA_QUEUED
, .data
= true, .dma
= true,
72 .lba48
= true, .read
= true, .ncq
= true },
73 { .cmd
= WRITE_FPDMA_QUEUED
, .data
= true, .dma
= true,
74 .lba48
= true, .write
= true, .ncq
= true },
75 { .cmd
= CMD_READ_MAX
, .lba28
= true },
76 { .cmd
= CMD_READ_MAX_EXT
, .lba48
= true },
77 { .cmd
= CMD_FLUSH_CACHE
, .data
= false },
78 { .cmd
= CMD_PACKET
, .data
= true, .size
= 16,
79 .atapi
= true, .pio
= true },
80 { .cmd
= CMD_PACKET_ID
, .data
= true, .pio
= true,
81 .size
= 512, .read
= true }
85 /* Test Management Data */
95 AHCICommandProp
*props
;
96 /* Data to be transferred to the guest */
97 AHCICommandHeader header
;
99 unsigned char *atapi_cmd
;
103 * Allocate space in the guest using information in the AHCIQState object.
105 uint64_t ahci_alloc(AHCIQState
*ahci
, size_t bytes
)
108 g_assert(ahci
->parent
);
109 return qmalloc(ahci
->parent
, bytes
);
112 void ahci_free(AHCIQState
*ahci
, uint64_t addr
)
115 g_assert(ahci
->parent
);
116 qfree(ahci
->parent
, addr
);
119 bool is_atapi(AHCIQState
*ahci
, uint8_t port
)
121 return ahci_px_rreg(ahci
, port
, AHCI_PX_SIG
) == AHCI_SIGNATURE_CDROM
;
125 * Locate, verify, and return a handle to the AHCI device.
127 QPCIDevice
*get_ahci_device(QTestState
*qts
, uint32_t *fingerprint
)
130 uint32_t ahci_fingerprint
;
133 pcibus
= qpci_new_pc(qts
, NULL
);
135 /* Find the AHCI PCI device and verify it's the right one. */
136 ahci
= qpci_device_find(pcibus
, QPCI_DEVFN(0x1F, 0x02));
137 g_assert(ahci
!= NULL
);
139 ahci_fingerprint
= qpci_config_readl(ahci
, PCI_VENDOR_ID
);
141 switch (ahci_fingerprint
) {
142 case AHCI_INTEL_ICH9
:
145 /* Unknown device. */
146 g_assert_not_reached();
150 *fingerprint
= ahci_fingerprint
;
155 void free_ahci_device(QPCIDevice
*dev
)
157 QPCIBus
*pcibus
= dev
? dev
->bus
: NULL
;
159 /* libqos doesn't have a function for this, so free it manually */
161 qpci_free_pc(pcibus
);
164 /* Free all memory in-use by the AHCI device. */
165 void ahci_clean_mem(AHCIQState
*ahci
)
169 for (port
= 0; port
< 32; ++port
) {
170 if (ahci
->port
[port
].fb
) {
171 ahci_free(ahci
, ahci
->port
[port
].fb
);
172 ahci
->port
[port
].fb
= 0;
174 if (ahci
->port
[port
].clb
) {
175 for (slot
= 0; slot
< 32; slot
++) {
176 ahci_destroy_command(ahci
, port
, slot
);
178 ahci_free(ahci
, ahci
->port
[port
].clb
);
179 ahci
->port
[port
].clb
= 0;
184 /*** Logical Device Initialization ***/
187 * Start the PCI device and sanity-check default operation.
189 void ahci_pci_enable(AHCIQState
*ahci
)
193 start_ahci_device(ahci
);
195 switch (ahci
->fingerprint
) {
196 case AHCI_INTEL_ICH9
:
197 /* ICH9 has a register at PCI 0x92 that
198 * acts as a master port enabler mask. */
199 reg
= qpci_config_readb(ahci
->dev
, 0x92);
201 qpci_config_writeb(ahci
->dev
, 0x92, reg
);
202 /* 0...0111111b -- bit significant, ports 0-5 enabled. */
203 ASSERT_BIT_SET(qpci_config_readb(ahci
->dev
, 0x92), 0x3F);
210 * Map BAR5/ABAR, and engage the PCI device.
212 void start_ahci_device(AHCIQState
*ahci
)
214 /* Map AHCI's ABAR (BAR5) */
215 ahci
->hba_bar
= qpci_iomap(ahci
->dev
, 5, &ahci
->barsize
);
217 /* turns on pci.cmd.iose, pci.cmd.mse and pci.cmd.bme */
218 qpci_device_enable(ahci
->dev
);
222 * Test and initialize the AHCI's HBA memory areas.
223 * Initialize and start any ports with devices attached.
224 * Bring the HBA into the idle state.
226 void ahci_hba_enable(AHCIQState
*ahci
)
228 /* Bits of interest in this section:
229 * GHC.AE Global Host Control / AHCI Enable
230 * PxCMD.ST Port Command: Start
231 * PxCMD.SUD "Spin Up Device"
232 * PxCMD.POD "Power On Device"
233 * PxCMD.FRE "FIS Receive Enable"
234 * PxCMD.FR "FIS Receive Running"
235 * PxCMD.CR "Command List Running"
237 uint32_t reg
, ports_impl
;
239 uint8_t num_cmd_slots
;
241 g_assert(ahci
!= NULL
);
243 /* Set GHC.AE to 1 */
244 ahci_set(ahci
, AHCI_GHC
, AHCI_GHC_AE
);
245 reg
= ahci_rreg(ahci
, AHCI_GHC
);
246 ASSERT_BIT_SET(reg
, AHCI_GHC_AE
);
248 /* Cache CAP and CAP2. */
249 ahci
->cap
= ahci_rreg(ahci
, AHCI_CAP
);
250 ahci
->cap2
= ahci_rreg(ahci
, AHCI_CAP2
);
252 /* Read CAP.NCS, how many command slots do we have? */
253 num_cmd_slots
= ((ahci
->cap
& AHCI_CAP_NCS
) >> ctzl(AHCI_CAP_NCS
)) + 1;
254 g_test_message("Number of Command Slots: %u", num_cmd_slots
);
256 /* Determine which ports are implemented. */
257 ports_impl
= ahci_rreg(ahci
, AHCI_PI
);
259 for (i
= 0; ports_impl
; ports_impl
>>= 1, ++i
) {
260 if (!(ports_impl
& 0x01)) {
264 g_test_message("Initializing port %u", i
);
266 reg
= ahci_px_rreg(ahci
, i
, AHCI_PX_CMD
);
267 if (BITCLR(reg
, AHCI_PX_CMD_ST
| AHCI_PX_CMD_CR
|
268 AHCI_PX_CMD_FRE
| AHCI_PX_CMD_FR
)) {
269 g_test_message("port is idle");
271 g_test_message("port needs to be idled");
272 ahci_px_clr(ahci
, i
, AHCI_PX_CMD
,
273 (AHCI_PX_CMD_ST
| AHCI_PX_CMD_FRE
));
274 /* The port has 500ms to disengage. */
276 reg
= ahci_px_rreg(ahci
, i
, AHCI_PX_CMD
);
277 ASSERT_BIT_CLEAR(reg
, AHCI_PX_CMD_CR
);
278 ASSERT_BIT_CLEAR(reg
, AHCI_PX_CMD_FR
);
279 g_test_message("port is now idle");
280 /* The spec does allow for possibly needing a PORT RESET
281 * or HBA reset if we fail to idle the port. */
284 /* Allocate Memory for the Command List Buffer & FIS Buffer */
285 /* PxCLB space ... 0x20 per command, as in 4.2.2 p 36 */
286 ahci
->port
[i
].clb
= ahci_alloc(ahci
, num_cmd_slots
* 0x20);
287 qtest_memset(ahci
->parent
->qts
, ahci
->port
[i
].clb
, 0x00,
288 num_cmd_slots
* 0x20);
289 g_test_message("CLB: 0x%08" PRIx64
, ahci
->port
[i
].clb
);
290 ahci_px_wreg(ahci
, i
, AHCI_PX_CLB
, ahci
->port
[i
].clb
);
291 g_assert_cmphex(ahci
->port
[i
].clb
, ==,
292 ahci_px_rreg(ahci
, i
, AHCI_PX_CLB
));
294 /* PxFB space ... 0x100, as in 4.2.1 p 35 */
295 ahci
->port
[i
].fb
= ahci_alloc(ahci
, 0x100);
296 qtest_memset(ahci
->parent
->qts
, ahci
->port
[i
].fb
, 0x00, 0x100);
297 g_test_message("FB: 0x%08" PRIx64
, ahci
->port
[i
].fb
);
298 ahci_px_wreg(ahci
, i
, AHCI_PX_FB
, ahci
->port
[i
].fb
);
299 g_assert_cmphex(ahci
->port
[i
].fb
, ==,
300 ahci_px_rreg(ahci
, i
, AHCI_PX_FB
));
302 /* Clear PxSERR, PxIS, then IS.IPS[x] by writing '1's. */
303 ahci_px_wreg(ahci
, i
, AHCI_PX_SERR
, 0xFFFFFFFF);
304 ahci_px_wreg(ahci
, i
, AHCI_PX_IS
, 0xFFFFFFFF);
305 ahci_wreg(ahci
, AHCI_IS
, (1 << i
));
307 /* Verify Interrupts Cleared */
308 reg
= ahci_px_rreg(ahci
, i
, AHCI_PX_SERR
);
309 g_assert_cmphex(reg
, ==, 0);
311 reg
= ahci_px_rreg(ahci
, i
, AHCI_PX_IS
);
312 g_assert_cmphex(reg
, ==, 0);
314 reg
= ahci_rreg(ahci
, AHCI_IS
);
315 ASSERT_BIT_CLEAR(reg
, (1 << i
));
317 /* Enable All Interrupts: */
318 ahci_px_wreg(ahci
, i
, AHCI_PX_IE
, 0xFFFFFFFF);
319 reg
= ahci_px_rreg(ahci
, i
, AHCI_PX_IE
);
320 g_assert_cmphex(reg
, ==, ~((uint32_t)AHCI_PX_IE_RESERVED
));
322 /* Enable the FIS Receive Engine. */
323 ahci_px_set(ahci
, i
, AHCI_PX_CMD
, AHCI_PX_CMD_FRE
);
324 reg
= ahci_px_rreg(ahci
, i
, AHCI_PX_CMD
);
325 ASSERT_BIT_SET(reg
, AHCI_PX_CMD_FR
);
327 /* AHCI 1.3 spec: if !STS.BSY, !STS.DRQ and PxSSTS.DET indicates
328 * physical presence, a device is present and may be started. However,
329 * PxSERR.DIAG.X /may/ need to be cleared a priori. */
330 reg
= ahci_px_rreg(ahci
, i
, AHCI_PX_SERR
);
331 if (BITSET(reg
, AHCI_PX_SERR_DIAG_X
)) {
332 ahci_px_set(ahci
, i
, AHCI_PX_SERR
, AHCI_PX_SERR_DIAG_X
);
335 reg
= ahci_px_rreg(ahci
, i
, AHCI_PX_TFD
);
336 if (BITCLR(reg
, AHCI_PX_TFD_STS_BSY
| AHCI_PX_TFD_STS_DRQ
)) {
337 reg
= ahci_px_rreg(ahci
, i
, AHCI_PX_SSTS
);
338 if ((reg
& AHCI_PX_SSTS_DET
) == SSTS_DET_ESTABLISHED
) {
339 /* Device Found: set PxCMD.ST := 1 */
340 ahci_px_set(ahci
, i
, AHCI_PX_CMD
, AHCI_PX_CMD_ST
);
341 ASSERT_BIT_SET(ahci_px_rreg(ahci
, i
, AHCI_PX_CMD
),
343 g_test_message("Started Device %u", i
);
344 } else if ((reg
& AHCI_PX_SSTS_DET
)) {
345 /* Device present, but in some unknown state. */
346 g_assert_not_reached();
352 ahci_set(ahci
, AHCI_GHC
, AHCI_GHC_IE
);
353 reg
= ahci_rreg(ahci
, AHCI_GHC
);
354 ASSERT_BIT_SET(reg
, AHCI_GHC_IE
);
356 ahci
->enabled
= true;
357 /* TODO: The device should now be idling and waiting for commands.
358 * In the future, a small test-case to inspect the Register D2H FIS
359 * and clear the initial interrupts might be good. */
363 * Pick the first implemented and running port
365 unsigned ahci_port_select(AHCIQState
*ahci
)
370 ports
= ahci_rreg(ahci
, AHCI_PI
);
371 for (i
= 0; i
< 32; ports
>>= 1, ++i
) {
376 if (!(ports
& 0x01)) {
380 reg
= ahci_px_rreg(ahci
, i
, AHCI_PX_CMD
);
381 if (BITSET(reg
, AHCI_PX_CMD_ST
)) {
390 * Clear a port's interrupts and status information prior to a test.
392 void ahci_port_clear(AHCIQState
*ahci
, uint8_t port
)
396 /* Clear out this port's interrupts (ignore the init register d2h fis) */
397 reg
= ahci_px_rreg(ahci
, port
, AHCI_PX_IS
);
398 ahci_px_wreg(ahci
, port
, AHCI_PX_IS
, reg
);
399 g_assert_cmphex(ahci_px_rreg(ahci
, port
, AHCI_PX_IS
), ==, 0);
401 /* Wipe the FIS-Receive Buffer */
402 qtest_memset(ahci
->parent
->qts
, ahci
->port
[port
].fb
, 0x00, 0x100);
406 * Check a port for errors.
408 void ahci_port_check_error(AHCIQState
*ahci
, uint8_t port
,
409 uint32_t imask
, uint8_t emask
)
413 /* The upper 9 bits of the IS register all indicate errors. */
414 reg
= ahci_px_rreg(ahci
, port
, AHCI_PX_IS
);
417 g_assert_cmphex(reg
, ==, 0);
419 /* The Sata Error Register should be empty. */
420 reg
= ahci_px_rreg(ahci
, port
, AHCI_PX_SERR
);
421 g_assert_cmphex(reg
, ==, 0);
423 /* The TFD also has two error sections. */
424 reg
= ahci_px_rreg(ahci
, port
, AHCI_PX_TFD
);
426 ASSERT_BIT_CLEAR(reg
, AHCI_PX_TFD_STS_ERR
);
428 ASSERT_BIT_SET(reg
, AHCI_PX_TFD_STS_ERR
);
430 ASSERT_BIT_CLEAR(reg
, AHCI_PX_TFD_ERR
& (~emask
<< 8));
431 ASSERT_BIT_SET(reg
, AHCI_PX_TFD_ERR
& (emask
<< 8));
434 void ahci_port_check_interrupts(AHCIQState
*ahci
, uint8_t port
,
439 /* Check for expected interrupts */
440 reg
= ahci_px_rreg(ahci
, port
, AHCI_PX_IS
);
441 ASSERT_BIT_SET(reg
, intr_mask
);
443 /* Clear expected interrupts and assert all interrupts now cleared. */
444 ahci_px_wreg(ahci
, port
, AHCI_PX_IS
, intr_mask
);
445 g_assert_cmphex(ahci_px_rreg(ahci
, port
, AHCI_PX_IS
), ==, 0);
448 void ahci_port_check_nonbusy(AHCIQState
*ahci
, uint8_t port
, uint8_t slot
)
452 /* Assert that the command slot is no longer busy (NCQ) */
453 reg
= ahci_px_rreg(ahci
, port
, AHCI_PX_SACT
);
454 ASSERT_BIT_CLEAR(reg
, (1 << slot
));
457 reg
= ahci_px_rreg(ahci
, port
, AHCI_PX_CI
);
458 ASSERT_BIT_CLEAR(reg
, (1 << slot
));
460 /* And assert that we are generally not busy. */
461 reg
= ahci_px_rreg(ahci
, port
, AHCI_PX_TFD
);
462 ASSERT_BIT_CLEAR(reg
, AHCI_PX_TFD_STS_BSY
);
463 ASSERT_BIT_CLEAR(reg
, AHCI_PX_TFD_STS_DRQ
);
466 void ahci_port_check_d2h_sanity(AHCIQState
*ahci
, uint8_t port
, uint8_t slot
)
468 RegD2HFIS
*d2h
= g_malloc0(0x20);
471 qtest_memread(ahci
->parent
->qts
, ahci
->port
[port
].fb
+ 0x40, d2h
, 0x20);
472 g_assert_cmphex(d2h
->fis_type
, ==, 0x34);
474 reg
= ahci_px_rreg(ahci
, port
, AHCI_PX_TFD
);
475 g_assert_cmphex((reg
& AHCI_PX_TFD_ERR
) >> 8, ==, d2h
->error
);
476 g_assert_cmphex((reg
& AHCI_PX_TFD_STS
), ==, d2h
->status
);
481 void ahci_port_check_pio_sanity(AHCIQState
*ahci
, AHCICommand
*cmd
)
483 PIOSetupFIS
*pio
= g_malloc0(0x20);
484 uint8_t port
= cmd
->port
;
486 /* We cannot check the Status or E_Status registers, because
487 * the status may have again changed between the PIO Setup FIS
488 * and the conclusion of the command with the D2H Register FIS. */
489 qtest_memread(ahci
->parent
->qts
, ahci
->port
[port
].fb
+ 0x20, pio
, 0x20);
490 g_assert_cmphex(pio
->fis_type
, ==, 0x5f);
492 /* Data transferred by PIO will either be:
493 * (1) 12 or 16 bytes for an ATAPI command packet (QEMU always uses 12), or
494 * (2) Actual data from the drive.
495 * If we do both, (2) winds up erasing any evidence of (1).
497 if (cmd
->props
->atapi
&& (cmd
->xbytes
== 0 || cmd
->props
->dma
)) {
498 g_assert(le16_to_cpu(pio
->tx_count
) == 12 ||
499 le16_to_cpu(pio
->tx_count
) == 16);
501 /* The AHCI test suite here does not test any PIO command that specifies
502 * a DRQ block larger than one sector (like 0xC4), so this should always
503 * be one sector or less. */
504 size_t pio_len
= ((cmd
->xbytes
% cmd
->sector_size
) ?
505 (cmd
->xbytes
% cmd
->sector_size
) : cmd
->sector_size
);
506 g_assert_cmphex(le16_to_cpu(pio
->tx_count
), ==, pio_len
);
511 void ahci_port_check_cmd_sanity(AHCIQState
*ahci
, AHCICommand
*cmd
)
513 AHCICommandHeader cmdh
;
515 ahci_get_command_header(ahci
, cmd
->port
, cmd
->slot
, &cmdh
);
516 /* Physical Region Descriptor Byte Count is not required to work for NCQ. */
517 if (!cmd
->props
->ncq
) {
518 g_assert_cmphex(cmd
->xbytes
, ==, cmdh
.prdbc
);
522 /* Get the command in #slot of port #port. */
523 void ahci_get_command_header(AHCIQState
*ahci
, uint8_t port
,
524 uint8_t slot
, AHCICommandHeader
*cmd
)
526 uint64_t ba
= ahci
->port
[port
].clb
;
527 ba
+= slot
* sizeof(AHCICommandHeader
);
528 qtest_memread(ahci
->parent
->qts
, ba
, cmd
, sizeof(AHCICommandHeader
));
530 cmd
->flags
= le16_to_cpu(cmd
->flags
);
531 cmd
->prdtl
= le16_to_cpu(cmd
->prdtl
);
532 cmd
->prdbc
= le32_to_cpu(cmd
->prdbc
);
533 cmd
->ctba
= le64_to_cpu(cmd
->ctba
);
536 /* Set the command in #slot of port #port. */
537 void ahci_set_command_header(AHCIQState
*ahci
, uint8_t port
,
538 uint8_t slot
, AHCICommandHeader
*cmd
)
540 AHCICommandHeader tmp
= { .flags
= 0 };
541 uint64_t ba
= ahci
->port
[port
].clb
;
542 ba
+= slot
* sizeof(AHCICommandHeader
);
544 tmp
.flags
= cpu_to_le16(cmd
->flags
);
545 tmp
.prdtl
= cpu_to_le16(cmd
->prdtl
);
546 tmp
.prdbc
= cpu_to_le32(cmd
->prdbc
);
547 tmp
.ctba
= cpu_to_le64(cmd
->ctba
);
549 qtest_memwrite(ahci
->parent
->qts
, ba
, &tmp
, sizeof(AHCICommandHeader
));
552 void ahci_destroy_command(AHCIQState
*ahci
, uint8_t port
, uint8_t slot
)
554 AHCICommandHeader cmd
;
556 /* Obtain the Nth Command Header */
557 ahci_get_command_header(ahci
, port
, slot
, &cmd
);
559 /* No address in it, so just return -- it's empty. */
564 ahci_free(ahci
, cmd
.ctba
);
567 /* NULL the header. */
568 memset(&cmd
, 0x00, sizeof(cmd
));
569 ahci_set_command_header(ahci
, port
, slot
, &cmd
);
570 ahci
->port
[port
].ctba
[slot
] = 0;
571 ahci
->port
[port
].prdtl
[slot
] = 0;
574 void ahci_write_fis(AHCIQState
*ahci
, AHCICommand
*cmd
)
576 RegH2DFIS tmp
= cmd
->fis
;
577 uint64_t addr
= cmd
->header
.ctba
;
579 /* NCQ commands use exclusively 8 bit fields and needs no adjustment.
580 * Only the count field needs to be adjusted for non-NCQ commands.
581 * The auxiliary FIS fields are defined per-command and are not currently
582 * implemented in libqos/ahci.o, but may or may not need to be flipped. */
583 if (!cmd
->props
->ncq
) {
584 tmp
.count
= cpu_to_le16(tmp
.count
);
587 qtest_memwrite(ahci
->parent
->qts
, addr
, &tmp
, sizeof(tmp
));
590 unsigned ahci_pick_cmd(AHCIQState
*ahci
, uint8_t port
)
596 reg
= ahci_px_rreg(ahci
, port
, AHCI_PX_CI
);
598 /* Pick the least recently used command slot that's available */
599 for (i
= 0; i
< 32; ++i
) {
600 j
= ((ahci
->port
[port
].next
+ i
) % 32);
601 if (reg
& (1 << j
)) {
604 ahci_destroy_command(ahci
, port
, j
);
605 ahci
->port
[port
].next
= (j
+ 1) % 32;
609 g_test_message("All command slots were busy.");
610 g_assert_not_reached();
613 inline unsigned size_to_prdtl(unsigned bytes
, unsigned bytes_per_prd
)
615 /* Each PRD can describe up to 4MiB */
616 g_assert_cmphex(bytes_per_prd
, <=, 4096 * 1024);
617 g_assert_cmphex(bytes_per_prd
& 0x01, ==, 0x00);
618 return (bytes
+ bytes_per_prd
- 1) / bytes_per_prd
;
621 const AHCIOpts default_opts
= { .size
= 0 };
624 * ahci_exec: execute a given command on a specific
627 * @ahci: The device to send the command to
628 * @port: The port number of the SATA device we wish
629 * to have execute this command
630 * @op: The S/ATA command to execute, or if opts.atapi
631 * is true, the SCSI command code.
632 * @opts: Optional arguments to modify execution behavior.
634 void ahci_exec(AHCIQState
*ahci
, uint8_t port
,
635 uint8_t op
, const AHCIOpts
*opts_in
)
641 opts
= g_memdup((opts_in
== NULL
? &default_opts
: opts_in
),
644 /* No guest buffer provided, create one. */
645 if (opts
->size
&& !opts
->buffer
) {
646 opts
->buffer
= ahci_alloc(ahci
, opts
->size
);
647 g_assert(opts
->buffer
);
648 qtest_memset(ahci
->parent
->qts
, opts
->buffer
, 0x00, opts
->size
);
651 /* Command creation */
653 uint16_t bcl
= opts
->set_bcl
? opts
->bcl
: ATAPI_SECTOR_SIZE
;
654 cmd
= ahci_atapi_command_create(op
, bcl
, opts
->atapi_dma
);
656 cmd
= ahci_command_create(op
);
658 ahci_command_adjust(cmd
, opts
->lba
, opts
->buffer
,
659 opts
->size
, opts
->prd_size
);
662 rc
= opts
->pre_cb(ahci
, cmd
, opts
);
663 g_assert_cmpint(rc
, ==, 0);
666 /* Write command to memory and issue it */
667 ahci_command_commit(ahci
, cmd
, port
);
668 ahci_command_issue_async(ahci
, cmd
);
670 qtest_qmp_eventwait(ahci
->parent
->qts
, "STOP");
673 rc
= opts
->mid_cb(ahci
, cmd
, opts
);
674 g_assert_cmpint(rc
, ==, 0);
677 qtest_qmp_send(ahci
->parent
->qts
, "{'execute':'cont' }");
678 qtest_qmp_eventwait(ahci
->parent
->qts
, "RESUME");
681 /* Wait for command to complete and verify sanity */
682 ahci_command_wait(ahci
, cmd
);
683 ahci_command_verify(ahci
, cmd
);
685 rc
= opts
->post_cb(ahci
, cmd
, opts
);
686 g_assert_cmpint(rc
, ==, 0);
688 ahci_command_free(cmd
);
689 if (opts
->buffer
!= opts_in
->buffer
) {
690 ahci_free(ahci
, opts
->buffer
);
695 /* Issue a command, expecting it to fail and STOP the VM */
696 AHCICommand
*ahci_guest_io_halt(AHCIQState
*ahci
, uint8_t port
,
697 uint8_t ide_cmd
, uint64_t buffer
,
698 size_t bufsize
, uint64_t sector
)
702 cmd
= ahci_command_create(ide_cmd
);
703 ahci_command_adjust(cmd
, sector
, buffer
, bufsize
, 0);
704 ahci_command_commit(ahci
, cmd
, port
);
705 ahci_command_issue_async(ahci
, cmd
);
706 qtest_qmp_eventwait(ahci
->parent
->qts
, "STOP");
711 /* Resume a previously failed command and verify/finalize */
712 void ahci_guest_io_resume(AHCIQState
*ahci
, AHCICommand
*cmd
)
714 /* Complete the command */
715 qtest_qmp_send(ahci
->parent
->qts
, "{'execute':'cont' }");
716 qtest_qmp_eventwait(ahci
->parent
->qts
, "RESUME");
717 ahci_command_wait(ahci
, cmd
);
718 ahci_command_verify(ahci
, cmd
);
719 ahci_command_free(cmd
);
722 /* Given a guest buffer address, perform an IO operation */
723 void ahci_guest_io(AHCIQState
*ahci
, uint8_t port
, uint8_t ide_cmd
,
724 uint64_t buffer
, size_t bufsize
, uint64_t sector
)
727 cmd
= ahci_command_create(ide_cmd
);
728 ahci_command_set_buffer(cmd
, buffer
);
729 ahci_command_set_size(cmd
, bufsize
);
731 ahci_command_set_offset(cmd
, sector
);
733 ahci_command_commit(ahci
, cmd
, port
);
734 ahci_command_issue(ahci
, cmd
);
735 ahci_command_verify(ahci
, cmd
);
736 ahci_command_free(cmd
);
739 static AHCICommandProp
*ahci_command_find(uint8_t command_name
)
743 for (i
= 0; i
< ARRAY_SIZE(ahci_command_properties
); i
++) {
744 if (ahci_command_properties
[i
].cmd
== command_name
) {
745 return &ahci_command_properties
[i
];
752 /* Given a HOST buffer, create a buffer address and perform an IO operation. */
753 void ahci_io(AHCIQState
*ahci
, uint8_t port
, uint8_t ide_cmd
,
754 void *buffer
, size_t bufsize
, uint64_t sector
)
757 AHCICommandProp
*props
;
759 props
= ahci_command_find(ide_cmd
);
761 ptr
= ahci_alloc(ahci
, bufsize
);
762 g_assert(!bufsize
|| ptr
);
763 qtest_memset(ahci
->parent
->qts
, ptr
, 0x00, bufsize
);
765 if (bufsize
&& props
->write
) {
766 qtest_bufwrite(ahci
->parent
->qts
, ptr
, buffer
, bufsize
);
769 ahci_guest_io(ahci
, port
, ide_cmd
, ptr
, bufsize
, sector
);
771 if (bufsize
&& props
->read
) {
772 qtest_bufread(ahci
->parent
->qts
, ptr
, buffer
, bufsize
);
775 ahci_free(ahci
, ptr
);
779 * Initializes a basic command header in memory.
780 * We assume that this is for an ATA command using RegH2DFIS.
782 static void command_header_init(AHCICommand
*cmd
)
784 AHCICommandHeader
*hdr
= &cmd
->header
;
785 AHCICommandProp
*props
= cmd
->props
;
787 hdr
->flags
= 5; /* RegH2DFIS is 5 DW long. Must be < 32 */
788 hdr
->flags
|= CMDH_CLR_BSY
; /* Clear the BSY bit when done */
790 hdr
->flags
|= CMDH_WRITE
;
793 hdr
->flags
|= CMDH_ATAPI
;
795 /* Other flags: PREFETCH, RESET, and BIST */
796 hdr
->prdtl
= size_to_prdtl(cmd
->xbytes
, cmd
->prd_size
);
801 static void command_table_init(AHCICommand
*cmd
)
803 RegH2DFIS
*fis
= &(cmd
->fis
);
804 uint16_t sect_count
= (cmd
->xbytes
/ cmd
->sector_size
);
806 fis
->fis_type
= REG_H2D_FIS
;
807 fis
->flags
= REG_H2D_FIS_CMD
; /* "Command" bit */
808 fis
->command
= cmd
->name
;
810 if (cmd
->props
->ncq
) {
811 NCQFIS
*ncqfis
= (NCQFIS
*)fis
;
812 /* NCQ is weird and re-uses FIS frames for unrelated data.
813 * See SATA 3.2, 13.6.4.1 READ FPDMA QUEUED for an example. */
814 ncqfis
->sector_low
= sect_count
& 0xFF;
815 ncqfis
->sector_hi
= (sect_count
>> 8) & 0xFF;
816 ncqfis
->device
= NCQ_DEVICE_MAGIC
;
817 /* Force Unit Access is bit 7 in the device register */
818 ncqfis
->tag
= 0; /* bits 3-7 are the NCQ tag */
819 ncqfis
->prio
= 0; /* bits 6,7 are a prio tag */
820 /* RARC bit is bit 0 of TAG field */
822 fis
->feature_low
= 0x00;
823 fis
->feature_high
= 0x00;
824 if (cmd
->props
->lba28
|| cmd
->props
->lba48
) {
825 fis
->device
= ATA_DEVICE_LBA
;
827 fis
->count
= (cmd
->xbytes
/ cmd
->sector_size
);
831 memset(fis
->aux
, 0x00, ARRAY_SIZE(fis
->aux
));
834 void ahci_command_enable_atapi_dma(AHCICommand
*cmd
)
836 RegH2DFIS
*fis
= &(cmd
->fis
);
837 g_assert(cmd
->props
->atapi
);
838 fis
->feature_low
|= 0x01;
839 /* PIO is still used to transfer the ATAPI command */
840 g_assert(cmd
->props
->pio
);
841 cmd
->props
->dma
= true;
842 /* BUG: We expect the DMA Setup interrupt for DMA commands */
843 /* cmd->interrupts |= AHCI_PX_IS_DSS; */
846 AHCICommand
*ahci_command_create(uint8_t command_name
)
848 AHCICommandProp
*props
= ahci_command_find(command_name
);
852 cmd
= g_new0(AHCICommand
, 1);
853 g_assert(!(props
->dma
&& props
->pio
) || props
->atapi
);
854 g_assert(!(props
->lba28
&& props
->lba48
));
855 g_assert(!(props
->read
&& props
->write
));
856 g_assert(!props
->size
|| props
->data
);
857 g_assert(!props
->ncq
|| props
->lba48
);
859 /* Defaults and book-keeping */
860 cmd
->props
= g_memdup(props
, sizeof(AHCICommandProp
));
861 cmd
->name
= command_name
;
862 cmd
->xbytes
= props
->size
;
863 cmd
->prd_size
= 4096;
864 cmd
->buffer
= 0xabad1dea;
865 cmd
->sector_size
= props
->atapi
? ATAPI_SECTOR_SIZE
: AHCI_SECTOR_SIZE
;
867 if (!cmd
->props
->ncq
) {
868 cmd
->interrupts
= AHCI_PX_IS_DHRS
;
870 /* BUG: We expect the DPS interrupt for data commands */
871 /* cmd->interrupts |= props->data ? AHCI_PX_IS_DPS : 0; */
872 /* BUG: We expect the DMA Setup interrupt for DMA commands */
873 /* cmd->interrupts |= props->dma ? AHCI_PX_IS_DSS : 0; */
874 cmd
->interrupts
|= props
->ncq
? AHCI_PX_IS_SDBS
: 0;
876 command_header_init(cmd
);
877 command_table_init(cmd
);
882 AHCICommand
*ahci_atapi_command_create(uint8_t scsi_cmd
, uint16_t bcl
, bool dma
)
884 AHCICommand
*cmd
= ahci_command_create(CMD_PACKET
);
885 cmd
->atapi_cmd
= g_malloc0(16);
886 cmd
->atapi_cmd
[0] = scsi_cmd
;
887 stw_le_p(&cmd
->fis
.lba_lo
[1], bcl
);
889 ahci_command_enable_atapi_dma(cmd
);
891 cmd
->interrupts
|= bcl
? AHCI_PX_IS_PSS
: 0;
896 void ahci_atapi_test_ready(AHCIQState
*ahci
, uint8_t port
,
897 bool ready
, uint8_t expected_sense
)
899 AHCICommand
*cmd
= ahci_atapi_command_create(CMD_ATAPI_TEST_UNIT_READY
, 0, false);
900 ahci_command_set_size(cmd
, 0);
902 cmd
->interrupts
|= AHCI_PX_IS_TFES
;
903 cmd
->errors
|= expected_sense
<< 4;
905 ahci_command_commit(ahci
, cmd
, port
);
906 ahci_command_issue(ahci
, cmd
);
907 ahci_command_verify(ahci
, cmd
);
908 ahci_command_free(cmd
);
911 static int copy_buffer(AHCIQState
*ahci
, AHCICommand
*cmd
,
912 const AHCIOpts
*opts
)
914 unsigned char *rx
= opts
->opaque
;
915 qtest_bufread(ahci
->parent
->qts
, opts
->buffer
, rx
, opts
->size
);
919 void ahci_atapi_get_sense(AHCIQState
*ahci
, uint8_t port
,
920 uint8_t *sense
, uint8_t *asc
)
926 .post_cb
= copy_buffer
,
931 ahci_exec(ahci
, port
, CMD_ATAPI_REQUEST_SENSE
, &opts
);
939 void ahci_atapi_eject(AHCIQState
*ahci
, uint8_t port
)
941 AHCICommand
*cmd
= ahci_atapi_command_create(CMD_ATAPI_START_STOP_UNIT
, 0, false);
942 ahci_command_set_size(cmd
, 0);
944 cmd
->atapi_cmd
[4] = 0x02; /* loej = true */
945 ahci_command_commit(ahci
, cmd
, port
);
946 ahci_command_issue(ahci
, cmd
);
947 ahci_command_verify(ahci
, cmd
);
948 ahci_command_free(cmd
);
951 void ahci_atapi_load(AHCIQState
*ahci
, uint8_t port
)
953 AHCICommand
*cmd
= ahci_atapi_command_create(CMD_ATAPI_START_STOP_UNIT
, 0, false);
954 ahci_command_set_size(cmd
, 0);
956 cmd
->atapi_cmd
[4] = 0x03; /* loej,start = true */
957 ahci_command_commit(ahci
, cmd
, port
);
958 ahci_command_issue(ahci
, cmd
);
959 ahci_command_verify(ahci
, cmd
);
960 ahci_command_free(cmd
);
963 void ahci_command_free(AHCICommand
*cmd
)
965 g_free(cmd
->atapi_cmd
);
970 void ahci_command_set_flags(AHCICommand
*cmd
, uint16_t cmdh_flags
)
972 cmd
->header
.flags
|= cmdh_flags
;
975 void ahci_command_clr_flags(AHCICommand
*cmd
, uint16_t cmdh_flags
)
977 cmd
->header
.flags
&= ~cmdh_flags
;
980 static void ahci_atapi_command_set_offset(AHCICommand
*cmd
, uint64_t lba
)
982 unsigned char *cbd
= cmd
->atapi_cmd
;
986 case CMD_ATAPI_READ_10
:
987 case CMD_ATAPI_READ_CD
:
988 g_assert_cmpuint(lba
, <=, UINT32_MAX
);
989 stl_be_p(&cbd
[2], lba
);
991 case CMD_ATAPI_REQUEST_SENSE
:
992 case CMD_ATAPI_TEST_UNIT_READY
:
993 case CMD_ATAPI_START_STOP_UNIT
:
994 g_assert_cmpuint(lba
, ==, 0x00);
997 /* SCSI doesn't have uniform packet formats,
998 * so you have to add support for it manually. Sorry! */
999 fprintf(stderr
, "The Libqos AHCI driver does not support the "
1000 "set_offset operation for ATAPI command 0x%02x, "
1001 "please add support.\n",
1003 g_assert_not_reached();
1007 void ahci_command_set_offset(AHCICommand
*cmd
, uint64_t lba_sect
)
1009 RegH2DFIS
*fis
= &(cmd
->fis
);
1011 if (cmd
->props
->atapi
) {
1012 ahci_atapi_command_set_offset(cmd
, lba_sect
);
1014 } else if (!cmd
->props
->data
&& !lba_sect
) {
1015 /* Not meaningful, ignore. */
1017 } else if (cmd
->props
->lba28
) {
1018 g_assert_cmphex(lba_sect
, <=, 0xFFFFFFF);
1019 } else if (cmd
->props
->lba48
|| cmd
->props
->ncq
) {
1020 g_assert_cmphex(lba_sect
, <=, 0xFFFFFFFFFFFF);
1022 /* Can't set offset if we don't know the format. */
1023 g_assert_not_reached();
1026 /* LBA28 uses the low nibble of the device/control register for LBA24:27 */
1027 fis
->lba_lo
[0] = (lba_sect
& 0xFF);
1028 fis
->lba_lo
[1] = (lba_sect
>> 8) & 0xFF;
1029 fis
->lba_lo
[2] = (lba_sect
>> 16) & 0xFF;
1030 if (cmd
->props
->lba28
) {
1031 fis
->device
= (fis
->device
& 0xF0) | ((lba_sect
>> 24) & 0x0F);
1033 fis
->lba_hi
[0] = (lba_sect
>> 24) & 0xFF;
1034 fis
->lba_hi
[1] = (lba_sect
>> 32) & 0xFF;
1035 fis
->lba_hi
[2] = (lba_sect
>> 40) & 0xFF;
1038 void ahci_command_set_buffer(AHCICommand
*cmd
, uint64_t buffer
)
1040 cmd
->buffer
= buffer
;
1043 static void ahci_atapi_set_size(AHCICommand
*cmd
, uint64_t xbytes
)
1045 unsigned char *cbd
= cmd
->atapi_cmd
;
1046 uint64_t nsectors
= xbytes
/ ATAPI_SECTOR_SIZE
;
1051 case CMD_ATAPI_READ_10
:
1052 g_assert_cmpuint(nsectors
, <=, UINT16_MAX
);
1053 stw_be_p(&cbd
[7], nsectors
);
1055 case CMD_ATAPI_READ_CD
:
1056 /* 24bit BE store */
1057 g_assert_cmpuint(nsectors
, <, 1ULL << 24);
1059 cbd
[6] = (tmp
& 0xFF0000) >> 16;
1060 cbd
[7] = (tmp
& 0xFF00) >> 8;
1061 cbd
[8] = (tmp
& 0xFF);
1063 case CMD_ATAPI_REQUEST_SENSE
:
1064 g_assert_cmpuint(xbytes
, <=, UINT8_MAX
);
1065 cbd
[4] = (uint8_t)xbytes
;
1067 case CMD_ATAPI_TEST_UNIT_READY
:
1068 case CMD_ATAPI_START_STOP_UNIT
:
1069 g_assert_cmpuint(xbytes
, ==, 0);
1072 /* SCSI doesn't have uniform packet formats,
1073 * so you have to add support for it manually. Sorry! */
1074 fprintf(stderr
, "The Libqos AHCI driver does not support the set_size "
1075 "operation for ATAPI command 0x%02x, please add support.\n",
1077 g_assert_not_reached();
1081 void ahci_command_set_sizes(AHCICommand
*cmd
, uint64_t xbytes
,
1084 uint16_t sect_count
;
1086 /* Each PRD can describe up to 4MiB, and must not be odd. */
1087 g_assert_cmphex(prd_size
, <=, 4096 * 1024);
1088 g_assert_cmphex(prd_size
& 0x01, ==, 0x00);
1090 cmd
->prd_size
= prd_size
;
1092 cmd
->xbytes
= xbytes
;
1093 sect_count
= (cmd
->xbytes
/ cmd
->sector_size
);
1095 if (cmd
->props
->ncq
) {
1096 NCQFIS
*nfis
= (NCQFIS
*)&(cmd
->fis
);
1097 nfis
->sector_low
= sect_count
& 0xFF;
1098 nfis
->sector_hi
= (sect_count
>> 8) & 0xFF;
1099 } else if (cmd
->props
->atapi
) {
1100 ahci_atapi_set_size(cmd
, xbytes
);
1102 /* For writes, the PIO Setup FIS interrupt only comes from DRQs
1105 if (cmd
->props
->pio
&& sect_count
> (cmd
->props
->read
? 0 : 1)) {
1106 cmd
->interrupts
|= AHCI_PX_IS_PSS
;
1108 cmd
->fis
.count
= sect_count
;
1110 cmd
->header
.prdtl
= size_to_prdtl(cmd
->xbytes
, cmd
->prd_size
);
1113 void ahci_command_set_size(AHCICommand
*cmd
, uint64_t xbytes
)
1115 ahci_command_set_sizes(cmd
, xbytes
, cmd
->prd_size
);
1118 void ahci_command_set_prd_size(AHCICommand
*cmd
, unsigned prd_size
)
1120 ahci_command_set_sizes(cmd
, cmd
->xbytes
, prd_size
);
1123 void ahci_command_adjust(AHCICommand
*cmd
, uint64_t offset
, uint64_t buffer
,
1124 uint64_t xbytes
, unsigned prd_size
)
1126 ahci_command_set_sizes(cmd
, xbytes
, prd_size
);
1127 ahci_command_set_buffer(cmd
, buffer
);
1128 ahci_command_set_offset(cmd
, offset
);
1131 void ahci_command_commit(AHCIQState
*ahci
, AHCICommand
*cmd
, uint8_t port
)
1134 uint64_t table_size
, table_ptr
, remaining
;
1137 /* This command is now tied to this port/command slot */
1139 cmd
->slot
= ahci_pick_cmd(ahci
, port
);
1141 if (cmd
->props
->ncq
) {
1142 NCQFIS
*nfis
= (NCQFIS
*)&cmd
->fis
;
1143 nfis
->tag
= (cmd
->slot
<< 3) & 0xFC;
1146 /* Create a buffer for the command table */
1147 prdtl
= size_to_prdtl(cmd
->xbytes
, cmd
->prd_size
);
1148 table_size
= CMD_TBL_SIZ(prdtl
);
1149 table_ptr
= ahci_alloc(ahci
, table_size
);
1150 g_assert(table_ptr
);
1151 /* AHCI 1.3: Must be aligned to 0x80 */
1152 g_assert((table_ptr
& 0x7F) == 0x00);
1153 cmd
->header
.ctba
= table_ptr
;
1155 /* Commit the command header (part of the Command List Buffer) */
1156 ahci_set_command_header(ahci
, port
, cmd
->slot
, &(cmd
->header
));
1157 /* Now, write the command table (FIS, ACMD, and PRDT) -- FIS first, */
1158 ahci_write_fis(ahci
, cmd
);
1159 /* Then ATAPI CMD, if needed */
1160 if (cmd
->props
->atapi
) {
1161 qtest_memwrite(ahci
->parent
->qts
, table_ptr
+ 0x40, cmd
->atapi_cmd
, 16);
1164 /* Construct and write the PRDs to the command table */
1165 g_assert_cmphex(prdtl
, ==, cmd
->header
.prdtl
);
1166 remaining
= cmd
->xbytes
;
1167 for (i
= 0; i
< prdtl
; ++i
) {
1168 prd
.dba
= cpu_to_le64(cmd
->buffer
+ (cmd
->prd_size
* i
));
1170 if (remaining
> cmd
->prd_size
) {
1171 /* Note that byte count is 0-based. */
1172 prd
.dbc
= cpu_to_le32(cmd
->prd_size
- 1);
1173 remaining
-= cmd
->prd_size
;
1175 /* Again, dbc is 0-based. */
1176 prd
.dbc
= cpu_to_le32(remaining
- 1);
1179 prd
.dbc
|= cpu_to_le32(0x80000000); /* Request DPS Interrupt */
1181 /* Commit the PRD entry to the Command Table */
1182 qtest_memwrite(ahci
->parent
->qts
, table_ptr
+ 0x80 + (i
* sizeof(PRD
)),
1186 /* Bookmark the PRDTL and CTBA values */
1187 ahci
->port
[port
].ctba
[cmd
->slot
] = table_ptr
;
1188 ahci
->port
[port
].prdtl
[cmd
->slot
] = prdtl
;
1191 void ahci_command_issue_async(AHCIQState
*ahci
, AHCICommand
*cmd
)
1193 if (cmd
->props
->ncq
) {
1194 ahci_px_wreg(ahci
, cmd
->port
, AHCI_PX_SACT
, (1 << cmd
->slot
));
1197 ahci_px_wreg(ahci
, cmd
->port
, AHCI_PX_CI
, (1 << cmd
->slot
));
1200 void ahci_command_wait(AHCIQState
*ahci
, AHCICommand
*cmd
)
1202 /* We can't rely on STS_BSY until the command has started processing.
1203 * Therefore, we also use the Command Issue bit as indication of
1204 * a command in-flight. */
1206 #define RSET(REG, MASK) (BITSET(ahci_px_rreg(ahci, cmd->port, (REG)), (MASK)))
1208 while (RSET(AHCI_PX_TFD
, AHCI_PX_TFD_STS_BSY
) ||
1209 RSET(AHCI_PX_CI
, 1 << cmd
->slot
) ||
1210 (cmd
->props
->ncq
&& RSET(AHCI_PX_SACT
, 1 << cmd
->slot
))) {
1216 void ahci_command_issue(AHCIQState
*ahci
, AHCICommand
*cmd
)
1218 ahci_command_issue_async(ahci
, cmd
);
1219 ahci_command_wait(ahci
, cmd
);
1222 void ahci_command_verify(AHCIQState
*ahci
, AHCICommand
*cmd
)
1224 uint8_t slot
= cmd
->slot
;
1225 uint8_t port
= cmd
->port
;
1227 ahci_port_check_error(ahci
, port
, cmd
->interrupts
, cmd
->errors
);
1228 ahci_port_check_interrupts(ahci
, port
, cmd
->interrupts
);
1229 ahci_port_check_nonbusy(ahci
, port
, slot
);
1230 ahci_port_check_cmd_sanity(ahci
, cmd
);
1231 if (cmd
->interrupts
& AHCI_PX_IS_DHRS
) {
1232 ahci_port_check_d2h_sanity(ahci
, port
, slot
);
1234 if (cmd
->props
->pio
) {
1235 ahci_port_check_pio_sanity(ahci
, cmd
);
1239 uint8_t ahci_command_slot(AHCICommand
*cmd
)