|
|
1.1 ! root 1: /* ! 2: * QEMU AHCI Emulation ! 3: * ! 4: * Copyright (c) 2010 [email protected] ! 5: * Copyright (c) 2010 Roland Elek <[email protected]> ! 6: * Copyright (c) 2010 Sebastian Herbszt <[email protected]> ! 7: * Copyright (c) 2010 Alexander Graf <[email protected]> ! 8: * ! 9: * This library is free software; you can redistribute it and/or ! 10: * modify it under the terms of the GNU Lesser General Public ! 11: * License as published by the Free Software Foundation; either ! 12: * version 2 of the License, or (at your option) any later version. ! 13: * ! 14: * This library is distributed in the hope that it will be useful, ! 15: * but WITHOUT ANY WARRANTY; without even the implied warranty of ! 16: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ! 17: * Lesser General Public License for more details. ! 18: * ! 19: * You should have received a copy of the GNU Lesser General Public ! 20: * License along with this library; if not, see <http://www.gnu.org/licenses/>. ! 21: * ! 22: */ ! 23: ! 24: #ifndef HW_IDE_AHCI_H ! 25: #define HW_IDE_AHCI_H ! 26: ! 27: #define AHCI_PCI_BAR 5 ! 28: #define AHCI_MAX_PORTS 32 ! 29: #define AHCI_MAX_SG 168 /* hardware max is 64K */ ! 30: #define AHCI_DMA_BOUNDARY 0xffffffff ! 31: #define AHCI_USE_CLUSTERING 0 ! 32: #define AHCI_MAX_CMDS 32 ! 33: #define AHCI_CMD_SZ 32 ! 34: #define AHCI_CMD_SLOT_SZ (AHCI_MAX_CMDS * AHCI_CMD_SZ) ! 35: #define AHCI_RX_FIS_SZ 256 ! 36: #define AHCI_CMD_TBL_CDB 0x40 ! 37: #define AHCI_CMD_TBL_HDR_SZ 0x80 ! 38: #define AHCI_CMD_TBL_SZ (AHCI_CMD_TBL_HDR_SZ + (AHCI_MAX_SG * 16)) ! 39: #define AHCI_CMD_TBL_AR_SZ (AHCI_CMD_TBL_SZ * AHCI_MAX_CMDS) ! 40: #define AHCI_PORT_PRIV_DMA_SZ (AHCI_CMD_SLOT_SZ + AHCI_CMD_TBL_AR_SZ + \ ! 41: AHCI_RX_FIS_SZ) ! 42: ! 43: #define AHCI_IRQ_ON_SG (1 << 31) ! 44: #define AHCI_CMD_ATAPI (1 << 5) ! 45: #define AHCI_CMD_WRITE (1 << 6) ! 46: #define AHCI_CMD_PREFETCH (1 << 7) ! 47: #define AHCI_CMD_RESET (1 << 8) ! 48: #define AHCI_CMD_CLR_BUSY (1 << 10) ! 49: ! 50: #define RX_FIS_D2H_REG 0x40 /* offset of D2H Register FIS data */ ! 51: #define RX_FIS_SDB 0x58 /* offset of SDB FIS data */ ! 52: #define RX_FIS_UNK 0x60 /* offset of Unknown FIS data */ ! 53: ! 54: /* global controller registers */ ! 55: #define HOST_CAP 0x00 /* host capabilities */ ! 56: #define HOST_CTL 0x04 /* global host control */ ! 57: #define HOST_IRQ_STAT 0x08 /* interrupt status */ ! 58: #define HOST_PORTS_IMPL 0x0c /* bitmap of implemented ports */ ! 59: #define HOST_VERSION 0x10 /* AHCI spec. version compliancy */ ! 60: ! 61: /* HOST_CTL bits */ ! 62: #define HOST_CTL_RESET (1 << 0) /* reset controller; self-clear */ ! 63: #define HOST_CTL_IRQ_EN (1 << 1) /* global IRQ enable */ ! 64: #define HOST_CTL_AHCI_EN (1 << 31) /* AHCI enabled */ ! 65: ! 66: /* HOST_CAP bits */ ! 67: #define HOST_CAP_SSC (1 << 14) /* Slumber capable */ ! 68: #define HOST_CAP_AHCI (1 << 18) /* AHCI only */ ! 69: #define HOST_CAP_CLO (1 << 24) /* Command List Override support */ ! 70: #define HOST_CAP_SSS (1 << 27) /* Staggered Spin-up */ ! 71: #define HOST_CAP_NCQ (1 << 30) /* Native Command Queueing */ ! 72: #define HOST_CAP_64 (1 << 31) /* PCI DAC (64-bit DMA) support */ ! 73: ! 74: /* registers for each SATA port */ ! 75: #define PORT_LST_ADDR 0x00 /* command list DMA addr */ ! 76: #define PORT_LST_ADDR_HI 0x04 /* command list DMA addr hi */ ! 77: #define PORT_FIS_ADDR 0x08 /* FIS rx buf addr */ ! 78: #define PORT_FIS_ADDR_HI 0x0c /* FIS rx buf addr hi */ ! 79: #define PORT_IRQ_STAT 0x10 /* interrupt status */ ! 80: #define PORT_IRQ_MASK 0x14 /* interrupt enable/disable mask */ ! 81: #define PORT_CMD 0x18 /* port command */ ! 82: #define PORT_TFDATA 0x20 /* taskfile data */ ! 83: #define PORT_SIG 0x24 /* device TF signature */ ! 84: #define PORT_SCR_STAT 0x28 /* SATA phy register: SStatus */ ! 85: #define PORT_SCR_CTL 0x2c /* SATA phy register: SControl */ ! 86: #define PORT_SCR_ERR 0x30 /* SATA phy register: SError */ ! 87: #define PORT_SCR_ACT 0x34 /* SATA phy register: SActive */ ! 88: #define PORT_CMD_ISSUE 0x38 /* command issue */ ! 89: #define PORT_RESERVED 0x3c /* reserved */ ! 90: ! 91: /* PORT_IRQ_{STAT,MASK} bits */ ! 92: #define PORT_IRQ_COLD_PRES (1 << 31) /* cold presence detect */ ! 93: #define PORT_IRQ_TF_ERR (1 << 30) /* task file error */ ! 94: #define PORT_IRQ_HBUS_ERR (1 << 29) /* host bus fatal error */ ! 95: #define PORT_IRQ_HBUS_DATA_ERR (1 << 28) /* host bus data error */ ! 96: #define PORT_IRQ_IF_ERR (1 << 27) /* interface fatal error */ ! 97: #define PORT_IRQ_IF_NONFATAL (1 << 26) /* interface non-fatal error */ ! 98: #define PORT_IRQ_OVERFLOW (1 << 24) /* xfer exhausted available S/G */ ! 99: #define PORT_IRQ_BAD_PMP (1 << 23) /* incorrect port multiplier */ ! 100: ! 101: #define PORT_IRQ_PHYRDY (1 << 22) /* PhyRdy changed */ ! 102: #define PORT_IRQ_DEV_ILCK (1 << 7) /* device interlock */ ! 103: #define PORT_IRQ_CONNECT (1 << 6) /* port connect change status */ ! 104: #define PORT_IRQ_SG_DONE (1 << 5) /* descriptor processed */ ! 105: #define PORT_IRQ_UNK_FIS (1 << 4) /* unknown FIS rx'd */ ! 106: #define PORT_IRQ_SDB_FIS (1 << 3) /* Set Device Bits FIS rx'd */ ! 107: #define PORT_IRQ_DMAS_FIS (1 << 2) /* DMA Setup FIS rx'd */ ! 108: #define PORT_IRQ_PIOS_FIS (1 << 1) /* PIO Setup FIS rx'd */ ! 109: #define PORT_IRQ_D2H_REG_FIS (1 << 0) /* D2H Register FIS rx'd */ ! 110: ! 111: #define PORT_IRQ_FREEZE (PORT_IRQ_HBUS_ERR | PORT_IRQ_IF_ERR | \ ! 112: PORT_IRQ_CONNECT | PORT_IRQ_PHYRDY | \ ! 113: PORT_IRQ_UNK_FIS) ! 114: #define PORT_IRQ_ERROR (PORT_IRQ_FREEZE | PORT_IRQ_TF_ERR | \ ! 115: PORT_IRQ_HBUS_DATA_ERR) ! 116: #define DEF_PORT_IRQ (PORT_IRQ_ERROR | PORT_IRQ_SG_DONE | \ ! 117: PORT_IRQ_SDB_FIS | PORT_IRQ_DMAS_FIS | \ ! 118: PORT_IRQ_PIOS_FIS | PORT_IRQ_D2H_REG_FIS) ! 119: ! 120: /* PORT_CMD bits */ ! 121: #define PORT_CMD_ATAPI (1 << 24) /* Device is ATAPI */ ! 122: #define PORT_CMD_LIST_ON (1 << 15) /* cmd list DMA engine running */ ! 123: #define PORT_CMD_FIS_ON (1 << 14) /* FIS DMA engine running */ ! 124: #define PORT_CMD_FIS_RX (1 << 4) /* Enable FIS receive DMA engine */ ! 125: #define PORT_CMD_CLO (1 << 3) /* Command list override */ ! 126: #define PORT_CMD_POWER_ON (1 << 2) /* Power up device */ ! 127: #define PORT_CMD_SPIN_UP (1 << 1) /* Spin up device */ ! 128: #define PORT_CMD_START (1 << 0) /* Enable port DMA engine */ ! 129: ! 130: #define PORT_CMD_ICC_MASK (0xf << 28) /* i/f ICC state mask */ ! 131: #define PORT_CMD_ICC_ACTIVE (0x1 << 28) /* Put i/f in active state */ ! 132: #define PORT_CMD_ICC_PARTIAL (0x2 << 28) /* Put i/f in partial state */ ! 133: #define PORT_CMD_ICC_SLUMBER (0x6 << 28) /* Put i/f in slumber state */ ! 134: ! 135: #define PORT_IRQ_STAT_DHRS (1 << 0) /* Device to Host Register FIS */ ! 136: #define PORT_IRQ_STAT_PSS (1 << 1) /* PIO Setup FIS */ ! 137: #define PORT_IRQ_STAT_DSS (1 << 2) /* DMA Setup FIS */ ! 138: #define PORT_IRQ_STAT_SDBS (1 << 3) /* Set Device Bits */ ! 139: #define PORT_IRQ_STAT_UFS (1 << 4) /* Unknown FIS */ ! 140: #define PORT_IRQ_STAT_DPS (1 << 5) /* Descriptor Processed */ ! 141: #define PORT_IRQ_STAT_PCS (1 << 6) /* Port Connect Change Status */ ! 142: #define PORT_IRQ_STAT_DMPS (1 << 7) /* Device Mechanical Presence ! 143: Status */ ! 144: #define PORT_IRQ_STAT_PRCS (1 << 22) /* File Ready Status */ ! 145: #define PORT_IRQ_STAT_IPMS (1 << 23) /* Incorrect Port Multiplier ! 146: Status */ ! 147: #define PORT_IRQ_STAT_OFS (1 << 24) /* Overflow Status */ ! 148: #define PORT_IRQ_STAT_INFS (1 << 26) /* Interface Non-Fatal Error ! 149: Status */ ! 150: #define PORT_IRQ_STAT_IFS (1 << 27) /* Interface Fatal Error */ ! 151: #define PORT_IRQ_STAT_HBDS (1 << 28) /* Host Bus Data Error Status */ ! 152: #define PORT_IRQ_STAT_HBFS (1 << 29) /* Host Bus Fatal Error Status */ ! 153: #define PORT_IRQ_STAT_TFES (1 << 30) /* Task File Error Status */ ! 154: #define PORT_IRQ_STAT_CPDS (1 << 31) /* Code Port Detect Status */ ! 155: ! 156: /* ap->flags bits */ ! 157: #define AHCI_FLAG_NO_NCQ (1 << 24) ! 158: #define AHCI_FLAG_IGN_IRQ_IF_ERR (1 << 25) /* ignore IRQ_IF_ERR */ ! 159: #define AHCI_FLAG_HONOR_PI (1 << 26) /* honor PORTS_IMPL */ ! 160: #define AHCI_FLAG_IGN_SERR_INTERNAL (1 << 27) /* ignore SERR_INTERNAL */ ! 161: #define AHCI_FLAG_32BIT_ONLY (1 << 28) /* force 32bit */ ! 162: ! 163: #define ATA_SRST (1 << 2) /* software reset */ ! 164: ! 165: #define STATE_RUN 0 ! 166: #define STATE_RESET 1 ! 167: ! 168: #define SATA_SCR_SSTATUS_DET_NODEV 0x0 ! 169: #define SATA_SCR_SSTATUS_DET_DEV_PRESENT_PHY_UP 0x3 ! 170: ! 171: #define SATA_SCR_SSTATUS_SPD_NODEV 0x00 ! 172: #define SATA_SCR_SSTATUS_SPD_GEN1 0x10 ! 173: ! 174: #define SATA_SCR_SSTATUS_IPM_NODEV 0x000 ! 175: #define SATA_SCR_SSTATUS_IPM_ACTIVE 0X100 ! 176: ! 177: #define AHCI_SCR_SCTL_DET 0xf ! 178: ! 179: #define SATA_FIS_TYPE_REGISTER_H2D 0x27 ! 180: #define SATA_FIS_REG_H2D_UPDATE_COMMAND_REGISTER 0x80 ! 181: ! 182: #define AHCI_CMD_HDR_CMD_FIS_LEN 0x1f ! 183: #define AHCI_CMD_HDR_PRDT_LEN 16 ! 184: ! 185: #define SATA_SIGNATURE_CDROM 0xeb140000 ! 186: #define SATA_SIGNATURE_DISK 0x00000101 ! 187: ! 188: #define AHCI_GENERIC_HOST_CONTROL_REGS_MAX_ADDR 0x20 ! 189: /* Shouldn't this be 0x2c? */ ! 190: ! 191: #define AHCI_PORT_REGS_START_ADDR 0x100 ! 192: #define AHCI_PORT_ADDR_OFFSET_MASK 0x7f ! 193: #define AHCI_PORT_ADDR_OFFSET_LEN 0x80 ! 194: ! 195: #define AHCI_NUM_COMMAND_SLOTS 31 ! 196: #define AHCI_SUPPORTED_SPEED 20 ! 197: #define AHCI_SUPPORTED_SPEED_GEN1 1 ! 198: #define AHCI_VERSION_1_0 0x10000 ! 199: ! 200: #define AHCI_PROGMODE_MAJOR_REV_1 1 ! 201: ! 202: #define AHCI_COMMAND_TABLE_ACMD 0x40 ! 203: ! 204: #define IDE_FEATURE_DMA 1 ! 205: ! 206: #define READ_FPDMA_QUEUED 0x60 ! 207: #define WRITE_FPDMA_QUEUED 0x61 ! 208: ! 209: #define RES_FIS_DSFIS 0x00 ! 210: #define RES_FIS_PSFIS 0x20 ! 211: #define RES_FIS_RFIS 0x40 ! 212: #define RES_FIS_SDBFIS 0x58 ! 213: #define RES_FIS_UFIS 0x60 ! 214: ! 215: typedef struct AHCIControlRegs { ! 216: uint32_t cap; ! 217: uint32_t ghc; ! 218: uint32_t irqstatus; ! 219: uint32_t impl; ! 220: uint32_t version; ! 221: } AHCIControlRegs; ! 222: ! 223: typedef struct AHCIPortRegs { ! 224: uint32_t lst_addr; ! 225: uint32_t lst_addr_hi; ! 226: uint32_t fis_addr; ! 227: uint32_t fis_addr_hi; ! 228: uint32_t irq_stat; ! 229: uint32_t irq_mask; ! 230: uint32_t cmd; ! 231: uint32_t unused0; ! 232: uint32_t tfdata; ! 233: uint32_t sig; ! 234: uint32_t scr_stat; ! 235: uint32_t scr_ctl; ! 236: uint32_t scr_err; ! 237: uint32_t scr_act; ! 238: uint32_t cmd_issue; ! 239: uint32_t reserved; ! 240: } AHCIPortRegs; ! 241: ! 242: typedef struct AHCICmdHdr { ! 243: uint32_t opts; ! 244: uint32_t status; ! 245: uint64_t tbl_addr; ! 246: uint32_t reserved[4]; ! 247: } __attribute__ ((packed)) AHCICmdHdr; ! 248: ! 249: typedef struct AHCI_SG { ! 250: uint64_t addr; ! 251: uint32_t reserved; ! 252: uint32_t flags_size; ! 253: } __attribute__ ((packed)) AHCI_SG; ! 254: ! 255: typedef struct AHCIDevice AHCIDevice; ! 256: ! 257: typedef struct NCQTransferState { ! 258: AHCIDevice *drive; ! 259: BlockDriverAIOCB *aiocb; ! 260: QEMUSGList sglist; ! 261: int is_read; ! 262: uint16_t sector_count; ! 263: uint64_t lba; ! 264: uint8_t tag; ! 265: int slot; ! 266: int used; ! 267: } NCQTransferState; ! 268: ! 269: struct AHCIDevice { ! 270: IDEDMA dma; ! 271: IDEBus port; ! 272: int port_no; ! 273: uint32_t port_state; ! 274: uint32_t finished; ! 275: AHCIPortRegs port_regs; ! 276: struct AHCIState *hba; ! 277: QEMUBH *check_bh; ! 278: uint8_t *lst; ! 279: uint8_t *res_fis; ! 280: int dma_status; ! 281: int done_atapi_packet; ! 282: int busy_slot; ! 283: int init_d2h_sent; ! 284: BlockDriverCompletionFunc *dma_cb; ! 285: AHCICmdHdr *cur_cmd; ! 286: NCQTransferState ncq_tfs[AHCI_MAX_CMDS]; ! 287: }; ! 288: ! 289: typedef struct AHCIState { ! 290: AHCIDevice *dev; ! 291: AHCIControlRegs control_regs; ! 292: int mem; ! 293: int ports; ! 294: qemu_irq irq; ! 295: } AHCIState; ! 296: ! 297: typedef struct AHCIPCIState { ! 298: PCIDevice card; ! 299: AHCIState ahci; ! 300: } AHCIPCIState; ! 301: ! 302: typedef struct NCQFrame { ! 303: uint8_t fis_type; ! 304: uint8_t c; ! 305: uint8_t command; ! 306: uint8_t sector_count_low; ! 307: uint8_t lba0; ! 308: uint8_t lba1; ! 309: uint8_t lba2; ! 310: uint8_t fua; ! 311: uint8_t lba3; ! 312: uint8_t lba4; ! 313: uint8_t lba5; ! 314: uint8_t sector_count_high; ! 315: uint8_t tag; ! 316: uint8_t reserved5; ! 317: uint8_t reserved6; ! 318: uint8_t control; ! 319: uint8_t reserved7; ! 320: uint8_t reserved8; ! 321: uint8_t reserved9; ! 322: uint8_t reserved10; ! 323: } __attribute__ ((packed)) NCQFrame; ! 324: ! 325: void ahci_init(AHCIState *s, DeviceState *qdev, int ports); ! 326: void ahci_uninit(AHCIState *s); ! 327: ! 328: void ahci_pci_map(PCIDevice *pci_dev, int region_num, ! 329: pcibus_t addr, pcibus_t size, int type); ! 330: ! 331: void ahci_reset(void *opaque); ! 332: ! 333: #endif /* HW_IDE_AHCI_H */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.