diff options
Diffstat (limited to 'hw/ide')
-rw-r--r-- | hw/ide/Makefile.objs | 10 | ||||
-rw-r--r-- | hw/ide/ahci.c | 33 | ||||
-rw-r--r-- | hw/ide/ahci.h | 3 | ||||
-rw-r--r-- | hw/ide/atapi.c | 31 | ||||
-rw-r--r-- | hw/ide/cmd646.c | 6 | ||||
-rw-r--r-- | hw/ide/core.c | 73 | ||||
-rw-r--r-- | hw/ide/ich.c | 2 | ||||
-rw-r--r-- | hw/ide/internal.h | 11 | ||||
-rw-r--r-- | hw/ide/macio.c | 4 | ||||
-rw-r--r-- | hw/ide/piix.c | 6 | ||||
-rw-r--r-- | hw/ide/qdev.c | 72 | ||||
-rw-r--r-- | hw/ide/via.c | 3 |
12 files changed, 182 insertions, 72 deletions
diff --git a/hw/ide/Makefile.objs b/hw/ide/Makefile.objs new file mode 100644 index 0000000000..cf718dd016 --- /dev/null +++ b/hw/ide/Makefile.objs @@ -0,0 +1,10 @@ +hw-obj-$(CONFIG_IDE_CORE) += core.o atapi.o +hw-obj-$(CONFIG_IDE_QDEV) += qdev.o +hw-obj-$(CONFIG_IDE_PCI) += pci.o +hw-obj-$(CONFIG_IDE_ISA) += isa.o +hw-obj-$(CONFIG_IDE_PIIX) += piix.o +hw-obj-$(CONFIG_IDE_CMD646) += cmd646.o +hw-obj-$(CONFIG_IDE_MACIO) += macio.o +hw-obj-$(CONFIG_IDE_VIA) += via.o +hw-obj-$(CONFIG_AHCI) += ahci.o +hw-obj-$(CONFIG_AHCI) += ich.o diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c index e275e68934..efea93f0b4 100644 --- a/hw/ide/ahci.c +++ b/hw/ide/ahci.c @@ -588,7 +588,7 @@ static void ahci_write_fis_d2h(AHCIDevice *ad, uint8_t *cmd_fis) AHCIPortRegs *pr = &ad->port_regs; uint8_t *d2h_fis; int i; - target_phys_addr_t cmd_len = 0x80; + dma_addr_t cmd_len = 0x80; int cmd_mapped = 0; if (!ad->res_fis || !(pr->cmd & PORT_CMD_FIS_RX)) { @@ -598,7 +598,8 @@ static void ahci_write_fis_d2h(AHCIDevice *ad, uint8_t *cmd_fis) if (!cmd_fis) { /* map cmd_fis */ uint64_t tbl_addr = le64_to_cpu(ad->cur_cmd->tbl_addr); - cmd_fis = cpu_physical_memory_map(tbl_addr, &cmd_len, 0); + cmd_fis = dma_memory_map(ad->hba->dma, tbl_addr, &cmd_len, + DMA_DIRECTION_TO_DEVICE); cmd_mapped = 1; } @@ -630,7 +631,8 @@ static void ahci_write_fis_d2h(AHCIDevice *ad, uint8_t *cmd_fis) ahci_trigger_irq(ad->hba, ad, PORT_IRQ_D2H_REG_FIS); if (cmd_mapped) { - cpu_physical_memory_unmap(cmd_fis, cmd_len, 0, cmd_len); + dma_memory_unmap(ad->hba->dma, cmd_fis, cmd_len, + DMA_DIRECTION_TO_DEVICE, cmd_len); } } @@ -640,8 +642,8 @@ static int ahci_populate_sglist(AHCIDevice *ad, QEMUSGList *sglist) uint32_t opts = le32_to_cpu(cmd->opts); uint64_t prdt_addr = le64_to_cpu(cmd->tbl_addr) + 0x80; int sglist_alloc_hint = opts >> AHCI_CMD_HDR_PRDT_LEN; - target_phys_addr_t prdt_len = (sglist_alloc_hint * sizeof(AHCI_SG)); - target_phys_addr_t real_prdt_len = prdt_len; + dma_addr_t prdt_len = (sglist_alloc_hint * sizeof(AHCI_SG)); + dma_addr_t real_prdt_len = prdt_len; uint8_t *prdt; int i; int r = 0; @@ -652,7 +654,8 @@ static int ahci_populate_sglist(AHCIDevice *ad, QEMUSGList *sglist) } /* map PRDT */ - if (!(prdt = cpu_physical_memory_map(prdt_addr, &prdt_len, 0))){ + if (!(prdt = dma_memory_map(ad->hba->dma, prdt_addr, &prdt_len, + DMA_DIRECTION_TO_DEVICE))){ DPRINTF(ad->port_no, "map failed\n"); return -1; } @@ -667,7 +670,7 @@ static int ahci_populate_sglist(AHCIDevice *ad, QEMUSGList *sglist) if (sglist_alloc_hint > 0) { AHCI_SG *tbl = (AHCI_SG *)prdt; - qemu_sglist_init(sglist, sglist_alloc_hint); + qemu_sglist_init(sglist, sglist_alloc_hint, ad->hba->dma); for (i = 0; i < sglist_alloc_hint; i++) { /* flags_size is zero-based */ qemu_sglist_add(sglist, le64_to_cpu(tbl[i].addr), @@ -676,7 +679,8 @@ static int ahci_populate_sglist(AHCIDevice *ad, QEMUSGList *sglist) } out: - cpu_physical_memory_unmap(prdt, prdt_len, 0, prdt_len); + dma_memory_unmap(ad->hba->dma, prdt, prdt_len, + DMA_DIRECTION_TO_DEVICE, prdt_len); return r; } @@ -786,7 +790,7 @@ static int handle_cmd(AHCIState *s, int port, int slot) uint64_t tbl_addr; AHCICmdHdr *cmd; uint8_t *cmd_fis; - target_phys_addr_t cmd_len; + dma_addr_t cmd_len; if (s->dev[port].port.ifs[0].status & (BUSY_STAT|DRQ_STAT)) { /* Engine currently busy, try again later */ @@ -808,7 +812,8 @@ static int handle_cmd(AHCIState *s, int port, int slot) tbl_addr = le64_to_cpu(cmd->tbl_addr); cmd_len = 0x80; - cmd_fis = cpu_physical_memory_map(tbl_addr, &cmd_len, 1); + cmd_fis = dma_memory_map(s->dma, tbl_addr, &cmd_len, + DMA_DIRECTION_FROM_DEVICE); if (!cmd_fis) { DPRINTF(port, "error: guest passed us an invalid cmd fis\n"); @@ -934,7 +939,8 @@ static int handle_cmd(AHCIState *s, int port, int slot) } out: - cpu_physical_memory_unmap(cmd_fis, cmd_len, 1, cmd_len); + dma_memory_unmap(s->dma, cmd_fis, cmd_len, DMA_DIRECTION_FROM_DEVICE, + cmd_len); if (s->dev[port].port.ifs[0].status & (BUSY_STAT|DRQ_STAT)) { /* async command, complete later */ @@ -1114,11 +1120,12 @@ static const IDEDMAOps ahci_dma_ops = { .reset = ahci_dma_reset, }; -void ahci_init(AHCIState *s, DeviceState *qdev, int ports) +void ahci_init(AHCIState *s, DeviceState *qdev, DMAContext *dma, int ports) { qemu_irq *irqs; int i; + s->dma = dma; s->ports = ports; s->dev = g_malloc0(sizeof(AHCIDevice) * ports); ahci_reg_init(s); @@ -1187,7 +1194,7 @@ static void sysbus_ahci_reset(DeviceState *dev) static int sysbus_ahci_init(SysBusDevice *dev) { SysbusAHCIState *s = FROM_SYSBUS(SysbusAHCIState, dev); - ahci_init(&s->ahci, &dev->qdev, s->num_ports); + ahci_init(&s->ahci, &dev->qdev, NULL, s->num_ports); sysbus_init_mmio(dev, &s->ahci.mem); sysbus_init_irq(dev, &s->ahci.irq); diff --git a/hw/ide/ahci.h b/hw/ide/ahci.h index ec1b6a5f66..1200a56ada 100644 --- a/hw/ide/ahci.h +++ b/hw/ide/ahci.h @@ -299,6 +299,7 @@ typedef struct AHCIState { uint32_t idp_index; /* Current IDP index */ int ports; qemu_irq irq; + DMAContext *dma; } AHCIState; typedef struct AHCIPCIState { @@ -329,7 +330,7 @@ typedef struct NCQFrame { uint8_t reserved10; } QEMU_PACKED NCQFrame; -void ahci_init(AHCIState *s, DeviceState *qdev, int ports); +void ahci_init(AHCIState *s, DeviceState *qdev, DMAContext *dma, int ports); void ahci_uninit(AHCIState *s); void ahci_reset(AHCIState *s); diff --git a/hw/ide/atapi.c b/hw/ide/atapi.c index 5919cf52d8..f7f714c726 100644 --- a/hw/ide/atapi.c +++ b/hw/ide/atapi.c @@ -956,6 +956,36 @@ static void cmd_read_cdvd_capacity(IDEState *s, uint8_t* buf) ide_atapi_cmd_reply(s, 8, 8); } +static void cmd_read_disc_information(IDEState *s, uint8_t* buf) +{ + uint8_t type = buf[1] & 7; + uint32_t max_len = ube16_to_cpu(buf + 7); + + /* Types 1/2 are only defined for Blu-Ray. */ + if (type != 0) { + ide_atapi_cmd_error(s, ILLEGAL_REQUEST, + ASC_INV_FIELD_IN_CMD_PACKET); + return; + } + + memset(buf, 0, 34); + buf[1] = 32; + buf[2] = 0xe; /* last session complete, disc finalized */ + buf[3] = 1; /* first track on disc */ + buf[4] = 1; /* # of sessions */ + buf[5] = 1; /* first track of last session */ + buf[6] = 1; /* last track of last session */ + buf[7] = 0x20; /* unrestricted use */ + buf[8] = 0x00; /* CD-ROM or DVD-ROM */ + /* 9-10-11: most significant byte corresponding bytes 4-5-6 */ + /* 12-23: not meaningful for CD-ROM or DVD-ROM */ + /* 24-31: disc bar code */ + /* 32: disc application code */ + /* 33: number of OPC tables */ + + ide_atapi_cmd_reply(s, 34, max_len); +} + static void cmd_read_dvd_structure(IDEState *s, uint8_t* buf) { int max_len; @@ -1045,6 +1075,7 @@ static const struct { [ 0x43 ] = { cmd_read_toc_pma_atip, CHECK_READY }, [ 0x46 ] = { cmd_get_configuration, ALLOW_UA }, [ 0x4a ] = { cmd_get_event_status_notification, ALLOW_UA }, + [ 0x51 ] = { cmd_read_disc_information, CHECK_READY }, [ 0x5a ] = { cmd_mode_sense, /* (10) */ 0 }, [ 0xa8 ] = { cmd_read, /* (12) */ CHECK_READY }, [ 0xad ] = { cmd_read_dvd_structure, CHECK_READY }, diff --git a/hw/ide/cmd646.c b/hw/ide/cmd646.c index 4ff3624aa9..e0b9443496 100644 --- a/hw/ide/cmd646.c +++ b/hw/ide/cmd646.c @@ -94,12 +94,12 @@ static void cmd646_data_write(void *opaque, target_phys_addr_t addr, CMD646BAR *cmd646bar = opaque; if (size == 1) { - return ide_ioport_write(cmd646bar->bus, addr, data); + ide_ioport_write(cmd646bar->bus, addr, data); } else if (addr == 0) { if (size == 2) { - return ide_data_writew(cmd646bar->bus, addr, data); + ide_data_writew(cmd646bar->bus, addr, data); } else { - return ide_data_writel(cmd646bar->bus, addr, data); + ide_data_writel(cmd646bar->bus, addr, data); } } } diff --git a/hw/ide/core.c b/hw/ide/core.c index 9785d5f713..d65ef3d58d 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -30,6 +30,7 @@ #include "qemu-timer.h" #include "sysemu.h" #include "dma.h" +#include "hw/block-common.h" #include "blockdev.h" #include <hw/ide/internal.h> @@ -1047,6 +1048,7 @@ static bool ide_cmd_permitted(IDEState *s, uint32_t cmd) void ide_exec_cmd(IDEBus *bus, uint32_t val) { + uint16_t *identify_data; IDEState *s; int n; int lba48 = 0; @@ -1231,10 +1233,21 @@ void ide_exec_cmd(IDEBus *bus, uint32_t val) goto abort_cmd; /* XXX: valid for CDROM ? */ switch(s->feature) { - case 0xcc: /* reverting to power-on defaults enable */ - case 0x66: /* reverting to power-on defaults disable */ case 0x02: /* write cache enable */ + bdrv_set_enable_write_cache(s->bs, true); + identify_data = (uint16_t *)s->identify_data; + put_le16(identify_data + 85, (1 << 14) | (1 << 5) | 1); + s->status = READY_STAT | SEEK_STAT; + ide_set_irq(s->bus); + break; case 0x82: /* write cache disable */ + bdrv_set_enable_write_cache(s->bs, false); + identify_data = (uint16_t *)s->identify_data; + put_le16(identify_data + 85, (1 << 14) | 1); + ide_flush_cache(s); + break; + case 0xcc: /* reverting to power-on defaults enable */ + case 0x66: /* reverting to power-on defaults disable */ case 0xaa: /* read look-ahead enable */ case 0x55: /* read look-ahead disable */ case 0x05: /* set advanced power management mode */ @@ -1250,7 +1263,7 @@ void ide_exec_cmd(IDEBus *bus, uint32_t val) break; case 0x03: { /* set transfer mode */ uint8_t val = s->nsector & 0x07; - uint16_t *identify_data = (uint16_t *)s->identify_data; + identify_data = (uint16_t *)s->identify_data; switch (s->nsector >> 3) { case 0x00: /* pio default */ @@ -1912,31 +1925,20 @@ static const BlockDevOps ide_cd_block_ops = { int ide_init_drive(IDEState *s, BlockDriverState *bs, IDEDriveKind kind, const char *version, const char *serial, const char *model, - uint64_t wwn) + uint64_t wwn, + uint32_t cylinders, uint32_t heads, uint32_t secs, + int chs_trans) { - int cylinders, heads, secs; uint64_t nb_sectors; s->bs = bs; s->drive_kind = kind; bdrv_get_geometry(bs, &nb_sectors); - bdrv_guess_geometry(bs, &cylinders, &heads, &secs); - if (cylinders < 1 || cylinders > 16383) { - error_report("cyls must be between 1 and 16383"); - return -1; - } - if (heads < 1 || heads > 16) { - error_report("heads must be between 1 and 16"); - return -1; - } - if (secs < 1 || secs > 63) { - error_report("secs must be between 1 and 63"); - return -1; - } s->cylinders = cylinders; s->heads = heads; s->sectors = secs; + s->chs_trans = chs_trans; s->nb_sectors = nb_sectors; s->wwn = wwn; /* The SMART values should be preserved across power cycles @@ -1983,7 +1985,7 @@ int ide_init_drive(IDEState *s, BlockDriverState *bs, IDEDriveKind kind, if (version) { pstrcpy(s->version, sizeof(s->version), version); } else { - pstrcpy(s->version, sizeof(s->version), QEMU_VERSION); + pstrcpy(s->version, sizeof(s->version), qemu_get_version()); } ide_reset(s); @@ -2063,17 +2065,39 @@ void ide_init2(IDEBus *bus, qemu_irq irq) void ide_init2_with_non_qdev_drives(IDEBus *bus, DriveInfo *hd0, DriveInfo *hd1, qemu_irq irq) { - int i; + int i, trans; DriveInfo *dinfo; + uint32_t cyls, heads, secs; for(i = 0; i < 2; i++) { dinfo = i == 0 ? hd0 : hd1; ide_init1(bus, i); if (dinfo) { + cyls = dinfo->cyls; + heads = dinfo->heads; + secs = dinfo->secs; + trans = dinfo->trans; + if (!cyls && !heads && !secs) { + hd_geometry_guess(dinfo->bdrv, &cyls, &heads, &secs, &trans); + } else if (trans == BIOS_ATA_TRANSLATION_AUTO) { + trans = hd_bios_chs_auto_trans(cyls, heads, secs); + } + if (cyls < 1 || cyls > 65535) { + error_report("cyls must be between 1 and 65535"); + exit(1); + } + if (heads < 1 || heads > 16) { + error_report("heads must be between 1 and 16"); + exit(1); + } + if (secs < 1 || secs > 255) { + error_report("secs must be between 1 and 255"); + exit(1); + } if (ide_init_drive(&bus->ifs[i], dinfo->bdrv, - dinfo->media_cd ? IDE_CD : IDE_HD, NULL, - *dinfo->serial ? dinfo->serial : NULL, - NULL, 0) < 0) { + dinfo->media_cd ? IDE_CD : IDE_HD, + NULL, dinfo->serial, NULL, 0, + cyls, heads, secs, trans) < 0) { error_report("Can't set up IDE drive %s", dinfo->id); exit(1); } @@ -2146,6 +2170,9 @@ static int ide_drive_post_load(void *opaque, int version_id) s->cdrom_changed = 1; } } + if (s->identify_set) { + bdrv_set_enable_write_cache(s->bs, !!(s->identify_data[85] & (1 << 5))); + } return 0; } diff --git a/hw/ide/ich.c b/hw/ide/ich.c index c3a425b22f..272b7734b5 100644 --- a/hw/ide/ich.c +++ b/hw/ide/ich.c @@ -98,7 +98,7 @@ static int pci_ich9_ahci_init(PCIDevice *dev) uint8_t *sata_cap; d = DO_UPCAST(struct AHCIPCIState, card, dev); - ahci_init(&d->ahci, &dev->qdev, 6); + ahci_init(&d->ahci, &dev->qdev, pci_dma_context(dev), 6); pci_config_set_prog_interface(d->card.config, AHCI_PROGMODE_MAJOR_REV_1); diff --git a/hw/ide/internal.h b/hw/ide/internal.h index f8a027d0e4..7170bd9cd0 100644 --- a/hw/ide/internal.h +++ b/hw/ide/internal.h @@ -11,6 +11,7 @@ #include "iorange.h" #include "dma.h" #include "sysemu.h" +#include "hw/block-common.h" #include "hw/scsi-defs.h" /* debug IDE devices */ @@ -25,6 +26,9 @@ 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 @@ -341,7 +345,7 @@ struct IDEState { uint8_t unit; /* ide config */ IDEDriveKind drive_kind; - int cylinders, heads, sectors; + int cylinders, heads, sectors, chs_trans; int64_t nb_sectors; int mult_sectors; int identify_set; @@ -471,6 +475,7 @@ struct IDEDevice { DeviceState qdev; uint32_t unit; BlockConf conf; + int chs_trans; char *version; char *serial; char *model; @@ -542,7 +547,9 @@ uint32_t ide_data_readl(void *opaque, uint32_t addr); int ide_init_drive(IDEState *s, BlockDriverState *bs, IDEDriveKind kind, const char *version, const char *serial, const char *model, - uint64_t wwn); + 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_init2_with_non_qdev_drives(IDEBus *bus, DriveInfo *hd0, DriveInfo *hd1, qemu_irq irq); diff --git a/hw/ide/macio.c b/hw/ide/macio.c index 7b38d9e683..848cb31429 100644 --- a/hw/ide/macio.c +++ b/hw/ide/macio.c @@ -76,7 +76,7 @@ static void pmac_ide_atapi_transfer_cb(void *opaque, int ret) s->io_buffer_size = io->len; - qemu_sglist_init(&s->sg, io->len / MACIO_PAGE_SIZE + 1); + qemu_sglist_init(&s->sg, io->len / MACIO_PAGE_SIZE + 1, NULL); qemu_sglist_add(&s->sg, io->addr, io->len); io->addr += io->len; io->len = 0; @@ -133,7 +133,7 @@ static void pmac_ide_transfer_cb(void *opaque, int ret) s->io_buffer_index = 0; s->io_buffer_size = io->len; - qemu_sglist_init(&s->sg, io->len / MACIO_PAGE_SIZE + 1); + qemu_sglist_init(&s->sg, io->len / MACIO_PAGE_SIZE + 1, NULL); qemu_sglist_add(&s->sg, io->addr, io->len); io->addr += io->len; io->len = 0; diff --git a/hw/ide/piix.c b/hw/ide/piix.c index 455c1b2698..4ded9ee13d 100644 --- a/hw/ide/piix.c +++ b/hw/ide/piix.c @@ -22,11 +22,12 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + #include <hw/hw.h> #include <hw/pc.h> #include <hw/pci.h> #include <hw/isa.h> -#include "block.h" +#include "blockdev.h" #include "sysemu.h" #include "dma.h" @@ -72,7 +73,8 @@ static void bmdma_write(void *opaque, target_phys_addr_t addr, #endif switch(addr & 3) { case 0: - return bmdma_cmd_writeb(bm, val); + bmdma_cmd_writeb(bm, val); + break; case 2: bm->status = (val & 0x60) | (bm->status & 1) | (bm->status & ~val & 0x06); break; diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c index a46578d685..22e58dfc8a 100644 --- a/hw/ide/qdev.c +++ b/hw/ide/qdev.c @@ -21,25 +21,35 @@ #include "qemu-error.h" #include <hw/ide/internal.h> #include "blockdev.h" +#include "hw/block-common.h" #include "sysemu.h" /* --------------------------------- */ static char *idebus_get_fw_dev_path(DeviceState *dev); -static struct BusInfo ide_bus_info = { - .name = "IDE", - .size = sizeof(IDEBus), - .get_fw_dev_path = idebus_get_fw_dev_path, - .props = (Property[]) { - DEFINE_PROP_UINT32("unit", IDEDevice, unit, -1), - DEFINE_PROP_END_OF_LIST(), - }, +static Property ide_props[] = { + DEFINE_PROP_UINT32("unit", IDEDevice, unit, -1), + DEFINE_PROP_END_OF_LIST(), +}; + +static void ide_bus_class_init(ObjectClass *klass, void *data) +{ + BusClass *k = BUS_CLASS(klass); + + k->get_fw_dev_path = idebus_get_fw_dev_path; +} + +static const TypeInfo ide_bus_info = { + .name = TYPE_IDE_BUS, + .parent = TYPE_BUS, + .instance_size = sizeof(IDEBus), + .class_init = ide_bus_class_init, }; void ide_bus_new(IDEBus *idebus, DeviceState *dev, int bus_id) { - qbus_create_inplace(&idebus->qbus, &ide_bus_info, dev, NULL); + qbus_create_inplace(&idebus->qbus, TYPE_IDE_BUS, dev, NULL); idebus->bus_id = bus_id; } @@ -102,11 +112,24 @@ IDEDevice *ide_create_drive(IDEBus *bus, int unit, DriveInfo *drive) return DO_UPCAST(IDEDevice, qdev, dev); } -void ide_get_bs(BlockDriverState *bs[], BusState *qbus) +int ide_get_geometry(BusState *bus, int unit, + int16_t *cyls, int8_t *heads, int8_t *secs) { - IDEBus *bus = DO_UPCAST(IDEBus, qbus, qbus); - bs[0] = bus->master ? bus->master->conf.bs : NULL; - bs[1] = bus->slave ? bus->slave->conf.bs : NULL; + IDEState *s = &DO_UPCAST(IDEBus, qbus, bus)->ifs[unit]; + + if (s->drive_kind != IDE_HD || !s->bs) { + return -1; + } + + *cyls = s->cylinders; + *heads = s->heads; + *secs = s->sectors; + return 0; +} + +int ide_get_bios_chs_trans(BusState *bus, int unit) +{ + return DO_UPCAST(IDEBus, qbus, bus)->ifs[unit].chs_trans; } /* --------------------------------- */ @@ -119,25 +142,21 @@ static int ide_dev_initfn(IDEDevice *dev, IDEDriveKind kind) { IDEBus *bus = DO_UPCAST(IDEBus, qbus, dev->qdev.parent_bus); IDEState *s = bus->ifs + dev->unit; - const char *serial; - DriveInfo *dinfo; if (dev->conf.discard_granularity && dev->conf.discard_granularity != 512) { error_report("discard_granularity must be 512 for ide"); return -1; } - serial = dev->serial; - if (!serial) { - /* try to fall back to value set with legacy -drive serial=... */ - dinfo = drive_get_by_blockdev(dev->conf.bs); - if (*dinfo->serial) { - serial = dinfo->serial; - } + blkconf_serial(&dev->conf, &dev->serial); + if (blkconf_geometry(&dev->conf, &dev->chs_trans, 65536, 16, 255) < 0) { + return -1; } if (ide_init_drive(s, dev->conf.bs, kind, - dev->version, serial, dev->model, dev->wwn) < 0) { + dev->version, dev->serial, dev->model, dev->wwn, + dev->conf.cyls, dev->conf.heads, dev->conf.secs, + dev->chs_trans) < 0) { return -1; } @@ -180,6 +199,9 @@ static int ide_drive_initfn(IDEDevice *dev) static Property ide_hd_properties[] = { DEFINE_IDE_DEV_PROPERTIES(), + DEFINE_BLOCK_CHS_PROPERTIES(IDEDrive, dev.conf), + DEFINE_PROP_BIOS_CHS_TRANS("bios-chs-trans", + IDEDrive, dev.chs_trans, BIOS_ATA_TRANSLATION_AUTO), DEFINE_PROP_END_OF_LIST(), }; @@ -248,7 +270,8 @@ static void ide_device_class_init(ObjectClass *klass, void *data) { DeviceClass *k = DEVICE_CLASS(klass); k->init = ide_qdev_init; - k->bus_info = &ide_bus_info; + k->bus_type = TYPE_IDE_BUS; + k->props = ide_props; } static TypeInfo ide_device_type_info = { @@ -262,6 +285,7 @@ static TypeInfo ide_device_type_info = { static void ide_register_types(void) { + type_register_static(&ide_bus_info); type_register_static(&ide_hd_info); type_register_static(&ide_cd_info); type_register_static(&ide_drive_info); diff --git a/hw/ide/via.c b/hw/ide/via.c index 3e25085d42..b20e4f094e 100644 --- a/hw/ide/via.c +++ b/hw/ide/via.c @@ -74,7 +74,8 @@ static void bmdma_write(void *opaque, target_phys_addr_t addr, #endif switch (addr & 3) { case 0: - return bmdma_cmd_writeb(bm, val); + bmdma_cmd_writeb(bm, val); + break; case 2: bm->status = (val & 0x60) | (bm->status & 1) | (bm->status & ~val & 0x06); break; |