1f6ad2e32SAlexander Graf /* 2f6ad2e32SAlexander Graf * QEMU AHCI Emulation 3f6ad2e32SAlexander Graf * 4f6ad2e32SAlexander Graf * Copyright (c) 2010 qiaochong@loongson.cn 5f6ad2e32SAlexander Graf * Copyright (c) 2010 Roland Elek <elek.roland@gmail.com> 6f6ad2e32SAlexander Graf * Copyright (c) 2010 Sebastian Herbszt <herbszt@gmx.de> 7f6ad2e32SAlexander Graf * Copyright (c) 2010 Alexander Graf <agraf@suse.de> 8f6ad2e32SAlexander Graf * 9f6ad2e32SAlexander Graf * This library is free software; you can redistribute it and/or 10f6ad2e32SAlexander Graf * modify it under the terms of the GNU Lesser General Public 11f6ad2e32SAlexander Graf * License as published by the Free Software Foundation; either 1261f3c91aSChetan Pant * version 2.1 of the License, or (at your option) any later version. 13f6ad2e32SAlexander Graf * 14f6ad2e32SAlexander Graf * This library is distributed in the hope that it will be useful, 15f6ad2e32SAlexander Graf * but WITHOUT ANY WARRANTY; without even the implied warranty of 16f6ad2e32SAlexander Graf * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17f6ad2e32SAlexander Graf * Lesser General Public License for more details. 18f6ad2e32SAlexander Graf * 19f6ad2e32SAlexander Graf * You should have received a copy of the GNU Lesser General Public 20f6ad2e32SAlexander Graf * License along with this library; if not, see <http://www.gnu.org/licenses/>. 21f6ad2e32SAlexander Graf * 22f6ad2e32SAlexander Graf */ 23f6ad2e32SAlexander Graf 2453239262SPeter Maydell #include "qemu/osdep.h" 25da9f1172SPhilippe Mathieu-Daudé #include "hw/irq.h" 26a9c94277SMarkus Armbruster #include "hw/pci/msi.h" 27a9c94277SMarkus Armbruster #include "hw/pci/pci.h" 28a27bd6c7SMarkus Armbruster #include "hw/qdev-properties.h" 29d6454270SMarkus Armbruster #include "migration/vmstate.h" 30f6ad2e32SAlexander Graf 31d49b6836SMarkus Armbruster #include "qemu/error-report.h" 3206e35065SJohn Snow #include "qemu/log.h" 33db725815SMarkus Armbruster #include "qemu/main-loop.h" 340b8fa32fSMarkus Armbruster #include "qemu/module.h" 354be74634SMarkus Armbruster #include "sysemu/block-backend.h" 369c17d615SPaolo Bonzini #include "sysemu/dma.h" 37a9c94277SMarkus Armbruster #include "hw/ide/internal.h" 38a9c94277SMarkus Armbruster #include "hw/ide/pci.h" 399314b859SMichael S. Tsirkin #include "ahci_internal.h" 40f6ad2e32SAlexander Graf 41e4baa9f0SJohn Snow #include "trace.h" 42f6ad2e32SAlexander Graf 43f6ad2e32SAlexander Graf static void check_cmd(AHCIState *s, int port); 44e2a5d9b3SNiklas Cassel static void handle_cmd(AHCIState *s, int port, uint8_t slot); 45f6ad2e32SAlexander Graf static void ahci_reset_port(AHCIState *s, int port); 462967dc82SNiklas Cassel static bool ahci_write_fis_d2h(AHCIDevice *ad, bool d2h_fis_i); 47e2a5d9b3SNiklas Cassel static void ahci_clear_cmd_issue(AHCIDevice *ad, uint8_t slot); 4887e62065SAlexander Graf static void ahci_init_d2h(AHCIDevice *ad); 49ae0cebd7SPhilippe Mathieu-Daudé static int ahci_dma_prepare_buf(const IDEDMA *dma, int32_t limit); 50a13ab5a3SJohn Snow static bool ahci_map_clb_address(AHCIDevice *ad); 51a13ab5a3SJohn Snow static bool ahci_map_fis_address(AHCIDevice *ad); 52fc3d8e11SJohn Snow static void ahci_unmap_clb_address(AHCIDevice *ad); 53fc3d8e11SJohn Snow static void ahci_unmap_fis_address(AHCIDevice *ad); 54659142ecSJohn Snow 55da868a46SJohn Snow static const char *AHCIHostReg_lookup[AHCI_HOST_REG__COUNT] = { 56da868a46SJohn Snow [AHCI_HOST_REG_CAP] = "CAP", 57da868a46SJohn Snow [AHCI_HOST_REG_CTL] = "GHC", 58da868a46SJohn Snow [AHCI_HOST_REG_IRQ_STAT] = "IS", 59da868a46SJohn Snow [AHCI_HOST_REG_PORTS_IMPL] = "PI", 60da868a46SJohn Snow [AHCI_HOST_REG_VERSION] = "VS", 61da868a46SJohn Snow [AHCI_HOST_REG_CCC_CTL] = "CCC_CTL", 62da868a46SJohn Snow [AHCI_HOST_REG_CCC_PORTS] = "CCC_PORTS", 63da868a46SJohn Snow [AHCI_HOST_REG_EM_LOC] = "EM_LOC", 64da868a46SJohn Snow [AHCI_HOST_REG_EM_CTL] = "EM_CTL", 65da868a46SJohn Snow [AHCI_HOST_REG_CAP2] = "CAP2", 66da868a46SJohn Snow [AHCI_HOST_REG_BOHC] = "BOHC", 67da868a46SJohn Snow }; 68da868a46SJohn Snow 694e6e1de4SJohn Snow static const char *AHCIPortReg_lookup[AHCI_PORT_REG__COUNT] = { 704e6e1de4SJohn Snow [AHCI_PORT_REG_LST_ADDR] = "PxCLB", 714e6e1de4SJohn Snow [AHCI_PORT_REG_LST_ADDR_HI] = "PxCLBU", 724e6e1de4SJohn Snow [AHCI_PORT_REG_FIS_ADDR] = "PxFB", 734e6e1de4SJohn Snow [AHCI_PORT_REG_FIS_ADDR_HI] = "PxFBU", 744e6e1de4SJohn Snow [AHCI_PORT_REG_IRQ_STAT] = "PxIS", 754e6e1de4SJohn Snow [AHCI_PORT_REG_IRQ_MASK] = "PXIE", 764e6e1de4SJohn Snow [AHCI_PORT_REG_CMD] = "PxCMD", 774e6e1de4SJohn Snow [7] = "Reserved", 784e6e1de4SJohn Snow [AHCI_PORT_REG_TFDATA] = "PxTFD", 794e6e1de4SJohn Snow [AHCI_PORT_REG_SIG] = "PxSIG", 804e6e1de4SJohn Snow [AHCI_PORT_REG_SCR_STAT] = "PxSSTS", 814e6e1de4SJohn Snow [AHCI_PORT_REG_SCR_CTL] = "PxSCTL", 824e6e1de4SJohn Snow [AHCI_PORT_REG_SCR_ERR] = "PxSERR", 834e6e1de4SJohn Snow [AHCI_PORT_REG_SCR_ACT] = "PxSACT", 844e6e1de4SJohn Snow [AHCI_PORT_REG_CMD_ISSUE] = "PxCI", 854e6e1de4SJohn Snow [AHCI_PORT_REG_SCR_NOTIF] = "PxSNTF", 864e6e1de4SJohn Snow [AHCI_PORT_REG_FIS_CTL] = "PxFBS", 874e6e1de4SJohn Snow [AHCI_PORT_REG_DEV_SLEEP] = "PxDEVSLP", 884e6e1de4SJohn Snow [18 ... 27] = "Reserved", 894e6e1de4SJohn Snow [AHCI_PORT_REG_VENDOR_1 ... 904e6e1de4SJohn Snow AHCI_PORT_REG_VENDOR_4] = "PxVS", 914e6e1de4SJohn Snow }; 924e6e1de4SJohn Snow 935fa0feecSJohn Snow static const char *AHCIPortIRQ_lookup[AHCI_PORT_IRQ__COUNT] = { 945fa0feecSJohn Snow [AHCI_PORT_IRQ_BIT_DHRS] = "DHRS", 955fa0feecSJohn Snow [AHCI_PORT_IRQ_BIT_PSS] = "PSS", 965fa0feecSJohn Snow [AHCI_PORT_IRQ_BIT_DSS] = "DSS", 975fa0feecSJohn Snow [AHCI_PORT_IRQ_BIT_SDBS] = "SDBS", 985fa0feecSJohn Snow [AHCI_PORT_IRQ_BIT_UFS] = "UFS", 995fa0feecSJohn Snow [AHCI_PORT_IRQ_BIT_DPS] = "DPS", 1005fa0feecSJohn Snow [AHCI_PORT_IRQ_BIT_PCS] = "PCS", 1015fa0feecSJohn Snow [AHCI_PORT_IRQ_BIT_DMPS] = "DMPS", 1025fa0feecSJohn Snow [8 ... 21] = "RESERVED", 1035fa0feecSJohn Snow [AHCI_PORT_IRQ_BIT_PRCS] = "PRCS", 1045fa0feecSJohn Snow [AHCI_PORT_IRQ_BIT_IPMS] = "IPMS", 1055fa0feecSJohn Snow [AHCI_PORT_IRQ_BIT_OFS] = "OFS", 1065fa0feecSJohn Snow [25] = "RESERVED", 1075fa0feecSJohn Snow [AHCI_PORT_IRQ_BIT_INFS] = "INFS", 1085fa0feecSJohn Snow [AHCI_PORT_IRQ_BIT_IFS] = "IFS", 1095fa0feecSJohn Snow [AHCI_PORT_IRQ_BIT_HBDS] = "HBDS", 1105fa0feecSJohn Snow [AHCI_PORT_IRQ_BIT_HBFS] = "HBFS", 1115fa0feecSJohn Snow [AHCI_PORT_IRQ_BIT_TFES] = "TFES", 1125fa0feecSJohn Snow [AHCI_PORT_IRQ_BIT_CPDS] = "CPDS" 1135fa0feecSJohn Snow }; 114f6ad2e32SAlexander Graf 115f6ad2e32SAlexander Graf static uint32_t ahci_port_read(AHCIState *s, int port, int offset) 116f6ad2e32SAlexander Graf { 117f6ad2e32SAlexander Graf uint32_t val; 118536551d7SJohn Snow AHCIPortRegs *pr = &s->dev[port].port_regs; 119536551d7SJohn Snow enum AHCIPortReg regnum = offset / sizeof(uint32_t); 120536551d7SJohn Snow assert(regnum < (AHCI_PORT_ADDR_OFFSET_LEN / sizeof(uint32_t))); 121f6ad2e32SAlexander Graf 122536551d7SJohn Snow switch (regnum) { 123536551d7SJohn Snow case AHCI_PORT_REG_LST_ADDR: 124f6ad2e32SAlexander Graf val = pr->lst_addr; 125f6ad2e32SAlexander Graf break; 126536551d7SJohn Snow case AHCI_PORT_REG_LST_ADDR_HI: 127f6ad2e32SAlexander Graf val = pr->lst_addr_hi; 128f6ad2e32SAlexander Graf break; 129536551d7SJohn Snow case AHCI_PORT_REG_FIS_ADDR: 130f6ad2e32SAlexander Graf val = pr->fis_addr; 131f6ad2e32SAlexander Graf break; 132536551d7SJohn Snow case AHCI_PORT_REG_FIS_ADDR_HI: 133f6ad2e32SAlexander Graf val = pr->fis_addr_hi; 134f6ad2e32SAlexander Graf break; 135536551d7SJohn Snow case AHCI_PORT_REG_IRQ_STAT: 136f6ad2e32SAlexander Graf val = pr->irq_stat; 137f6ad2e32SAlexander Graf break; 138536551d7SJohn Snow case AHCI_PORT_REG_IRQ_MASK: 139f6ad2e32SAlexander Graf val = pr->irq_mask; 140f6ad2e32SAlexander Graf break; 141536551d7SJohn Snow case AHCI_PORT_REG_CMD: 142f6ad2e32SAlexander Graf val = pr->cmd; 143f6ad2e32SAlexander Graf break; 144536551d7SJohn Snow case AHCI_PORT_REG_TFDATA: 145fac7aa7fSJohn Snow val = pr->tfdata; 146f6ad2e32SAlexander Graf break; 147536551d7SJohn Snow case AHCI_PORT_REG_SIG: 148f6ad2e32SAlexander Graf val = pr->sig; 149f6ad2e32SAlexander Graf break; 150536551d7SJohn Snow case AHCI_PORT_REG_SCR_STAT: 1514be74634SMarkus Armbruster if (s->dev[port].port.ifs[0].blk) { 152f6ad2e32SAlexander Graf val = SATA_SCR_SSTATUS_DET_DEV_PRESENT_PHY_UP | 153f6ad2e32SAlexander Graf SATA_SCR_SSTATUS_SPD_GEN1 | SATA_SCR_SSTATUS_IPM_ACTIVE; 154f6ad2e32SAlexander Graf } else { 155f6ad2e32SAlexander Graf val = SATA_SCR_SSTATUS_DET_NODEV; 156f6ad2e32SAlexander Graf } 157f6ad2e32SAlexander Graf break; 158536551d7SJohn Snow case AHCI_PORT_REG_SCR_CTL: 159f6ad2e32SAlexander Graf val = pr->scr_ctl; 160f6ad2e32SAlexander Graf break; 161536551d7SJohn Snow case AHCI_PORT_REG_SCR_ERR: 162f6ad2e32SAlexander Graf val = pr->scr_err; 163f6ad2e32SAlexander Graf break; 164536551d7SJohn Snow case AHCI_PORT_REG_SCR_ACT: 165f6ad2e32SAlexander Graf val = pr->scr_act; 166f6ad2e32SAlexander Graf break; 167536551d7SJohn Snow case AHCI_PORT_REG_CMD_ISSUE: 168f6ad2e32SAlexander Graf val = pr->cmd_issue; 169f6ad2e32SAlexander Graf break; 170f6ad2e32SAlexander Graf default: 171e5389163SJohn Snow trace_ahci_port_read_default(s, port, AHCIPortReg_lookup[regnum], 172e5389163SJohn Snow offset); 173f6ad2e32SAlexander Graf val = 0; 174f6ad2e32SAlexander Graf } 175f6ad2e32SAlexander Graf 176e5389163SJohn Snow trace_ahci_port_read(s, port, AHCIPortReg_lookup[regnum], offset, val); 177e4baa9f0SJohn Snow return val; 178f6ad2e32SAlexander Graf } 179f6ad2e32SAlexander Graf 180dc5a43edSJohn Snow static void ahci_irq_raise(AHCIState *s) 181f6ad2e32SAlexander Graf { 182bb639f82SAlistair Francis DeviceState *dev_state = s->container; 183bb639f82SAlistair Francis PCIDevice *pci_dev = (PCIDevice *) object_dynamic_cast(OBJECT(dev_state), 184bb639f82SAlistair Francis TYPE_PCI_DEVICE); 185f6ad2e32SAlexander Graf 186e4baa9f0SJohn Snow trace_ahci_irq_raise(s); 187f6ad2e32SAlexander Graf 188bd164307SRob Herring if (pci_dev && msi_enabled(pci_dev)) { 1890d3aea56SAndreas Färber msi_notify(pci_dev, 0); 190f6ad2e32SAlexander Graf } else { 191f6ad2e32SAlexander Graf qemu_irq_raise(s->irq); 192f6ad2e32SAlexander Graf } 193f6ad2e32SAlexander Graf } 194f6ad2e32SAlexander Graf 195dc5a43edSJohn Snow static void ahci_irq_lower(AHCIState *s) 196f6ad2e32SAlexander Graf { 197bb639f82SAlistair Francis DeviceState *dev_state = s->container; 198bb639f82SAlistair Francis PCIDevice *pci_dev = (PCIDevice *) object_dynamic_cast(OBJECT(dev_state), 199bb639f82SAlistair Francis TYPE_PCI_DEVICE); 200f6ad2e32SAlexander Graf 201e4baa9f0SJohn Snow trace_ahci_irq_lower(s); 202f6ad2e32SAlexander Graf 203bd164307SRob Herring if (!pci_dev || !msi_enabled(pci_dev)) { 204f6ad2e32SAlexander Graf qemu_irq_lower(s->irq); 205f6ad2e32SAlexander Graf } 206f6ad2e32SAlexander Graf } 207f6ad2e32SAlexander Graf 208f6ad2e32SAlexander Graf static void ahci_check_irq(AHCIState *s) 209f6ad2e32SAlexander Graf { 210f6ad2e32SAlexander Graf int i; 211e4baa9f0SJohn Snow uint32_t old_irq = s->control_regs.irqstatus; 212f6ad2e32SAlexander Graf 213b8676728SAlexander Graf s->control_regs.irqstatus = 0; 2142c4b9d0eSAlexander Graf for (i = 0; i < s->ports; i++) { 215f6ad2e32SAlexander Graf AHCIPortRegs *pr = &s->dev[i].port_regs; 216f6ad2e32SAlexander Graf if (pr->irq_stat & pr->irq_mask) { 217f6ad2e32SAlexander Graf s->control_regs.irqstatus |= (1 << i); 218f6ad2e32SAlexander Graf } 219f6ad2e32SAlexander Graf } 220e4baa9f0SJohn Snow trace_ahci_check_irq(s, old_irq, s->control_regs.irqstatus); 221f6ad2e32SAlexander Graf if (s->control_regs.irqstatus && 222f6ad2e32SAlexander Graf (s->control_regs.ghc & HOST_CTL_IRQ_EN)) { 223dc5a43edSJohn Snow ahci_irq_raise(s); 224f6ad2e32SAlexander Graf } else { 225dc5a43edSJohn Snow ahci_irq_lower(s); 226f6ad2e32SAlexander Graf } 227f6ad2e32SAlexander Graf } 228f6ad2e32SAlexander Graf 229f6ad2e32SAlexander Graf static void ahci_trigger_irq(AHCIState *s, AHCIDevice *d, 2305fa0feecSJohn Snow enum AHCIPortIRQ irqbit) 231f6ad2e32SAlexander Graf { 232159a9df0SJohn Snow g_assert((unsigned)irqbit < 32); 2335fa0feecSJohn Snow uint32_t irq = 1U << irqbit; 2345fa0feecSJohn Snow uint32_t irqstat = d->port_regs.irq_stat | irq; 235f6ad2e32SAlexander Graf 2365fa0feecSJohn Snow trace_ahci_trigger_irq(s, d->port_no, 2375fa0feecSJohn Snow AHCIPortIRQ_lookup[irqbit], irq, 2385fa0feecSJohn Snow d->port_regs.irq_stat, irqstat, 2395fa0feecSJohn Snow irqstat & d->port_regs.irq_mask); 2405fa0feecSJohn Snow 2415fa0feecSJohn Snow d->port_regs.irq_stat = irqstat; 242f6ad2e32SAlexander Graf ahci_check_irq(s); 243f6ad2e32SAlexander Graf } 244f6ad2e32SAlexander Graf 2455a18e67dSLe Tan static void map_page(AddressSpace *as, uint8_t **ptr, uint64_t addr, 2465a18e67dSLe Tan uint32_t wanted) 247f6ad2e32SAlexander Graf { 248a8170e5eSAvi Kivity hwaddr len = wanted; 249f6ad2e32SAlexander Graf 250f6ad2e32SAlexander Graf if (*ptr) { 2515a18e67dSLe Tan dma_memory_unmap(as, *ptr, len, DMA_DIRECTION_FROM_DEVICE, len); 252f6ad2e32SAlexander Graf } 253f6ad2e32SAlexander Graf 254a1d4b0a3SPhilippe Mathieu-Daudé *ptr = dma_memory_map(as, addr, &len, DMA_DIRECTION_FROM_DEVICE, 255a1d4b0a3SPhilippe Mathieu-Daudé MEMTXATTRS_UNSPECIFIED); 2561d1c4bdbSPhilippe Mathieu-Daudé if (len < wanted && *ptr) { 2575a18e67dSLe Tan dma_memory_unmap(as, *ptr, len, DMA_DIRECTION_FROM_DEVICE, len); 258f6ad2e32SAlexander Graf *ptr = NULL; 259f6ad2e32SAlexander Graf } 260f6ad2e32SAlexander Graf } 261f6ad2e32SAlexander Graf 262cd6cb73bSJohn Snow /** 263cd6cb73bSJohn Snow * Check the cmd register to see if we should start or stop 264cd6cb73bSJohn Snow * the DMA or FIS RX engines. 265cd6cb73bSJohn Snow * 266d5904749SJohn Snow * @ad: Device to dis/engage. 267cd6cb73bSJohn Snow * 268cd6cb73bSJohn Snow * @return 0 on success, -1 on error. 269cd6cb73bSJohn Snow */ 270d5904749SJohn Snow static int ahci_cond_start_engines(AHCIDevice *ad) 271cd6cb73bSJohn Snow { 272cd6cb73bSJohn Snow AHCIPortRegs *pr = &ad->port_regs; 273d5904749SJohn Snow bool cmd_start = pr->cmd & PORT_CMD_START; 274d5904749SJohn Snow bool cmd_on = pr->cmd & PORT_CMD_LIST_ON; 275d5904749SJohn Snow bool fis_start = pr->cmd & PORT_CMD_FIS_RX; 276d5904749SJohn Snow bool fis_on = pr->cmd & PORT_CMD_FIS_ON; 277cd6cb73bSJohn Snow 278d5904749SJohn Snow if (cmd_start && !cmd_on) { 279f32a2f33SJohn Snow if (!ahci_map_clb_address(ad)) { 280d5904749SJohn Snow pr->cmd &= ~PORT_CMD_START; 281cd6cb73bSJohn Snow error_report("AHCI: Failed to start DMA engine: " 282cd6cb73bSJohn Snow "bad command list buffer address"); 283cd6cb73bSJohn Snow return -1; 284cd6cb73bSJohn Snow } 285d5904749SJohn Snow } else if (!cmd_start && cmd_on) { 286cd6cb73bSJohn Snow ahci_unmap_clb_address(ad); 287cd6cb73bSJohn Snow } 288cd6cb73bSJohn Snow 289d5904749SJohn Snow if (fis_start && !fis_on) { 290f32a2f33SJohn Snow if (!ahci_map_fis_address(ad)) { 291d5904749SJohn Snow pr->cmd &= ~PORT_CMD_FIS_RX; 292cd6cb73bSJohn Snow error_report("AHCI: Failed to start FIS receive engine: " 293cd6cb73bSJohn Snow "bad FIS receive buffer address"); 294cd6cb73bSJohn Snow return -1; 295cd6cb73bSJohn Snow } 296d5904749SJohn Snow } else if (!fis_start && fis_on) { 297cd6cb73bSJohn Snow ahci_unmap_fis_address(ad); 298cd6cb73bSJohn Snow } 299cd6cb73bSJohn Snow 300cd6cb73bSJohn Snow return 0; 301cd6cb73bSJohn Snow } 302cd6cb73bSJohn Snow 303f6ad2e32SAlexander Graf static void ahci_port_write(AHCIState *s, int port, int offset, uint32_t val) 304f6ad2e32SAlexander Graf { 305f6ad2e32SAlexander Graf AHCIPortRegs *pr = &s->dev[port].port_regs; 306f647f458SJohn Snow enum AHCIPortReg regnum = offset / sizeof(uint32_t); 307f647f458SJohn Snow assert(regnum < (AHCI_PORT_ADDR_OFFSET_LEN / sizeof(uint32_t))); 30806e35065SJohn Snow trace_ahci_port_write(s, port, AHCIPortReg_lookup[regnum], offset, val); 309f6ad2e32SAlexander Graf 310f647f458SJohn Snow switch (regnum) { 311f647f458SJohn Snow case AHCI_PORT_REG_LST_ADDR: 312f6ad2e32SAlexander Graf pr->lst_addr = val; 313f6ad2e32SAlexander Graf break; 314f647f458SJohn Snow case AHCI_PORT_REG_LST_ADDR_HI: 315f6ad2e32SAlexander Graf pr->lst_addr_hi = val; 316f6ad2e32SAlexander Graf break; 317f647f458SJohn Snow case AHCI_PORT_REG_FIS_ADDR: 318f6ad2e32SAlexander Graf pr->fis_addr = val; 319f6ad2e32SAlexander Graf break; 320f647f458SJohn Snow case AHCI_PORT_REG_FIS_ADDR_HI: 321f6ad2e32SAlexander Graf pr->fis_addr_hi = val; 322f6ad2e32SAlexander Graf break; 323f647f458SJohn Snow case AHCI_PORT_REG_IRQ_STAT: 324f6ad2e32SAlexander Graf pr->irq_stat &= ~val; 325b8676728SAlexander Graf ahci_check_irq(s); 326f6ad2e32SAlexander Graf break; 327f647f458SJohn Snow case AHCI_PORT_REG_IRQ_MASK: 328f6ad2e32SAlexander Graf pr->irq_mask = val & 0xfdc000ff; 329f6ad2e32SAlexander Graf ahci_check_irq(s); 330f6ad2e32SAlexander Graf break; 331f647f458SJohn Snow case AHCI_PORT_REG_CMD: 332d73b84d0SNiklas Cassel if ((pr->cmd & PORT_CMD_START) && !(val & PORT_CMD_START)) { 333d73b84d0SNiklas Cassel pr->scr_act = 0; 334d73b84d0SNiklas Cassel pr->cmd_issue = 0; 335d73b84d0SNiklas Cassel } 336d73b84d0SNiklas Cassel 337fc3d8e11SJohn Snow /* Block any Read-only fields from being set; 33809b61db7SStefan Fritsch * including LIST_ON and FIS_ON. 33909b61db7SStefan Fritsch * The spec requires to set ICC bits to zero after the ICC change 34009b61db7SStefan Fritsch * is done. We don't support ICC state changes, therefore always 34109b61db7SStefan Fritsch * force the ICC bits to zero. 34209b61db7SStefan Fritsch */ 34309b61db7SStefan Fritsch pr->cmd = (pr->cmd & PORT_CMD_RO_MASK) | 34409b61db7SStefan Fritsch (val & ~(PORT_CMD_RO_MASK | PORT_CMD_ICC_MASK)); 345f6ad2e32SAlexander Graf 346d5904749SJohn Snow /* Check FIS RX and CLB engines */ 347d5904749SJohn Snow ahci_cond_start_engines(&s->dev[port]); 348f6ad2e32SAlexander Graf 34987e62065SAlexander Graf /* XXX usually the FIS would be pending on the bus here and 35087e62065SAlexander Graf issuing deferred until the OS enables FIS receival. 35187e62065SAlexander Graf Instead, we only submit it once - which works in most 35287e62065SAlexander Graf cases, but is a hack. */ 35387e62065SAlexander Graf if ((pr->cmd & PORT_CMD_FIS_ON) && 35487e62065SAlexander Graf !s->dev[port].init_d2h_sent) { 35587e62065SAlexander Graf ahci_init_d2h(&s->dev[port]); 35687e62065SAlexander Graf } 35787e62065SAlexander Graf 358f6ad2e32SAlexander Graf check_cmd(s, port); 359f6ad2e32SAlexander Graf break; 360f647f458SJohn Snow case AHCI_PORT_REG_TFDATA: 361f647f458SJohn Snow case AHCI_PORT_REG_SIG: 362f647f458SJohn Snow case AHCI_PORT_REG_SCR_STAT: 363fac7aa7fSJohn Snow /* Read Only */ 364f6ad2e32SAlexander Graf break; 365f647f458SJohn Snow case AHCI_PORT_REG_SCR_CTL: 366f6ad2e32SAlexander Graf if (((pr->scr_ctl & AHCI_SCR_SCTL_DET) == 1) && 367f6ad2e32SAlexander Graf ((val & AHCI_SCR_SCTL_DET) == 0)) { 368f6ad2e32SAlexander Graf ahci_reset_port(s, port); 369f6ad2e32SAlexander Graf } 370f6ad2e32SAlexander Graf pr->scr_ctl = val; 371f6ad2e32SAlexander Graf break; 372f647f458SJohn Snow case AHCI_PORT_REG_SCR_ERR: 373f6ad2e32SAlexander Graf pr->scr_err &= ~val; 374f6ad2e32SAlexander Graf break; 375f647f458SJohn Snow case AHCI_PORT_REG_SCR_ACT: 376f6ad2e32SAlexander Graf /* RW1 */ 377f6ad2e32SAlexander Graf pr->scr_act |= val; 378f6ad2e32SAlexander Graf break; 379f647f458SJohn Snow case AHCI_PORT_REG_CMD_ISSUE: 380f6ad2e32SAlexander Graf pr->cmd_issue |= val; 381f6ad2e32SAlexander Graf check_cmd(s, port); 382f6ad2e32SAlexander Graf break; 383f6ad2e32SAlexander Graf default: 38406e35065SJohn Snow trace_ahci_port_write_unimpl(s, port, AHCIPortReg_lookup[regnum], 38506e35065SJohn Snow offset, val); 38606e35065SJohn Snow qemu_log_mask(LOG_UNIMP, "Attempted write to unimplemented register: " 38706e35065SJohn Snow "AHCI port %d register %s, offset 0x%x: 0x%"PRIx32, 38806e35065SJohn Snow port, AHCIPortReg_lookup[regnum], offset, val); 389f6ad2e32SAlexander Graf break; 390f6ad2e32SAlexander Graf } 391f6ad2e32SAlexander Graf } 392f6ad2e32SAlexander Graf 393e9ebb2f7SJohn Snow static uint64_t ahci_mem_read_32(void *opaque, hwaddr addr) 394f6ad2e32SAlexander Graf { 39567e576c2SAvi Kivity AHCIState *s = opaque; 396f6ad2e32SAlexander Graf uint32_t val = 0; 397f6ad2e32SAlexander Graf 398f6ad2e32SAlexander Graf if (addr < AHCI_GENERIC_HOST_CONTROL_REGS_MAX_ADDR) { 399215c41aaSJohn Snow enum AHCIHostReg regnum = addr / 4; 400215c41aaSJohn Snow assert(regnum < AHCI_HOST_REG__COUNT); 401215c41aaSJohn Snow 402215c41aaSJohn Snow switch (regnum) { 403215c41aaSJohn Snow case AHCI_HOST_REG_CAP: 404f6ad2e32SAlexander Graf val = s->control_regs.cap; 405f6ad2e32SAlexander Graf break; 406215c41aaSJohn Snow case AHCI_HOST_REG_CTL: 407f6ad2e32SAlexander Graf val = s->control_regs.ghc; 408f6ad2e32SAlexander Graf break; 409215c41aaSJohn Snow case AHCI_HOST_REG_IRQ_STAT: 410f6ad2e32SAlexander Graf val = s->control_regs.irqstatus; 411f6ad2e32SAlexander Graf break; 412215c41aaSJohn Snow case AHCI_HOST_REG_PORTS_IMPL: 413f6ad2e32SAlexander Graf val = s->control_regs.impl; 414f6ad2e32SAlexander Graf break; 415215c41aaSJohn Snow case AHCI_HOST_REG_VERSION: 416f6ad2e32SAlexander Graf val = s->control_regs.version; 417f6ad2e32SAlexander Graf break; 418215c41aaSJohn Snow default: 4199da8ac32SJohn Snow trace_ahci_mem_read_32_host_default(s, AHCIHostReg_lookup[regnum], 4209da8ac32SJohn Snow addr); 421f6ad2e32SAlexander Graf } 4229da8ac32SJohn Snow trace_ahci_mem_read_32_host(s, AHCIHostReg_lookup[regnum], addr, val); 423f6ad2e32SAlexander Graf } else if ((addr >= AHCI_PORT_REGS_START_ADDR) && 4242c4b9d0eSAlexander Graf (addr < (AHCI_PORT_REGS_START_ADDR + 4252c4b9d0eSAlexander Graf (s->ports * AHCI_PORT_ADDR_OFFSET_LEN)))) { 426f6ad2e32SAlexander Graf val = ahci_port_read(s, (addr - AHCI_PORT_REGS_START_ADDR) >> 7, 427f6ad2e32SAlexander Graf addr & AHCI_PORT_ADDR_OFFSET_MASK); 4289da8ac32SJohn Snow } else { 4299da8ac32SJohn Snow trace_ahci_mem_read_32_default(s, addr, val); 430f6ad2e32SAlexander Graf } 431f6ad2e32SAlexander Graf 432e4baa9f0SJohn Snow trace_ahci_mem_read_32(s, addr, val); 433f6ad2e32SAlexander Graf return val; 434f6ad2e32SAlexander Graf } 435f6ad2e32SAlexander Graf 436f6ad2e32SAlexander Graf 437e9ebb2f7SJohn Snow /** 438e9ebb2f7SJohn Snow * AHCI 1.3 section 3 ("HBA Memory Registers") 439e9ebb2f7SJohn Snow * Support unaligned 8/16/32 bit reads, and 64 bit aligned reads. 440e9ebb2f7SJohn Snow * Caller is responsible for masking unwanted higher order bytes. 441e9ebb2f7SJohn Snow */ 442e9ebb2f7SJohn Snow static uint64_t ahci_mem_read(void *opaque, hwaddr addr, unsigned size) 443e9ebb2f7SJohn Snow { 444e9ebb2f7SJohn Snow hwaddr aligned = addr & ~0x3; 445e9ebb2f7SJohn Snow int ofst = addr - aligned; 446e9ebb2f7SJohn Snow uint64_t lo = ahci_mem_read_32(opaque, aligned); 447e9ebb2f7SJohn Snow uint64_t hi; 44880274267SPeter Crosthwaite uint64_t val; 449e9ebb2f7SJohn Snow 450e9ebb2f7SJohn Snow /* if < 8 byte read does not cross 4 byte boundary */ 451e9ebb2f7SJohn Snow if (ofst + size <= 4) { 45280274267SPeter Crosthwaite val = lo >> (ofst * 8); 45380274267SPeter Crosthwaite } else { 454719a3077SMarkus Armbruster g_assert(size > 1); 455e9ebb2f7SJohn Snow 456e9ebb2f7SJohn Snow /* If the 64bit read is unaligned, we will produce undefined 457e9ebb2f7SJohn Snow * results. AHCI does not support unaligned 64bit reads. */ 458e9ebb2f7SJohn Snow hi = ahci_mem_read_32(opaque, aligned + 4); 45980274267SPeter Crosthwaite val = (hi << 32 | lo) >> (ofst * 8); 46080274267SPeter Crosthwaite } 46180274267SPeter Crosthwaite 462e4baa9f0SJohn Snow trace_ahci_mem_read(opaque, size, addr, val); 46380274267SPeter Crosthwaite return val; 464e9ebb2f7SJohn Snow } 465e9ebb2f7SJohn Snow 466f6ad2e32SAlexander Graf 467a8170e5eSAvi Kivity static void ahci_mem_write(void *opaque, hwaddr addr, 46867e576c2SAvi Kivity uint64_t val, unsigned size) 469f6ad2e32SAlexander Graf { 47067e576c2SAvi Kivity AHCIState *s = opaque; 471f6ad2e32SAlexander Graf 472e4baa9f0SJohn Snow trace_ahci_mem_write(s, size, addr, val); 47380274267SPeter Crosthwaite 474f6ad2e32SAlexander Graf /* Only aligned reads are allowed on AHCI */ 475f6ad2e32SAlexander Graf if (addr & 3) { 476580e7333SPhilippe Mathieu-Daudé qemu_log_mask(LOG_GUEST_ERROR, 477580e7333SPhilippe Mathieu-Daudé "ahci: Mis-aligned write to addr 0x%03" HWADDR_PRIX "\n", 478580e7333SPhilippe Mathieu-Daudé addr); 479f6ad2e32SAlexander Graf return; 480f6ad2e32SAlexander Graf } 481f6ad2e32SAlexander Graf 482f6ad2e32SAlexander Graf if (addr < AHCI_GENERIC_HOST_CONTROL_REGS_MAX_ADDR) { 483d566811aSJohn Snow enum AHCIHostReg regnum = addr / 4; 484d566811aSJohn Snow assert(regnum < AHCI_HOST_REG__COUNT); 485d566811aSJohn Snow 486d566811aSJohn Snow switch (regnum) { 487d566811aSJohn Snow case AHCI_HOST_REG_CAP: /* R/WO, RO */ 488f6ad2e32SAlexander Graf /* FIXME handle R/WO */ 489f6ad2e32SAlexander Graf break; 490d566811aSJohn Snow case AHCI_HOST_REG_CTL: /* R/W */ 491f6ad2e32SAlexander Graf if (val & HOST_CTL_RESET) { 4928ab60a07SJan Kiszka ahci_reset(s); 493f6ad2e32SAlexander Graf } else { 494f6ad2e32SAlexander Graf s->control_regs.ghc = (val & 0x3) | HOST_CTL_AHCI_EN; 495f6ad2e32SAlexander Graf ahci_check_irq(s); 496f6ad2e32SAlexander Graf } 497f6ad2e32SAlexander Graf break; 498d566811aSJohn Snow case AHCI_HOST_REG_IRQ_STAT: /* R/WC, RO */ 499f6ad2e32SAlexander Graf s->control_regs.irqstatus &= ~val; 500f6ad2e32SAlexander Graf ahci_check_irq(s); 501f6ad2e32SAlexander Graf break; 502d566811aSJohn Snow case AHCI_HOST_REG_PORTS_IMPL: /* R/WO, RO */ 503f6ad2e32SAlexander Graf /* FIXME handle R/WO */ 504f6ad2e32SAlexander Graf break; 505d566811aSJohn Snow case AHCI_HOST_REG_VERSION: /* RO */ 506f6ad2e32SAlexander Graf /* FIXME report write? */ 507f6ad2e32SAlexander Graf break; 508f6ad2e32SAlexander Graf default: 50901796126SJohn Snow qemu_log_mask(LOG_UNIMP, 51001796126SJohn Snow "Attempted write to unimplemented register: " 51101796126SJohn Snow "AHCI host register %s, " 51201796126SJohn Snow "offset 0x%"PRIx64": 0x%"PRIx64, 51301796126SJohn Snow AHCIHostReg_lookup[regnum], addr, val); 51401796126SJohn Snow trace_ahci_mem_write_host_unimpl(s, size, 51501796126SJohn Snow AHCIHostReg_lookup[regnum], addr); 516f6ad2e32SAlexander Graf } 51701796126SJohn Snow trace_ahci_mem_write_host(s, size, AHCIHostReg_lookup[regnum], 51801796126SJohn Snow addr, val); 519f6ad2e32SAlexander Graf } else if ((addr >= AHCI_PORT_REGS_START_ADDR) && 5202c4b9d0eSAlexander Graf (addr < (AHCI_PORT_REGS_START_ADDR + 5212c4b9d0eSAlexander Graf (s->ports * AHCI_PORT_ADDR_OFFSET_LEN)))) { 522f6ad2e32SAlexander Graf ahci_port_write(s, (addr - AHCI_PORT_REGS_START_ADDR) >> 7, 523f6ad2e32SAlexander Graf addr & AHCI_PORT_ADDR_OFFSET_MASK, val); 52401796126SJohn Snow } else { 52501796126SJohn Snow qemu_log_mask(LOG_UNIMP, "Attempted write to unimplemented register: " 52601796126SJohn Snow "AHCI global register at offset 0x%"PRIx64": 0x%"PRIx64, 52701796126SJohn Snow addr, val); 52801796126SJohn Snow trace_ahci_mem_write_unimpl(s, size, addr, val); 529f6ad2e32SAlexander Graf } 530f6ad2e32SAlexander Graf } 531f6ad2e32SAlexander Graf 532a348f108SStefan Weil static const MemoryRegionOps ahci_mem_ops = { 53367e576c2SAvi Kivity .read = ahci_mem_read, 53467e576c2SAvi Kivity .write = ahci_mem_write, 53567e576c2SAvi Kivity .endianness = DEVICE_LITTLE_ENDIAN, 536f6ad2e32SAlexander Graf }; 537f6ad2e32SAlexander Graf 538a8170e5eSAvi Kivity static uint64_t ahci_idp_read(void *opaque, hwaddr addr, 539465f1ab1SDaniel Verkamp unsigned size) 540465f1ab1SDaniel Verkamp { 541465f1ab1SDaniel Verkamp AHCIState *s = opaque; 542465f1ab1SDaniel Verkamp 543465f1ab1SDaniel Verkamp if (addr == s->idp_offset) { 544465f1ab1SDaniel Verkamp /* index register */ 545465f1ab1SDaniel Verkamp return s->idp_index; 546465f1ab1SDaniel Verkamp } else if (addr == s->idp_offset + 4) { 547465f1ab1SDaniel Verkamp /* data register - do memory read at location selected by index */ 548465f1ab1SDaniel Verkamp return ahci_mem_read(opaque, s->idp_index, size); 549465f1ab1SDaniel Verkamp } else { 550465f1ab1SDaniel Verkamp return 0; 551465f1ab1SDaniel Verkamp } 552465f1ab1SDaniel Verkamp } 553465f1ab1SDaniel Verkamp 554a8170e5eSAvi Kivity static void ahci_idp_write(void *opaque, hwaddr addr, 555465f1ab1SDaniel Verkamp uint64_t val, unsigned size) 556465f1ab1SDaniel Verkamp { 557465f1ab1SDaniel Verkamp AHCIState *s = opaque; 558465f1ab1SDaniel Verkamp 559465f1ab1SDaniel Verkamp if (addr == s->idp_offset) { 560465f1ab1SDaniel Verkamp /* index register - mask off reserved bits */ 561465f1ab1SDaniel Verkamp s->idp_index = (uint32_t)val & ((AHCI_MEM_BAR_SIZE - 1) & ~3); 562465f1ab1SDaniel Verkamp } else if (addr == s->idp_offset + 4) { 563465f1ab1SDaniel Verkamp /* data register - do memory write at location selected by index */ 564465f1ab1SDaniel Verkamp ahci_mem_write(opaque, s->idp_index, val, size); 565465f1ab1SDaniel Verkamp } 566465f1ab1SDaniel Verkamp } 567465f1ab1SDaniel Verkamp 568a348f108SStefan Weil static const MemoryRegionOps ahci_idp_ops = { 569465f1ab1SDaniel Verkamp .read = ahci_idp_read, 570465f1ab1SDaniel Verkamp .write = ahci_idp_write, 571465f1ab1SDaniel Verkamp .endianness = DEVICE_LITTLE_ENDIAN, 572465f1ab1SDaniel Verkamp }; 573465f1ab1SDaniel Verkamp 574465f1ab1SDaniel Verkamp 575f6ad2e32SAlexander Graf static void ahci_reg_init(AHCIState *s) 576f6ad2e32SAlexander Graf { 577f6ad2e32SAlexander Graf int i; 578f6ad2e32SAlexander Graf 5792c4b9d0eSAlexander Graf s->control_regs.cap = (s->ports - 1) | 580f6ad2e32SAlexander Graf (AHCI_NUM_COMMAND_SLOTS << 8) | 581f6ad2e32SAlexander Graf (AHCI_SUPPORTED_SPEED_GEN1 << AHCI_SUPPORTED_SPEED) | 58298cb5dccSLadi Prosek HOST_CAP_NCQ | HOST_CAP_AHCI | HOST_CAP_64; 583f6ad2e32SAlexander Graf 5842c4b9d0eSAlexander Graf s->control_regs.impl = (1 << s->ports) - 1; 585f6ad2e32SAlexander Graf 586f6ad2e32SAlexander Graf s->control_regs.version = AHCI_VERSION_1_0; 587f6ad2e32SAlexander Graf 5882c4b9d0eSAlexander Graf for (i = 0; i < s->ports; i++) { 589f6ad2e32SAlexander Graf s->dev[i].port_state = STATE_RUN; 590f6ad2e32SAlexander Graf } 591f6ad2e32SAlexander Graf } 592f6ad2e32SAlexander Graf 593f6ad2e32SAlexander Graf static void check_cmd(AHCIState *s, int port) 594f6ad2e32SAlexander Graf { 595f6ad2e32SAlexander Graf AHCIPortRegs *pr = &s->dev[port].port_regs; 5969364384dSJohn Snow uint8_t slot; 597f6ad2e32SAlexander Graf 598f6ad2e32SAlexander Graf if ((pr->cmd & PORT_CMD_START) && pr->cmd_issue) { 599f6ad2e32SAlexander Graf for (slot = 0; (slot < 32) && pr->cmd_issue; slot++) { 600e2a5d9b3SNiklas Cassel if (pr->cmd_issue & (1U << slot)) { 601e2a5d9b3SNiklas Cassel handle_cmd(s, port, slot); 602f6ad2e32SAlexander Graf } 603f6ad2e32SAlexander Graf } 604f6ad2e32SAlexander Graf } 605f6ad2e32SAlexander Graf } 606f6ad2e32SAlexander Graf 607f6ad2e32SAlexander Graf static void ahci_check_cmd_bh(void *opaque) 608f6ad2e32SAlexander Graf { 609f6ad2e32SAlexander Graf AHCIDevice *ad = opaque; 610f6ad2e32SAlexander Graf 611f6ad2e32SAlexander Graf qemu_bh_delete(ad->check_bh); 612f6ad2e32SAlexander Graf ad->check_bh = NULL; 613f6ad2e32SAlexander Graf 614f6ad2e32SAlexander Graf check_cmd(ad->hba, ad->port_no); 615f6ad2e32SAlexander Graf } 616f6ad2e32SAlexander Graf 61787e62065SAlexander Graf static void ahci_init_d2h(AHCIDevice *ad) 61887e62065SAlexander Graf { 61987e62065SAlexander Graf IDEState *ide_state = &ad->port.ifs[0]; 62033a983cbSJohn Snow AHCIPortRegs *pr = &ad->port_regs; 62187e62065SAlexander Graf 622e47f9eb1SJohn Snow if (ad->init_d2h_sent) { 623e47f9eb1SJohn Snow return; 624e47f9eb1SJohn Snow } 625e47f9eb1SJohn Snow 6262967dc82SNiklas Cassel if (ahci_write_fis_d2h(ad, true)) { 627e47f9eb1SJohn Snow ad->init_d2h_sent = true; 62833a983cbSJohn Snow /* We're emulating receiving the first Reg H2D Fis from the device; 62933a983cbSJohn Snow * Update the SIG register, but otherwise proceed as normal. */ 63040fe17beSPeter Maydell pr->sig = ((uint32_t)ide_state->hcyl << 24) | 63133a983cbSJohn Snow (ide_state->lcyl << 16) | 63233a983cbSJohn Snow (ide_state->sector << 8) | 63333a983cbSJohn Snow (ide_state->nsector & 0xFF); 634e47f9eb1SJohn Snow } 63587e62065SAlexander Graf } 63687e62065SAlexander Graf 63733a983cbSJohn Snow static void ahci_set_signature(AHCIDevice *ad, uint32_t sig) 63833a983cbSJohn Snow { 63933a983cbSJohn Snow IDEState *s = &ad->port.ifs[0]; 64033a983cbSJohn Snow s->hcyl = sig >> 24 & 0xFF; 64133a983cbSJohn Snow s->lcyl = sig >> 16 & 0xFF; 64233a983cbSJohn Snow s->sector = sig >> 8 & 0xFF; 64333a983cbSJohn Snow s->nsector = sig & 0xFF; 64433a983cbSJohn Snow 645e4baa9f0SJohn Snow trace_ahci_set_signature(ad->hba, ad->port_no, s->nsector, s->sector, 646e4baa9f0SJohn Snow s->lcyl, s->hcyl, sig); 64733a983cbSJohn Snow } 64833a983cbSJohn Snow 649f6ad2e32SAlexander Graf static void ahci_reset_port(AHCIState *s, int port) 650f6ad2e32SAlexander Graf { 651f6ad2e32SAlexander Graf AHCIDevice *d = &s->dev[port]; 652f6ad2e32SAlexander Graf AHCIPortRegs *pr = &d->port_regs; 653f6ad2e32SAlexander Graf IDEState *ide_state = &d->port.ifs[0]; 654f6ad2e32SAlexander Graf int i; 655f6ad2e32SAlexander Graf 656e4baa9f0SJohn Snow trace_ahci_reset_port(s, port); 657f6ad2e32SAlexander Graf 658f6ad2e32SAlexander Graf ide_bus_reset(&d->port); 659f6ad2e32SAlexander Graf ide_state->ncq_queues = AHCI_MAX_CMDS; 660f6ad2e32SAlexander Graf 661f6ad2e32SAlexander Graf pr->scr_stat = 0; 662f6ad2e32SAlexander Graf pr->scr_err = 0; 663f6ad2e32SAlexander Graf pr->scr_act = 0; 664fac7aa7fSJohn Snow pr->tfdata = 0x7F; 665fac7aa7fSJohn Snow pr->sig = 0xFFFFFFFF; 666f6ad2e32SAlexander Graf d->busy_slot = -1; 6674ac557c8SKevin Wolf d->init_d2h_sent = false; 668f6ad2e32SAlexander Graf 669f6ad2e32SAlexander Graf ide_state = &s->dev[port].port.ifs[0]; 6704be74634SMarkus Armbruster if (!ide_state->blk) { 671f6ad2e32SAlexander Graf return; 672f6ad2e32SAlexander Graf } 673f6ad2e32SAlexander Graf 674f6ad2e32SAlexander Graf /* reset ncq queue */ 675f6ad2e32SAlexander Graf for (i = 0; i < AHCI_MAX_CMDS; i++) { 676f6ad2e32SAlexander Graf NCQTransferState *ncq_tfs = &s->dev[port].ncq_tfs[i]; 6777c03a691SJohn Snow ncq_tfs->halt = false; 678f6ad2e32SAlexander Graf if (!ncq_tfs->used) { 679f6ad2e32SAlexander Graf continue; 680f6ad2e32SAlexander Graf } 681f6ad2e32SAlexander Graf 682f6ad2e32SAlexander Graf if (ncq_tfs->aiocb) { 6834be74634SMarkus Armbruster blk_aio_cancel(ncq_tfs->aiocb); 684f6ad2e32SAlexander Graf ncq_tfs->aiocb = NULL; 685f6ad2e32SAlexander Graf } 686f6ad2e32SAlexander Graf 6874be74634SMarkus Armbruster /* Maybe we just finished the request thanks to blk_aio_cancel() */ 688c9b308d2SAlexander Graf if (!ncq_tfs->used) { 689c9b308d2SAlexander Graf continue; 690c9b308d2SAlexander Graf } 691c9b308d2SAlexander Graf 692f6ad2e32SAlexander Graf qemu_sglist_destroy(&ncq_tfs->sglist); 693f6ad2e32SAlexander Graf ncq_tfs->used = 0; 694f6ad2e32SAlexander Graf } 695f6ad2e32SAlexander Graf 696f6ad2e32SAlexander Graf s->dev[port].port_state = STATE_RUN; 697f91a0aa3SJohn Snow if (ide_state->drive_kind == IDE_CD) { 698af33a321SNiklas Cassel ahci_set_signature(d, SATA_SIGNATURE_CDROM); 699f6ad2e32SAlexander Graf ide_state->status = SEEK_STAT | WRERR_STAT | READY_STAT; 700f6ad2e32SAlexander Graf } else { 70133a983cbSJohn Snow ahci_set_signature(d, SATA_SIGNATURE_DISK); 702f6ad2e32SAlexander Graf ide_state->status = SEEK_STAT | WRERR_STAT; 703f6ad2e32SAlexander Graf } 704f6ad2e32SAlexander Graf 705f6ad2e32SAlexander Graf ide_state->error = 1; 70687e62065SAlexander Graf ahci_init_d2h(d); 707f6ad2e32SAlexander Graf } 708f6ad2e32SAlexander Graf 709797285c8SJohn Snow /* Buffer pretty output based on a raw FIS structure. */ 71026941eb4SAlexander Bulekov static char *ahci_pretty_buffer_fis(const uint8_t *fis, int cmd_len) 711f6ad2e32SAlexander Graf { 712f6ad2e32SAlexander Graf int i; 713797285c8SJohn Snow GString *s = g_string_new("FIS:"); 714f6ad2e32SAlexander Graf 715f6ad2e32SAlexander Graf for (i = 0; i < cmd_len; i++) { 716f6ad2e32SAlexander Graf if ((i & 0xf) == 0) { 717797285c8SJohn Snow g_string_append_printf(s, "\n0x%02x: ", i); 718f6ad2e32SAlexander Graf } 719797285c8SJohn Snow g_string_append_printf(s, "%02x ", fis[i]); 720f6ad2e32SAlexander Graf } 721797285c8SJohn Snow g_string_append_c(s, '\n'); 722797285c8SJohn Snow 723797285c8SJohn Snow return g_string_free(s, FALSE); 724f6ad2e32SAlexander Graf } 725f6ad2e32SAlexander Graf 726a13ab5a3SJohn Snow static bool ahci_map_fis_address(AHCIDevice *ad) 727a13ab5a3SJohn Snow { 728a13ab5a3SJohn Snow AHCIPortRegs *pr = &ad->port_regs; 729a13ab5a3SJohn Snow map_page(ad->hba->as, &ad->res_fis, 730a13ab5a3SJohn Snow ((uint64_t)pr->fis_addr_hi << 32) | pr->fis_addr, 256); 731f32a2f33SJohn Snow if (ad->res_fis != NULL) { 732f32a2f33SJohn Snow pr->cmd |= PORT_CMD_FIS_ON; 733f32a2f33SJohn Snow return true; 734f32a2f33SJohn Snow } 735f32a2f33SJohn Snow 736f32a2f33SJohn Snow pr->cmd &= ~PORT_CMD_FIS_ON; 737f32a2f33SJohn Snow return false; 738a13ab5a3SJohn Snow } 739a13ab5a3SJohn Snow 740fc3d8e11SJohn Snow static void ahci_unmap_fis_address(AHCIDevice *ad) 741fc3d8e11SJohn Snow { 74299b4cb71SJohn Snow if (ad->res_fis == NULL) { 743e4baa9f0SJohn Snow trace_ahci_unmap_fis_address_null(ad->hba, ad->port_no); 74499b4cb71SJohn Snow return; 74599b4cb71SJohn Snow } 746f32a2f33SJohn Snow ad->port_regs.cmd &= ~PORT_CMD_FIS_ON; 747fc3d8e11SJohn Snow dma_memory_unmap(ad->hba->as, ad->res_fis, 256, 748fc3d8e11SJohn Snow DMA_DIRECTION_FROM_DEVICE, 256); 749fc3d8e11SJohn Snow ad->res_fis = NULL; 750fc3d8e11SJohn Snow } 751fc3d8e11SJohn Snow 752a13ab5a3SJohn Snow static bool ahci_map_clb_address(AHCIDevice *ad) 753a13ab5a3SJohn Snow { 754a13ab5a3SJohn Snow AHCIPortRegs *pr = &ad->port_regs; 755a13ab5a3SJohn Snow ad->cur_cmd = NULL; 756a13ab5a3SJohn Snow map_page(ad->hba->as, &ad->lst, 757a13ab5a3SJohn Snow ((uint64_t)pr->lst_addr_hi << 32) | pr->lst_addr, 1024); 758f32a2f33SJohn Snow if (ad->lst != NULL) { 759f32a2f33SJohn Snow pr->cmd |= PORT_CMD_LIST_ON; 760f32a2f33SJohn Snow return true; 761f32a2f33SJohn Snow } 762f32a2f33SJohn Snow 763f32a2f33SJohn Snow pr->cmd &= ~PORT_CMD_LIST_ON; 764f32a2f33SJohn Snow return false; 765a13ab5a3SJohn Snow } 766a13ab5a3SJohn Snow 767fc3d8e11SJohn Snow static void ahci_unmap_clb_address(AHCIDevice *ad) 768fc3d8e11SJohn Snow { 76999b4cb71SJohn Snow if (ad->lst == NULL) { 770e4baa9f0SJohn Snow trace_ahci_unmap_clb_address_null(ad->hba, ad->port_no); 77199b4cb71SJohn Snow return; 77299b4cb71SJohn Snow } 773f32a2f33SJohn Snow ad->port_regs.cmd &= ~PORT_CMD_LIST_ON; 774fc3d8e11SJohn Snow dma_memory_unmap(ad->hba->as, ad->lst, 1024, 775fc3d8e11SJohn Snow DMA_DIRECTION_FROM_DEVICE, 1024); 776fc3d8e11SJohn Snow ad->lst = NULL; 777fc3d8e11SJohn Snow } 778fc3d8e11SJohn Snow 7797c649ac5SJohn Snow static void ahci_write_fis_sdb(AHCIState *s, NCQTransferState *ncq_tfs) 780f6ad2e32SAlexander Graf { 7817c649ac5SJohn Snow AHCIDevice *ad = ncq_tfs->drive; 782fac7aa7fSJohn Snow AHCIPortRegs *pr = &ad->port_regs; 783f6ad2e32SAlexander Graf IDEState *ide_state; 78454a7f8f3SJohn Snow SDBFIS *sdb_fis; 785f6ad2e32SAlexander Graf 7867c649ac5SJohn Snow if (!ad->res_fis || 787f6ad2e32SAlexander Graf !(pr->cmd & PORT_CMD_FIS_RX)) { 788f6ad2e32SAlexander Graf return; 789f6ad2e32SAlexander Graf } 790f6ad2e32SAlexander Graf 79154a7f8f3SJohn Snow sdb_fis = (SDBFIS *)&ad->res_fis[RES_FIS_SDBFIS]; 792fac7aa7fSJohn Snow ide_state = &ad->port.ifs[0]; 793f6ad2e32SAlexander Graf 79417fcb74aSStefan Hajnoczi sdb_fis->type = SATA_FIS_TYPE_SDB; 79554a7f8f3SJohn Snow /* Interrupt pending & Notification bit */ 7967c649ac5SJohn Snow sdb_fis->flags = 0x40; /* Interrupt bit, always 1 for NCQ */ 79754a7f8f3SJohn Snow sdb_fis->status = ide_state->status & 0x77; 79854a7f8f3SJohn Snow sdb_fis->error = ide_state->error; 79954a7f8f3SJohn Snow /* update SAct field in SDB_FIS */ 80054a7f8f3SJohn Snow sdb_fis->payload = cpu_to_le32(ad->finished); 801f6ad2e32SAlexander Graf 802fac7aa7fSJohn Snow /* Update shadow registers (except BSY 0x80 and DRQ 0x08) */ 803fac7aa7fSJohn Snow pr->tfdata = (ad->port.ifs[0].error << 8) | 804fac7aa7fSJohn Snow (ad->port.ifs[0].status & 0x77) | 805fac7aa7fSJohn Snow (pr->tfdata & 0x88); 8067c649ac5SJohn Snow pr->scr_act &= ~ad->finished; 8077c649ac5SJohn Snow ad->finished = 0; 808fac7aa7fSJohn Snow 8097e85cb0dSNiklas Cassel /* 8107e85cb0dSNiklas Cassel * TFES IRQ is always raised if ERR_STAT is set, regardless of I bit. 8117e85cb0dSNiklas Cassel * If ERR_STAT is not set, trigger SDBS IRQ if interrupt bit is set 8127e85cb0dSNiklas Cassel * (which currently, it always is). 8137e85cb0dSNiklas Cassel */ 8147e85cb0dSNiklas Cassel if (sdb_fis->status & ERR_STAT) { 8157e85cb0dSNiklas Cassel ahci_trigger_irq(s, ad, AHCI_PORT_IRQ_BIT_TFES); 8167e85cb0dSNiklas Cassel } else if (sdb_fis->flags & 0x40) { 8175fa0feecSJohn Snow ahci_trigger_irq(s, ad, AHCI_PORT_IRQ_BIT_SDBS); 818f6ad2e32SAlexander Graf } 8197c649ac5SJohn Snow } 820f6ad2e32SAlexander Graf 821ae79c2dbSPaolo Bonzini static void ahci_write_fis_pio(AHCIDevice *ad, uint16_t len, bool pio_fis_i) 82208841520SPaolo Bonzini { 82308841520SPaolo Bonzini AHCIPortRegs *pr = &ad->port_regs; 824dd628221SJohn Snow uint8_t *pio_fis; 8257b8bad1bSJohn Snow IDEState *s = &ad->port.ifs[0]; 82608841520SPaolo Bonzini 82708841520SPaolo Bonzini if (!ad->res_fis || !(pr->cmd & PORT_CMD_FIS_RX)) { 82808841520SPaolo Bonzini return; 82908841520SPaolo Bonzini } 83008841520SPaolo Bonzini 83108841520SPaolo Bonzini pio_fis = &ad->res_fis[RES_FIS_PSFIS]; 83208841520SPaolo Bonzini 83317fcb74aSStefan Hajnoczi pio_fis[0] = SATA_FIS_TYPE_PIO_SETUP; 834ae79c2dbSPaolo Bonzini pio_fis[1] = (pio_fis_i ? (1 << 6) : 0); 8357b8bad1bSJohn Snow pio_fis[2] = s->status; 8367b8bad1bSJohn Snow pio_fis[3] = s->error; 83708841520SPaolo Bonzini 8387b8bad1bSJohn Snow pio_fis[4] = s->sector; 8397b8bad1bSJohn Snow pio_fis[5] = s->lcyl; 8407b8bad1bSJohn Snow pio_fis[6] = s->hcyl; 8417b8bad1bSJohn Snow pio_fis[7] = s->select; 8427b8bad1bSJohn Snow pio_fis[8] = s->hob_sector; 8437b8bad1bSJohn Snow pio_fis[9] = s->hob_lcyl; 8447b8bad1bSJohn Snow pio_fis[10] = s->hob_hcyl; 8457b8bad1bSJohn Snow pio_fis[11] = 0; 846dd628221SJohn Snow pio_fis[12] = s->nsector & 0xFF; 847dd628221SJohn Snow pio_fis[13] = (s->nsector >> 8) & 0xFF; 84808841520SPaolo Bonzini pio_fis[14] = 0; 8497b8bad1bSJohn Snow pio_fis[15] = s->status; 85008841520SPaolo Bonzini pio_fis[16] = len & 255; 85108841520SPaolo Bonzini pio_fis[17] = len >> 8; 85208841520SPaolo Bonzini pio_fis[18] = 0; 85308841520SPaolo Bonzini pio_fis[19] = 0; 85408841520SPaolo Bonzini 855fac7aa7fSJohn Snow /* Update shadow registers: */ 856fac7aa7fSJohn Snow pr->tfdata = (ad->port.ifs[0].error << 8) | 857fac7aa7fSJohn Snow ad->port.ifs[0].status; 858fac7aa7fSJohn Snow 85908841520SPaolo Bonzini if (pio_fis[2] & ERR_STAT) { 8605fa0feecSJohn Snow ahci_trigger_irq(ad->hba, ad, AHCI_PORT_IRQ_BIT_TFES); 86108841520SPaolo Bonzini } 86208841520SPaolo Bonzini } 86308841520SPaolo Bonzini 8642967dc82SNiklas Cassel static bool ahci_write_fis_d2h(AHCIDevice *ad, bool d2h_fis_i) 865f6ad2e32SAlexander Graf { 866f6ad2e32SAlexander Graf AHCIPortRegs *pr = &ad->port_regs; 867f6ad2e32SAlexander Graf uint8_t *d2h_fis; 868f6ad2e32SAlexander Graf int i; 8697b8bad1bSJohn Snow IDEState *s = &ad->port.ifs[0]; 870f6ad2e32SAlexander Graf 871f6ad2e32SAlexander Graf if (!ad->res_fis || !(pr->cmd & PORT_CMD_FIS_RX)) { 872e47f9eb1SJohn Snow return false; 873f6ad2e32SAlexander Graf } 874f6ad2e32SAlexander Graf 875f6ad2e32SAlexander Graf d2h_fis = &ad->res_fis[RES_FIS_RFIS]; 876f6ad2e32SAlexander Graf 87717fcb74aSStefan Hajnoczi d2h_fis[0] = SATA_FIS_TYPE_REGISTER_D2H; 8782967dc82SNiklas Cassel d2h_fis[1] = d2h_fis_i ? (1 << 6) : 0; /* interrupt bit */ 8797b8bad1bSJohn Snow d2h_fis[2] = s->status; 8807b8bad1bSJohn Snow d2h_fis[3] = s->error; 881f6ad2e32SAlexander Graf 8827b8bad1bSJohn Snow d2h_fis[4] = s->sector; 8837b8bad1bSJohn Snow d2h_fis[5] = s->lcyl; 8847b8bad1bSJohn Snow d2h_fis[6] = s->hcyl; 8857b8bad1bSJohn Snow d2h_fis[7] = s->select; 8867b8bad1bSJohn Snow d2h_fis[8] = s->hob_sector; 8877b8bad1bSJohn Snow d2h_fis[9] = s->hob_lcyl; 8887b8bad1bSJohn Snow d2h_fis[10] = s->hob_hcyl; 8897b8bad1bSJohn Snow d2h_fis[11] = 0; 890dd628221SJohn Snow d2h_fis[12] = s->nsector & 0xFF; 891dd628221SJohn Snow d2h_fis[13] = (s->nsector >> 8) & 0xFF; 8924bb9c939SDaniel Verkamp for (i = 14; i < 20; i++) { 893f6ad2e32SAlexander Graf d2h_fis[i] = 0; 894f6ad2e32SAlexander Graf } 895f6ad2e32SAlexander Graf 896fac7aa7fSJohn Snow /* Update shadow registers: */ 897fac7aa7fSJohn Snow pr->tfdata = (ad->port.ifs[0].error << 8) | 898fac7aa7fSJohn Snow ad->port.ifs[0].status; 899fac7aa7fSJohn Snow 900f6ad2e32SAlexander Graf if (d2h_fis[2] & ERR_STAT) { 9015fa0feecSJohn Snow ahci_trigger_irq(ad->hba, ad, AHCI_PORT_IRQ_BIT_TFES); 902f6ad2e32SAlexander Graf } 903f6ad2e32SAlexander Graf 9042967dc82SNiklas Cassel if (d2h_fis_i) { 9055fa0feecSJohn Snow ahci_trigger_irq(ad->hba, ad, AHCI_PORT_IRQ_BIT_DHRS); 9062967dc82SNiklas Cassel } 9072967dc82SNiklas Cassel 908e47f9eb1SJohn Snow return true; 909f6ad2e32SAlexander Graf } 910f6ad2e32SAlexander Graf 911d02f8adcSReza Jelveh static int prdt_tbl_entry_size(const AHCI_SG *tbl) 912d02f8adcSReza Jelveh { 913a718978eSJohn Snow /* flags_size is zero-based */ 914d02f8adcSReza Jelveh return (le32_to_cpu(tbl->flags_size) & AHCI_PRDT_SIZE_MASK) + 1; 915d02f8adcSReza Jelveh } 916d02f8adcSReza Jelveh 9179fbf0fa8SJohn Snow /** 9189fbf0fa8SJohn Snow * Fetch entries in a guest-provided PRDT and convert it into a QEMU SGlist. 9199fbf0fa8SJohn Snow * @ad: The AHCIDevice for whom we are building the SGList. 9209fbf0fa8SJohn Snow * @sglist: The SGList target to add PRD entries to. 9219fbf0fa8SJohn Snow * @cmd: The AHCI Command Header that describes where the PRDT is. 9229fbf0fa8SJohn Snow * @limit: The remaining size of the S/ATA transaction, in bytes. 9239fbf0fa8SJohn Snow * @offset: The number of bytes already transferred, in bytes. 9249fbf0fa8SJohn Snow * 9259fbf0fa8SJohn Snow * The AHCI PRDT can describe up to 256GiB. S/ATA only support transactions of 9269fbf0fa8SJohn Snow * up to 32MiB as of ATA8-ACS3 rev 1b, assuming a 512 byte sector size. We stop 9279fbf0fa8SJohn Snow * building the sglist from the PRDT as soon as we hit @limit bytes, 9289fbf0fa8SJohn Snow * which is <= INT32_MAX/2GiB. 9299fbf0fa8SJohn Snow */ 9303251bdcfSJohn Snow static int ahci_populate_sglist(AHCIDevice *ad, QEMUSGList *sglist, 9319fbf0fa8SJohn Snow AHCICmdHdr *cmd, int64_t limit, uint64_t offset) 932f6ad2e32SAlexander Graf { 933d56f4d69SJohn Snow uint16_t opts = le16_to_cpu(cmd->opts); 934d56f4d69SJohn Snow uint16_t prdtl = le16_to_cpu(cmd->prdtl); 935d56f4d69SJohn Snow uint64_t cfis_addr = le64_to_cpu(cmd->tbl_addr); 936d56f4d69SJohn Snow uint64_t prdt_addr = cfis_addr + 0x80; 937d56f4d69SJohn Snow dma_addr_t prdt_len = (prdtl * sizeof(AHCI_SG)); 93810ca2943SDavid Gibson dma_addr_t real_prdt_len = prdt_len; 939f6ad2e32SAlexander Graf uint8_t *prdt; 940f6ad2e32SAlexander Graf int i; 941f6ad2e32SAlexander Graf int r = 0; 9423251bdcfSJohn Snow uint64_t sum = 0; 94361f52e06SJason Baron int off_idx = -1; 9443251bdcfSJohn Snow int64_t off_pos = -1; 94561f52e06SJason Baron int tbl_entry_size; 946f487b677SPaolo Bonzini IDEBus *bus = &ad->port; 947f487b677SPaolo Bonzini BusState *qbus = BUS(bus); 948f6ad2e32SAlexander Graf 949e4baa9f0SJohn Snow trace_ahci_populate_sglist(ad->hba, ad->port_no); 950e4baa9f0SJohn Snow 951d56f4d69SJohn Snow if (!prdtl) { 952e4baa9f0SJohn Snow trace_ahci_populate_sglist_no_prdtl(ad->hba, ad->port_no, opts); 953f6ad2e32SAlexander Graf return -1; 954f6ad2e32SAlexander Graf } 955f6ad2e32SAlexander Graf 956f6ad2e32SAlexander Graf /* map PRDT */ 957df32fd1cSPaolo Bonzini if (!(prdt = dma_memory_map(ad->hba->as, prdt_addr, &prdt_len, 958a1d4b0a3SPhilippe Mathieu-Daudé DMA_DIRECTION_TO_DEVICE, 959a1d4b0a3SPhilippe Mathieu-Daudé MEMTXATTRS_UNSPECIFIED))){ 960e4baa9f0SJohn Snow trace_ahci_populate_sglist_no_map(ad->hba, ad->port_no); 961f6ad2e32SAlexander Graf return -1; 962f6ad2e32SAlexander Graf } 963f6ad2e32SAlexander Graf 964f6ad2e32SAlexander Graf if (prdt_len < real_prdt_len) { 965e4baa9f0SJohn Snow trace_ahci_populate_sglist_short_map(ad->hba, ad->port_no); 966f6ad2e32SAlexander Graf r = -1; 967f6ad2e32SAlexander Graf goto out; 968f6ad2e32SAlexander Graf } 969f6ad2e32SAlexander Graf 970f6ad2e32SAlexander Graf /* Get entries in the PRDT, init a qemu sglist accordingly */ 971d56f4d69SJohn Snow if (prdtl > 0) { 972f6ad2e32SAlexander Graf AHCI_SG *tbl = (AHCI_SG *)prdt; 97361f52e06SJason Baron sum = 0; 974d56f4d69SJohn Snow for (i = 0; i < prdtl; i++) { 975d02f8adcSReza Jelveh tbl_entry_size = prdt_tbl_entry_size(&tbl[i]); 976a718978eSJohn Snow if (offset < (sum + tbl_entry_size)) { 97761f52e06SJason Baron off_idx = i; 97861f52e06SJason Baron off_pos = offset - sum; 97961f52e06SJason Baron break; 98061f52e06SJason Baron } 98161f52e06SJason Baron sum += tbl_entry_size; 98261f52e06SJason Baron } 98361f52e06SJason Baron if ((off_idx == -1) || (off_pos < 0) || (off_pos > tbl_entry_size)) { 984e4baa9f0SJohn Snow trace_ahci_populate_sglist_bad_offset(ad->hba, ad->port_no, 985e4baa9f0SJohn Snow off_idx, off_pos); 98661f52e06SJason Baron r = -1; 98761f52e06SJason Baron goto out; 98861f52e06SJason Baron } 98961f52e06SJason Baron 990d56f4d69SJohn Snow qemu_sglist_init(sglist, qbus->parent, (prdtl - off_idx), 991f487b677SPaolo Bonzini ad->hba->as); 992ac381236SJohn Snow qemu_sglist_add(sglist, le64_to_cpu(tbl[off_idx].addr) + off_pos, 993a718978eSJohn Snow MIN(prdt_tbl_entry_size(&tbl[off_idx]) - off_pos, 994a718978eSJohn Snow limit)); 99561f52e06SJason Baron 996a718978eSJohn Snow for (i = off_idx + 1; i < prdtl && sglist->size < limit; i++) { 997f6ad2e32SAlexander Graf qemu_sglist_add(sglist, le64_to_cpu(tbl[i].addr), 998a718978eSJohn Snow MIN(prdt_tbl_entry_size(&tbl[i]), 999a718978eSJohn Snow limit - sglist->size)); 1000f6ad2e32SAlexander Graf } 1001f6ad2e32SAlexander Graf } 1002f6ad2e32SAlexander Graf 1003f6ad2e32SAlexander Graf out: 1004df32fd1cSPaolo Bonzini dma_memory_unmap(ad->hba->as, prdt, prdt_len, 100510ca2943SDavid Gibson DMA_DIRECTION_TO_DEVICE, prdt_len); 1006f6ad2e32SAlexander Graf return r; 1007f6ad2e32SAlexander Graf } 1008f6ad2e32SAlexander Graf 1009a55c8231SJohn Snow static void ncq_err(NCQTransferState *ncq_tfs) 1010a55c8231SJohn Snow { 1011a55c8231SJohn Snow IDEState *ide_state = &ncq_tfs->drive->port.ifs[0]; 1012a55c8231SJohn Snow 1013a55c8231SJohn Snow ide_state->error = ABRT_ERR; 1014a55c8231SJohn Snow ide_state->status = READY_STAT | ERR_STAT; 10155839df7bSMarc-André Lureau qemu_sglist_destroy(&ncq_tfs->sglist); 10164ab0359aSPrasad J Pandit ncq_tfs->used = 0; 1017a55c8231SJohn Snow } 1018a55c8231SJohn Snow 101954f32237SJohn Snow static void ncq_finish(NCQTransferState *ncq_tfs) 1020f6ad2e32SAlexander Graf { 10217c649ac5SJohn Snow /* If we didn't error out, set our finished bit. Errored commands 10227c649ac5SJohn Snow * do not get a bit set for the SDB FIS ACT register, nor do they 10237c649ac5SJohn Snow * clear the outstanding bit in scr_act (PxSACT). */ 10249f894235SNiklas Cassel if (ncq_tfs->used) { 10257c649ac5SJohn Snow ncq_tfs->drive->finished |= (1 << ncq_tfs->tag); 10267c649ac5SJohn Snow } 1027f6ad2e32SAlexander Graf 10287c649ac5SJohn Snow ahci_write_fis_sdb(ncq_tfs->drive->hba, ncq_tfs); 1029f6ad2e32SAlexander Graf 1030e4baa9f0SJohn Snow trace_ncq_finish(ncq_tfs->drive->hba, ncq_tfs->drive->port_no, 1031f6ad2e32SAlexander Graf ncq_tfs->tag); 1032f6ad2e32SAlexander Graf 10334be74634SMarkus Armbruster block_acct_done(blk_get_stats(ncq_tfs->drive->port.ifs[0].blk), 10345366d0c8SBenoît Canet &ncq_tfs->acct); 1035f6ad2e32SAlexander Graf qemu_sglist_destroy(&ncq_tfs->sglist); 1036f6ad2e32SAlexander Graf ncq_tfs->used = 0; 1037f6ad2e32SAlexander Graf } 1038f6ad2e32SAlexander Graf 103954f32237SJohn Snow static void ncq_cb(void *opaque, int ret) 104054f32237SJohn Snow { 104154f32237SJohn Snow NCQTransferState *ncq_tfs = (NCQTransferState *)opaque; 104254f32237SJohn Snow IDEState *ide_state = &ncq_tfs->drive->port.ifs[0]; 104354f32237SJohn Snow 1044df403bc5SJohn Snow ncq_tfs->aiocb = NULL; 104554f32237SJohn Snow 104654f32237SJohn Snow if (ret < 0) { 10477c03a691SJohn Snow bool is_read = ncq_tfs->cmd == READ_FPDMA_QUEUED; 10487c03a691SJohn Snow BlockErrorAction action = blk_get_error_action(ide_state->blk, 10497c03a691SJohn Snow is_read, -ret); 10507c03a691SJohn Snow if (action == BLOCK_ERROR_ACTION_STOP) { 10517c03a691SJohn Snow ncq_tfs->halt = true; 10527c03a691SJohn Snow ide_state->bus->error_status = IDE_RETRY_HBA; 10537c03a691SJohn Snow } else if (action == BLOCK_ERROR_ACTION_REPORT) { 105454f32237SJohn Snow ncq_err(ncq_tfs); 10557c03a691SJohn Snow } 10567c03a691SJohn Snow blk_error_action(ide_state->blk, action, is_read, -ret); 105754f32237SJohn Snow } else { 105854f32237SJohn Snow ide_state->status = READY_STAT | SEEK_STAT; 105954f32237SJohn Snow } 106054f32237SJohn Snow 10617c03a691SJohn Snow if (!ncq_tfs->halt) { 106254f32237SJohn Snow ncq_finish(ncq_tfs); 106354f32237SJohn Snow } 10647c03a691SJohn Snow } 106554f32237SJohn Snow 106672a065dbSJohn Snow static int is_ncq(uint8_t ata_cmd) 106772a065dbSJohn Snow { 106872a065dbSJohn Snow /* Based on SATA 3.2 section 13.6.3.2 */ 106972a065dbSJohn Snow switch (ata_cmd) { 107072a065dbSJohn Snow case READ_FPDMA_QUEUED: 107172a065dbSJohn Snow case WRITE_FPDMA_QUEUED: 107272a065dbSJohn Snow case NCQ_NON_DATA: 107372a065dbSJohn Snow case RECEIVE_FPDMA_QUEUED: 107472a065dbSJohn Snow case SEND_FPDMA_QUEUED: 107572a065dbSJohn Snow return 1; 107672a065dbSJohn Snow default: 107772a065dbSJohn Snow return 0; 107872a065dbSJohn Snow } 107972a065dbSJohn Snow } 108072a065dbSJohn Snow 1081631ddc22SJohn Snow static void execute_ncq_command(NCQTransferState *ncq_tfs) 1082631ddc22SJohn Snow { 1083631ddc22SJohn Snow AHCIDevice *ad = ncq_tfs->drive; 1084631ddc22SJohn Snow IDEState *ide_state = &ad->port.ifs[0]; 1085631ddc22SJohn Snow int port = ad->port_no; 10867c03a691SJohn Snow 1087631ddc22SJohn Snow g_assert(is_ncq(ncq_tfs->cmd)); 10887c03a691SJohn Snow ncq_tfs->halt = false; 1089631ddc22SJohn Snow 1090631ddc22SJohn Snow switch (ncq_tfs->cmd) { 1091631ddc22SJohn Snow case READ_FPDMA_QUEUED: 1092e4baa9f0SJohn Snow trace_execute_ncq_command_read(ad->hba, port, ncq_tfs->tag, 1093e4baa9f0SJohn Snow ncq_tfs->sector_count, ncq_tfs->lba); 1094631ddc22SJohn Snow dma_acct_start(ide_state->blk, &ncq_tfs->acct, 1095631ddc22SJohn Snow &ncq_tfs->sglist, BLOCK_ACCT_READ); 1096631ddc22SJohn Snow ncq_tfs->aiocb = dma_blk_read(ide_state->blk, &ncq_tfs->sglist, 1097cbe0ed62SPaolo Bonzini ncq_tfs->lba << BDRV_SECTOR_BITS, 109899868af3SMark Cave-Ayland BDRV_SECTOR_SIZE, 1099cbe0ed62SPaolo Bonzini ncq_cb, ncq_tfs); 1100631ddc22SJohn Snow break; 1101631ddc22SJohn Snow case WRITE_FPDMA_QUEUED: 1102eb8fde18SFiona Ebner trace_execute_ncq_command_write(ad->hba, port, ncq_tfs->tag, 1103e4baa9f0SJohn Snow ncq_tfs->sector_count, ncq_tfs->lba); 1104631ddc22SJohn Snow dma_acct_start(ide_state->blk, &ncq_tfs->acct, 1105631ddc22SJohn Snow &ncq_tfs->sglist, BLOCK_ACCT_WRITE); 1106631ddc22SJohn Snow ncq_tfs->aiocb = dma_blk_write(ide_state->blk, &ncq_tfs->sglist, 1107cbe0ed62SPaolo Bonzini ncq_tfs->lba << BDRV_SECTOR_BITS, 110899868af3SMark Cave-Ayland BDRV_SECTOR_SIZE, 1109cbe0ed62SPaolo Bonzini ncq_cb, ncq_tfs); 1110631ddc22SJohn Snow break; 1111631ddc22SJohn Snow default: 1112e4baa9f0SJohn Snow trace_execute_ncq_command_unsup(ad->hba, port, 1113e4baa9f0SJohn Snow ncq_tfs->tag, ncq_tfs->cmd); 1114631ddc22SJohn Snow ncq_err(ncq_tfs); 1115631ddc22SJohn Snow } 1116631ddc22SJohn Snow } 1117631ddc22SJohn Snow 1118631ddc22SJohn Snow 111926941eb4SAlexander Bulekov static void process_ncq_command(AHCIState *s, int port, const uint8_t *cmd_fis, 11209364384dSJohn Snow uint8_t slot) 1121f6ad2e32SAlexander Graf { 1122b6fe41faSJohn Snow AHCIDevice *ad = &s->dev[port]; 112326941eb4SAlexander Bulekov const NCQFrame *ncq_fis = (NCQFrame *)cmd_fis; 1124f6ad2e32SAlexander Graf uint8_t tag = ncq_fis->tag >> 3; 1125b6fe41faSJohn Snow NCQTransferState *ncq_tfs = &ad->ncq_tfs[tag]; 11263bcbe4aaSJohn Snow size_t size; 1127f6ad2e32SAlexander Graf 1128922f893eSJohn Snow g_assert(is_ncq(ncq_fis->command)); 1129f6ad2e32SAlexander Graf if (ncq_tfs->used) { 1130f6ad2e32SAlexander Graf /* error - already in use */ 1131580e7333SPhilippe Mathieu-Daudé qemu_log_mask(LOG_GUEST_ERROR, "%s: tag %d already used\n", 1132580e7333SPhilippe Mathieu-Daudé __func__, tag); 1133f6ad2e32SAlexander Graf return; 1134f6ad2e32SAlexander Graf } 1135f6ad2e32SAlexander Graf 1136e2a5d9b3SNiklas Cassel /* 1137e2a5d9b3SNiklas Cassel * A NCQ command clears the bit in PxCI after the command has been QUEUED 1138e2a5d9b3SNiklas Cassel * successfully (ERROR not set, BUSY and DRQ cleared). 1139e2a5d9b3SNiklas Cassel * 1140e2a5d9b3SNiklas Cassel * For NCQ commands, PxCI will always be cleared here. 1141e2a5d9b3SNiklas Cassel * 1142e2a5d9b3SNiklas Cassel * (Once the NCQ command is COMPLETED, the device will send a SDB FIS with 1143e2a5d9b3SNiklas Cassel * the interrupt bit set, which will clear PxSACT and raise an interrupt.) 1144e2a5d9b3SNiklas Cassel */ 1145e2a5d9b3SNiklas Cassel ahci_clear_cmd_issue(ad, slot); 1146e2a5d9b3SNiklas Cassel 1147e2a5d9b3SNiklas Cassel /* 1148e2a5d9b3SNiklas Cassel * In reality, for NCQ commands, PxCI is cleared after receiving a D2H FIS 1149e2a5d9b3SNiklas Cassel * without the interrupt bit set, but since ahci_write_fis_d2h() can raise 1150e2a5d9b3SNiklas Cassel * an IRQ on error, we need to call them in reverse order. 1151e2a5d9b3SNiklas Cassel */ 11522967dc82SNiklas Cassel ahci_write_fis_d2h(ad, false); 11532967dc82SNiklas Cassel 1154f6ad2e32SAlexander Graf ncq_tfs->used = 1; 1155b6fe41faSJohn Snow ncq_tfs->drive = ad; 1156f6ad2e32SAlexander Graf ncq_tfs->slot = slot; 1157c82bd3c8SJohn Snow ncq_tfs->cmdh = &((AHCICmdHdr *)ad->lst)[slot]; 11584614619eSJohn Snow ncq_tfs->cmd = ncq_fis->command; 1159f6ad2e32SAlexander Graf ncq_tfs->lba = ((uint64_t)ncq_fis->lba5 << 40) | 1160f6ad2e32SAlexander Graf ((uint64_t)ncq_fis->lba4 << 32) | 1161f6ad2e32SAlexander Graf ((uint64_t)ncq_fis->lba3 << 24) | 1162f6ad2e32SAlexander Graf ((uint64_t)ncq_fis->lba2 << 16) | 1163f6ad2e32SAlexander Graf ((uint64_t)ncq_fis->lba1 << 8) | 1164f6ad2e32SAlexander Graf (uint64_t)ncq_fis->lba0; 11653bcbe4aaSJohn Snow ncq_tfs->tag = tag; 1166f6ad2e32SAlexander Graf 11675d5f8921SJohn Snow /* Sanity-check the NCQ packet */ 11685d5f8921SJohn Snow if (tag != slot) { 1169e4baa9f0SJohn Snow trace_process_ncq_command_mismatch(s, port, tag, slot); 11705d5f8921SJohn Snow } 11715d5f8921SJohn Snow 11725d5f8921SJohn Snow if (ncq_fis->aux0 || ncq_fis->aux1 || ncq_fis->aux2 || ncq_fis->aux3) { 1173e4baa9f0SJohn Snow trace_process_ncq_command_aux(s, port, tag); 11745d5f8921SJohn Snow } 11755d5f8921SJohn Snow if (ncq_fis->prio || ncq_fis->icc) { 1176e4baa9f0SJohn Snow trace_process_ncq_command_prioicc(s, port, tag); 11775d5f8921SJohn Snow } 11785d5f8921SJohn Snow if (ncq_fis->fua & NCQ_FIS_FUA_MASK) { 1179e4baa9f0SJohn Snow trace_process_ncq_command_fua(s, port, tag); 11805d5f8921SJohn Snow } 11815d5f8921SJohn Snow if (ncq_fis->tag & NCQ_FIS_RARC_MASK) { 1182e4baa9f0SJohn Snow trace_process_ncq_command_rarc(s, port, tag); 11835d5f8921SJohn Snow } 11845d5f8921SJohn Snow 1185e08a9835SJohn Snow ncq_tfs->sector_count = ((ncq_fis->sector_count_high << 8) | 1186e08a9835SJohn Snow ncq_fis->sector_count_low); 1187e08a9835SJohn Snow if (!ncq_tfs->sector_count) { 1188e08a9835SJohn Snow ncq_tfs->sector_count = 0x10000; 1189e08a9835SJohn Snow } 1190075f32d3SPhilippe Mathieu-Daudé size = ncq_tfs->sector_count * BDRV_SECTOR_SIZE; 1191c82bd3c8SJohn Snow ahci_populate_sglist(ad, &ncq_tfs->sglist, ncq_tfs->cmdh, size, 0); 11923bcbe4aaSJohn Snow 11933bcbe4aaSJohn Snow if (ncq_tfs->sglist.size < size) { 119460791a2cSPhilippe Mathieu-Daudé error_report("ahci: PRDT length for NCQ command (0x" DMA_ADDR_FMT ") " 11953bcbe4aaSJohn Snow "is smaller than the requested size (0x%zx)", 11963bcbe4aaSJohn Snow ncq_tfs->sglist.size, size); 11973bcbe4aaSJohn Snow ncq_err(ncq_tfs); 11985fa0feecSJohn Snow ahci_trigger_irq(ad->hba, ad, AHCI_PORT_IRQ_BIT_OFS); 11993bcbe4aaSJohn Snow return; 12005d5f8921SJohn Snow } else if (ncq_tfs->sglist.size != size) { 1201e4baa9f0SJohn Snow trace_process_ncq_command_large(s, port, tag, 12025d5f8921SJohn Snow ncq_tfs->sglist.size, size); 12033bcbe4aaSJohn Snow } 1204f6ad2e32SAlexander Graf 1205e4baa9f0SJohn Snow trace_process_ncq_command(s, port, tag, 1206e4baa9f0SJohn Snow ncq_fis->command, 1207e4baa9f0SJohn Snow ncq_tfs->lba, 1208e4baa9f0SJohn Snow ncq_tfs->lba + ncq_tfs->sector_count - 1); 1209631ddc22SJohn Snow execute_ncq_command(ncq_tfs); 1210f6ad2e32SAlexander Graf } 1211f6ad2e32SAlexander Graf 1212ee364416SJohn Snow static AHCICmdHdr *get_cmd_header(AHCIState *s, uint8_t port, uint8_t slot) 1213ee364416SJohn Snow { 1214ee364416SJohn Snow if (port >= s->ports || slot >= AHCI_MAX_CMDS) { 1215ee364416SJohn Snow return NULL; 1216ee364416SJohn Snow } 1217ee364416SJohn Snow 1218ee364416SJohn Snow return s->dev[port].lst ? &((AHCICmdHdr *)s->dev[port].lst)[slot] : NULL; 1219ee364416SJohn Snow } 1220ee364416SJohn Snow 1221107f0d46SJohn Snow static void handle_reg_h2d_fis(AHCIState *s, int port, 122226941eb4SAlexander Bulekov uint8_t slot, const uint8_t *cmd_fis) 1223f6ad2e32SAlexander Graf { 1224107f0d46SJohn Snow IDEState *ide_state = &s->dev[port].port.ifs[0]; 1225ee364416SJohn Snow AHCICmdHdr *cmd = get_cmd_header(s, port, slot); 1226e2a5d9b3SNiklas Cassel AHCIDevice *ad = &s->dev[port]; 1227d56f4d69SJohn Snow uint16_t opts = le16_to_cpu(cmd->opts); 1228f6ad2e32SAlexander Graf 1229102e5625SJohn Snow if (cmd_fis[1] & 0x0F) { 1230e4baa9f0SJohn Snow trace_handle_reg_h2d_fis_pmp(s, port, cmd_fis[1], 1231e4baa9f0SJohn Snow cmd_fis[2], cmd_fis[3]); 1232107f0d46SJohn Snow return; 1233102e5625SJohn Snow } 1234102e5625SJohn Snow 1235102e5625SJohn Snow if (cmd_fis[1] & 0x70) { 1236e4baa9f0SJohn Snow trace_handle_reg_h2d_fis_res(s, port, cmd_fis[1], 1237e4baa9f0SJohn Snow cmd_fis[2], cmd_fis[3]); 1238107f0d46SJohn Snow return; 1239f6ad2e32SAlexander Graf } 1240f6ad2e32SAlexander Graf 12411cbdd968SJohn Snow if (!(cmd_fis[1] & SATA_FIS_REG_H2D_UPDATE_COMMAND_REGISTER)) { 1242f6ad2e32SAlexander Graf switch (s->dev[port].port_state) { 1243f6ad2e32SAlexander Graf case STATE_RUN: 1244f6ad2e32SAlexander Graf if (cmd_fis[15] & ATA_SRST) { 1245f6ad2e32SAlexander Graf s->dev[port].port_state = STATE_RESET; 1246f6ad2e32SAlexander Graf } 1247f6ad2e32SAlexander Graf break; 1248f6ad2e32SAlexander Graf case STATE_RESET: 1249f6ad2e32SAlexander Graf if (!(cmd_fis[15] & ATA_SRST)) { 1250f6ad2e32SAlexander Graf ahci_reset_port(s, port); 1251f6ad2e32SAlexander Graf } 1252f6ad2e32SAlexander Graf break; 1253f6ad2e32SAlexander Graf } 1254107f0d46SJohn Snow return; 12551cbdd968SJohn Snow } 1256f6ad2e32SAlexander Graf 1257f6ad2e32SAlexander Graf /* Check for NCQ command */ 125872a065dbSJohn Snow if (is_ncq(cmd_fis[2])) { 1259f6ad2e32SAlexander Graf process_ncq_command(s, port, cmd_fis, slot); 1260107f0d46SJohn Snow return; 1261f6ad2e32SAlexander Graf } 1262f6ad2e32SAlexander Graf 12631cbdd968SJohn Snow /* Decompose the FIS: 12641cbdd968SJohn Snow * AHCI does not interpret FIS packets, it only forwards them. 12651cbdd968SJohn Snow * SATA 1.0 describes how to decode LBA28 and CHS FIS packets. 12661cbdd968SJohn Snow * Later specifications, e.g, SATA 3.2, describe LBA48 FIS packets. 12671cbdd968SJohn Snow * 12681cbdd968SJohn Snow * ATA4 describes sector number for LBA28/CHS commands. 12691cbdd968SJohn Snow * ATA6 describes sector number for LBA48 commands. 12701cbdd968SJohn Snow * ATA8 deprecates CHS fully, describing only LBA28/48. 12711cbdd968SJohn Snow * 12721cbdd968SJohn Snow * We dutifully convert the FIS into IDE registers, and allow the 12731cbdd968SJohn Snow * core layer to interpret them as needed. */ 1274f6ad2e32SAlexander Graf ide_state->feature = cmd_fis[3]; 12751cbdd968SJohn Snow ide_state->sector = cmd_fis[4]; /* LBA 7:0 */ 12761cbdd968SJohn Snow ide_state->lcyl = cmd_fis[5]; /* LBA 15:8 */ 12771cbdd968SJohn Snow ide_state->hcyl = cmd_fis[6]; /* LBA 23:16 */ 12781cbdd968SJohn Snow ide_state->select = cmd_fis[7]; /* LBA 27:24 (LBA28) */ 12791cbdd968SJohn Snow ide_state->hob_sector = cmd_fis[8]; /* LBA 31:24 */ 12801cbdd968SJohn Snow ide_state->hob_lcyl = cmd_fis[9]; /* LBA 39:32 */ 12811cbdd968SJohn Snow ide_state->hob_hcyl = cmd_fis[10]; /* LBA 47:40 */ 12821cbdd968SJohn Snow ide_state->hob_feature = cmd_fis[11]; 12831cbdd968SJohn Snow ide_state->nsector = (int64_t)((cmd_fis[13] << 8) | cmd_fis[12]); 12841cbdd968SJohn Snow /* 14, 16, 17, 18, 19: Reserved (SATA 1.0) */ 12851cbdd968SJohn Snow /* 15: Only valid when UPDATE_COMMAND not set. */ 1286f6ad2e32SAlexander Graf 1287f6ad2e32SAlexander Graf /* Copy the ACMD field (ATAPI packet, if any) from the AHCI command 1288107f0d46SJohn Snow * table to ide_state->io_buffer */ 1289f6ad2e32SAlexander Graf if (opts & AHCI_CMD_ATAPI) { 1290f6ad2e32SAlexander Graf memcpy(ide_state->io_buffer, &cmd_fis[AHCI_COMMAND_TABLE_ACMD], 0x10); 1291797285c8SJohn Snow if (trace_event_get_state_backends(TRACE_HANDLE_REG_H2D_FIS_DUMP)) { 1292797285c8SJohn Snow char *pretty_fis = ahci_pretty_buffer_fis(ide_state->io_buffer, 0x10); 1293797285c8SJohn Snow trace_handle_reg_h2d_fis_dump(s, port, pretty_fis); 1294797285c8SJohn Snow g_free(pretty_fis); 1295797285c8SJohn Snow } 1296f6ad2e32SAlexander Graf } 1297f6ad2e32SAlexander Graf 1298f6ad2e32SAlexander Graf ide_state->error = 0; 1299ae79c2dbSPaolo Bonzini s->dev[port].done_first_drq = false; 1300f6ad2e32SAlexander Graf /* Reset transferred byte counter */ 1301f6ad2e32SAlexander Graf cmd->status = 0; 1302f6ad2e32SAlexander Graf 1303e2a5d9b3SNiklas Cassel /* 1304e2a5d9b3SNiklas Cassel * A non-NCQ command clears the bit in PxCI after the command has COMPLETED 1305e2a5d9b3SNiklas Cassel * successfully (ERROR not set, BUSY and DRQ cleared). 1306e2a5d9b3SNiklas Cassel * 1307e2a5d9b3SNiklas Cassel * For non-NCQ commands, PxCI will always be cleared by ahci_cmd_done(). 1308e2a5d9b3SNiklas Cassel */ 1309e2a5d9b3SNiklas Cassel ad->busy_slot = slot; 1310e2a5d9b3SNiklas Cassel 1311f6ad2e32SAlexander Graf /* We're ready to process the command in FIS byte 2. */ 1312783f4474SPhilippe Mathieu-Daudé ide_bus_exec_cmd(&s->dev[port].port, cmd_fis[2]); 1313f6ad2e32SAlexander Graf } 1314f6ad2e32SAlexander Graf 1315e2a5d9b3SNiklas Cassel static void handle_cmd(AHCIState *s, int port, uint8_t slot) 1316107f0d46SJohn Snow { 1317107f0d46SJohn Snow IDEState *ide_state; 1318107f0d46SJohn Snow uint64_t tbl_addr; 1319107f0d46SJohn Snow AHCICmdHdr *cmd; 1320107f0d46SJohn Snow uint8_t *cmd_fis; 1321107f0d46SJohn Snow dma_addr_t cmd_len; 1322107f0d46SJohn Snow 1323107f0d46SJohn Snow if (s->dev[port].port.ifs[0].status & (BUSY_STAT|DRQ_STAT)) { 1324107f0d46SJohn Snow /* Engine currently busy, try again later */ 1325e4baa9f0SJohn Snow trace_handle_cmd_busy(s, port); 1326e2a5d9b3SNiklas Cassel return; 1327107f0d46SJohn Snow } 1328107f0d46SJohn Snow 1329107f0d46SJohn Snow if (!s->dev[port].lst) { 1330e4baa9f0SJohn Snow trace_handle_cmd_nolist(s, port); 1331e2a5d9b3SNiklas Cassel return; 1332107f0d46SJohn Snow } 1333ee364416SJohn Snow cmd = get_cmd_header(s, port, slot); 1334107f0d46SJohn Snow /* remember current slot handle for later */ 1335107f0d46SJohn Snow s->dev[port].cur_cmd = cmd; 1336107f0d46SJohn Snow 1337107f0d46SJohn Snow /* The device we are working for */ 1338107f0d46SJohn Snow ide_state = &s->dev[port].port.ifs[0]; 1339107f0d46SJohn Snow if (!ide_state->blk) { 1340e4baa9f0SJohn Snow trace_handle_cmd_badport(s, port); 1341e2a5d9b3SNiklas Cassel return; 1342107f0d46SJohn Snow } 1343107f0d46SJohn Snow 1344107f0d46SJohn Snow tbl_addr = le64_to_cpu(cmd->tbl_addr); 1345107f0d46SJohn Snow cmd_len = 0x80; 1346107f0d46SJohn Snow cmd_fis = dma_memory_map(s->as, tbl_addr, &cmd_len, 1347a1d4b0a3SPhilippe Mathieu-Daudé DMA_DIRECTION_TO_DEVICE, MEMTXATTRS_UNSPECIFIED); 1348107f0d46SJohn Snow if (!cmd_fis) { 1349e4baa9f0SJohn Snow trace_handle_cmd_badfis(s, port); 1350e2a5d9b3SNiklas Cassel return; 1351107f0d46SJohn Snow } else if (cmd_len != 0x80) { 13525fa0feecSJohn Snow ahci_trigger_irq(s, &s->dev[port], AHCI_PORT_IRQ_BIT_HBFS); 1353e4baa9f0SJohn Snow trace_handle_cmd_badmap(s, port, cmd_len); 1354107f0d46SJohn Snow goto out; 1355107f0d46SJohn Snow } 1356797285c8SJohn Snow if (trace_event_get_state_backends(TRACE_HANDLE_CMD_FIS_DUMP)) { 1357797285c8SJohn Snow char *pretty_fis = ahci_pretty_buffer_fis(cmd_fis, 0x80); 1358797285c8SJohn Snow trace_handle_cmd_fis_dump(s, port, pretty_fis); 1359797285c8SJohn Snow g_free(pretty_fis); 1360797285c8SJohn Snow } 1361107f0d46SJohn Snow switch (cmd_fis[0]) { 1362107f0d46SJohn Snow case SATA_FIS_TYPE_REGISTER_H2D: 1363107f0d46SJohn Snow handle_reg_h2d_fis(s, port, slot, cmd_fis); 1364107f0d46SJohn Snow break; 1365107f0d46SJohn Snow default: 1366e4baa9f0SJohn Snow trace_handle_cmd_unhandled_fis(s, port, 1367e4baa9f0SJohn Snow cmd_fis[0], cmd_fis[1], cmd_fis[2]); 1368107f0d46SJohn Snow break; 1369107f0d46SJohn Snow } 1370107f0d46SJohn Snow 1371f6ad2e32SAlexander Graf out: 137226941eb4SAlexander Bulekov dma_memory_unmap(s->as, cmd_fis, cmd_len, DMA_DIRECTION_TO_DEVICE, 137310ca2943SDavid Gibson cmd_len); 1374f6ad2e32SAlexander Graf } 1375f6ad2e32SAlexander Graf 1376bed9bcfaSPaolo Bonzini /* Transfer PIO data between RAM and device */ 1377ae0cebd7SPhilippe Mathieu-Daudé static void ahci_pio_transfer(const IDEDMA *dma) 1378f6ad2e32SAlexander Graf { 1379f6ad2e32SAlexander Graf AHCIDevice *ad = DO_UPCAST(AHCIDevice, dma, dma); 1380f6ad2e32SAlexander Graf IDEState *s = &ad->port.ifs[0]; 1381f6ad2e32SAlexander Graf uint32_t size = (uint32_t)(s->data_end - s->data_ptr); 1382f6ad2e32SAlexander Graf /* write == ram -> device */ 1383d56f4d69SJohn Snow uint16_t opts = le16_to_cpu(ad->cur_cmd->opts); 1384f6ad2e32SAlexander Graf int is_write = opts & AHCI_CMD_WRITE; 1385f6ad2e32SAlexander Graf int is_atapi = opts & AHCI_CMD_ATAPI; 1386f6ad2e32SAlexander Graf int has_sglist = 0; 1387ae79c2dbSPaolo Bonzini bool pio_fis_i; 1388f6ad2e32SAlexander Graf 1389ae79c2dbSPaolo Bonzini /* The PIO Setup FIS is received prior to transfer, but the interrupt 1390ae79c2dbSPaolo Bonzini * is only triggered after data is received. 1391ae79c2dbSPaolo Bonzini * 1392ae79c2dbSPaolo Bonzini * The device only sets the 'I' bit in the PIO Setup FIS for device->host 1393ae79c2dbSPaolo Bonzini * requests (see "DPIOI1" in the SATA spec), or for host->device DRQs after 1394ae79c2dbSPaolo Bonzini * the first (see "DPIOO1"). The latter is consistent with the spec's 1395ae79c2dbSPaolo Bonzini * description of the PACKET protocol, where the command part of ATAPI requests 1396ae79c2dbSPaolo Bonzini * ("DPKT0") has the 'I' bit clear, while the data part of PIO ATAPI requests 1397ae79c2dbSPaolo Bonzini * ("DPKT4a" and "DPKT7") has the 'I' bit set for both directions for all DRQs. 1398ae79c2dbSPaolo Bonzini */ 1399ae79c2dbSPaolo Bonzini pio_fis_i = ad->done_first_drq || (!is_atapi && !is_write); 1400ae79c2dbSPaolo Bonzini ahci_write_fis_pio(ad, size, pio_fis_i); 1401956556e1SJohn Snow 1402ae79c2dbSPaolo Bonzini if (is_atapi && !ad->done_first_drq) { 1403f6ad2e32SAlexander Graf /* already prepopulated iobuffer */ 1404f6ad2e32SAlexander Graf goto out; 1405f6ad2e32SAlexander Graf } 1406f6ad2e32SAlexander Graf 1407a718978eSJohn Snow if (ahci_dma_prepare_buf(dma, size)) { 1408f6ad2e32SAlexander Graf has_sglist = 1; 1409f6ad2e32SAlexander Graf } 1410f6ad2e32SAlexander Graf 1411bed9bcfaSPaolo Bonzini trace_ahci_pio_transfer(ad->hba, ad->port_no, is_write ? "writ" : "read", 1412e4baa9f0SJohn Snow size, is_atapi ? "atapi" : "ata", 1413f6ad2e32SAlexander Graf has_sglist ? "" : "o"); 1414f6ad2e32SAlexander Graf 1415da221327SPaolo Bonzini if (has_sglist && size) { 1416392e48afSPhilippe Mathieu-Daudé const MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED; 1417392e48afSPhilippe Mathieu-Daudé 1418da221327SPaolo Bonzini if (is_write) { 1419f02b664aSPhilippe Mathieu-Daudé dma_buf_write(s->data_ptr, size, NULL, &s->sg, attrs); 1420da221327SPaolo Bonzini } else { 1421f02b664aSPhilippe Mathieu-Daudé dma_buf_read(s->data_ptr, size, NULL, &s->sg, attrs); 1422f6ad2e32SAlexander Graf } 1423f6ad2e32SAlexander Graf } 1424f6ad2e32SAlexander Graf 1425956556e1SJohn Snow /* Update number of transferred bytes, destroy sglist */ 1426956556e1SJohn Snow dma_buf_commit(s, size); 1427ae79c2dbSPaolo Bonzini 1428f6ad2e32SAlexander Graf out: 1429f6ad2e32SAlexander Graf /* declare that we processed everything */ 1430f6ad2e32SAlexander Graf s->data_ptr = s->data_end; 1431ae79c2dbSPaolo Bonzini 1432ae79c2dbSPaolo Bonzini ad->done_first_drq = true; 1433ae79c2dbSPaolo Bonzini if (pio_fis_i) { 1434ae79c2dbSPaolo Bonzini ahci_trigger_irq(ad->hba, ad, AHCI_PORT_IRQ_BIT_PSS); 1435ae79c2dbSPaolo Bonzini } 1436f6ad2e32SAlexander Graf } 1437f6ad2e32SAlexander Graf 1438ae0cebd7SPhilippe Mathieu-Daudé static void ahci_start_dma(const IDEDMA *dma, IDEState *s, 1439097310b5SMarkus Armbruster BlockCompletionFunc *dma_cb) 1440f6ad2e32SAlexander Graf { 1441f6ad2e32SAlexander Graf AHCIDevice *ad = DO_UPCAST(AHCIDevice, dma, dma); 1442e4baa9f0SJohn Snow trace_ahci_start_dma(ad->hba, ad->port_no); 144361f52e06SJason Baron s->io_buffer_offset = 0; 1444f6ad2e32SAlexander Graf dma_cb(s, 0); 1445f6ad2e32SAlexander Graf } 1446f6ad2e32SAlexander Graf 1447ae0cebd7SPhilippe Mathieu-Daudé static void ahci_restart_dma(const IDEDMA *dma) 1448e8ef8743SPaolo Bonzini { 1449e8ef8743SPaolo Bonzini /* Nothing to do, ahci_start_dma already resets s->io_buffer_offset. */ 1450e8ef8743SPaolo Bonzini } 1451e8ef8743SPaolo Bonzini 1452659142ecSJohn Snow /** 14537c03a691SJohn Snow * IDE/PIO restarts are handled by the core layer, but NCQ commands 14547c03a691SJohn Snow * need an extra kick from the AHCI HBA. 14557c03a691SJohn Snow */ 1456ae0cebd7SPhilippe Mathieu-Daudé static void ahci_restart(const IDEDMA *dma) 14577c03a691SJohn Snow { 14587c03a691SJohn Snow AHCIDevice *ad = DO_UPCAST(AHCIDevice, dma, dma); 14597c03a691SJohn Snow int i; 14607c03a691SJohn Snow 14617c03a691SJohn Snow for (i = 0; i < AHCI_MAX_CMDS; i++) { 14627c03a691SJohn Snow NCQTransferState *ncq_tfs = &ad->ncq_tfs[i]; 14637c03a691SJohn Snow if (ncq_tfs->halt) { 14647c03a691SJohn Snow execute_ncq_command(ncq_tfs); 14657c03a691SJohn Snow } 14667c03a691SJohn Snow } 14677c03a691SJohn Snow } 14687c03a691SJohn Snow 14697c03a691SJohn Snow /** 1470aaeda4a3SJohn Snow * Called in DMA and PIO R/W chains to read the PRDT. 1471aaeda4a3SJohn Snow * Not shared with NCQ pathways. 1472659142ecSJohn Snow */ 1473ae0cebd7SPhilippe Mathieu-Daudé static int32_t ahci_dma_prepare_buf(const IDEDMA *dma, int32_t limit) 1474f6ad2e32SAlexander Graf { 1475f6ad2e32SAlexander Graf AHCIDevice *ad = DO_UPCAST(AHCIDevice, dma, dma); 1476f6ad2e32SAlexander Graf IDEState *s = &ad->port.ifs[0]; 1477f6ad2e32SAlexander Graf 1478c82bd3c8SJohn Snow if (ahci_populate_sglist(ad, &s->sg, ad->cur_cmd, 1479c82bd3c8SJohn Snow limit, s->io_buffer_offset) == -1) { 1480e4baa9f0SJohn Snow trace_ahci_dma_prepare_buf_fail(ad->hba, ad->port_no); 14813251bdcfSJohn Snow return -1; 14823251bdcfSJohn Snow } 1483da221327SPaolo Bonzini s->io_buffer_size = s->sg.size; 1484f6ad2e32SAlexander Graf 1485e4baa9f0SJohn Snow trace_ahci_dma_prepare_buf(ad->hba, ad->port_no, limit, s->io_buffer_size); 14863251bdcfSJohn Snow return s->io_buffer_size; 1487f6ad2e32SAlexander Graf } 1488f6ad2e32SAlexander Graf 1489659142ecSJohn Snow /** 1490aaeda4a3SJohn Snow * Updates the command header with a bytes-read value. 1491aaeda4a3SJohn Snow * Called via dma_buf_commit, for both DMA and PIO paths. 1492aaeda4a3SJohn Snow * sglist destruction is handled within dma_buf_commit. 1493659142ecSJohn Snow */ 1494ae0cebd7SPhilippe Mathieu-Daudé static void ahci_commit_buf(const IDEDMA *dma, uint32_t tx_bytes) 1495659142ecSJohn Snow { 1496659142ecSJohn Snow AHCIDevice *ad = DO_UPCAST(AHCIDevice, dma, dma); 1497659142ecSJohn Snow 1498659142ecSJohn Snow tx_bytes += le32_to_cpu(ad->cur_cmd->status); 1499659142ecSJohn Snow ad->cur_cmd->status = cpu_to_le32(tx_bytes); 1500659142ecSJohn Snow } 1501659142ecSJohn Snow 1502ae0cebd7SPhilippe Mathieu-Daudé static int ahci_dma_rw_buf(const IDEDMA *dma, bool is_write) 1503f6ad2e32SAlexander Graf { 1504f6ad2e32SAlexander Graf AHCIDevice *ad = DO_UPCAST(AHCIDevice, dma, dma); 1505f6ad2e32SAlexander Graf IDEState *s = &ad->port.ifs[0]; 1506f6ad2e32SAlexander Graf uint8_t *p = s->io_buffer + s->io_buffer_index; 1507f6ad2e32SAlexander Graf int l = s->io_buffer_size - s->io_buffer_index; 1508f6ad2e32SAlexander Graf 1509c82bd3c8SJohn Snow if (ahci_populate_sglist(ad, &s->sg, ad->cur_cmd, l, s->io_buffer_offset)) { 1510f6ad2e32SAlexander Graf return 0; 1511f6ad2e32SAlexander Graf } 1512f6ad2e32SAlexander Graf 1513f6ad2e32SAlexander Graf if (is_write) { 1514f02b664aSPhilippe Mathieu-Daudé dma_buf_read(p, l, NULL, &s->sg, MEMTXATTRS_UNSPECIFIED); 1515f6ad2e32SAlexander Graf } else { 1516f02b664aSPhilippe Mathieu-Daudé dma_buf_write(p, l, NULL, &s->sg, MEMTXATTRS_UNSPECIFIED); 1517f6ad2e32SAlexander Graf } 1518f6ad2e32SAlexander Graf 1519659142ecSJohn Snow /* free sglist, update byte count */ 1520aaeda4a3SJohn Snow dma_buf_commit(s, l); 1521f6ad2e32SAlexander Graf s->io_buffer_index += l; 1522f6ad2e32SAlexander Graf 1523e4baa9f0SJohn Snow trace_ahci_dma_rw_buf(ad->hba, ad->port_no, l); 1524f6ad2e32SAlexander Graf return 1; 1525f6ad2e32SAlexander Graf } 1526f6ad2e32SAlexander Graf 1527e2a5d9b3SNiklas Cassel static void ahci_clear_cmd_issue(AHCIDevice *ad, uint8_t slot) 1528e2a5d9b3SNiklas Cassel { 1529e2a5d9b3SNiklas Cassel IDEState *ide_state = &ad->port.ifs[0]; 1530e2a5d9b3SNiklas Cassel 15311a16ce64SNiklas Cassel if (!(ide_state->status & ERR_STAT) && 15321a16ce64SNiklas Cassel !(ide_state->status & (BUSY_STAT | DRQ_STAT))) { 1533e2a5d9b3SNiklas Cassel ad->port_regs.cmd_issue &= ~(1 << slot); 1534e2a5d9b3SNiklas Cassel } 1535e2a5d9b3SNiklas Cassel } 1536e2a5d9b3SNiklas Cassel 1537e2a5d9b3SNiklas Cassel /* Non-NCQ command is done - This function is never called for NCQ commands. */ 1538ae0cebd7SPhilippe Mathieu-Daudé static void ahci_cmd_done(const IDEDMA *dma) 1539a62eaa26SKevin Wolf { 1540f6ad2e32SAlexander Graf AHCIDevice *ad = DO_UPCAST(AHCIDevice, dma, dma); 15411a16ce64SNiklas Cassel IDEState *ide_state = &ad->port.ifs[0]; 1542f6ad2e32SAlexander Graf 1543e4baa9f0SJohn Snow trace_ahci_cmd_done(ad->hba, ad->port_no); 1544f6ad2e32SAlexander Graf 15455694c7eaSJohn Snow /* no longer busy */ 15465694c7eaSJohn Snow if (ad->busy_slot != -1) { 1547e2a5d9b3SNiklas Cassel ahci_clear_cmd_issue(ad, ad->busy_slot); 15485694c7eaSJohn Snow ad->busy_slot = -1; 15495694c7eaSJohn Snow } 15505694c7eaSJohn Snow 1551e2a5d9b3SNiklas Cassel /* 1552e2a5d9b3SNiklas Cassel * In reality, for non-NCQ commands, PxCI is cleared after receiving a D2H 1553e2a5d9b3SNiklas Cassel * FIS with the interrupt bit set, but since ahci_write_fis_d2h() will raise 1554e2a5d9b3SNiklas Cassel * an IRQ, we need to call them in reverse order. 1555e2a5d9b3SNiklas Cassel */ 15562967dc82SNiklas Cassel ahci_write_fis_d2h(ad, true); 1557f6ad2e32SAlexander Graf 15581a16ce64SNiklas Cassel if (!(ide_state->status & ERR_STAT) && 15591a16ce64SNiklas Cassel ad->port_regs.cmd_issue && !ad->check_bh) { 1560f63192b0SAlexander Bulekov ad->check_bh = qemu_bh_new_guarded(ahci_check_cmd_bh, ad, 1561f63192b0SAlexander Bulekov &ad->mem_reentrancy_guard); 1562f6ad2e32SAlexander Graf qemu_bh_schedule(ad->check_bh); 15634d29b50aSJan Kiszka } 1564f6ad2e32SAlexander Graf } 1565f6ad2e32SAlexander Graf 1566f6ad2e32SAlexander Graf static void ahci_irq_set(void *opaque, int n, int level) 1567f6ad2e32SAlexander Graf { 1568c5f12a80SPhilippe Mathieu-Daudé qemu_log_mask(LOG_UNIMP, "ahci: IRQ#%d level:%d\n", n, level); 1569f6ad2e32SAlexander Graf } 1570f6ad2e32SAlexander Graf 1571f6ad2e32SAlexander Graf static const IDEDMAOps ahci_dma_ops = { 1572f6ad2e32SAlexander Graf .start_dma = ahci_start_dma, 15737c03a691SJohn Snow .restart = ahci_restart, 1574e8ef8743SPaolo Bonzini .restart_dma = ahci_restart_dma, 1575bed9bcfaSPaolo Bonzini .pio_transfer = ahci_pio_transfer, 1576f6ad2e32SAlexander Graf .prepare_buf = ahci_dma_prepare_buf, 1577659142ecSJohn Snow .commit_buf = ahci_commit_buf, 1578f6ad2e32SAlexander Graf .rw_buf = ahci_dma_rw_buf, 1579c7e73adbSPaolo Bonzini .cmd_done = ahci_cmd_done, 1580f6ad2e32SAlexander Graf }; 1581f6ad2e32SAlexander Graf 15820487eea4SPeter Crosthwaite void ahci_init(AHCIState *s, DeviceState *qdev) 15830487eea4SPeter Crosthwaite { 15840487eea4SPeter Crosthwaite s->container = qdev; 15850487eea4SPeter Crosthwaite /* XXX BAR size should be 1k, but that breaks, so bump it to 4k for now */ 15860487eea4SPeter Crosthwaite memory_region_init_io(&s->mem, OBJECT(qdev), &ahci_mem_ops, s, 15870487eea4SPeter Crosthwaite "ahci", AHCI_MEM_BAR_SIZE); 15880487eea4SPeter Crosthwaite memory_region_init_io(&s->idp, OBJECT(qdev), &ahci_idp_ops, s, 15890487eea4SPeter Crosthwaite "ahci-idp", 32); 15900487eea4SPeter Crosthwaite } 15910487eea4SPeter Crosthwaite 15920487eea4SPeter Crosthwaite void ahci_realize(AHCIState *s, DeviceState *qdev, AddressSpace *as, int ports) 1593f6ad2e32SAlexander Graf { 1594f6ad2e32SAlexander Graf qemu_irq *irqs; 1595f6ad2e32SAlexander Graf int i; 1596f6ad2e32SAlexander Graf 1597df32fd1cSPaolo Bonzini s->as = as; 15982c4b9d0eSAlexander Graf s->ports = ports; 15995839e53bSMarkus Armbruster s->dev = g_new0(AHCIDevice, ports); 1600f6ad2e32SAlexander Graf ahci_reg_init(s); 16012c4b9d0eSAlexander Graf irqs = qemu_allocate_irqs(ahci_irq_set, s, s->ports); 16022c4b9d0eSAlexander Graf for (i = 0; i < s->ports; i++) { 1603f6ad2e32SAlexander Graf AHCIDevice *ad = &s->dev[i]; 1604f6ad2e32SAlexander Graf 160582c74ac4SPeter Maydell ide_bus_init(&ad->port, sizeof(ad->port), qdev, i, 1); 1606c9519630SPhilippe Mathieu-Daudé ide_bus_init_output_irq(&ad->port, irqs[i]); 1607f6ad2e32SAlexander Graf 1608f6ad2e32SAlexander Graf ad->hba = s; 1609f6ad2e32SAlexander Graf ad->port_no = i; 1610f6ad2e32SAlexander Graf ad->port.dma = &ad->dma; 1611f6ad2e32SAlexander Graf ad->port.dma->ops = &ahci_dma_ops; 1612e29b1246SPhilippe Mathieu-Daudé ide_bus_register_restart_cb(&ad->port); 1613f6ad2e32SAlexander Graf } 16149d324b0eSMarc-André Lureau g_free(irqs); 1615f6ad2e32SAlexander Graf } 1616f6ad2e32SAlexander Graf 16172c4b9d0eSAlexander Graf void ahci_uninit(AHCIState *s) 16182c4b9d0eSAlexander Graf { 1619d68f0f77SLi Qiang int i, j; 1620d68f0f77SLi Qiang 1621d68f0f77SLi Qiang for (i = 0; i < s->ports; i++) { 1622d68f0f77SLi Qiang AHCIDevice *ad = &s->dev[i]; 1623d68f0f77SLi Qiang 1624d68f0f77SLi Qiang for (j = 0; j < 2; j++) { 1625*a5afeefbSPhilippe Mathieu-Daudé ide_exit(&ad->port.ifs[j]); 1626d68f0f77SLi Qiang } 1627955f5c7bSIgor Mammedov object_unparent(OBJECT(&ad->port)); 1628d68f0f77SLi Qiang } 1629d68f0f77SLi Qiang 16307267c094SAnthony Liguori g_free(s->dev); 16312c4b9d0eSAlexander Graf } 16322c4b9d0eSAlexander Graf 16338ab60a07SJan Kiszka void ahci_reset(AHCIState *s) 1634f6ad2e32SAlexander Graf { 1635a26a13daSAlexander Motin AHCIPortRegs *pr; 1636f6ad2e32SAlexander Graf int i; 1637f6ad2e32SAlexander Graf 1638e4baa9f0SJohn Snow trace_ahci_reset(s); 1639e4baa9f0SJohn Snow 16408ab60a07SJan Kiszka s->control_regs.irqstatus = 0; 164113164591SMichael S. Tsirkin /* AHCI Enable (AE) 164213164591SMichael S. Tsirkin * The implementation of this bit is dependent upon the value of the 164313164591SMichael S. Tsirkin * CAP.SAM bit. If CAP.SAM is '0', then GHC.AE shall be read-write and 164413164591SMichael S. Tsirkin * shall have a reset value of '0'. If CAP.SAM is '1', then AE shall be 164513164591SMichael S. Tsirkin * read-only and shall have a reset value of '1'. 164613164591SMichael S. Tsirkin * 164713164591SMichael S. Tsirkin * We set HOST_CAP_AHCI so we must enable AHCI at reset. 164813164591SMichael S. Tsirkin */ 164913164591SMichael S. Tsirkin s->control_regs.ghc = HOST_CTL_AHCI_EN; 1650760c3e44SAlexander Graf 16518ab60a07SJan Kiszka for (i = 0; i < s->ports; i++) { 16528ab60a07SJan Kiszka pr = &s->dev[i].port_regs; 1653a26a13daSAlexander Motin pr->irq_stat = 0; 1654a26a13daSAlexander Motin pr->irq_mask = 0; 1655a26a13daSAlexander Motin pr->scr_ctl = 0; 16562a4f4f34SJason Baron pr->cmd = PORT_CMD_SPIN_UP | PORT_CMD_POWER_ON; 16578ab60a07SJan Kiszka ahci_reset_port(s, i); 1658f6ad2e32SAlexander Graf } 1659f6ad2e32SAlexander Graf } 1660d9fa31a3SRob Herring 1661684d5013SJohn Snow static const VMStateDescription vmstate_ncq_tfs = { 1662684d5013SJohn Snow .name = "ncq state", 1663684d5013SJohn Snow .version_id = 1, 1664684d5013SJohn Snow .fields = (VMStateField[]) { 1665684d5013SJohn Snow VMSTATE_UINT32(sector_count, NCQTransferState), 1666684d5013SJohn Snow VMSTATE_UINT64(lba, NCQTransferState), 1667684d5013SJohn Snow VMSTATE_UINT8(tag, NCQTransferState), 1668684d5013SJohn Snow VMSTATE_UINT8(cmd, NCQTransferState), 1669684d5013SJohn Snow VMSTATE_UINT8(slot, NCQTransferState), 1670684d5013SJohn Snow VMSTATE_BOOL(used, NCQTransferState), 1671684d5013SJohn Snow VMSTATE_BOOL(halt, NCQTransferState), 1672684d5013SJohn Snow VMSTATE_END_OF_LIST() 1673684d5013SJohn Snow }, 1674684d5013SJohn Snow }; 1675684d5013SJohn Snow 1676a2623021SJason Baron static const VMStateDescription vmstate_ahci_device = { 1677a2623021SJason Baron .name = "ahci port", 1678a2623021SJason Baron .version_id = 1, 1679a2623021SJason Baron .fields = (VMStateField[]) { 1680a2623021SJason Baron VMSTATE_IDE_BUS(port, AHCIDevice), 1681bd664910SJohn Snow VMSTATE_IDE_DRIVE(port.ifs[0], AHCIDevice), 1682a2623021SJason Baron VMSTATE_UINT32(port_state, AHCIDevice), 1683a2623021SJason Baron VMSTATE_UINT32(finished, AHCIDevice), 1684a2623021SJason Baron VMSTATE_UINT32(port_regs.lst_addr, AHCIDevice), 1685a2623021SJason Baron VMSTATE_UINT32(port_regs.lst_addr_hi, AHCIDevice), 1686a2623021SJason Baron VMSTATE_UINT32(port_regs.fis_addr, AHCIDevice), 1687a2623021SJason Baron VMSTATE_UINT32(port_regs.fis_addr_hi, AHCIDevice), 1688a2623021SJason Baron VMSTATE_UINT32(port_regs.irq_stat, AHCIDevice), 1689a2623021SJason Baron VMSTATE_UINT32(port_regs.irq_mask, AHCIDevice), 1690a2623021SJason Baron VMSTATE_UINT32(port_regs.cmd, AHCIDevice), 1691a2623021SJason Baron VMSTATE_UINT32(port_regs.tfdata, AHCIDevice), 1692a2623021SJason Baron VMSTATE_UINT32(port_regs.sig, AHCIDevice), 1693a2623021SJason Baron VMSTATE_UINT32(port_regs.scr_stat, AHCIDevice), 1694a2623021SJason Baron VMSTATE_UINT32(port_regs.scr_ctl, AHCIDevice), 1695a2623021SJason Baron VMSTATE_UINT32(port_regs.scr_err, AHCIDevice), 1696a2623021SJason Baron VMSTATE_UINT32(port_regs.scr_act, AHCIDevice), 1697a2623021SJason Baron VMSTATE_UINT32(port_regs.cmd_issue, AHCIDevice), 1698ae79c2dbSPaolo Bonzini VMSTATE_BOOL(done_first_drq, AHCIDevice), 1699a2623021SJason Baron VMSTATE_INT32(busy_slot, AHCIDevice), 1700a2623021SJason Baron VMSTATE_BOOL(init_d2h_sent, AHCIDevice), 1701684d5013SJohn Snow VMSTATE_STRUCT_ARRAY(ncq_tfs, AHCIDevice, AHCI_MAX_CMDS, 1702684d5013SJohn Snow 1, vmstate_ncq_tfs, NCQTransferState), 1703a2623021SJason Baron VMSTATE_END_OF_LIST() 1704a2623021SJason Baron }, 1705a2623021SJason Baron }; 1706a2623021SJason Baron 1707a2623021SJason Baron static int ahci_state_post_load(void *opaque, int version_id) 1708a2623021SJason Baron { 1709684d5013SJohn Snow int i, j; 1710a2623021SJason Baron struct AHCIDevice *ad; 1711684d5013SJohn Snow NCQTransferState *ncq_tfs; 1712f8a6c5f3SJohn Snow AHCIPortRegs *pr; 1713a2623021SJason Baron AHCIState *s = opaque; 1714a2623021SJason Baron 1715a2623021SJason Baron for (i = 0; i < s->ports; i++) { 1716a2623021SJason Baron ad = &s->dev[i]; 1717f8a6c5f3SJohn Snow pr = &ad->port_regs; 1718f8a6c5f3SJohn Snow 1719f8a6c5f3SJohn Snow if (!(pr->cmd & PORT_CMD_START) && (pr->cmd & PORT_CMD_LIST_ON)) { 1720f8a6c5f3SJohn Snow error_report("AHCI: DMA engine should be off, but status bit " 1721f8a6c5f3SJohn Snow "indicates it is still running."); 1722f8a6c5f3SJohn Snow return -1; 1723f8a6c5f3SJohn Snow } 1724f8a6c5f3SJohn Snow if (!(pr->cmd & PORT_CMD_FIS_RX) && (pr->cmd & PORT_CMD_FIS_ON)) { 1725f8a6c5f3SJohn Snow error_report("AHCI: FIS RX engine should be off, but status bit " 1726f8a6c5f3SJohn Snow "indicates it is still running."); 1727f8a6c5f3SJohn Snow return -1; 1728f8a6c5f3SJohn Snow } 1729a2623021SJason Baron 1730d5904749SJohn Snow /* After a migrate, the DMA/FIS engines are "off" and 1731d5904749SJohn Snow * need to be conditionally restarted */ 1732d5904749SJohn Snow pr->cmd &= ~(PORT_CMD_LIST_ON | PORT_CMD_FIS_ON); 1733d5904749SJohn Snow if (ahci_cond_start_engines(ad) != 0) { 1734cd6cb73bSJohn Snow return -1; 1735cd6cb73bSJohn Snow } 1736cd6cb73bSJohn Snow 1737684d5013SJohn Snow for (j = 0; j < AHCI_MAX_CMDS; j++) { 1738684d5013SJohn Snow ncq_tfs = &ad->ncq_tfs[j]; 1739684d5013SJohn Snow ncq_tfs->drive = ad; 1740684d5013SJohn Snow 1741684d5013SJohn Snow if (ncq_tfs->used != ncq_tfs->halt) { 1742684d5013SJohn Snow return -1; 1743684d5013SJohn Snow } 1744684d5013SJohn Snow if (!ncq_tfs->halt) { 1745684d5013SJohn Snow continue; 1746684d5013SJohn Snow } 1747684d5013SJohn Snow if (!is_ncq(ncq_tfs->cmd)) { 1748684d5013SJohn Snow return -1; 1749684d5013SJohn Snow } 1750684d5013SJohn Snow if (ncq_tfs->slot != ncq_tfs->tag) { 1751684d5013SJohn Snow return -1; 1752684d5013SJohn Snow } 1753684d5013SJohn Snow /* If ncq_tfs->halt is justly set, the engine should be engaged, 1754684d5013SJohn Snow * and the command list buffer should be mapped. */ 1755684d5013SJohn Snow ncq_tfs->cmdh = get_cmd_header(s, i, ncq_tfs->slot); 1756684d5013SJohn Snow if (!ncq_tfs->cmdh) { 1757684d5013SJohn Snow return -1; 1758684d5013SJohn Snow } 1759684d5013SJohn Snow ahci_populate_sglist(ncq_tfs->drive, &ncq_tfs->sglist, 1760075f32d3SPhilippe Mathieu-Daudé ncq_tfs->cmdh, 1761075f32d3SPhilippe Mathieu-Daudé ncq_tfs->sector_count * BDRV_SECTOR_SIZE, 1762684d5013SJohn Snow 0); 1763684d5013SJohn Snow if (ncq_tfs->sector_count != ncq_tfs->sglist.size >> 9) { 1764684d5013SJohn Snow return -1; 1765684d5013SJohn Snow } 1766684d5013SJohn Snow } 1767684d5013SJohn Snow 1768684d5013SJohn Snow 1769a2623021SJason Baron /* 1770e8ef8743SPaolo Bonzini * If an error is present, ad->busy_slot will be valid and not -1. 1771e8ef8743SPaolo Bonzini * In this case, an operation is waiting to resume and will re-check 1772e8ef8743SPaolo Bonzini * for additional AHCI commands to execute upon completion. 1773e8ef8743SPaolo Bonzini * 1774e8ef8743SPaolo Bonzini * In the case where no error was present, busy_slot will be -1, 1775e8ef8743SPaolo Bonzini * and we should check to see if there are additional commands waiting. 1776a2623021SJason Baron */ 1777e8ef8743SPaolo Bonzini if (ad->busy_slot == -1) { 1778a2623021SJason Baron check_cmd(s, i); 1779c27c73aaSJohn Snow } else { 1780c27c73aaSJohn Snow /* We are in the middle of a command, and may need to access 1781c27c73aaSJohn Snow * the command header in guest memory again. */ 1782c27c73aaSJohn Snow if (ad->busy_slot < 0 || ad->busy_slot >= AHCI_MAX_CMDS) { 1783c27c73aaSJohn Snow return -1; 1784c27c73aaSJohn Snow } 1785ee364416SJohn Snow ad->cur_cmd = get_cmd_header(s, i, ad->busy_slot); 1786a2623021SJason Baron } 1787e8ef8743SPaolo Bonzini } 1788a2623021SJason Baron 1789a2623021SJason Baron return 0; 1790a2623021SJason Baron } 1791a2623021SJason Baron 1792a2623021SJason Baron const VMStateDescription vmstate_ahci = { 1793a2623021SJason Baron .name = "ahci", 1794a2623021SJason Baron .version_id = 1, 1795a2623021SJason Baron .post_load = ahci_state_post_load, 1796a2623021SJason Baron .fields = (VMStateField[]) { 1797a2623021SJason Baron VMSTATE_STRUCT_VARRAY_POINTER_INT32(dev, AHCIState, ports, 1798a2623021SJason Baron vmstate_ahci_device, AHCIDevice), 1799a2623021SJason Baron VMSTATE_UINT32(control_regs.cap, AHCIState), 1800a2623021SJason Baron VMSTATE_UINT32(control_regs.ghc, AHCIState), 1801a2623021SJason Baron VMSTATE_UINT32(control_regs.irqstatus, AHCIState), 1802a2623021SJason Baron VMSTATE_UINT32(control_regs.impl, AHCIState), 1803a2623021SJason Baron VMSTATE_UINT32(control_regs.version, AHCIState), 1804a2623021SJason Baron VMSTATE_UINT32(idp_index, AHCIState), 1805d2164ad3SHalil Pasic VMSTATE_INT32_EQUAL(ports, AHCIState, NULL), 1806a2623021SJason Baron VMSTATE_END_OF_LIST() 1807a2623021SJason Baron }, 1808a2623021SJason Baron }; 1809a2623021SJason Baron 1810d9fa31a3SRob Herring static const VMStateDescription vmstate_sysbus_ahci = { 1811d9fa31a3SRob Herring .name = "sysbus-ahci", 1812a2623021SJason Baron .fields = (VMStateField[]) { 1813bd164307SRob Herring VMSTATE_AHCI(ahci, SysbusAHCIState), 1814a2623021SJason Baron VMSTATE_END_OF_LIST() 1815a2623021SJason Baron }, 1816d9fa31a3SRob Herring }; 1817d9fa31a3SRob Herring 18188ab60a07SJan Kiszka static void sysbus_ahci_reset(DeviceState *dev) 18198ab60a07SJan Kiszka { 1820b3b162c3SHu Tao SysbusAHCIState *s = SYSBUS_AHCI(dev); 18218ab60a07SJan Kiszka 18228ab60a07SJan Kiszka ahci_reset(&s->ahci); 18238ab60a07SJan Kiszka } 18248ab60a07SJan Kiszka 18250487eea4SPeter Crosthwaite static void sysbus_ahci_init(Object *obj) 1826d9fa31a3SRob Herring { 18270487eea4SPeter Crosthwaite SysbusAHCIState *s = SYSBUS_AHCI(obj); 18280487eea4SPeter Crosthwaite SysBusDevice *sbd = SYS_BUS_DEVICE(obj); 1829d9fa31a3SRob Herring 18300487eea4SPeter Crosthwaite ahci_init(&s->ahci, DEVICE(obj)); 18317acb423fSHu Tao 18327acb423fSHu Tao sysbus_init_mmio(sbd, &s->ahci.mem); 18337acb423fSHu Tao sysbus_init_irq(sbd, &s->ahci.irq); 1834d9fa31a3SRob Herring } 1835d9fa31a3SRob Herring 18360487eea4SPeter Crosthwaite static void sysbus_ahci_realize(DeviceState *dev, Error **errp) 18370487eea4SPeter Crosthwaite { 18380487eea4SPeter Crosthwaite SysbusAHCIState *s = SYSBUS_AHCI(dev); 18390487eea4SPeter Crosthwaite 18400487eea4SPeter Crosthwaite ahci_realize(&s->ahci, dev, &address_space_memory, s->num_ports); 18410487eea4SPeter Crosthwaite } 18420487eea4SPeter Crosthwaite 184339bffca2SAnthony Liguori static Property sysbus_ahci_properties[] = { 184439bffca2SAnthony Liguori DEFINE_PROP_UINT32("num-ports", SysbusAHCIState, num_ports, 1), 184539bffca2SAnthony Liguori DEFINE_PROP_END_OF_LIST(), 184639bffca2SAnthony Liguori }; 184739bffca2SAnthony Liguori 1848999e12bbSAnthony Liguori static void sysbus_ahci_class_init(ObjectClass *klass, void *data) 1849999e12bbSAnthony Liguori { 185039bffca2SAnthony Liguori DeviceClass *dc = DEVICE_CLASS(klass); 1851999e12bbSAnthony Liguori 18527acb423fSHu Tao dc->realize = sysbus_ahci_realize; 185339bffca2SAnthony Liguori dc->vmsd = &vmstate_sysbus_ahci; 18544f67d30bSMarc-André Lureau device_class_set_props(dc, sysbus_ahci_properties); 18558ab60a07SJan Kiszka dc->reset = sysbus_ahci_reset; 1856125ee0edSMarcel Apfelbaum set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); 1857999e12bbSAnthony Liguori } 1858999e12bbSAnthony Liguori 18598c43a6f0SAndreas Färber static const TypeInfo sysbus_ahci_info = { 1860b3b162c3SHu Tao .name = TYPE_SYSBUS_AHCI, 186139bffca2SAnthony Liguori .parent = TYPE_SYS_BUS_DEVICE, 186239bffca2SAnthony Liguori .instance_size = sizeof(SysbusAHCIState), 18630487eea4SPeter Crosthwaite .instance_init = sysbus_ahci_init, 1864999e12bbSAnthony Liguori .class_init = sysbus_ahci_class_init, 1865d9fa31a3SRob Herring }; 1866d9fa31a3SRob Herring 186783f7d43aSAndreas Färber static void sysbus_ahci_register_types(void) 1868d9fa31a3SRob Herring { 186939bffca2SAnthony Liguori type_register_static(&sysbus_ahci_info); 1870d9fa31a3SRob Herring } 1871d9fa31a3SRob Herring 187283f7d43aSAndreas Färber type_init(sysbus_ahci_register_types) 1873d93162e1SJohn Snow 1874bbe3179aSJohn Snow int32_t ahci_get_num_ports(PCIDevice *dev) 1875bbe3179aSJohn Snow { 1876aa3c41fbSEduardo Habkost AHCIPCIState *d = ICH9_AHCI(dev); 1877bbe3179aSJohn Snow AHCIState *ahci = &d->ahci; 1878bbe3179aSJohn Snow 1879bbe3179aSJohn Snow return ahci->ports; 1880bbe3179aSJohn Snow } 1881bbe3179aSJohn Snow 1882d93162e1SJohn Snow void ahci_ide_create_devs(PCIDevice *dev, DriveInfo **hd) 1883d93162e1SJohn Snow { 1884aa3c41fbSEduardo Habkost AHCIPCIState *d = ICH9_AHCI(dev); 1885d93162e1SJohn Snow AHCIState *ahci = &d->ahci; 1886d93162e1SJohn Snow int i; 1887d93162e1SJohn Snow 1888d93162e1SJohn Snow for (i = 0; i < ahci->ports; i++) { 1889d93162e1SJohn Snow if (hd[i] == NULL) { 1890d93162e1SJohn Snow continue; 1891d93162e1SJohn Snow } 1892b6a5ab27SPhilippe Mathieu-Daudé ide_bus_create_drive(&ahci->dev[i].port, 0, hd[i]); 1893d93162e1SJohn Snow } 1894d93162e1SJohn Snow 1895d93162e1SJohn Snow } 1896