11cf4323eSThomas Huth #ifndef LIBQOS_AHCI_H 21cf4323eSThomas Huth #define LIBQOS_AHCI_H 31cf4323eSThomas Huth 41cf4323eSThomas Huth /* 51cf4323eSThomas Huth * AHCI qtest library functions and definitions 61cf4323eSThomas Huth * 71cf4323eSThomas Huth * Copyright (c) 2014 John Snow <jsnow@redhat.com> 81cf4323eSThomas Huth * 91cf4323eSThomas Huth * Permission is hereby granted, free of charge, to any person obtaining a copy 101cf4323eSThomas Huth * of this software and associated documentation files (the "Software"), to deal 111cf4323eSThomas Huth * in the Software without restriction, including without limitation the rights 121cf4323eSThomas Huth * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 131cf4323eSThomas Huth * copies of the Software, and to permit persons to whom the Software is 141cf4323eSThomas Huth * furnished to do so, subject to the following conditions: 151cf4323eSThomas Huth * 161cf4323eSThomas Huth * The above copyright notice and this permission notice shall be included in 171cf4323eSThomas Huth * all copies or substantial portions of the Software. 181cf4323eSThomas Huth * 191cf4323eSThomas Huth * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 201cf4323eSThomas Huth * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 211cf4323eSThomas Huth * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 221cf4323eSThomas Huth * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 231cf4323eSThomas Huth * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 241cf4323eSThomas Huth * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 251cf4323eSThomas Huth * THE SOFTWARE. 261cf4323eSThomas Huth */ 271cf4323eSThomas Huth 281cf4323eSThomas Huth #include "libqos/libqos.h" 291cf4323eSThomas Huth #include "libqos/pci.h" 301cf4323eSThomas Huth #include "libqos/malloc-pc.h" 311cf4323eSThomas Huth 321cf4323eSThomas Huth /*** Supplementary PCI Config Space IDs & Masks ***/ 331cf4323eSThomas Huth #define PCI_DEVICE_ID_INTEL_Q35_AHCI (0x2922) 341cf4323eSThomas Huth #define PCI_MSI_FLAGS_RESERVED (0xFF00) 351cf4323eSThomas Huth #define PCI_PM_CTRL_RESERVED (0xFC) 361cf4323eSThomas Huth #define PCI_BCC(REG32) ((REG32) >> 24) 371cf4323eSThomas Huth #define PCI_PI(REG32) (((REG32) >> 8) & 0xFF) 381cf4323eSThomas Huth #define PCI_SCC(REG32) (((REG32) >> 16) & 0xFF) 391cf4323eSThomas Huth 401cf4323eSThomas Huth /*** Recognized AHCI Device Types ***/ 411cf4323eSThomas Huth #define AHCI_INTEL_ICH9 (PCI_DEVICE_ID_INTEL_Q35_AHCI << 16 | \ 421cf4323eSThomas Huth PCI_VENDOR_ID_INTEL) 431cf4323eSThomas Huth 441cf4323eSThomas Huth /*** AHCI/HBA Register Offsets and Bitmasks ***/ 451cf4323eSThomas Huth #define AHCI_CAP (0) 461cf4323eSThomas Huth #define AHCI_CAP_NP (0x1F) 471cf4323eSThomas Huth #define AHCI_CAP_SXS (0x20) 481cf4323eSThomas Huth #define AHCI_CAP_EMS (0x40) 491cf4323eSThomas Huth #define AHCI_CAP_CCCS (0x80) 501cf4323eSThomas Huth #define AHCI_CAP_NCS (0x1F00) 511cf4323eSThomas Huth #define AHCI_CAP_PSC (0x2000) 521cf4323eSThomas Huth #define AHCI_CAP_SSC (0x4000) 531cf4323eSThomas Huth #define AHCI_CAP_PMD (0x8000) 541cf4323eSThomas Huth #define AHCI_CAP_FBSS (0x10000) 551cf4323eSThomas Huth #define AHCI_CAP_SPM (0x20000) 561cf4323eSThomas Huth #define AHCI_CAP_SAM (0x40000) 571cf4323eSThomas Huth #define AHCI_CAP_RESERVED (0x80000) 581cf4323eSThomas Huth #define AHCI_CAP_ISS (0xF00000) 591cf4323eSThomas Huth #define AHCI_CAP_SCLO (0x1000000) 601cf4323eSThomas Huth #define AHCI_CAP_SAL (0x2000000) 611cf4323eSThomas Huth #define AHCI_CAP_SALP (0x4000000) 621cf4323eSThomas Huth #define AHCI_CAP_SSS (0x8000000) 631cf4323eSThomas Huth #define AHCI_CAP_SMPS (0x10000000) 641cf4323eSThomas Huth #define AHCI_CAP_SSNTF (0x20000000) 651cf4323eSThomas Huth #define AHCI_CAP_SNCQ (0x40000000) 661cf4323eSThomas Huth #define AHCI_CAP_S64A (0x80000000) 671cf4323eSThomas Huth 681cf4323eSThomas Huth #define AHCI_GHC (1) 691cf4323eSThomas Huth #define AHCI_GHC_HR (0x01) 701cf4323eSThomas Huth #define AHCI_GHC_IE (0x02) 711cf4323eSThomas Huth #define AHCI_GHC_MRSM (0x04) 721cf4323eSThomas Huth #define AHCI_GHC_RESERVED (0x7FFFFFF8) 731cf4323eSThomas Huth #define AHCI_GHC_AE (0x80000000) 741cf4323eSThomas Huth 751cf4323eSThomas Huth #define AHCI_IS (2) 761cf4323eSThomas Huth #define AHCI_PI (3) 771cf4323eSThomas Huth #define AHCI_VS (4) 781cf4323eSThomas Huth 791cf4323eSThomas Huth #define AHCI_CCCCTL (5) 801cf4323eSThomas Huth #define AHCI_CCCCTL_EN (0x01) 811cf4323eSThomas Huth #define AHCI_CCCCTL_RESERVED (0x06) 821cf4323eSThomas Huth #define AHCI_CCCCTL_CC (0xFF00) 831cf4323eSThomas Huth #define AHCI_CCCCTL_TV (0xFFFF0000) 841cf4323eSThomas Huth 851cf4323eSThomas Huth #define AHCI_CCCPORTS (6) 861cf4323eSThomas Huth #define AHCI_EMLOC (7) 871cf4323eSThomas Huth 881cf4323eSThomas Huth #define AHCI_EMCTL (8) 891cf4323eSThomas Huth #define AHCI_EMCTL_STSMR (0x01) 901cf4323eSThomas Huth #define AHCI_EMCTL_CTLTM (0x100) 911cf4323eSThomas Huth #define AHCI_EMCTL_CTLRST (0x200) 921cf4323eSThomas Huth #define AHCI_EMCTL_RESERVED (0xF0F0FCFE) 931cf4323eSThomas Huth 941cf4323eSThomas Huth #define AHCI_CAP2 (9) 951cf4323eSThomas Huth #define AHCI_CAP2_BOH (0x01) 961cf4323eSThomas Huth #define AHCI_CAP2_NVMP (0x02) 971cf4323eSThomas Huth #define AHCI_CAP2_APST (0x04) 981cf4323eSThomas Huth #define AHCI_CAP2_RESERVED (0xFFFFFFF8) 991cf4323eSThomas Huth 1001cf4323eSThomas Huth #define AHCI_BOHC (10) 1011cf4323eSThomas Huth #define AHCI_RESERVED (11) 1021cf4323eSThomas Huth #define AHCI_NVMHCI (24) 1031cf4323eSThomas Huth #define AHCI_VENDOR (40) 1041cf4323eSThomas Huth #define AHCI_PORTS (64) 1051cf4323eSThomas Huth 1061cf4323eSThomas Huth /*** Port Memory Offsets & Bitmasks ***/ 1071cf4323eSThomas Huth #define AHCI_PX_CLB (0) 1081cf4323eSThomas Huth #define AHCI_PX_CLB_RESERVED (0x1FF) 1091cf4323eSThomas Huth 1101cf4323eSThomas Huth #define AHCI_PX_CLBU (1) 1111cf4323eSThomas Huth 1121cf4323eSThomas Huth #define AHCI_PX_FB (2) 1131cf4323eSThomas Huth #define AHCI_PX_FB_RESERVED (0xFF) 1141cf4323eSThomas Huth 1151cf4323eSThomas Huth #define AHCI_PX_FBU (3) 1161cf4323eSThomas Huth 1171cf4323eSThomas Huth #define AHCI_PX_IS (4) 1181cf4323eSThomas Huth #define AHCI_PX_IS_DHRS (0x1) 1191cf4323eSThomas Huth #define AHCI_PX_IS_PSS (0x2) 1201cf4323eSThomas Huth #define AHCI_PX_IS_DSS (0x4) 1211cf4323eSThomas Huth #define AHCI_PX_IS_SDBS (0x8) 1221cf4323eSThomas Huth #define AHCI_PX_IS_UFS (0x10) 1231cf4323eSThomas Huth #define AHCI_PX_IS_DPS (0x20) 1241cf4323eSThomas Huth #define AHCI_PX_IS_PCS (0x40) 1251cf4323eSThomas Huth #define AHCI_PX_IS_DMPS (0x80) 1261cf4323eSThomas Huth #define AHCI_PX_IS_RESERVED (0x23FFF00) 1271cf4323eSThomas Huth #define AHCI_PX_IS_PRCS (0x400000) 1281cf4323eSThomas Huth #define AHCI_PX_IS_IPMS (0x800000) 1291cf4323eSThomas Huth #define AHCI_PX_IS_OFS (0x1000000) 1301cf4323eSThomas Huth #define AHCI_PX_IS_INFS (0x4000000) 1311cf4323eSThomas Huth #define AHCI_PX_IS_IFS (0x8000000) 1321cf4323eSThomas Huth #define AHCI_PX_IS_HBDS (0x10000000) 1331cf4323eSThomas Huth #define AHCI_PX_IS_HBFS (0x20000000) 1341cf4323eSThomas Huth #define AHCI_PX_IS_TFES (0x40000000) 1351cf4323eSThomas Huth #define AHCI_PX_IS_CPDS (0x80000000) 1361cf4323eSThomas Huth 1371cf4323eSThomas Huth #define AHCI_PX_IE (5) 1381cf4323eSThomas Huth #define AHCI_PX_IE_DHRE (0x1) 1391cf4323eSThomas Huth #define AHCI_PX_IE_PSE (0x2) 1401cf4323eSThomas Huth #define AHCI_PX_IE_DSE (0x4) 1411cf4323eSThomas Huth #define AHCI_PX_IE_SDBE (0x8) 1421cf4323eSThomas Huth #define AHCI_PX_IE_UFE (0x10) 1431cf4323eSThomas Huth #define AHCI_PX_IE_DPE (0x20) 1441cf4323eSThomas Huth #define AHCI_PX_IE_PCE (0x40) 1451cf4323eSThomas Huth #define AHCI_PX_IE_DMPE (0x80) 1461cf4323eSThomas Huth #define AHCI_PX_IE_RESERVED (0x23FFF00) 1471cf4323eSThomas Huth #define AHCI_PX_IE_PRCE (0x400000) 1481cf4323eSThomas Huth #define AHCI_PX_IE_IPME (0x800000) 1491cf4323eSThomas Huth #define AHCI_PX_IE_OFE (0x1000000) 1501cf4323eSThomas Huth #define AHCI_PX_IE_INFE (0x4000000) 1511cf4323eSThomas Huth #define AHCI_PX_IE_IFE (0x8000000) 1521cf4323eSThomas Huth #define AHCI_PX_IE_HBDE (0x10000000) 1531cf4323eSThomas Huth #define AHCI_PX_IE_HBFE (0x20000000) 1541cf4323eSThomas Huth #define AHCI_PX_IE_TFEE (0x40000000) 1551cf4323eSThomas Huth #define AHCI_PX_IE_CPDE (0x80000000) 1561cf4323eSThomas Huth 1571cf4323eSThomas Huth #define AHCI_PX_CMD (6) 1581cf4323eSThomas Huth #define AHCI_PX_CMD_ST (0x1) 1591cf4323eSThomas Huth #define AHCI_PX_CMD_SUD (0x2) 1601cf4323eSThomas Huth #define AHCI_PX_CMD_POD (0x4) 1611cf4323eSThomas Huth #define AHCI_PX_CMD_CLO (0x8) 1621cf4323eSThomas Huth #define AHCI_PX_CMD_FRE (0x10) 1631cf4323eSThomas Huth #define AHCI_PX_CMD_RESERVED (0xE0) 1641cf4323eSThomas Huth #define AHCI_PX_CMD_CCS (0x1F00) 1651cf4323eSThomas Huth #define AHCI_PX_CMD_MPSS (0x2000) 1661cf4323eSThomas Huth #define AHCI_PX_CMD_FR (0x4000) 1671cf4323eSThomas Huth #define AHCI_PX_CMD_CR (0x8000) 1681cf4323eSThomas Huth #define AHCI_PX_CMD_CPS (0x10000) 1691cf4323eSThomas Huth #define AHCI_PX_CMD_PMA (0x20000) 1701cf4323eSThomas Huth #define AHCI_PX_CMD_HPCP (0x40000) 1711cf4323eSThomas Huth #define AHCI_PX_CMD_MPSP (0x80000) 1721cf4323eSThomas Huth #define AHCI_PX_CMD_CPD (0x100000) 1731cf4323eSThomas Huth #define AHCI_PX_CMD_ESP (0x200000) 1741cf4323eSThomas Huth #define AHCI_PX_CMD_FBSCP (0x400000) 1751cf4323eSThomas Huth #define AHCI_PX_CMD_APSTE (0x800000) 1761cf4323eSThomas Huth #define AHCI_PX_CMD_ATAPI (0x1000000) 1771cf4323eSThomas Huth #define AHCI_PX_CMD_DLAE (0x2000000) 1781cf4323eSThomas Huth #define AHCI_PX_CMD_ALPE (0x4000000) 1791cf4323eSThomas Huth #define AHCI_PX_CMD_ASP (0x8000000) 1801cf4323eSThomas Huth #define AHCI_PX_CMD_ICC (0xF0000000) 1811cf4323eSThomas Huth 1821cf4323eSThomas Huth #define AHCI_PX_RES1 (7) 1831cf4323eSThomas Huth 1841cf4323eSThomas Huth #define AHCI_PX_TFD (8) 1851cf4323eSThomas Huth #define AHCI_PX_TFD_STS (0xFF) 1861cf4323eSThomas Huth #define AHCI_PX_TFD_STS_ERR (0x01) 1871cf4323eSThomas Huth #define AHCI_PX_TFD_STS_CS1 (0x06) 1881cf4323eSThomas Huth #define AHCI_PX_TFD_STS_DRQ (0x08) 1891cf4323eSThomas Huth #define AHCI_PX_TFD_STS_CS2 (0x70) 1901cf4323eSThomas Huth #define AHCI_PX_TFD_STS_BSY (0x80) 1911cf4323eSThomas Huth #define AHCI_PX_TFD_ERR (0xFF00) 1921cf4323eSThomas Huth #define AHCI_PX_TFD_RESERVED (0xFFFF0000) 1931cf4323eSThomas Huth 1941cf4323eSThomas Huth #define AHCI_PX_SIG (9) 1951cf4323eSThomas Huth #define AHCI_PX_SIG_SECTOR_COUNT (0xFF) 1961cf4323eSThomas Huth #define AHCI_PX_SIG_LBA_LOW (0xFF00) 1971cf4323eSThomas Huth #define AHCI_PX_SIG_LBA_MID (0xFF0000) 1981cf4323eSThomas Huth #define AHCI_PX_SIG_LBA_HIGH (0xFF000000) 1991cf4323eSThomas Huth 2001cf4323eSThomas Huth #define AHCI_PX_SSTS (10) 2011cf4323eSThomas Huth #define AHCI_PX_SSTS_DET (0x0F) 2021cf4323eSThomas Huth #define AHCI_PX_SSTS_SPD (0xF0) 2031cf4323eSThomas Huth #define AHCI_PX_SSTS_IPM (0xF00) 2041cf4323eSThomas Huth #define AHCI_PX_SSTS_RESERVED (0xFFFFF000) 2051cf4323eSThomas Huth #define SSTS_DET_NO_DEVICE (0x00) 2061cf4323eSThomas Huth #define SSTS_DET_PRESENT (0x01) 2071cf4323eSThomas Huth #define SSTS_DET_ESTABLISHED (0x03) 2081cf4323eSThomas Huth #define SSTS_DET_OFFLINE (0x04) 2091cf4323eSThomas Huth 2101cf4323eSThomas Huth #define AHCI_PX_SCTL (11) 2111cf4323eSThomas Huth 2121cf4323eSThomas Huth #define AHCI_PX_SERR (12) 2131cf4323eSThomas Huth #define AHCI_PX_SERR_ERR (0xFFFF) 2141cf4323eSThomas Huth #define AHCI_PX_SERR_DIAG (0xFFFF0000) 2151cf4323eSThomas Huth #define AHCI_PX_SERR_DIAG_X (0x04000000) 2161cf4323eSThomas Huth 2171cf4323eSThomas Huth #define AHCI_PX_SACT (13) 2181cf4323eSThomas Huth #define AHCI_PX_CI (14) 2191cf4323eSThomas Huth #define AHCI_PX_SNTF (15) 2201cf4323eSThomas Huth 2211cf4323eSThomas Huth #define AHCI_PX_FBS (16) 2221cf4323eSThomas Huth #define AHCI_PX_FBS_EN (0x1) 2231cf4323eSThomas Huth #define AHCI_PX_FBS_DEC (0x2) 2241cf4323eSThomas Huth #define AHCI_PX_FBS_SDE (0x4) 2251cf4323eSThomas Huth #define AHCI_PX_FBS_DEV (0xF00) 2261cf4323eSThomas Huth #define AHCI_PX_FBS_ADO (0xF000) 2271cf4323eSThomas Huth #define AHCI_PX_FBS_DWE (0xF0000) 2281cf4323eSThomas Huth #define AHCI_PX_FBS_RESERVED (0xFFF000F8) 2291cf4323eSThomas Huth 2301cf4323eSThomas Huth #define AHCI_PX_RES2 (17) 2311cf4323eSThomas Huth #define AHCI_PX_VS (28) 2321cf4323eSThomas Huth 2331cf4323eSThomas Huth #define HBA_DATA_REGION_SIZE (256) 2341cf4323eSThomas Huth #define HBA_PORT_DATA_SIZE (128) 2351cf4323eSThomas Huth #define HBA_PORT_NUM_REG (HBA_PORT_DATA_SIZE/4) 2361cf4323eSThomas Huth 2371cf4323eSThomas Huth #define AHCI_VERSION_0_95 (0x00000905) 2381cf4323eSThomas Huth #define AHCI_VERSION_1_0 (0x00010000) 2391cf4323eSThomas Huth #define AHCI_VERSION_1_1 (0x00010100) 2401cf4323eSThomas Huth #define AHCI_VERSION_1_2 (0x00010200) 2411cf4323eSThomas Huth #define AHCI_VERSION_1_3 (0x00010300) 2421cf4323eSThomas Huth 2431cf4323eSThomas Huth #define AHCI_SECTOR_SIZE (512) 2441cf4323eSThomas Huth #define ATAPI_SECTOR_SIZE (2048) 2451cf4323eSThomas Huth 2461cf4323eSThomas Huth #define AHCI_SIGNATURE_CDROM (0xeb140101) 2471cf4323eSThomas Huth #define AHCI_SIGNATURE_DISK (0x00000101) 2481cf4323eSThomas Huth 2491cf4323eSThomas Huth /* FIS types */ 2501cf4323eSThomas Huth enum { 2511cf4323eSThomas Huth REG_H2D_FIS = 0x27, 2521cf4323eSThomas Huth REG_D2H_FIS = 0x34, 2531cf4323eSThomas Huth DMA_ACTIVATE_FIS = 0x39, 2541cf4323eSThomas Huth DMA_SETUP_FIS = 0x41, 2551cf4323eSThomas Huth DATA_FIS = 0x46, 2561cf4323eSThomas Huth BIST_ACTIVATE_FIS = 0x58, 2571cf4323eSThomas Huth PIO_SETUP_FIS = 0x5F, 2581cf4323eSThomas Huth SDB_FIS = 0xA1 2591cf4323eSThomas Huth }; 2601cf4323eSThomas Huth 2611cf4323eSThomas Huth /* FIS flags */ 2621cf4323eSThomas Huth #define REG_H2D_FIS_CMD 0x80 2631cf4323eSThomas Huth 2641cf4323eSThomas Huth /* ATA Commands */ 2651cf4323eSThomas Huth enum { 2661cf4323eSThomas Huth /* DMA */ 2671cf4323eSThomas Huth CMD_READ_DMA = 0xC8, 2681cf4323eSThomas Huth CMD_READ_DMA_EXT = 0x25, 2691cf4323eSThomas Huth CMD_WRITE_DMA = 0xCA, 2701cf4323eSThomas Huth CMD_WRITE_DMA_EXT = 0x35, 2711cf4323eSThomas Huth /* PIO */ 2721cf4323eSThomas Huth CMD_READ_PIO = 0x20, 2731cf4323eSThomas Huth CMD_READ_PIO_EXT = 0x24, 2741cf4323eSThomas Huth CMD_WRITE_PIO = 0x30, 2751cf4323eSThomas Huth CMD_WRITE_PIO_EXT = 0x34, 2761cf4323eSThomas Huth /* Misc */ 2771cf4323eSThomas Huth CMD_READ_MAX = 0xF8, 2781cf4323eSThomas Huth CMD_READ_MAX_EXT = 0x27, 2791cf4323eSThomas Huth CMD_FLUSH_CACHE = 0xE7, 2801cf4323eSThomas Huth CMD_IDENTIFY = 0xEC, 2811cf4323eSThomas Huth CMD_PACKET = 0xA0, 2821cf4323eSThomas Huth CMD_PACKET_ID = 0xA1, 2831cf4323eSThomas Huth /* NCQ */ 2841cf4323eSThomas Huth READ_FPDMA_QUEUED = 0x60, 2851cf4323eSThomas Huth WRITE_FPDMA_QUEUED = 0x61, 2861cf4323eSThomas Huth }; 2871cf4323eSThomas Huth 2881cf4323eSThomas Huth /* ATAPI Commands */ 2891cf4323eSThomas Huth enum { 2901cf4323eSThomas Huth CMD_ATAPI_TEST_UNIT_READY = 0x00, 2911cf4323eSThomas Huth CMD_ATAPI_REQUEST_SENSE = 0x03, 2921cf4323eSThomas Huth CMD_ATAPI_START_STOP_UNIT = 0x1b, 2931cf4323eSThomas Huth CMD_ATAPI_READ_10 = 0x28, 2941cf4323eSThomas Huth CMD_ATAPI_READ_CD = 0xbe, 2951cf4323eSThomas Huth }; 2961cf4323eSThomas Huth 2971cf4323eSThomas Huth enum { 2981cf4323eSThomas Huth SENSE_NO_SENSE = 0x00, 2991cf4323eSThomas Huth SENSE_NOT_READY = 0x02, 3001cf4323eSThomas Huth SENSE_UNIT_ATTENTION = 0x06, 3011cf4323eSThomas Huth }; 3021cf4323eSThomas Huth 3031cf4323eSThomas Huth enum { 3041cf4323eSThomas Huth ASC_MEDIUM_MAY_HAVE_CHANGED = 0x28, 3051cf4323eSThomas Huth ASC_MEDIUM_NOT_PRESENT = 0x3a, 3061cf4323eSThomas Huth }; 3071cf4323eSThomas Huth 3081cf4323eSThomas Huth /* AHCI Command Header Flags & Masks*/ 3091cf4323eSThomas Huth #define CMDH_CFL (0x1F) 3101cf4323eSThomas Huth #define CMDH_ATAPI (0x20) 3111cf4323eSThomas Huth #define CMDH_WRITE (0x40) 3121cf4323eSThomas Huth #define CMDH_PREFETCH (0x80) 3131cf4323eSThomas Huth #define CMDH_RESET (0x100) 3141cf4323eSThomas Huth #define CMDH_BIST (0x200) 3151cf4323eSThomas Huth #define CMDH_CLR_BSY (0x400) 3161cf4323eSThomas Huth #define CMDH_RES (0x800) 3171cf4323eSThomas Huth #define CMDH_PMP (0xF000) 3181cf4323eSThomas Huth 3191cf4323eSThomas Huth /* ATA device register masks */ 3201cf4323eSThomas Huth #define ATA_DEVICE_MAGIC 0xA0 /* used in ata1-3 */ 3211cf4323eSThomas Huth #define ATA_DEVICE_LBA 0x40 3221cf4323eSThomas Huth #define NCQ_DEVICE_MAGIC 0x40 /* for ncq device registers */ 3231cf4323eSThomas Huth #define ATA_DEVICE_DRIVE 0x10 3241cf4323eSThomas Huth #define ATA_DEVICE_HEAD 0x0F 3251cf4323eSThomas Huth 3261cf4323eSThomas Huth /*** Structures ***/ 3271cf4323eSThomas Huth 3281cf4323eSThomas Huth typedef struct AHCIPortQState { 3291cf4323eSThomas Huth uint64_t fb; 3301cf4323eSThomas Huth uint64_t clb; 3311cf4323eSThomas Huth uint64_t ctba[32]; 3321cf4323eSThomas Huth uint16_t prdtl[32]; 3331cf4323eSThomas Huth uint8_t next; /** Next Command Slot to Use **/ 3341cf4323eSThomas Huth } AHCIPortQState; 3351cf4323eSThomas Huth 3361cf4323eSThomas Huth typedef struct AHCIQState { 3371cf4323eSThomas Huth QOSState *parent; 3381cf4323eSThomas Huth QPCIDevice *dev; 3391cf4323eSThomas Huth QPCIBar hba_bar; 3401cf4323eSThomas Huth uint64_t barsize; 3411cf4323eSThomas Huth uint32_t fingerprint; 3421cf4323eSThomas Huth uint32_t cap; 3431cf4323eSThomas Huth uint32_t cap2; 3441cf4323eSThomas Huth AHCIPortQState port[32]; 3451cf4323eSThomas Huth bool enabled; 3461cf4323eSThomas Huth } AHCIQState; 3471cf4323eSThomas Huth 3481cf4323eSThomas Huth /** 3491cf4323eSThomas Huth * Generic FIS structure. 3501cf4323eSThomas Huth */ 3511cf4323eSThomas Huth typedef struct FIS { 3521cf4323eSThomas Huth uint8_t fis_type; 3531cf4323eSThomas Huth uint8_t flags; 354*f7795e40SPhilippe Mathieu-Daudé char data[]; 3551cf4323eSThomas Huth } __attribute__((__packed__)) FIS; 3561cf4323eSThomas Huth 3571cf4323eSThomas Huth /** 3581cf4323eSThomas Huth * Register device-to-host FIS structure. 3591cf4323eSThomas Huth */ 3601cf4323eSThomas Huth typedef struct RegD2HFIS { 3611cf4323eSThomas Huth /* DW0 */ 3621cf4323eSThomas Huth uint8_t fis_type; 3631cf4323eSThomas Huth uint8_t flags; 3641cf4323eSThomas Huth uint8_t status; 3651cf4323eSThomas Huth uint8_t error; 3661cf4323eSThomas Huth /* DW1 */ 3671cf4323eSThomas Huth uint8_t lba_lo[3]; 3681cf4323eSThomas Huth uint8_t device; 3691cf4323eSThomas Huth /* DW2 */ 3701cf4323eSThomas Huth uint8_t lba_hi[3]; 3711cf4323eSThomas Huth uint8_t res0; 3721cf4323eSThomas Huth /* DW3 */ 3731cf4323eSThomas Huth uint16_t count; 3741cf4323eSThomas Huth uint16_t res1; 3751cf4323eSThomas Huth /* DW4 */ 3761cf4323eSThomas Huth uint32_t res2; 3771cf4323eSThomas Huth } __attribute__((__packed__)) RegD2HFIS; 3781cf4323eSThomas Huth 3791cf4323eSThomas Huth /** 3801cf4323eSThomas Huth * Register device-to-host FIS structure; 3811cf4323eSThomas Huth * PIO Setup variety. 3821cf4323eSThomas Huth */ 3831cf4323eSThomas Huth typedef struct PIOSetupFIS { 3841cf4323eSThomas Huth /* DW0 */ 3851cf4323eSThomas Huth uint8_t fis_type; 3861cf4323eSThomas Huth uint8_t flags; 3871cf4323eSThomas Huth uint8_t status; 3881cf4323eSThomas Huth uint8_t error; 3891cf4323eSThomas Huth /* DW1 */ 3901cf4323eSThomas Huth uint8_t lba_lo[3]; 3911cf4323eSThomas Huth uint8_t device; 3921cf4323eSThomas Huth /* DW2 */ 3931cf4323eSThomas Huth uint8_t lba_hi[3]; 3941cf4323eSThomas Huth uint8_t res0; 3951cf4323eSThomas Huth /* DW3 */ 3961cf4323eSThomas Huth uint16_t count; 3971cf4323eSThomas Huth uint8_t res1; 3981cf4323eSThomas Huth uint8_t e_status; 3991cf4323eSThomas Huth /* DW4 */ 4001cf4323eSThomas Huth uint16_t tx_count; 4011cf4323eSThomas Huth uint16_t res2; 4021cf4323eSThomas Huth } __attribute__((__packed__)) PIOSetupFIS; 4031cf4323eSThomas Huth 4041cf4323eSThomas Huth /** 4051cf4323eSThomas Huth * Register host-to-device FIS structure. 4061cf4323eSThomas Huth */ 4071cf4323eSThomas Huth typedef struct RegH2DFIS { 4081cf4323eSThomas Huth /* DW0 */ 4091cf4323eSThomas Huth uint8_t fis_type; 4101cf4323eSThomas Huth uint8_t flags; 4111cf4323eSThomas Huth uint8_t command; 4121cf4323eSThomas Huth uint8_t feature_low; 4131cf4323eSThomas Huth /* DW1 */ 4141cf4323eSThomas Huth uint8_t lba_lo[3]; 4151cf4323eSThomas Huth uint8_t device; 4161cf4323eSThomas Huth /* DW2 */ 4171cf4323eSThomas Huth uint8_t lba_hi[3]; 4181cf4323eSThomas Huth uint8_t feature_high; 4191cf4323eSThomas Huth /* DW3 */ 4201cf4323eSThomas Huth uint16_t count; 4211cf4323eSThomas Huth uint8_t icc; 4221cf4323eSThomas Huth uint8_t control; 4231cf4323eSThomas Huth /* DW4 */ 4241cf4323eSThomas Huth uint8_t aux[4]; 4251cf4323eSThomas Huth } __attribute__((__packed__)) RegH2DFIS; 4261cf4323eSThomas Huth 4271cf4323eSThomas Huth /** 4281cf4323eSThomas Huth * Register host-to-device FIS structure, for NCQ commands. 4291cf4323eSThomas Huth * Actually just a RegH2DFIS, but with fields repurposed. 4301cf4323eSThomas Huth * Repurposed fields are annotated below. 4311cf4323eSThomas Huth */ 4321cf4323eSThomas Huth typedef struct NCQFIS { 4331cf4323eSThomas Huth /* DW0 */ 4341cf4323eSThomas Huth uint8_t fis_type; 4351cf4323eSThomas Huth uint8_t flags; 4361cf4323eSThomas Huth uint8_t command; 4371cf4323eSThomas Huth uint8_t sector_low; /* H2D: Feature 7:0 */ 4381cf4323eSThomas Huth /* DW1 */ 4391cf4323eSThomas Huth uint8_t lba_lo[3]; 4401cf4323eSThomas Huth uint8_t device; 4411cf4323eSThomas Huth /* DW2 */ 4421cf4323eSThomas Huth uint8_t lba_hi[3]; 4431cf4323eSThomas Huth uint8_t sector_hi; /* H2D: Feature 15:8 */ 4441cf4323eSThomas Huth /* DW3 */ 4451cf4323eSThomas Huth uint8_t tag; /* H2D: Count 0:7 */ 4461cf4323eSThomas Huth uint8_t prio; /* H2D: Count 15:8 */ 4471cf4323eSThomas Huth uint8_t icc; 4481cf4323eSThomas Huth uint8_t control; 4491cf4323eSThomas Huth /* DW4 */ 4501cf4323eSThomas Huth uint8_t aux[4]; 4511cf4323eSThomas Huth } __attribute__((__packed__)) NCQFIS; 4521cf4323eSThomas Huth 4531cf4323eSThomas Huth /** 4541cf4323eSThomas Huth * Command List entry structure. 4551cf4323eSThomas Huth * The command list contains between 1-32 of these structures. 4561cf4323eSThomas Huth */ 4571cf4323eSThomas Huth typedef struct AHCICommandHeader { 4581cf4323eSThomas Huth uint16_t flags; /* Cmd-Fis-Len, PMP#, and flags. */ 4591cf4323eSThomas Huth uint16_t prdtl; /* Phys Region Desc. Table Length */ 4601cf4323eSThomas Huth uint32_t prdbc; /* Phys Region Desc. Byte Count */ 4611cf4323eSThomas Huth uint64_t ctba; /* Command Table Descriptor Base Address */ 4621cf4323eSThomas Huth uint32_t res[4]; 4631cf4323eSThomas Huth } __attribute__((__packed__)) AHCICommandHeader; 4641cf4323eSThomas Huth 4651cf4323eSThomas Huth /** 4661cf4323eSThomas Huth * Physical Region Descriptor; pointed to by the Command List Header, 4671cf4323eSThomas Huth * struct ahci_command. 4681cf4323eSThomas Huth */ 4691cf4323eSThomas Huth typedef struct PRD { 4701cf4323eSThomas Huth uint64_t dba; /* Data Base Address */ 4711cf4323eSThomas Huth uint32_t res; /* Reserved */ 4721cf4323eSThomas Huth uint32_t dbc; /* Data Byte Count (0-indexed) & Interrupt Flag (bit 2^31) */ 4731cf4323eSThomas Huth } __attribute__((__packed__)) PRD; 4741cf4323eSThomas Huth 4751cf4323eSThomas Huth /* Opaque, defined within ahci.c */ 4761cf4323eSThomas Huth typedef struct AHCICommand AHCICommand; 4771cf4323eSThomas Huth 4781cf4323eSThomas Huth /* Options to ahci_exec */ 4791cf4323eSThomas Huth typedef struct AHCIOpts { 4801cf4323eSThomas Huth size_t size; /* Size of transfer */ 4811cf4323eSThomas Huth unsigned prd_size; /* Size per-each PRD */ 4821cf4323eSThomas Huth bool set_bcl; /* Override the default BCL of ATAPI_SECTOR_SIZE */ 4831cf4323eSThomas Huth unsigned bcl; /* Byte Count Limit, for ATAPI PIO */ 4841cf4323eSThomas Huth uint64_t lba; /* Starting LBA offset */ 4851cf4323eSThomas Huth uint64_t buffer; /* Pointer to source or destination guest buffer */ 4861cf4323eSThomas Huth bool atapi; /* ATAPI command? */ 4871cf4323eSThomas Huth bool atapi_dma; /* Use DMA for ATAPI? */ 4881cf4323eSThomas Huth bool error; 4891cf4323eSThomas Huth int (*pre_cb)(AHCIQState*, AHCICommand*, const struct AHCIOpts *); 4901cf4323eSThomas Huth int (*mid_cb)(AHCIQState*, AHCICommand*, const struct AHCIOpts *); 4911cf4323eSThomas Huth int (*post_cb)(AHCIQState*, AHCICommand*, const struct AHCIOpts *); 4921cf4323eSThomas Huth void *opaque; 4931cf4323eSThomas Huth } AHCIOpts; 4941cf4323eSThomas Huth 4951cf4323eSThomas Huth /*** Macro Utilities ***/ 4961cf4323eSThomas Huth #define BITANY(data, mask) (((data) & (mask)) != 0) 4971cf4323eSThomas Huth #define BITSET(data, mask) (((data) & (mask)) == (mask)) 4981cf4323eSThomas Huth #define BITCLR(data, mask) (((data) & (mask)) == 0) 4991cf4323eSThomas Huth #define ASSERT_BIT_SET(data, mask) g_assert_cmphex((data) & (mask), ==, (mask)) 5001cf4323eSThomas Huth #define ASSERT_BIT_CLEAR(data, mask) g_assert_cmphex((data) & (mask), ==, 0) 5011cf4323eSThomas Huth 5021cf4323eSThomas Huth /* For calculating how big the PRD table needs to be: */ 5031cf4323eSThomas Huth #define CMD_TBL_SIZ(n) ((0x80 + ((n) * sizeof(PRD)) + 0x7F) & ~0x7F) 5041cf4323eSThomas Huth 5051cf4323eSThomas Huth /* Helpers for reading/writing AHCI HBA register values */ 5061cf4323eSThomas Huth 5071cf4323eSThomas Huth static inline uint32_t ahci_mread(AHCIQState *ahci, size_t offset) 5081cf4323eSThomas Huth { 5091cf4323eSThomas Huth return qpci_io_readl(ahci->dev, ahci->hba_bar, offset); 5101cf4323eSThomas Huth } 5111cf4323eSThomas Huth 5121cf4323eSThomas Huth static inline void ahci_mwrite(AHCIQState *ahci, size_t offset, uint32_t value) 5131cf4323eSThomas Huth { 5141cf4323eSThomas Huth qpci_io_writel(ahci->dev, ahci->hba_bar, offset, value); 5151cf4323eSThomas Huth } 5161cf4323eSThomas Huth 5171cf4323eSThomas Huth static inline uint32_t ahci_rreg(AHCIQState *ahci, uint32_t reg_num) 5181cf4323eSThomas Huth { 5191cf4323eSThomas Huth return ahci_mread(ahci, 4 * reg_num); 5201cf4323eSThomas Huth } 5211cf4323eSThomas Huth 5221cf4323eSThomas Huth static inline void ahci_wreg(AHCIQState *ahci, uint32_t reg_num, uint32_t value) 5231cf4323eSThomas Huth { 5241cf4323eSThomas Huth ahci_mwrite(ahci, 4 * reg_num, value); 5251cf4323eSThomas Huth } 5261cf4323eSThomas Huth 5271cf4323eSThomas Huth static inline void ahci_set(AHCIQState *ahci, uint32_t reg_num, uint32_t mask) 5281cf4323eSThomas Huth { 5291cf4323eSThomas Huth ahci_wreg(ahci, reg_num, ahci_rreg(ahci, reg_num) | mask); 5301cf4323eSThomas Huth } 5311cf4323eSThomas Huth 5321cf4323eSThomas Huth static inline void ahci_clr(AHCIQState *ahci, uint32_t reg_num, uint32_t mask) 5331cf4323eSThomas Huth { 5341cf4323eSThomas Huth ahci_wreg(ahci, reg_num, ahci_rreg(ahci, reg_num) & ~mask); 5351cf4323eSThomas Huth } 5361cf4323eSThomas Huth 5371cf4323eSThomas Huth static inline size_t ahci_px_offset(uint8_t port, uint32_t reg_num) 5381cf4323eSThomas Huth { 5391cf4323eSThomas Huth return AHCI_PORTS + (HBA_PORT_NUM_REG * port) + reg_num; 5401cf4323eSThomas Huth } 5411cf4323eSThomas Huth 5421cf4323eSThomas Huth static inline uint32_t ahci_px_rreg(AHCIQState *ahci, uint8_t port, 5431cf4323eSThomas Huth uint32_t reg_num) 5441cf4323eSThomas Huth { 5451cf4323eSThomas Huth return ahci_rreg(ahci, ahci_px_offset(port, reg_num)); 5461cf4323eSThomas Huth } 5471cf4323eSThomas Huth 5481cf4323eSThomas Huth static inline void ahci_px_wreg(AHCIQState *ahci, uint8_t port, 5491cf4323eSThomas Huth uint32_t reg_num, uint32_t value) 5501cf4323eSThomas Huth { 5511cf4323eSThomas Huth ahci_wreg(ahci, ahci_px_offset(port, reg_num), value); 5521cf4323eSThomas Huth } 5531cf4323eSThomas Huth 5541cf4323eSThomas Huth static inline void ahci_px_set(AHCIQState *ahci, uint8_t port, 5551cf4323eSThomas Huth uint32_t reg_num, uint32_t mask) 5561cf4323eSThomas Huth { 5571cf4323eSThomas Huth ahci_px_wreg(ahci, port, reg_num, 5581cf4323eSThomas Huth ahci_px_rreg(ahci, port, reg_num) | mask); 5591cf4323eSThomas Huth } 5601cf4323eSThomas Huth 5611cf4323eSThomas Huth static inline void ahci_px_clr(AHCIQState *ahci, uint8_t port, 5621cf4323eSThomas Huth uint32_t reg_num, uint32_t mask) 5631cf4323eSThomas Huth { 5641cf4323eSThomas Huth ahci_px_wreg(ahci, port, reg_num, 5651cf4323eSThomas Huth ahci_px_rreg(ahci, port, reg_num) & ~mask); 5661cf4323eSThomas Huth } 5671cf4323eSThomas Huth 5681cf4323eSThomas Huth /*** Prototypes ***/ 5691cf4323eSThomas Huth uint64_t ahci_alloc(AHCIQState *ahci, size_t bytes); 5701cf4323eSThomas Huth void ahci_free(AHCIQState *ahci, uint64_t addr); 5711cf4323eSThomas Huth void ahci_clean_mem(AHCIQState *ahci); 5721cf4323eSThomas Huth 5731cf4323eSThomas Huth /* Device management */ 5741cf4323eSThomas Huth QPCIDevice *get_ahci_device(QTestState *qts, uint32_t *fingerprint); 5751cf4323eSThomas Huth void free_ahci_device(QPCIDevice *dev); 5761cf4323eSThomas Huth void ahci_pci_enable(AHCIQState *ahci); 5771cf4323eSThomas Huth void start_ahci_device(AHCIQState *ahci); 5781cf4323eSThomas Huth void ahci_hba_enable(AHCIQState *ahci); 5791cf4323eSThomas Huth 5801cf4323eSThomas Huth /* Port Management */ 5811cf4323eSThomas Huth unsigned ahci_port_select(AHCIQState *ahci); 5821cf4323eSThomas Huth void ahci_port_clear(AHCIQState *ahci, uint8_t port); 5831cf4323eSThomas Huth 5841cf4323eSThomas Huth /* Command header / table management */ 5851cf4323eSThomas Huth unsigned ahci_pick_cmd(AHCIQState *ahci, uint8_t port); 5861cf4323eSThomas Huth void ahci_get_command_header(AHCIQState *ahci, uint8_t port, 5871cf4323eSThomas Huth uint8_t slot, AHCICommandHeader *cmd); 5881cf4323eSThomas Huth void ahci_set_command_header(AHCIQState *ahci, uint8_t port, 5891cf4323eSThomas Huth uint8_t slot, AHCICommandHeader *cmd); 5901cf4323eSThomas Huth void ahci_destroy_command(AHCIQState *ahci, uint8_t port, uint8_t slot); 5911cf4323eSThomas Huth 5921cf4323eSThomas Huth /* AHCI sanity check routines */ 5931cf4323eSThomas Huth void ahci_port_check_error(AHCIQState *ahci, uint8_t port, 5941cf4323eSThomas Huth uint32_t imask, uint8_t emask); 5951cf4323eSThomas Huth void ahci_port_check_interrupts(AHCIQState *ahci, uint8_t port, 5961cf4323eSThomas Huth uint32_t intr_mask); 5971cf4323eSThomas Huth void ahci_port_check_nonbusy(AHCIQState *ahci, uint8_t port, uint8_t slot); 5981cf4323eSThomas Huth void ahci_port_check_d2h_sanity(AHCIQState *ahci, uint8_t port, uint8_t slot); 5991cf4323eSThomas Huth void ahci_port_check_pio_sanity(AHCIQState *ahci, AHCICommand *cmd); 6001cf4323eSThomas Huth void ahci_port_check_cmd_sanity(AHCIQState *ahci, AHCICommand *cmd); 6011cf4323eSThomas Huth 6021cf4323eSThomas Huth /* Misc */ 6031cf4323eSThomas Huth bool is_atapi(AHCIQState *ahci, uint8_t port); 6041cf4323eSThomas Huth unsigned size_to_prdtl(unsigned bytes, unsigned bytes_per_prd); 6051cf4323eSThomas Huth 6061cf4323eSThomas Huth /* Command: Macro level execution */ 6071cf4323eSThomas Huth void ahci_guest_io(AHCIQState *ahci, uint8_t port, uint8_t ide_cmd, 6081cf4323eSThomas Huth uint64_t gbuffer, size_t size, uint64_t sector); 6091cf4323eSThomas Huth AHCICommand *ahci_guest_io_halt(AHCIQState *ahci, uint8_t port, uint8_t ide_cmd, 6101cf4323eSThomas Huth uint64_t gbuffer, size_t size, uint64_t sector); 6111cf4323eSThomas Huth void ahci_guest_io_resume(AHCIQState *ahci, AHCICommand *cmd); 6121cf4323eSThomas Huth void ahci_io(AHCIQState *ahci, uint8_t port, uint8_t ide_cmd, 6131cf4323eSThomas Huth void *buffer, size_t bufsize, uint64_t sector); 6141cf4323eSThomas Huth void ahci_exec(AHCIQState *ahci, uint8_t port, 6151cf4323eSThomas Huth uint8_t op, const AHCIOpts *opts); 6161cf4323eSThomas Huth void ahci_atapi_test_ready(AHCIQState *ahci, uint8_t port, bool ready, 6171cf4323eSThomas Huth uint8_t expected_sense); 6181cf4323eSThomas Huth void ahci_atapi_get_sense(AHCIQState *ahci, uint8_t port, 6191cf4323eSThomas Huth uint8_t *sense, uint8_t *asc); 6201cf4323eSThomas Huth void ahci_atapi_eject(AHCIQState *ahci, uint8_t port); 6211cf4323eSThomas Huth void ahci_atapi_load(AHCIQState *ahci, uint8_t port); 6221cf4323eSThomas Huth 6231cf4323eSThomas Huth /* Command: Fine-grained lifecycle */ 6241cf4323eSThomas Huth AHCICommand *ahci_command_create(uint8_t command_name); 6251cf4323eSThomas Huth AHCICommand *ahci_atapi_command_create(uint8_t scsi_cmd, uint16_t bcl, bool dma); 6261cf4323eSThomas Huth void ahci_command_commit(AHCIQState *ahci, AHCICommand *cmd, uint8_t port); 6271cf4323eSThomas Huth void ahci_command_issue(AHCIQState *ahci, AHCICommand *cmd); 6281cf4323eSThomas Huth void ahci_command_issue_async(AHCIQState *ahci, AHCICommand *cmd); 6291cf4323eSThomas Huth void ahci_command_wait(AHCIQState *ahci, AHCICommand *cmd); 6301cf4323eSThomas Huth void ahci_command_verify(AHCIQState *ahci, AHCICommand *cmd); 6311cf4323eSThomas Huth void ahci_command_free(AHCICommand *cmd); 6321cf4323eSThomas Huth 6331cf4323eSThomas Huth /* Command: adjustments */ 6341cf4323eSThomas Huth void ahci_command_set_flags(AHCICommand *cmd, uint16_t cmdh_flags); 6351cf4323eSThomas Huth void ahci_command_clr_flags(AHCICommand *cmd, uint16_t cmdh_flags); 6361cf4323eSThomas Huth void ahci_command_set_offset(AHCICommand *cmd, uint64_t lba_sect); 6371cf4323eSThomas Huth void ahci_command_set_buffer(AHCICommand *cmd, uint64_t buffer); 6381cf4323eSThomas Huth void ahci_command_set_size(AHCICommand *cmd, uint64_t xbytes); 6391cf4323eSThomas Huth void ahci_command_set_prd_size(AHCICommand *cmd, unsigned prd_size); 6401cf4323eSThomas Huth void ahci_command_set_sizes(AHCICommand *cmd, uint64_t xbytes, 6411cf4323eSThomas Huth unsigned prd_size); 6421cf4323eSThomas Huth void ahci_command_set_acmd(AHCICommand *cmd, void *acmd); 6431cf4323eSThomas Huth void ahci_command_enable_atapi_dma(AHCICommand *cmd); 6441cf4323eSThomas Huth void ahci_command_adjust(AHCICommand *cmd, uint64_t lba_sect, uint64_t gbuffer, 6451cf4323eSThomas Huth uint64_t xbytes, unsigned prd_size); 6461cf4323eSThomas Huth 6471cf4323eSThomas Huth /* Command: Misc */ 6481cf4323eSThomas Huth uint8_t ahci_command_slot(AHCICommand *cmd); 6491cf4323eSThomas Huth void ahci_write_fis(AHCIQState *ahci, AHCICommand *cmd); 6501cf4323eSThomas Huth 6511cf4323eSThomas Huth #endif 652