diff options
Diffstat (limited to 'hw/ide')
-rw-r--r-- | hw/ide/ahci.c | 54 | ||||
-rw-r--r-- | hw/ide/ahci.h | 10 | ||||
-rw-r--r-- | hw/ide/atapi.c | 58 | ||||
-rw-r--r-- | hw/ide/cmd646.c | 1 | ||||
-rw-r--r-- | hw/ide/core.c | 166 | ||||
-rw-r--r-- | hw/ide/ich.c | 28 | ||||
-rw-r--r-- | hw/ide/internal.h | 6 | ||||
-rw-r--r-- | hw/ide/isa.c | 1 | ||||
-rw-r--r-- | hw/ide/macio.c | 3 | ||||
-rw-r--r-- | hw/ide/microdrive.c | 1 | ||||
-rw-r--r-- | hw/ide/mmio.c | 1 | ||||
-rw-r--r-- | hw/ide/pci.c | 3 | ||||
-rw-r--r-- | hw/ide/via.c | 1 |
13 files changed, 248 insertions, 85 deletions
diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c index f4fa1545bd..1c7e3a00b5 100644 --- a/hw/ide/ahci.c +++ b/hw/ide/ahci.c @@ -370,6 +370,43 @@ static MemoryRegionOps ahci_mem_ops = { .endianness = DEVICE_LITTLE_ENDIAN, }; +static uint64_t ahci_idp_read(void *opaque, target_phys_addr_t addr, + unsigned size) +{ + AHCIState *s = opaque; + + if (addr == s->idp_offset) { + /* index register */ + return s->idp_index; + } else if (addr == s->idp_offset + 4) { + /* data register - do memory read at location selected by index */ + return ahci_mem_read(opaque, s->idp_index, size); + } else { + return 0; + } +} + +static void ahci_idp_write(void *opaque, target_phys_addr_t addr, + uint64_t val, unsigned size) +{ + AHCIState *s = opaque; + + if (addr == s->idp_offset) { + /* index register - mask off reserved bits */ + s->idp_index = (uint32_t)val & ((AHCI_MEM_BAR_SIZE - 1) & ~3); + } else if (addr == s->idp_offset + 4) { + /* data register - do memory write at location selected by index */ + ahci_mem_write(opaque, s->idp_index, val, size); + } +} + +static MemoryRegionOps ahci_idp_ops = { + .read = ahci_idp_read, + .write = ahci_idp_write, + .endianness = DEVICE_LITTLE_ENDIAN, +}; + + static void ahci_reg_init(AHCIState *s) { int i; @@ -499,10 +536,7 @@ static void ahci_reset_port(AHCIState *s, int port) ide_bus_reset(&d->port); ide_state->ncq_queues = AHCI_MAX_CMDS; - pr->irq_stat = 0; - pr->irq_mask = 0; pr->scr_stat = 0; - pr->scr_ctl = 0; pr->scr_err = 0; pr->scr_act = 0; d->busy_slot = -1; @@ -754,7 +788,6 @@ static void process_ncq_command(AHCIState *s, int port, uint8_t *cmd_fis, case READ_FPDMA_QUEUED: DPRINTF(port, "NCQ reading %d sectors from LBA %ld, tag %d\n", ncq_tfs->sector_count-1, ncq_tfs->lba, ncq_tfs->tag); - ncq_tfs->is_read = 1; DPRINTF(port, "tag %d aio read %ld\n", ncq_tfs->tag, ncq_tfs->lba); @@ -768,7 +801,6 @@ static void process_ncq_command(AHCIState *s, int port, uint8_t *cmd_fis, case WRITE_FPDMA_QUEUED: DPRINTF(port, "NCQ writing %d sectors to LBA %ld, tag %d\n", ncq_tfs->sector_count-1, ncq_tfs->lba, ncq_tfs->tag); - ncq_tfs->is_read = 0; DPRINTF(port, "tag %d aio write %ld\n", ncq_tfs->tag, ncq_tfs->lba); @@ -1105,7 +1137,7 @@ static void ahci_irq_set(void *opaque, int n, int level) { } -static void ahci_dma_restart_cb(void *opaque, int running, int reason) +static void ahci_dma_restart_cb(void *opaque, int running, RunState state) { } @@ -1135,7 +1167,9 @@ void ahci_init(AHCIState *s, DeviceState *qdev, int ports) s->dev = g_malloc0(sizeof(AHCIDevice) * ports); ahci_reg_init(s); /* XXX BAR size should be 1k, but that breaks, so bump it to 4k for now */ - memory_region_init_io(&s->mem, &ahci_mem_ops, s, "ahci", 0x1000); + memory_region_init_io(&s->mem, &ahci_mem_ops, s, "ahci", AHCI_MEM_BAR_SIZE); + memory_region_init_io(&s->idp, &ahci_idp_ops, s, "ahci-idp", 32); + irqs = qemu_allocate_irqs(ahci_irq_set, s, s->ports); for (i = 0; i < s->ports; i++) { @@ -1155,18 +1189,24 @@ void ahci_init(AHCIState *s, DeviceState *qdev, int ports) void ahci_uninit(AHCIState *s) { memory_region_destroy(&s->mem); + memory_region_destroy(&s->idp); g_free(s->dev); } void ahci_reset(void *opaque) { struct AHCIPCIState *d = opaque; + AHCIPortRegs *pr; int i; d->ahci.control_regs.irqstatus = 0; d->ahci.control_regs.ghc = 0; for (i = 0; i < d->ahci.ports; i++) { + pr = &d->ahci.dev[i].port_regs; + pr->irq_stat = 0; + pr->irq_mask = 0; + pr->scr_ctl = 0; ahci_reset_port(&d->ahci, i); } } diff --git a/hw/ide/ahci.h b/hw/ide/ahci.h index 3c29d93b47..b223d2c055 100644 --- a/hw/ide/ahci.h +++ b/hw/ide/ahci.h @@ -24,7 +24,7 @@ #ifndef HW_IDE_AHCI_H #define HW_IDE_AHCI_H -#define AHCI_PCI_BAR 5 +#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 @@ -212,6 +212,10 @@ #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; @@ -259,7 +263,6 @@ typedef struct NCQTransferState { BlockDriverAIOCB *aiocb; QEMUSGList sglist; BlockAcctCookie acct; - int is_read; uint16_t sector_count; uint64_t lba; uint8_t tag; @@ -291,6 +294,9 @@ typedef struct AHCIState { 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 */ int ports; qemu_irq irq; } AHCIState; diff --git a/hw/ide/atapi.c b/hw/ide/atapi.c index f38d2896ae..3f909c3a99 100644 --- a/hw/ide/atapi.c +++ b/hw/ide/atapi.c @@ -73,7 +73,7 @@ static void lba_to_msf(uint8_t *buf, int lba) static inline int media_present(IDEState *s) { - return (s->nb_sectors > 0); + return !s->tray_open && s->nb_sectors > 0; } /* XXX: DVDs that could fit on a CD will be reported as a CD */ @@ -521,7 +521,7 @@ static unsigned int event_status_media(IDEState *s, uint8_t event_code, media_status; media_status = 0; - if (s->bs->tray_open) { + if (s->tray_open) { media_status = MS_TRAY_OPEN; } else if (bdrv_is_inserted(s->bs)) { media_status = MS_MEDIA_PRESENT; @@ -788,8 +788,9 @@ static void cmd_mode_sense(IDEState *s, uint8_t *buf) buf[12] = 0x71; buf[13] = 3 << 5; buf[14] = (1 << 0) | (1 << 3) | (1 << 5); - if (bdrv_is_locked(s->bs)) + if (s->tray_locked) { buf[6] |= 1 << 1; + } buf[15] = 0x00; cpu_to_ube16(&buf[16], 706); buf[18] = 0; @@ -831,7 +832,8 @@ static void cmd_test_unit_ready(IDEState *s, uint8_t *buf) static void cmd_prevent_allow_medium_removal(IDEState *s, uint8_t* buf) { - bdrv_set_locked(s->bs, buf[4] & 1); + s->tray_locked = buf[4] & 1; + bdrv_lock_medium(s->bs, buf[4] & 1); ide_atapi_cmd_ok(s); } @@ -903,29 +905,22 @@ static void cmd_seek(IDEState *s, uint8_t* buf) static void cmd_start_stop_unit(IDEState *s, uint8_t* buf) { - int start, eject, sense, err = 0; - start = buf[4] & 1; - eject = (buf[4] >> 1) & 1; - - if (eject) { - err = bdrv_eject(s->bs, !start); - } - - switch (err) { - case 0: - ide_atapi_cmd_ok(s); - break; - case -EBUSY: - sense = SENSE_NOT_READY; - if (bdrv_is_inserted(s->bs)) { - sense = SENSE_ILLEGAL_REQUEST; + int sense; + bool start = buf[4] & 1; + bool loej = buf[4] & 2; /* load on start, eject on !start */ + + if (loej) { + if (!start && !s->tray_open && s->tray_locked) { + sense = bdrv_is_inserted(s->bs) + ? SENSE_NOT_READY : SENSE_ILLEGAL_REQUEST; + ide_atapi_cmd_error(s, sense, ASC_MEDIA_REMOVAL_PREVENTED); + return; } - ide_atapi_cmd_error(s, sense, ASC_MEDIA_REMOVAL_PREVENTED); - break; - default: - ide_atapi_cmd_error(s, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT); - break; + bdrv_eject(s->bs, !start); + s->tray_open = !start; } + + ide_atapi_cmd_ok(s); } static void cmd_mechanism_status(IDEState *s, uint8_t* buf) @@ -1073,20 +1068,21 @@ static const struct { [ 0x03 ] = { cmd_request_sense, ALLOW_UA }, [ 0x12 ] = { cmd_inquiry, ALLOW_UA }, [ 0x1a ] = { cmd_mode_sense, /* (6) */ 0 }, - [ 0x1b ] = { cmd_start_stop_unit, 0 }, + [ 0x1b ] = { cmd_start_stop_unit, 0 }, /* [1] */ [ 0x1e ] = { cmd_prevent_allow_medium_removal, 0 }, [ 0x25 ] = { cmd_read_cdvd_capacity, CHECK_READY }, - [ 0x28 ] = { cmd_read, /* (10) */ 0 }, + [ 0x28 ] = { cmd_read, /* (10) */ CHECK_READY }, [ 0x2b ] = { cmd_seek, CHECK_READY }, [ 0x43 ] = { cmd_read_toc_pma_atip, CHECK_READY }, [ 0x46 ] = { cmd_get_configuration, ALLOW_UA }, [ 0x4a ] = { cmd_get_event_status_notification, ALLOW_UA }, [ 0x5a ] = { cmd_mode_sense, /* (10) */ 0 }, - [ 0xa8 ] = { cmd_read, /* (12) */ 0 }, - [ 0xad ] = { cmd_read_dvd_structure, 0 }, + [ 0xa8 ] = { cmd_read, /* (12) */ CHECK_READY }, + [ 0xad ] = { cmd_read_dvd_structure, CHECK_READY }, [ 0xbb ] = { cmd_set_speed, 0 }, [ 0xbd ] = { cmd_mechanism_status, 0 }, - [ 0xbe ] = { cmd_read_cd, 0 }, + [ 0xbe ] = { cmd_read_cd, CHECK_READY }, + /* [1] handler detects and reports not ready condition itself */ }; void ide_atapi_cmd(IDEState *s) @@ -1122,7 +1118,7 @@ void ide_atapi_cmd(IDEState *s) * GET_EVENT_STATUS_NOTIFICATION to detect such tray open/close * states rely on this behavior. */ - if (bdrv_is_inserted(s->bs) && s->cdrom_changed) { + if (!s->tray_open && bdrv_is_inserted(s->bs) && s->cdrom_changed) { ide_atapi_cmd_error(s, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT); s->cdrom_changed = 0; diff --git a/hw/ide/cmd646.c b/hw/ide/cmd646.c index 4d91e2c642..5fe98b1bb3 100644 --- a/hw/ide/cmd646.c +++ b/hw/ide/cmd646.c @@ -27,7 +27,6 @@ #include <hw/pci.h> #include <hw/isa.h> #include "block.h" -#include "block_int.h" #include "sysemu.h" #include "dma.h" diff --git a/hw/ide/core.c b/hw/ide/core.c index 1806e008bc..4e76fc78d3 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -30,6 +30,7 @@ #include "sysemu.h" #include "dma.h" #include "blockdev.h" +#include "block_int.h" #include <hw/ide/internal.h> @@ -526,7 +527,7 @@ static int ide_handle_rw_error(IDEState *s, int error, int op) s->bus->dma->ops->set_unit(s->bus->dma, s->unit); s->bus->error_status = op; bdrv_mon_event(s->bs, BDRV_ACTION_STOP, is_read); - vm_stop(VMSTOP_DISKFULL); + vm_stop(RSTATE_IO_ERROR); } else { if (op & BM_STATUS_DMA_RETRY) { dma_buf_commit(s, 0); @@ -602,7 +603,7 @@ handle_rw_error: break; case IDE_DMA_TRIM: s->bus->dma->aiocb = dma_bdrv_io(s->bs, &s->sg, sector_num, - ide_issue_trim, ide_dma_cb, s, 1); + ide_issue_trim, ide_dma_cb, s, true); break; } @@ -783,11 +784,12 @@ static void ide_cfata_metadata_write(IDEState *s) } /* called when the inserted state of the media has changed */ -static void ide_cd_change_cb(void *opaque) +static void ide_cd_change_cb(void *opaque, bool load) { IDEState *s = opaque; uint64_t nb_sectors; + s->tray_open = !load; bdrv_get_geometry(s->bs, &nb_sectors); s->nb_sectors = nb_sectors; @@ -901,6 +903,78 @@ void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val) } } +#define HD_OK (1u << IDE_HD) +#define CD_OK (1u << IDE_CD) +#define CFA_OK (1u << IDE_CFATA) +#define HD_CFA_OK (HD_OK | CFA_OK) +#define ALL_OK (HD_OK | CD_OK | CFA_OK) + +/* See ACS-2 T13/2015-D Table B.2 Command codes */ +static const uint8_t ide_cmd_table[0x100] = { + /* NOP not implemented, mandatory for CD */ + [CFA_REQ_EXT_ERROR_CODE] = CFA_OK, + [WIN_DSM] = ALL_OK, + [WIN_DEVICE_RESET] = CD_OK, + [WIN_RECAL] = HD_CFA_OK, + [WIN_READ] = ALL_OK, + [WIN_READ_ONCE] = ALL_OK, + [WIN_READ_EXT] = HD_CFA_OK, + [WIN_READDMA_EXT] = HD_CFA_OK, + [WIN_READ_NATIVE_MAX_EXT] = HD_CFA_OK, + [WIN_MULTREAD_EXT] = HD_CFA_OK, + [WIN_WRITE] = HD_CFA_OK, + [WIN_WRITE_ONCE] = HD_CFA_OK, + [WIN_WRITE_EXT] = HD_CFA_OK, + [WIN_WRITEDMA_EXT] = HD_CFA_OK, + [CFA_WRITE_SECT_WO_ERASE] = CFA_OK, + [WIN_MULTWRITE_EXT] = HD_CFA_OK, + [WIN_WRITE_VERIFY] = HD_CFA_OK, + [WIN_VERIFY] = HD_CFA_OK, + [WIN_VERIFY_ONCE] = HD_CFA_OK, + [WIN_VERIFY_EXT] = HD_CFA_OK, + [WIN_SEEK] = HD_CFA_OK, + [CFA_TRANSLATE_SECTOR] = CFA_OK, + [WIN_DIAGNOSE] = ALL_OK, + [WIN_SPECIFY] = HD_CFA_OK, + [WIN_STANDBYNOW2] = ALL_OK, + [WIN_IDLEIMMEDIATE2] = ALL_OK, + [WIN_STANDBY2] = ALL_OK, + [WIN_SETIDLE2] = ALL_OK, + [WIN_CHECKPOWERMODE2] = ALL_OK, + [WIN_SLEEPNOW2] = ALL_OK, + [WIN_PACKETCMD] = CD_OK, + [WIN_PIDENTIFY] = CD_OK, + [WIN_SMART] = HD_CFA_OK, + [CFA_ACCESS_METADATA_STORAGE] = CFA_OK, + [CFA_ERASE_SECTORS] = CFA_OK, + [WIN_MULTREAD] = HD_CFA_OK, + [WIN_MULTWRITE] = HD_CFA_OK, + [WIN_SETMULT] = HD_CFA_OK, + [WIN_READDMA] = HD_CFA_OK, + [WIN_READDMA_ONCE] = HD_CFA_OK, + [WIN_WRITEDMA] = HD_CFA_OK, + [WIN_WRITEDMA_ONCE] = HD_CFA_OK, + [CFA_WRITE_MULTI_WO_ERASE] = CFA_OK, + [WIN_STANDBYNOW1] = ALL_OK, + [WIN_IDLEIMMEDIATE] = ALL_OK, + [WIN_STANDBY] = ALL_OK, + [WIN_SETIDLE1] = ALL_OK, + [WIN_CHECKPOWERMODE1] = ALL_OK, + [WIN_SLEEPNOW1] = ALL_OK, + [WIN_FLUSH_CACHE] = ALL_OK, + [WIN_FLUSH_CACHE_EXT] = HD_CFA_OK, + [WIN_IDENTIFY] = ALL_OK, + [WIN_SETFEATURES] = ALL_OK, + [IBM_SENSE_CONDITION] = CFA_OK, + [CFA_WEAR_LEVEL] = CFA_OK, + [WIN_READ_NATIVE_MAX] = ALL_OK, +}; + +static bool ide_cmd_permitted(IDEState *s, uint32_t cmd) +{ + return cmd < ARRAY_SIZE(ide_cmd_table) + && (ide_cmd_table[cmd] & (1u << s->drive_kind)); +} void ide_exec_cmd(IDEBus *bus, uint32_t val) { @@ -920,6 +994,10 @@ void ide_exec_cmd(IDEBus *bus, uint32_t val) if ((s->status & (BUSY_STAT|DRQ_STAT)) && val != WIN_DEVICE_RESET) return; + if (!ide_cmd_permitted(s, val)) { + goto abort_cmd; + } + switch(val) { case WIN_DSM: switch (s->feature) { @@ -983,8 +1061,10 @@ void ide_exec_cmd(IDEBus *bus, uint32_t val) lba48 = 1; case WIN_READ: case WIN_READ_ONCE: - if (!s->bs) + if (s->drive_kind == IDE_CD) { + ide_set_signature(s); /* odd, but ATA4 8.27.5.2 requires it */ goto abort_cmd; + } ide_cmd_lba48_transform(s, lba48); s->req_nb_sectors = 1; ide_sector_read(s); @@ -1138,21 +1218,15 @@ void ide_exec_cmd(IDEBus *bus, uint32_t val) ide_set_irq(s->bus); break; case WIN_SEEK: - if(s->drive_kind == IDE_CD) - goto abort_cmd; /* XXX: Check that seek is within bounds */ s->status = READY_STAT | SEEK_STAT; ide_set_irq(s->bus); break; /* ATAPI commands */ case WIN_PIDENTIFY: - if (s->drive_kind == IDE_CD) { - ide_atapi_identify(s); - s->status = READY_STAT | SEEK_STAT; - ide_transfer_start(s, s->io_buffer, 512, ide_transfer_stop); - } else { - ide_abort_command(s); - } + ide_atapi_identify(s); + s->status = READY_STAT | SEEK_STAT; + ide_transfer_start(s, s->io_buffer, 512, ide_transfer_stop); ide_set_irq(s->bus); break; case WIN_DIAGNOSE: @@ -1169,15 +1243,11 @@ void ide_exec_cmd(IDEBus *bus, uint32_t val) ide_set_irq(s->bus); break; case WIN_DEVICE_RESET: - if (s->drive_kind != IDE_CD) - goto abort_cmd; ide_set_signature(s); s->status = 0x00; /* NOTE: READY is _not_ set */ s->error = 0x01; break; case WIN_PACKETCMD: - if (s->drive_kind != IDE_CD) - goto abort_cmd; /* overlapping commands not supported */ if (s->feature & 0x02) goto abort_cmd; @@ -1189,16 +1259,12 @@ void ide_exec_cmd(IDEBus *bus, uint32_t val) break; /* CF-ATA commands */ case CFA_REQ_EXT_ERROR_CODE: - if (s->drive_kind != IDE_CFATA) - goto abort_cmd; s->error = 0x09; /* miscellaneous error */ s->status = READY_STAT | SEEK_STAT; ide_set_irq(s->bus); break; case CFA_ERASE_SECTORS: case CFA_WEAR_LEVEL: - if (s->drive_kind != IDE_CFATA) - goto abort_cmd; if (val == CFA_WEAR_LEVEL) s->nsector = 0; if (val == CFA_ERASE_SECTORS) @@ -1208,8 +1274,6 @@ void ide_exec_cmd(IDEBus *bus, uint32_t val) ide_set_irq(s->bus); break; case CFA_TRANSLATE_SECTOR: - if (s->drive_kind != IDE_CFATA) - goto abort_cmd; s->error = 0x00; s->status = READY_STAT | SEEK_STAT; memset(s->io_buffer, 0, 0x200); @@ -1228,8 +1292,6 @@ void ide_exec_cmd(IDEBus *bus, uint32_t val) ide_set_irq(s->bus); break; case CFA_ACCESS_METADATA_STORAGE: - if (s->drive_kind != IDE_CFATA) - goto abort_cmd; switch (s->feature) { case 0x02: /* Inquiry Metadata Storage */ ide_cfata_metadata_inquiry(s); @@ -1248,8 +1310,6 @@ void ide_exec_cmd(IDEBus *bus, uint32_t val) ide_set_irq(s->bus); break; case IBM_SENSE_CONDITION: - if (s->drive_kind != IDE_CFATA) - goto abort_cmd; switch (s->feature) { case 0x01: /* sense temperature in device */ s->nsector = 0x50; /* +20 C */ @@ -1262,8 +1322,6 @@ void ide_exec_cmd(IDEBus *bus, uint32_t val) break; case WIN_SMART: - if (s->drive_kind == IDE_CD) - goto abort_cmd; if (s->hcyl != 0xc2 || s->lcyl != 0x4f) goto abort_cmd; if (!s->smart_enabled && s->feature != SMART_ENABLE) @@ -1418,6 +1476,7 @@ void ide_exec_cmd(IDEBus *bus, uint32_t val) } break; default: + /* should not be reachable */ abort_cmd: ide_abort_command(s); ide_set_irq(s->bus); @@ -1738,8 +1797,20 @@ void ide_bus_reset(IDEBus *bus) bus->dma->ops->reset(bus->dma); } +static bool ide_cd_is_tray_open(void *opaque) +{ + return ((IDEState *)opaque)->tray_open; +} + +static bool ide_cd_is_medium_locked(void *opaque) +{ + return ((IDEState *)opaque)->tray_locked; +} + static const BlockDevOps ide_cd_block_ops = { .change_media_cb = ide_cd_change_cb, + .is_tray_open = ide_cd_is_tray_open, + .is_medium_locked = ide_cd_is_medium_locked, }; int ide_init_drive(IDEState *s, BlockDriverState *bs, IDEDriveKind kind, @@ -1777,7 +1848,7 @@ int ide_init_drive(IDEState *s, BlockDriverState *bs, IDEDriveKind kind, s->smart_selftest_count = 0; if (kind == IDE_CD) { bdrv_set_dev_ops(bs, &ide_cd_block_ops, s); - bs->buffer_alignment = 2048; + bdrv_set_buffer_alignment(bs, 2048); } else { if (!bdrv_is_inserted(s->bs)) { error_report("Device needs media, but drive is empty"); @@ -1801,7 +1872,6 @@ int ide_init_drive(IDEState *s, BlockDriverState *bs, IDEDriveKind kind, } ide_reset(s); - bdrv_set_removable(bs, s->drive_kind == IDE_CD); return 0; } @@ -1840,7 +1910,7 @@ static int ide_nop_int(IDEDMA *dma, int x) return 0; } -static void ide_nop_restart(void *opaque, int x, int y) +static void ide_nop_restart(void *opaque, int x, RunState y) { } @@ -1995,6 +2065,22 @@ static bool ide_drive_pio_state_needed(void *opaque) || (s->bus->error_status & BM_STATUS_PIO_RETRY); } +static int ide_tray_state_post_load(void *opaque, int version_id) +{ + IDEState *s = opaque; + + bdrv_eject(s->bs, s->tray_open); + bdrv_lock_medium(s->bs, s->tray_locked); + return 0; +} + +static bool ide_tray_state_needed(void *opaque) +{ + IDEState *s = opaque; + + return s->tray_open || s->tray_locked; +} + static bool ide_atapi_gesn_needed(void *opaque) { IDEState *s = opaque; @@ -2022,6 +2108,19 @@ static const VMStateDescription vmstate_ide_atapi_gesn_state = { } }; +static const VMStateDescription vmstate_ide_tray_state = { + .name = "ide_drive/tray_state", + .version_id = 1, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .post_load = ide_tray_state_post_load, + .fields = (VMStateField[]) { + VMSTATE_BOOL(tray_open, IDEState), + VMSTATE_BOOL(tray_locked, IDEState), + VMSTATE_END_OF_LIST() + } +}; + static const VMStateDescription vmstate_ide_drive_pio_state = { .name = "ide_drive/pio_state", .version_id = 1, @@ -2076,6 +2175,9 @@ const VMStateDescription vmstate_ide_drive = { .vmsd = &vmstate_ide_drive_pio_state, .needed = ide_drive_pio_state_needed, }, { + .vmsd = &vmstate_ide_tray_state, + .needed = ide_tray_state_needed, + }, { .vmsd = &vmstate_ide_atapi_gesn_state, .needed = ide_atapi_gesn_needed, }, { diff --git a/hw/ide/ich.c b/hw/ide/ich.c index 5278bc4d6c..3f7510f52e 100644 --- a/hw/ide/ich.c +++ b/hw/ide/ich.c @@ -66,12 +66,19 @@ #include <hw/pci.h> #include <hw/isa.h> #include "block.h" -#include "block_int.h" #include "dma.h" #include <hw/ide/pci.h> #include <hw/ide/ahci.h> +#define ICH9_SATA_CAP_OFFSET 0xA8 + +#define ICH9_IDP_BAR 4 +#define ICH9_MEM_BAR 5 + +#define ICH9_IDP_INDEX 0x10 +#define ICH9_IDP_INDEX_LOG2 0x04 + static const VMStateDescription vmstate_ahci = { .name = "ahci", .unmigratable = 1, @@ -80,6 +87,8 @@ static const VMStateDescription vmstate_ahci = { static int pci_ich9_ahci_init(PCIDevice *dev) { struct AHCIPCIState *d; + int sata_cap_offset; + uint8_t *sata_cap; d = DO_UPCAST(struct AHCIPCIState, card, dev); ahci_init(&d->ahci, &dev->qdev, 6); @@ -98,7 +107,22 @@ static int pci_ich9_ahci_init(PCIDevice *dev) msi_init(dev, 0x50, 1, true, false); d->ahci.irq = d->card.irq[0]; - pci_register_bar(&d->card, 5, 0, &d->ahci.mem); + pci_register_bar(&d->card, ICH9_IDP_BAR, PCI_BASE_ADDRESS_SPACE_IO, + &d->ahci.idp); + pci_register_bar(&d->card, ICH9_MEM_BAR, PCI_BASE_ADDRESS_SPACE_MEMORY, + &d->ahci.mem); + + sata_cap_offset = pci_add_capability(&d->card, PCI_CAP_ID_SATA, + ICH9_SATA_CAP_OFFSET, SATA_CAP_SIZE); + if (sata_cap_offset < 0) { + return sata_cap_offset; + } + + sata_cap = d->card.config + sata_cap_offset; + pci_set_word(sata_cap + SATA_CAP_REV, 0x10); + pci_set_long(sata_cap + SATA_CAP_BAR, + (ICH9_IDP_BAR + 0x4) | (ICH9_IDP_INDEX_LOG2 << 4)); + d->ahci.idp_offset = ICH9_IDP_INDEX; return 0; } diff --git a/hw/ide/internal.h b/hw/ide/internal.h index 111785294d..9046e96013 100644 --- a/hw/ide/internal.h +++ b/hw/ide/internal.h @@ -7,9 +7,9 @@ * non-internal declarations are in hw/ide.h */ #include <hw/ide.h> -#include "block_int.h" #include "iorange.h" #include "dma.h" +#include "sysemu.h" /* debug IDE devices */ //#define DEBUG_IDE @@ -388,7 +388,7 @@ typedef void EndTransferFunc(IDEState *); typedef void DMAStartFunc(IDEDMA *, IDEState *, BlockDriverCompletionFunc *); typedef int DMAFunc(IDEDMA *); typedef int DMAIntFunc(IDEDMA *, int); -typedef void DMARestartFunc(void *, int, int); +typedef void DMARestartFunc(void *, int, RunState); struct unreported_events { bool eject_request; @@ -442,6 +442,8 @@ struct IDEState { 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; diff --git a/hw/ide/isa.c b/hw/ide/isa.c index 4ac745324c..28b69d2cc3 100644 --- a/hw/ide/isa.c +++ b/hw/ide/isa.c @@ -26,7 +26,6 @@ #include <hw/pc.h> #include <hw/isa.h> #include "block.h" -#include "block_int.h" #include "dma.h" #include <hw/ide/internal.h> diff --git a/hw/ide/macio.c b/hw/ide/macio.c index fdf5d75082..37b8239b4d 100644 --- a/hw/ide/macio.c +++ b/hw/ide/macio.c @@ -26,7 +26,6 @@ #include <hw/ppc_mac.h> #include <hw/mac_dbdma.h> #include "block.h" -#include "block_int.h" #include "dma.h" #include <hw/ide/internal.h> @@ -157,7 +156,7 @@ static void pmac_ide_transfer_cb(void *opaque, int ret) break; case IDE_DMA_TRIM: m->aiocb = dma_bdrv_io(s->bs, &s->sg, sector_num, - ide_issue_trim, pmac_ide_transfer_cb, s, 1); + ide_issue_trim, pmac_ide_transfer_cb, s, true); break; } diff --git a/hw/ide/microdrive.c b/hw/ide/microdrive.c index 91c0e3c89d..9eee5b50ba 100644 --- a/hw/ide/microdrive.c +++ b/hw/ide/microdrive.c @@ -26,7 +26,6 @@ #include <hw/pc.h> #include <hw/pcmcia.h> #include "block.h" -#include "block_int.h" #include "dma.h" #include <hw/ide/internal.h> diff --git a/hw/ide/mmio.c b/hw/ide/mmio.c index 132b7517ba..2ec21b0163 100644 --- a/hw/ide/mmio.c +++ b/hw/ide/mmio.c @@ -24,7 +24,6 @@ */ #include <hw/hw.h> #include "block.h" -#include "block_int.h" #include "dma.h" #include <hw/ide/internal.h> diff --git a/hw/ide/pci.c b/hw/ide/pci.c index d1a14d7cc1..f133c422b6 100644 --- a/hw/ide/pci.c +++ b/hw/ide/pci.c @@ -27,7 +27,6 @@ #include <hw/pci.h> #include <hw/isa.h> #include "block.h" -#include "block_int.h" #include "dma.h" #include <hw/ide/pci.h> @@ -223,7 +222,7 @@ static void bmdma_restart_bh(void *opaque) } } -static void bmdma_restart_cb(void *opaque, int running, int reason) +static void bmdma_restart_cb(void *opaque, int running, RunState state) { IDEDMA *dma = opaque; BMDMAState *bm = DO_UPCAST(BMDMAState, dma, dma); diff --git a/hw/ide/via.c b/hw/ide/via.c index c0b9d43827..dab8a39f57 100644 --- a/hw/ide/via.c +++ b/hw/ide/via.c @@ -28,7 +28,6 @@ #include <hw/pci.h> #include <hw/isa.h> #include "block.h" -#include "block_int.h" #include "sysemu.h" #include "dma.h" |