From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:50057) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XUlzv-0008W8-Hj for qemu-devel@nongnu.org; Thu, 18 Sep 2014 20:24:32 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1XUlzq-000471-NF for qemu-devel@nongnu.org; Thu, 18 Sep 2014 20:24:27 -0400 Received: from mx1.redhat.com ([209.132.183.28]:61267) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XUlzq-00046F-CC for qemu-devel@nongnu.org; Thu, 18 Sep 2014 20:24:22 -0400 Received: from int-mx14.intmail.prod.int.phx2.redhat.com (int-mx14.intmail.prod.int.phx2.redhat.com [10.5.11.27]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id s8INi5YD031403 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL) for ; Thu, 18 Sep 2014 19:44:05 -0400 From: John Snow Date: Thu, 18 Sep 2014 19:43:25 -0400 Message-Id: <1411083819-9284-2-git-send-email-jsnow@redhat.com> In-Reply-To: <1411083819-9284-1-git-send-email-jsnow@redhat.com> References: <1411083819-9284-1-git-send-email-jsnow@redhat.com> Subject: [Qemu-devel] [PATCH 01/15] qtest/ahci: Add AHCIState structure List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: kwolf@redhat.com, mst@redhat.com, armbru@redhat.com, stefanha@redhat.com, pbonzini@redhat.com, John Snow Introduce a state structure that can be used to conveniently bookmark key values of the AHCI Device instead of re-polling it all the time. This structure also helps ease of cleanup. Signed-off-by: John Snow --- tests/ahci-test.c | 283 ++++++++++++++++++++++++++---------------------------- 1 file changed, 138 insertions(+), 145 deletions(-) diff --git a/tests/ahci-test.c b/tests/ahci-test.c index 7cc49f0..d845635 100644 --- a/tests/ahci-test.c +++ b/tests/ahci-test.c @@ -254,6 +254,21 @@ /*** Structures ***/ +typedef struct AHCIPortState { + uint64_t fb; + uint64_t clb; +} AHCIPortState; + +typedef struct AHCIState { + QPCIDevice *dev; + void *hba_base; + uint64_t barsize; + uint32_t fingerprint; + uint32_t cap; + uint32_t cap2; + AHCIPortState port[32]; +} AHCIState; + /** * Generic FIS structure. */ @@ -343,18 +358,11 @@ typedef struct PRD { uint32_t dbc; /* Data Byte Count (0-indexed) & Interrupt Flag (bit 2^31) */ } PRD; -typedef struct HBACap { - uint32_t cap; - uint32_t cap2; -} HBACap; - /*** Globals ***/ static QGuestAllocator *guest_malloc; static QPCIBus *pcibus; -static uint64_t barsize; static char tmp_path[] = "/tmp/qtest.XXXXXX"; static bool ahci_pedantic; -static uint32_t ahci_fingerprint; /*** Macro Utilities ***/ #define BITANY(data, mask) (((data) & (mask)) != 0) @@ -364,8 +372,9 @@ static uint32_t ahci_fingerprint; #define ASSERT_BIT_CLEAR(data, mask) g_assert_cmphex((data) & (mask), ==, 0) /*** IO macros for the AHCI memory registers. ***/ -#define AHCI_READ(OFST) qpci_io_readl(ahci, hba_base + (OFST)) -#define AHCI_WRITE(OFST, VAL) qpci_io_writel(ahci, hba_base + (OFST), (VAL)) +#define AHCI_READ(OFST) qpci_io_readl(ahci->dev, ahci->hba_base + (OFST)) +#define AHCI_WRITE(OFST, VAL) qpci_io_writel(ahci->dev, \ + ahci->hba_base + (OFST), (VAL)) #define AHCI_RREG(regno) AHCI_READ(4 * (regno)) #define AHCI_WREG(regno, val) AHCI_WRITE(4 * (regno), (val)) #define AHCI_SET(regno, mask) AHCI_WREG((regno), AHCI_RREG(regno) | (mask)) @@ -385,17 +394,16 @@ static uint32_t ahci_fingerprint; /*** Function Declarations ***/ -static QPCIDevice *get_ahci_device(void); -static QPCIDevice *start_ahci_device(QPCIDevice *dev, void **hba_base); +static QPCIDevice *get_ahci_device(uint32_t *fingerprint); +static void start_ahci_device(AHCIState *ahci); static void free_ahci_device(QPCIDevice *dev); -static void ahci_test_port_spec(QPCIDevice *ahci, void *hba_base, - HBACap *hcap, uint8_t port); -static void ahci_test_pci_spec(QPCIDevice *ahci); -static void ahci_test_pci_caps(QPCIDevice *ahci, uint16_t header, +static void ahci_test_port_spec(AHCIState *ahci, uint8_t port); +static void ahci_test_pci_spec(AHCIState *ahci); +static void ahci_test_pci_caps(AHCIState *ahci, uint16_t header, uint8_t offset); -static void ahci_test_satacap(QPCIDevice *ahci, uint8_t offset); -static void ahci_test_msicap(QPCIDevice *ahci, uint8_t offset); -static void ahci_test_pmcap(QPCIDevice *ahci, uint8_t offset); +static void ahci_test_satacap(AHCIState *ahci, uint8_t offset); +static void ahci_test_msicap(AHCIState *ahci, uint8_t offset); +static void ahci_test_pmcap(AHCIState *ahci, uint8_t offset); /*** Utilities ***/ @@ -413,9 +421,10 @@ static void string_bswap16(uint16_t *s, size_t bytes) /** * Locate, verify, and return a handle to the AHCI device. */ -static QPCIDevice *get_ahci_device(void) +static QPCIDevice *get_ahci_device(uint32_t *fingerprint) { QPCIDevice *ahci; + uint32_t ahci_fingerprint; pcibus = qpci_init_pc(); @@ -433,21 +442,19 @@ static QPCIDevice *get_ahci_device(void) g_assert_not_reached(); } + *fingerprint = ahci_fingerprint; return ahci; } -static void free_ahci_device(QPCIDevice *ahci) +static void free_ahci_device(QPCIDevice *dev) { /* libqos doesn't have a function for this, so free it manually */ - g_free(ahci); + g_free(dev); if (pcibus) { qpci_free_pc(pcibus); pcibus = NULL; } - - /* Clear our cached barsize information. */ - barsize = 0; } /*** Test Setup & Teardown ***/ @@ -485,8 +492,12 @@ static void qtest_shutdown(void) /** * Start a Q35 machine and bookmark a handle to the AHCI device. */ -static QPCIDevice *ahci_boot(void) +static AHCIState *ahci_boot(void) { + AHCIState *s; + + s = g_malloc0(sizeof(AHCIState)); + qtest_boot("-drive if=none,id=drive0,file=%s,cache=writeback,serial=%s" " -M q35 " "-device ide-hd,drive=drive0 " @@ -494,15 +505,18 @@ static QPCIDevice *ahci_boot(void) tmp_path, "testdisk", "version"); /* Verify that we have an AHCI device present. */ - return get_ahci_device(); + s->dev = get_ahci_device(&s->fingerprint); + + return s; } /** * Clean up the PCI device, then terminate the QEMU instance. */ -static void ahci_shutdown(QPCIDevice *ahci) +static void ahci_shutdown(AHCIState *ahci) { - free_ahci_device(ahci); + free_ahci_device(ahci->dev); + g_free(ahci); qtest_shutdown(); } @@ -511,21 +525,21 @@ static void ahci_shutdown(QPCIDevice *ahci) /** * Start the PCI device and sanity-check default operation. */ -static void ahci_pci_enable(QPCIDevice *ahci, void **hba_base) +static void ahci_pci_enable(AHCIState *ahci) { uint8_t reg; - start_ahci_device(ahci, hba_base); + start_ahci_device(ahci); - switch (ahci_fingerprint) { + switch (ahci->fingerprint) { case AHCI_INTEL_ICH9: /* ICH9 has a register at PCI 0x92 that * acts as a master port enabler mask. */ - reg = qpci_config_readb(ahci, 0x92); + reg = qpci_config_readb(ahci->dev, 0x92); reg |= 0x3F; - qpci_config_writeb(ahci, 0x92, reg); + qpci_config_writeb(ahci->dev, 0x92, reg); /* 0...0111111b -- bit significant, ports 0-5 enabled. */ - ASSERT_BIT_SET(qpci_config_readb(ahci, 0x92), 0x3F); + ASSERT_BIT_SET(qpci_config_readb(ahci->dev, 0x92), 0x3F); break; } @@ -534,15 +548,14 @@ static void ahci_pci_enable(QPCIDevice *ahci, void **hba_base) /** * Map BAR5/ABAR, and engage the PCI device. */ -static QPCIDevice *start_ahci_device(QPCIDevice *ahci, void **hba_base) +static void start_ahci_device(AHCIState *ahci) { /* Map AHCI's ABAR (BAR5) */ - *hba_base = qpci_iomap(ahci, 5, &barsize); + ahci->hba_base = qpci_iomap(ahci->dev, 5, &ahci->barsize); + g_assert(ahci->hba_base != 0); /* turns on pci.cmd.iose, pci.cmd.mse and pci.cmd.bme */ - qpci_device_enable(ahci); - - return ahci; + qpci_device_enable(ahci->dev); } /** @@ -550,7 +563,7 @@ static QPCIDevice *start_ahci_device(QPCIDevice *ahci, void **hba_base) * Initialize and start any ports with devices attached. * Bring the HBA into the idle state. */ -static void ahci_hba_enable(QPCIDevice *ahci, void *hba_base) +static void ahci_hba_enable(AHCIState *ahci) { /* Bits of interest in this section: * GHC.AE Global Host Control / AHCI Enable @@ -561,15 +574,11 @@ static void ahci_hba_enable(QPCIDevice *ahci, void *hba_base) * PxCMD.FR "FIS Receive Running" * PxCMD.CR "Command List Running" */ - - g_assert(ahci != NULL); - g_assert(hba_base != NULL); - - uint32_t reg, ports_impl, clb, fb; + uint32_t reg, ports_impl; uint16_t i; uint8_t num_cmd_slots; - g_assert(hba_base != 0); + g_assert(ahci != NULL); /* Set GHC.AE to 1 */ AHCI_SET(AHCI_GHC, AHCI_GHC_AE); @@ -610,16 +619,16 @@ static void ahci_hba_enable(QPCIDevice *ahci, void *hba_base) /* Allocate Memory for the Command List Buffer & FIS Buffer */ /* PxCLB space ... 0x20 per command, as in 4.2.2 p 36 */ - clb = guest_alloc(guest_malloc, num_cmd_slots * 0x20); - g_test_message("CLB: 0x%08x", clb); - PX_WREG(i, AHCI_PX_CLB, clb); - g_assert_cmphex(clb, ==, PX_RREG(i, AHCI_PX_CLB)); + ahci->port[i].clb = guest_alloc(guest_malloc, num_cmd_slots * 0x20); + g_test_message("CLB: 0x%08lx", ahci->port[i].clb); + PX_WREG(i, AHCI_PX_CLB, ahci->port[i].clb); + g_assert_cmphex(ahci->port[i].clb, ==, PX_RREG(i, AHCI_PX_CLB)); /* PxFB space ... 0x100, as in 4.2.1 p 35 */ - fb = guest_alloc(guest_malloc, 0x100); - g_test_message("FB: 0x%08x", fb); - PX_WREG(i, AHCI_PX_FB, fb); - g_assert_cmphex(fb, ==, PX_RREG(i, AHCI_PX_FB)); + ahci->port[i].fb = guest_alloc(guest_malloc, 0x100); + g_test_message("FB: 0x%08lx", ahci->port[i].fb); + PX_WREG(i, AHCI_PX_FB, ahci->port[i].fb); + g_assert_cmphex(ahci->port[i].fb, ==, PX_RREG(i, AHCI_PX_FB)); /* Clear PxSERR, PxIS, then IS.IPS[x] by writing '1's. */ PX_WREG(i, AHCI_PX_SERR, 0xFFFFFFFF); @@ -684,14 +693,14 @@ static void ahci_hba_enable(QPCIDevice *ahci, void *hba_base) /** * Implementation for test_pci_spec. Ensures PCI configuration space is sane. */ -static void ahci_test_pci_spec(QPCIDevice *ahci) +static void ahci_test_pci_spec(AHCIState *ahci) { uint8_t datab; uint16_t data; uint32_t datal; /* Most of these bits should start cleared until we turn them on. */ - data = qpci_config_readw(ahci, PCI_COMMAND); + data = qpci_config_readw(ahci->dev, PCI_COMMAND); ASSERT_BIT_CLEAR(data, PCI_COMMAND_MEMORY); ASSERT_BIT_CLEAR(data, PCI_COMMAND_MASTER); ASSERT_BIT_CLEAR(data, PCI_COMMAND_SPECIAL); /* Reserved */ @@ -703,7 +712,7 @@ static void ahci_test_pci_spec(QPCIDevice *ahci) ASSERT_BIT_CLEAR(data, PCI_COMMAND_INTX_DISABLE); ASSERT_BIT_CLEAR(data, 0xF800); /* Reserved */ - data = qpci_config_readw(ahci, PCI_STATUS); + data = qpci_config_readw(ahci->dev, PCI_STATUS); ASSERT_BIT_CLEAR(data, 0x01 | 0x02 | 0x04); /* Reserved */ ASSERT_BIT_CLEAR(data, PCI_STATUS_INTERRUPT); ASSERT_BIT_SET(data, PCI_STATUS_CAP_LIST); /* must be set */ @@ -716,7 +725,7 @@ static void ahci_test_pci_spec(QPCIDevice *ahci) ASSERT_BIT_CLEAR(data, PCI_STATUS_DETECTED_PARITY); /* RID occupies the low byte, CCs occupy the high three. */ - datal = qpci_config_readl(ahci, PCI_CLASS_REVISION); + datal = qpci_config_readl(ahci->dev, PCI_CLASS_REVISION); if (ahci_pedantic) { /* AHCI 1.3 specifies that at-boot, the RID should reset to 0x00, * Though in practice this is likely seldom true. */ @@ -739,40 +748,40 @@ static void ahci_test_pci_spec(QPCIDevice *ahci) g_assert_not_reached(); } - datab = qpci_config_readb(ahci, PCI_CACHE_LINE_SIZE); + datab = qpci_config_readb(ahci->dev, PCI_CACHE_LINE_SIZE); g_assert_cmphex(datab, ==, 0); - datab = qpci_config_readb(ahci, PCI_LATENCY_TIMER); + datab = qpci_config_readb(ahci->dev, PCI_LATENCY_TIMER); g_assert_cmphex(datab, ==, 0); /* Only the bottom 7 bits must be off. */ - datab = qpci_config_readb(ahci, PCI_HEADER_TYPE); + datab = qpci_config_readb(ahci->dev, PCI_HEADER_TYPE); ASSERT_BIT_CLEAR(datab, 0x7F); /* BIST is optional, but the low 7 bits must always start off regardless. */ - datab = qpci_config_readb(ahci, PCI_BIST); + datab = qpci_config_readb(ahci->dev, PCI_BIST); ASSERT_BIT_CLEAR(datab, 0x7F); /* BARS 0-4 do not have a boot spec, but ABAR/BAR5 must be clean. */ - datal = qpci_config_readl(ahci, PCI_BASE_ADDRESS_5); + datal = qpci_config_readl(ahci->dev, PCI_BASE_ADDRESS_5); g_assert_cmphex(datal, ==, 0); - qpci_config_writel(ahci, PCI_BASE_ADDRESS_5, 0xFFFFFFFF); - datal = qpci_config_readl(ahci, PCI_BASE_ADDRESS_5); + qpci_config_writel(ahci->dev, PCI_BASE_ADDRESS_5, 0xFFFFFFFF); + datal = qpci_config_readl(ahci->dev, PCI_BASE_ADDRESS_5); /* ABAR must be 32-bit, memory mapped, non-prefetchable and * must be >= 512 bytes. To that end, bits 0-8 must be off. */ ASSERT_BIT_CLEAR(datal, 0xFF); /* Capability list MUST be present, */ - datal = qpci_config_readl(ahci, PCI_CAPABILITY_LIST); + datal = qpci_config_readl(ahci->dev, PCI_CAPABILITY_LIST); /* But these bits are reserved. */ ASSERT_BIT_CLEAR(datal, ~0xFF); g_assert_cmphex(datal, !=, 0); /* Check specification adherence for capability extenstions. */ - data = qpci_config_readw(ahci, datal); + data = qpci_config_readw(ahci->dev, datal); - switch (ahci_fingerprint) { + switch (ahci->fingerprint) { case AHCI_INTEL_ICH9: /* Intel ICH9 Family Datasheet 14.1.19 p.550 */ g_assert_cmphex((data & 0xFF), ==, PCI_CAP_ID_MSI); @@ -785,18 +794,18 @@ static void ahci_test_pci_spec(QPCIDevice *ahci) ahci_test_pci_caps(ahci, data, (uint8_t)datal); /* Reserved. */ - datal = qpci_config_readl(ahci, PCI_CAPABILITY_LIST + 4); + datal = qpci_config_readl(ahci->dev, PCI_CAPABILITY_LIST + 4); g_assert_cmphex(datal, ==, 0); /* IPIN might vary, but ILINE must be off. */ - datab = qpci_config_readb(ahci, PCI_INTERRUPT_LINE); + datab = qpci_config_readb(ahci->dev, PCI_INTERRUPT_LINE); g_assert_cmphex(datab, ==, 0); } /** * Test PCI capabilities for AHCI specification adherence. */ -static void ahci_test_pci_caps(QPCIDevice *ahci, uint16_t header, +static void ahci_test_pci_caps(AHCIState *ahci, uint16_t header, uint8_t offset) { uint8_t cid = header & 0xFF; @@ -820,14 +829,14 @@ static void ahci_test_pci_caps(QPCIDevice *ahci, uint16_t header, } if (next) { - ahci_test_pci_caps(ahci, qpci_config_readw(ahci, next), next); + ahci_test_pci_caps(ahci, qpci_config_readw(ahci->dev, next), next); } } /** * Test SATA PCI capabilitity for AHCI specification adherence. */ -static void ahci_test_satacap(QPCIDevice *ahci, uint8_t offset) +static void ahci_test_satacap(AHCIState *ahci, uint8_t offset) { uint16_t dataw; uint32_t datal; @@ -835,11 +844,11 @@ static void ahci_test_satacap(QPCIDevice *ahci, uint8_t offset) g_test_message("Verifying SATACAP"); /* Assert that the SATACAP version is 1.0, And reserved bits are empty. */ - dataw = qpci_config_readw(ahci, offset + 2); + dataw = qpci_config_readw(ahci->dev, offset + 2); g_assert_cmphex(dataw, ==, 0x10); /* Grab the SATACR1 register. */ - datal = qpci_config_readw(ahci, offset + 4); + datal = qpci_config_readw(ahci->dev, offset + 4); switch (datal & 0x0F) { case 0x04: /* BAR0 */ @@ -862,30 +871,29 @@ static void ahci_test_satacap(QPCIDevice *ahci, uint8_t offset) /** * Test MSI PCI capability for AHCI specification adherence. */ -static void ahci_test_msicap(QPCIDevice *ahci, uint8_t offset) +static void ahci_test_msicap(AHCIState *ahci, uint8_t offset) { uint16_t dataw; uint32_t datal; g_test_message("Verifying MSICAP"); - dataw = qpci_config_readw(ahci, offset + PCI_MSI_FLAGS); + dataw = qpci_config_readw(ahci->dev, offset + PCI_MSI_FLAGS); ASSERT_BIT_CLEAR(dataw, PCI_MSI_FLAGS_ENABLE); ASSERT_BIT_CLEAR(dataw, PCI_MSI_FLAGS_QSIZE); ASSERT_BIT_CLEAR(dataw, PCI_MSI_FLAGS_RESERVED); - datal = qpci_config_readl(ahci, offset + PCI_MSI_ADDRESS_LO); + datal = qpci_config_readl(ahci->dev, offset + PCI_MSI_ADDRESS_LO); g_assert_cmphex(datal, ==, 0); - if (dataw & PCI_MSI_FLAGS_64BIT) { g_test_message("MSICAP is 64bit"); - datal = qpci_config_readl(ahci, offset + PCI_MSI_ADDRESS_HI); + datal = qpci_config_readl(ahci->dev, offset + PCI_MSI_ADDRESS_HI); g_assert_cmphex(datal, ==, 0); - dataw = qpci_config_readw(ahci, offset + PCI_MSI_DATA_64); + dataw = qpci_config_readw(ahci->dev, offset + PCI_MSI_DATA_64); g_assert_cmphex(dataw, ==, 0); } else { g_test_message("MSICAP is 32bit"); - dataw = qpci_config_readw(ahci, offset + PCI_MSI_DATA_32); + dataw = qpci_config_readw(ahci->dev, offset + PCI_MSI_DATA_32); g_assert_cmphex(dataw, ==, 0); } } @@ -893,36 +901,34 @@ static void ahci_test_msicap(QPCIDevice *ahci, uint8_t offset) /** * Test Power Management PCI capability for AHCI specification adherence. */ -static void ahci_test_pmcap(QPCIDevice *ahci, uint8_t offset) +static void ahci_test_pmcap(AHCIState *ahci, uint8_t offset) { uint16_t dataw; g_test_message("Verifying PMCAP"); - dataw = qpci_config_readw(ahci, offset + PCI_PM_PMC); + dataw = qpci_config_readw(ahci->dev, offset + PCI_PM_PMC); ASSERT_BIT_CLEAR(dataw, PCI_PM_CAP_PME_CLOCK); ASSERT_BIT_CLEAR(dataw, PCI_PM_CAP_RESERVED); ASSERT_BIT_CLEAR(dataw, PCI_PM_CAP_D1); ASSERT_BIT_CLEAR(dataw, PCI_PM_CAP_D2); - dataw = qpci_config_readw(ahci, offset + PCI_PM_CTRL); + dataw = qpci_config_readw(ahci->dev, offset + PCI_PM_CTRL); ASSERT_BIT_CLEAR(dataw, PCI_PM_CTRL_STATE_MASK); ASSERT_BIT_CLEAR(dataw, PCI_PM_CTRL_RESERVED); ASSERT_BIT_CLEAR(dataw, PCI_PM_CTRL_DATA_SEL_MASK); ASSERT_BIT_CLEAR(dataw, PCI_PM_CTRL_DATA_SCALE_MASK); } -static void ahci_test_hba_spec(QPCIDevice *ahci, void *hba_base) +static void ahci_test_hba_spec(AHCIState *ahci) { - HBACap hcap; unsigned i; - uint32_t cap, cap2, reg; + uint32_t reg; uint32_t ports; uint8_t nports_impl; uint8_t maxports; - g_assert(ahci != 0); - g_assert(hba_base != 0); + g_assert(ahci != NULL); /* * Note that the AHCI spec does expect the BIOS to set up a few things: @@ -945,15 +951,15 @@ static void ahci_test_hba_spec(QPCIDevice *ahci, void *hba_base) */ /* 1 CAP - Capabilities Register */ - cap = AHCI_RREG(AHCI_CAP); - ASSERT_BIT_CLEAR(cap, AHCI_CAP_RESERVED); + ahci->cap = AHCI_RREG(AHCI_CAP); + ASSERT_BIT_CLEAR(ahci->cap, AHCI_CAP_RESERVED); /* 2 GHC - Global Host Control */ reg = AHCI_RREG(AHCI_GHC); ASSERT_BIT_CLEAR(reg, AHCI_GHC_HR); ASSERT_BIT_CLEAR(reg, AHCI_GHC_IE); ASSERT_BIT_CLEAR(reg, AHCI_GHC_MRSM); - if (BITSET(cap, AHCI_CAP_SAM)) { + if (BITSET(ahci->cap, AHCI_CAP_SAM)) { g_test_message("Supports AHCI-Only Mode: GHC_AE is Read-Only."); ASSERT_BIT_SET(reg, AHCI_GHC_AE); } else { @@ -971,13 +977,13 @@ static void ahci_test_hba_spec(QPCIDevice *ahci, void *hba_base) g_assert_cmphex(ports, !=, 0); /* Ports Implemented must be <= Number of Ports. */ nports_impl = ctpopl(ports); - g_assert_cmpuint(((AHCI_CAP_NP & cap) + 1), >=, nports_impl); + g_assert_cmpuint(((AHCI_CAP_NP & ahci->cap) + 1), >=, nports_impl); - g_assert_cmphex(barsize, >, 0); /* Ports must be within the proper range. Given a mapping of SIZE, * 256 bytes are used for global HBA control, and the rest is used * for ports data, at 0x80 bytes each. */ - maxports = (barsize - HBA_DATA_REGION_SIZE) / HBA_PORT_DATA_SIZE; + g_assert_cmphex(ahci->barsize, >, 0); + maxports = (ahci->barsize - HBA_DATA_REGION_SIZE) / HBA_PORT_DATA_SIZE; /* e.g, 30 ports for 4K of memory. (4096 - 256) / 128 = 30 */ g_assert_cmphex((reg >> maxports), ==, 0); @@ -996,7 +1002,7 @@ static void ahci_test_hba_spec(QPCIDevice *ahci, void *hba_base) /* 6 Command Completion Coalescing Control: depends on CAP.CCCS. */ reg = AHCI_RREG(AHCI_CCCCTL); - if (BITSET(cap, AHCI_CAP_CCCS)) { + if (BITSET(ahci->cap, AHCI_CAP_CCCS)) { ASSERT_BIT_CLEAR(reg, AHCI_CCCCTL_EN); ASSERT_BIT_CLEAR(reg, AHCI_CCCCTL_RESERVED); ASSERT_BIT_SET(reg, AHCI_CCCCTL_CC); @@ -1012,13 +1018,13 @@ static void ahci_test_hba_spec(QPCIDevice *ahci, void *hba_base) /* 8 EM_LOC */ reg = AHCI_RREG(AHCI_EMLOC); - if (BITCLR(cap, AHCI_CAP_EMS)) { + if (BITCLR(ahci->cap, AHCI_CAP_EMS)) { g_assert_cmphex(reg, ==, 0); } /* 9 EM_CTL */ reg = AHCI_RREG(AHCI_EMCTL); - if (BITSET(cap, AHCI_CAP_EMS)) { + if (BITSET(ahci->cap, AHCI_CAP_EMS)) { ASSERT_BIT_CLEAR(reg, AHCI_EMCTL_STSMR); ASSERT_BIT_CLEAR(reg, AHCI_EMCTL_CTLTM); ASSERT_BIT_CLEAR(reg, AHCI_EMCTL_CTLRST); @@ -1028,8 +1034,8 @@ static void ahci_test_hba_spec(QPCIDevice *ahci, void *hba_base) } /* 10 CAP2 -- Capabilities Extended */ - cap2 = AHCI_RREG(AHCI_CAP2); - ASSERT_BIT_CLEAR(cap2, AHCI_CAP2_RESERVED); + ahci->cap2 = AHCI_RREG(AHCI_CAP2); + ASSERT_BIT_CLEAR(ahci->cap2, AHCI_CAP2_RESERVED); /* 11 BOHC -- Bios/OS Handoff Control */ reg = AHCI_RREG(AHCI_BOHC); @@ -1043,7 +1049,7 @@ static void ahci_test_hba_spec(QPCIDevice *ahci, void *hba_base) } /* 24 -- 39: NVMHCI */ - if (BITCLR(cap2, AHCI_CAP2_NVMP)) { + if (BITCLR(ahci->cap2, AHCI_CAP2_NVMP)) { g_test_message("Verifying HBA/NVMHCI area is empty."); for (i = AHCI_NVMHCI; i < AHCI_VENDOR; ++i) { reg = AHCI_RREG(i); @@ -1059,12 +1065,10 @@ static void ahci_test_hba_spec(QPCIDevice *ahci, void *hba_base) } /* 64 -- XX: Port Space */ - hcap.cap = cap; - hcap.cap2 = cap2; for (i = 0; ports || (i < maxports); ports >>= 1, ++i) { if (BITSET(ports, 0x1)) { g_test_message("Testing port %u for spec", i); - ahci_test_port_spec(ahci, hba_base, &hcap, i); + ahci_test_port_spec(ahci, i); } else { uint16_t j; uint16_t low = AHCI_PORTS + (32 * i); @@ -1083,8 +1087,7 @@ static void ahci_test_hba_spec(QPCIDevice *ahci, void *hba_base) /** * Test the memory space for one port for specification adherence. */ -static void ahci_test_port_spec(QPCIDevice *ahci, void *hba_base, - HBACap *hcap, uint8_t port) +static void ahci_test_port_spec(AHCIState *ahci, uint8_t port) { uint32_t reg; unsigned i; @@ -1094,7 +1097,7 @@ static void ahci_test_port_spec(QPCIDevice *ahci, void *hba_base, ASSERT_BIT_CLEAR(reg, AHCI_PX_CLB_RESERVED); /* (1) CLBU */ - if (BITCLR(hcap->cap, AHCI_CAP_S64A)) { + if (BITCLR(ahci->cap, AHCI_CAP_S64A)) { reg = PX_RREG(port, AHCI_PX_CLBU); g_assert_cmphex(reg, ==, 0); } @@ -1104,7 +1107,7 @@ static void ahci_test_port_spec(QPCIDevice *ahci, void *hba_base, ASSERT_BIT_CLEAR(reg, AHCI_PX_FB_RESERVED); /* (3) FBU */ - if (BITCLR(hcap->cap, AHCI_CAP_S64A)) { + if (BITCLR(ahci->cap, AHCI_CAP_S64A)) { reg = PX_RREG(port, AHCI_PX_FBU); g_assert_cmphex(reg, ==, 0); } @@ -1140,7 +1143,7 @@ static void ahci_test_port_spec(QPCIDevice *ahci, void *hba_base, ASSERT_BIT_CLEAR(reg, AHCI_PX_CMD_MPSS); } /* If we do not support MPS, MPSS and MPSP must be off. */ - if (BITCLR(hcap->cap, AHCI_CAP_SMPS)) { + if (BITCLR(ahci->cap, AHCI_CAP_SMPS)) { ASSERT_BIT_CLEAR(reg, AHCI_PX_CMD_MPSS); ASSERT_BIT_CLEAR(reg, AHCI_PX_CMD_MPSP); } @@ -1151,7 +1154,7 @@ static void ahci_test_port_spec(QPCIDevice *ahci, void *hba_base, /* HPCP and ESP cannot both be active. */ g_assert_false(BITSET(reg, AHCI_PX_CMD_HPCP | AHCI_PX_CMD_ESP)); /* If CAP.FBSS is not set, FBSCP must not be set. */ - if (BITCLR(hcap->cap, AHCI_CAP_FBSS)) { + if (BITCLR(ahci->cap, AHCI_CAP_FBSS)) { ASSERT_BIT_CLEAR(reg, AHCI_PX_CMD_FBSCP); } @@ -1211,7 +1214,7 @@ static void ahci_test_port_spec(QPCIDevice *ahci, void *hba_base, ASSERT_BIT_CLEAR(reg, AHCI_PX_FBS_DEV); ASSERT_BIT_CLEAR(reg, AHCI_PX_FBS_DWE); ASSERT_BIT_CLEAR(reg, AHCI_PX_FBS_RESERVED); - if (BITSET(hcap->cap, AHCI_CAP_FBSS)) { + if (BITSET(ahci->cap, AHCI_CAP_FBSS)) { /* if Port-Multiplier FIS-based switching avail, ADO must >= 2 */ g_assert((reg & AHCI_PX_FBS_ADO) >> ctzl(AHCI_PX_FBS_ADO) >= 2); } @@ -1235,20 +1238,19 @@ static void ahci_test_port_spec(QPCIDevice *ahci, void *hba_base, * Utilizing an initialized AHCI HBA, issue an IDENTIFY command to the first * device we see, then read and check the response. */ -static void ahci_test_identify(QPCIDevice *ahci, void *hba_base) +static void ahci_test_identify(AHCIState *ahci) { RegD2HFIS *d2h = g_malloc0(0x20); RegD2HFIS *pio = g_malloc0(0x20); RegH2DFIS fis; AHCICommand cmd; PRD prd; - uint32_t ports, reg, clb, table, fb, data_ptr; + uint32_t ports, reg, table, data_ptr; uint16_t buff[256]; unsigned i; int rc; g_assert(ahci != NULL); - g_assert(hba_base != NULL); /* We need to: * (1) Create a Command Table Buffer and update the Command List Slot #0 @@ -1289,9 +1291,8 @@ static void ahci_test_identify(QPCIDevice *ahci, void *hba_base) g_assert_cmphex(PX_RREG(i, AHCI_PX_IS), ==, 0); /* Wipe the FIS-Recieve Buffer */ - fb = PX_RREG(i, AHCI_PX_FB); - g_assert_cmphex(fb, !=, 0); - qmemset(fb, 0x00, 0x100); + g_assert_cmphex(ahci->port[i].fb, !=, 0); + qmemset(ahci->port[i].fb, 0x00, 0x100); /* Create a Command Table buffer. 0x80 is the smallest with a PRDTL of 0. */ /* We need at least one PRD, so round up to the nearest 0x80 multiple. */ @@ -1303,13 +1304,9 @@ static void ahci_test_identify(QPCIDevice *ahci, void *hba_base) data_ptr = guest_alloc(guest_malloc, 512); g_assert(data_ptr); - /* Grab the Command List Buffer pointer */ - clb = PX_RREG(i, AHCI_PX_CLB); - g_assert(clb); - /* Copy the existing Command #0 structure from the CLB into local memory, * and build a new command #0. */ - memread(clb, &cmd, sizeof(cmd)); + memread(ahci->port[i].clb, &cmd, sizeof(cmd)); cmd.b1 = 5; /* reg_h2d_fis is 5 double-words long */ cmd.b2 = 0x04; /* clear PxTFD.STS.BSY when done */ cmd.prdtl = cpu_to_le16(1); /* One PRD table entry. */ @@ -1341,7 +1338,7 @@ static void ahci_test_identify(QPCIDevice *ahci, void *hba_base) memwrite(table + 0x80, &prd, sizeof(prd)); /* Commit Command #0, pointing to the Table, to the Command List Buffer. */ - memwrite(clb, &cmd, sizeof(cmd)); + memwrite(ahci->port[i].clb, &cmd, sizeof(cmd)); /* Everything is in place, but we haven't given the go-ahead yet. */ g_assert_cmphex(PX_RREG(i, AHCI_PX_IS), ==, 0); @@ -1371,12 +1368,12 @@ static void ahci_test_identify(QPCIDevice *ahci, void *hba_base) ASSERT_BIT_CLEAR(reg, AHCI_PX_TFD_ERR); /* Investigate CMD #0, assert that we read 512 bytes */ - memread(clb, &cmd, sizeof(cmd)); + memread(ahci->port[i].clb, &cmd, sizeof(cmd)); g_assert_cmphex(512, ==, le32_to_cpu(cmd.prdbc)); /* Investigate FIS responses */ - memread(fb + 0x20, pio, 0x20); - memread(fb + 0x40, d2h, 0x20); + memread(ahci->port[i].fb + 0x20, pio, 0x20); + memread(ahci->port[i].fb + 0x40, d2h, 0x20); g_assert_cmphex(pio->fis_type, ==, 0x5f); g_assert_cmphex(d2h->fis_type, ==, 0x34); g_assert_cmphex(pio->flags, ==, d2h->flags); @@ -1420,7 +1417,7 @@ static void ahci_test_identify(QPCIDevice *ahci, void *hba_base) */ static void test_sanity(void) { - QPCIDevice *ahci; + AHCIState *ahci; ahci = ahci_boot(); ahci_shutdown(ahci); } @@ -1431,7 +1428,7 @@ static void test_sanity(void) */ static void test_pci_spec(void) { - QPCIDevice *ahci; + AHCIState *ahci; ahci = ahci_boot(); ahci_test_pci_spec(ahci); ahci_shutdown(ahci); @@ -1443,10 +1440,9 @@ static void test_pci_spec(void) */ static void test_pci_enable(void) { - QPCIDevice *ahci; - void *hba_base; + AHCIState *ahci; ahci = ahci_boot(); - ahci_pci_enable(ahci, &hba_base); + ahci_pci_enable(ahci); ahci_shutdown(ahci); } @@ -1456,12 +1452,11 @@ static void test_pci_enable(void) */ static void test_hba_spec(void) { - QPCIDevice *ahci; - void *hba_base; + AHCIState *ahci; ahci = ahci_boot(); - ahci_pci_enable(ahci, &hba_base); - ahci_test_hba_spec(ahci, hba_base); + ahci_pci_enable(ahci); + ahci_test_hba_spec(ahci); ahci_shutdown(ahci); } @@ -1471,12 +1466,11 @@ static void test_hba_spec(void) */ static void test_hba_enable(void) { - QPCIDevice *ahci; - void *hba_base; + AHCIState *ahci; ahci = ahci_boot(); - ahci_pci_enable(ahci, &hba_base); - ahci_hba_enable(ahci, hba_base); + ahci_pci_enable(ahci); + ahci_hba_enable(ahci); ahci_shutdown(ahci); } @@ -1486,13 +1480,12 @@ static void test_hba_enable(void) */ static void test_identify(void) { - QPCIDevice *ahci; - void *hba_base; + AHCIState *ahci; ahci = ahci_boot(); - ahci_pci_enable(ahci, &hba_base); - ahci_hba_enable(ahci, hba_base); - ahci_test_identify(ahci, hba_base); + ahci_pci_enable(ahci); + ahci_hba_enable(ahci); + ahci_test_identify(ahci); ahci_shutdown(ahci); } -- 1.9.3