Message ID | 1466169069-29375-2-git-send-email-real@ispras.ru (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On 17/06/2016 15:10, Efimov Vasily wrote: > The patch moves "hw/ide/achi.h", "hw/ide/pci.h" and "hw/ide/internal.h" headers > to corresponding folders inside "include" folder alike other Qemu headers. > > Signed-off-by: Efimov Vasily <real@ispras.ru> > --- > This patch only moves headers (with the exception of include path correction > in 'ahci.c'). checkpatch.pl reports a lot of problems with legacy code in > these headers but I think this patch is not the place to fix these problem Use "git config --global diff.renames true". The patch will be shorter and checkpatch will stop complaining! > --- > hw/ide/ahci.c | 2 +- > hw/ide/ahci.h | 405 ----------------------------- > hw/ide/internal.h | 635 ---------------------------------------------- > hw/ide/pci.h | 76 ------ > include/hw/ide/ahci.h | 405 +++++++++++++++++++++++++++++ > include/hw/ide/internal.h | 635 ++++++++++++++++++++++++++++++++++++++++++++++ > include/hw/ide/pci.h | 76 ++++++ > 7 files changed, 1117 insertions(+), 1117 deletions(-) > delete mode 100644 hw/ide/ahci.h > delete mode 100644 hw/ide/internal.h > delete mode 100644 hw/ide/pci.h > create mode 100644 include/hw/ide/ahci.h > create mode 100644 include/hw/ide/internal.h > create mode 100644 include/hw/ide/pci.h > > diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c > index 502d4f1..b1a7b65 100644 > --- a/hw/ide/ahci.c > +++ b/hw/ide/ahci.c > @@ -30,7 +30,7 @@ > #include "qemu/error-report.h" > #include "sysemu/block-backend.h" > #include "sysemu/dma.h" > -#include "internal.h" > +#include <hw/ide/internal.h> > #include <hw/ide/pci.h> > #include <hw/ide/ahci.h> > > diff --git a/hw/ide/ahci.h b/hw/ide/ahci.h > deleted file mode 100644 > index bc777ed..0000000 > --- a/hw/ide/ahci.h > +++ /dev/null > @@ -1,405 +0,0 @@ > -/* > - * QEMU AHCI Emulation > - * > - * Copyright (c) 2010 qiaochong@loongson.cn > - * Copyright (c) 2010 Roland Elek <elek.roland@gmail.com> > - * Copyright (c) 2010 Sebastian Herbszt <herbszt@gmx.de> > - * Copyright (c) 2010 Alexander Graf <agraf@suse.de> > - * > - * This library is free software; you can redistribute it and/or > - * modify it under the terms of the GNU Lesser General Public > - * License as published by the Free Software Foundation; either > - * version 2 of the License, or (at your option) any later version. > - * > - * This library is distributed in the hope that it will be useful, > - * but WITHOUT ANY WARRANTY; without even the implied warranty of > - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > - * Lesser General Public License for more details. > - * > - * You should have received a copy of the GNU Lesser General Public > - * License along with this library; if not, see <http://www.gnu.org/licenses/>. > - * > - */ > - > -#ifndef HW_IDE_AHCI_H > -#define HW_IDE_AHCI_H > - > -#include <hw/sysbus.h> > - > -#define AHCI_MEM_BAR_SIZE 0x1000 > -#define AHCI_MAX_PORTS 32 > -#define AHCI_MAX_SG 168 /* hardware max is 64K */ > -#define AHCI_DMA_BOUNDARY 0xffffffff > -#define AHCI_USE_CLUSTERING 0 > -#define AHCI_MAX_CMDS 32 > -#define AHCI_CMD_SZ 32 > -#define AHCI_CMD_SLOT_SZ (AHCI_MAX_CMDS * AHCI_CMD_SZ) > -#define AHCI_RX_FIS_SZ 256 > -#define AHCI_CMD_TBL_CDB 0x40 > -#define AHCI_CMD_TBL_HDR_SZ 0x80 > -#define AHCI_CMD_TBL_SZ (AHCI_CMD_TBL_HDR_SZ + (AHCI_MAX_SG * 16)) > -#define AHCI_CMD_TBL_AR_SZ (AHCI_CMD_TBL_SZ * AHCI_MAX_CMDS) > -#define AHCI_PORT_PRIV_DMA_SZ (AHCI_CMD_SLOT_SZ + AHCI_CMD_TBL_AR_SZ + \ > - AHCI_RX_FIS_SZ) > - > -#define AHCI_IRQ_ON_SG (1U << 31) > -#define AHCI_CMD_ATAPI (1 << 5) > -#define AHCI_CMD_WRITE (1 << 6) > -#define AHCI_CMD_PREFETCH (1 << 7) > -#define AHCI_CMD_RESET (1 << 8) > -#define AHCI_CMD_CLR_BUSY (1 << 10) > - > -#define RX_FIS_D2H_REG 0x40 /* offset of D2H Register FIS data */ > -#define RX_FIS_SDB 0x58 /* offset of SDB FIS data */ > -#define RX_FIS_UNK 0x60 /* offset of Unknown FIS data */ > - > -/* global controller registers */ > -#define HOST_CAP 0x00 /* host capabilities */ > -#define HOST_CTL 0x04 /* global host control */ > -#define HOST_IRQ_STAT 0x08 /* interrupt status */ > -#define HOST_PORTS_IMPL 0x0c /* bitmap of implemented ports */ > -#define HOST_VERSION 0x10 /* AHCI spec. version compliancy */ > - > -/* HOST_CTL bits */ > -#define HOST_CTL_RESET (1 << 0) /* reset controller; self-clear */ > -#define HOST_CTL_IRQ_EN (1 << 1) /* global IRQ enable */ > -#define HOST_CTL_AHCI_EN (1U << 31) /* AHCI enabled */ > - > -/* HOST_CAP bits */ > -#define HOST_CAP_SSC (1 << 14) /* Slumber capable */ > -#define HOST_CAP_AHCI (1 << 18) /* AHCI only */ > -#define HOST_CAP_CLO (1 << 24) /* Command List Override support */ > -#define HOST_CAP_SSS (1 << 27) /* Staggered Spin-up */ > -#define HOST_CAP_NCQ (1 << 30) /* Native Command Queueing */ > -#define HOST_CAP_64 (1U << 31) /* PCI DAC (64-bit DMA) support */ > - > -/* registers for each SATA port */ > -#define PORT_LST_ADDR 0x00 /* command list DMA addr */ > -#define PORT_LST_ADDR_HI 0x04 /* command list DMA addr hi */ > -#define PORT_FIS_ADDR 0x08 /* FIS rx buf addr */ > -#define PORT_FIS_ADDR_HI 0x0c /* FIS rx buf addr hi */ > -#define PORT_IRQ_STAT 0x10 /* interrupt status */ > -#define PORT_IRQ_MASK 0x14 /* interrupt enable/disable mask */ > -#define PORT_CMD 0x18 /* port command */ > -#define PORT_TFDATA 0x20 /* taskfile data */ > -#define PORT_SIG 0x24 /* device TF signature */ > -#define PORT_SCR_STAT 0x28 /* SATA phy register: SStatus */ > -#define PORT_SCR_CTL 0x2c /* SATA phy register: SControl */ > -#define PORT_SCR_ERR 0x30 /* SATA phy register: SError */ > -#define PORT_SCR_ACT 0x34 /* SATA phy register: SActive */ > -#define PORT_CMD_ISSUE 0x38 /* command issue */ > -#define PORT_RESERVED 0x3c /* reserved */ > - > -/* PORT_IRQ_{STAT,MASK} bits */ > -#define PORT_IRQ_COLD_PRES (1U << 31) /* cold presence detect */ > -#define PORT_IRQ_TF_ERR (1 << 30) /* task file error */ > -#define PORT_IRQ_HBUS_ERR (1 << 29) /* host bus fatal error */ > -#define PORT_IRQ_HBUS_DATA_ERR (1 << 28) /* host bus data error */ > -#define PORT_IRQ_IF_ERR (1 << 27) /* interface fatal error */ > -#define PORT_IRQ_IF_NONFATAL (1 << 26) /* interface non-fatal error */ > -#define PORT_IRQ_OVERFLOW (1 << 24) /* xfer exhausted available S/G */ > -#define PORT_IRQ_BAD_PMP (1 << 23) /* incorrect port multiplier */ > - > -#define PORT_IRQ_PHYRDY (1 << 22) /* PhyRdy changed */ > -#define PORT_IRQ_DEV_ILCK (1 << 7) /* device interlock */ > -#define PORT_IRQ_CONNECT (1 << 6) /* port connect change status */ > -#define PORT_IRQ_SG_DONE (1 << 5) /* descriptor processed */ > -#define PORT_IRQ_UNK_FIS (1 << 4) /* unknown FIS rx'd */ > -#define PORT_IRQ_SDB_FIS (1 << 3) /* Set Device Bits FIS rx'd */ > -#define PORT_IRQ_DMAS_FIS (1 << 2) /* DMA Setup FIS rx'd */ > -#define PORT_IRQ_PIOS_FIS (1 << 1) /* PIO Setup FIS rx'd */ > -#define PORT_IRQ_D2H_REG_FIS (1 << 0) /* D2H Register FIS rx'd */ > - > -#define PORT_IRQ_FREEZE (PORT_IRQ_HBUS_ERR | PORT_IRQ_IF_ERR | \ > - PORT_IRQ_CONNECT | PORT_IRQ_PHYRDY | \ > - PORT_IRQ_UNK_FIS) > -#define PORT_IRQ_ERROR (PORT_IRQ_FREEZE | PORT_IRQ_TF_ERR | \ > - PORT_IRQ_HBUS_DATA_ERR) > -#define DEF_PORT_IRQ (PORT_IRQ_ERROR | PORT_IRQ_SG_DONE | \ > - PORT_IRQ_SDB_FIS | PORT_IRQ_DMAS_FIS | \ > - PORT_IRQ_PIOS_FIS | PORT_IRQ_D2H_REG_FIS) > - > -/* PORT_CMD bits */ > -#define PORT_CMD_ATAPI (1 << 24) /* Device is ATAPI */ > -#define PORT_CMD_LIST_ON (1 << 15) /* cmd list DMA engine running */ > -#define PORT_CMD_FIS_ON (1 << 14) /* FIS DMA engine running */ > -#define PORT_CMD_FIS_RX (1 << 4) /* Enable FIS receive DMA engine */ > -#define PORT_CMD_CLO (1 << 3) /* Command list override */ > -#define PORT_CMD_POWER_ON (1 << 2) /* Power up device */ > -#define PORT_CMD_SPIN_UP (1 << 1) /* Spin up device */ > -#define PORT_CMD_START (1 << 0) /* Enable port DMA engine */ > - > -#define PORT_CMD_ICC_MASK (0xfU << 28) /* i/f ICC state mask */ > -#define PORT_CMD_ICC_ACTIVE (0x1 << 28) /* Put i/f in active state */ > -#define PORT_CMD_ICC_PARTIAL (0x2 << 28) /* Put i/f in partial state */ > -#define PORT_CMD_ICC_SLUMBER (0x6 << 28) /* Put i/f in slumber state */ > - > -#define PORT_CMD_RO_MASK 0x007dffe0 /* Which CMD bits are read only? */ > - > -/* ap->flags bits */ > -#define AHCI_FLAG_NO_NCQ (1 << 24) > -#define AHCI_FLAG_IGN_IRQ_IF_ERR (1 << 25) /* ignore IRQ_IF_ERR */ > -#define AHCI_FLAG_HONOR_PI (1 << 26) /* honor PORTS_IMPL */ > -#define AHCI_FLAG_IGN_SERR_INTERNAL (1 << 27) /* ignore SERR_INTERNAL */ > -#define AHCI_FLAG_32BIT_ONLY (1 << 28) /* force 32bit */ > - > -#define ATA_SRST (1 << 2) /* software reset */ > - > -#define STATE_RUN 0 > -#define STATE_RESET 1 > - > -#define SATA_SCR_SSTATUS_DET_NODEV 0x0 > -#define SATA_SCR_SSTATUS_DET_DEV_PRESENT_PHY_UP 0x3 > - > -#define SATA_SCR_SSTATUS_SPD_NODEV 0x00 > -#define SATA_SCR_SSTATUS_SPD_GEN1 0x10 > - > -#define SATA_SCR_SSTATUS_IPM_NODEV 0x000 > -#define SATA_SCR_SSTATUS_IPM_ACTIVE 0X100 > - > -#define AHCI_SCR_SCTL_DET 0xf > - > -#define SATA_FIS_TYPE_REGISTER_H2D 0x27 > -#define SATA_FIS_REG_H2D_UPDATE_COMMAND_REGISTER 0x80 > -#define SATA_FIS_TYPE_REGISTER_D2H 0x34 > -#define SATA_FIS_TYPE_PIO_SETUP 0x5f > -#define SATA_FIS_TYPE_SDB 0xA1 > - > -#define AHCI_CMD_HDR_CMD_FIS_LEN 0x1f > -#define AHCI_CMD_HDR_PRDT_LEN 16 > - > -#define SATA_SIGNATURE_CDROM 0xeb140101 > -#define SATA_SIGNATURE_DISK 0x00000101 > - > -#define AHCI_GENERIC_HOST_CONTROL_REGS_MAX_ADDR 0x20 > - /* Shouldn't this be 0x2c? */ > - > -#define AHCI_PORT_REGS_START_ADDR 0x100 > -#define AHCI_PORT_ADDR_OFFSET_MASK 0x7f > -#define AHCI_PORT_ADDR_OFFSET_LEN 0x80 > - > -#define AHCI_NUM_COMMAND_SLOTS 31 > -#define AHCI_SUPPORTED_SPEED 20 > -#define AHCI_SUPPORTED_SPEED_GEN1 1 > -#define AHCI_VERSION_1_0 0x10000 > - > -#define AHCI_PROGMODE_MAJOR_REV_1 1 > - > -#define AHCI_COMMAND_TABLE_ACMD 0x40 > - > -#define AHCI_PRDT_SIZE_MASK 0x3fffff > - > -#define IDE_FEATURE_DMA 1 > - > -#define READ_FPDMA_QUEUED 0x60 > -#define WRITE_FPDMA_QUEUED 0x61 > -#define NCQ_NON_DATA 0x63 > -#define RECEIVE_FPDMA_QUEUED 0x65 > -#define SEND_FPDMA_QUEUED 0x64 > - > -#define NCQ_FIS_FUA_MASK 0x80 > -#define NCQ_FIS_RARC_MASK 0x01 > - > -#define RES_FIS_DSFIS 0x00 > -#define RES_FIS_PSFIS 0x20 > -#define RES_FIS_RFIS 0x40 > -#define RES_FIS_SDBFIS 0x58 > -#define RES_FIS_UFIS 0x60 > - > -#define SATA_CAP_SIZE 0x8 > -#define SATA_CAP_REV 0x2 > -#define SATA_CAP_BAR 0x4 > - > -typedef struct AHCIControlRegs { > - uint32_t cap; > - uint32_t ghc; > - uint32_t irqstatus; > - uint32_t impl; > - uint32_t version; > -} AHCIControlRegs; > - > -typedef struct AHCIPortRegs { > - uint32_t lst_addr; > - uint32_t lst_addr_hi; > - uint32_t fis_addr; > - uint32_t fis_addr_hi; > - uint32_t irq_stat; > - uint32_t irq_mask; > - uint32_t cmd; > - uint32_t unused0; > - uint32_t tfdata; > - uint32_t sig; > - uint32_t scr_stat; > - uint32_t scr_ctl; > - uint32_t scr_err; > - uint32_t scr_act; > - uint32_t cmd_issue; > - uint32_t reserved; > -} AHCIPortRegs; > - > -typedef struct AHCICmdHdr { > - uint16_t opts; > - uint16_t prdtl; > - uint32_t status; > - uint64_t tbl_addr; > - uint32_t reserved[4]; > -} QEMU_PACKED AHCICmdHdr; > - > -typedef struct AHCI_SG { > - uint64_t addr; > - uint32_t reserved; > - uint32_t flags_size; > -} QEMU_PACKED AHCI_SG; > - > -typedef struct AHCIDevice AHCIDevice; > - > -typedef struct NCQTransferState { > - AHCIDevice *drive; > - BlockAIOCB *aiocb; > - AHCICmdHdr *cmdh; > - QEMUSGList sglist; > - BlockAcctCookie acct; > - uint32_t sector_count; > - uint64_t lba; > - uint8_t tag; > - uint8_t cmd; > - uint8_t slot; > - bool used; > - bool halt; > -} NCQTransferState; > - > -struct AHCIDevice { > - IDEDMA dma; > - IDEBus port; > - int port_no; > - uint32_t port_state; > - uint32_t finished; > - AHCIPortRegs port_regs; > - struct AHCIState *hba; > - QEMUBH *check_bh; > - uint8_t *lst; > - uint8_t *res_fis; > - bool done_atapi_packet; > - int32_t busy_slot; > - bool init_d2h_sent; > - AHCICmdHdr *cur_cmd; > - NCQTransferState ncq_tfs[AHCI_MAX_CMDS]; > -}; > - > -typedef struct AHCIState { > - DeviceState *container; > - > - AHCIDevice *dev; > - AHCIControlRegs control_regs; > - MemoryRegion mem; > - MemoryRegion idp; /* Index-Data Pair I/O port space */ > - unsigned idp_offset; /* Offset of index in I/O port space */ > - uint32_t idp_index; /* Current IDP index */ > - int32_t ports; > - qemu_irq irq; > - AddressSpace *as; > -} AHCIState; > - > -typedef struct AHCIPCIState { > - /*< private >*/ > - PCIDevice parent_obj; > - /*< public >*/ > - > - AHCIState ahci; > -} AHCIPCIState; > - > -#define TYPE_ICH9_AHCI "ich9-ahci" > - > -#define ICH_AHCI(obj) \ > - OBJECT_CHECK(AHCIPCIState, (obj), TYPE_ICH9_AHCI) > - > -extern const VMStateDescription vmstate_ahci; > - > -#define VMSTATE_AHCI(_field, _state) { \ > - .name = (stringify(_field)), \ > - .size = sizeof(AHCIState), \ > - .vmsd = &vmstate_ahci, \ > - .flags = VMS_STRUCT, \ > - .offset = vmstate_offset_value(_state, _field, AHCIState), \ > -} > - > -/** > - * NCQFrame is the same as a Register H2D FIS (described in SATA 3.2), > - * but some fields have been re-mapped and re-purposed, as seen in > - * SATA 3.2 section 13.6.4.1 ("READ FPDMA QUEUED") > - * > - * cmd_fis[3], feature 7:0, becomes sector count 7:0. > - * cmd_fis[7], device 7:0, uses bit 7 as the Force Unit Access bit. > - * cmd_fis[11], feature 15:8, becomes sector count 15:8. > - * cmd_fis[12], count 7:0, becomes the NCQ TAG (7:3) and RARC bit (0) > - * cmd_fis[13], count 15:8, becomes the priority value (7:6) > - * bytes 16-19 become an le32 "auxiliary" field. > - */ > -typedef struct NCQFrame { > - uint8_t fis_type; > - uint8_t c; > - uint8_t command; > - uint8_t sector_count_low; /* (feature 7:0) */ > - uint8_t lba0; > - uint8_t lba1; > - uint8_t lba2; > - uint8_t fua; /* (device 7:0) */ > - uint8_t lba3; > - uint8_t lba4; > - uint8_t lba5; > - uint8_t sector_count_high; /* (feature 15:8) */ > - uint8_t tag; /* (count 0:7) */ > - uint8_t prio; /* (count 15:8) */ > - uint8_t icc; > - uint8_t control; > - uint8_t aux0; > - uint8_t aux1; > - uint8_t aux2; > - uint8_t aux3; > -} QEMU_PACKED NCQFrame; > - > -typedef struct SDBFIS { > - uint8_t type; > - uint8_t flags; > - uint8_t status; > - uint8_t error; > - uint32_t payload; > -} QEMU_PACKED SDBFIS; > - > -void ahci_realize(AHCIState *s, DeviceState *qdev, AddressSpace *as, int ports); > -void ahci_init(AHCIState *s, DeviceState *qdev); > -void ahci_uninit(AHCIState *s); > - > -void ahci_reset(AHCIState *s); > - > -void ahci_ide_create_devs(PCIDevice *dev, DriveInfo **hd); > - > -#define TYPE_SYSBUS_AHCI "sysbus-ahci" > -#define SYSBUS_AHCI(obj) OBJECT_CHECK(SysbusAHCIState, (obj), TYPE_SYSBUS_AHCI) > - > -typedef struct SysbusAHCIState { > - /*< private >*/ > - SysBusDevice parent_obj; > - /*< public >*/ > - > - AHCIState ahci; > - uint32_t num_ports; > -} SysbusAHCIState; > - > -#define TYPE_ALLWINNER_AHCI "allwinner-ahci" > -#define ALLWINNER_AHCI(obj) OBJECT_CHECK(AllwinnerAHCIState, (obj), \ > - TYPE_ALLWINNER_AHCI) > - > -#define ALLWINNER_AHCI_MMIO_OFF 0x80 > -#define ALLWINNER_AHCI_MMIO_SIZE 0x80 > - > -struct AllwinnerAHCIState { > - /*< private >*/ > - SysbusAHCIState parent_obj; > - /*< public >*/ > - > - MemoryRegion mmio; > - uint32_t regs[ALLWINNER_AHCI_MMIO_SIZE/4]; > -}; > - > -#endif /* HW_IDE_AHCI_H */ > diff --git a/hw/ide/internal.h b/hw/ide/internal.h > deleted file mode 100644 > index 773928a..0000000 > --- a/hw/ide/internal.h > +++ /dev/null > @@ -1,635 +0,0 @@ > -#ifndef HW_IDE_INTERNAL_H > -#define HW_IDE_INTERNAL_H > - > -/* > - * QEMU IDE Emulation -- internal header file > - * only files in hw/ide/ are supposed to include this file. > - * non-internal declarations are in hw/ide.h > - */ > -#include <hw/ide.h> > -#include <hw/isa/isa.h> > -#include "sysemu/dma.h" > -#include "sysemu/sysemu.h" > -#include "hw/block/block.h" > -#include "block/scsi.h" > - > -/* debug IDE devices */ > -//#define DEBUG_IDE > -//#define DEBUG_IDE_ATAPI > -//#define DEBUG_AIO > -#define USE_DMA_CDROM > - > -typedef struct IDEBus IDEBus; > -typedef struct IDEDevice IDEDevice; > -typedef struct IDEState IDEState; > -typedef struct IDEDMA IDEDMA; > -typedef struct IDEDMAOps IDEDMAOps; > - > -#define TYPE_IDE_BUS "IDE" > -#define IDE_BUS(obj) OBJECT_CHECK(IDEBus, (obj), TYPE_IDE_BUS) > - > -/* Bits of HD_STATUS */ > -#define ERR_STAT 0x01 > -#define INDEX_STAT 0x02 > -#define ECC_STAT 0x04 /* Corrected error */ > -#define DRQ_STAT 0x08 > -#define SEEK_STAT 0x10 > -#define SRV_STAT 0x10 > -#define WRERR_STAT 0x20 > -#define READY_STAT 0x40 > -#define BUSY_STAT 0x80 > - > -/* Bits for HD_ERROR */ > -#define MARK_ERR 0x01 /* Bad address mark */ > -#define TRK0_ERR 0x02 /* couldn't find track 0 */ > -#define ABRT_ERR 0x04 /* Command aborted */ > -#define MCR_ERR 0x08 /* media change request */ > -#define ID_ERR 0x10 /* ID field not found */ > -#define MC_ERR 0x20 /* media changed */ > -#define ECC_ERR 0x40 /* Uncorrectable ECC error */ > -#define BBD_ERR 0x80 /* pre-EIDE meaning: block marked bad */ > -#define ICRC_ERR 0x80 /* new meaning: CRC error during transfer */ > - > -/* Bits of HD_NSECTOR */ > -#define CD 0x01 > -#define IO 0x02 > -#define REL 0x04 > -#define TAG_MASK 0xf8 > - > -#define IDE_CMD_RESET 0x04 > -#define IDE_CMD_DISABLE_IRQ 0x02 > - > -/* ACS-2 T13/2015-D Table B.2 Command codes */ > -#define WIN_NOP 0x00 > -/* reserved 0x01..0x02 */ > -#define CFA_REQ_EXT_ERROR_CODE 0x03 /* CFA Request Extended Error Code */ > -/* reserved 0x04..0x05 */ > -#define WIN_DSM 0x06 > -/* reserved 0x07 */ > -#define WIN_DEVICE_RESET 0x08 > -/* reserved 0x09..0x0a */ > -/* REQUEST SENSE DATA EXT 0x0B */ > -/* reserved 0x0C..0x0F */ > -#define WIN_RECAL 0x10 /* obsolete since ATA4 */ > -/* obsolete since ATA3, retired in ATA4 0x11..0x1F */ > -#define WIN_READ 0x20 /* 28-Bit */ > -#define WIN_READ_ONCE 0x21 /* 28-Bit w/o retries, obsolete since ATA5 */ > -/* obsolete since ATA4 0x22..0x23 */ > -#define WIN_READ_EXT 0x24 /* 48-Bit */ > -#define WIN_READDMA_EXT 0x25 /* 48-Bit */ > -#define WIN_READDMA_QUEUED_EXT 0x26 /* 48-Bit, obsolete since ACS2 */ > -#define WIN_READ_NATIVE_MAX_EXT 0x27 /* 48-Bit */ > -/* reserved 0x28 */ > -#define WIN_MULTREAD_EXT 0x29 /* 48-Bit */ > -/* READ STREAM DMA EXT 0x2A */ > -/* READ STREAM EXT 0x2B */ > -/* reserved 0x2C..0x2E */ > -/* READ LOG EXT 0x2F */ > -#define WIN_WRITE 0x30 /* 28-Bit */ > -#define WIN_WRITE_ONCE 0x31 /* 28-Bit w/o retries, obsolete since ATA5 */ > -/* obsolete since ATA4 0x32..0x33 */ > -#define WIN_WRITE_EXT 0x34 /* 48-Bit */ > -#define WIN_WRITEDMA_EXT 0x35 /* 48-Bit */ > -#define WIN_WRITEDMA_QUEUED_EXT 0x36 /* 48-Bit */ > -#define WIN_SET_MAX_EXT 0x37 /* 48-Bit, obsolete since ACS2 */ > -#define WIN_SET_MAX_EXT 0x37 /* 48-Bit */ > -#define CFA_WRITE_SECT_WO_ERASE 0x38 /* CFA Write Sectors without erase */ > -#define WIN_MULTWRITE_EXT 0x39 /* 48-Bit */ > -/* WRITE STREAM DMA EXT 0x3A */ > -/* WRITE STREAM EXT 0x3B */ > -#define WIN_WRITE_VERIFY 0x3C /* 28-Bit, obsolete since ATA4 */ > -/* WRITE DMA FUA EXT 0x3D */ > -/* obsolete since ACS2 0x3E */ > -/* WRITE LOG EXT 0x3F */ > -#define WIN_VERIFY 0x40 /* 28-Bit - Read Verify Sectors */ > -#define WIN_VERIFY_ONCE 0x41 /* 28-Bit - w/o retries, obsolete since ATA5 */ > -#define WIN_VERIFY_EXT 0x42 /* 48-Bit */ > -/* reserved 0x43..0x44 */ > -/* WRITE UNCORRECTABLE EXT 0x45 */ > -/* reserved 0x46 */ > -/* READ LOG DMA EXT 0x47 */ > -/* reserved 0x48..0x4F */ > -/* obsolete since ATA4 0x50 */ > -/* CONFIGURE STREAM 0x51 */ > -/* reserved 0x52..0x56 */ > -/* WRITE LOG DMA EXT 0x57 */ > -/* reserved 0x58..0x5A */ > -/* TRUSTED NON DATA 0x5B */ > -/* TRUSTED RECEIVE 0x5C */ > -/* TRUSTED RECEIVE DMA 0x5D */ > -/* TRUSTED SEND 0x5E */ > -/* TRUSTED SEND DMA 0x5F */ > -/* READ FPDMA QUEUED 0x60 */ > -/* WRITE FPDMA QUEUED 0x61 */ > -/* reserved 0x62->0x6F */ > -#define WIN_SEEK 0x70 /* obsolete since ATA7 */ > -/* reserved 0x71-0x7F */ > -/* vendor specific 0x80-0x86 */ > -#define CFA_TRANSLATE_SECTOR 0x87 /* CFA Translate Sector */ > -/* vendor specific 0x88-0x8F */ > -#define WIN_DIAGNOSE 0x90 > -#define WIN_SPECIFY 0x91 /* set drive geometry translation, obsolete since ATA6 */ > -#define WIN_DOWNLOAD_MICROCODE 0x92 > -/* DOWNLOAD MICROCODE DMA 0x93 */ > -#define WIN_STANDBYNOW2 0x94 /* retired in ATA4 */ > -#define WIN_IDLEIMMEDIATE2 0x95 /* force drive to become "ready", retired in ATA4 */ > -#define WIN_STANDBY2 0x96 /* retired in ATA4 */ > -#define WIN_SETIDLE2 0x97 /* retired in ATA4 */ > -#define WIN_CHECKPOWERMODE2 0x98 /* retired in ATA4 */ > -#define WIN_SLEEPNOW2 0x99 /* retired in ATA4 */ > -/* vendor specific 0x9A */ > -/* reserved 0x9B..0x9F */ > -#define WIN_PACKETCMD 0xA0 /* Send a packet command. */ > -#define WIN_PIDENTIFY 0xA1 /* identify ATAPI device */ > -#define WIN_QUEUED_SERVICE 0xA2 /* obsolete since ACS2 */ > -/* reserved 0xA3..0xAF */ > -#define WIN_SMART 0xB0 /* self-monitoring and reporting */ > -/* Device Configuration Overlay 0xB1 */ > -/* reserved 0xB2..0xB3 */ > -/* Sanitize Device 0xB4 */ > -/* reserved 0xB5 */ > -/* NV Cache 0xB6 */ > -/* reserved for CFA 0xB7..0xBB */ > -#define CFA_ACCESS_METADATA_STORAGE 0xB8 > -/* reserved 0xBC..0xBF */ > -#define CFA_ERASE_SECTORS 0xC0 /* microdrives implement as NOP */ > -/* vendor specific 0xC1..0xC3 */ > -#define WIN_MULTREAD 0xC4 /* read sectors using multiple mode*/ > -#define WIN_MULTWRITE 0xC5 /* write sectors using multiple mode */ > -#define WIN_SETMULT 0xC6 /* enable/disable multiple mode */ > -#define WIN_READDMA_QUEUED 0xC7 /* read sectors using Queued DMA transfers, obsolete since ACS2 */ > -#define WIN_READDMA 0xC8 /* read sectors using DMA transfers */ > -#define WIN_READDMA_ONCE 0xC9 /* 28-Bit - w/o retries, obsolete since ATA5 */ > -#define WIN_WRITEDMA 0xCA /* write sectors using DMA transfers */ > -#define WIN_WRITEDMA_ONCE 0xCB /* 28-Bit - w/o retries, obsolete since ATA5 */ > -#define WIN_WRITEDMA_QUEUED 0xCC /* write sectors using Queued DMA transfers, obsolete since ACS2 */ > -#define CFA_WRITE_MULTI_WO_ERASE 0xCD /* CFA Write multiple without erase */ > -/* WRITE MULTIPLE FUA EXT 0xCE */ > -/* reserved 0xCF..0xDO */ > -/* CHECK MEDIA CARD TYPE 0xD1 */ > -/* reserved for media card pass through 0xD2..0xD4 */ > -/* reserved 0xD5..0xD9 */ > -#define WIN_GETMEDIASTATUS 0xDA /* obsolete since ATA8 */ > -/* obsolete since ATA3, retired in ATA4 0xDB..0xDD */ > -#define WIN_DOORLOCK 0xDE /* lock door on removable drives, obsolete since ATA8 */ > -#define WIN_DOORUNLOCK 0xDF /* unlock door on removable drives, obsolete since ATA8 */ > -#define WIN_STANDBYNOW1 0xE0 > -#define WIN_IDLEIMMEDIATE 0xE1 /* force drive to become "ready" */ > -#define WIN_STANDBY 0xE2 /* Set device in Standby Mode */ > -#define WIN_SETIDLE1 0xE3 > -#define WIN_READ_BUFFER 0xE4 /* force read only 1 sector */ > -#define WIN_CHECKPOWERMODE1 0xE5 > -#define WIN_SLEEPNOW1 0xE6 > -#define WIN_FLUSH_CACHE 0xE7 > -#define WIN_WRITE_BUFFER 0xE8 /* force write only 1 sector */ > -/* READ BUFFER DMA 0xE9 */ > -#define WIN_FLUSH_CACHE_EXT 0xEA /* 48-Bit */ > -/* WRITE BUFFER DMA 0xEB */ > -#define WIN_IDENTIFY 0xEC /* ask drive to identify itself */ > -#define WIN_MEDIAEJECT 0xED /* obsolete since ATA8 */ > -/* obsolete since ATA4 0xEE */ > -#define WIN_SETFEATURES 0xEF /* set special drive features */ > -#define IBM_SENSE_CONDITION 0xF0 /* measure disk temperature, vendor specific */ > -#define WIN_SECURITY_SET_PASS 0xF1 > -#define WIN_SECURITY_UNLOCK 0xF2 > -#define WIN_SECURITY_ERASE_PREPARE 0xF3 > -#define WIN_SECURITY_ERASE_UNIT 0xF4 > -#define WIN_SECURITY_FREEZE_LOCK 0xF5 > -#define CFA_WEAR_LEVEL 0xF5 /* microdrives implement as NOP; not specified in T13! */ > -#define WIN_SECURITY_DISABLE 0xF6 > -/* vendor specific 0xF7 */ > -#define WIN_READ_NATIVE_MAX 0xF8 /* return the native maximum address */ > -#define WIN_SET_MAX 0xF9 > -/* vendor specific 0xFA..0xFF */ > - > -/* set to 1 set disable mult support */ > -#define MAX_MULT_SECTORS 16 > - > -#define IDE_DMA_BUF_SECTORS 256 > - > -/* feature values for Data Set Management */ > -#define DSM_TRIM 0x01 > - > -#if (IDE_DMA_BUF_SECTORS < MAX_MULT_SECTORS) > -#error "IDE_DMA_BUF_SECTORS must be bigger or equal to MAX_MULT_SECTORS" > -#endif > - > -/* ATAPI defines */ > - > -#define ATAPI_PACKET_SIZE 12 > - > -/* The generic packet command opcodes for CD/DVD Logical Units, > - * From Table 57 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */ > -#define GPCMD_BLANK 0xa1 > -#define GPCMD_CLOSE_TRACK 0x5b > -#define GPCMD_FLUSH_CACHE 0x35 > -#define GPCMD_FORMAT_UNIT 0x04 > -#define GPCMD_GET_CONFIGURATION 0x46 > -#define GPCMD_GET_EVENT_STATUS_NOTIFICATION 0x4a > -#define GPCMD_GET_PERFORMANCE 0xac > -#define GPCMD_INQUIRY 0x12 > -#define GPCMD_LOAD_UNLOAD 0xa6 > -#define GPCMD_MECHANISM_STATUS 0xbd > -#define GPCMD_MODE_SELECT_10 0x55 > -#define GPCMD_MODE_SENSE_10 0x5a > -#define GPCMD_PAUSE_RESUME 0x4b > -#define GPCMD_PLAY_AUDIO_10 0x45 > -#define GPCMD_PLAY_AUDIO_MSF 0x47 > -#define GPCMD_PLAY_AUDIO_TI 0x48 > -#define GPCMD_PLAY_CD 0xbc > -#define GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1e > -#define GPCMD_READ_10 0x28 > -#define GPCMD_READ_12 0xa8 > -#define GPCMD_READ_CDVD_CAPACITY 0x25 > -#define GPCMD_READ_CD 0xbe > -#define GPCMD_READ_CD_MSF 0xb9 > -#define GPCMD_READ_DISC_INFO 0x51 > -#define GPCMD_READ_DVD_STRUCTURE 0xad > -#define GPCMD_READ_FORMAT_CAPACITIES 0x23 > -#define GPCMD_READ_HEADER 0x44 > -#define GPCMD_READ_TRACK_RZONE_INFO 0x52 > -#define GPCMD_READ_SUBCHANNEL 0x42 > -#define GPCMD_READ_TOC_PMA_ATIP 0x43 > -#define GPCMD_REPAIR_RZONE_TRACK 0x58 > -#define GPCMD_REPORT_KEY 0xa4 > -#define GPCMD_REQUEST_SENSE 0x03 > -#define GPCMD_RESERVE_RZONE_TRACK 0x53 > -#define GPCMD_SCAN 0xba > -#define GPCMD_SEEK 0x2b > -#define GPCMD_SEND_DVD_STRUCTURE 0xad > -#define GPCMD_SEND_EVENT 0xa2 > -#define GPCMD_SEND_KEY 0xa3 > -#define GPCMD_SEND_OPC 0x54 > -#define GPCMD_SET_READ_AHEAD 0xa7 > -#define GPCMD_SET_STREAMING 0xb6 > -#define GPCMD_START_STOP_UNIT 0x1b > -#define GPCMD_STOP_PLAY_SCAN 0x4e > -#define GPCMD_TEST_UNIT_READY 0x00 > -#define GPCMD_VERIFY_10 0x2f > -#define GPCMD_WRITE_10 0x2a > -#define GPCMD_WRITE_AND_VERIFY_10 0x2e > -/* This is listed as optional in ATAPI 2.6, but is (curiously) > - * missing from Mt. Fuji, Table 57. It _is_ mentioned in Mt. Fuji > - * Table 377 as an MMC command for SCSi devices though... Most ATAPI > - * drives support it. */ > -#define GPCMD_SET_SPEED 0xbb > -/* This seems to be a SCSI specific CD-ROM opcode > - * to play data at track/index */ > -#define GPCMD_PLAYAUDIO_TI 0x48 > -/* > - * From MS Media Status Notification Support Specification. For > - * older drives only. > - */ > -#define GPCMD_GET_MEDIA_STATUS 0xda > -#define GPCMD_MODE_SENSE_6 0x1a > - > -#define ATAPI_INT_REASON_CD 0x01 /* 0 = data transfer */ > -#define ATAPI_INT_REASON_IO 0x02 /* 1 = transfer to the host */ > -#define ATAPI_INT_REASON_REL 0x04 > -#define ATAPI_INT_REASON_TAG 0xf8 > - > -/* same constants as bochs */ > -#define ASC_NO_SEEK_COMPLETE 0x02 > -#define ASC_ILLEGAL_OPCODE 0x20 > -#define ASC_LOGICAL_BLOCK_OOR 0x21 > -#define ASC_INV_FIELD_IN_CMD_PACKET 0x24 > -#define ASC_MEDIUM_MAY_HAVE_CHANGED 0x28 > -#define ASC_INCOMPATIBLE_FORMAT 0x30 > -#define ASC_MEDIUM_NOT_PRESENT 0x3a > -#define ASC_SAVING_PARAMETERS_NOT_SUPPORTED 0x39 > -#define ASC_DATA_PHASE_ERROR 0x4b > -#define ASC_MEDIA_REMOVAL_PREVENTED 0x53 > - > -#define CFA_NO_ERROR 0x00 > -#define CFA_MISC_ERROR 0x09 > -#define CFA_INVALID_COMMAND 0x20 > -#define CFA_INVALID_ADDRESS 0x21 > -#define CFA_ADDRESS_OVERFLOW 0x2f > - > -#define SMART_READ_DATA 0xd0 > -#define SMART_READ_THRESH 0xd1 > -#define SMART_ATTR_AUTOSAVE 0xd2 > -#define SMART_SAVE_ATTR 0xd3 > -#define SMART_EXECUTE_OFFLINE 0xd4 > -#define SMART_READ_LOG 0xd5 > -#define SMART_WRITE_LOG 0xd6 > -#define SMART_ENABLE 0xd8 > -#define SMART_DISABLE 0xd9 > -#define SMART_STATUS 0xda > - > -typedef enum { IDE_HD, IDE_CD, IDE_CFATA } IDEDriveKind; > - > -typedef void EndTransferFunc(IDEState *); > - > -typedef void DMAStartFunc(IDEDMA *, IDEState *, BlockCompletionFunc *); > -typedef void DMAVoidFunc(IDEDMA *); > -typedef int DMAIntFunc(IDEDMA *, int); > -typedef int32_t DMAInt32Func(IDEDMA *, int32_t len); > -typedef void DMAu32Func(IDEDMA *, uint32_t); > -typedef void DMAStopFunc(IDEDMA *, bool); > -typedef void DMARestartFunc(void *, int, RunState); > - > -struct unreported_events { > - bool eject_request; > - bool new_media; > -}; > - > -enum ide_dma_cmd { > - IDE_DMA_READ, > - IDE_DMA_WRITE, > - IDE_DMA_TRIM, > - IDE_DMA_ATAPI, > -}; > - > -#define ide_cmd_is_read(s) \ > - ((s)->dma_cmd == IDE_DMA_READ) > - > -typedef struct IDEBufferedRequest { > - QLIST_ENTRY(IDEBufferedRequest) list; > - struct iovec iov; > - QEMUIOVector qiov; > - QEMUIOVector *original_qiov; > - BlockCompletionFunc *original_cb; > - void *original_opaque; > - bool orphaned; > -} IDEBufferedRequest; > - > -/* NOTE: IDEState represents in fact one drive */ > -struct IDEState { > - IDEBus *bus; > - uint8_t unit; > - /* ide config */ > - IDEDriveKind drive_kind; > - int cylinders, heads, sectors, chs_trans; > - int64_t nb_sectors; > - int mult_sectors; > - int identify_set; > - uint8_t identify_data[512]; > - int drive_serial; > - char drive_serial_str[21]; > - char drive_model_str[41]; > - uint64_t wwn; > - /* ide regs */ > - uint8_t feature; > - uint8_t error; > - uint32_t nsector; > - uint8_t sector; > - uint8_t lcyl; > - uint8_t hcyl; > - /* other part of tf for lba48 support */ > - uint8_t hob_feature; > - uint8_t hob_nsector; > - uint8_t hob_sector; > - uint8_t hob_lcyl; > - uint8_t hob_hcyl; > - > - uint8_t select; > - uint8_t status; > - > - /* set for lba48 access */ > - uint8_t lba48; > - BlockBackend *blk; > - char version[9]; > - /* ATAPI specific */ > - struct unreported_events events; > - uint8_t sense_key; > - uint8_t asc; > - bool tray_open; > - bool tray_locked; > - uint8_t cdrom_changed; > - int packet_transfer_size; > - int elementary_transfer_size; > - int32_t io_buffer_index; > - int lba; > - int cd_sector_size; > - int atapi_dma; /* true if dma is requested for the packet cmd */ > - BlockAcctCookie acct; > - BlockAIOCB *pio_aiocb; > - struct iovec iov; > - QEMUIOVector qiov; > - QLIST_HEAD(, IDEBufferedRequest) buffered_requests; > - /* ATA DMA state */ > - uint64_t io_buffer_offset; > - int32_t io_buffer_size; > - QEMUSGList sg; > - /* PIO transfer handling */ > - int req_nb_sectors; /* number of sectors per interrupt */ > - EndTransferFunc *end_transfer_func; > - uint8_t *data_ptr; > - uint8_t *data_end; > - uint8_t *io_buffer; > - /* PIO save/restore */ > - int32_t io_buffer_total_len; > - int32_t cur_io_buffer_offset; > - int32_t cur_io_buffer_len; > - uint8_t end_transfer_fn_idx; > - QEMUTimer *sector_write_timer; /* only used for win2k install hack */ > - uint32_t irq_count; /* counts IRQs when using win2k install hack */ > - /* CF-ATA extended error */ > - uint8_t ext_error; > - /* CF-ATA metadata storage */ > - uint32_t mdata_size; > - uint8_t *mdata_storage; > - int media_changed; > - enum ide_dma_cmd dma_cmd; > - /* SMART */ > - uint8_t smart_enabled; > - uint8_t smart_autosave; > - int smart_errors; > - uint8_t smart_selftest_count; > - uint8_t *smart_selftest_data; > - /* AHCI */ > - int ncq_queues; > -}; > - > -struct IDEDMAOps { > - DMAStartFunc *start_dma; > - DMAVoidFunc *start_transfer; > - DMAInt32Func *prepare_buf; > - DMAu32Func *commit_buf; > - DMAIntFunc *rw_buf; > - DMAVoidFunc *restart; > - DMAVoidFunc *restart_dma; > - DMAStopFunc *set_inactive; > - DMAVoidFunc *cmd_done; > - DMAVoidFunc *reset; > -}; > - > -struct IDEDMA { > - const struct IDEDMAOps *ops; > - struct iovec iov; > - QEMUIOVector qiov; > - BlockAIOCB *aiocb; > -}; > - > -struct IDEBus { > - BusState qbus; > - IDEDevice *master; > - IDEDevice *slave; > - IDEState ifs[2]; > - QEMUBH *bh; > - > - int bus_id; > - int max_units; > - IDEDMA *dma; > - uint8_t unit; > - uint8_t cmd; > - qemu_irq irq; > - > - int error_status; > - uint8_t retry_unit; > - int64_t retry_sector_num; > - uint32_t retry_nsector; > -}; > - > -#define TYPE_IDE_DEVICE "ide-device" > -#define IDE_DEVICE(obj) \ > - OBJECT_CHECK(IDEDevice, (obj), TYPE_IDE_DEVICE) > -#define IDE_DEVICE_CLASS(klass) \ > - OBJECT_CLASS_CHECK(IDEDeviceClass, (klass), TYPE_IDE_DEVICE) > -#define IDE_DEVICE_GET_CLASS(obj) \ > - OBJECT_GET_CLASS(IDEDeviceClass, (obj), TYPE_IDE_DEVICE) > - > -typedef struct IDEDeviceClass { > - DeviceClass parent_class; > - int (*init)(IDEDevice *dev); > -} IDEDeviceClass; > - > -struct IDEDevice { > - DeviceState qdev; > - uint32_t unit; > - BlockConf conf; > - int chs_trans; > - char *version; > - char *serial; > - char *model; > - uint64_t wwn; > -}; > - > -/* These are used for the error_status field of IDEBus */ > -#define IDE_RETRY_MASK 0xf8 > -#define IDE_RETRY_DMA 0x08 > -#define IDE_RETRY_PIO 0x10 > -#define IDE_RETRY_ATAPI 0x20 /* reused IDE_RETRY_READ bit */ > -#define IDE_RETRY_READ 0x20 > -#define IDE_RETRY_FLUSH 0x40 > -#define IDE_RETRY_TRIM 0x80 > -#define IDE_RETRY_HBA 0x100 > - > -#define IS_IDE_RETRY_DMA(_status) \ > - ((_status) & IDE_RETRY_DMA) > - > -#define IS_IDE_RETRY_PIO(_status) \ > - ((_status) & IDE_RETRY_PIO) > - > -/* > - * The method of the IDE_RETRY_ATAPI determination is to use a previously > - * impossible bit combination as a new status value. > - */ > -#define IS_IDE_RETRY_ATAPI(_status) \ > - (((_status) & IDE_RETRY_MASK) == IDE_RETRY_ATAPI) > - > -static inline uint8_t ide_dma_cmd_to_retry(uint8_t dma_cmd) > -{ > - switch (dma_cmd) { > - case IDE_DMA_READ: > - return IDE_RETRY_DMA | IDE_RETRY_READ; > - case IDE_DMA_WRITE: > - return IDE_RETRY_DMA; > - case IDE_DMA_TRIM: > - return IDE_RETRY_DMA | IDE_RETRY_TRIM; > - case IDE_DMA_ATAPI: > - return IDE_RETRY_ATAPI; > - default: > - break; > - } > - return 0; > -} > - > -static inline IDEState *idebus_active_if(IDEBus *bus) > -{ > - return bus->ifs + bus->unit; > -} > - > -static inline void ide_set_irq(IDEBus *bus) > -{ > - if (!(bus->cmd & IDE_CMD_DISABLE_IRQ)) { > - qemu_irq_raise(bus->irq); > - } > -} > - > -/* hw/ide/core.c */ > -extern const VMStateDescription vmstate_ide_bus; > - > -#define VMSTATE_IDE_BUS(_field, _state) \ > - VMSTATE_STRUCT(_field, _state, 1, vmstate_ide_bus, IDEBus) > - > -#define VMSTATE_IDE_BUS_ARRAY(_field, _state, _num) \ > - VMSTATE_STRUCT_ARRAY(_field, _state, _num, 1, vmstate_ide_bus, IDEBus) > - > -extern const VMStateDescription vmstate_ide_drive; > - > -#define VMSTATE_IDE_DRIVES(_field, _state) \ > - VMSTATE_STRUCT_ARRAY(_field, _state, 2, 3, vmstate_ide_drive, IDEState) > - > -#define VMSTATE_IDE_DRIVE(_field, _state) \ > - VMSTATE_STRUCT(_field, _state, 1, vmstate_ide_drive, IDEState) > - > -void ide_bus_reset(IDEBus *bus); > -int64_t ide_get_sector(IDEState *s); > -void ide_set_sector(IDEState *s, int64_t sector_num); > - > -void ide_start_dma(IDEState *s, BlockCompletionFunc *cb); > -void dma_buf_commit(IDEState *s, uint32_t tx_bytes); > -void ide_dma_error(IDEState *s); > -void ide_abort_command(IDEState *s); > - > -void ide_atapi_cmd_ok(IDEState *s); > -void ide_atapi_cmd_error(IDEState *s, int sense_key, int asc); > -void ide_atapi_dma_restart(IDEState *s); > -void ide_atapi_io_error(IDEState *s, int ret); > - > -void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val); > -uint32_t ide_ioport_read(void *opaque, uint32_t addr1); > -uint32_t ide_status_read(void *opaque, uint32_t addr); > -void ide_cmd_write(void *opaque, uint32_t addr, uint32_t val); > -void ide_data_writew(void *opaque, uint32_t addr, uint32_t val); > -uint32_t ide_data_readw(void *opaque, uint32_t addr); > -void ide_data_writel(void *opaque, uint32_t addr, uint32_t val); > -uint32_t ide_data_readl(void *opaque, uint32_t addr); > - > -int ide_init_drive(IDEState *s, BlockBackend *blk, IDEDriveKind kind, > - const char *version, const char *serial, const char *model, > - uint64_t wwn, > - uint32_t cylinders, uint32_t heads, uint32_t secs, > - int chs_trans); > -void ide_init2(IDEBus *bus, qemu_irq irq); > -void ide_init_ioport(IDEBus *bus, ISADevice *isa, int iobase, int iobase2); > -void ide_register_restart_cb(IDEBus *bus); > - > -void ide_exec_cmd(IDEBus *bus, uint32_t val); > - > -void ide_transfer_start(IDEState *s, uint8_t *buf, int size, > - EndTransferFunc *end_transfer_func); > -void ide_transfer_stop(IDEState *s); > -void ide_set_inactive(IDEState *s, bool more); > -BlockAIOCB *ide_issue_trim( > - int64_t offset, QEMUIOVector *qiov, > - BlockCompletionFunc *cb, void *cb_opaque, void *opaque); > -BlockAIOCB *ide_buffered_readv(IDEState *s, int64_t sector_num, > - QEMUIOVector *iov, int nb_sectors, > - BlockCompletionFunc *cb, void *opaque); > -void ide_cancel_dma_sync(IDEState *s); > - > -/* hw/ide/atapi.c */ > -void ide_atapi_cmd(IDEState *s); > -void ide_atapi_cmd_reply_end(IDEState *s); > - > -/* hw/ide/qdev.c */ > -void ide_bus_new(IDEBus *idebus, size_t idebus_size, DeviceState *dev, > - int bus_id, int max_units); > -IDEDevice *ide_create_drive(IDEBus *bus, int unit, DriveInfo *drive); > - > -int ide_handle_rw_error(IDEState *s, int error, int op); > - > -#endif /* HW_IDE_INTERNAL_H */ > diff --git a/hw/ide/pci.h b/hw/ide/pci.h > deleted file mode 100644 > index 0f2d4b9..0000000 > --- a/hw/ide/pci.h > +++ /dev/null > @@ -1,76 +0,0 @@ > -#ifndef HW_IDE_PCI_H > -#define HW_IDE_PCI_H > - > -#include <hw/ide/internal.h> > - > -#define BM_STATUS_DMAING 0x01 > -#define BM_STATUS_ERROR 0x02 > -#define BM_STATUS_INT 0x04 > - > -#define BM_CMD_START 0x01 > -#define BM_CMD_READ 0x08 > - > -typedef struct BMDMAState { > - IDEDMA dma; > - uint8_t cmd; > - uint8_t status; > - uint32_t addr; > - > - IDEBus *bus; > - /* current transfer state */ > - uint32_t cur_addr; > - uint32_t cur_prd_last; > - uint32_t cur_prd_addr; > - uint32_t cur_prd_len; > - BlockCompletionFunc *dma_cb; > - MemoryRegion addr_ioport; > - MemoryRegion extra_io; > - qemu_irq irq; > - > - /* Bit 0-2 and 7: BM status register > - * Bit 3-6: bus->error_status */ > - uint8_t migration_compat_status; > - uint8_t migration_retry_unit; > - int64_t migration_retry_sector_num; > - uint32_t migration_retry_nsector; > - > - struct PCIIDEState *pci_dev; > -} BMDMAState; > - > -typedef struct CMD646BAR { > - MemoryRegion cmd; > - MemoryRegion data; > - IDEBus *bus; > - struct PCIIDEState *pci_dev; > -} CMD646BAR; > - > -#define TYPE_PCI_IDE "pci-ide" > -#define PCI_IDE(obj) OBJECT_CHECK(PCIIDEState, (obj), TYPE_PCI_IDE) > - > -typedef struct PCIIDEState { > - /*< private >*/ > - PCIDevice parent_obj; > - /*< public >*/ > - > - IDEBus bus[2]; > - BMDMAState bmdma[2]; > - uint32_t secondary; /* used only for cmd646 */ > - MemoryRegion bmdma_bar; > - CMD646BAR cmd646_bar[2]; /* used only for cmd646 */ > -} PCIIDEState; > - > - > -static inline IDEState *bmdma_active_if(BMDMAState *bmdma) > -{ > - assert(bmdma->bus->retry_unit != (uint8_t)-1); > - return bmdma->bus->ifs + bmdma->bus->retry_unit; > -} > - > - > -void bmdma_init(IDEBus *bus, BMDMAState *bm, PCIIDEState *d); > -void bmdma_cmd_writeb(BMDMAState *bm, uint32_t val); > -extern MemoryRegionOps bmdma_addr_ioport_ops; > -void pci_ide_create_devs(PCIDevice *dev, DriveInfo **hd_table); > - > -extern const VMStateDescription vmstate_ide_pci; > -#endif > diff --git a/include/hw/ide/ahci.h b/include/hw/ide/ahci.h > new file mode 100644 > index 0000000..bc777ed > --- /dev/null > +++ b/include/hw/ide/ahci.h > @@ -0,0 +1,405 @@ > +/* > + * QEMU AHCI Emulation > + * > + * Copyright (c) 2010 qiaochong@loongson.cn > + * Copyright (c) 2010 Roland Elek <elek.roland@gmail.com> > + * Copyright (c) 2010 Sebastian Herbszt <herbszt@gmx.de> > + * Copyright (c) 2010 Alexander Graf <agraf@suse.de> > + * > + * This library is free software; you can redistribute it and/or > + * modify it under the terms of the GNU Lesser General Public > + * License as published by the Free Software Foundation; either > + * version 2 of the License, or (at your option) any later version. > + * > + * This library is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + * Lesser General Public License for more details. > + * > + * You should have received a copy of the GNU Lesser General Public > + * License along with this library; if not, see <http://www.gnu.org/licenses/>. > + * > + */ > + > +#ifndef HW_IDE_AHCI_H > +#define HW_IDE_AHCI_H > + > +#include <hw/sysbus.h> > + > +#define AHCI_MEM_BAR_SIZE 0x1000 > +#define AHCI_MAX_PORTS 32 > +#define AHCI_MAX_SG 168 /* hardware max is 64K */ > +#define AHCI_DMA_BOUNDARY 0xffffffff > +#define AHCI_USE_CLUSTERING 0 > +#define AHCI_MAX_CMDS 32 > +#define AHCI_CMD_SZ 32 > +#define AHCI_CMD_SLOT_SZ (AHCI_MAX_CMDS * AHCI_CMD_SZ) > +#define AHCI_RX_FIS_SZ 256 > +#define AHCI_CMD_TBL_CDB 0x40 > +#define AHCI_CMD_TBL_HDR_SZ 0x80 > +#define AHCI_CMD_TBL_SZ (AHCI_CMD_TBL_HDR_SZ + (AHCI_MAX_SG * 16)) > +#define AHCI_CMD_TBL_AR_SZ (AHCI_CMD_TBL_SZ * AHCI_MAX_CMDS) > +#define AHCI_PORT_PRIV_DMA_SZ (AHCI_CMD_SLOT_SZ + AHCI_CMD_TBL_AR_SZ + \ > + AHCI_RX_FIS_SZ) > + > +#define AHCI_IRQ_ON_SG (1U << 31) > +#define AHCI_CMD_ATAPI (1 << 5) > +#define AHCI_CMD_WRITE (1 << 6) > +#define AHCI_CMD_PREFETCH (1 << 7) > +#define AHCI_CMD_RESET (1 << 8) > +#define AHCI_CMD_CLR_BUSY (1 << 10) > + > +#define RX_FIS_D2H_REG 0x40 /* offset of D2H Register FIS data */ > +#define RX_FIS_SDB 0x58 /* offset of SDB FIS data */ > +#define RX_FIS_UNK 0x60 /* offset of Unknown FIS data */ > + > +/* global controller registers */ > +#define HOST_CAP 0x00 /* host capabilities */ > +#define HOST_CTL 0x04 /* global host control */ > +#define HOST_IRQ_STAT 0x08 /* interrupt status */ > +#define HOST_PORTS_IMPL 0x0c /* bitmap of implemented ports */ > +#define HOST_VERSION 0x10 /* AHCI spec. version compliancy */ > + > +/* HOST_CTL bits */ > +#define HOST_CTL_RESET (1 << 0) /* reset controller; self-clear */ > +#define HOST_CTL_IRQ_EN (1 << 1) /* global IRQ enable */ > +#define HOST_CTL_AHCI_EN (1U << 31) /* AHCI enabled */ > + > +/* HOST_CAP bits */ > +#define HOST_CAP_SSC (1 << 14) /* Slumber capable */ > +#define HOST_CAP_AHCI (1 << 18) /* AHCI only */ > +#define HOST_CAP_CLO (1 << 24) /* Command List Override support */ > +#define HOST_CAP_SSS (1 << 27) /* Staggered Spin-up */ > +#define HOST_CAP_NCQ (1 << 30) /* Native Command Queueing */ > +#define HOST_CAP_64 (1U << 31) /* PCI DAC (64-bit DMA) support */ > + > +/* registers for each SATA port */ > +#define PORT_LST_ADDR 0x00 /* command list DMA addr */ > +#define PORT_LST_ADDR_HI 0x04 /* command list DMA addr hi */ > +#define PORT_FIS_ADDR 0x08 /* FIS rx buf addr */ > +#define PORT_FIS_ADDR_HI 0x0c /* FIS rx buf addr hi */ > +#define PORT_IRQ_STAT 0x10 /* interrupt status */ > +#define PORT_IRQ_MASK 0x14 /* interrupt enable/disable mask */ > +#define PORT_CMD 0x18 /* port command */ > +#define PORT_TFDATA 0x20 /* taskfile data */ > +#define PORT_SIG 0x24 /* device TF signature */ > +#define PORT_SCR_STAT 0x28 /* SATA phy register: SStatus */ > +#define PORT_SCR_CTL 0x2c /* SATA phy register: SControl */ > +#define PORT_SCR_ERR 0x30 /* SATA phy register: SError */ > +#define PORT_SCR_ACT 0x34 /* SATA phy register: SActive */ > +#define PORT_CMD_ISSUE 0x38 /* command issue */ > +#define PORT_RESERVED 0x3c /* reserved */ > + > +/* PORT_IRQ_{STAT,MASK} bits */ > +#define PORT_IRQ_COLD_PRES (1U << 31) /* cold presence detect */ > +#define PORT_IRQ_TF_ERR (1 << 30) /* task file error */ > +#define PORT_IRQ_HBUS_ERR (1 << 29) /* host bus fatal error */ > +#define PORT_IRQ_HBUS_DATA_ERR (1 << 28) /* host bus data error */ > +#define PORT_IRQ_IF_ERR (1 << 27) /* interface fatal error */ > +#define PORT_IRQ_IF_NONFATAL (1 << 26) /* interface non-fatal error */ > +#define PORT_IRQ_OVERFLOW (1 << 24) /* xfer exhausted available S/G */ > +#define PORT_IRQ_BAD_PMP (1 << 23) /* incorrect port multiplier */ > + > +#define PORT_IRQ_PHYRDY (1 << 22) /* PhyRdy changed */ > +#define PORT_IRQ_DEV_ILCK (1 << 7) /* device interlock */ > +#define PORT_IRQ_CONNECT (1 << 6) /* port connect change status */ > +#define PORT_IRQ_SG_DONE (1 << 5) /* descriptor processed */ > +#define PORT_IRQ_UNK_FIS (1 << 4) /* unknown FIS rx'd */ > +#define PORT_IRQ_SDB_FIS (1 << 3) /* Set Device Bits FIS rx'd */ > +#define PORT_IRQ_DMAS_FIS (1 << 2) /* DMA Setup FIS rx'd */ > +#define PORT_IRQ_PIOS_FIS (1 << 1) /* PIO Setup FIS rx'd */ > +#define PORT_IRQ_D2H_REG_FIS (1 << 0) /* D2H Register FIS rx'd */ > + > +#define PORT_IRQ_FREEZE (PORT_IRQ_HBUS_ERR | PORT_IRQ_IF_ERR | \ > + PORT_IRQ_CONNECT | PORT_IRQ_PHYRDY | \ > + PORT_IRQ_UNK_FIS) > +#define PORT_IRQ_ERROR (PORT_IRQ_FREEZE | PORT_IRQ_TF_ERR | \ > + PORT_IRQ_HBUS_DATA_ERR) > +#define DEF_PORT_IRQ (PORT_IRQ_ERROR | PORT_IRQ_SG_DONE | \ > + PORT_IRQ_SDB_FIS | PORT_IRQ_DMAS_FIS | \ > + PORT_IRQ_PIOS_FIS | PORT_IRQ_D2H_REG_FIS) > + > +/* PORT_CMD bits */ > +#define PORT_CMD_ATAPI (1 << 24) /* Device is ATAPI */ > +#define PORT_CMD_LIST_ON (1 << 15) /* cmd list DMA engine running */ > +#define PORT_CMD_FIS_ON (1 << 14) /* FIS DMA engine running */ > +#define PORT_CMD_FIS_RX (1 << 4) /* Enable FIS receive DMA engine */ > +#define PORT_CMD_CLO (1 << 3) /* Command list override */ > +#define PORT_CMD_POWER_ON (1 << 2) /* Power up device */ > +#define PORT_CMD_SPIN_UP (1 << 1) /* Spin up device */ > +#define PORT_CMD_START (1 << 0) /* Enable port DMA engine */ > + > +#define PORT_CMD_ICC_MASK (0xfU << 28) /* i/f ICC state mask */ > +#define PORT_CMD_ICC_ACTIVE (0x1 << 28) /* Put i/f in active state */ > +#define PORT_CMD_ICC_PARTIAL (0x2 << 28) /* Put i/f in partial state */ > +#define PORT_CMD_ICC_SLUMBER (0x6 << 28) /* Put i/f in slumber state */ > + > +#define PORT_CMD_RO_MASK 0x007dffe0 /* Which CMD bits are read only? */ > + > +/* ap->flags bits */ > +#define AHCI_FLAG_NO_NCQ (1 << 24) > +#define AHCI_FLAG_IGN_IRQ_IF_ERR (1 << 25) /* ignore IRQ_IF_ERR */ > +#define AHCI_FLAG_HONOR_PI (1 << 26) /* honor PORTS_IMPL */ > +#define AHCI_FLAG_IGN_SERR_INTERNAL (1 << 27) /* ignore SERR_INTERNAL */ > +#define AHCI_FLAG_32BIT_ONLY (1 << 28) /* force 32bit */ > + > +#define ATA_SRST (1 << 2) /* software reset */ > + > +#define STATE_RUN 0 > +#define STATE_RESET 1 > + > +#define SATA_SCR_SSTATUS_DET_NODEV 0x0 > +#define SATA_SCR_SSTATUS_DET_DEV_PRESENT_PHY_UP 0x3 > + > +#define SATA_SCR_SSTATUS_SPD_NODEV 0x00 > +#define SATA_SCR_SSTATUS_SPD_GEN1 0x10 > + > +#define SATA_SCR_SSTATUS_IPM_NODEV 0x000 > +#define SATA_SCR_SSTATUS_IPM_ACTIVE 0X100 > + > +#define AHCI_SCR_SCTL_DET 0xf > + > +#define SATA_FIS_TYPE_REGISTER_H2D 0x27 > +#define SATA_FIS_REG_H2D_UPDATE_COMMAND_REGISTER 0x80 > +#define SATA_FIS_TYPE_REGISTER_D2H 0x34 > +#define SATA_FIS_TYPE_PIO_SETUP 0x5f > +#define SATA_FIS_TYPE_SDB 0xA1 > + > +#define AHCI_CMD_HDR_CMD_FIS_LEN 0x1f > +#define AHCI_CMD_HDR_PRDT_LEN 16 > + > +#define SATA_SIGNATURE_CDROM 0xeb140101 > +#define SATA_SIGNATURE_DISK 0x00000101 > + > +#define AHCI_GENERIC_HOST_CONTROL_REGS_MAX_ADDR 0x20 > + /* Shouldn't this be 0x2c? */ > + > +#define AHCI_PORT_REGS_START_ADDR 0x100 > +#define AHCI_PORT_ADDR_OFFSET_MASK 0x7f > +#define AHCI_PORT_ADDR_OFFSET_LEN 0x80 > + > +#define AHCI_NUM_COMMAND_SLOTS 31 > +#define AHCI_SUPPORTED_SPEED 20 > +#define AHCI_SUPPORTED_SPEED_GEN1 1 > +#define AHCI_VERSION_1_0 0x10000 > + > +#define AHCI_PROGMODE_MAJOR_REV_1 1 > + > +#define AHCI_COMMAND_TABLE_ACMD 0x40 > + > +#define AHCI_PRDT_SIZE_MASK 0x3fffff > + > +#define IDE_FEATURE_DMA 1 > + > +#define READ_FPDMA_QUEUED 0x60 > +#define WRITE_FPDMA_QUEUED 0x61 > +#define NCQ_NON_DATA 0x63 > +#define RECEIVE_FPDMA_QUEUED 0x65 > +#define SEND_FPDMA_QUEUED 0x64 > + > +#define NCQ_FIS_FUA_MASK 0x80 > +#define NCQ_FIS_RARC_MASK 0x01 > + > +#define RES_FIS_DSFIS 0x00 > +#define RES_FIS_PSFIS 0x20 > +#define RES_FIS_RFIS 0x40 > +#define RES_FIS_SDBFIS 0x58 > +#define RES_FIS_UFIS 0x60 > + > +#define SATA_CAP_SIZE 0x8 > +#define SATA_CAP_REV 0x2 > +#define SATA_CAP_BAR 0x4 > + > +typedef struct AHCIControlRegs { > + uint32_t cap; > + uint32_t ghc; > + uint32_t irqstatus; > + uint32_t impl; > + uint32_t version; > +} AHCIControlRegs; > + > +typedef struct AHCIPortRegs { > + uint32_t lst_addr; > + uint32_t lst_addr_hi; > + uint32_t fis_addr; > + uint32_t fis_addr_hi; > + uint32_t irq_stat; > + uint32_t irq_mask; > + uint32_t cmd; > + uint32_t unused0; > + uint32_t tfdata; > + uint32_t sig; > + uint32_t scr_stat; > + uint32_t scr_ctl; > + uint32_t scr_err; > + uint32_t scr_act; > + uint32_t cmd_issue; > + uint32_t reserved; > +} AHCIPortRegs; > + > +typedef struct AHCICmdHdr { > + uint16_t opts; > + uint16_t prdtl; > + uint32_t status; > + uint64_t tbl_addr; > + uint32_t reserved[4]; > +} QEMU_PACKED AHCICmdHdr; > + > +typedef struct AHCI_SG { > + uint64_t addr; > + uint32_t reserved; > + uint32_t flags_size; > +} QEMU_PACKED AHCI_SG; > + > +typedef struct AHCIDevice AHCIDevice; > + > +typedef struct NCQTransferState { > + AHCIDevice *drive; > + BlockAIOCB *aiocb; > + AHCICmdHdr *cmdh; > + QEMUSGList sglist; > + BlockAcctCookie acct; > + uint32_t sector_count; > + uint64_t lba; > + uint8_t tag; > + uint8_t cmd; > + uint8_t slot; > + bool used; > + bool halt; > +} NCQTransferState; > + > +struct AHCIDevice { > + IDEDMA dma; > + IDEBus port; > + int port_no; > + uint32_t port_state; > + uint32_t finished; > + AHCIPortRegs port_regs; > + struct AHCIState *hba; > + QEMUBH *check_bh; > + uint8_t *lst; > + uint8_t *res_fis; > + bool done_atapi_packet; > + int32_t busy_slot; > + bool init_d2h_sent; > + AHCICmdHdr *cur_cmd; > + NCQTransferState ncq_tfs[AHCI_MAX_CMDS]; > +}; > + > +typedef struct AHCIState { > + DeviceState *container; > + > + AHCIDevice *dev; > + AHCIControlRegs control_regs; > + MemoryRegion mem; > + MemoryRegion idp; /* Index-Data Pair I/O port space */ > + unsigned idp_offset; /* Offset of index in I/O port space */ > + uint32_t idp_index; /* Current IDP index */ > + int32_t ports; > + qemu_irq irq; > + AddressSpace *as; > +} AHCIState; > + > +typedef struct AHCIPCIState { > + /*< private >*/ > + PCIDevice parent_obj; > + /*< public >*/ > + > + AHCIState ahci; > +} AHCIPCIState; > + > +#define TYPE_ICH9_AHCI "ich9-ahci" > + > +#define ICH_AHCI(obj) \ > + OBJECT_CHECK(AHCIPCIState, (obj), TYPE_ICH9_AHCI) > + > +extern const VMStateDescription vmstate_ahci; > + > +#define VMSTATE_AHCI(_field, _state) { \ > + .name = (stringify(_field)), \ > + .size = sizeof(AHCIState), \ > + .vmsd = &vmstate_ahci, \ > + .flags = VMS_STRUCT, \ > + .offset = vmstate_offset_value(_state, _field, AHCIState), \ > +} > + > +/** > + * NCQFrame is the same as a Register H2D FIS (described in SATA 3.2), > + * but some fields have been re-mapped and re-purposed, as seen in > + * SATA 3.2 section 13.6.4.1 ("READ FPDMA QUEUED") > + * > + * cmd_fis[3], feature 7:0, becomes sector count 7:0. > + * cmd_fis[7], device 7:0, uses bit 7 as the Force Unit Access bit. > + * cmd_fis[11], feature 15:8, becomes sector count 15:8. > + * cmd_fis[12], count 7:0, becomes the NCQ TAG (7:3) and RARC bit (0) > + * cmd_fis[13], count 15:8, becomes the priority value (7:6) > + * bytes 16-19 become an le32 "auxiliary" field. > + */ > +typedef struct NCQFrame { > + uint8_t fis_type; > + uint8_t c; > + uint8_t command; > + uint8_t sector_count_low; /* (feature 7:0) */ > + uint8_t lba0; > + uint8_t lba1; > + uint8_t lba2; > + uint8_t fua; /* (device 7:0) */ > + uint8_t lba3; > + uint8_t lba4; > + uint8_t lba5; > + uint8_t sector_count_high; /* (feature 15:8) */ > + uint8_t tag; /* (count 0:7) */ > + uint8_t prio; /* (count 15:8) */ > + uint8_t icc; > + uint8_t control; > + uint8_t aux0; > + uint8_t aux1; > + uint8_t aux2; > + uint8_t aux3; > +} QEMU_PACKED NCQFrame; > + > +typedef struct SDBFIS { > + uint8_t type; > + uint8_t flags; > + uint8_t status; > + uint8_t error; > + uint32_t payload; > +} QEMU_PACKED SDBFIS; > + > +void ahci_realize(AHCIState *s, DeviceState *qdev, AddressSpace *as, int ports); > +void ahci_init(AHCIState *s, DeviceState *qdev); > +void ahci_uninit(AHCIState *s); > + > +void ahci_reset(AHCIState *s); > + > +void ahci_ide_create_devs(PCIDevice *dev, DriveInfo **hd); > + > +#define TYPE_SYSBUS_AHCI "sysbus-ahci" > +#define SYSBUS_AHCI(obj) OBJECT_CHECK(SysbusAHCIState, (obj), TYPE_SYSBUS_AHCI) > + > +typedef struct SysbusAHCIState { > + /*< private >*/ > + SysBusDevice parent_obj; > + /*< public >*/ > + > + AHCIState ahci; > + uint32_t num_ports; > +} SysbusAHCIState; > + > +#define TYPE_ALLWINNER_AHCI "allwinner-ahci" > +#define ALLWINNER_AHCI(obj) OBJECT_CHECK(AllwinnerAHCIState, (obj), \ > + TYPE_ALLWINNER_AHCI) > + > +#define ALLWINNER_AHCI_MMIO_OFF 0x80 > +#define ALLWINNER_AHCI_MMIO_SIZE 0x80 > + > +struct AllwinnerAHCIState { > + /*< private >*/ > + SysbusAHCIState parent_obj; > + /*< public >*/ > + > + MemoryRegion mmio; > + uint32_t regs[ALLWINNER_AHCI_MMIO_SIZE/4]; > +}; > + > +#endif /* HW_IDE_AHCI_H */ > diff --git a/include/hw/ide/internal.h b/include/hw/ide/internal.h > new file mode 100644 > index 0000000..773928a > --- /dev/null > +++ b/include/hw/ide/internal.h > @@ -0,0 +1,635 @@ > +#ifndef HW_IDE_INTERNAL_H > +#define HW_IDE_INTERNAL_H > + > +/* > + * QEMU IDE Emulation -- internal header file > + * only files in hw/ide/ are supposed to include this file. > + * non-internal declarations are in hw/ide.h > + */ > +#include <hw/ide.h> > +#include <hw/isa/isa.h> > +#include "sysemu/dma.h" > +#include "sysemu/sysemu.h" > +#include "hw/block/block.h" > +#include "block/scsi.h" > + > +/* debug IDE devices */ > +//#define DEBUG_IDE > +//#define DEBUG_IDE_ATAPI > +//#define DEBUG_AIO > +#define USE_DMA_CDROM > + > +typedef struct IDEBus IDEBus; > +typedef struct IDEDevice IDEDevice; > +typedef struct IDEState IDEState; > +typedef struct IDEDMA IDEDMA; > +typedef struct IDEDMAOps IDEDMAOps; > + > +#define TYPE_IDE_BUS "IDE" > +#define IDE_BUS(obj) OBJECT_CHECK(IDEBus, (obj), TYPE_IDE_BUS) > + > +/* Bits of HD_STATUS */ > +#define ERR_STAT 0x01 > +#define INDEX_STAT 0x02 > +#define ECC_STAT 0x04 /* Corrected error */ > +#define DRQ_STAT 0x08 > +#define SEEK_STAT 0x10 > +#define SRV_STAT 0x10 > +#define WRERR_STAT 0x20 > +#define READY_STAT 0x40 > +#define BUSY_STAT 0x80 > + > +/* Bits for HD_ERROR */ > +#define MARK_ERR 0x01 /* Bad address mark */ > +#define TRK0_ERR 0x02 /* couldn't find track 0 */ > +#define ABRT_ERR 0x04 /* Command aborted */ > +#define MCR_ERR 0x08 /* media change request */ > +#define ID_ERR 0x10 /* ID field not found */ > +#define MC_ERR 0x20 /* media changed */ > +#define ECC_ERR 0x40 /* Uncorrectable ECC error */ > +#define BBD_ERR 0x80 /* pre-EIDE meaning: block marked bad */ > +#define ICRC_ERR 0x80 /* new meaning: CRC error during transfer */ > + > +/* Bits of HD_NSECTOR */ > +#define CD 0x01 > +#define IO 0x02 > +#define REL 0x04 > +#define TAG_MASK 0xf8 > + > +#define IDE_CMD_RESET 0x04 > +#define IDE_CMD_DISABLE_IRQ 0x02 > + > +/* ACS-2 T13/2015-D Table B.2 Command codes */ > +#define WIN_NOP 0x00 > +/* reserved 0x01..0x02 */ > +#define CFA_REQ_EXT_ERROR_CODE 0x03 /* CFA Request Extended Error Code */ > +/* reserved 0x04..0x05 */ > +#define WIN_DSM 0x06 > +/* reserved 0x07 */ > +#define WIN_DEVICE_RESET 0x08 > +/* reserved 0x09..0x0a */ > +/* REQUEST SENSE DATA EXT 0x0B */ > +/* reserved 0x0C..0x0F */ > +#define WIN_RECAL 0x10 /* obsolete since ATA4 */ > +/* obsolete since ATA3, retired in ATA4 0x11..0x1F */ > +#define WIN_READ 0x20 /* 28-Bit */ > +#define WIN_READ_ONCE 0x21 /* 28-Bit w/o retries, obsolete since ATA5 */ > +/* obsolete since ATA4 0x22..0x23 */ > +#define WIN_READ_EXT 0x24 /* 48-Bit */ > +#define WIN_READDMA_EXT 0x25 /* 48-Bit */ > +#define WIN_READDMA_QUEUED_EXT 0x26 /* 48-Bit, obsolete since ACS2 */ > +#define WIN_READ_NATIVE_MAX_EXT 0x27 /* 48-Bit */ > +/* reserved 0x28 */ > +#define WIN_MULTREAD_EXT 0x29 /* 48-Bit */ > +/* READ STREAM DMA EXT 0x2A */ > +/* READ STREAM EXT 0x2B */ > +/* reserved 0x2C..0x2E */ > +/* READ LOG EXT 0x2F */ > +#define WIN_WRITE 0x30 /* 28-Bit */ > +#define WIN_WRITE_ONCE 0x31 /* 28-Bit w/o retries, obsolete since ATA5 */ > +/* obsolete since ATA4 0x32..0x33 */ > +#define WIN_WRITE_EXT 0x34 /* 48-Bit */ > +#define WIN_WRITEDMA_EXT 0x35 /* 48-Bit */ > +#define WIN_WRITEDMA_QUEUED_EXT 0x36 /* 48-Bit */ > +#define WIN_SET_MAX_EXT 0x37 /* 48-Bit, obsolete since ACS2 */ > +#define WIN_SET_MAX_EXT 0x37 /* 48-Bit */ > +#define CFA_WRITE_SECT_WO_ERASE 0x38 /* CFA Write Sectors without erase */ > +#define WIN_MULTWRITE_EXT 0x39 /* 48-Bit */ > +/* WRITE STREAM DMA EXT 0x3A */ > +/* WRITE STREAM EXT 0x3B */ > +#define WIN_WRITE_VERIFY 0x3C /* 28-Bit, obsolete since ATA4 */ > +/* WRITE DMA FUA EXT 0x3D */ > +/* obsolete since ACS2 0x3E */ > +/* WRITE LOG EXT 0x3F */ > +#define WIN_VERIFY 0x40 /* 28-Bit - Read Verify Sectors */ > +#define WIN_VERIFY_ONCE 0x41 /* 28-Bit - w/o retries, obsolete since ATA5 */ > +#define WIN_VERIFY_EXT 0x42 /* 48-Bit */ > +/* reserved 0x43..0x44 */ > +/* WRITE UNCORRECTABLE EXT 0x45 */ > +/* reserved 0x46 */ > +/* READ LOG DMA EXT 0x47 */ > +/* reserved 0x48..0x4F */ > +/* obsolete since ATA4 0x50 */ > +/* CONFIGURE STREAM 0x51 */ > +/* reserved 0x52..0x56 */ > +/* WRITE LOG DMA EXT 0x57 */ > +/* reserved 0x58..0x5A */ > +/* TRUSTED NON DATA 0x5B */ > +/* TRUSTED RECEIVE 0x5C */ > +/* TRUSTED RECEIVE DMA 0x5D */ > +/* TRUSTED SEND 0x5E */ > +/* TRUSTED SEND DMA 0x5F */ > +/* READ FPDMA QUEUED 0x60 */ > +/* WRITE FPDMA QUEUED 0x61 */ > +/* reserved 0x62->0x6F */ > +#define WIN_SEEK 0x70 /* obsolete since ATA7 */ > +/* reserved 0x71-0x7F */ > +/* vendor specific 0x80-0x86 */ > +#define CFA_TRANSLATE_SECTOR 0x87 /* CFA Translate Sector */ > +/* vendor specific 0x88-0x8F */ > +#define WIN_DIAGNOSE 0x90 > +#define WIN_SPECIFY 0x91 /* set drive geometry translation, obsolete since ATA6 */ > +#define WIN_DOWNLOAD_MICROCODE 0x92 > +/* DOWNLOAD MICROCODE DMA 0x93 */ > +#define WIN_STANDBYNOW2 0x94 /* retired in ATA4 */ > +#define WIN_IDLEIMMEDIATE2 0x95 /* force drive to become "ready", retired in ATA4 */ > +#define WIN_STANDBY2 0x96 /* retired in ATA4 */ > +#define WIN_SETIDLE2 0x97 /* retired in ATA4 */ > +#define WIN_CHECKPOWERMODE2 0x98 /* retired in ATA4 */ > +#define WIN_SLEEPNOW2 0x99 /* retired in ATA4 */ > +/* vendor specific 0x9A */ > +/* reserved 0x9B..0x9F */ > +#define WIN_PACKETCMD 0xA0 /* Send a packet command. */ > +#define WIN_PIDENTIFY 0xA1 /* identify ATAPI device */ > +#define WIN_QUEUED_SERVICE 0xA2 /* obsolete since ACS2 */ > +/* reserved 0xA3..0xAF */ > +#define WIN_SMART 0xB0 /* self-monitoring and reporting */ > +/* Device Configuration Overlay 0xB1 */ > +/* reserved 0xB2..0xB3 */ > +/* Sanitize Device 0xB4 */ > +/* reserved 0xB5 */ > +/* NV Cache 0xB6 */ > +/* reserved for CFA 0xB7..0xBB */ > +#define CFA_ACCESS_METADATA_STORAGE 0xB8 > +/* reserved 0xBC..0xBF */ > +#define CFA_ERASE_SECTORS 0xC0 /* microdrives implement as NOP */ > +/* vendor specific 0xC1..0xC3 */ > +#define WIN_MULTREAD 0xC4 /* read sectors using multiple mode*/ > +#define WIN_MULTWRITE 0xC5 /* write sectors using multiple mode */ > +#define WIN_SETMULT 0xC6 /* enable/disable multiple mode */ > +#define WIN_READDMA_QUEUED 0xC7 /* read sectors using Queued DMA transfers, obsolete since ACS2 */ > +#define WIN_READDMA 0xC8 /* read sectors using DMA transfers */ > +#define WIN_READDMA_ONCE 0xC9 /* 28-Bit - w/o retries, obsolete since ATA5 */ > +#define WIN_WRITEDMA 0xCA /* write sectors using DMA transfers */ > +#define WIN_WRITEDMA_ONCE 0xCB /* 28-Bit - w/o retries, obsolete since ATA5 */ > +#define WIN_WRITEDMA_QUEUED 0xCC /* write sectors using Queued DMA transfers, obsolete since ACS2 */ > +#define CFA_WRITE_MULTI_WO_ERASE 0xCD /* CFA Write multiple without erase */ > +/* WRITE MULTIPLE FUA EXT 0xCE */ > +/* reserved 0xCF..0xDO */ > +/* CHECK MEDIA CARD TYPE 0xD1 */ > +/* reserved for media card pass through 0xD2..0xD4 */ > +/* reserved 0xD5..0xD9 */ > +#define WIN_GETMEDIASTATUS 0xDA /* obsolete since ATA8 */ > +/* obsolete since ATA3, retired in ATA4 0xDB..0xDD */ > +#define WIN_DOORLOCK 0xDE /* lock door on removable drives, obsolete since ATA8 */ > +#define WIN_DOORUNLOCK 0xDF /* unlock door on removable drives, obsolete since ATA8 */ > +#define WIN_STANDBYNOW1 0xE0 > +#define WIN_IDLEIMMEDIATE 0xE1 /* force drive to become "ready" */ > +#define WIN_STANDBY 0xE2 /* Set device in Standby Mode */ > +#define WIN_SETIDLE1 0xE3 > +#define WIN_READ_BUFFER 0xE4 /* force read only 1 sector */ > +#define WIN_CHECKPOWERMODE1 0xE5 > +#define WIN_SLEEPNOW1 0xE6 > +#define WIN_FLUSH_CACHE 0xE7 > +#define WIN_WRITE_BUFFER 0xE8 /* force write only 1 sector */ > +/* READ BUFFER DMA 0xE9 */ > +#define WIN_FLUSH_CACHE_EXT 0xEA /* 48-Bit */ > +/* WRITE BUFFER DMA 0xEB */ > +#define WIN_IDENTIFY 0xEC /* ask drive to identify itself */ > +#define WIN_MEDIAEJECT 0xED /* obsolete since ATA8 */ > +/* obsolete since ATA4 0xEE */ > +#define WIN_SETFEATURES 0xEF /* set special drive features */ > +#define IBM_SENSE_CONDITION 0xF0 /* measure disk temperature, vendor specific */ > +#define WIN_SECURITY_SET_PASS 0xF1 > +#define WIN_SECURITY_UNLOCK 0xF2 > +#define WIN_SECURITY_ERASE_PREPARE 0xF3 > +#define WIN_SECURITY_ERASE_UNIT 0xF4 > +#define WIN_SECURITY_FREEZE_LOCK 0xF5 > +#define CFA_WEAR_LEVEL 0xF5 /* microdrives implement as NOP; not specified in T13! */ > +#define WIN_SECURITY_DISABLE 0xF6 > +/* vendor specific 0xF7 */ > +#define WIN_READ_NATIVE_MAX 0xF8 /* return the native maximum address */ > +#define WIN_SET_MAX 0xF9 > +/* vendor specific 0xFA..0xFF */ > + > +/* set to 1 set disable mult support */ > +#define MAX_MULT_SECTORS 16 > + > +#define IDE_DMA_BUF_SECTORS 256 > + > +/* feature values for Data Set Management */ > +#define DSM_TRIM 0x01 > + > +#if (IDE_DMA_BUF_SECTORS < MAX_MULT_SECTORS) > +#error "IDE_DMA_BUF_SECTORS must be bigger or equal to MAX_MULT_SECTORS" > +#endif > + > +/* ATAPI defines */ > + > +#define ATAPI_PACKET_SIZE 12 > + > +/* The generic packet command opcodes for CD/DVD Logical Units, > + * From Table 57 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */ > +#define GPCMD_BLANK 0xa1 > +#define GPCMD_CLOSE_TRACK 0x5b > +#define GPCMD_FLUSH_CACHE 0x35 > +#define GPCMD_FORMAT_UNIT 0x04 > +#define GPCMD_GET_CONFIGURATION 0x46 > +#define GPCMD_GET_EVENT_STATUS_NOTIFICATION 0x4a > +#define GPCMD_GET_PERFORMANCE 0xac > +#define GPCMD_INQUIRY 0x12 > +#define GPCMD_LOAD_UNLOAD 0xa6 > +#define GPCMD_MECHANISM_STATUS 0xbd > +#define GPCMD_MODE_SELECT_10 0x55 > +#define GPCMD_MODE_SENSE_10 0x5a > +#define GPCMD_PAUSE_RESUME 0x4b > +#define GPCMD_PLAY_AUDIO_10 0x45 > +#define GPCMD_PLAY_AUDIO_MSF 0x47 > +#define GPCMD_PLAY_AUDIO_TI 0x48 > +#define GPCMD_PLAY_CD 0xbc > +#define GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1e > +#define GPCMD_READ_10 0x28 > +#define GPCMD_READ_12 0xa8 > +#define GPCMD_READ_CDVD_CAPACITY 0x25 > +#define GPCMD_READ_CD 0xbe > +#define GPCMD_READ_CD_MSF 0xb9 > +#define GPCMD_READ_DISC_INFO 0x51 > +#define GPCMD_READ_DVD_STRUCTURE 0xad > +#define GPCMD_READ_FORMAT_CAPACITIES 0x23 > +#define GPCMD_READ_HEADER 0x44 > +#define GPCMD_READ_TRACK_RZONE_INFO 0x52 > +#define GPCMD_READ_SUBCHANNEL 0x42 > +#define GPCMD_READ_TOC_PMA_ATIP 0x43 > +#define GPCMD_REPAIR_RZONE_TRACK 0x58 > +#define GPCMD_REPORT_KEY 0xa4 > +#define GPCMD_REQUEST_SENSE 0x03 > +#define GPCMD_RESERVE_RZONE_TRACK 0x53 > +#define GPCMD_SCAN 0xba > +#define GPCMD_SEEK 0x2b > +#define GPCMD_SEND_DVD_STRUCTURE 0xad > +#define GPCMD_SEND_EVENT 0xa2 > +#define GPCMD_SEND_KEY 0xa3 > +#define GPCMD_SEND_OPC 0x54 > +#define GPCMD_SET_READ_AHEAD 0xa7 > +#define GPCMD_SET_STREAMING 0xb6 > +#define GPCMD_START_STOP_UNIT 0x1b > +#define GPCMD_STOP_PLAY_SCAN 0x4e > +#define GPCMD_TEST_UNIT_READY 0x00 > +#define GPCMD_VERIFY_10 0x2f > +#define GPCMD_WRITE_10 0x2a > +#define GPCMD_WRITE_AND_VERIFY_10 0x2e > +/* This is listed as optional in ATAPI 2.6, but is (curiously) > + * missing from Mt. Fuji, Table 57. It _is_ mentioned in Mt. Fuji > + * Table 377 as an MMC command for SCSi devices though... Most ATAPI > + * drives support it. */ > +#define GPCMD_SET_SPEED 0xbb > +/* This seems to be a SCSI specific CD-ROM opcode > + * to play data at track/index */ > +#define GPCMD_PLAYAUDIO_TI 0x48 > +/* > + * From MS Media Status Notification Support Specification. For > + * older drives only. > + */ > +#define GPCMD_GET_MEDIA_STATUS 0xda > +#define GPCMD_MODE_SENSE_6 0x1a > + > +#define ATAPI_INT_REASON_CD 0x01 /* 0 = data transfer */ > +#define ATAPI_INT_REASON_IO 0x02 /* 1 = transfer to the host */ > +#define ATAPI_INT_REASON_REL 0x04 > +#define ATAPI_INT_REASON_TAG 0xf8 > + > +/* same constants as bochs */ > +#define ASC_NO_SEEK_COMPLETE 0x02 > +#define ASC_ILLEGAL_OPCODE 0x20 > +#define ASC_LOGICAL_BLOCK_OOR 0x21 > +#define ASC_INV_FIELD_IN_CMD_PACKET 0x24 > +#define ASC_MEDIUM_MAY_HAVE_CHANGED 0x28 > +#define ASC_INCOMPATIBLE_FORMAT 0x30 > +#define ASC_MEDIUM_NOT_PRESENT 0x3a > +#define ASC_SAVING_PARAMETERS_NOT_SUPPORTED 0x39 > +#define ASC_DATA_PHASE_ERROR 0x4b > +#define ASC_MEDIA_REMOVAL_PREVENTED 0x53 > + > +#define CFA_NO_ERROR 0x00 > +#define CFA_MISC_ERROR 0x09 > +#define CFA_INVALID_COMMAND 0x20 > +#define CFA_INVALID_ADDRESS 0x21 > +#define CFA_ADDRESS_OVERFLOW 0x2f > + > +#define SMART_READ_DATA 0xd0 > +#define SMART_READ_THRESH 0xd1 > +#define SMART_ATTR_AUTOSAVE 0xd2 > +#define SMART_SAVE_ATTR 0xd3 > +#define SMART_EXECUTE_OFFLINE 0xd4 > +#define SMART_READ_LOG 0xd5 > +#define SMART_WRITE_LOG 0xd6 > +#define SMART_ENABLE 0xd8 > +#define SMART_DISABLE 0xd9 > +#define SMART_STATUS 0xda > + > +typedef enum { IDE_HD, IDE_CD, IDE_CFATA } IDEDriveKind; > + > +typedef void EndTransferFunc(IDEState *); > + > +typedef void DMAStartFunc(IDEDMA *, IDEState *, BlockCompletionFunc *); > +typedef void DMAVoidFunc(IDEDMA *); > +typedef int DMAIntFunc(IDEDMA *, int); > +typedef int32_t DMAInt32Func(IDEDMA *, int32_t len); > +typedef void DMAu32Func(IDEDMA *, uint32_t); > +typedef void DMAStopFunc(IDEDMA *, bool); > +typedef void DMARestartFunc(void *, int, RunState); > + > +struct unreported_events { > + bool eject_request; > + bool new_media; > +}; > + > +enum ide_dma_cmd { > + IDE_DMA_READ, > + IDE_DMA_WRITE, > + IDE_DMA_TRIM, > + IDE_DMA_ATAPI, > +}; > + > +#define ide_cmd_is_read(s) \ > + ((s)->dma_cmd == IDE_DMA_READ) > + > +typedef struct IDEBufferedRequest { > + QLIST_ENTRY(IDEBufferedRequest) list; > + struct iovec iov; > + QEMUIOVector qiov; > + QEMUIOVector *original_qiov; > + BlockCompletionFunc *original_cb; > + void *original_opaque; > + bool orphaned; > +} IDEBufferedRequest; > + > +/* NOTE: IDEState represents in fact one drive */ > +struct IDEState { > + IDEBus *bus; > + uint8_t unit; > + /* ide config */ > + IDEDriveKind drive_kind; > + int cylinders, heads, sectors, chs_trans; > + int64_t nb_sectors; > + int mult_sectors; > + int identify_set; > + uint8_t identify_data[512]; > + int drive_serial; > + char drive_serial_str[21]; > + char drive_model_str[41]; > + uint64_t wwn; > + /* ide regs */ > + uint8_t feature; > + uint8_t error; > + uint32_t nsector; > + uint8_t sector; > + uint8_t lcyl; > + uint8_t hcyl; > + /* other part of tf for lba48 support */ > + uint8_t hob_feature; > + uint8_t hob_nsector; > + uint8_t hob_sector; > + uint8_t hob_lcyl; > + uint8_t hob_hcyl; > + > + uint8_t select; > + uint8_t status; > + > + /* set for lba48 access */ > + uint8_t lba48; > + BlockBackend *blk; > + char version[9]; > + /* ATAPI specific */ > + struct unreported_events events; > + uint8_t sense_key; > + uint8_t asc; > + bool tray_open; > + bool tray_locked; > + uint8_t cdrom_changed; > + int packet_transfer_size; > + int elementary_transfer_size; > + int32_t io_buffer_index; > + int lba; > + int cd_sector_size; > + int atapi_dma; /* true if dma is requested for the packet cmd */ > + BlockAcctCookie acct; > + BlockAIOCB *pio_aiocb; > + struct iovec iov; > + QEMUIOVector qiov; > + QLIST_HEAD(, IDEBufferedRequest) buffered_requests; > + /* ATA DMA state */ > + uint64_t io_buffer_offset; > + int32_t io_buffer_size; > + QEMUSGList sg; > + /* PIO transfer handling */ > + int req_nb_sectors; /* number of sectors per interrupt */ > + EndTransferFunc *end_transfer_func; > + uint8_t *data_ptr; > + uint8_t *data_end; > + uint8_t *io_buffer; > + /* PIO save/restore */ > + int32_t io_buffer_total_len; > + int32_t cur_io_buffer_offset; > + int32_t cur_io_buffer_len; > + uint8_t end_transfer_fn_idx; > + QEMUTimer *sector_write_timer; /* only used for win2k install hack */ > + uint32_t irq_count; /* counts IRQs when using win2k install hack */ > + /* CF-ATA extended error */ > + uint8_t ext_error; > + /* CF-ATA metadata storage */ > + uint32_t mdata_size; > + uint8_t *mdata_storage; > + int media_changed; > + enum ide_dma_cmd dma_cmd; > + /* SMART */ > + uint8_t smart_enabled; > + uint8_t smart_autosave; > + int smart_errors; > + uint8_t smart_selftest_count; > + uint8_t *smart_selftest_data; > + /* AHCI */ > + int ncq_queues; > +}; > + > +struct IDEDMAOps { > + DMAStartFunc *start_dma; > + DMAVoidFunc *start_transfer; > + DMAInt32Func *prepare_buf; > + DMAu32Func *commit_buf; > + DMAIntFunc *rw_buf; > + DMAVoidFunc *restart; > + DMAVoidFunc *restart_dma; > + DMAStopFunc *set_inactive; > + DMAVoidFunc *cmd_done; > + DMAVoidFunc *reset; > +}; > + > +struct IDEDMA { > + const struct IDEDMAOps *ops; > + struct iovec iov; > + QEMUIOVector qiov; > + BlockAIOCB *aiocb; > +}; > + > +struct IDEBus { > + BusState qbus; > + IDEDevice *master; > + IDEDevice *slave; > + IDEState ifs[2]; > + QEMUBH *bh; > + > + int bus_id; > + int max_units; > + IDEDMA *dma; > + uint8_t unit; > + uint8_t cmd; > + qemu_irq irq; > + > + int error_status; > + uint8_t retry_unit; > + int64_t retry_sector_num; > + uint32_t retry_nsector; > +}; > + > +#define TYPE_IDE_DEVICE "ide-device" > +#define IDE_DEVICE(obj) \ > + OBJECT_CHECK(IDEDevice, (obj), TYPE_IDE_DEVICE) > +#define IDE_DEVICE_CLASS(klass) \ > + OBJECT_CLASS_CHECK(IDEDeviceClass, (klass), TYPE_IDE_DEVICE) > +#define IDE_DEVICE_GET_CLASS(obj) \ > + OBJECT_GET_CLASS(IDEDeviceClass, (obj), TYPE_IDE_DEVICE) > + > +typedef struct IDEDeviceClass { > + DeviceClass parent_class; > + int (*init)(IDEDevice *dev); > +} IDEDeviceClass; > + > +struct IDEDevice { > + DeviceState qdev; > + uint32_t unit; > + BlockConf conf; > + int chs_trans; > + char *version; > + char *serial; > + char *model; > + uint64_t wwn; > +}; > + > +/* These are used for the error_status field of IDEBus */ > +#define IDE_RETRY_MASK 0xf8 > +#define IDE_RETRY_DMA 0x08 > +#define IDE_RETRY_PIO 0x10 > +#define IDE_RETRY_ATAPI 0x20 /* reused IDE_RETRY_READ bit */ > +#define IDE_RETRY_READ 0x20 > +#define IDE_RETRY_FLUSH 0x40 > +#define IDE_RETRY_TRIM 0x80 > +#define IDE_RETRY_HBA 0x100 > + > +#define IS_IDE_RETRY_DMA(_status) \ > + ((_status) & IDE_RETRY_DMA) > + > +#define IS_IDE_RETRY_PIO(_status) \ > + ((_status) & IDE_RETRY_PIO) > + > +/* > + * The method of the IDE_RETRY_ATAPI determination is to use a previously > + * impossible bit combination as a new status value. > + */ > +#define IS_IDE_RETRY_ATAPI(_status) \ > + (((_status) & IDE_RETRY_MASK) == IDE_RETRY_ATAPI) > + > +static inline uint8_t ide_dma_cmd_to_retry(uint8_t dma_cmd) > +{ > + switch (dma_cmd) { > + case IDE_DMA_READ: > + return IDE_RETRY_DMA | IDE_RETRY_READ; > + case IDE_DMA_WRITE: > + return IDE_RETRY_DMA; > + case IDE_DMA_TRIM: > + return IDE_RETRY_DMA | IDE_RETRY_TRIM; > + case IDE_DMA_ATAPI: > + return IDE_RETRY_ATAPI; > + default: > + break; > + } > + return 0; > +} > + > +static inline IDEState *idebus_active_if(IDEBus *bus) > +{ > + return bus->ifs + bus->unit; > +} > + > +static inline void ide_set_irq(IDEBus *bus) > +{ > + if (!(bus->cmd & IDE_CMD_DISABLE_IRQ)) { > + qemu_irq_raise(bus->irq); > + } > +} > + > +/* hw/ide/core.c */ > +extern const VMStateDescription vmstate_ide_bus; > + > +#define VMSTATE_IDE_BUS(_field, _state) \ > + VMSTATE_STRUCT(_field, _state, 1, vmstate_ide_bus, IDEBus) > + > +#define VMSTATE_IDE_BUS_ARRAY(_field, _state, _num) \ > + VMSTATE_STRUCT_ARRAY(_field, _state, _num, 1, vmstate_ide_bus, IDEBus) > + > +extern const VMStateDescription vmstate_ide_drive; > + > +#define VMSTATE_IDE_DRIVES(_field, _state) \ > + VMSTATE_STRUCT_ARRAY(_field, _state, 2, 3, vmstate_ide_drive, IDEState) > + > +#define VMSTATE_IDE_DRIVE(_field, _state) \ > + VMSTATE_STRUCT(_field, _state, 1, vmstate_ide_drive, IDEState) > + > +void ide_bus_reset(IDEBus *bus); > +int64_t ide_get_sector(IDEState *s); > +void ide_set_sector(IDEState *s, int64_t sector_num); > + > +void ide_start_dma(IDEState *s, BlockCompletionFunc *cb); > +void dma_buf_commit(IDEState *s, uint32_t tx_bytes); > +void ide_dma_error(IDEState *s); > +void ide_abort_command(IDEState *s); > + > +void ide_atapi_cmd_ok(IDEState *s); > +void ide_atapi_cmd_error(IDEState *s, int sense_key, int asc); > +void ide_atapi_dma_restart(IDEState *s); > +void ide_atapi_io_error(IDEState *s, int ret); > + > +void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val); > +uint32_t ide_ioport_read(void *opaque, uint32_t addr1); > +uint32_t ide_status_read(void *opaque, uint32_t addr); > +void ide_cmd_write(void *opaque, uint32_t addr, uint32_t val); > +void ide_data_writew(void *opaque, uint32_t addr, uint32_t val); > +uint32_t ide_data_readw(void *opaque, uint32_t addr); > +void ide_data_writel(void *opaque, uint32_t addr, uint32_t val); > +uint32_t ide_data_readl(void *opaque, uint32_t addr); > + > +int ide_init_drive(IDEState *s, BlockBackend *blk, IDEDriveKind kind, > + const char *version, const char *serial, const char *model, > + uint64_t wwn, > + uint32_t cylinders, uint32_t heads, uint32_t secs, > + int chs_trans); > +void ide_init2(IDEBus *bus, qemu_irq irq); > +void ide_init_ioport(IDEBus *bus, ISADevice *isa, int iobase, int iobase2); > +void ide_register_restart_cb(IDEBus *bus); > + > +void ide_exec_cmd(IDEBus *bus, uint32_t val); > + > +void ide_transfer_start(IDEState *s, uint8_t *buf, int size, > + EndTransferFunc *end_transfer_func); > +void ide_transfer_stop(IDEState *s); > +void ide_set_inactive(IDEState *s, bool more); > +BlockAIOCB *ide_issue_trim( > + int64_t offset, QEMUIOVector *qiov, > + BlockCompletionFunc *cb, void *cb_opaque, void *opaque); > +BlockAIOCB *ide_buffered_readv(IDEState *s, int64_t sector_num, > + QEMUIOVector *iov, int nb_sectors, > + BlockCompletionFunc *cb, void *opaque); > +void ide_cancel_dma_sync(IDEState *s); > + > +/* hw/ide/atapi.c */ > +void ide_atapi_cmd(IDEState *s); > +void ide_atapi_cmd_reply_end(IDEState *s); > + > +/* hw/ide/qdev.c */ > +void ide_bus_new(IDEBus *idebus, size_t idebus_size, DeviceState *dev, > + int bus_id, int max_units); > +IDEDevice *ide_create_drive(IDEBus *bus, int unit, DriveInfo *drive); > + > +int ide_handle_rw_error(IDEState *s, int error, int op); > + > +#endif /* HW_IDE_INTERNAL_H */ > diff --git a/include/hw/ide/pci.h b/include/hw/ide/pci.h > new file mode 100644 > index 0000000..0f2d4b9 > --- /dev/null > +++ b/include/hw/ide/pci.h > @@ -0,0 +1,76 @@ > +#ifndef HW_IDE_PCI_H > +#define HW_IDE_PCI_H > + > +#include <hw/ide/internal.h> > + > +#define BM_STATUS_DMAING 0x01 > +#define BM_STATUS_ERROR 0x02 > +#define BM_STATUS_INT 0x04 > + > +#define BM_CMD_START 0x01 > +#define BM_CMD_READ 0x08 > + > +typedef struct BMDMAState { > + IDEDMA dma; > + uint8_t cmd; > + uint8_t status; > + uint32_t addr; > + > + IDEBus *bus; > + /* current transfer state */ > + uint32_t cur_addr; > + uint32_t cur_prd_last; > + uint32_t cur_prd_addr; > + uint32_t cur_prd_len; > + BlockCompletionFunc *dma_cb; > + MemoryRegion addr_ioport; > + MemoryRegion extra_io; > + qemu_irq irq; > + > + /* Bit 0-2 and 7: BM status register > + * Bit 3-6: bus->error_status */ > + uint8_t migration_compat_status; > + uint8_t migration_retry_unit; > + int64_t migration_retry_sector_num; > + uint32_t migration_retry_nsector; > + > + struct PCIIDEState *pci_dev; > +} BMDMAState; > + > +typedef struct CMD646BAR { > + MemoryRegion cmd; > + MemoryRegion data; > + IDEBus *bus; > + struct PCIIDEState *pci_dev; > +} CMD646BAR; > + > +#define TYPE_PCI_IDE "pci-ide" > +#define PCI_IDE(obj) OBJECT_CHECK(PCIIDEState, (obj), TYPE_PCI_IDE) > + > +typedef struct PCIIDEState { > + /*< private >*/ > + PCIDevice parent_obj; > + /*< public >*/ > + > + IDEBus bus[2]; > + BMDMAState bmdma[2]; > + uint32_t secondary; /* used only for cmd646 */ > + MemoryRegion bmdma_bar; > + CMD646BAR cmd646_bar[2]; /* used only for cmd646 */ > +} PCIIDEState; > + > + > +static inline IDEState *bmdma_active_if(BMDMAState *bmdma) > +{ > + assert(bmdma->bus->retry_unit != (uint8_t)-1); > + return bmdma->bus->ifs + bmdma->bus->retry_unit; > +} > + > + > +void bmdma_init(IDEBus *bus, BMDMAState *bm, PCIIDEState *d); > +void bmdma_cmd_writeb(BMDMAState *bm, uint32_t val); > +extern MemoryRegionOps bmdma_addr_ioport_ops; > +void pci_ide_create_devs(PCIDevice *dev, DriveInfo **hd_table); > + > +extern const VMStateDescription vmstate_ide_pci; > +#endif >
diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c index 502d4f1..b1a7b65 100644 --- a/hw/ide/ahci.c +++ b/hw/ide/ahci.c @@ -30,7 +30,7 @@ #include "qemu/error-report.h" #include "sysemu/block-backend.h" #include "sysemu/dma.h" -#include "internal.h" +#include <hw/ide/internal.h> #include <hw/ide/pci.h> #include <hw/ide/ahci.h> diff --git a/hw/ide/ahci.h b/hw/ide/ahci.h deleted file mode 100644 index bc777ed..0000000 --- a/hw/ide/ahci.h +++ /dev/null @@ -1,405 +0,0 @@ -/* - * QEMU AHCI Emulation - * - * Copyright (c) 2010 qiaochong@loongson.cn - * Copyright (c) 2010 Roland Elek <elek.roland@gmail.com> - * Copyright (c) 2010 Sebastian Herbszt <herbszt@gmx.de> - * Copyright (c) 2010 Alexander Graf <agraf@suse.de> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, see <http://www.gnu.org/licenses/>. - * - */ - -#ifndef HW_IDE_AHCI_H -#define HW_IDE_AHCI_H - -#include <hw/sysbus.h> - -#define AHCI_MEM_BAR_SIZE 0x1000 -#define AHCI_MAX_PORTS 32 -#define AHCI_MAX_SG 168 /* hardware max is 64K */ -#define AHCI_DMA_BOUNDARY 0xffffffff -#define AHCI_USE_CLUSTERING 0 -#define AHCI_MAX_CMDS 32 -#define AHCI_CMD_SZ 32 -#define AHCI_CMD_SLOT_SZ (AHCI_MAX_CMDS * AHCI_CMD_SZ) -#define AHCI_RX_FIS_SZ 256 -#define AHCI_CMD_TBL_CDB 0x40 -#define AHCI_CMD_TBL_HDR_SZ 0x80 -#define AHCI_CMD_TBL_SZ (AHCI_CMD_TBL_HDR_SZ + (AHCI_MAX_SG * 16)) -#define AHCI_CMD_TBL_AR_SZ (AHCI_CMD_TBL_SZ * AHCI_MAX_CMDS) -#define AHCI_PORT_PRIV_DMA_SZ (AHCI_CMD_SLOT_SZ + AHCI_CMD_TBL_AR_SZ + \ - AHCI_RX_FIS_SZ) - -#define AHCI_IRQ_ON_SG (1U << 31) -#define AHCI_CMD_ATAPI (1 << 5) -#define AHCI_CMD_WRITE (1 << 6) -#define AHCI_CMD_PREFETCH (1 << 7) -#define AHCI_CMD_RESET (1 << 8) -#define AHCI_CMD_CLR_BUSY (1 << 10) - -#define RX_FIS_D2H_REG 0x40 /* offset of D2H Register FIS data */ -#define RX_FIS_SDB 0x58 /* offset of SDB FIS data */ -#define RX_FIS_UNK 0x60 /* offset of Unknown FIS data */ - -/* global controller registers */ -#define HOST_CAP 0x00 /* host capabilities */ -#define HOST_CTL 0x04 /* global host control */ -#define HOST_IRQ_STAT 0x08 /* interrupt status */ -#define HOST_PORTS_IMPL 0x0c /* bitmap of implemented ports */ -#define HOST_VERSION 0x10 /* AHCI spec. version compliancy */ - -/* HOST_CTL bits */ -#define HOST_CTL_RESET (1 << 0) /* reset controller; self-clear */ -#define HOST_CTL_IRQ_EN (1 << 1) /* global IRQ enable */ -#define HOST_CTL_AHCI_EN (1U << 31) /* AHCI enabled */ - -/* HOST_CAP bits */ -#define HOST_CAP_SSC (1 << 14) /* Slumber capable */ -#define HOST_CAP_AHCI (1 << 18) /* AHCI only */ -#define HOST_CAP_CLO (1 << 24) /* Command List Override support */ -#define HOST_CAP_SSS (1 << 27) /* Staggered Spin-up */ -#define HOST_CAP_NCQ (1 << 30) /* Native Command Queueing */ -#define HOST_CAP_64 (1U << 31) /* PCI DAC (64-bit DMA) support */ - -/* registers for each SATA port */ -#define PORT_LST_ADDR 0x00 /* command list DMA addr */ -#define PORT_LST_ADDR_HI 0x04 /* command list DMA addr hi */ -#define PORT_FIS_ADDR 0x08 /* FIS rx buf addr */ -#define PORT_FIS_ADDR_HI 0x0c /* FIS rx buf addr hi */ -#define PORT_IRQ_STAT 0x10 /* interrupt status */ -#define PORT_IRQ_MASK 0x14 /* interrupt enable/disable mask */ -#define PORT_CMD 0x18 /* port command */ -#define PORT_TFDATA 0x20 /* taskfile data */ -#define PORT_SIG 0x24 /* device TF signature */ -#define PORT_SCR_STAT 0x28 /* SATA phy register: SStatus */ -#define PORT_SCR_CTL 0x2c /* SATA phy register: SControl */ -#define PORT_SCR_ERR 0x30 /* SATA phy register: SError */ -#define PORT_SCR_ACT 0x34 /* SATA phy register: SActive */ -#define PORT_CMD_ISSUE 0x38 /* command issue */ -#define PORT_RESERVED 0x3c /* reserved */ - -/* PORT_IRQ_{STAT,MASK} bits */ -#define PORT_IRQ_COLD_PRES (1U << 31) /* cold presence detect */ -#define PORT_IRQ_TF_ERR (1 << 30) /* task file error */ -#define PORT_IRQ_HBUS_ERR (1 << 29) /* host bus fatal error */ -#define PORT_IRQ_HBUS_DATA_ERR (1 << 28) /* host bus data error */ -#define PORT_IRQ_IF_ERR (1 << 27) /* interface fatal error */ -#define PORT_IRQ_IF_NONFATAL (1 << 26) /* interface non-fatal error */ -#define PORT_IRQ_OVERFLOW (1 << 24) /* xfer exhausted available S/G */ -#define PORT_IRQ_BAD_PMP (1 << 23) /* incorrect port multiplier */ - -#define PORT_IRQ_PHYRDY (1 << 22) /* PhyRdy changed */ -#define PORT_IRQ_DEV_ILCK (1 << 7) /* device interlock */ -#define PORT_IRQ_CONNECT (1 << 6) /* port connect change status */ -#define PORT_IRQ_SG_DONE (1 << 5) /* descriptor processed */ -#define PORT_IRQ_UNK_FIS (1 << 4) /* unknown FIS rx'd */ -#define PORT_IRQ_SDB_FIS (1 << 3) /* Set Device Bits FIS rx'd */ -#define PORT_IRQ_DMAS_FIS (1 << 2) /* DMA Setup FIS rx'd */ -#define PORT_IRQ_PIOS_FIS (1 << 1) /* PIO Setup FIS rx'd */ -#define PORT_IRQ_D2H_REG_FIS (1 << 0) /* D2H Register FIS rx'd */ - -#define PORT_IRQ_FREEZE (PORT_IRQ_HBUS_ERR | PORT_IRQ_IF_ERR | \ - PORT_IRQ_CONNECT | PORT_IRQ_PHYRDY | \ - PORT_IRQ_UNK_FIS) -#define PORT_IRQ_ERROR (PORT_IRQ_FREEZE | PORT_IRQ_TF_ERR | \ - PORT_IRQ_HBUS_DATA_ERR) -#define DEF_PORT_IRQ (PORT_IRQ_ERROR | PORT_IRQ_SG_DONE | \ - PORT_IRQ_SDB_FIS | PORT_IRQ_DMAS_FIS | \ - PORT_IRQ_PIOS_FIS | PORT_IRQ_D2H_REG_FIS) - -/* PORT_CMD bits */ -#define PORT_CMD_ATAPI (1 << 24) /* Device is ATAPI */ -#define PORT_CMD_LIST_ON (1 << 15) /* cmd list DMA engine running */ -#define PORT_CMD_FIS_ON (1 << 14) /* FIS DMA engine running */ -#define PORT_CMD_FIS_RX (1 << 4) /* Enable FIS receive DMA engine */ -#define PORT_CMD_CLO (1 << 3) /* Command list override */ -#define PORT_CMD_POWER_ON (1 << 2) /* Power up device */ -#define PORT_CMD_SPIN_UP (1 << 1) /* Spin up device */ -#define PORT_CMD_START (1 << 0) /* Enable port DMA engine */ - -#define PORT_CMD_ICC_MASK (0xfU << 28) /* i/f ICC state mask */ -#define PORT_CMD_ICC_ACTIVE (0x1 << 28) /* Put i/f in active state */ -#define PORT_CMD_ICC_PARTIAL (0x2 << 28) /* Put i/f in partial state */ -#define PORT_CMD_ICC_SLUMBER (0x6 << 28) /* Put i/f in slumber state */ - -#define PORT_CMD_RO_MASK 0x007dffe0 /* Which CMD bits are read only? */ - -/* ap->flags bits */ -#define AHCI_FLAG_NO_NCQ (1 << 24) -#define AHCI_FLAG_IGN_IRQ_IF_ERR (1 << 25) /* ignore IRQ_IF_ERR */ -#define AHCI_FLAG_HONOR_PI (1 << 26) /* honor PORTS_IMPL */ -#define AHCI_FLAG_IGN_SERR_INTERNAL (1 << 27) /* ignore SERR_INTERNAL */ -#define AHCI_FLAG_32BIT_ONLY (1 << 28) /* force 32bit */ - -#define ATA_SRST (1 << 2) /* software reset */ - -#define STATE_RUN 0 -#define STATE_RESET 1 - -#define SATA_SCR_SSTATUS_DET_NODEV 0x0 -#define SATA_SCR_SSTATUS_DET_DEV_PRESENT_PHY_UP 0x3 - -#define SATA_SCR_SSTATUS_SPD_NODEV 0x00 -#define SATA_SCR_SSTATUS_SPD_GEN1 0x10 - -#define SATA_SCR_SSTATUS_IPM_NODEV 0x000 -#define SATA_SCR_SSTATUS_IPM_ACTIVE 0X100 - -#define AHCI_SCR_SCTL_DET 0xf - -#define SATA_FIS_TYPE_REGISTER_H2D 0x27 -#define SATA_FIS_REG_H2D_UPDATE_COMMAND_REGISTER 0x80 -#define SATA_FIS_TYPE_REGISTER_D2H 0x34 -#define SATA_FIS_TYPE_PIO_SETUP 0x5f -#define SATA_FIS_TYPE_SDB 0xA1 - -#define AHCI_CMD_HDR_CMD_FIS_LEN 0x1f -#define AHCI_CMD_HDR_PRDT_LEN 16 - -#define SATA_SIGNATURE_CDROM 0xeb140101 -#define SATA_SIGNATURE_DISK 0x00000101 - -#define AHCI_GENERIC_HOST_CONTROL_REGS_MAX_ADDR 0x20 - /* Shouldn't this be 0x2c? */ - -#define AHCI_PORT_REGS_START_ADDR 0x100 -#define AHCI_PORT_ADDR_OFFSET_MASK 0x7f -#define AHCI_PORT_ADDR_OFFSET_LEN 0x80 - -#define AHCI_NUM_COMMAND_SLOTS 31 -#define AHCI_SUPPORTED_SPEED 20 -#define AHCI_SUPPORTED_SPEED_GEN1 1 -#define AHCI_VERSION_1_0 0x10000 - -#define AHCI_PROGMODE_MAJOR_REV_1 1 - -#define AHCI_COMMAND_TABLE_ACMD 0x40 - -#define AHCI_PRDT_SIZE_MASK 0x3fffff - -#define IDE_FEATURE_DMA 1 - -#define READ_FPDMA_QUEUED 0x60 -#define WRITE_FPDMA_QUEUED 0x61 -#define NCQ_NON_DATA 0x63 -#define RECEIVE_FPDMA_QUEUED 0x65 -#define SEND_FPDMA_QUEUED 0x64 - -#define NCQ_FIS_FUA_MASK 0x80 -#define NCQ_FIS_RARC_MASK 0x01 - -#define RES_FIS_DSFIS 0x00 -#define RES_FIS_PSFIS 0x20 -#define RES_FIS_RFIS 0x40 -#define RES_FIS_SDBFIS 0x58 -#define RES_FIS_UFIS 0x60 - -#define SATA_CAP_SIZE 0x8 -#define SATA_CAP_REV 0x2 -#define SATA_CAP_BAR 0x4 - -typedef struct AHCIControlRegs { - uint32_t cap; - uint32_t ghc; - uint32_t irqstatus; - uint32_t impl; - uint32_t version; -} AHCIControlRegs; - -typedef struct AHCIPortRegs { - uint32_t lst_addr; - uint32_t lst_addr_hi; - uint32_t fis_addr; - uint32_t fis_addr_hi; - uint32_t irq_stat; - uint32_t irq_mask; - uint32_t cmd; - uint32_t unused0; - uint32_t tfdata; - uint32_t sig; - uint32_t scr_stat; - uint32_t scr_ctl; - uint32_t scr_err; - uint32_t scr_act; - uint32_t cmd_issue; - uint32_t reserved; -} AHCIPortRegs; - -typedef struct AHCICmdHdr { - uint16_t opts; - uint16_t prdtl; - uint32_t status; - uint64_t tbl_addr; - uint32_t reserved[4]; -} QEMU_PACKED AHCICmdHdr; - -typedef struct AHCI_SG { - uint64_t addr; - uint32_t reserved; - uint32_t flags_size; -} QEMU_PACKED AHCI_SG; - -typedef struct AHCIDevice AHCIDevice; - -typedef struct NCQTransferState { - AHCIDevice *drive; - BlockAIOCB *aiocb; - AHCICmdHdr *cmdh; - QEMUSGList sglist; - BlockAcctCookie acct; - uint32_t sector_count; - uint64_t lba; - uint8_t tag; - uint8_t cmd; - uint8_t slot; - bool used; - bool halt; -} NCQTransferState; - -struct AHCIDevice { - IDEDMA dma; - IDEBus port; - int port_no; - uint32_t port_state; - uint32_t finished; - AHCIPortRegs port_regs; - struct AHCIState *hba; - QEMUBH *check_bh; - uint8_t *lst; - uint8_t *res_fis; - bool done_atapi_packet; - int32_t busy_slot; - bool init_d2h_sent; - AHCICmdHdr *cur_cmd; - NCQTransferState ncq_tfs[AHCI_MAX_CMDS]; -}; - -typedef struct AHCIState { - DeviceState *container; - - AHCIDevice *dev; - AHCIControlRegs control_regs; - MemoryRegion mem; - MemoryRegion idp; /* Index-Data Pair I/O port space */ - unsigned idp_offset; /* Offset of index in I/O port space */ - uint32_t idp_index; /* Current IDP index */ - int32_t ports; - qemu_irq irq; - AddressSpace *as; -} AHCIState; - -typedef struct AHCIPCIState { - /*< private >*/ - PCIDevice parent_obj; - /*< public >*/ - - AHCIState ahci; -} AHCIPCIState; - -#define TYPE_ICH9_AHCI "ich9-ahci" - -#define ICH_AHCI(obj) \ - OBJECT_CHECK(AHCIPCIState, (obj), TYPE_ICH9_AHCI) - -extern const VMStateDescription vmstate_ahci; - -#define VMSTATE_AHCI(_field, _state) { \ - .name = (stringify(_field)), \ - .size = sizeof(AHCIState), \ - .vmsd = &vmstate_ahci, \ - .flags = VMS_STRUCT, \ - .offset = vmstate_offset_value(_state, _field, AHCIState), \ -} - -/** - * NCQFrame is the same as a Register H2D FIS (described in SATA 3.2), - * but some fields have been re-mapped and re-purposed, as seen in - * SATA 3.2 section 13.6.4.1 ("READ FPDMA QUEUED") - * - * cmd_fis[3], feature 7:0, becomes sector count 7:0. - * cmd_fis[7], device 7:0, uses bit 7 as the Force Unit Access bit. - * cmd_fis[11], feature 15:8, becomes sector count 15:8. - * cmd_fis[12], count 7:0, becomes the NCQ TAG (7:3) and RARC bit (0) - * cmd_fis[13], count 15:8, becomes the priority value (7:6) - * bytes 16-19 become an le32 "auxiliary" field. - */ -typedef struct NCQFrame { - uint8_t fis_type; - uint8_t c; - uint8_t command; - uint8_t sector_count_low; /* (feature 7:0) */ - uint8_t lba0; - uint8_t lba1; - uint8_t lba2; - uint8_t fua; /* (device 7:0) */ - uint8_t lba3; - uint8_t lba4; - uint8_t lba5; - uint8_t sector_count_high; /* (feature 15:8) */ - uint8_t tag; /* (count 0:7) */ - uint8_t prio; /* (count 15:8) */ - uint8_t icc; - uint8_t control; - uint8_t aux0; - uint8_t aux1; - uint8_t aux2; - uint8_t aux3; -} QEMU_PACKED NCQFrame; - -typedef struct SDBFIS { - uint8_t type; - uint8_t flags; - uint8_t status; - uint8_t error; - uint32_t payload; -} QEMU_PACKED SDBFIS; - -void ahci_realize(AHCIState *s, DeviceState *qdev, AddressSpace *as, int ports); -void ahci_init(AHCIState *s, DeviceState *qdev); -void ahci_uninit(AHCIState *s); - -void ahci_reset(AHCIState *s); - -void ahci_ide_create_devs(PCIDevice *dev, DriveInfo **hd); - -#define TYPE_SYSBUS_AHCI "sysbus-ahci" -#define SYSBUS_AHCI(obj) OBJECT_CHECK(SysbusAHCIState, (obj), TYPE_SYSBUS_AHCI) - -typedef struct SysbusAHCIState { - /*< private >*/ - SysBusDevice parent_obj; - /*< public >*/ - - AHCIState ahci; - uint32_t num_ports; -} SysbusAHCIState; - -#define TYPE_ALLWINNER_AHCI "allwinner-ahci" -#define ALLWINNER_AHCI(obj) OBJECT_CHECK(AllwinnerAHCIState, (obj), \ - TYPE_ALLWINNER_AHCI) - -#define ALLWINNER_AHCI_MMIO_OFF 0x80 -#define ALLWINNER_AHCI_MMIO_SIZE 0x80 - -struct AllwinnerAHCIState { - /*< private >*/ - SysbusAHCIState parent_obj; - /*< public >*/ - - MemoryRegion mmio; - uint32_t regs[ALLWINNER_AHCI_MMIO_SIZE/4]; -}; - -#endif /* HW_IDE_AHCI_H */ diff --git a/hw/ide/internal.h b/hw/ide/internal.h deleted file mode 100644 index 773928a..0000000 --- a/hw/ide/internal.h +++ /dev/null @@ -1,635 +0,0 @@ -#ifndef HW_IDE_INTERNAL_H -#define HW_IDE_INTERNAL_H - -/* - * QEMU IDE Emulation -- internal header file - * only files in hw/ide/ are supposed to include this file. - * non-internal declarations are in hw/ide.h - */ -#include <hw/ide.h> -#include <hw/isa/isa.h> -#include "sysemu/dma.h" -#include "sysemu/sysemu.h" -#include "hw/block/block.h" -#include "block/scsi.h" - -/* debug IDE devices */ -//#define DEBUG_IDE -//#define DEBUG_IDE_ATAPI -//#define DEBUG_AIO -#define USE_DMA_CDROM - -typedef struct IDEBus IDEBus; -typedef struct IDEDevice IDEDevice; -typedef struct IDEState IDEState; -typedef struct IDEDMA IDEDMA; -typedef struct IDEDMAOps IDEDMAOps; - -#define TYPE_IDE_BUS "IDE" -#define IDE_BUS(obj) OBJECT_CHECK(IDEBus, (obj), TYPE_IDE_BUS) - -/* Bits of HD_STATUS */ -#define ERR_STAT 0x01 -#define INDEX_STAT 0x02 -#define ECC_STAT 0x04 /* Corrected error */ -#define DRQ_STAT 0x08 -#define SEEK_STAT 0x10 -#define SRV_STAT 0x10 -#define WRERR_STAT 0x20 -#define READY_STAT 0x40 -#define BUSY_STAT 0x80 - -/* Bits for HD_ERROR */ -#define MARK_ERR 0x01 /* Bad address mark */ -#define TRK0_ERR 0x02 /* couldn't find track 0 */ -#define ABRT_ERR 0x04 /* Command aborted */ -#define MCR_ERR 0x08 /* media change request */ -#define ID_ERR 0x10 /* ID field not found */ -#define MC_ERR 0x20 /* media changed */ -#define ECC_ERR 0x40 /* Uncorrectable ECC error */ -#define BBD_ERR 0x80 /* pre-EIDE meaning: block marked bad */ -#define ICRC_ERR 0x80 /* new meaning: CRC error during transfer */ - -/* Bits of HD_NSECTOR */ -#define CD 0x01 -#define IO 0x02 -#define REL 0x04 -#define TAG_MASK 0xf8 - -#define IDE_CMD_RESET 0x04 -#define IDE_CMD_DISABLE_IRQ 0x02 - -/* ACS-2 T13/2015-D Table B.2 Command codes */ -#define WIN_NOP 0x00 -/* reserved 0x01..0x02 */ -#define CFA_REQ_EXT_ERROR_CODE 0x03 /* CFA Request Extended Error Code */ -/* reserved 0x04..0x05 */ -#define WIN_DSM 0x06 -/* reserved 0x07 */ -#define WIN_DEVICE_RESET 0x08 -/* reserved 0x09..0x0a */ -/* REQUEST SENSE DATA EXT 0x0B */ -/* reserved 0x0C..0x0F */ -#define WIN_RECAL 0x10 /* obsolete since ATA4 */ -/* obsolete since ATA3, retired in ATA4 0x11..0x1F */ -#define WIN_READ 0x20 /* 28-Bit */ -#define WIN_READ_ONCE 0x21 /* 28-Bit w/o retries, obsolete since ATA5 */ -/* obsolete since ATA4 0x22..0x23 */ -#define WIN_READ_EXT 0x24 /* 48-Bit */ -#define WIN_READDMA_EXT 0x25 /* 48-Bit */ -#define WIN_READDMA_QUEUED_EXT 0x26 /* 48-Bit, obsolete since ACS2 */ -#define WIN_READ_NATIVE_MAX_EXT 0x27 /* 48-Bit */ -/* reserved 0x28 */ -#define WIN_MULTREAD_EXT 0x29 /* 48-Bit */ -/* READ STREAM DMA EXT 0x2A */ -/* READ STREAM EXT 0x2B */ -/* reserved 0x2C..0x2E */ -/* READ LOG EXT 0x2F */ -#define WIN_WRITE 0x30 /* 28-Bit */ -#define WIN_WRITE_ONCE 0x31 /* 28-Bit w/o retries, obsolete since ATA5 */ -/* obsolete since ATA4 0x32..0x33 */ -#define WIN_WRITE_EXT 0x34 /* 48-Bit */ -#define WIN_WRITEDMA_EXT 0x35 /* 48-Bit */ -#define WIN_WRITEDMA_QUEUED_EXT 0x36 /* 48-Bit */ -#define WIN_SET_MAX_EXT 0x37 /* 48-Bit, obsolete since ACS2 */ -#define WIN_SET_MAX_EXT 0x37 /* 48-Bit */ -#define CFA_WRITE_SECT_WO_ERASE 0x38 /* CFA Write Sectors without erase */ -#define WIN_MULTWRITE_EXT 0x39 /* 48-Bit */ -/* WRITE STREAM DMA EXT 0x3A */ -/* WRITE STREAM EXT 0x3B */ -#define WIN_WRITE_VERIFY 0x3C /* 28-Bit, obsolete since ATA4 */ -/* WRITE DMA FUA EXT 0x3D */ -/* obsolete since ACS2 0x3E */ -/* WRITE LOG EXT 0x3F */ -#define WIN_VERIFY 0x40 /* 28-Bit - Read Verify Sectors */ -#define WIN_VERIFY_ONCE 0x41 /* 28-Bit - w/o retries, obsolete since ATA5 */ -#define WIN_VERIFY_EXT 0x42 /* 48-Bit */ -/* reserved 0x43..0x44 */ -/* WRITE UNCORRECTABLE EXT 0x45 */ -/* reserved 0x46 */ -/* READ LOG DMA EXT 0x47 */ -/* reserved 0x48..0x4F */ -/* obsolete since ATA4 0x50 */ -/* CONFIGURE STREAM 0x51 */ -/* reserved 0x52..0x56 */ -/* WRITE LOG DMA EXT 0x57 */ -/* reserved 0x58..0x5A */ -/* TRUSTED NON DATA 0x5B */ -/* TRUSTED RECEIVE 0x5C */ -/* TRUSTED RECEIVE DMA 0x5D */ -/* TRUSTED SEND 0x5E */ -/* TRUSTED SEND DMA 0x5F */ -/* READ FPDMA QUEUED 0x60 */ -/* WRITE FPDMA QUEUED 0x61 */ -/* reserved 0x62->0x6F */ -#define WIN_SEEK 0x70 /* obsolete since ATA7 */ -/* reserved 0x71-0x7F */ -/* vendor specific 0x80-0x86 */ -#define CFA_TRANSLATE_SECTOR 0x87 /* CFA Translate Sector */ -/* vendor specific 0x88-0x8F */ -#define WIN_DIAGNOSE 0x90 -#define WIN_SPECIFY 0x91 /* set drive geometry translation, obsolete since ATA6 */ -#define WIN_DOWNLOAD_MICROCODE 0x92 -/* DOWNLOAD MICROCODE DMA 0x93 */ -#define WIN_STANDBYNOW2 0x94 /* retired in ATA4 */ -#define WIN_IDLEIMMEDIATE2 0x95 /* force drive to become "ready", retired in ATA4 */ -#define WIN_STANDBY2 0x96 /* retired in ATA4 */ -#define WIN_SETIDLE2 0x97 /* retired in ATA4 */ -#define WIN_CHECKPOWERMODE2 0x98 /* retired in ATA4 */ -#define WIN_SLEEPNOW2 0x99 /* retired in ATA4 */ -/* vendor specific 0x9A */ -/* reserved 0x9B..0x9F */ -#define WIN_PACKETCMD 0xA0 /* Send a packet command. */ -#define WIN_PIDENTIFY 0xA1 /* identify ATAPI device */ -#define WIN_QUEUED_SERVICE 0xA2 /* obsolete since ACS2 */ -/* reserved 0xA3..0xAF */ -#define WIN_SMART 0xB0 /* self-monitoring and reporting */ -/* Device Configuration Overlay 0xB1 */ -/* reserved 0xB2..0xB3 */ -/* Sanitize Device 0xB4 */ -/* reserved 0xB5 */ -/* NV Cache 0xB6 */ -/* reserved for CFA 0xB7..0xBB */ -#define CFA_ACCESS_METADATA_STORAGE 0xB8 -/* reserved 0xBC..0xBF */ -#define CFA_ERASE_SECTORS 0xC0 /* microdrives implement as NOP */ -/* vendor specific 0xC1..0xC3 */ -#define WIN_MULTREAD 0xC4 /* read sectors using multiple mode*/ -#define WIN_MULTWRITE 0xC5 /* write sectors using multiple mode */ -#define WIN_SETMULT 0xC6 /* enable/disable multiple mode */ -#define WIN_READDMA_QUEUED 0xC7 /* read sectors using Queued DMA transfers, obsolete since ACS2 */ -#define WIN_READDMA 0xC8 /* read sectors using DMA transfers */ -#define WIN_READDMA_ONCE 0xC9 /* 28-Bit - w/o retries, obsolete since ATA5 */ -#define WIN_WRITEDMA 0xCA /* write sectors using DMA transfers */ -#define WIN_WRITEDMA_ONCE 0xCB /* 28-Bit - w/o retries, obsolete since ATA5 */ -#define WIN_WRITEDMA_QUEUED 0xCC /* write sectors using Queued DMA transfers, obsolete since ACS2 */ -#define CFA_WRITE_MULTI_WO_ERASE 0xCD /* CFA Write multiple without erase */ -/* WRITE MULTIPLE FUA EXT 0xCE */ -/* reserved 0xCF..0xDO */ -/* CHECK MEDIA CARD TYPE 0xD1 */ -/* reserved for media card pass through 0xD2..0xD4 */ -/* reserved 0xD5..0xD9 */ -#define WIN_GETMEDIASTATUS 0xDA /* obsolete since ATA8 */ -/* obsolete since ATA3, retired in ATA4 0xDB..0xDD */ -#define WIN_DOORLOCK 0xDE /* lock door on removable drives, obsolete since ATA8 */ -#define WIN_DOORUNLOCK 0xDF /* unlock door on removable drives, obsolete since ATA8 */ -#define WIN_STANDBYNOW1 0xE0 -#define WIN_IDLEIMMEDIATE 0xE1 /* force drive to become "ready" */ -#define WIN_STANDBY 0xE2 /* Set device in Standby Mode */ -#define WIN_SETIDLE1 0xE3 -#define WIN_READ_BUFFER 0xE4 /* force read only 1 sector */ -#define WIN_CHECKPOWERMODE1 0xE5 -#define WIN_SLEEPNOW1 0xE6 -#define WIN_FLUSH_CACHE 0xE7 -#define WIN_WRITE_BUFFER 0xE8 /* force write only 1 sector */ -/* READ BUFFER DMA 0xE9 */ -#define WIN_FLUSH_CACHE_EXT 0xEA /* 48-Bit */ -/* WRITE BUFFER DMA 0xEB */ -#define WIN_IDENTIFY 0xEC /* ask drive to identify itself */ -#define WIN_MEDIAEJECT 0xED /* obsolete since ATA8 */ -/* obsolete since ATA4 0xEE */ -#define WIN_SETFEATURES 0xEF /* set special drive features */ -#define IBM_SENSE_CONDITION 0xF0 /* measure disk temperature, vendor specific */ -#define WIN_SECURITY_SET_PASS 0xF1 -#define WIN_SECURITY_UNLOCK 0xF2 -#define WIN_SECURITY_ERASE_PREPARE 0xF3 -#define WIN_SECURITY_ERASE_UNIT 0xF4 -#define WIN_SECURITY_FREEZE_LOCK 0xF5 -#define CFA_WEAR_LEVEL 0xF5 /* microdrives implement as NOP; not specified in T13! */ -#define WIN_SECURITY_DISABLE 0xF6 -/* vendor specific 0xF7 */ -#define WIN_READ_NATIVE_MAX 0xF8 /* return the native maximum address */ -#define WIN_SET_MAX 0xF9 -/* vendor specific 0xFA..0xFF */ - -/* set to 1 set disable mult support */ -#define MAX_MULT_SECTORS 16 - -#define IDE_DMA_BUF_SECTORS 256 - -/* feature values for Data Set Management */ -#define DSM_TRIM 0x01 - -#if (IDE_DMA_BUF_SECTORS < MAX_MULT_SECTORS) -#error "IDE_DMA_BUF_SECTORS must be bigger or equal to MAX_MULT_SECTORS" -#endif - -/* ATAPI defines */ - -#define ATAPI_PACKET_SIZE 12 - -/* The generic packet command opcodes for CD/DVD Logical Units, - * From Table 57 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */ -#define GPCMD_BLANK 0xa1 -#define GPCMD_CLOSE_TRACK 0x5b -#define GPCMD_FLUSH_CACHE 0x35 -#define GPCMD_FORMAT_UNIT 0x04 -#define GPCMD_GET_CONFIGURATION 0x46 -#define GPCMD_GET_EVENT_STATUS_NOTIFICATION 0x4a -#define GPCMD_GET_PERFORMANCE 0xac -#define GPCMD_INQUIRY 0x12 -#define GPCMD_LOAD_UNLOAD 0xa6 -#define GPCMD_MECHANISM_STATUS 0xbd -#define GPCMD_MODE_SELECT_10 0x55 -#define GPCMD_MODE_SENSE_10 0x5a -#define GPCMD_PAUSE_RESUME 0x4b -#define GPCMD_PLAY_AUDIO_10 0x45 -#define GPCMD_PLAY_AUDIO_MSF 0x47 -#define GPCMD_PLAY_AUDIO_TI 0x48 -#define GPCMD_PLAY_CD 0xbc -#define GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1e -#define GPCMD_READ_10 0x28 -#define GPCMD_READ_12 0xa8 -#define GPCMD_READ_CDVD_CAPACITY 0x25 -#define GPCMD_READ_CD 0xbe -#define GPCMD_READ_CD_MSF 0xb9 -#define GPCMD_READ_DISC_INFO 0x51 -#define GPCMD_READ_DVD_STRUCTURE 0xad -#define GPCMD_READ_FORMAT_CAPACITIES 0x23 -#define GPCMD_READ_HEADER 0x44 -#define GPCMD_READ_TRACK_RZONE_INFO 0x52 -#define GPCMD_READ_SUBCHANNEL 0x42 -#define GPCMD_READ_TOC_PMA_ATIP 0x43 -#define GPCMD_REPAIR_RZONE_TRACK 0x58 -#define GPCMD_REPORT_KEY 0xa4 -#define GPCMD_REQUEST_SENSE 0x03 -#define GPCMD_RESERVE_RZONE_TRACK 0x53 -#define GPCMD_SCAN 0xba -#define GPCMD_SEEK 0x2b -#define GPCMD_SEND_DVD_STRUCTURE 0xad -#define GPCMD_SEND_EVENT 0xa2 -#define GPCMD_SEND_KEY 0xa3 -#define GPCMD_SEND_OPC 0x54 -#define GPCMD_SET_READ_AHEAD 0xa7 -#define GPCMD_SET_STREAMING 0xb6 -#define GPCMD_START_STOP_UNIT 0x1b -#define GPCMD_STOP_PLAY_SCAN 0x4e -#define GPCMD_TEST_UNIT_READY 0x00 -#define GPCMD_VERIFY_10 0x2f -#define GPCMD_WRITE_10 0x2a -#define GPCMD_WRITE_AND_VERIFY_10 0x2e -/* This is listed as optional in ATAPI 2.6, but is (curiously) - * missing from Mt. Fuji, Table 57. It _is_ mentioned in Mt. Fuji - * Table 377 as an MMC command for SCSi devices though... Most ATAPI - * drives support it. */ -#define GPCMD_SET_SPEED 0xbb -/* This seems to be a SCSI specific CD-ROM opcode - * to play data at track/index */ -#define GPCMD_PLAYAUDIO_TI 0x48 -/* - * From MS Media Status Notification Support Specification. For - * older drives only. - */ -#define GPCMD_GET_MEDIA_STATUS 0xda -#define GPCMD_MODE_SENSE_6 0x1a - -#define ATAPI_INT_REASON_CD 0x01 /* 0 = data transfer */ -#define ATAPI_INT_REASON_IO 0x02 /* 1 = transfer to the host */ -#define ATAPI_INT_REASON_REL 0x04 -#define ATAPI_INT_REASON_TAG 0xf8 - -/* same constants as bochs */ -#define ASC_NO_SEEK_COMPLETE 0x02 -#define ASC_ILLEGAL_OPCODE 0x20 -#define ASC_LOGICAL_BLOCK_OOR 0x21 -#define ASC_INV_FIELD_IN_CMD_PACKET 0x24 -#define ASC_MEDIUM_MAY_HAVE_CHANGED 0x28 -#define ASC_INCOMPATIBLE_FORMAT 0x30 -#define ASC_MEDIUM_NOT_PRESENT 0x3a -#define ASC_SAVING_PARAMETERS_NOT_SUPPORTED 0x39 -#define ASC_DATA_PHASE_ERROR 0x4b -#define ASC_MEDIA_REMOVAL_PREVENTED 0x53 - -#define CFA_NO_ERROR 0x00 -#define CFA_MISC_ERROR 0x09 -#define CFA_INVALID_COMMAND 0x20 -#define CFA_INVALID_ADDRESS 0x21 -#define CFA_ADDRESS_OVERFLOW 0x2f - -#define SMART_READ_DATA 0xd0 -#define SMART_READ_THRESH 0xd1 -#define SMART_ATTR_AUTOSAVE 0xd2 -#define SMART_SAVE_ATTR 0xd3 -#define SMART_EXECUTE_OFFLINE 0xd4 -#define SMART_READ_LOG 0xd5 -#define SMART_WRITE_LOG 0xd6 -#define SMART_ENABLE 0xd8 -#define SMART_DISABLE 0xd9 -#define SMART_STATUS 0xda - -typedef enum { IDE_HD, IDE_CD, IDE_CFATA } IDEDriveKind; - -typedef void EndTransferFunc(IDEState *); - -typedef void DMAStartFunc(IDEDMA *, IDEState *, BlockCompletionFunc *); -typedef void DMAVoidFunc(IDEDMA *); -typedef int DMAIntFunc(IDEDMA *, int); -typedef int32_t DMAInt32Func(IDEDMA *, int32_t len); -typedef void DMAu32Func(IDEDMA *, uint32_t); -typedef void DMAStopFunc(IDEDMA *, bool); -typedef void DMARestartFunc(void *, int, RunState); - -struct unreported_events { - bool eject_request; - bool new_media; -}; - -enum ide_dma_cmd { - IDE_DMA_READ, - IDE_DMA_WRITE, - IDE_DMA_TRIM, - IDE_DMA_ATAPI, -}; - -#define ide_cmd_is_read(s) \ - ((s)->dma_cmd == IDE_DMA_READ) - -typedef struct IDEBufferedRequest { - QLIST_ENTRY(IDEBufferedRequest) list; - struct iovec iov; - QEMUIOVector qiov; - QEMUIOVector *original_qiov; - BlockCompletionFunc *original_cb; - void *original_opaque; - bool orphaned; -} IDEBufferedRequest; - -/* NOTE: IDEState represents in fact one drive */ -struct IDEState { - IDEBus *bus; - uint8_t unit; - /* ide config */ - IDEDriveKind drive_kind; - int cylinders, heads, sectors, chs_trans; - int64_t nb_sectors; - int mult_sectors; - int identify_set; - uint8_t identify_data[512]; - int drive_serial; - char drive_serial_str[21]; - char drive_model_str[41]; - uint64_t wwn; - /* ide regs */ - uint8_t feature; - uint8_t error; - uint32_t nsector; - uint8_t sector; - uint8_t lcyl; - uint8_t hcyl; - /* other part of tf for lba48 support */ - uint8_t hob_feature; - uint8_t hob_nsector; - uint8_t hob_sector; - uint8_t hob_lcyl; - uint8_t hob_hcyl; - - uint8_t select; - uint8_t status; - - /* set for lba48 access */ - uint8_t lba48; - BlockBackend *blk; - char version[9]; - /* ATAPI specific */ - struct unreported_events events; - uint8_t sense_key; - uint8_t asc; - bool tray_open; - bool tray_locked; - uint8_t cdrom_changed; - int packet_transfer_size; - int elementary_transfer_size; - int32_t io_buffer_index; - int lba; - int cd_sector_size; - int atapi_dma; /* true if dma is requested for the packet cmd */ - BlockAcctCookie acct; - BlockAIOCB *pio_aiocb; - struct iovec iov; - QEMUIOVector qiov; - QLIST_HEAD(, IDEBufferedRequest) buffered_requests; - /* ATA DMA state */ - uint64_t io_buffer_offset; - int32_t io_buffer_size; - QEMUSGList sg; - /* PIO transfer handling */ - int req_nb_sectors; /* number of sectors per interrupt */ - EndTransferFunc *end_transfer_func; - uint8_t *data_ptr; - uint8_t *data_end; - uint8_t *io_buffer; - /* PIO save/restore */ - int32_t io_buffer_total_len; - int32_t cur_io_buffer_offset; - int32_t cur_io_buffer_len; - uint8_t end_transfer_fn_idx; - QEMUTimer *sector_write_timer; /* only used for win2k install hack */ - uint32_t irq_count; /* counts IRQs when using win2k install hack */ - /* CF-ATA extended error */ - uint8_t ext_error; - /* CF-ATA metadata storage */ - uint32_t mdata_size; - uint8_t *mdata_storage; - int media_changed; - enum ide_dma_cmd dma_cmd; - /* SMART */ - uint8_t smart_enabled; - uint8_t smart_autosave; - int smart_errors; - uint8_t smart_selftest_count; - uint8_t *smart_selftest_data; - /* AHCI */ - int ncq_queues; -}; - -struct IDEDMAOps { - DMAStartFunc *start_dma; - DMAVoidFunc *start_transfer; - DMAInt32Func *prepare_buf; - DMAu32Func *commit_buf; - DMAIntFunc *rw_buf; - DMAVoidFunc *restart; - DMAVoidFunc *restart_dma; - DMAStopFunc *set_inactive; - DMAVoidFunc *cmd_done; - DMAVoidFunc *reset; -}; - -struct IDEDMA { - const struct IDEDMAOps *ops; - struct iovec iov; - QEMUIOVector qiov; - BlockAIOCB *aiocb; -}; - -struct IDEBus { - BusState qbus; - IDEDevice *master; - IDEDevice *slave; - IDEState ifs[2]; - QEMUBH *bh; - - int bus_id; - int max_units; - IDEDMA *dma; - uint8_t unit; - uint8_t cmd; - qemu_irq irq; - - int error_status; - uint8_t retry_unit; - int64_t retry_sector_num; - uint32_t retry_nsector; -}; - -#define TYPE_IDE_DEVICE "ide-device" -#define IDE_DEVICE(obj) \ - OBJECT_CHECK(IDEDevice, (obj), TYPE_IDE_DEVICE) -#define IDE_DEVICE_CLASS(klass) \ - OBJECT_CLASS_CHECK(IDEDeviceClass, (klass), TYPE_IDE_DEVICE) -#define IDE_DEVICE_GET_CLASS(obj) \ - OBJECT_GET_CLASS(IDEDeviceClass, (obj), TYPE_IDE_DEVICE) - -typedef struct IDEDeviceClass { - DeviceClass parent_class; - int (*init)(IDEDevice *dev); -} IDEDeviceClass; - -struct IDEDevice { - DeviceState qdev; - uint32_t unit; - BlockConf conf; - int chs_trans; - char *version; - char *serial; - char *model; - uint64_t wwn; -}; - -/* These are used for the error_status field of IDEBus */ -#define IDE_RETRY_MASK 0xf8 -#define IDE_RETRY_DMA 0x08 -#define IDE_RETRY_PIO 0x10 -#define IDE_RETRY_ATAPI 0x20 /* reused IDE_RETRY_READ bit */ -#define IDE_RETRY_READ 0x20 -#define IDE_RETRY_FLUSH 0x40 -#define IDE_RETRY_TRIM 0x80 -#define IDE_RETRY_HBA 0x100 - -#define IS_IDE_RETRY_DMA(_status) \ - ((_status) & IDE_RETRY_DMA) - -#define IS_IDE_RETRY_PIO(_status) \ - ((_status) & IDE_RETRY_PIO) - -/* - * The method of the IDE_RETRY_ATAPI determination is to use a previously - * impossible bit combination as a new status value. - */ -#define IS_IDE_RETRY_ATAPI(_status) \ - (((_status) & IDE_RETRY_MASK) == IDE_RETRY_ATAPI) - -static inline uint8_t ide_dma_cmd_to_retry(uint8_t dma_cmd) -{ - switch (dma_cmd) { - case IDE_DMA_READ: - return IDE_RETRY_DMA | IDE_RETRY_READ; - case IDE_DMA_WRITE: - return IDE_RETRY_DMA; - case IDE_DMA_TRIM: - return IDE_RETRY_DMA | IDE_RETRY_TRIM; - case IDE_DMA_ATAPI: - return IDE_RETRY_ATAPI; - default: - break; - } - return 0; -} - -static inline IDEState *idebus_active_if(IDEBus *bus) -{ - return bus->ifs + bus->unit; -} - -static inline void ide_set_irq(IDEBus *bus) -{ - if (!(bus->cmd & IDE_CMD_DISABLE_IRQ)) { - qemu_irq_raise(bus->irq); - } -} - -/* hw/ide/core.c */ -extern const VMStateDescription vmstate_ide_bus; - -#define VMSTATE_IDE_BUS(_field, _state) \ - VMSTATE_STRUCT(_field, _state, 1, vmstate_ide_bus, IDEBus) - -#define VMSTATE_IDE_BUS_ARRAY(_field, _state, _num) \ - VMSTATE_STRUCT_ARRAY(_field, _state, _num, 1, vmstate_ide_bus, IDEBus) - -extern const VMStateDescription vmstate_ide_drive; - -#define VMSTATE_IDE_DRIVES(_field, _state) \ - VMSTATE_STRUCT_ARRAY(_field, _state, 2, 3, vmstate_ide_drive, IDEState) - -#define VMSTATE_IDE_DRIVE(_field, _state) \ - VMSTATE_STRUCT(_field, _state, 1, vmstate_ide_drive, IDEState) - -void ide_bus_reset(IDEBus *bus); -int64_t ide_get_sector(IDEState *s); -void ide_set_sector(IDEState *s, int64_t sector_num); - -void ide_start_dma(IDEState *s, BlockCompletionFunc *cb); -void dma_buf_commit(IDEState *s, uint32_t tx_bytes); -void ide_dma_error(IDEState *s); -void ide_abort_command(IDEState *s); - -void ide_atapi_cmd_ok(IDEState *s); -void ide_atapi_cmd_error(IDEState *s, int sense_key, int asc); -void ide_atapi_dma_restart(IDEState *s); -void ide_atapi_io_error(IDEState *s, int ret); - -void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val); -uint32_t ide_ioport_read(void *opaque, uint32_t addr1); -uint32_t ide_status_read(void *opaque, uint32_t addr); -void ide_cmd_write(void *opaque, uint32_t addr, uint32_t val); -void ide_data_writew(void *opaque, uint32_t addr, uint32_t val); -uint32_t ide_data_readw(void *opaque, uint32_t addr); -void ide_data_writel(void *opaque, uint32_t addr, uint32_t val); -uint32_t ide_data_readl(void *opaque, uint32_t addr); - -int ide_init_drive(IDEState *s, BlockBackend *blk, IDEDriveKind kind, - const char *version, const char *serial, const char *model, - uint64_t wwn, - uint32_t cylinders, uint32_t heads, uint32_t secs, - int chs_trans); -void ide_init2(IDEBus *bus, qemu_irq irq); -void ide_init_ioport(IDEBus *bus, ISADevice *isa, int iobase, int iobase2); -void ide_register_restart_cb(IDEBus *bus); - -void ide_exec_cmd(IDEBus *bus, uint32_t val); - -void ide_transfer_start(IDEState *s, uint8_t *buf, int size, - EndTransferFunc *end_transfer_func); -void ide_transfer_stop(IDEState *s); -void ide_set_inactive(IDEState *s, bool more); -BlockAIOCB *ide_issue_trim( - int64_t offset, QEMUIOVector *qiov, - BlockCompletionFunc *cb, void *cb_opaque, void *opaque); -BlockAIOCB *ide_buffered_readv(IDEState *s, int64_t sector_num, - QEMUIOVector *iov, int nb_sectors, - BlockCompletionFunc *cb, void *opaque); -void ide_cancel_dma_sync(IDEState *s); - -/* hw/ide/atapi.c */ -void ide_atapi_cmd(IDEState *s); -void ide_atapi_cmd_reply_end(IDEState *s); - -/* hw/ide/qdev.c */ -void ide_bus_new(IDEBus *idebus, size_t idebus_size, DeviceState *dev, - int bus_id, int max_units); -IDEDevice *ide_create_drive(IDEBus *bus, int unit, DriveInfo *drive); - -int ide_handle_rw_error(IDEState *s, int error, int op); - -#endif /* HW_IDE_INTERNAL_H */ diff --git a/hw/ide/pci.h b/hw/ide/pci.h deleted file mode 100644 index 0f2d4b9..0000000 --- a/hw/ide/pci.h +++ /dev/null @@ -1,76 +0,0 @@ -#ifndef HW_IDE_PCI_H -#define HW_IDE_PCI_H - -#include <hw/ide/internal.h> - -#define BM_STATUS_DMAING 0x01 -#define BM_STATUS_ERROR 0x02 -#define BM_STATUS_INT 0x04 - -#define BM_CMD_START 0x01 -#define BM_CMD_READ 0x08 - -typedef struct BMDMAState { - IDEDMA dma; - uint8_t cmd; - uint8_t status; - uint32_t addr; - - IDEBus *bus; - /* current transfer state */ - uint32_t cur_addr; - uint32_t cur_prd_last; - uint32_t cur_prd_addr; - uint32_t cur_prd_len; - BlockCompletionFunc *dma_cb; - MemoryRegion addr_ioport; - MemoryRegion extra_io; - qemu_irq irq; - - /* Bit 0-2 and 7: BM status register - * Bit 3-6: bus->error_status */ - uint8_t migration_compat_status; - uint8_t migration_retry_unit; - int64_t migration_retry_sector_num; - uint32_t migration_retry_nsector; - - struct PCIIDEState *pci_dev; -} BMDMAState; - -typedef struct CMD646BAR { - MemoryRegion cmd; - MemoryRegion data; - IDEBus *bus; - struct PCIIDEState *pci_dev; -} CMD646BAR; - -#define TYPE_PCI_IDE "pci-ide" -#define PCI_IDE(obj) OBJECT_CHECK(PCIIDEState, (obj), TYPE_PCI_IDE) - -typedef struct PCIIDEState { - /*< private >*/ - PCIDevice parent_obj; - /*< public >*/ - - IDEBus bus[2]; - BMDMAState bmdma[2]; - uint32_t secondary; /* used only for cmd646 */ - MemoryRegion bmdma_bar; - CMD646BAR cmd646_bar[2]; /* used only for cmd646 */ -} PCIIDEState; - - -static inline IDEState *bmdma_active_if(BMDMAState *bmdma) -{ - assert(bmdma->bus->retry_unit != (uint8_t)-1); - return bmdma->bus->ifs + bmdma->bus->retry_unit; -} - - -void bmdma_init(IDEBus *bus, BMDMAState *bm, PCIIDEState *d); -void bmdma_cmd_writeb(BMDMAState *bm, uint32_t val); -extern MemoryRegionOps bmdma_addr_ioport_ops; -void pci_ide_create_devs(PCIDevice *dev, DriveInfo **hd_table); - -extern const VMStateDescription vmstate_ide_pci; -#endif diff --git a/include/hw/ide/ahci.h b/include/hw/ide/ahci.h new file mode 100644 index 0000000..bc777ed --- /dev/null +++ b/include/hw/ide/ahci.h @@ -0,0 +1,405 @@ +/* + * QEMU AHCI Emulation + * + * Copyright (c) 2010 qiaochong@loongson.cn + * Copyright (c) 2010 Roland Elek <elek.roland@gmail.com> + * Copyright (c) 2010 Sebastian Herbszt <herbszt@gmx.de> + * Copyright (c) 2010 Alexander Graf <agraf@suse.de> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + * + */ + +#ifndef HW_IDE_AHCI_H +#define HW_IDE_AHCI_H + +#include <hw/sysbus.h> + +#define AHCI_MEM_BAR_SIZE 0x1000 +#define AHCI_MAX_PORTS 32 +#define AHCI_MAX_SG 168 /* hardware max is 64K */ +#define AHCI_DMA_BOUNDARY 0xffffffff +#define AHCI_USE_CLUSTERING 0 +#define AHCI_MAX_CMDS 32 +#define AHCI_CMD_SZ 32 +#define AHCI_CMD_SLOT_SZ (AHCI_MAX_CMDS * AHCI_CMD_SZ) +#define AHCI_RX_FIS_SZ 256 +#define AHCI_CMD_TBL_CDB 0x40 +#define AHCI_CMD_TBL_HDR_SZ 0x80 +#define AHCI_CMD_TBL_SZ (AHCI_CMD_TBL_HDR_SZ + (AHCI_MAX_SG * 16)) +#define AHCI_CMD_TBL_AR_SZ (AHCI_CMD_TBL_SZ * AHCI_MAX_CMDS) +#define AHCI_PORT_PRIV_DMA_SZ (AHCI_CMD_SLOT_SZ + AHCI_CMD_TBL_AR_SZ + \ + AHCI_RX_FIS_SZ) + +#define AHCI_IRQ_ON_SG (1U << 31) +#define AHCI_CMD_ATAPI (1 << 5) +#define AHCI_CMD_WRITE (1 << 6) +#define AHCI_CMD_PREFETCH (1 << 7) +#define AHCI_CMD_RESET (1 << 8) +#define AHCI_CMD_CLR_BUSY (1 << 10) + +#define RX_FIS_D2H_REG 0x40 /* offset of D2H Register FIS data */ +#define RX_FIS_SDB 0x58 /* offset of SDB FIS data */ +#define RX_FIS_UNK 0x60 /* offset of Unknown FIS data */ + +/* global controller registers */ +#define HOST_CAP 0x00 /* host capabilities */ +#define HOST_CTL 0x04 /* global host control */ +#define HOST_IRQ_STAT 0x08 /* interrupt status */ +#define HOST_PORTS_IMPL 0x0c /* bitmap of implemented ports */ +#define HOST_VERSION 0x10 /* AHCI spec. version compliancy */ + +/* HOST_CTL bits */ +#define HOST_CTL_RESET (1 << 0) /* reset controller; self-clear */ +#define HOST_CTL_IRQ_EN (1 << 1) /* global IRQ enable */ +#define HOST_CTL_AHCI_EN (1U << 31) /* AHCI enabled */ + +/* HOST_CAP bits */ +#define HOST_CAP_SSC (1 << 14) /* Slumber capable */ +#define HOST_CAP_AHCI (1 << 18) /* AHCI only */ +#define HOST_CAP_CLO (1 << 24) /* Command List Override support */ +#define HOST_CAP_SSS (1 << 27) /* Staggered Spin-up */ +#define HOST_CAP_NCQ (1 << 30) /* Native Command Queueing */ +#define HOST_CAP_64 (1U << 31) /* PCI DAC (64-bit DMA) support */ + +/* registers for each SATA port */ +#define PORT_LST_ADDR 0x00 /* command list DMA addr */ +#define PORT_LST_ADDR_HI 0x04 /* command list DMA addr hi */ +#define PORT_FIS_ADDR 0x08 /* FIS rx buf addr */ +#define PORT_FIS_ADDR_HI 0x0c /* FIS rx buf addr hi */ +#define PORT_IRQ_STAT 0x10 /* interrupt status */ +#define PORT_IRQ_MASK 0x14 /* interrupt enable/disable mask */ +#define PORT_CMD 0x18 /* port command */ +#define PORT_TFDATA 0x20 /* taskfile data */ +#define PORT_SIG 0x24 /* device TF signature */ +#define PORT_SCR_STAT 0x28 /* SATA phy register: SStatus */ +#define PORT_SCR_CTL 0x2c /* SATA phy register: SControl */ +#define PORT_SCR_ERR 0x30 /* SATA phy register: SError */ +#define PORT_SCR_ACT 0x34 /* SATA phy register: SActive */ +#define PORT_CMD_ISSUE 0x38 /* command issue */ +#define PORT_RESERVED 0x3c /* reserved */ + +/* PORT_IRQ_{STAT,MASK} bits */ +#define PORT_IRQ_COLD_PRES (1U << 31) /* cold presence detect */ +#define PORT_IRQ_TF_ERR (1 << 30) /* task file error */ +#define PORT_IRQ_HBUS_ERR (1 << 29) /* host bus fatal error */ +#define PORT_IRQ_HBUS_DATA_ERR (1 << 28) /* host bus data error */ +#define PORT_IRQ_IF_ERR (1 << 27) /* interface fatal error */ +#define PORT_IRQ_IF_NONFATAL (1 << 26) /* interface non-fatal error */ +#define PORT_IRQ_OVERFLOW (1 << 24) /* xfer exhausted available S/G */ +#define PORT_IRQ_BAD_PMP (1 << 23) /* incorrect port multiplier */ + +#define PORT_IRQ_PHYRDY (1 << 22) /* PhyRdy changed */ +#define PORT_IRQ_DEV_ILCK (1 << 7) /* device interlock */ +#define PORT_IRQ_CONNECT (1 << 6) /* port connect change status */ +#define PORT_IRQ_SG_DONE (1 << 5) /* descriptor processed */ +#define PORT_IRQ_UNK_FIS (1 << 4) /* unknown FIS rx'd */ +#define PORT_IRQ_SDB_FIS (1 << 3) /* Set Device Bits FIS rx'd */ +#define PORT_IRQ_DMAS_FIS (1 << 2) /* DMA Setup FIS rx'd */ +#define PORT_IRQ_PIOS_FIS (1 << 1) /* PIO Setup FIS rx'd */ +#define PORT_IRQ_D2H_REG_FIS (1 << 0) /* D2H Register FIS rx'd */ + +#define PORT_IRQ_FREEZE (PORT_IRQ_HBUS_ERR | PORT_IRQ_IF_ERR | \ + PORT_IRQ_CONNECT | PORT_IRQ_PHYRDY | \ + PORT_IRQ_UNK_FIS) +#define PORT_IRQ_ERROR (PORT_IRQ_FREEZE | PORT_IRQ_TF_ERR | \ + PORT_IRQ_HBUS_DATA_ERR) +#define DEF_PORT_IRQ (PORT_IRQ_ERROR | PORT_IRQ_SG_DONE | \ + PORT_IRQ_SDB_FIS | PORT_IRQ_DMAS_FIS | \ + PORT_IRQ_PIOS_FIS | PORT_IRQ_D2H_REG_FIS) + +/* PORT_CMD bits */ +#define PORT_CMD_ATAPI (1 << 24) /* Device is ATAPI */ +#define PORT_CMD_LIST_ON (1 << 15) /* cmd list DMA engine running */ +#define PORT_CMD_FIS_ON (1 << 14) /* FIS DMA engine running */ +#define PORT_CMD_FIS_RX (1 << 4) /* Enable FIS receive DMA engine */ +#define PORT_CMD_CLO (1 << 3) /* Command list override */ +#define PORT_CMD_POWER_ON (1 << 2) /* Power up device */ +#define PORT_CMD_SPIN_UP (1 << 1) /* Spin up device */ +#define PORT_CMD_START (1 << 0) /* Enable port DMA engine */ + +#define PORT_CMD_ICC_MASK (0xfU << 28) /* i/f ICC state mask */ +#define PORT_CMD_ICC_ACTIVE (0x1 << 28) /* Put i/f in active state */ +#define PORT_CMD_ICC_PARTIAL (0x2 << 28) /* Put i/f in partial state */ +#define PORT_CMD_ICC_SLUMBER (0x6 << 28) /* Put i/f in slumber state */ + +#define PORT_CMD_RO_MASK 0x007dffe0 /* Which CMD bits are read only? */ + +/* ap->flags bits */ +#define AHCI_FLAG_NO_NCQ (1 << 24) +#define AHCI_FLAG_IGN_IRQ_IF_ERR (1 << 25) /* ignore IRQ_IF_ERR */ +#define AHCI_FLAG_HONOR_PI (1 << 26) /* honor PORTS_IMPL */ +#define AHCI_FLAG_IGN_SERR_INTERNAL (1 << 27) /* ignore SERR_INTERNAL */ +#define AHCI_FLAG_32BIT_ONLY (1 << 28) /* force 32bit */ + +#define ATA_SRST (1 << 2) /* software reset */ + +#define STATE_RUN 0 +#define STATE_RESET 1 + +#define SATA_SCR_SSTATUS_DET_NODEV 0x0 +#define SATA_SCR_SSTATUS_DET_DEV_PRESENT_PHY_UP 0x3 + +#define SATA_SCR_SSTATUS_SPD_NODEV 0x00 +#define SATA_SCR_SSTATUS_SPD_GEN1 0x10 + +#define SATA_SCR_SSTATUS_IPM_NODEV 0x000 +#define SATA_SCR_SSTATUS_IPM_ACTIVE 0X100 + +#define AHCI_SCR_SCTL_DET 0xf + +#define SATA_FIS_TYPE_REGISTER_H2D 0x27 +#define SATA_FIS_REG_H2D_UPDATE_COMMAND_REGISTER 0x80 +#define SATA_FIS_TYPE_REGISTER_D2H 0x34 +#define SATA_FIS_TYPE_PIO_SETUP 0x5f +#define SATA_FIS_TYPE_SDB 0xA1 + +#define AHCI_CMD_HDR_CMD_FIS_LEN 0x1f +#define AHCI_CMD_HDR_PRDT_LEN 16 + +#define SATA_SIGNATURE_CDROM 0xeb140101 +#define SATA_SIGNATURE_DISK 0x00000101 + +#define AHCI_GENERIC_HOST_CONTROL_REGS_MAX_ADDR 0x20 + /* Shouldn't this be 0x2c? */ + +#define AHCI_PORT_REGS_START_ADDR 0x100 +#define AHCI_PORT_ADDR_OFFSET_MASK 0x7f +#define AHCI_PORT_ADDR_OFFSET_LEN 0x80 + +#define AHCI_NUM_COMMAND_SLOTS 31 +#define AHCI_SUPPORTED_SPEED 20 +#define AHCI_SUPPORTED_SPEED_GEN1 1 +#define AHCI_VERSION_1_0 0x10000 + +#define AHCI_PROGMODE_MAJOR_REV_1 1 + +#define AHCI_COMMAND_TABLE_ACMD 0x40 + +#define AHCI_PRDT_SIZE_MASK 0x3fffff + +#define IDE_FEATURE_DMA 1 + +#define READ_FPDMA_QUEUED 0x60 +#define WRITE_FPDMA_QUEUED 0x61 +#define NCQ_NON_DATA 0x63 +#define RECEIVE_FPDMA_QUEUED 0x65 +#define SEND_FPDMA_QUEUED 0x64 + +#define NCQ_FIS_FUA_MASK 0x80 +#define NCQ_FIS_RARC_MASK 0x01 + +#define RES_FIS_DSFIS 0x00 +#define RES_FIS_PSFIS 0x20 +#define RES_FIS_RFIS 0x40 +#define RES_FIS_SDBFIS 0x58 +#define RES_FIS_UFIS 0x60 + +#define SATA_CAP_SIZE 0x8 +#define SATA_CAP_REV 0x2 +#define SATA_CAP_BAR 0x4 + +typedef struct AHCIControlRegs { + uint32_t cap; + uint32_t ghc; + uint32_t irqstatus; + uint32_t impl; + uint32_t version; +} AHCIControlRegs; + +typedef struct AHCIPortRegs { + uint32_t lst_addr; + uint32_t lst_addr_hi; + uint32_t fis_addr; + uint32_t fis_addr_hi; + uint32_t irq_stat; + uint32_t irq_mask; + uint32_t cmd; + uint32_t unused0; + uint32_t tfdata; + uint32_t sig; + uint32_t scr_stat; + uint32_t scr_ctl; + uint32_t scr_err; + uint32_t scr_act; + uint32_t cmd_issue; + uint32_t reserved; +} AHCIPortRegs; + +typedef struct AHCICmdHdr { + uint16_t opts; + uint16_t prdtl; + uint32_t status; + uint64_t tbl_addr; + uint32_t reserved[4]; +} QEMU_PACKED AHCICmdHdr; + +typedef struct AHCI_SG { + uint64_t addr; + uint32_t reserved; + uint32_t flags_size; +} QEMU_PACKED AHCI_SG; + +typedef struct AHCIDevice AHCIDevice; + +typedef struct NCQTransferState { + AHCIDevice *drive; + BlockAIOCB *aiocb; + AHCICmdHdr *cmdh; + QEMUSGList sglist; + BlockAcctCookie acct; + uint32_t sector_count; + uint64_t lba; + uint8_t tag; + uint8_t cmd; + uint8_t slot; + bool used; + bool halt; +} NCQTransferState; + +struct AHCIDevice { + IDEDMA dma; + IDEBus port; + int port_no; + uint32_t port_state; + uint32_t finished; + AHCIPortRegs port_regs; + struct AHCIState *hba; + QEMUBH *check_bh; + uint8_t *lst; + uint8_t *res_fis; + bool done_atapi_packet; + int32_t busy_slot; + bool init_d2h_sent; + AHCICmdHdr *cur_cmd; + NCQTransferState ncq_tfs[AHCI_MAX_CMDS]; +}; + +typedef struct AHCIState { + DeviceState *container; + + AHCIDevice *dev; + AHCIControlRegs control_regs; + MemoryRegion mem; + MemoryRegion idp; /* Index-Data Pair I/O port space */ + unsigned idp_offset; /* Offset of index in I/O port space */ + uint32_t idp_index; /* Current IDP index */ + int32_t ports; + qemu_irq irq; + AddressSpace *as; +} AHCIState; + +typedef struct AHCIPCIState { + /*< private >*/ + PCIDevice parent_obj; + /*< public >*/ + + AHCIState ahci; +} AHCIPCIState; + +#define TYPE_ICH9_AHCI "ich9-ahci" + +#define ICH_AHCI(obj) \ + OBJECT_CHECK(AHCIPCIState, (obj), TYPE_ICH9_AHCI) + +extern const VMStateDescription vmstate_ahci; + +#define VMSTATE_AHCI(_field, _state) { \ + .name = (stringify(_field)), \ + .size = sizeof(AHCIState), \ + .vmsd = &vmstate_ahci, \ + .flags = VMS_STRUCT, \ + .offset = vmstate_offset_value(_state, _field, AHCIState), \ +} + +/** + * NCQFrame is the same as a Register H2D FIS (described in SATA 3.2), + * but some fields have been re-mapped and re-purposed, as seen in + * SATA 3.2 section 13.6.4.1 ("READ FPDMA QUEUED") + * + * cmd_fis[3], feature 7:0, becomes sector count 7:0. + * cmd_fis[7], device 7:0, uses bit 7 as the Force Unit Access bit. + * cmd_fis[11], feature 15:8, becomes sector count 15:8. + * cmd_fis[12], count 7:0, becomes the NCQ TAG (7:3) and RARC bit (0) + * cmd_fis[13], count 15:8, becomes the priority value (7:6) + * bytes 16-19 become an le32 "auxiliary" field. + */ +typedef struct NCQFrame { + uint8_t fis_type; + uint8_t c; + uint8_t command; + uint8_t sector_count_low; /* (feature 7:0) */ + uint8_t lba0; + uint8_t lba1; + uint8_t lba2; + uint8_t fua; /* (device 7:0) */ + uint8_t lba3; + uint8_t lba4; + uint8_t lba5; + uint8_t sector_count_high; /* (feature 15:8) */ + uint8_t tag; /* (count 0:7) */ + uint8_t prio; /* (count 15:8) */ + uint8_t icc; + uint8_t control; + uint8_t aux0; + uint8_t aux1; + uint8_t aux2; + uint8_t aux3; +} QEMU_PACKED NCQFrame; + +typedef struct SDBFIS { + uint8_t type; + uint8_t flags; + uint8_t status; + uint8_t error; + uint32_t payload; +} QEMU_PACKED SDBFIS; + +void ahci_realize(AHCIState *s, DeviceState *qdev, AddressSpace *as, int ports); +void ahci_init(AHCIState *s, DeviceState *qdev); +void ahci_uninit(AHCIState *s); + +void ahci_reset(AHCIState *s); + +void ahci_ide_create_devs(PCIDevice *dev, DriveInfo **hd); + +#define TYPE_SYSBUS_AHCI "sysbus-ahci" +#define SYSBUS_AHCI(obj) OBJECT_CHECK(SysbusAHCIState, (obj), TYPE_SYSBUS_AHCI) + +typedef struct SysbusAHCIState { + /*< private >*/ + SysBusDevice parent_obj; + /*< public >*/ + + AHCIState ahci; + uint32_t num_ports; +} SysbusAHCIState; + +#define TYPE_ALLWINNER_AHCI "allwinner-ahci" +#define ALLWINNER_AHCI(obj) OBJECT_CHECK(AllwinnerAHCIState, (obj), \ + TYPE_ALLWINNER_AHCI) + +#define ALLWINNER_AHCI_MMIO_OFF 0x80 +#define ALLWINNER_AHCI_MMIO_SIZE 0x80 + +struct AllwinnerAHCIState { + /*< private >*/ + SysbusAHCIState parent_obj; + /*< public >*/ + + MemoryRegion mmio; + uint32_t regs[ALLWINNER_AHCI_MMIO_SIZE/4]; +}; + +#endif /* HW_IDE_AHCI_H */ diff --git a/include/hw/ide/internal.h b/include/hw/ide/internal.h new file mode 100644 index 0000000..773928a --- /dev/null +++ b/include/hw/ide/internal.h @@ -0,0 +1,635 @@ +#ifndef HW_IDE_INTERNAL_H +#define HW_IDE_INTERNAL_H + +/* + * QEMU IDE Emulation -- internal header file + * only files in hw/ide/ are supposed to include this file. + * non-internal declarations are in hw/ide.h + */ +#include <hw/ide.h> +#include <hw/isa/isa.h> +#include "sysemu/dma.h" +#include "sysemu/sysemu.h" +#include "hw/block/block.h" +#include "block/scsi.h" + +/* debug IDE devices */ +//#define DEBUG_IDE +//#define DEBUG_IDE_ATAPI +//#define DEBUG_AIO +#define USE_DMA_CDROM + +typedef struct IDEBus IDEBus; +typedef struct IDEDevice IDEDevice; +typedef struct IDEState IDEState; +typedef struct IDEDMA IDEDMA; +typedef struct IDEDMAOps IDEDMAOps; + +#define TYPE_IDE_BUS "IDE" +#define IDE_BUS(obj) OBJECT_CHECK(IDEBus, (obj), TYPE_IDE_BUS) + +/* Bits of HD_STATUS */ +#define ERR_STAT 0x01 +#define INDEX_STAT 0x02 +#define ECC_STAT 0x04 /* Corrected error */ +#define DRQ_STAT 0x08 +#define SEEK_STAT 0x10 +#define SRV_STAT 0x10 +#define WRERR_STAT 0x20 +#define READY_STAT 0x40 +#define BUSY_STAT 0x80 + +/* Bits for HD_ERROR */ +#define MARK_ERR 0x01 /* Bad address mark */ +#define TRK0_ERR 0x02 /* couldn't find track 0 */ +#define ABRT_ERR 0x04 /* Command aborted */ +#define MCR_ERR 0x08 /* media change request */ +#define ID_ERR 0x10 /* ID field not found */ +#define MC_ERR 0x20 /* media changed */ +#define ECC_ERR 0x40 /* Uncorrectable ECC error */ +#define BBD_ERR 0x80 /* pre-EIDE meaning: block marked bad */ +#define ICRC_ERR 0x80 /* new meaning: CRC error during transfer */ + +/* Bits of HD_NSECTOR */ +#define CD 0x01 +#define IO 0x02 +#define REL 0x04 +#define TAG_MASK 0xf8 + +#define IDE_CMD_RESET 0x04 +#define IDE_CMD_DISABLE_IRQ 0x02 + +/* ACS-2 T13/2015-D Table B.2 Command codes */ +#define WIN_NOP 0x00 +/* reserved 0x01..0x02 */ +#define CFA_REQ_EXT_ERROR_CODE 0x03 /* CFA Request Extended Error Code */ +/* reserved 0x04..0x05 */ +#define WIN_DSM 0x06 +/* reserved 0x07 */ +#define WIN_DEVICE_RESET 0x08 +/* reserved 0x09..0x0a */ +/* REQUEST SENSE DATA EXT 0x0B */ +/* reserved 0x0C..0x0F */ +#define WIN_RECAL 0x10 /* obsolete since ATA4 */ +/* obsolete since ATA3, retired in ATA4 0x11..0x1F */ +#define WIN_READ 0x20 /* 28-Bit */ +#define WIN_READ_ONCE 0x21 /* 28-Bit w/o retries, obsolete since ATA5 */ +/* obsolete since ATA4 0x22..0x23 */ +#define WIN_READ_EXT 0x24 /* 48-Bit */ +#define WIN_READDMA_EXT 0x25 /* 48-Bit */ +#define WIN_READDMA_QUEUED_EXT 0x26 /* 48-Bit, obsolete since ACS2 */ +#define WIN_READ_NATIVE_MAX_EXT 0x27 /* 48-Bit */ +/* reserved 0x28 */ +#define WIN_MULTREAD_EXT 0x29 /* 48-Bit */ +/* READ STREAM DMA EXT 0x2A */ +/* READ STREAM EXT 0x2B */ +/* reserved 0x2C..0x2E */ +/* READ LOG EXT 0x2F */ +#define WIN_WRITE 0x30 /* 28-Bit */ +#define WIN_WRITE_ONCE 0x31 /* 28-Bit w/o retries, obsolete since ATA5 */ +/* obsolete since ATA4 0x32..0x33 */ +#define WIN_WRITE_EXT 0x34 /* 48-Bit */ +#define WIN_WRITEDMA_EXT 0x35 /* 48-Bit */ +#define WIN_WRITEDMA_QUEUED_EXT 0x36 /* 48-Bit */ +#define WIN_SET_MAX_EXT 0x37 /* 48-Bit, obsolete since ACS2 */ +#define WIN_SET_MAX_EXT 0x37 /* 48-Bit */ +#define CFA_WRITE_SECT_WO_ERASE 0x38 /* CFA Write Sectors without erase */ +#define WIN_MULTWRITE_EXT 0x39 /* 48-Bit */ +/* WRITE STREAM DMA EXT 0x3A */ +/* WRITE STREAM EXT 0x3B */ +#define WIN_WRITE_VERIFY 0x3C /* 28-Bit, obsolete since ATA4 */ +/* WRITE DMA FUA EXT 0x3D */ +/* obsolete since ACS2 0x3E */ +/* WRITE LOG EXT 0x3F */ +#define WIN_VERIFY 0x40 /* 28-Bit - Read Verify Sectors */ +#define WIN_VERIFY_ONCE 0x41 /* 28-Bit - w/o retries, obsolete since ATA5 */ +#define WIN_VERIFY_EXT 0x42 /* 48-Bit */ +/* reserved 0x43..0x44 */ +/* WRITE UNCORRECTABLE EXT 0x45 */ +/* reserved 0x46 */ +/* READ LOG DMA EXT 0x47 */ +/* reserved 0x48..0x4F */ +/* obsolete since ATA4 0x50 */ +/* CONFIGURE STREAM 0x51 */ +/* reserved 0x52..0x56 */ +/* WRITE LOG DMA EXT 0x57 */ +/* reserved 0x58..0x5A */ +/* TRUSTED NON DATA 0x5B */ +/* TRUSTED RECEIVE 0x5C */ +/* TRUSTED RECEIVE DMA 0x5D */ +/* TRUSTED SEND 0x5E */ +/* TRUSTED SEND DMA 0x5F */ +/* READ FPDMA QUEUED 0x60 */ +/* WRITE FPDMA QUEUED 0x61 */ +/* reserved 0x62->0x6F */ +#define WIN_SEEK 0x70 /* obsolete since ATA7 */ +/* reserved 0x71-0x7F */ +/* vendor specific 0x80-0x86 */ +#define CFA_TRANSLATE_SECTOR 0x87 /* CFA Translate Sector */ +/* vendor specific 0x88-0x8F */ +#define WIN_DIAGNOSE 0x90 +#define WIN_SPECIFY 0x91 /* set drive geometry translation, obsolete since ATA6 */ +#define WIN_DOWNLOAD_MICROCODE 0x92 +/* DOWNLOAD MICROCODE DMA 0x93 */ +#define WIN_STANDBYNOW2 0x94 /* retired in ATA4 */ +#define WIN_IDLEIMMEDIATE2 0x95 /* force drive to become "ready", retired in ATA4 */ +#define WIN_STANDBY2 0x96 /* retired in ATA4 */ +#define WIN_SETIDLE2 0x97 /* retired in ATA4 */ +#define WIN_CHECKPOWERMODE2 0x98 /* retired in ATA4 */ +#define WIN_SLEEPNOW2 0x99 /* retired in ATA4 */ +/* vendor specific 0x9A */ +/* reserved 0x9B..0x9F */ +#define WIN_PACKETCMD 0xA0 /* Send a packet command. */ +#define WIN_PIDENTIFY 0xA1 /* identify ATAPI device */ +#define WIN_QUEUED_SERVICE 0xA2 /* obsolete since ACS2 */ +/* reserved 0xA3..0xAF */ +#define WIN_SMART 0xB0 /* self-monitoring and reporting */ +/* Device Configuration Overlay 0xB1 */ +/* reserved 0xB2..0xB3 */ +/* Sanitize Device 0xB4 */ +/* reserved 0xB5 */ +/* NV Cache 0xB6 */ +/* reserved for CFA 0xB7..0xBB */ +#define CFA_ACCESS_METADATA_STORAGE 0xB8 +/* reserved 0xBC..0xBF */ +#define CFA_ERASE_SECTORS 0xC0 /* microdrives implement as NOP */ +/* vendor specific 0xC1..0xC3 */ +#define WIN_MULTREAD 0xC4 /* read sectors using multiple mode*/ +#define WIN_MULTWRITE 0xC5 /* write sectors using multiple mode */ +#define WIN_SETMULT 0xC6 /* enable/disable multiple mode */ +#define WIN_READDMA_QUEUED 0xC7 /* read sectors using Queued DMA transfers, obsolete since ACS2 */ +#define WIN_READDMA 0xC8 /* read sectors using DMA transfers */ +#define WIN_READDMA_ONCE 0xC9 /* 28-Bit - w/o retries, obsolete since ATA5 */ +#define WIN_WRITEDMA 0xCA /* write sectors using DMA transfers */ +#define WIN_WRITEDMA_ONCE 0xCB /* 28-Bit - w/o retries, obsolete since ATA5 */ +#define WIN_WRITEDMA_QUEUED 0xCC /* write sectors using Queued DMA transfers, obsolete since ACS2 */ +#define CFA_WRITE_MULTI_WO_ERASE 0xCD /* CFA Write multiple without erase */ +/* WRITE MULTIPLE FUA EXT 0xCE */ +/* reserved 0xCF..0xDO */ +/* CHECK MEDIA CARD TYPE 0xD1 */ +/* reserved for media card pass through 0xD2..0xD4 */ +/* reserved 0xD5..0xD9 */ +#define WIN_GETMEDIASTATUS 0xDA /* obsolete since ATA8 */ +/* obsolete since ATA3, retired in ATA4 0xDB..0xDD */ +#define WIN_DOORLOCK 0xDE /* lock door on removable drives, obsolete since ATA8 */ +#define WIN_DOORUNLOCK 0xDF /* unlock door on removable drives, obsolete since ATA8 */ +#define WIN_STANDBYNOW1 0xE0 +#define WIN_IDLEIMMEDIATE 0xE1 /* force drive to become "ready" */ +#define WIN_STANDBY 0xE2 /* Set device in Standby Mode */ +#define WIN_SETIDLE1 0xE3 +#define WIN_READ_BUFFER 0xE4 /* force read only 1 sector */ +#define WIN_CHECKPOWERMODE1 0xE5 +#define WIN_SLEEPNOW1 0xE6 +#define WIN_FLUSH_CACHE 0xE7 +#define WIN_WRITE_BUFFER 0xE8 /* force write only 1 sector */ +/* READ BUFFER DMA 0xE9 */ +#define WIN_FLUSH_CACHE_EXT 0xEA /* 48-Bit */ +/* WRITE BUFFER DMA 0xEB */ +#define WIN_IDENTIFY 0xEC /* ask drive to identify itself */ +#define WIN_MEDIAEJECT 0xED /* obsolete since ATA8 */ +/* obsolete since ATA4 0xEE */ +#define WIN_SETFEATURES 0xEF /* set special drive features */ +#define IBM_SENSE_CONDITION 0xF0 /* measure disk temperature, vendor specific */ +#define WIN_SECURITY_SET_PASS 0xF1 +#define WIN_SECURITY_UNLOCK 0xF2 +#define WIN_SECURITY_ERASE_PREPARE 0xF3 +#define WIN_SECURITY_ERASE_UNIT 0xF4 +#define WIN_SECURITY_FREEZE_LOCK 0xF5 +#define CFA_WEAR_LEVEL 0xF5 /* microdrives implement as NOP; not specified in T13! */ +#define WIN_SECURITY_DISABLE 0xF6 +/* vendor specific 0xF7 */ +#define WIN_READ_NATIVE_MAX 0xF8 /* return the native maximum address */ +#define WIN_SET_MAX 0xF9 +/* vendor specific 0xFA..0xFF */ + +/* set to 1 set disable mult support */ +#define MAX_MULT_SECTORS 16 + +#define IDE_DMA_BUF_SECTORS 256 + +/* feature values for Data Set Management */ +#define DSM_TRIM 0x01 + +#if (IDE_DMA_BUF_SECTORS < MAX_MULT_SECTORS) +#error "IDE_DMA_BUF_SECTORS must be bigger or equal to MAX_MULT_SECTORS" +#endif + +/* ATAPI defines */ + +#define ATAPI_PACKET_SIZE 12 + +/* The generic packet command opcodes for CD/DVD Logical Units, + * From Table 57 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */ +#define GPCMD_BLANK 0xa1 +#define GPCMD_CLOSE_TRACK 0x5b +#define GPCMD_FLUSH_CACHE 0x35 +#define GPCMD_FORMAT_UNIT 0x04 +#define GPCMD_GET_CONFIGURATION 0x46 +#define GPCMD_GET_EVENT_STATUS_NOTIFICATION 0x4a +#define GPCMD_GET_PERFORMANCE 0xac +#define GPCMD_INQUIRY 0x12 +#define GPCMD_LOAD_UNLOAD 0xa6 +#define GPCMD_MECHANISM_STATUS 0xbd +#define GPCMD_MODE_SELECT_10 0x55 +#define GPCMD_MODE_SENSE_10 0x5a +#define GPCMD_PAUSE_RESUME 0x4b +#define GPCMD_PLAY_AUDIO_10 0x45 +#define GPCMD_PLAY_AUDIO_MSF 0x47 +#define GPCMD_PLAY_AUDIO_TI 0x48 +#define GPCMD_PLAY_CD 0xbc +#define GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1e +#define GPCMD_READ_10 0x28 +#define GPCMD_READ_12 0xa8 +#define GPCMD_READ_CDVD_CAPACITY 0x25 +#define GPCMD_READ_CD 0xbe +#define GPCMD_READ_CD_MSF 0xb9 +#define GPCMD_READ_DISC_INFO 0x51 +#define GPCMD_READ_DVD_STRUCTURE 0xad +#define GPCMD_READ_FORMAT_CAPACITIES 0x23 +#define GPCMD_READ_HEADER 0x44 +#define GPCMD_READ_TRACK_RZONE_INFO 0x52 +#define GPCMD_READ_SUBCHANNEL 0x42 +#define GPCMD_READ_TOC_PMA_ATIP 0x43 +#define GPCMD_REPAIR_RZONE_TRACK 0x58 +#define GPCMD_REPORT_KEY 0xa4 +#define GPCMD_REQUEST_SENSE 0x03 +#define GPCMD_RESERVE_RZONE_TRACK 0x53 +#define GPCMD_SCAN 0xba +#define GPCMD_SEEK 0x2b +#define GPCMD_SEND_DVD_STRUCTURE 0xad +#define GPCMD_SEND_EVENT 0xa2 +#define GPCMD_SEND_KEY 0xa3 +#define GPCMD_SEND_OPC 0x54 +#define GPCMD_SET_READ_AHEAD 0xa7 +#define GPCMD_SET_STREAMING 0xb6 +#define GPCMD_START_STOP_UNIT 0x1b +#define GPCMD_STOP_PLAY_SCAN 0x4e +#define GPCMD_TEST_UNIT_READY 0x00 +#define GPCMD_VERIFY_10 0x2f +#define GPCMD_WRITE_10 0x2a +#define GPCMD_WRITE_AND_VERIFY_10 0x2e +/* This is listed as optional in ATAPI 2.6, but is (curiously) + * missing from Mt. Fuji, Table 57. It _is_ mentioned in Mt. Fuji + * Table 377 as an MMC command for SCSi devices though... Most ATAPI + * drives support it. */ +#define GPCMD_SET_SPEED 0xbb +/* This seems to be a SCSI specific CD-ROM opcode + * to play data at track/index */ +#define GPCMD_PLAYAUDIO_TI 0x48 +/* + * From MS Media Status Notification Support Specification. For + * older drives only. + */ +#define GPCMD_GET_MEDIA_STATUS 0xda +#define GPCMD_MODE_SENSE_6 0x1a + +#define ATAPI_INT_REASON_CD 0x01 /* 0 = data transfer */ +#define ATAPI_INT_REASON_IO 0x02 /* 1 = transfer to the host */ +#define ATAPI_INT_REASON_REL 0x04 +#define ATAPI_INT_REASON_TAG 0xf8 + +/* same constants as bochs */ +#define ASC_NO_SEEK_COMPLETE 0x02 +#define ASC_ILLEGAL_OPCODE 0x20 +#define ASC_LOGICAL_BLOCK_OOR 0x21 +#define ASC_INV_FIELD_IN_CMD_PACKET 0x24 +#define ASC_MEDIUM_MAY_HAVE_CHANGED 0x28 +#define ASC_INCOMPATIBLE_FORMAT 0x30 +#define ASC_MEDIUM_NOT_PRESENT 0x3a +#define ASC_SAVING_PARAMETERS_NOT_SUPPORTED 0x39 +#define ASC_DATA_PHASE_ERROR 0x4b +#define ASC_MEDIA_REMOVAL_PREVENTED 0x53 + +#define CFA_NO_ERROR 0x00 +#define CFA_MISC_ERROR 0x09 +#define CFA_INVALID_COMMAND 0x20 +#define CFA_INVALID_ADDRESS 0x21 +#define CFA_ADDRESS_OVERFLOW 0x2f + +#define SMART_READ_DATA 0xd0 +#define SMART_READ_THRESH 0xd1 +#define SMART_ATTR_AUTOSAVE 0xd2 +#define SMART_SAVE_ATTR 0xd3 +#define SMART_EXECUTE_OFFLINE 0xd4 +#define SMART_READ_LOG 0xd5 +#define SMART_WRITE_LOG 0xd6 +#define SMART_ENABLE 0xd8 +#define SMART_DISABLE 0xd9 +#define SMART_STATUS 0xda + +typedef enum { IDE_HD, IDE_CD, IDE_CFATA } IDEDriveKind; + +typedef void EndTransferFunc(IDEState *); + +typedef void DMAStartFunc(IDEDMA *, IDEState *, BlockCompletionFunc *); +typedef void DMAVoidFunc(IDEDMA *); +typedef int DMAIntFunc(IDEDMA *, int); +typedef int32_t DMAInt32Func(IDEDMA *, int32_t len); +typedef void DMAu32Func(IDEDMA *, uint32_t); +typedef void DMAStopFunc(IDEDMA *, bool); +typedef void DMARestartFunc(void *, int, RunState); + +struct unreported_events { + bool eject_request; + bool new_media; +}; + +enum ide_dma_cmd { + IDE_DMA_READ, + IDE_DMA_WRITE, + IDE_DMA_TRIM, + IDE_DMA_ATAPI, +}; + +#define ide_cmd_is_read(s) \ + ((s)->dma_cmd == IDE_DMA_READ) + +typedef struct IDEBufferedRequest { + QLIST_ENTRY(IDEBufferedRequest) list; + struct iovec iov; + QEMUIOVector qiov; + QEMUIOVector *original_qiov; + BlockCompletionFunc *original_cb; + void *original_opaque; + bool orphaned; +} IDEBufferedRequest; + +/* NOTE: IDEState represents in fact one drive */ +struct IDEState { + IDEBus *bus; + uint8_t unit; + /* ide config */ + IDEDriveKind drive_kind; + int cylinders, heads, sectors, chs_trans; + int64_t nb_sectors; + int mult_sectors; + int identify_set; + uint8_t identify_data[512]; + int drive_serial; + char drive_serial_str[21]; + char drive_model_str[41]; + uint64_t wwn; + /* ide regs */ + uint8_t feature; + uint8_t error; + uint32_t nsector; + uint8_t sector; + uint8_t lcyl; + uint8_t hcyl; + /* other part of tf for lba48 support */ + uint8_t hob_feature; + uint8_t hob_nsector; + uint8_t hob_sector; + uint8_t hob_lcyl; + uint8_t hob_hcyl; + + uint8_t select; + uint8_t status; + + /* set for lba48 access */ + uint8_t lba48; + BlockBackend *blk; + char version[9]; + /* ATAPI specific */ + struct unreported_events events; + uint8_t sense_key; + uint8_t asc; + bool tray_open; + bool tray_locked; + uint8_t cdrom_changed; + int packet_transfer_size; + int elementary_transfer_size; + int32_t io_buffer_index; + int lba; + int cd_sector_size; + int atapi_dma; /* true if dma is requested for the packet cmd */ + BlockAcctCookie acct; + BlockAIOCB *pio_aiocb; + struct iovec iov; + QEMUIOVector qiov; + QLIST_HEAD(, IDEBufferedRequest) buffered_requests; + /* ATA DMA state */ + uint64_t io_buffer_offset; + int32_t io_buffer_size; + QEMUSGList sg; + /* PIO transfer handling */ + int req_nb_sectors; /* number of sectors per interrupt */ + EndTransferFunc *end_transfer_func; + uint8_t *data_ptr; + uint8_t *data_end; + uint8_t *io_buffer; + /* PIO save/restore */ + int32_t io_buffer_total_len; + int32_t cur_io_buffer_offset; + int32_t cur_io_buffer_len; + uint8_t end_transfer_fn_idx; + QEMUTimer *sector_write_timer; /* only used for win2k install hack */ + uint32_t irq_count; /* counts IRQs when using win2k install hack */ + /* CF-ATA extended error */ + uint8_t ext_error; + /* CF-ATA metadata storage */ + uint32_t mdata_size; + uint8_t *mdata_storage; + int media_changed; + enum ide_dma_cmd dma_cmd; + /* SMART */ + uint8_t smart_enabled; + uint8_t smart_autosave; + int smart_errors; + uint8_t smart_selftest_count; + uint8_t *smart_selftest_data; + /* AHCI */ + int ncq_queues; +}; + +struct IDEDMAOps { + DMAStartFunc *start_dma; + DMAVoidFunc *start_transfer; + DMAInt32Func *prepare_buf; + DMAu32Func *commit_buf; + DMAIntFunc *rw_buf; + DMAVoidFunc *restart; + DMAVoidFunc *restart_dma; + DMAStopFunc *set_inactive; + DMAVoidFunc *cmd_done; + DMAVoidFunc *reset; +}; + +struct IDEDMA { + const struct IDEDMAOps *ops; + struct iovec iov; + QEMUIOVector qiov; + BlockAIOCB *aiocb; +}; + +struct IDEBus { + BusState qbus; + IDEDevice *master; + IDEDevice *slave; + IDEState ifs[2]; + QEMUBH *bh; + + int bus_id; + int max_units; + IDEDMA *dma; + uint8_t unit; + uint8_t cmd; + qemu_irq irq; + + int error_status; + uint8_t retry_unit; + int64_t retry_sector_num; + uint32_t retry_nsector; +}; + +#define TYPE_IDE_DEVICE "ide-device" +#define IDE_DEVICE(obj) \ + OBJECT_CHECK(IDEDevice, (obj), TYPE_IDE_DEVICE) +#define IDE_DEVICE_CLASS(klass) \ + OBJECT_CLASS_CHECK(IDEDeviceClass, (klass), TYPE_IDE_DEVICE) +#define IDE_DEVICE_GET_CLASS(obj) \ + OBJECT_GET_CLASS(IDEDeviceClass, (obj), TYPE_IDE_DEVICE) + +typedef struct IDEDeviceClass { + DeviceClass parent_class; + int (*init)(IDEDevice *dev); +} IDEDeviceClass; + +struct IDEDevice { + DeviceState qdev; + uint32_t unit; + BlockConf conf; + int chs_trans; + char *version; + char *serial; + char *model; + uint64_t wwn; +}; + +/* These are used for the error_status field of IDEBus */ +#define IDE_RETRY_MASK 0xf8 +#define IDE_RETRY_DMA 0x08 +#define IDE_RETRY_PIO 0x10 +#define IDE_RETRY_ATAPI 0x20 /* reused IDE_RETRY_READ bit */ +#define IDE_RETRY_READ 0x20 +#define IDE_RETRY_FLUSH 0x40 +#define IDE_RETRY_TRIM 0x80 +#define IDE_RETRY_HBA 0x100 + +#define IS_IDE_RETRY_DMA(_status) \ + ((_status) & IDE_RETRY_DMA) + +#define IS_IDE_RETRY_PIO(_status) \ + ((_status) & IDE_RETRY_PIO) + +/* + * The method of the IDE_RETRY_ATAPI determination is to use a previously + * impossible bit combination as a new status value. + */ +#define IS_IDE_RETRY_ATAPI(_status) \ + (((_status) & IDE_RETRY_MASK) == IDE_RETRY_ATAPI) + +static inline uint8_t ide_dma_cmd_to_retry(uint8_t dma_cmd) +{ + switch (dma_cmd) { + case IDE_DMA_READ: + return IDE_RETRY_DMA | IDE_RETRY_READ; + case IDE_DMA_WRITE: + return IDE_RETRY_DMA; + case IDE_DMA_TRIM: + return IDE_RETRY_DMA | IDE_RETRY_TRIM; + case IDE_DMA_ATAPI: + return IDE_RETRY_ATAPI; + default: + break; + } + return 0; +} + +static inline IDEState *idebus_active_if(IDEBus *bus) +{ + return bus->ifs + bus->unit; +} + +static inline void ide_set_irq(IDEBus *bus) +{ + if (!(bus->cmd & IDE_CMD_DISABLE_IRQ)) { + qemu_irq_raise(bus->irq); + } +} + +/* hw/ide/core.c */ +extern const VMStateDescription vmstate_ide_bus; + +#define VMSTATE_IDE_BUS(_field, _state) \ + VMSTATE_STRUCT(_field, _state, 1, vmstate_ide_bus, IDEBus) + +#define VMSTATE_IDE_BUS_ARRAY(_field, _state, _num) \ + VMSTATE_STRUCT_ARRAY(_field, _state, _num, 1, vmstate_ide_bus, IDEBus) + +extern const VMStateDescription vmstate_ide_drive; + +#define VMSTATE_IDE_DRIVES(_field, _state) \ + VMSTATE_STRUCT_ARRAY(_field, _state, 2, 3, vmstate_ide_drive, IDEState) + +#define VMSTATE_IDE_DRIVE(_field, _state) \ + VMSTATE_STRUCT(_field, _state, 1, vmstate_ide_drive, IDEState) + +void ide_bus_reset(IDEBus *bus); +int64_t ide_get_sector(IDEState *s); +void ide_set_sector(IDEState *s, int64_t sector_num); + +void ide_start_dma(IDEState *s, BlockCompletionFunc *cb); +void dma_buf_commit(IDEState *s, uint32_t tx_bytes); +void ide_dma_error(IDEState *s); +void ide_abort_command(IDEState *s); + +void ide_atapi_cmd_ok(IDEState *s); +void ide_atapi_cmd_error(IDEState *s, int sense_key, int asc); +void ide_atapi_dma_restart(IDEState *s); +void ide_atapi_io_error(IDEState *s, int ret); + +void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val); +uint32_t ide_ioport_read(void *opaque, uint32_t addr1); +uint32_t ide_status_read(void *opaque, uint32_t addr); +void ide_cmd_write(void *opaque, uint32_t addr, uint32_t val); +void ide_data_writew(void *opaque, uint32_t addr, uint32_t val); +uint32_t ide_data_readw(void *opaque, uint32_t addr); +void ide_data_writel(void *opaque, uint32_t addr, uint32_t val); +uint32_t ide_data_readl(void *opaque, uint32_t addr); + +int ide_init_drive(IDEState *s, BlockBackend *blk, IDEDriveKind kind, + const char *version, const char *serial, const char *model, + uint64_t wwn, + uint32_t cylinders, uint32_t heads, uint32_t secs, + int chs_trans); +void ide_init2(IDEBus *bus, qemu_irq irq); +void ide_init_ioport(IDEBus *bus, ISADevice *isa, int iobase, int iobase2); +void ide_register_restart_cb(IDEBus *bus); + +void ide_exec_cmd(IDEBus *bus, uint32_t val); + +void ide_transfer_start(IDEState *s, uint8_t *buf, int size, + EndTransferFunc *end_transfer_func); +void ide_transfer_stop(IDEState *s); +void ide_set_inactive(IDEState *s, bool more); +BlockAIOCB *ide_issue_trim( + int64_t offset, QEMUIOVector *qiov, + BlockCompletionFunc *cb, void *cb_opaque, void *opaque); +BlockAIOCB *ide_buffered_readv(IDEState *s, int64_t sector_num, + QEMUIOVector *iov, int nb_sectors, + BlockCompletionFunc *cb, void *opaque); +void ide_cancel_dma_sync(IDEState *s); + +/* hw/ide/atapi.c */ +void ide_atapi_cmd(IDEState *s); +void ide_atapi_cmd_reply_end(IDEState *s); + +/* hw/ide/qdev.c */ +void ide_bus_new(IDEBus *idebus, size_t idebus_size, DeviceState *dev, + int bus_id, int max_units); +IDEDevice *ide_create_drive(IDEBus *bus, int unit, DriveInfo *drive); + +int ide_handle_rw_error(IDEState *s, int error, int op); + +#endif /* HW_IDE_INTERNAL_H */ diff --git a/include/hw/ide/pci.h b/include/hw/ide/pci.h new file mode 100644 index 0000000..0f2d4b9 --- /dev/null +++ b/include/hw/ide/pci.h @@ -0,0 +1,76 @@ +#ifndef HW_IDE_PCI_H +#define HW_IDE_PCI_H + +#include <hw/ide/internal.h> + +#define BM_STATUS_DMAING 0x01 +#define BM_STATUS_ERROR 0x02 +#define BM_STATUS_INT 0x04 + +#define BM_CMD_START 0x01 +#define BM_CMD_READ 0x08 + +typedef struct BMDMAState { + IDEDMA dma; + uint8_t cmd; + uint8_t status; + uint32_t addr; + + IDEBus *bus; + /* current transfer state */ + uint32_t cur_addr; + uint32_t cur_prd_last; + uint32_t cur_prd_addr; + uint32_t cur_prd_len; + BlockCompletionFunc *dma_cb; + MemoryRegion addr_ioport; + MemoryRegion extra_io; + qemu_irq irq; + + /* Bit 0-2 and 7: BM status register + * Bit 3-6: bus->error_status */ + uint8_t migration_compat_status; + uint8_t migration_retry_unit; + int64_t migration_retry_sector_num; + uint32_t migration_retry_nsector; + + struct PCIIDEState *pci_dev; +} BMDMAState; + +typedef struct CMD646BAR { + MemoryRegion cmd; + MemoryRegion data; + IDEBus *bus; + struct PCIIDEState *pci_dev; +} CMD646BAR; + +#define TYPE_PCI_IDE "pci-ide" +#define PCI_IDE(obj) OBJECT_CHECK(PCIIDEState, (obj), TYPE_PCI_IDE) + +typedef struct PCIIDEState { + /*< private >*/ + PCIDevice parent_obj; + /*< public >*/ + + IDEBus bus[2]; + BMDMAState bmdma[2]; + uint32_t secondary; /* used only for cmd646 */ + MemoryRegion bmdma_bar; + CMD646BAR cmd646_bar[2]; /* used only for cmd646 */ +} PCIIDEState; + + +static inline IDEState *bmdma_active_if(BMDMAState *bmdma) +{ + assert(bmdma->bus->retry_unit != (uint8_t)-1); + return bmdma->bus->ifs + bmdma->bus->retry_unit; +} + + +void bmdma_init(IDEBus *bus, BMDMAState *bm, PCIIDEState *d); +void bmdma_cmd_writeb(BMDMAState *bm, uint32_t val); +extern MemoryRegionOps bmdma_addr_ioport_ops; +void pci_ide_create_devs(PCIDevice *dev, DriveInfo **hd_table); + +extern const VMStateDescription vmstate_ide_pci; +#endif
The patch moves "hw/ide/achi.h", "hw/ide/pci.h" and "hw/ide/internal.h" headers to corresponding folders inside "include" folder alike other Qemu headers. Signed-off-by: Efimov Vasily <real@ispras.ru> --- This patch only moves headers (with the exception of include path correction in 'ahci.c'). checkpatch.pl reports a lot of problems with legacy code in these headers but I think this patch is not the place to fix these problem --- hw/ide/ahci.c | 2 +- hw/ide/ahci.h | 405 ----------------------------- hw/ide/internal.h | 635 ---------------------------------------------- hw/ide/pci.h | 76 ------ include/hw/ide/ahci.h | 405 +++++++++++++++++++++++++++++ include/hw/ide/internal.h | 635 ++++++++++++++++++++++++++++++++++++++++++++++ include/hw/ide/pci.h | 76 ++++++ 7 files changed, 1117 insertions(+), 1117 deletions(-) delete mode 100644 hw/ide/ahci.h delete mode 100644 hw/ide/internal.h delete mode 100644 hw/ide/pci.h create mode 100644 include/hw/ide/ahci.h create mode 100644 include/hw/ide/internal.h create mode 100644 include/hw/ide/pci.h