Lines Matching full:ahci

2  * libqos AHCI functions
28 #include "ahci.h"
104 uint64_t ahci_alloc(AHCIQState *ahci, size_t bytes) in ahci_alloc() argument
106 g_assert(ahci); in ahci_alloc()
107 g_assert(ahci->parent); in ahci_alloc()
108 return qmalloc(ahci->parent, bytes); in ahci_alloc()
111 void ahci_free(AHCIQState *ahci, uint64_t addr) in ahci_free() argument
113 g_assert(ahci); in ahci_free()
114 g_assert(ahci->parent); in ahci_free()
115 qfree(ahci->parent, addr); in ahci_free()
118 bool is_atapi(AHCIQState *ahci, uint8_t port) in is_atapi() argument
120 return ahci_px_rreg(ahci, port, AHCI_PX_SIG) == AHCI_SIGNATURE_CDROM; in is_atapi()
124 * Locate, verify, and return a handle to the AHCI device.
128 QPCIDevice *ahci; in get_ahci_device() local
134 /* Find the AHCI PCI device and verify it's the right one. */ in get_ahci_device()
135 ahci = qpci_device_find(pcibus, QPCI_DEVFN(0x1F, 0x02)); in get_ahci_device()
136 g_assert(ahci != NULL); in get_ahci_device()
138 ahci_fingerprint = qpci_config_readl(ahci, PCI_VENDOR_ID); in get_ahci_device()
151 return ahci; in get_ahci_device()
163 /* Free all memory in-use by the AHCI device. */
164 void ahci_clean_mem(AHCIQState *ahci) in ahci_clean_mem() argument
169 if (ahci->port[port].fb) { in ahci_clean_mem()
170 ahci_free(ahci, ahci->port[port].fb); in ahci_clean_mem()
171 ahci->port[port].fb = 0; in ahci_clean_mem()
173 if (ahci->port[port].clb) { in ahci_clean_mem()
175 ahci_destroy_command(ahci, port, slot); in ahci_clean_mem()
177 ahci_free(ahci, ahci->port[port].clb); in ahci_clean_mem()
178 ahci->port[port].clb = 0; in ahci_clean_mem()
188 void ahci_pci_enable(AHCIQState *ahci) in ahci_pci_enable() argument
192 start_ahci_device(ahci); in ahci_pci_enable()
194 switch (ahci->fingerprint) { in ahci_pci_enable()
198 reg = qpci_config_readb(ahci->dev, 0x92); in ahci_pci_enable()
200 qpci_config_writeb(ahci->dev, 0x92, reg); in ahci_pci_enable()
202 ASSERT_BIT_SET(qpci_config_readb(ahci->dev, 0x92), 0x3F); in ahci_pci_enable()
211 void start_ahci_device(AHCIQState *ahci) in start_ahci_device() argument
213 /* Map AHCI's ABAR (BAR5) */ in start_ahci_device()
214 ahci->hba_bar = qpci_iomap(ahci->dev, 5, &ahci->barsize); in start_ahci_device()
217 qpci_device_enable(ahci->dev); in start_ahci_device()
221 * Test and initialize the AHCI's HBA memory areas.
225 void ahci_hba_enable(AHCIQState *ahci) in ahci_hba_enable() argument
228 * GHC.AE Global Host Control / AHCI Enable in ahci_hba_enable()
240 g_assert(ahci != NULL); in ahci_hba_enable()
243 ahci_set(ahci, AHCI_GHC, AHCI_GHC_AE); in ahci_hba_enable()
244 reg = ahci_rreg(ahci, AHCI_GHC); in ahci_hba_enable()
248 ahci->cap = ahci_rreg(ahci, AHCI_CAP); in ahci_hba_enable()
249 ahci->cap2 = ahci_rreg(ahci, AHCI_CAP2); in ahci_hba_enable()
252 num_cmd_slots = ((ahci->cap & AHCI_CAP_NCS) >> ctzl(AHCI_CAP_NCS)) + 1; in ahci_hba_enable()
256 ports_impl = ahci_rreg(ahci, AHCI_PI); in ahci_hba_enable()
265 reg = ahci_px_rreg(ahci, i, AHCI_PX_CMD); in ahci_hba_enable()
271 ahci_px_clr(ahci, i, AHCI_PX_CMD, in ahci_hba_enable()
275 reg = ahci_px_rreg(ahci, i, AHCI_PX_CMD); in ahci_hba_enable()
285 ahci->port[i].clb = ahci_alloc(ahci, num_cmd_slots * 0x20); in ahci_hba_enable()
286 qtest_memset(ahci->parent->qts, ahci->port[i].clb, 0x00, in ahci_hba_enable()
288 g_test_message("CLB: 0x%08" PRIx64, ahci->port[i].clb); in ahci_hba_enable()
289 ahci_px_wreg(ahci, i, AHCI_PX_CLB, ahci->port[i].clb); in ahci_hba_enable()
290 g_assert_cmphex(ahci->port[i].clb, ==, in ahci_hba_enable()
291 ahci_px_rreg(ahci, i, AHCI_PX_CLB)); in ahci_hba_enable()
294 ahci->port[i].fb = ahci_alloc(ahci, 0x100); in ahci_hba_enable()
295 qtest_memset(ahci->parent->qts, ahci->port[i].fb, 0x00, 0x100); in ahci_hba_enable()
296 g_test_message("FB: 0x%08" PRIx64, ahci->port[i].fb); in ahci_hba_enable()
297 ahci_px_wreg(ahci, i, AHCI_PX_FB, ahci->port[i].fb); in ahci_hba_enable()
298 g_assert_cmphex(ahci->port[i].fb, ==, in ahci_hba_enable()
299 ahci_px_rreg(ahci, i, AHCI_PX_FB)); in ahci_hba_enable()
302 ahci_px_wreg(ahci, i, AHCI_PX_SERR, 0xFFFFFFFF); in ahci_hba_enable()
303 ahci_px_wreg(ahci, i, AHCI_PX_IS, 0xFFFFFFFF); in ahci_hba_enable()
304 ahci_wreg(ahci, AHCI_IS, (1 << i)); in ahci_hba_enable()
307 reg = ahci_px_rreg(ahci, i, AHCI_PX_SERR); in ahci_hba_enable()
310 reg = ahci_px_rreg(ahci, i, AHCI_PX_IS); in ahci_hba_enable()
313 reg = ahci_rreg(ahci, AHCI_IS); in ahci_hba_enable()
317 ahci_px_wreg(ahci, i, AHCI_PX_IE, 0xFFFFFFFF); in ahci_hba_enable()
318 reg = ahci_px_rreg(ahci, i, AHCI_PX_IE); in ahci_hba_enable()
322 ahci_px_set(ahci, i, AHCI_PX_CMD, AHCI_PX_CMD_FRE); in ahci_hba_enable()
323 reg = ahci_px_rreg(ahci, i, AHCI_PX_CMD); in ahci_hba_enable()
326 /* AHCI 1.3 spec: if !STS.BSY, !STS.DRQ and PxSSTS.DET indicates in ahci_hba_enable()
329 reg = ahci_px_rreg(ahci, i, AHCI_PX_SERR); in ahci_hba_enable()
331 ahci_px_set(ahci, i, AHCI_PX_SERR, AHCI_PX_SERR_DIAG_X); in ahci_hba_enable()
334 reg = ahci_px_rreg(ahci, i, AHCI_PX_TFD); in ahci_hba_enable()
336 reg = ahci_px_rreg(ahci, i, AHCI_PX_SSTS); in ahci_hba_enable()
339 ahci_px_set(ahci, i, AHCI_PX_CMD, AHCI_PX_CMD_ST); in ahci_hba_enable()
340 ASSERT_BIT_SET(ahci_px_rreg(ahci, i, AHCI_PX_CMD), in ahci_hba_enable()
351 ahci_set(ahci, AHCI_GHC, AHCI_GHC_IE); in ahci_hba_enable()
352 reg = ahci_rreg(ahci, AHCI_GHC); in ahci_hba_enable()
355 ahci->enabled = true; in ahci_hba_enable()
364 unsigned ahci_port_select(AHCIQState *ahci) in ahci_port_select() argument
369 ports = ahci_rreg(ahci, AHCI_PI); in ahci_port_select()
379 reg = ahci_px_rreg(ahci, i, AHCI_PX_CMD); in ahci_port_select()
391 void ahci_port_clear(AHCIQState *ahci, uint8_t port) in ahci_port_clear() argument
396 reg = ahci_px_rreg(ahci, port, AHCI_PX_IS); in ahci_port_clear()
397 ahci_px_wreg(ahci, port, AHCI_PX_IS, reg); in ahci_port_clear()
398 g_assert_cmphex(ahci_px_rreg(ahci, port, AHCI_PX_IS), ==, 0); in ahci_port_clear()
401 qtest_memset(ahci->parent->qts, ahci->port[port].fb, 0x00, 0x100); in ahci_port_clear()
407 void ahci_port_check_error(AHCIQState *ahci, AHCICommand *cmd) in ahci_port_check_error() argument
414 reg = ahci_px_rreg(ahci, port, AHCI_PX_IS); in ahci_port_check_error()
418 reg = ahci_px_rreg(ahci, port, AHCI_PX_IS); in ahci_port_check_error()
425 reg = ahci_px_rreg(ahci, port, AHCI_PX_SERR); in ahci_port_check_error()
429 * (see AHCI 1.3 section 6.2.2.1) such that we can send new commands. */ in ahci_port_check_error()
432 ahci_px_clr(ahci, port, AHCI_PX_CMD, AHCI_PX_CMD_ST); in ahci_port_check_error()
436 reg = ahci_px_rreg(ahci, port, AHCI_PX_CMD); in ahci_port_check_error()
440 reg = ahci_px_rreg(ahci, port, AHCI_PX_IS); in ahci_port_check_error()
441 ahci_px_wreg(ahci, port, AHCI_PX_IS, reg); in ahci_port_check_error()
446 reg = ahci_px_rreg(ahci, port, AHCI_PX_TFD); in ahci_port_check_error()
450 ahci_px_set(ahci, port, AHCI_PX_CMD, AHCI_PX_CMD_ST); in ahci_port_check_error()
454 reg = ahci_px_rreg(ahci, port, AHCI_PX_TFD); in ahci_port_check_error()
464 void ahci_port_check_interrupts(AHCIQState *ahci, AHCICommand *cmd) in ahci_port_check_interrupts() argument
477 reg = ahci_px_rreg(ahci, port, AHCI_PX_IS); in ahci_port_check_interrupts()
481 ahci_px_wreg(ahci, port, AHCI_PX_IS, cmd->interrupts); in ahci_port_check_interrupts()
482 g_assert_cmphex(ahci_px_rreg(ahci, port, AHCI_PX_IS), ==, 0); in ahci_port_check_interrupts()
485 void ahci_port_check_nonbusy(AHCIQState *ahci, AHCICommand *cmd) in ahci_port_check_nonbusy() argument
494 reg = ahci_px_rreg(ahci, port, AHCI_PX_SACT); in ahci_port_check_nonbusy()
505 reg = ahci_px_rreg(ahci, port, AHCI_PX_CI); in ahci_port_check_nonbusy()
513 reg = ahci_px_rreg(ahci, port, AHCI_PX_TFD); in ahci_port_check_nonbusy()
518 void ahci_port_check_d2h_sanity(AHCIQState *ahci, uint8_t port, uint8_t slot) in ahci_port_check_d2h_sanity() argument
523 qtest_memread(ahci->parent->qts, ahci->port[port].fb + 0x40, d2h, 0x20); in ahci_port_check_d2h_sanity()
526 reg = ahci_px_rreg(ahci, port, AHCI_PX_TFD); in ahci_port_check_d2h_sanity()
533 void ahci_port_check_pio_sanity(AHCIQState *ahci, AHCICommand *cmd) in ahci_port_check_pio_sanity() argument
541 qtest_memread(ahci->parent->qts, ahci->port[port].fb + 0x20, pio, 0x20); in ahci_port_check_pio_sanity()
553 /* The AHCI test suite here does not test any PIO command that specifies in ahci_port_check_pio_sanity()
563 void ahci_port_check_cmd_sanity(AHCIQState *ahci, AHCICommand *cmd) in ahci_port_check_cmd_sanity() argument
567 ahci_get_command_header(ahci, cmd->port, cmd->slot, &cmdh); in ahci_port_check_cmd_sanity()
575 void ahci_get_command_header(AHCIQState *ahci, uint8_t port, in ahci_get_command_header() argument
578 uint64_t ba = ahci->port[port].clb; in ahci_get_command_header()
580 qtest_memread(ahci->parent->qts, ba, cmd, sizeof(AHCICommandHeader)); in ahci_get_command_header()
589 void ahci_set_command_header(AHCIQState *ahci, uint8_t port, in ahci_set_command_header() argument
593 uint64_t ba = ahci->port[port].clb; in ahci_set_command_header()
601 qtest_memwrite(ahci->parent->qts, ba, &tmp, sizeof(AHCICommandHeader)); in ahci_set_command_header()
604 void ahci_destroy_command(AHCIQState *ahci, uint8_t port, uint8_t slot) in ahci_destroy_command() argument
609 ahci_get_command_header(ahci, port, slot, &cmd); in ahci_destroy_command()
616 ahci_free(ahci, cmd.ctba); in ahci_destroy_command()
621 ahci_set_command_header(ahci, port, slot, &cmd); in ahci_destroy_command()
622 ahci->port[port].ctba[slot] = 0; in ahci_destroy_command()
623 ahci->port[port].prdtl[slot] = 0; in ahci_destroy_command()
626 void ahci_write_fis(AHCIQState *ahci, AHCICommand *cmd) in ahci_write_fis() argument
634 * implemented in ahci.o, but may or may not need to be flipped. */ in ahci_write_fis()
639 qtest_memwrite(ahci->parent->qts, addr, &tmp, sizeof(tmp)); in ahci_write_fis()
642 unsigned ahci_pick_cmd(AHCIQState *ahci, uint8_t port) in ahci_pick_cmd() argument
648 reg = ahci_px_rreg(ahci, port, AHCI_PX_CI); in ahci_pick_cmd()
652 j = ((ahci->port[port].next + i) % 32); in ahci_pick_cmd()
656 ahci_destroy_command(ahci, port, j); in ahci_pick_cmd()
657 ahci->port[port].next = (j + 1) % 32; in ahci_pick_cmd()
677 * AHCI port.
679 * @ahci: The device to send the command to
686 void ahci_exec(AHCIQState *ahci, uint8_t port, in ahci_exec() argument
701 opts->buffer = ahci_alloc(ahci, opts->size); in ahci_exec()
703 qtest_memset(ahci->parent->qts, opts->buffer, 0x00, opts->size); in ahci_exec()
717 rc = opts->pre_cb(ahci, cmd, opts); in ahci_exec()
722 ahci_command_commit(ahci, cmd, port); in ahci_exec()
723 ahci_command_issue_async(ahci, cmd); in ahci_exec()
725 qtest_qmp_eventwait(ahci->parent->qts, "STOP"); in ahci_exec()
728 rc = opts->mid_cb(ahci, cmd, opts); in ahci_exec()
732 qtest_qmp_send(ahci->parent->qts, "{'execute':'cont' }"); in ahci_exec()
733 qtest_qmp_eventwait(ahci->parent->qts, "RESUME"); in ahci_exec()
737 ahci_command_wait(ahci, cmd); in ahci_exec()
738 ahci_command_verify(ahci, cmd); in ahci_exec()
740 rc = opts->post_cb(ahci, cmd, opts); in ahci_exec()
745 ahci_free(ahci, opts->buffer); in ahci_exec()
751 AHCICommand *ahci_guest_io_halt(AHCIQState *ahci, uint8_t port, in ahci_guest_io_halt() argument
759 ahci_command_commit(ahci, cmd, port); in ahci_guest_io_halt()
760 ahci_command_issue_async(ahci, cmd); in ahci_guest_io_halt()
761 qtest_qmp_eventwait(ahci->parent->qts, "STOP"); in ahci_guest_io_halt()
767 void ahci_guest_io_resume(AHCIQState *ahci, AHCICommand *cmd) in ahci_guest_io_resume() argument
770 qtest_qmp_send(ahci->parent->qts, "{'execute':'cont' }"); in ahci_guest_io_resume()
771 qtest_qmp_eventwait(ahci->parent->qts, "RESUME"); in ahci_guest_io_resume()
772 ahci_command_wait(ahci, cmd); in ahci_guest_io_resume()
773 ahci_command_verify(ahci, cmd); in ahci_guest_io_resume()
778 void ahci_guest_io(AHCIQState *ahci, uint8_t port, uint8_t ide_cmd, in ahci_guest_io() argument
788 ahci_command_commit(ahci, cmd, port); in ahci_guest_io()
789 ahci_command_issue(ahci, cmd); in ahci_guest_io()
790 ahci_command_verify(ahci, cmd); in ahci_guest_io()
808 void ahci_io(AHCIQState *ahci, uint8_t port, uint8_t ide_cmd, in ahci_io() argument
816 ptr = ahci_alloc(ahci, bufsize); in ahci_io()
818 qtest_memset(ahci->parent->qts, ptr, 0x00, bufsize); in ahci_io()
821 qtest_bufwrite(ahci->parent->qts, ptr, buffer, bufsize); in ahci_io()
824 ahci_guest_io(ahci, port, ide_cmd, ptr, bufsize, sector); in ahci_io()
827 qtest_bufread(ahci->parent->qts, ptr, buffer, bufsize); in ahci_io()
830 ahci_free(ahci, ptr); in ahci_io()
951 void ahci_atapi_test_ready(AHCIQState *ahci, uint8_t port, in ahci_atapi_test_ready() argument
960 ahci_command_commit(ahci, cmd, port); in ahci_atapi_test_ready()
961 ahci_command_issue(ahci, cmd); in ahci_atapi_test_ready()
962 ahci_command_verify(ahci, cmd); in ahci_atapi_test_ready()
966 static int copy_buffer(AHCIQState *ahci, AHCICommand *cmd, in copy_buffer() argument
970 qtest_bufread(ahci->parent->qts, opts->buffer, rx, opts->size); in copy_buffer()
974 void ahci_atapi_get_sense(AHCIQState *ahci, uint8_t port, in ahci_atapi_get_sense() argument
986 ahci_exec(ahci, port, CMD_ATAPI_REQUEST_SENSE, &opts); in ahci_atapi_get_sense()
994 void ahci_atapi_eject(AHCIQState *ahci, uint8_t port) in ahci_atapi_eject() argument
1000 ahci_command_commit(ahci, cmd, port); in ahci_atapi_eject()
1001 ahci_command_issue(ahci, cmd); in ahci_atapi_eject()
1002 ahci_command_verify(ahci, cmd); in ahci_atapi_eject()
1006 void ahci_atapi_load(AHCIQState *ahci, uint8_t port) in ahci_atapi_load() argument
1012 ahci_command_commit(ahci, cmd, port); in ahci_atapi_load()
1013 ahci_command_issue(ahci, cmd); in ahci_atapi_load()
1014 ahci_command_verify(ahci, cmd); in ahci_atapi_load()
1054 fprintf(stderr, "The Libqos AHCI driver does not support the " in ahci_atapi_command_set_offset()
1129 fprintf(stderr, "The Libqos AHCI driver does not support the set_size " in ahci_atapi_set_size()
1186 void ahci_command_commit(AHCIQState *ahci, AHCICommand *cmd, uint8_t port) in ahci_command_commit() argument
1194 cmd->slot = ahci_pick_cmd(ahci, port); in ahci_command_commit()
1204 table_ptr = ahci_alloc(ahci, table_size); in ahci_command_commit()
1206 /* AHCI 1.3: Must be aligned to 0x80 */ in ahci_command_commit()
1211 ahci_set_command_header(ahci, port, cmd->slot, &(cmd->header)); in ahci_command_commit()
1213 ahci_write_fis(ahci, cmd); in ahci_command_commit()
1216 qtest_memwrite(ahci->parent->qts, table_ptr + 0x40, cmd->atapi_cmd, 16); in ahci_command_commit()
1237 qtest_memwrite(ahci->parent->qts, table_ptr + 0x80 + (i * sizeof(PRD)), in ahci_command_commit()
1242 ahci->port[port].ctba[cmd->slot] = table_ptr; in ahci_command_commit()
1243 ahci->port[port].prdtl[cmd->slot] = prdtl; in ahci_command_commit()
1246 void ahci_command_issue_async(AHCIQState *ahci, AHCICommand *cmd) in ahci_command_issue_async() argument
1249 ahci_px_wreg(ahci, cmd->port, AHCI_PX_SACT, (1 << cmd->slot)); in ahci_command_issue_async()
1252 ahci_px_wreg(ahci, cmd->port, AHCI_PX_CI, (1 << cmd->slot)); in ahci_command_issue_async()
1255 void ahci_command_wait(AHCIQState *ahci, AHCICommand *cmd) in ahci_command_wait() argument
1261 #define RSET(REG, MASK) (BITSET(ahci_px_rreg(ahci, cmd->port, (REG)), (MASK))) in ahci_command_wait()
1272 void ahci_command_issue(AHCIQState *ahci, AHCICommand *cmd) in ahci_command_issue() argument
1274 ahci_command_issue_async(ahci, cmd); in ahci_command_issue()
1275 ahci_command_wait(ahci, cmd); in ahci_command_issue()
1278 void ahci_command_verify(AHCIQState *ahci, AHCICommand *cmd) in ahci_command_verify() argument
1283 ahci_port_check_nonbusy(ahci, cmd); in ahci_command_verify()
1284 ahci_port_check_error(ahci, cmd); in ahci_command_verify()
1285 ahci_port_check_interrupts(ahci, cmd); in ahci_command_verify()
1286 ahci_port_check_cmd_sanity(ahci, cmd); in ahci_command_verify()
1288 ahci_port_check_d2h_sanity(ahci, port, slot); in ahci_command_verify()
1291 ahci_port_check_pio_sanity(ahci, cmd); in ahci_command_verify()