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 12f6ad2e32SAlexander Graf * version 2 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 24f6ad2e32SAlexander Graf #include <hw/hw.h> 25f6ad2e32SAlexander Graf #include <hw/msi.h> 26f6ad2e32SAlexander Graf #include <hw/pc.h> 27f6ad2e32SAlexander Graf #include <hw/pci.h> 28f6ad2e32SAlexander Graf 29f6ad2e32SAlexander Graf #include "monitor.h" 30f6ad2e32SAlexander Graf #include "dma.h" 31f6ad2e32SAlexander Graf #include "cpu-common.h" 32f6ad2e32SAlexander Graf #include "internal.h" 33f6ad2e32SAlexander Graf #include <hw/ide/pci.h> 3403c7a6a8SSebastian Herbszt #include <hw/ide/ahci.h> 35f6ad2e32SAlexander Graf 36f6ad2e32SAlexander Graf /* #define DEBUG_AHCI */ 37f6ad2e32SAlexander Graf 38f6ad2e32SAlexander Graf #ifdef DEBUG_AHCI 39f6ad2e32SAlexander Graf #define DPRINTF(port, fmt, ...) \ 40f6ad2e32SAlexander Graf do { fprintf(stderr, "ahci: %s: [%d] ", __FUNCTION__, port); \ 41f6ad2e32SAlexander Graf fprintf(stderr, fmt, ## __VA_ARGS__); } while (0) 42f6ad2e32SAlexander Graf #else 43f6ad2e32SAlexander Graf #define DPRINTF(port, fmt, ...) do {} while(0) 44f6ad2e32SAlexander Graf #endif 45f6ad2e32SAlexander Graf 46f6ad2e32SAlexander Graf static void check_cmd(AHCIState *s, int port); 47f6ad2e32SAlexander Graf static int handle_cmd(AHCIState *s,int port,int slot); 48f6ad2e32SAlexander Graf static void ahci_reset_port(AHCIState *s, int port); 49f6ad2e32SAlexander Graf static void ahci_write_fis_d2h(AHCIDevice *ad, uint8_t *cmd_fis); 5087e62065SAlexander Graf static void ahci_init_d2h(AHCIDevice *ad); 51f6ad2e32SAlexander Graf 52f6ad2e32SAlexander Graf static uint32_t ahci_port_read(AHCIState *s, int port, int offset) 53f6ad2e32SAlexander Graf { 54f6ad2e32SAlexander Graf uint32_t val; 55f6ad2e32SAlexander Graf AHCIPortRegs *pr; 56f6ad2e32SAlexander Graf pr = &s->dev[port].port_regs; 57f6ad2e32SAlexander Graf 58f6ad2e32SAlexander Graf switch (offset) { 59f6ad2e32SAlexander Graf case PORT_LST_ADDR: 60f6ad2e32SAlexander Graf val = pr->lst_addr; 61f6ad2e32SAlexander Graf break; 62f6ad2e32SAlexander Graf case PORT_LST_ADDR_HI: 63f6ad2e32SAlexander Graf val = pr->lst_addr_hi; 64f6ad2e32SAlexander Graf break; 65f6ad2e32SAlexander Graf case PORT_FIS_ADDR: 66f6ad2e32SAlexander Graf val = pr->fis_addr; 67f6ad2e32SAlexander Graf break; 68f6ad2e32SAlexander Graf case PORT_FIS_ADDR_HI: 69f6ad2e32SAlexander Graf val = pr->fis_addr_hi; 70f6ad2e32SAlexander Graf break; 71f6ad2e32SAlexander Graf case PORT_IRQ_STAT: 72f6ad2e32SAlexander Graf val = pr->irq_stat; 73f6ad2e32SAlexander Graf break; 74f6ad2e32SAlexander Graf case PORT_IRQ_MASK: 75f6ad2e32SAlexander Graf val = pr->irq_mask; 76f6ad2e32SAlexander Graf break; 77f6ad2e32SAlexander Graf case PORT_CMD: 78f6ad2e32SAlexander Graf val = pr->cmd; 79f6ad2e32SAlexander Graf break; 80f6ad2e32SAlexander Graf case PORT_TFDATA: 81f6ad2e32SAlexander Graf val = ((uint16_t)s->dev[port].port.ifs[0].error << 8) | 82f6ad2e32SAlexander Graf s->dev[port].port.ifs[0].status; 83f6ad2e32SAlexander Graf break; 84f6ad2e32SAlexander Graf case PORT_SIG: 85f6ad2e32SAlexander Graf val = pr->sig; 86f6ad2e32SAlexander Graf break; 87f6ad2e32SAlexander Graf case PORT_SCR_STAT: 88f6ad2e32SAlexander Graf if (s->dev[port].port.ifs[0].bs) { 89f6ad2e32SAlexander Graf val = SATA_SCR_SSTATUS_DET_DEV_PRESENT_PHY_UP | 90f6ad2e32SAlexander Graf SATA_SCR_SSTATUS_SPD_GEN1 | SATA_SCR_SSTATUS_IPM_ACTIVE; 91f6ad2e32SAlexander Graf } else { 92f6ad2e32SAlexander Graf val = SATA_SCR_SSTATUS_DET_NODEV; 93f6ad2e32SAlexander Graf } 94f6ad2e32SAlexander Graf break; 95f6ad2e32SAlexander Graf case PORT_SCR_CTL: 96f6ad2e32SAlexander Graf val = pr->scr_ctl; 97f6ad2e32SAlexander Graf break; 98f6ad2e32SAlexander Graf case PORT_SCR_ERR: 99f6ad2e32SAlexander Graf val = pr->scr_err; 100f6ad2e32SAlexander Graf break; 101f6ad2e32SAlexander Graf case PORT_SCR_ACT: 102f6ad2e32SAlexander Graf pr->scr_act &= ~s->dev[port].finished; 103f6ad2e32SAlexander Graf s->dev[port].finished = 0; 104f6ad2e32SAlexander Graf val = pr->scr_act; 105f6ad2e32SAlexander Graf break; 106f6ad2e32SAlexander Graf case PORT_CMD_ISSUE: 107f6ad2e32SAlexander Graf val = pr->cmd_issue; 108f6ad2e32SAlexander Graf break; 109f6ad2e32SAlexander Graf case PORT_RESERVED: 110f6ad2e32SAlexander Graf default: 111f6ad2e32SAlexander Graf val = 0; 112f6ad2e32SAlexander Graf } 113f6ad2e32SAlexander Graf DPRINTF(port, "offset: 0x%x val: 0x%x\n", offset, val); 114f6ad2e32SAlexander Graf return val; 115f6ad2e32SAlexander Graf 116f6ad2e32SAlexander Graf } 117f6ad2e32SAlexander Graf 118f6ad2e32SAlexander Graf static void ahci_irq_raise(AHCIState *s, AHCIDevice *dev) 119f6ad2e32SAlexander Graf { 120f6ad2e32SAlexander Graf struct AHCIPCIState *d = container_of(s, AHCIPCIState, ahci); 121f6ad2e32SAlexander Graf 122f6ad2e32SAlexander Graf DPRINTF(0, "raise irq\n"); 123f6ad2e32SAlexander Graf 124f6ad2e32SAlexander Graf if (msi_enabled(&d->card)) { 125f6ad2e32SAlexander Graf msi_notify(&d->card, 0); 126f6ad2e32SAlexander Graf } else { 127f6ad2e32SAlexander Graf qemu_irq_raise(s->irq); 128f6ad2e32SAlexander Graf } 129f6ad2e32SAlexander Graf } 130f6ad2e32SAlexander Graf 131f6ad2e32SAlexander Graf static void ahci_irq_lower(AHCIState *s, AHCIDevice *dev) 132f6ad2e32SAlexander Graf { 133f6ad2e32SAlexander Graf struct AHCIPCIState *d = container_of(s, AHCIPCIState, ahci); 134f6ad2e32SAlexander Graf 135f6ad2e32SAlexander Graf DPRINTF(0, "lower irq\n"); 136f6ad2e32SAlexander Graf 137f6ad2e32SAlexander Graf if (!msi_enabled(&d->card)) { 138f6ad2e32SAlexander Graf qemu_irq_lower(s->irq); 139f6ad2e32SAlexander Graf } 140f6ad2e32SAlexander Graf } 141f6ad2e32SAlexander Graf 142f6ad2e32SAlexander Graf static void ahci_check_irq(AHCIState *s) 143f6ad2e32SAlexander Graf { 144f6ad2e32SAlexander Graf int i; 145f6ad2e32SAlexander Graf 146f6ad2e32SAlexander Graf DPRINTF(-1, "check irq %#x\n", s->control_regs.irqstatus); 147f6ad2e32SAlexander Graf 1482c4b9d0eSAlexander Graf for (i = 0; i < s->ports; i++) { 149f6ad2e32SAlexander Graf AHCIPortRegs *pr = &s->dev[i].port_regs; 150f6ad2e32SAlexander Graf if (pr->irq_stat & pr->irq_mask) { 151f6ad2e32SAlexander Graf s->control_regs.irqstatus |= (1 << i); 152f6ad2e32SAlexander Graf } 153f6ad2e32SAlexander Graf } 154f6ad2e32SAlexander Graf 155f6ad2e32SAlexander Graf if (s->control_regs.irqstatus && 156f6ad2e32SAlexander Graf (s->control_regs.ghc & HOST_CTL_IRQ_EN)) { 157f6ad2e32SAlexander Graf ahci_irq_raise(s, NULL); 158f6ad2e32SAlexander Graf } else { 159f6ad2e32SAlexander Graf ahci_irq_lower(s, NULL); 160f6ad2e32SAlexander Graf } 161f6ad2e32SAlexander Graf } 162f6ad2e32SAlexander Graf 163f6ad2e32SAlexander Graf static void ahci_trigger_irq(AHCIState *s, AHCIDevice *d, 164f6ad2e32SAlexander Graf int irq_type) 165f6ad2e32SAlexander Graf { 166f6ad2e32SAlexander Graf DPRINTF(d->port_no, "trigger irq %#x -> %x\n", 167f6ad2e32SAlexander Graf irq_type, d->port_regs.irq_mask & irq_type); 168f6ad2e32SAlexander Graf 169f6ad2e32SAlexander Graf d->port_regs.irq_stat |= irq_type; 170f6ad2e32SAlexander Graf ahci_check_irq(s); 171f6ad2e32SAlexander Graf } 172f6ad2e32SAlexander Graf 173f6ad2e32SAlexander Graf static void map_page(uint8_t **ptr, uint64_t addr, uint32_t wanted) 174f6ad2e32SAlexander Graf { 175f6ad2e32SAlexander Graf target_phys_addr_t len = wanted; 176f6ad2e32SAlexander Graf 177f6ad2e32SAlexander Graf if (*ptr) { 178fe6ceac8SStefan Hajnoczi cpu_physical_memory_unmap(*ptr, len, 1, len); 179f6ad2e32SAlexander Graf } 180f6ad2e32SAlexander Graf 181f6ad2e32SAlexander Graf *ptr = cpu_physical_memory_map(addr, &len, 1); 182f6ad2e32SAlexander Graf if (len < wanted) { 183fe6ceac8SStefan Hajnoczi cpu_physical_memory_unmap(*ptr, len, 1, len); 184f6ad2e32SAlexander Graf *ptr = NULL; 185f6ad2e32SAlexander Graf } 186f6ad2e32SAlexander Graf } 187f6ad2e32SAlexander Graf 188f6ad2e32SAlexander Graf static void ahci_port_write(AHCIState *s, int port, int offset, uint32_t val) 189f6ad2e32SAlexander Graf { 190f6ad2e32SAlexander Graf AHCIPortRegs *pr = &s->dev[port].port_regs; 191f6ad2e32SAlexander Graf 192f6ad2e32SAlexander Graf DPRINTF(port, "offset: 0x%x val: 0x%x\n", offset, val); 193f6ad2e32SAlexander Graf switch (offset) { 194f6ad2e32SAlexander Graf case PORT_LST_ADDR: 195f6ad2e32SAlexander Graf pr->lst_addr = val; 196f6ad2e32SAlexander Graf map_page(&s->dev[port].lst, 197f6ad2e32SAlexander Graf ((uint64_t)pr->lst_addr_hi << 32) | pr->lst_addr, 1024); 198f6ad2e32SAlexander Graf s->dev[port].cur_cmd = NULL; 199f6ad2e32SAlexander Graf break; 200f6ad2e32SAlexander Graf case PORT_LST_ADDR_HI: 201f6ad2e32SAlexander Graf pr->lst_addr_hi = val; 202f6ad2e32SAlexander Graf map_page(&s->dev[port].lst, 203f6ad2e32SAlexander Graf ((uint64_t)pr->lst_addr_hi << 32) | pr->lst_addr, 1024); 204f6ad2e32SAlexander Graf s->dev[port].cur_cmd = NULL; 205f6ad2e32SAlexander Graf break; 206f6ad2e32SAlexander Graf case PORT_FIS_ADDR: 207f6ad2e32SAlexander Graf pr->fis_addr = val; 208f6ad2e32SAlexander Graf map_page(&s->dev[port].res_fis, 209f6ad2e32SAlexander Graf ((uint64_t)pr->fis_addr_hi << 32) | pr->fis_addr, 256); 210f6ad2e32SAlexander Graf break; 211f6ad2e32SAlexander Graf case PORT_FIS_ADDR_HI: 212f6ad2e32SAlexander Graf pr->fis_addr_hi = val; 213f6ad2e32SAlexander Graf map_page(&s->dev[port].res_fis, 214f6ad2e32SAlexander Graf ((uint64_t)pr->fis_addr_hi << 32) | pr->fis_addr, 256); 215f6ad2e32SAlexander Graf break; 216f6ad2e32SAlexander Graf case PORT_IRQ_STAT: 217f6ad2e32SAlexander Graf pr->irq_stat &= ~val; 218f6ad2e32SAlexander Graf break; 219f6ad2e32SAlexander Graf case PORT_IRQ_MASK: 220f6ad2e32SAlexander Graf pr->irq_mask = val & 0xfdc000ff; 221f6ad2e32SAlexander Graf ahci_check_irq(s); 222f6ad2e32SAlexander Graf break; 223f6ad2e32SAlexander Graf case PORT_CMD: 224f6ad2e32SAlexander Graf pr->cmd = val & ~(PORT_CMD_LIST_ON | PORT_CMD_FIS_ON); 225f6ad2e32SAlexander Graf 226f6ad2e32SAlexander Graf if (pr->cmd & PORT_CMD_START) { 227f6ad2e32SAlexander Graf pr->cmd |= PORT_CMD_LIST_ON; 228f6ad2e32SAlexander Graf } 229f6ad2e32SAlexander Graf 230f6ad2e32SAlexander Graf if (pr->cmd & PORT_CMD_FIS_RX) { 231f6ad2e32SAlexander Graf pr->cmd |= PORT_CMD_FIS_ON; 232f6ad2e32SAlexander Graf } 233f6ad2e32SAlexander Graf 23487e62065SAlexander Graf /* XXX usually the FIS would be pending on the bus here and 23587e62065SAlexander Graf issuing deferred until the OS enables FIS receival. 23687e62065SAlexander Graf Instead, we only submit it once - which works in most 23787e62065SAlexander Graf cases, but is a hack. */ 23887e62065SAlexander Graf if ((pr->cmd & PORT_CMD_FIS_ON) && 23987e62065SAlexander Graf !s->dev[port].init_d2h_sent) { 24087e62065SAlexander Graf ahci_init_d2h(&s->dev[port]); 24187e62065SAlexander Graf s->dev[port].init_d2h_sent = 1; 24287e62065SAlexander Graf } 24387e62065SAlexander Graf 244f6ad2e32SAlexander Graf check_cmd(s, port); 245f6ad2e32SAlexander Graf break; 246f6ad2e32SAlexander Graf case PORT_TFDATA: 247f6ad2e32SAlexander Graf s->dev[port].port.ifs[0].error = (val >> 8) & 0xff; 248f6ad2e32SAlexander Graf s->dev[port].port.ifs[0].status = val & 0xff; 249f6ad2e32SAlexander Graf break; 250f6ad2e32SAlexander Graf case PORT_SIG: 251f6ad2e32SAlexander Graf pr->sig = val; 252f6ad2e32SAlexander Graf break; 253f6ad2e32SAlexander Graf case PORT_SCR_STAT: 254f6ad2e32SAlexander Graf pr->scr_stat = val; 255f6ad2e32SAlexander Graf break; 256f6ad2e32SAlexander Graf case PORT_SCR_CTL: 257f6ad2e32SAlexander Graf if (((pr->scr_ctl & AHCI_SCR_SCTL_DET) == 1) && 258f6ad2e32SAlexander Graf ((val & AHCI_SCR_SCTL_DET) == 0)) { 259f6ad2e32SAlexander Graf ahci_reset_port(s, port); 260f6ad2e32SAlexander Graf } 261f6ad2e32SAlexander Graf pr->scr_ctl = val; 262f6ad2e32SAlexander Graf break; 263f6ad2e32SAlexander Graf case PORT_SCR_ERR: 264f6ad2e32SAlexander Graf pr->scr_err &= ~val; 265f6ad2e32SAlexander Graf break; 266f6ad2e32SAlexander Graf case PORT_SCR_ACT: 267f6ad2e32SAlexander Graf /* RW1 */ 268f6ad2e32SAlexander Graf pr->scr_act |= val; 269f6ad2e32SAlexander Graf break; 270f6ad2e32SAlexander Graf case PORT_CMD_ISSUE: 271f6ad2e32SAlexander Graf pr->cmd_issue |= val; 272f6ad2e32SAlexander Graf check_cmd(s, port); 273f6ad2e32SAlexander Graf break; 274f6ad2e32SAlexander Graf default: 275f6ad2e32SAlexander Graf break; 276f6ad2e32SAlexander Graf } 277f6ad2e32SAlexander Graf } 278f6ad2e32SAlexander Graf 27967e576c2SAvi Kivity static uint64_t ahci_mem_read(void *opaque, target_phys_addr_t addr, 28067e576c2SAvi Kivity unsigned size) 281f6ad2e32SAlexander Graf { 28267e576c2SAvi Kivity AHCIState *s = opaque; 283f6ad2e32SAlexander Graf uint32_t val = 0; 284f6ad2e32SAlexander Graf 285f6ad2e32SAlexander Graf if (addr < AHCI_GENERIC_HOST_CONTROL_REGS_MAX_ADDR) { 286f6ad2e32SAlexander Graf switch (addr) { 287f6ad2e32SAlexander Graf case HOST_CAP: 288f6ad2e32SAlexander Graf val = s->control_regs.cap; 289f6ad2e32SAlexander Graf break; 290f6ad2e32SAlexander Graf case HOST_CTL: 291f6ad2e32SAlexander Graf val = s->control_regs.ghc; 292f6ad2e32SAlexander Graf break; 293f6ad2e32SAlexander Graf case HOST_IRQ_STAT: 294f6ad2e32SAlexander Graf val = s->control_regs.irqstatus; 295f6ad2e32SAlexander Graf break; 296f6ad2e32SAlexander Graf case HOST_PORTS_IMPL: 297f6ad2e32SAlexander Graf val = s->control_regs.impl; 298f6ad2e32SAlexander Graf break; 299f6ad2e32SAlexander Graf case HOST_VERSION: 300f6ad2e32SAlexander Graf val = s->control_regs.version; 301f6ad2e32SAlexander Graf break; 302f6ad2e32SAlexander Graf } 303f6ad2e32SAlexander Graf 304f6ad2e32SAlexander Graf DPRINTF(-1, "(addr 0x%08X), val 0x%08X\n", (unsigned) addr, val); 305f6ad2e32SAlexander Graf } else if ((addr >= AHCI_PORT_REGS_START_ADDR) && 3062c4b9d0eSAlexander Graf (addr < (AHCI_PORT_REGS_START_ADDR + 3072c4b9d0eSAlexander Graf (s->ports * AHCI_PORT_ADDR_OFFSET_LEN)))) { 308f6ad2e32SAlexander Graf val = ahci_port_read(s, (addr - AHCI_PORT_REGS_START_ADDR) >> 7, 309f6ad2e32SAlexander Graf addr & AHCI_PORT_ADDR_OFFSET_MASK); 310f6ad2e32SAlexander Graf } 311f6ad2e32SAlexander Graf 312f6ad2e32SAlexander Graf return val; 313f6ad2e32SAlexander Graf } 314f6ad2e32SAlexander Graf 315f6ad2e32SAlexander Graf 316f6ad2e32SAlexander Graf 31767e576c2SAvi Kivity static void ahci_mem_write(void *opaque, target_phys_addr_t addr, 31867e576c2SAvi Kivity uint64_t val, unsigned size) 319f6ad2e32SAlexander Graf { 32067e576c2SAvi Kivity AHCIState *s = opaque; 321f6ad2e32SAlexander Graf 322f6ad2e32SAlexander Graf /* Only aligned reads are allowed on AHCI */ 323f6ad2e32SAlexander Graf if (addr & 3) { 324f6ad2e32SAlexander Graf fprintf(stderr, "ahci: Mis-aligned write to addr 0x" 325f6ad2e32SAlexander Graf TARGET_FMT_plx "\n", addr); 326f6ad2e32SAlexander Graf return; 327f6ad2e32SAlexander Graf } 328f6ad2e32SAlexander Graf 329f6ad2e32SAlexander Graf if (addr < AHCI_GENERIC_HOST_CONTROL_REGS_MAX_ADDR) { 330f6ad2e32SAlexander Graf DPRINTF(-1, "(addr 0x%08X), val 0x%08X\n", (unsigned) addr, val); 331f6ad2e32SAlexander Graf 332f6ad2e32SAlexander Graf switch (addr) { 333f6ad2e32SAlexander Graf case HOST_CAP: /* R/WO, RO */ 334f6ad2e32SAlexander Graf /* FIXME handle R/WO */ 335f6ad2e32SAlexander Graf break; 336f6ad2e32SAlexander Graf case HOST_CTL: /* R/W */ 337f6ad2e32SAlexander Graf if (val & HOST_CTL_RESET) { 338f6ad2e32SAlexander Graf DPRINTF(-1, "HBA Reset\n"); 339760c3e44SAlexander Graf ahci_reset(container_of(s, AHCIPCIState, ahci)); 340f6ad2e32SAlexander Graf } else { 341f6ad2e32SAlexander Graf s->control_regs.ghc = (val & 0x3) | HOST_CTL_AHCI_EN; 342f6ad2e32SAlexander Graf ahci_check_irq(s); 343f6ad2e32SAlexander Graf } 344f6ad2e32SAlexander Graf break; 345f6ad2e32SAlexander Graf case HOST_IRQ_STAT: /* R/WC, RO */ 346f6ad2e32SAlexander Graf s->control_regs.irqstatus &= ~val; 347f6ad2e32SAlexander Graf ahci_check_irq(s); 348f6ad2e32SAlexander Graf break; 349f6ad2e32SAlexander Graf case HOST_PORTS_IMPL: /* R/WO, RO */ 350f6ad2e32SAlexander Graf /* FIXME handle R/WO */ 351f6ad2e32SAlexander Graf break; 352f6ad2e32SAlexander Graf case HOST_VERSION: /* RO */ 353f6ad2e32SAlexander Graf /* FIXME report write? */ 354f6ad2e32SAlexander Graf break; 355f6ad2e32SAlexander Graf default: 356f6ad2e32SAlexander Graf DPRINTF(-1, "write to unknown register 0x%x\n", (unsigned)addr); 357f6ad2e32SAlexander Graf } 358f6ad2e32SAlexander Graf } else if ((addr >= AHCI_PORT_REGS_START_ADDR) && 3592c4b9d0eSAlexander Graf (addr < (AHCI_PORT_REGS_START_ADDR + 3602c4b9d0eSAlexander Graf (s->ports * AHCI_PORT_ADDR_OFFSET_LEN)))) { 361f6ad2e32SAlexander Graf ahci_port_write(s, (addr - AHCI_PORT_REGS_START_ADDR) >> 7, 362f6ad2e32SAlexander Graf addr & AHCI_PORT_ADDR_OFFSET_MASK, val); 363f6ad2e32SAlexander Graf } 364f6ad2e32SAlexander Graf 365f6ad2e32SAlexander Graf } 366f6ad2e32SAlexander Graf 36767e576c2SAvi Kivity static MemoryRegionOps ahci_mem_ops = { 36867e576c2SAvi Kivity .read = ahci_mem_read, 36967e576c2SAvi Kivity .write = ahci_mem_write, 37067e576c2SAvi Kivity .endianness = DEVICE_LITTLE_ENDIAN, 371f6ad2e32SAlexander Graf }; 372f6ad2e32SAlexander Graf 373*465f1ab1SDaniel Verkamp static uint64_t ahci_idp_read(void *opaque, target_phys_addr_t addr, 374*465f1ab1SDaniel Verkamp unsigned size) 375*465f1ab1SDaniel Verkamp { 376*465f1ab1SDaniel Verkamp AHCIState *s = opaque; 377*465f1ab1SDaniel Verkamp 378*465f1ab1SDaniel Verkamp if (addr == s->idp_offset) { 379*465f1ab1SDaniel Verkamp /* index register */ 380*465f1ab1SDaniel Verkamp return s->idp_index; 381*465f1ab1SDaniel Verkamp } else if (addr == s->idp_offset + 4) { 382*465f1ab1SDaniel Verkamp /* data register - do memory read at location selected by index */ 383*465f1ab1SDaniel Verkamp return ahci_mem_read(opaque, s->idp_index, size); 384*465f1ab1SDaniel Verkamp } else { 385*465f1ab1SDaniel Verkamp return 0; 386*465f1ab1SDaniel Verkamp } 387*465f1ab1SDaniel Verkamp } 388*465f1ab1SDaniel Verkamp 389*465f1ab1SDaniel Verkamp static void ahci_idp_write(void *opaque, target_phys_addr_t addr, 390*465f1ab1SDaniel Verkamp uint64_t val, unsigned size) 391*465f1ab1SDaniel Verkamp { 392*465f1ab1SDaniel Verkamp AHCIState *s = opaque; 393*465f1ab1SDaniel Verkamp 394*465f1ab1SDaniel Verkamp if (addr == s->idp_offset) { 395*465f1ab1SDaniel Verkamp /* index register - mask off reserved bits */ 396*465f1ab1SDaniel Verkamp s->idp_index = (uint32_t)val & ((AHCI_MEM_BAR_SIZE - 1) & ~3); 397*465f1ab1SDaniel Verkamp } else if (addr == s->idp_offset + 4) { 398*465f1ab1SDaniel Verkamp /* data register - do memory write at location selected by index */ 399*465f1ab1SDaniel Verkamp ahci_mem_write(opaque, s->idp_index, val, size); 400*465f1ab1SDaniel Verkamp } 401*465f1ab1SDaniel Verkamp } 402*465f1ab1SDaniel Verkamp 403*465f1ab1SDaniel Verkamp static MemoryRegionOps ahci_idp_ops = { 404*465f1ab1SDaniel Verkamp .read = ahci_idp_read, 405*465f1ab1SDaniel Verkamp .write = ahci_idp_write, 406*465f1ab1SDaniel Verkamp .endianness = DEVICE_LITTLE_ENDIAN, 407*465f1ab1SDaniel Verkamp }; 408*465f1ab1SDaniel Verkamp 409*465f1ab1SDaniel Verkamp 410f6ad2e32SAlexander Graf static void ahci_reg_init(AHCIState *s) 411f6ad2e32SAlexander Graf { 412f6ad2e32SAlexander Graf int i; 413f6ad2e32SAlexander Graf 4142c4b9d0eSAlexander Graf s->control_regs.cap = (s->ports - 1) | 415f6ad2e32SAlexander Graf (AHCI_NUM_COMMAND_SLOTS << 8) | 416f6ad2e32SAlexander Graf (AHCI_SUPPORTED_SPEED_GEN1 << AHCI_SUPPORTED_SPEED) | 417f6ad2e32SAlexander Graf HOST_CAP_NCQ | HOST_CAP_AHCI; 418f6ad2e32SAlexander Graf 4192c4b9d0eSAlexander Graf s->control_regs.impl = (1 << s->ports) - 1; 420f6ad2e32SAlexander Graf 421f6ad2e32SAlexander Graf s->control_regs.version = AHCI_VERSION_1_0; 422f6ad2e32SAlexander Graf 4232c4b9d0eSAlexander Graf for (i = 0; i < s->ports; i++) { 424f6ad2e32SAlexander Graf s->dev[i].port_state = STATE_RUN; 425f6ad2e32SAlexander Graf } 426f6ad2e32SAlexander Graf } 427f6ad2e32SAlexander Graf 428f6ad2e32SAlexander Graf static uint32_t read_from_sglist(uint8_t *buffer, uint32_t len, 429f6ad2e32SAlexander Graf QEMUSGList *sglist) 430f6ad2e32SAlexander Graf { 431f6ad2e32SAlexander Graf uint32_t i = 0; 432f6ad2e32SAlexander Graf uint32_t total = 0, once; 433f6ad2e32SAlexander Graf ScatterGatherEntry *cur_prd; 434f6ad2e32SAlexander Graf uint32_t sgcount; 435f6ad2e32SAlexander Graf 436f6ad2e32SAlexander Graf cur_prd = sglist->sg; 437f6ad2e32SAlexander Graf sgcount = sglist->nsg; 438f6ad2e32SAlexander Graf for (i = 0; len && sgcount; i++) { 439f6ad2e32SAlexander Graf once = MIN(cur_prd->len, len); 440f6ad2e32SAlexander Graf cpu_physical_memory_read(cur_prd->base, buffer, once); 441f6ad2e32SAlexander Graf cur_prd++; 442f6ad2e32SAlexander Graf sgcount--; 443f6ad2e32SAlexander Graf len -= once; 444f6ad2e32SAlexander Graf buffer += once; 445f6ad2e32SAlexander Graf total += once; 446f6ad2e32SAlexander Graf } 447f6ad2e32SAlexander Graf 448f6ad2e32SAlexander Graf return total; 449f6ad2e32SAlexander Graf } 450f6ad2e32SAlexander Graf 451f6ad2e32SAlexander Graf static uint32_t write_to_sglist(uint8_t *buffer, uint32_t len, 452f6ad2e32SAlexander Graf QEMUSGList *sglist) 453f6ad2e32SAlexander Graf { 454f6ad2e32SAlexander Graf uint32_t i = 0; 455f6ad2e32SAlexander Graf uint32_t total = 0, once; 456f6ad2e32SAlexander Graf ScatterGatherEntry *cur_prd; 457f6ad2e32SAlexander Graf uint32_t sgcount; 458f6ad2e32SAlexander Graf 459f6ad2e32SAlexander Graf DPRINTF(-1, "total: 0x%x bytes\n", len); 460f6ad2e32SAlexander Graf 461f6ad2e32SAlexander Graf cur_prd = sglist->sg; 462f6ad2e32SAlexander Graf sgcount = sglist->nsg; 463f6ad2e32SAlexander Graf for (i = 0; len && sgcount; i++) { 464f6ad2e32SAlexander Graf once = MIN(cur_prd->len, len); 465f6ad2e32SAlexander Graf DPRINTF(-1, "write 0x%x bytes to 0x%lx\n", once, (long)cur_prd->base); 466f6ad2e32SAlexander Graf cpu_physical_memory_write(cur_prd->base, buffer, once); 467f6ad2e32SAlexander Graf cur_prd++; 468f6ad2e32SAlexander Graf sgcount--; 469f6ad2e32SAlexander Graf len -= once; 470f6ad2e32SAlexander Graf buffer += once; 471f6ad2e32SAlexander Graf total += once; 472f6ad2e32SAlexander Graf } 473f6ad2e32SAlexander Graf 474f6ad2e32SAlexander Graf return total; 475f6ad2e32SAlexander Graf } 476f6ad2e32SAlexander Graf 477f6ad2e32SAlexander Graf static void check_cmd(AHCIState *s, int port) 478f6ad2e32SAlexander Graf { 479f6ad2e32SAlexander Graf AHCIPortRegs *pr = &s->dev[port].port_regs; 480f6ad2e32SAlexander Graf int slot; 481f6ad2e32SAlexander Graf 482f6ad2e32SAlexander Graf if ((pr->cmd & PORT_CMD_START) && pr->cmd_issue) { 483f6ad2e32SAlexander Graf for (slot = 0; (slot < 32) && pr->cmd_issue; slot++) { 484f6ad2e32SAlexander Graf if ((pr->cmd_issue & (1 << slot)) && 485f6ad2e32SAlexander Graf !handle_cmd(s, port, slot)) { 486f6ad2e32SAlexander Graf pr->cmd_issue &= ~(1 << slot); 487f6ad2e32SAlexander Graf } 488f6ad2e32SAlexander Graf } 489f6ad2e32SAlexander Graf } 490f6ad2e32SAlexander Graf } 491f6ad2e32SAlexander Graf 492f6ad2e32SAlexander Graf static void ahci_check_cmd_bh(void *opaque) 493f6ad2e32SAlexander Graf { 494f6ad2e32SAlexander Graf AHCIDevice *ad = opaque; 495f6ad2e32SAlexander Graf 496f6ad2e32SAlexander Graf qemu_bh_delete(ad->check_bh); 497f6ad2e32SAlexander Graf ad->check_bh = NULL; 498f6ad2e32SAlexander Graf 499f6ad2e32SAlexander Graf if ((ad->busy_slot != -1) && 500f6ad2e32SAlexander Graf !(ad->port.ifs[0].status & (BUSY_STAT|DRQ_STAT))) { 501f6ad2e32SAlexander Graf /* no longer busy */ 502f6ad2e32SAlexander Graf ad->port_regs.cmd_issue &= ~(1 << ad->busy_slot); 503f6ad2e32SAlexander Graf ad->busy_slot = -1; 504f6ad2e32SAlexander Graf } 505f6ad2e32SAlexander Graf 506f6ad2e32SAlexander Graf check_cmd(ad->hba, ad->port_no); 507f6ad2e32SAlexander Graf } 508f6ad2e32SAlexander Graf 50987e62065SAlexander Graf static void ahci_init_d2h(AHCIDevice *ad) 51087e62065SAlexander Graf { 51187e62065SAlexander Graf uint8_t init_fis[0x20]; 51287e62065SAlexander Graf IDEState *ide_state = &ad->port.ifs[0]; 51387e62065SAlexander Graf 51487e62065SAlexander Graf memset(init_fis, 0, sizeof(init_fis)); 51587e62065SAlexander Graf 51687e62065SAlexander Graf init_fis[4] = 1; 51787e62065SAlexander Graf init_fis[12] = 1; 51887e62065SAlexander Graf 51987e62065SAlexander Graf if (ide_state->drive_kind == IDE_CD) { 52087e62065SAlexander Graf init_fis[5] = ide_state->lcyl; 52187e62065SAlexander Graf init_fis[6] = ide_state->hcyl; 52287e62065SAlexander Graf } 52387e62065SAlexander Graf 52487e62065SAlexander Graf ahci_write_fis_d2h(ad, init_fis); 52587e62065SAlexander Graf } 52687e62065SAlexander Graf 527f6ad2e32SAlexander Graf static void ahci_reset_port(AHCIState *s, int port) 528f6ad2e32SAlexander Graf { 529f6ad2e32SAlexander Graf AHCIDevice *d = &s->dev[port]; 530f6ad2e32SAlexander Graf AHCIPortRegs *pr = &d->port_regs; 531f6ad2e32SAlexander Graf IDEState *ide_state = &d->port.ifs[0]; 532f6ad2e32SAlexander Graf int i; 533f6ad2e32SAlexander Graf 534f6ad2e32SAlexander Graf DPRINTF(port, "reset port\n"); 535f6ad2e32SAlexander Graf 536f6ad2e32SAlexander Graf ide_bus_reset(&d->port); 537f6ad2e32SAlexander Graf ide_state->ncq_queues = AHCI_MAX_CMDS; 538f6ad2e32SAlexander Graf 539f6ad2e32SAlexander Graf pr->scr_stat = 0; 540f6ad2e32SAlexander Graf pr->scr_err = 0; 541f6ad2e32SAlexander Graf pr->scr_act = 0; 542f6ad2e32SAlexander Graf d->busy_slot = -1; 54387e62065SAlexander Graf d->init_d2h_sent = 0; 544f6ad2e32SAlexander Graf 545f6ad2e32SAlexander Graf ide_state = &s->dev[port].port.ifs[0]; 546f6ad2e32SAlexander Graf if (!ide_state->bs) { 547f6ad2e32SAlexander Graf return; 548f6ad2e32SAlexander Graf } 549f6ad2e32SAlexander Graf 550f6ad2e32SAlexander Graf /* reset ncq queue */ 551f6ad2e32SAlexander Graf for (i = 0; i < AHCI_MAX_CMDS; i++) { 552f6ad2e32SAlexander Graf NCQTransferState *ncq_tfs = &s->dev[port].ncq_tfs[i]; 553f6ad2e32SAlexander Graf if (!ncq_tfs->used) { 554f6ad2e32SAlexander Graf continue; 555f6ad2e32SAlexander Graf } 556f6ad2e32SAlexander Graf 557f6ad2e32SAlexander Graf if (ncq_tfs->aiocb) { 558f6ad2e32SAlexander Graf bdrv_aio_cancel(ncq_tfs->aiocb); 559f6ad2e32SAlexander Graf ncq_tfs->aiocb = NULL; 560f6ad2e32SAlexander Graf } 561f6ad2e32SAlexander Graf 562f6ad2e32SAlexander Graf qemu_sglist_destroy(&ncq_tfs->sglist); 563f6ad2e32SAlexander Graf ncq_tfs->used = 0; 564f6ad2e32SAlexander Graf } 565f6ad2e32SAlexander Graf 566f6ad2e32SAlexander Graf s->dev[port].port_state = STATE_RUN; 567f6ad2e32SAlexander Graf if (!ide_state->bs) { 568f6ad2e32SAlexander Graf s->dev[port].port_regs.sig = 0; 569cdfe17dfSBlue Swirl ide_state->status = SEEK_STAT | WRERR_STAT; 570f6ad2e32SAlexander Graf } else if (ide_state->drive_kind == IDE_CD) { 571f6ad2e32SAlexander Graf s->dev[port].port_regs.sig = SATA_SIGNATURE_CDROM; 572f6ad2e32SAlexander Graf ide_state->lcyl = 0x14; 573f6ad2e32SAlexander Graf ide_state->hcyl = 0xeb; 574f6ad2e32SAlexander Graf DPRINTF(port, "set lcyl = %d\n", ide_state->lcyl); 575f6ad2e32SAlexander Graf ide_state->status = SEEK_STAT | WRERR_STAT | READY_STAT; 576f6ad2e32SAlexander Graf } else { 577f6ad2e32SAlexander Graf s->dev[port].port_regs.sig = SATA_SIGNATURE_DISK; 578f6ad2e32SAlexander Graf ide_state->status = SEEK_STAT | WRERR_STAT; 579f6ad2e32SAlexander Graf } 580f6ad2e32SAlexander Graf 581f6ad2e32SAlexander Graf ide_state->error = 1; 58287e62065SAlexander Graf ahci_init_d2h(d); 583f6ad2e32SAlexander Graf } 584f6ad2e32SAlexander Graf 585f6ad2e32SAlexander Graf static void debug_print_fis(uint8_t *fis, int cmd_len) 586f6ad2e32SAlexander Graf { 587f6ad2e32SAlexander Graf #ifdef DEBUG_AHCI 588f6ad2e32SAlexander Graf int i; 589f6ad2e32SAlexander Graf 590f6ad2e32SAlexander Graf fprintf(stderr, "fis:"); 591f6ad2e32SAlexander Graf for (i = 0; i < cmd_len; i++) { 592f6ad2e32SAlexander Graf if ((i & 0xf) == 0) { 593f6ad2e32SAlexander Graf fprintf(stderr, "\n%02x:",i); 594f6ad2e32SAlexander Graf } 595f6ad2e32SAlexander Graf fprintf(stderr, "%02x ",fis[i]); 596f6ad2e32SAlexander Graf } 597f6ad2e32SAlexander Graf fprintf(stderr, "\n"); 598f6ad2e32SAlexander Graf #endif 599f6ad2e32SAlexander Graf } 600f6ad2e32SAlexander Graf 601f6ad2e32SAlexander Graf static void ahci_write_fis_sdb(AHCIState *s, int port, uint32_t finished) 602f6ad2e32SAlexander Graf { 603f6ad2e32SAlexander Graf AHCIPortRegs *pr = &s->dev[port].port_regs; 604f6ad2e32SAlexander Graf IDEState *ide_state; 605f6ad2e32SAlexander Graf uint8_t *sdb_fis; 606f6ad2e32SAlexander Graf 607f6ad2e32SAlexander Graf if (!s->dev[port].res_fis || 608f6ad2e32SAlexander Graf !(pr->cmd & PORT_CMD_FIS_RX)) { 609f6ad2e32SAlexander Graf return; 610f6ad2e32SAlexander Graf } 611f6ad2e32SAlexander Graf 612f6ad2e32SAlexander Graf sdb_fis = &s->dev[port].res_fis[RES_FIS_SDBFIS]; 613f6ad2e32SAlexander Graf ide_state = &s->dev[port].port.ifs[0]; 614f6ad2e32SAlexander Graf 615f6ad2e32SAlexander Graf /* clear memory */ 616f6ad2e32SAlexander Graf *(uint32_t*)sdb_fis = 0; 617f6ad2e32SAlexander Graf 618f6ad2e32SAlexander Graf /* write values */ 619f6ad2e32SAlexander Graf sdb_fis[0] = ide_state->error; 620f6ad2e32SAlexander Graf sdb_fis[2] = ide_state->status & 0x77; 621f6ad2e32SAlexander Graf s->dev[port].finished |= finished; 622f6ad2e32SAlexander Graf *(uint32_t*)(sdb_fis + 4) = cpu_to_le32(s->dev[port].finished); 623f6ad2e32SAlexander Graf 624f6ad2e32SAlexander Graf ahci_trigger_irq(s, &s->dev[port], PORT_IRQ_STAT_SDBS); 625f6ad2e32SAlexander Graf } 626f6ad2e32SAlexander Graf 627f6ad2e32SAlexander Graf static void ahci_write_fis_d2h(AHCIDevice *ad, uint8_t *cmd_fis) 628f6ad2e32SAlexander Graf { 629f6ad2e32SAlexander Graf AHCIPortRegs *pr = &ad->port_regs; 630f6ad2e32SAlexander Graf uint8_t *d2h_fis; 631f6ad2e32SAlexander Graf int i; 632f6ad2e32SAlexander Graf target_phys_addr_t cmd_len = 0x80; 633f6ad2e32SAlexander Graf int cmd_mapped = 0; 634f6ad2e32SAlexander Graf 635f6ad2e32SAlexander Graf if (!ad->res_fis || !(pr->cmd & PORT_CMD_FIS_RX)) { 636f6ad2e32SAlexander Graf return; 637f6ad2e32SAlexander Graf } 638f6ad2e32SAlexander Graf 639f6ad2e32SAlexander Graf if (!cmd_fis) { 640f6ad2e32SAlexander Graf /* map cmd_fis */ 641f6ad2e32SAlexander Graf uint64_t tbl_addr = le64_to_cpu(ad->cur_cmd->tbl_addr); 642f6ad2e32SAlexander Graf cmd_fis = cpu_physical_memory_map(tbl_addr, &cmd_len, 0); 643f6ad2e32SAlexander Graf cmd_mapped = 1; 644f6ad2e32SAlexander Graf } 645f6ad2e32SAlexander Graf 646f6ad2e32SAlexander Graf d2h_fis = &ad->res_fis[RES_FIS_RFIS]; 647f6ad2e32SAlexander Graf 648f6ad2e32SAlexander Graf d2h_fis[0] = 0x34; 649f6ad2e32SAlexander Graf d2h_fis[1] = (ad->hba->control_regs.irqstatus ? (1 << 6) : 0); 650f6ad2e32SAlexander Graf d2h_fis[2] = ad->port.ifs[0].status; 651f6ad2e32SAlexander Graf d2h_fis[3] = ad->port.ifs[0].error; 652f6ad2e32SAlexander Graf 653f6ad2e32SAlexander Graf d2h_fis[4] = cmd_fis[4]; 654f6ad2e32SAlexander Graf d2h_fis[5] = cmd_fis[5]; 655f6ad2e32SAlexander Graf d2h_fis[6] = cmd_fis[6]; 656f6ad2e32SAlexander Graf d2h_fis[7] = cmd_fis[7]; 657f6ad2e32SAlexander Graf d2h_fis[8] = cmd_fis[8]; 658f6ad2e32SAlexander Graf d2h_fis[9] = cmd_fis[9]; 659f6ad2e32SAlexander Graf d2h_fis[10] = cmd_fis[10]; 660f6ad2e32SAlexander Graf d2h_fis[11] = cmd_fis[11]; 661f6ad2e32SAlexander Graf d2h_fis[12] = cmd_fis[12]; 662f6ad2e32SAlexander Graf d2h_fis[13] = cmd_fis[13]; 663f6ad2e32SAlexander Graf for (i = 14; i < 0x20; i++) { 664f6ad2e32SAlexander Graf d2h_fis[i] = 0; 665f6ad2e32SAlexander Graf } 666f6ad2e32SAlexander Graf 667f6ad2e32SAlexander Graf if (d2h_fis[2] & ERR_STAT) { 668f6ad2e32SAlexander Graf ahci_trigger_irq(ad->hba, ad, PORT_IRQ_STAT_TFES); 669f6ad2e32SAlexander Graf } 670f6ad2e32SAlexander Graf 671f6ad2e32SAlexander Graf ahci_trigger_irq(ad->hba, ad, PORT_IRQ_D2H_REG_FIS); 672f6ad2e32SAlexander Graf 673f6ad2e32SAlexander Graf if (cmd_mapped) { 674fe6ceac8SStefan Hajnoczi cpu_physical_memory_unmap(cmd_fis, cmd_len, 0, cmd_len); 675f6ad2e32SAlexander Graf } 676f6ad2e32SAlexander Graf } 677f6ad2e32SAlexander Graf 678f6ad2e32SAlexander Graf static int ahci_populate_sglist(AHCIDevice *ad, QEMUSGList *sglist) 679f6ad2e32SAlexander Graf { 680f6ad2e32SAlexander Graf AHCICmdHdr *cmd = ad->cur_cmd; 681f6ad2e32SAlexander Graf uint32_t opts = le32_to_cpu(cmd->opts); 682f6ad2e32SAlexander Graf uint64_t prdt_addr = le64_to_cpu(cmd->tbl_addr) + 0x80; 683f6ad2e32SAlexander Graf int sglist_alloc_hint = opts >> AHCI_CMD_HDR_PRDT_LEN; 684f6ad2e32SAlexander Graf target_phys_addr_t prdt_len = (sglist_alloc_hint * sizeof(AHCI_SG)); 685f6ad2e32SAlexander Graf target_phys_addr_t real_prdt_len = prdt_len; 686f6ad2e32SAlexander Graf uint8_t *prdt; 687f6ad2e32SAlexander Graf int i; 688f6ad2e32SAlexander Graf int r = 0; 689f6ad2e32SAlexander Graf 690f6ad2e32SAlexander Graf if (!sglist_alloc_hint) { 691f6ad2e32SAlexander Graf DPRINTF(ad->port_no, "no sg list given by guest: 0x%08x\n", opts); 692f6ad2e32SAlexander Graf return -1; 693f6ad2e32SAlexander Graf } 694f6ad2e32SAlexander Graf 695f6ad2e32SAlexander Graf /* map PRDT */ 696f6ad2e32SAlexander Graf if (!(prdt = cpu_physical_memory_map(prdt_addr, &prdt_len, 0))){ 697f6ad2e32SAlexander Graf DPRINTF(ad->port_no, "map failed\n"); 698f6ad2e32SAlexander Graf return -1; 699f6ad2e32SAlexander Graf } 700f6ad2e32SAlexander Graf 701f6ad2e32SAlexander Graf if (prdt_len < real_prdt_len) { 702f6ad2e32SAlexander Graf DPRINTF(ad->port_no, "mapped less than expected\n"); 703f6ad2e32SAlexander Graf r = -1; 704f6ad2e32SAlexander Graf goto out; 705f6ad2e32SAlexander Graf } 706f6ad2e32SAlexander Graf 707f6ad2e32SAlexander Graf /* Get entries in the PRDT, init a qemu sglist accordingly */ 708f6ad2e32SAlexander Graf if (sglist_alloc_hint > 0) { 709f6ad2e32SAlexander Graf AHCI_SG *tbl = (AHCI_SG *)prdt; 710f6ad2e32SAlexander Graf 711f6ad2e32SAlexander Graf qemu_sglist_init(sglist, sglist_alloc_hint); 712f6ad2e32SAlexander Graf for (i = 0; i < sglist_alloc_hint; i++) { 713f6ad2e32SAlexander Graf /* flags_size is zero-based */ 714f6ad2e32SAlexander Graf qemu_sglist_add(sglist, le64_to_cpu(tbl[i].addr), 715f6ad2e32SAlexander Graf le32_to_cpu(tbl[i].flags_size) + 1); 716f6ad2e32SAlexander Graf } 717f6ad2e32SAlexander Graf } 718f6ad2e32SAlexander Graf 719f6ad2e32SAlexander Graf out: 720fe6ceac8SStefan Hajnoczi cpu_physical_memory_unmap(prdt, prdt_len, 0, prdt_len); 721f6ad2e32SAlexander Graf return r; 722f6ad2e32SAlexander Graf } 723f6ad2e32SAlexander Graf 724f6ad2e32SAlexander Graf static void ncq_cb(void *opaque, int ret) 725f6ad2e32SAlexander Graf { 726f6ad2e32SAlexander Graf NCQTransferState *ncq_tfs = (NCQTransferState *)opaque; 727f6ad2e32SAlexander Graf IDEState *ide_state = &ncq_tfs->drive->port.ifs[0]; 728f6ad2e32SAlexander Graf 729f6ad2e32SAlexander Graf /* Clear bit for this tag in SActive */ 730f6ad2e32SAlexander Graf ncq_tfs->drive->port_regs.scr_act &= ~(1 << ncq_tfs->tag); 731f6ad2e32SAlexander Graf 732f6ad2e32SAlexander Graf if (ret < 0) { 733f6ad2e32SAlexander Graf /* error */ 734f6ad2e32SAlexander Graf ide_state->error = ABRT_ERR; 735f6ad2e32SAlexander Graf ide_state->status = READY_STAT | ERR_STAT; 736f6ad2e32SAlexander Graf ncq_tfs->drive->port_regs.scr_err |= (1 << ncq_tfs->tag); 737f6ad2e32SAlexander Graf } else { 738f6ad2e32SAlexander Graf ide_state->status = READY_STAT | SEEK_STAT; 739f6ad2e32SAlexander Graf } 740f6ad2e32SAlexander Graf 741f6ad2e32SAlexander Graf ahci_write_fis_sdb(ncq_tfs->drive->hba, ncq_tfs->drive->port_no, 742f6ad2e32SAlexander Graf (1 << ncq_tfs->tag)); 743f6ad2e32SAlexander Graf 744f6ad2e32SAlexander Graf DPRINTF(ncq_tfs->drive->port_no, "NCQ transfer tag %d finished\n", 745f6ad2e32SAlexander Graf ncq_tfs->tag); 746f6ad2e32SAlexander Graf 747a597e79cSChristoph Hellwig bdrv_acct_done(ncq_tfs->drive->port.ifs[0].bs, &ncq_tfs->acct); 748f6ad2e32SAlexander Graf qemu_sglist_destroy(&ncq_tfs->sglist); 749f6ad2e32SAlexander Graf ncq_tfs->used = 0; 750f6ad2e32SAlexander Graf } 751f6ad2e32SAlexander Graf 752f6ad2e32SAlexander Graf static void process_ncq_command(AHCIState *s, int port, uint8_t *cmd_fis, 753f6ad2e32SAlexander Graf int slot) 754f6ad2e32SAlexander Graf { 755f6ad2e32SAlexander Graf NCQFrame *ncq_fis = (NCQFrame*)cmd_fis; 756f6ad2e32SAlexander Graf uint8_t tag = ncq_fis->tag >> 3; 757f6ad2e32SAlexander Graf NCQTransferState *ncq_tfs = &s->dev[port].ncq_tfs[tag]; 758f6ad2e32SAlexander Graf 759f6ad2e32SAlexander Graf if (ncq_tfs->used) { 760f6ad2e32SAlexander Graf /* error - already in use */ 761f6ad2e32SAlexander Graf fprintf(stderr, "%s: tag %d already used\n", __FUNCTION__, tag); 762f6ad2e32SAlexander Graf return; 763f6ad2e32SAlexander Graf } 764f6ad2e32SAlexander Graf 765f6ad2e32SAlexander Graf ncq_tfs->used = 1; 766f6ad2e32SAlexander Graf ncq_tfs->drive = &s->dev[port]; 767f6ad2e32SAlexander Graf ncq_tfs->slot = slot; 768f6ad2e32SAlexander Graf ncq_tfs->lba = ((uint64_t)ncq_fis->lba5 << 40) | 769f6ad2e32SAlexander Graf ((uint64_t)ncq_fis->lba4 << 32) | 770f6ad2e32SAlexander Graf ((uint64_t)ncq_fis->lba3 << 24) | 771f6ad2e32SAlexander Graf ((uint64_t)ncq_fis->lba2 << 16) | 772f6ad2e32SAlexander Graf ((uint64_t)ncq_fis->lba1 << 8) | 773f6ad2e32SAlexander Graf (uint64_t)ncq_fis->lba0; 774f6ad2e32SAlexander Graf 775f6ad2e32SAlexander Graf /* Note: We calculate the sector count, but don't currently rely on it. 776f6ad2e32SAlexander Graf * The total size of the DMA buffer tells us the transfer size instead. */ 777f6ad2e32SAlexander Graf ncq_tfs->sector_count = ((uint16_t)ncq_fis->sector_count_high << 8) | 778f6ad2e32SAlexander Graf ncq_fis->sector_count_low; 779f6ad2e32SAlexander Graf 780f6ad2e32SAlexander Graf DPRINTF(port, "NCQ transfer LBA from %ld to %ld, drive max %ld\n", 781f6ad2e32SAlexander Graf ncq_tfs->lba, ncq_tfs->lba + ncq_tfs->sector_count - 2, 782f6ad2e32SAlexander Graf s->dev[port].port.ifs[0].nb_sectors - 1); 783f6ad2e32SAlexander Graf 784f6ad2e32SAlexander Graf ahci_populate_sglist(&s->dev[port], &ncq_tfs->sglist); 785f6ad2e32SAlexander Graf ncq_tfs->tag = tag; 786f6ad2e32SAlexander Graf 787f6ad2e32SAlexander Graf switch(ncq_fis->command) { 788f6ad2e32SAlexander Graf case READ_FPDMA_QUEUED: 789f6ad2e32SAlexander Graf DPRINTF(port, "NCQ reading %d sectors from LBA %ld, tag %d\n", 790f6ad2e32SAlexander Graf ncq_tfs->sector_count-1, ncq_tfs->lba, ncq_tfs->tag); 791f6ad2e32SAlexander Graf 792f6ad2e32SAlexander Graf DPRINTF(port, "tag %d aio read %ld\n", ncq_tfs->tag, ncq_tfs->lba); 793a597e79cSChristoph Hellwig 794a597e79cSChristoph Hellwig bdrv_acct_start(ncq_tfs->drive->port.ifs[0].bs, &ncq_tfs->acct, 795a597e79cSChristoph Hellwig (ncq_tfs->sector_count-1) * BDRV_SECTOR_SIZE, 796a597e79cSChristoph Hellwig BDRV_ACCT_READ); 797f6ad2e32SAlexander Graf ncq_tfs->aiocb = dma_bdrv_read(ncq_tfs->drive->port.ifs[0].bs, 798f6ad2e32SAlexander Graf &ncq_tfs->sglist, ncq_tfs->lba, 799f6ad2e32SAlexander Graf ncq_cb, ncq_tfs); 800f6ad2e32SAlexander Graf break; 801f6ad2e32SAlexander Graf case WRITE_FPDMA_QUEUED: 802f6ad2e32SAlexander Graf DPRINTF(port, "NCQ writing %d sectors to LBA %ld, tag %d\n", 803f6ad2e32SAlexander Graf ncq_tfs->sector_count-1, ncq_tfs->lba, ncq_tfs->tag); 804f6ad2e32SAlexander Graf 805f6ad2e32SAlexander Graf DPRINTF(port, "tag %d aio write %ld\n", ncq_tfs->tag, ncq_tfs->lba); 806a597e79cSChristoph Hellwig 807a597e79cSChristoph Hellwig bdrv_acct_start(ncq_tfs->drive->port.ifs[0].bs, &ncq_tfs->acct, 808a597e79cSChristoph Hellwig (ncq_tfs->sector_count-1) * BDRV_SECTOR_SIZE, 809a597e79cSChristoph Hellwig BDRV_ACCT_WRITE); 810f6ad2e32SAlexander Graf ncq_tfs->aiocb = dma_bdrv_write(ncq_tfs->drive->port.ifs[0].bs, 811f6ad2e32SAlexander Graf &ncq_tfs->sglist, ncq_tfs->lba, 812f6ad2e32SAlexander Graf ncq_cb, ncq_tfs); 813f6ad2e32SAlexander Graf break; 814f6ad2e32SAlexander Graf default: 815f6ad2e32SAlexander Graf DPRINTF(port, "error: tried to process non-NCQ command as NCQ\n"); 816f6ad2e32SAlexander Graf qemu_sglist_destroy(&ncq_tfs->sglist); 817f6ad2e32SAlexander Graf break; 818f6ad2e32SAlexander Graf } 819f6ad2e32SAlexander Graf } 820f6ad2e32SAlexander Graf 821f6ad2e32SAlexander Graf static int handle_cmd(AHCIState *s, int port, int slot) 822f6ad2e32SAlexander Graf { 823f6ad2e32SAlexander Graf IDEState *ide_state; 824f6ad2e32SAlexander Graf uint32_t opts; 825f6ad2e32SAlexander Graf uint64_t tbl_addr; 826f6ad2e32SAlexander Graf AHCICmdHdr *cmd; 827f6ad2e32SAlexander Graf uint8_t *cmd_fis; 828f6ad2e32SAlexander Graf target_phys_addr_t cmd_len; 829f6ad2e32SAlexander Graf 830f6ad2e32SAlexander Graf if (s->dev[port].port.ifs[0].status & (BUSY_STAT|DRQ_STAT)) { 831f6ad2e32SAlexander Graf /* Engine currently busy, try again later */ 832f6ad2e32SAlexander Graf DPRINTF(port, "engine busy\n"); 833f6ad2e32SAlexander Graf return -1; 834f6ad2e32SAlexander Graf } 835f6ad2e32SAlexander Graf 836f6ad2e32SAlexander Graf cmd = &((AHCICmdHdr *)s->dev[port].lst)[slot]; 837f6ad2e32SAlexander Graf 838f6ad2e32SAlexander Graf if (!s->dev[port].lst) { 839f6ad2e32SAlexander Graf DPRINTF(port, "error: lst not given but cmd handled"); 840f6ad2e32SAlexander Graf return -1; 841f6ad2e32SAlexander Graf } 842f6ad2e32SAlexander Graf 843f6ad2e32SAlexander Graf /* remember current slot handle for later */ 844f6ad2e32SAlexander Graf s->dev[port].cur_cmd = cmd; 845f6ad2e32SAlexander Graf 846f6ad2e32SAlexander Graf opts = le32_to_cpu(cmd->opts); 847f6ad2e32SAlexander Graf tbl_addr = le64_to_cpu(cmd->tbl_addr); 848f6ad2e32SAlexander Graf 849f6ad2e32SAlexander Graf cmd_len = 0x80; 850f6ad2e32SAlexander Graf cmd_fis = cpu_physical_memory_map(tbl_addr, &cmd_len, 1); 851f6ad2e32SAlexander Graf 852f6ad2e32SAlexander Graf if (!cmd_fis) { 853f6ad2e32SAlexander Graf DPRINTF(port, "error: guest passed us an invalid cmd fis\n"); 854f6ad2e32SAlexander Graf return -1; 855f6ad2e32SAlexander Graf } 856f6ad2e32SAlexander Graf 857f6ad2e32SAlexander Graf /* The device we are working for */ 858f6ad2e32SAlexander Graf ide_state = &s->dev[port].port.ifs[0]; 859f6ad2e32SAlexander Graf 860f6ad2e32SAlexander Graf if (!ide_state->bs) { 861f6ad2e32SAlexander Graf DPRINTF(port, "error: guest accessed unused port"); 862f6ad2e32SAlexander Graf goto out; 863f6ad2e32SAlexander Graf } 864f6ad2e32SAlexander Graf 865f6ad2e32SAlexander Graf debug_print_fis(cmd_fis, 0x90); 866f6ad2e32SAlexander Graf //debug_print_fis(cmd_fis, (opts & AHCI_CMD_HDR_CMD_FIS_LEN) * 4); 867f6ad2e32SAlexander Graf 868f6ad2e32SAlexander Graf switch (cmd_fis[0]) { 869f6ad2e32SAlexander Graf case SATA_FIS_TYPE_REGISTER_H2D: 870f6ad2e32SAlexander Graf break; 871f6ad2e32SAlexander Graf default: 872f6ad2e32SAlexander Graf DPRINTF(port, "unknown command cmd_fis[0]=%02x cmd_fis[1]=%02x " 873f6ad2e32SAlexander Graf "cmd_fis[2]=%02x\n", cmd_fis[0], cmd_fis[1], 874f6ad2e32SAlexander Graf cmd_fis[2]); 875f6ad2e32SAlexander Graf goto out; 876f6ad2e32SAlexander Graf break; 877f6ad2e32SAlexander Graf } 878f6ad2e32SAlexander Graf 879f6ad2e32SAlexander Graf switch (cmd_fis[1]) { 880f6ad2e32SAlexander Graf case SATA_FIS_REG_H2D_UPDATE_COMMAND_REGISTER: 881f6ad2e32SAlexander Graf break; 882f6ad2e32SAlexander Graf case 0: 883f6ad2e32SAlexander Graf break; 884f6ad2e32SAlexander Graf default: 885f6ad2e32SAlexander Graf DPRINTF(port, "unknown command cmd_fis[0]=%02x cmd_fis[1]=%02x " 886f6ad2e32SAlexander Graf "cmd_fis[2]=%02x\n", cmd_fis[0], cmd_fis[1], 887f6ad2e32SAlexander Graf cmd_fis[2]); 888f6ad2e32SAlexander Graf goto out; 889f6ad2e32SAlexander Graf break; 890f6ad2e32SAlexander Graf } 891f6ad2e32SAlexander Graf 892f6ad2e32SAlexander Graf switch (s->dev[port].port_state) { 893f6ad2e32SAlexander Graf case STATE_RUN: 894f6ad2e32SAlexander Graf if (cmd_fis[15] & ATA_SRST) { 895f6ad2e32SAlexander Graf s->dev[port].port_state = STATE_RESET; 896f6ad2e32SAlexander Graf } 897f6ad2e32SAlexander Graf break; 898f6ad2e32SAlexander Graf case STATE_RESET: 899f6ad2e32SAlexander Graf if (!(cmd_fis[15] & ATA_SRST)) { 900f6ad2e32SAlexander Graf ahci_reset_port(s, port); 901f6ad2e32SAlexander Graf } 902f6ad2e32SAlexander Graf break; 903f6ad2e32SAlexander Graf } 904f6ad2e32SAlexander Graf 905f6ad2e32SAlexander Graf if (cmd_fis[1] == SATA_FIS_REG_H2D_UPDATE_COMMAND_REGISTER) { 906f6ad2e32SAlexander Graf 907f6ad2e32SAlexander Graf /* Check for NCQ command */ 908f6ad2e32SAlexander Graf if ((cmd_fis[2] == READ_FPDMA_QUEUED) || 909f6ad2e32SAlexander Graf (cmd_fis[2] == WRITE_FPDMA_QUEUED)) { 910f6ad2e32SAlexander Graf process_ncq_command(s, port, cmd_fis, slot); 911f6ad2e32SAlexander Graf goto out; 912f6ad2e32SAlexander Graf } 913f6ad2e32SAlexander Graf 914f6ad2e32SAlexander Graf /* Decompose the FIS */ 915f6ad2e32SAlexander Graf ide_state->nsector = (int64_t)((cmd_fis[13] << 8) | cmd_fis[12]); 916f6ad2e32SAlexander Graf ide_state->feature = cmd_fis[3]; 917f6ad2e32SAlexander Graf if (!ide_state->nsector) { 918f6ad2e32SAlexander Graf ide_state->nsector = 256; 919f6ad2e32SAlexander Graf } 920f6ad2e32SAlexander Graf 921f6ad2e32SAlexander Graf if (ide_state->drive_kind != IDE_CD) { 9221fddfba1SAlexander Graf /* 9231fddfba1SAlexander Graf * We set the sector depending on the sector defined in the FIS. 9241fddfba1SAlexander Graf * Unfortunately, the spec isn't exactly obvious on this one. 9251fddfba1SAlexander Graf * 9261fddfba1SAlexander Graf * Apparently LBA48 commands set fis bytes 10,9,8,6,5,4 to the 9271fddfba1SAlexander Graf * 48 bit sector number. ATA_CMD_READ_DMA_EXT is an example for 9281fddfba1SAlexander Graf * such a command. 9291fddfba1SAlexander Graf * 9301fddfba1SAlexander Graf * Non-LBA48 commands however use 7[lower 4 bits],6,5,4 to define a 9311fddfba1SAlexander Graf * 28-bit sector number. ATA_CMD_READ_DMA is an example for such 9321fddfba1SAlexander Graf * a command. 9331fddfba1SAlexander Graf * 9341fddfba1SAlexander Graf * Since the spec doesn't explicitly state what each field should 9351fddfba1SAlexander Graf * do, I simply assume non-used fields as reserved and OR everything 9361fddfba1SAlexander Graf * together, independent of the command. 9371fddfba1SAlexander Graf */ 9381fddfba1SAlexander Graf ide_set_sector(ide_state, ((uint64_t)cmd_fis[10] << 40) 9391fddfba1SAlexander Graf | ((uint64_t)cmd_fis[9] << 32) 9401fddfba1SAlexander Graf /* This is used for LBA48 commands */ 9411fddfba1SAlexander Graf | ((uint64_t)cmd_fis[8] << 24) 9421fddfba1SAlexander Graf /* This is used for non-LBA48 commands */ 9431fddfba1SAlexander Graf | ((uint64_t)(cmd_fis[7] & 0xf) << 24) 9441fddfba1SAlexander Graf | ((uint64_t)cmd_fis[6] << 16) 9451fddfba1SAlexander Graf | ((uint64_t)cmd_fis[5] << 8) 9461fddfba1SAlexander Graf | cmd_fis[4]); 947f6ad2e32SAlexander Graf } 948f6ad2e32SAlexander Graf 949f6ad2e32SAlexander Graf /* Copy the ACMD field (ATAPI packet, if any) from the AHCI command 950f6ad2e32SAlexander Graf * table to ide_state->io_buffer 951f6ad2e32SAlexander Graf */ 952f6ad2e32SAlexander Graf if (opts & AHCI_CMD_ATAPI) { 953f6ad2e32SAlexander Graf memcpy(ide_state->io_buffer, &cmd_fis[AHCI_COMMAND_TABLE_ACMD], 0x10); 954f6ad2e32SAlexander Graf ide_state->lcyl = 0x14; 955f6ad2e32SAlexander Graf ide_state->hcyl = 0xeb; 956f6ad2e32SAlexander Graf debug_print_fis(ide_state->io_buffer, 0x10); 957f6ad2e32SAlexander Graf ide_state->feature = IDE_FEATURE_DMA; 958f6ad2e32SAlexander Graf s->dev[port].done_atapi_packet = 0; 959f6ad2e32SAlexander Graf /* XXX send PIO setup FIS */ 960f6ad2e32SAlexander Graf } 961f6ad2e32SAlexander Graf 962f6ad2e32SAlexander Graf ide_state->error = 0; 963f6ad2e32SAlexander Graf 964f6ad2e32SAlexander Graf /* Reset transferred byte counter */ 965f6ad2e32SAlexander Graf cmd->status = 0; 966f6ad2e32SAlexander Graf 967f6ad2e32SAlexander Graf /* We're ready to process the command in FIS byte 2. */ 968f6ad2e32SAlexander Graf ide_exec_cmd(&s->dev[port].port, cmd_fis[2]); 969f6ad2e32SAlexander Graf 970f6ad2e32SAlexander Graf if (s->dev[port].port.ifs[0].status & READY_STAT) { 971f6ad2e32SAlexander Graf ahci_write_fis_d2h(&s->dev[port], cmd_fis); 972f6ad2e32SAlexander Graf } 973f6ad2e32SAlexander Graf } 974f6ad2e32SAlexander Graf 975f6ad2e32SAlexander Graf out: 976fe6ceac8SStefan Hajnoczi cpu_physical_memory_unmap(cmd_fis, cmd_len, 1, cmd_len); 977f6ad2e32SAlexander Graf 978f6ad2e32SAlexander Graf if (s->dev[port].port.ifs[0].status & (BUSY_STAT|DRQ_STAT)) { 979f6ad2e32SAlexander Graf /* async command, complete later */ 980f6ad2e32SAlexander Graf s->dev[port].busy_slot = slot; 981f6ad2e32SAlexander Graf return -1; 982f6ad2e32SAlexander Graf } 983f6ad2e32SAlexander Graf 984f6ad2e32SAlexander Graf /* done handling the command */ 985f6ad2e32SAlexander Graf return 0; 986f6ad2e32SAlexander Graf } 987f6ad2e32SAlexander Graf 988f6ad2e32SAlexander Graf /* DMA dev <-> ram */ 989f6ad2e32SAlexander Graf static int ahci_start_transfer(IDEDMA *dma) 990f6ad2e32SAlexander Graf { 991f6ad2e32SAlexander Graf AHCIDevice *ad = DO_UPCAST(AHCIDevice, dma, dma); 992f6ad2e32SAlexander Graf IDEState *s = &ad->port.ifs[0]; 993f6ad2e32SAlexander Graf uint32_t size = (uint32_t)(s->data_end - s->data_ptr); 994f6ad2e32SAlexander Graf /* write == ram -> device */ 995f6ad2e32SAlexander Graf uint32_t opts = le32_to_cpu(ad->cur_cmd->opts); 996f6ad2e32SAlexander Graf int is_write = opts & AHCI_CMD_WRITE; 997f6ad2e32SAlexander Graf int is_atapi = opts & AHCI_CMD_ATAPI; 998f6ad2e32SAlexander Graf int has_sglist = 0; 999f6ad2e32SAlexander Graf 1000f6ad2e32SAlexander Graf if (is_atapi && !ad->done_atapi_packet) { 1001f6ad2e32SAlexander Graf /* already prepopulated iobuffer */ 1002f6ad2e32SAlexander Graf ad->done_atapi_packet = 1; 1003f6ad2e32SAlexander Graf goto out; 1004f6ad2e32SAlexander Graf } 1005f6ad2e32SAlexander Graf 1006f6ad2e32SAlexander Graf if (!ahci_populate_sglist(ad, &s->sg)) { 1007f6ad2e32SAlexander Graf has_sglist = 1; 1008f6ad2e32SAlexander Graf } 1009f6ad2e32SAlexander Graf 1010f6ad2e32SAlexander Graf DPRINTF(ad->port_no, "%sing %d bytes on %s w/%s sglist\n", 1011f6ad2e32SAlexander Graf is_write ? "writ" : "read", size, is_atapi ? "atapi" : "ata", 1012f6ad2e32SAlexander Graf has_sglist ? "" : "o"); 1013f6ad2e32SAlexander Graf 1014f6ad2e32SAlexander Graf if (is_write && has_sglist && (s->data_ptr < s->data_end)) { 1015f6ad2e32SAlexander Graf read_from_sglist(s->data_ptr, size, &s->sg); 1016f6ad2e32SAlexander Graf } 1017f6ad2e32SAlexander Graf 1018f6ad2e32SAlexander Graf if (!is_write && has_sglist && (s->data_ptr < s->data_end)) { 1019f6ad2e32SAlexander Graf write_to_sglist(s->data_ptr, size, &s->sg); 1020f6ad2e32SAlexander Graf } 1021f6ad2e32SAlexander Graf 1022f6ad2e32SAlexander Graf /* update number of transferred bytes */ 1023f6ad2e32SAlexander Graf ad->cur_cmd->status = cpu_to_le32(le32_to_cpu(ad->cur_cmd->status) + size); 1024f6ad2e32SAlexander Graf 1025f6ad2e32SAlexander Graf out: 1026f6ad2e32SAlexander Graf /* declare that we processed everything */ 1027f6ad2e32SAlexander Graf s->data_ptr = s->data_end; 1028f6ad2e32SAlexander Graf 1029f6ad2e32SAlexander Graf if (has_sglist) { 1030f6ad2e32SAlexander Graf qemu_sglist_destroy(&s->sg); 1031f6ad2e32SAlexander Graf } 1032f6ad2e32SAlexander Graf 1033f6ad2e32SAlexander Graf s->end_transfer_func(s); 1034f6ad2e32SAlexander Graf 1035f6ad2e32SAlexander Graf if (!(s->status & DRQ_STAT)) { 1036f6ad2e32SAlexander Graf /* done with DMA */ 1037f6ad2e32SAlexander Graf ahci_trigger_irq(ad->hba, ad, PORT_IRQ_STAT_DSS); 1038f6ad2e32SAlexander Graf } 1039f6ad2e32SAlexander Graf 1040f6ad2e32SAlexander Graf return 0; 1041f6ad2e32SAlexander Graf } 1042f6ad2e32SAlexander Graf 1043f6ad2e32SAlexander Graf static void ahci_start_dma(IDEDMA *dma, IDEState *s, 1044f6ad2e32SAlexander Graf BlockDriverCompletionFunc *dma_cb) 1045f6ad2e32SAlexander Graf { 1046f6ad2e32SAlexander Graf AHCIDevice *ad = DO_UPCAST(AHCIDevice, dma, dma); 1047f6ad2e32SAlexander Graf 1048f6ad2e32SAlexander Graf DPRINTF(ad->port_no, "\n"); 1049f6ad2e32SAlexander Graf ad->dma_cb = dma_cb; 1050f6ad2e32SAlexander Graf ad->dma_status |= BM_STATUS_DMAING; 1051f6ad2e32SAlexander Graf dma_cb(s, 0); 1052f6ad2e32SAlexander Graf } 1053f6ad2e32SAlexander Graf 1054f6ad2e32SAlexander Graf static int ahci_dma_prepare_buf(IDEDMA *dma, int is_write) 1055f6ad2e32SAlexander Graf { 1056f6ad2e32SAlexander Graf AHCIDevice *ad = DO_UPCAST(AHCIDevice, dma, dma); 1057f6ad2e32SAlexander Graf IDEState *s = &ad->port.ifs[0]; 1058f6ad2e32SAlexander Graf int i; 1059f6ad2e32SAlexander Graf 1060f6ad2e32SAlexander Graf ahci_populate_sglist(ad, &s->sg); 1061f6ad2e32SAlexander Graf 1062f6ad2e32SAlexander Graf s->io_buffer_size = 0; 1063f6ad2e32SAlexander Graf for (i = 0; i < s->sg.nsg; i++) { 1064f6ad2e32SAlexander Graf s->io_buffer_size += s->sg.sg[i].len; 1065f6ad2e32SAlexander Graf } 1066f6ad2e32SAlexander Graf 1067f6ad2e32SAlexander Graf DPRINTF(ad->port_no, "len=%#x\n", s->io_buffer_size); 1068f6ad2e32SAlexander Graf return s->io_buffer_size != 0; 1069f6ad2e32SAlexander Graf } 1070f6ad2e32SAlexander Graf 1071f6ad2e32SAlexander Graf static int ahci_dma_rw_buf(IDEDMA *dma, int is_write) 1072f6ad2e32SAlexander Graf { 1073f6ad2e32SAlexander Graf AHCIDevice *ad = DO_UPCAST(AHCIDevice, dma, dma); 1074f6ad2e32SAlexander Graf IDEState *s = &ad->port.ifs[0]; 1075f6ad2e32SAlexander Graf uint8_t *p = s->io_buffer + s->io_buffer_index; 1076f6ad2e32SAlexander Graf int l = s->io_buffer_size - s->io_buffer_index; 1077f6ad2e32SAlexander Graf 1078f6ad2e32SAlexander Graf if (ahci_populate_sglist(ad, &s->sg)) { 1079f6ad2e32SAlexander Graf return 0; 1080f6ad2e32SAlexander Graf } 1081f6ad2e32SAlexander Graf 1082f6ad2e32SAlexander Graf if (is_write) { 1083f6ad2e32SAlexander Graf write_to_sglist(p, l, &s->sg); 1084f6ad2e32SAlexander Graf } else { 1085f6ad2e32SAlexander Graf read_from_sglist(p, l, &s->sg); 1086f6ad2e32SAlexander Graf } 1087f6ad2e32SAlexander Graf 1088f6ad2e32SAlexander Graf /* update number of transferred bytes */ 1089f6ad2e32SAlexander Graf ad->cur_cmd->status = cpu_to_le32(le32_to_cpu(ad->cur_cmd->status) + l); 1090f6ad2e32SAlexander Graf s->io_buffer_index += l; 1091f6ad2e32SAlexander Graf 1092f6ad2e32SAlexander Graf DPRINTF(ad->port_no, "len=%#x\n", l); 1093f6ad2e32SAlexander Graf 1094f6ad2e32SAlexander Graf return 1; 1095f6ad2e32SAlexander Graf } 1096f6ad2e32SAlexander Graf 1097f6ad2e32SAlexander Graf static int ahci_dma_set_unit(IDEDMA *dma, int unit) 1098f6ad2e32SAlexander Graf { 1099f6ad2e32SAlexander Graf /* only a single unit per link */ 1100f6ad2e32SAlexander Graf return 0; 1101f6ad2e32SAlexander Graf } 1102f6ad2e32SAlexander Graf 1103f6ad2e32SAlexander Graf static int ahci_dma_add_status(IDEDMA *dma, int status) 1104f6ad2e32SAlexander Graf { 1105f6ad2e32SAlexander Graf AHCIDevice *ad = DO_UPCAST(AHCIDevice, dma, dma); 1106f6ad2e32SAlexander Graf ad->dma_status |= status; 1107f6ad2e32SAlexander Graf DPRINTF(ad->port_no, "set status: %x\n", status); 1108f6ad2e32SAlexander Graf 1109f6ad2e32SAlexander Graf if (status & BM_STATUS_INT) { 1110f6ad2e32SAlexander Graf ahci_trigger_irq(ad->hba, ad, PORT_IRQ_STAT_DSS); 1111f6ad2e32SAlexander Graf } 1112f6ad2e32SAlexander Graf 1113f6ad2e32SAlexander Graf return 0; 1114f6ad2e32SAlexander Graf } 1115f6ad2e32SAlexander Graf 1116f6ad2e32SAlexander Graf static int ahci_dma_set_inactive(IDEDMA *dma) 1117f6ad2e32SAlexander Graf { 1118f6ad2e32SAlexander Graf AHCIDevice *ad = DO_UPCAST(AHCIDevice, dma, dma); 1119f6ad2e32SAlexander Graf 1120f6ad2e32SAlexander Graf DPRINTF(ad->port_no, "dma done\n"); 1121f6ad2e32SAlexander Graf 1122f6ad2e32SAlexander Graf /* update d2h status */ 1123f6ad2e32SAlexander Graf ahci_write_fis_d2h(ad, NULL); 1124f6ad2e32SAlexander Graf 1125f6ad2e32SAlexander Graf ad->dma_cb = NULL; 1126f6ad2e32SAlexander Graf 11274d29b50aSJan Kiszka if (!ad->check_bh) { 1128f6ad2e32SAlexander Graf /* maybe we still have something to process, check later */ 1129f6ad2e32SAlexander Graf ad->check_bh = qemu_bh_new(ahci_check_cmd_bh, ad); 1130f6ad2e32SAlexander Graf qemu_bh_schedule(ad->check_bh); 11314d29b50aSJan Kiszka } 1132f6ad2e32SAlexander Graf 1133f6ad2e32SAlexander Graf return 0; 1134f6ad2e32SAlexander Graf } 1135f6ad2e32SAlexander Graf 1136f6ad2e32SAlexander Graf static void ahci_irq_set(void *opaque, int n, int level) 1137f6ad2e32SAlexander Graf { 1138f6ad2e32SAlexander Graf } 1139f6ad2e32SAlexander Graf 11401dfb4dd9SLuiz Capitulino static void ahci_dma_restart_cb(void *opaque, int running, RunState state) 1141f6ad2e32SAlexander Graf { 1142f6ad2e32SAlexander Graf } 1143f6ad2e32SAlexander Graf 1144f6ad2e32SAlexander Graf static int ahci_dma_reset(IDEDMA *dma) 1145f6ad2e32SAlexander Graf { 1146f6ad2e32SAlexander Graf return 0; 1147f6ad2e32SAlexander Graf } 1148f6ad2e32SAlexander Graf 1149f6ad2e32SAlexander Graf static const IDEDMAOps ahci_dma_ops = { 1150f6ad2e32SAlexander Graf .start_dma = ahci_start_dma, 1151f6ad2e32SAlexander Graf .start_transfer = ahci_start_transfer, 1152f6ad2e32SAlexander Graf .prepare_buf = ahci_dma_prepare_buf, 1153f6ad2e32SAlexander Graf .rw_buf = ahci_dma_rw_buf, 1154f6ad2e32SAlexander Graf .set_unit = ahci_dma_set_unit, 1155f6ad2e32SAlexander Graf .add_status = ahci_dma_add_status, 1156f6ad2e32SAlexander Graf .set_inactive = ahci_dma_set_inactive, 1157f6ad2e32SAlexander Graf .restart_cb = ahci_dma_restart_cb, 1158f6ad2e32SAlexander Graf .reset = ahci_dma_reset, 1159f6ad2e32SAlexander Graf }; 1160f6ad2e32SAlexander Graf 11612c4b9d0eSAlexander Graf void ahci_init(AHCIState *s, DeviceState *qdev, int ports) 1162f6ad2e32SAlexander Graf { 1163f6ad2e32SAlexander Graf qemu_irq *irqs; 1164f6ad2e32SAlexander Graf int i; 1165f6ad2e32SAlexander Graf 11662c4b9d0eSAlexander Graf s->ports = ports; 11677267c094SAnthony Liguori s->dev = g_malloc0(sizeof(AHCIDevice) * ports); 1168f6ad2e32SAlexander Graf ahci_reg_init(s); 116967e576c2SAvi Kivity /* XXX BAR size should be 1k, but that breaks, so bump it to 4k for now */ 1170*465f1ab1SDaniel Verkamp memory_region_init_io(&s->mem, &ahci_mem_ops, s, "ahci", AHCI_MEM_BAR_SIZE); 1171*465f1ab1SDaniel Verkamp memory_region_init_io(&s->idp, &ahci_idp_ops, s, "ahci-idp", 32); 1172*465f1ab1SDaniel Verkamp 11732c4b9d0eSAlexander Graf irqs = qemu_allocate_irqs(ahci_irq_set, s, s->ports); 1174f6ad2e32SAlexander Graf 11752c4b9d0eSAlexander Graf for (i = 0; i < s->ports; i++) { 1176f6ad2e32SAlexander Graf AHCIDevice *ad = &s->dev[i]; 1177f6ad2e32SAlexander Graf 1178f6ad2e32SAlexander Graf ide_bus_new(&ad->port, qdev, i); 1179f6ad2e32SAlexander Graf ide_init2(&ad->port, irqs[i]); 1180f6ad2e32SAlexander Graf 1181f6ad2e32SAlexander Graf ad->hba = s; 1182f6ad2e32SAlexander Graf ad->port_no = i; 1183f6ad2e32SAlexander Graf ad->port.dma = &ad->dma; 1184f6ad2e32SAlexander Graf ad->port.dma->ops = &ahci_dma_ops; 1185f6ad2e32SAlexander Graf ad->port_regs.cmd = PORT_CMD_SPIN_UP | PORT_CMD_POWER_ON; 1186f6ad2e32SAlexander Graf } 1187f6ad2e32SAlexander Graf } 1188f6ad2e32SAlexander Graf 11892c4b9d0eSAlexander Graf void ahci_uninit(AHCIState *s) 11902c4b9d0eSAlexander Graf { 119167e576c2SAvi Kivity memory_region_destroy(&s->mem); 1192*465f1ab1SDaniel Verkamp memory_region_destroy(&s->idp); 11937267c094SAnthony Liguori g_free(s->dev); 11942c4b9d0eSAlexander Graf } 11952c4b9d0eSAlexander Graf 119603c7a6a8SSebastian Herbszt void ahci_reset(void *opaque) 1197f6ad2e32SAlexander Graf { 1198f6ad2e32SAlexander Graf struct AHCIPCIState *d = opaque; 1199a26a13daSAlexander Motin AHCIPortRegs *pr; 1200f6ad2e32SAlexander Graf int i; 1201f6ad2e32SAlexander Graf 1202760c3e44SAlexander Graf d->ahci.control_regs.irqstatus = 0; 1203760c3e44SAlexander Graf d->ahci.control_regs.ghc = 0; 1204760c3e44SAlexander Graf 12052c4b9d0eSAlexander Graf for (i = 0; i < d->ahci.ports; i++) { 1206a26a13daSAlexander Motin pr = &d->ahci.dev[i].port_regs; 1207a26a13daSAlexander Motin pr->irq_stat = 0; 1208a26a13daSAlexander Motin pr->irq_mask = 0; 1209a26a13daSAlexander Motin pr->scr_ctl = 0; 1210f6ad2e32SAlexander Graf ahci_reset_port(&d->ahci, i); 1211f6ad2e32SAlexander Graf } 1212f6ad2e32SAlexander Graf } 1213