diff options
Diffstat (limited to 'hw')
-rw-r--r-- | hw/fdc.c | 22 | ||||
-rw-r--r-- | hw/ide/core.c | 70 | ||||
-rw-r--r-- | hw/ide/internal.h | 9 | ||||
-rw-r--r-- | hw/ide/macio.c | 2 | ||||
-rw-r--r-- | hw/ide/microdrive.c | 2 | ||||
-rw-r--r-- | hw/ide/qdev.c | 13 | ||||
-rw-r--r-- | hw/qdev.c | 6 | ||||
-rw-r--r-- | hw/scsi-bus.c | 4 | ||||
-rw-r--r-- | hw/scsi-disk.c | 5 | ||||
-rw-r--r-- | hw/scsi-generic.c | 9 | ||||
-rw-r--r-- | hw/virtio-blk.c | 14 | ||||
-rw-r--r-- | hw/virtio-blk.h | 3 |
12 files changed, 116 insertions, 43 deletions
@@ -29,6 +29,7 @@ #include "hw.h" #include "fdc.h" +#include "qemu-error.h" #include "qemu-timer.h" #include "isa.h" #include "sysbus.h" @@ -1844,7 +1845,7 @@ static void fdctrl_result_timer(void *opaque) } /* Init functions */ -static void fdctrl_connect_drives(FDCtrl *fdctrl) +static int fdctrl_connect_drives(FDCtrl *fdctrl) { unsigned int i; FDrive *drive; @@ -1852,12 +1853,24 @@ static void fdctrl_connect_drives(FDCtrl *fdctrl) for (i = 0; i < MAX_FD; i++) { drive = &fdctrl->drives[i]; + if (drive->bs) { + if (bdrv_get_on_error(drive->bs, 0) != BLOCK_ERR_STOP_ENOSPC) { + error_report("fdc doesn't support drive option werror"); + return -1; + } + if (bdrv_get_on_error(drive->bs, 1) != BLOCK_ERR_REPORT) { + error_report("fdc doesn't support drive option rerror"); + return -1; + } + } + fd_init(drive); fd_revalidate(drive); if (drive->bs) { bdrv_set_removable(drive->bs, 1); } } + return 0; } FDCtrl *fdctrl_init_isa(DriveInfo **fds) @@ -1871,8 +1884,7 @@ FDCtrl *fdctrl_init_isa(DriveInfo **fds) if (fds[1]) { qdev_prop_set_drive_nofail(&dev->qdev, "driveB", fds[1]->bdrv); } - if (qdev_init(&dev->qdev) < 0) - return NULL; + qdev_init_nofail(&dev->qdev); return &(DO_UPCAST(FDCtrlISABus, busdev, dev)->state); } @@ -1950,9 +1962,7 @@ static int fdctrl_init_common(FDCtrl *fdctrl) if (fdctrl->dma_chann != -1) DMA_register_channel(fdctrl->dma_chann, &fdctrl_transfer_handler, fdctrl); - fdctrl_connect_drives(fdctrl); - - return 0; + return fdctrl_connect_drives(fdctrl); } static int isabus_fdc_init1(ISADevice *dev) diff --git a/hw/ide/core.c b/hw/ide/core.c index ebdceb5fec..af52c2cb2d 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -26,6 +26,7 @@ #include <hw/pc.h> #include <hw/pci.h> #include <hw/scsi.h> +#include "qemu-error.h" #include "qemu-timer.h" #include "sysemu.h" #include "dma.h" @@ -292,7 +293,7 @@ static void ide_set_signature(IDEState *s) /* put signature */ s->nsector = 1; s->sector = 1; - if (s->is_cdrom) { + if (s->drive_kind == IDE_CD) { s->lcyl = 0x14; s->hcyl = 0xeb; } else if (s->bs) { @@ -1827,15 +1828,15 @@ void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val) switch(val) { case WIN_IDENTIFY: - if (s->bs && !s->is_cdrom) { - if (!s->is_cf) + if (s->bs && s->drive_kind != IDE_CD) { + if (s->drive_kind != IDE_CFATA) ide_identify(s); else ide_cfata_identify(s); s->status = READY_STAT | SEEK_STAT; ide_transfer_start(s, s->io_buffer, 512, ide_transfer_stop); } else { - if (s->is_cdrom) { + if (s->drive_kind == IDE_CD) { ide_set_signature(s); } ide_abort_command(s); @@ -1849,7 +1850,7 @@ void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val) ide_set_irq(s->bus); break; case WIN_SETMULT: - if (s->is_cf && s->nsector == 0) { + if (s->drive_kind == IDE_CFATA && s->nsector == 0) { /* Disable Read and Write Multiple */ s->mult_sectors = 0; s->status = READY_STAT | SEEK_STAT; @@ -2033,7 +2034,7 @@ void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val) ide_set_irq(s->bus); break; case WIN_SEEK: - if(s->is_cdrom) + if(s->drive_kind == IDE_CD) goto abort_cmd; /* XXX: Check that seek is within bounds */ s->status = READY_STAT | SEEK_STAT; @@ -2041,7 +2042,7 @@ void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val) break; /* ATAPI commands */ case WIN_PIDENTIFY: - if (s->is_cdrom) { + 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); @@ -2052,7 +2053,7 @@ void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val) break; case WIN_DIAGNOSE: ide_set_signature(s); - if (s->is_cdrom) + if (s->drive_kind == IDE_CD) s->status = 0; /* ATAPI spec (v6) section 9.10 defines packet * devices to return a clear status register * with READY_STAT *not* set. */ @@ -2064,14 +2065,14 @@ void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val) ide_set_irq(s->bus); break; case WIN_SRST: - if (!s->is_cdrom) + 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->is_cdrom) + if (s->drive_kind != IDE_CD) goto abort_cmd; /* overlapping commands not supported */ if (s->feature & 0x02) @@ -2084,7 +2085,7 @@ void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val) break; /* CF-ATA commands */ case CFA_REQ_EXT_ERROR_CODE: - if (!s->is_cf) + if (s->drive_kind != IDE_CFATA) goto abort_cmd; s->error = 0x09; /* miscellaneous error */ s->status = READY_STAT | SEEK_STAT; @@ -2092,7 +2093,7 @@ void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val) break; case CFA_ERASE_SECTORS: case CFA_WEAR_LEVEL: - if (!s->is_cf) + if (s->drive_kind != IDE_CFATA) goto abort_cmd; if (val == CFA_WEAR_LEVEL) s->nsector = 0; @@ -2103,7 +2104,7 @@ void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val) ide_set_irq(s->bus); break; case CFA_TRANSLATE_SECTOR: - if (!s->is_cf) + if (s->drive_kind != IDE_CFATA) goto abort_cmd; s->error = 0x00; s->status = READY_STAT | SEEK_STAT; @@ -2123,7 +2124,7 @@ void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val) ide_set_irq(s->bus); break; case CFA_ACCESS_METADATA_STORAGE: - if (!s->is_cf) + if (s->drive_kind != IDE_CFATA) goto abort_cmd; switch (s->feature) { case 0x02: /* Inquiry Metadata Storage */ @@ -2143,7 +2144,7 @@ void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val) ide_set_irq(s->bus); break; case IBM_SENSE_CONDITION: - if (!s->is_cf) + if (s->drive_kind != IDE_CFATA) goto abort_cmd; switch (s->feature) { case 0x01: /* sense temperature in device */ @@ -2157,7 +2158,7 @@ void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val) break; case WIN_SMART: - if (s->is_cdrom) + if (s->drive_kind == IDE_CD) goto abort_cmd; if (s->hcyl != 0xc2 || s->lcyl != 0x4f) goto abort_cmd; @@ -2438,7 +2439,7 @@ void ide_cmd_write(void *opaque, uint32_t addr, uint32_t val) /* high to low */ for(i = 0;i < 2; i++) { s = &bus->ifs[i]; - if (s->is_cdrom) + if (s->drive_kind == IDE_CD) s->status = 0x00; /* NOTE: READY is _not_ set */ else s->status = READY_STAT | SEEK_STAT; @@ -2540,7 +2541,7 @@ static void ide_reset(IDEState *s) #ifdef DEBUG_IDE printf("ide: reset\n"); #endif - if (s->is_cf) + if (s->drive_kind == IDE_CFATA) s->mult_sectors = 0; else s->mult_sectors = MAX_MULT_SECTORS; @@ -2594,8 +2595,8 @@ void ide_bus_reset(IDEBus *bus) ide_clear_hob(bus); } -void ide_init_drive(IDEState *s, BlockDriverState *bs, - const char *version, const char *serial) +int ide_init_drive(IDEState *s, BlockDriverState *bs, + const char *version, const char *serial) { int cylinders, heads, secs; uint64_t nb_sectors; @@ -2603,6 +2604,18 @@ void ide_init_drive(IDEState *s, BlockDriverState *bs, s->bs = bs; 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; @@ -2614,8 +2627,13 @@ void ide_init_drive(IDEState *s, BlockDriverState *bs, s->smart_errors = 0; s->smart_selftest_count = 0; if (bdrv_get_type_hint(bs) == BDRV_TYPE_CDROM) { - s->is_cdrom = 1; + s->drive_kind = IDE_CD; bdrv_set_change_cb(bs, cdrom_change_cb, s); + } else { + if (bdrv_is_read_only(bs)) { + error_report("Can't use a read-only drive"); + return -1; + } } if (serial) { strncpy(s->drive_serial_str, serial, sizeof(s->drive_serial_str)); @@ -2629,7 +2647,8 @@ void ide_init_drive(IDEState *s, BlockDriverState *bs, pstrcpy(s->version, sizeof(s->version), QEMU_VERSION); } ide_reset(s); - bdrv_set_removable(bs, s->is_cdrom); + bdrv_set_removable(bs, s->drive_kind == IDE_CD); + return 0; } static void ide_init1(IDEBus *bus, int unit) @@ -2669,8 +2688,11 @@ void ide_init2_with_non_qdev_drives(IDEBus *bus, DriveInfo *hd0, dinfo = i == 0 ? hd0 : hd1; ide_init1(bus, i); if (dinfo) { - ide_init_drive(&bus->ifs[i], dinfo->bdrv, NULL, - *dinfo->serial ? dinfo->serial : NULL); + if (ide_init_drive(&bus->ifs[i], dinfo->bdrv, NULL, + *dinfo->serial ? dinfo->serial : NULL) < 0) { + error_report("Can't set up IDE drive %s", dinfo->id); + exit(1); + } } else { ide_reset(&bus->ifs[i]); } diff --git a/hw/ide/internal.h b/hw/ide/internal.h index 0125a9f0b9..416554324c 100644 --- a/hw/ide/internal.h +++ b/hw/ide/internal.h @@ -362,6 +362,8 @@ typedef struct BMDMAState BMDMAState; #define SMART_DISABLE 0xd9 #define SMART_STATUS 0xda +typedef enum { IDE_HD, IDE_CD, IDE_CFATA } IDEDriveKind; + typedef void EndTransferFunc(IDEState *); /* NOTE: IDEState represents in fact one drive */ @@ -369,8 +371,7 @@ struct IDEState { IDEBus *bus; uint8_t unit; /* ide config */ - int is_cdrom; - int is_cf; + IDEDriveKind drive_kind; int cylinders, heads, sectors; int64_t nb_sectors; int mult_sectors; @@ -555,8 +556,8 @@ 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); -void ide_init_drive(IDEState *s, BlockDriverState *bs, - const char *version, const char *serial); +int ide_init_drive(IDEState *s, BlockDriverState *bs, + const char *version, const char *serial); 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 fd4bdfd13c..bd1c73e62b 100644 --- a/hw/ide/macio.c +++ b/hw/ide/macio.c @@ -162,7 +162,7 @@ static void pmac_ide_transfer(DBDMA_io *io) IDEState *s = idebus_active_if(&m->bus); s->io_buffer_size = 0; - if (s->is_cdrom) { + if (s->drive_kind == IDE_CD) { pmac_ide_atapi_transfer_cb(io, 0); return; } diff --git a/hw/ide/microdrive.c b/hw/ide/microdrive.c index 8e20e7467c..2ceeb87c0c 100644 --- a/hw/ide/microdrive.c +++ b/hw/ide/microdrive.c @@ -541,7 +541,7 @@ PCMCIACardState *dscm1xxxx_init(DriveInfo *bdrv) ide_init2_with_non_qdev_drives(&md->bus, bdrv, NULL, qemu_allocate_irqs(md_set_irq, md, 1)[0]); - md->bus.ifs[0].is_cf = 1; + md->bus.ifs[0].drive_kind = IDE_CFATA; md->bus.ifs[0].mdata_size = METADATA_SIZE; md->bus.ifs[0].mdata_storage = (uint8_t *) qemu_mallocz(METADATA_SIZE); diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c index 2977a168e5..53468edcbc 100644 --- a/hw/ide/qdev.c +++ b/hw/ide/qdev.c @@ -18,7 +18,7 @@ */ #include <hw/hw.h> #include "dma.h" - +#include "qemu-error.h" #include <hw/ide/internal.h> /* --------------------------------- */ @@ -40,7 +40,7 @@ static int ide_qdev_init(DeviceState *qdev, DeviceInfo *base) IDEBus *bus = DO_UPCAST(IDEBus, qbus, qdev->parent_bus); if (!dev->conf.bs) { - fprintf(stderr, "%s: no drive specified\n", qdev->info->name); + error_report("No drive specified"); goto err; } if (dev->unit == -1) { @@ -49,19 +49,20 @@ static int ide_qdev_init(DeviceState *qdev, DeviceInfo *base) switch (dev->unit) { case 0: if (bus->master) { - fprintf(stderr, "ide: tried to assign master twice\n"); + error_report("IDE unit %d is in use", dev->unit); goto err; } bus->master = dev; break; case 1: if (bus->slave) { - fprintf(stderr, "ide: tried to assign slave twice\n"); + error_report("IDE unit %d is in use", dev->unit); goto err; } bus->slave = dev; break; default: + error_report("Invalid IDE unit %d", dev->unit); goto err; } return info->init(dev); @@ -117,7 +118,9 @@ static int ide_drive_initfn(IDEDevice *dev) } } - ide_init_drive(s, dev->conf.bs, dev->version, serial); + if (ide_init_drive(s, dev->conf.bs, dev->version, serial) < 0) { + return -1; + } if (!dev->version) { dev->version = qemu_strdup(s->version); @@ -326,8 +326,10 @@ void qdev_init_nofail(DeviceState *dev) { DeviceInfo *info = dev->info; - if (qdev_init(dev) < 0) - hw_error("Initialization of device %s failed\n", info->name); + if (qdev_init(dev) < 0) { + error_report("Initialization of device %s failed\n", info->name); + exit(1); + } } /* Unlink device from bus and free the structure. */ diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c index b84b9b98b5..d69c74c4ef 100644 --- a/hw/scsi-bus.c +++ b/hw/scsi-bus.c @@ -102,19 +102,23 @@ SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv, int int scsi_bus_legacy_handle_cmdline(SCSIBus *bus) { + Location loc; DriveInfo *dinfo; int res = 0, unit; + loc_push_none(&loc); for (unit = 0; unit < MAX_SCSI_DEVS; unit++) { dinfo = drive_get(IF_SCSI, bus->busnr, unit); if (dinfo == NULL) { continue; } + qemu_opts_loc_restore(dinfo->opts); if (!scsi_bus_legacy_add_drive(bus, dinfo->bdrv, unit)) { res = -1; break; } } + loc_pop(&loc); return res; } diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c index 3e41011ccb..c30709c550 100644 --- a/hw/scsi-disk.c +++ b/hw/scsi-disk.c @@ -1059,6 +1059,11 @@ static int scsi_disk_initfn(SCSIDevice *dev) s->bs = s->qdev.conf.bs; is_cd = bdrv_get_type_hint(s->bs) == BDRV_TYPE_CDROM; + if (bdrv_get_on_error(s->bs, 1) != BLOCK_ERR_REPORT) { + error_report("Device doesn't support drive option rerror"); + return -1; + } + if (!s->serial) { /* try to fall back to value set with legacy -drive serial=... */ dinfo = drive_get_by_blockdev(s->bs); diff --git a/hw/scsi-generic.c b/hw/scsi-generic.c index 3915e7844e..a8b4176d80 100644 --- a/hw/scsi-generic.c +++ b/hw/scsi-generic.c @@ -474,6 +474,15 @@ static int scsi_generic_initfn(SCSIDevice *dev) return -1; } + if (bdrv_get_on_error(s->bs, 0) != BLOCK_ERR_STOP_ENOSPC) { + error_report("Device doesn't support drive option werror"); + return -1; + } + if (bdrv_get_on_error(s->bs, 1) != BLOCK_ERR_REPORT) { + error_report("Device doesn't support drive option rerror"); + return -1; + } + /* check we are using a driver managing SG_IO (version 3 and after */ if (bdrv_ioctl(s->bs, SG_GET_VERSION_NUM, &sg_version) < 0 || sg_version < 30000) { diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c index 1de4242620..8747634fbe 100644 --- a/hw/virtio-blk.c +++ b/hw/virtio-blk.c @@ -26,6 +26,7 @@ typedef struct VirtIOBlock QEMUBH *bh; BlockConf *conf; unsigned short sector_mask; + char sn[BLOCK_SERIAL_STRLEN]; } VirtIOBlock; static VirtIOBlock *to_virtio_blk(VirtIODevice *vdev) @@ -324,6 +325,12 @@ static void virtio_blk_handle_request(VirtIOBlockReq *req, virtio_blk_handle_flush(req, mrb); } else if (req->out->type & VIRTIO_BLK_T_SCSI_CMD) { virtio_blk_handle_scsi(req); + } else if (req->out->type & VIRTIO_BLK_T_GET_ID) { + VirtIOBlock *s = req->dev; + + memcpy(req->elem.in_sg[0].iov_base, s->sn, + MIN(req->elem.in_sg[0].iov_len, sizeof(s->sn))); + virtio_blk_req_complete(req, VIRTIO_BLK_S_OK); } else if (req->out->type & VIRTIO_BLK_T_OUT) { qemu_iovec_init_external(&req->qiov, &req->elem.out_sg[1], req->elem.out_num - 1); @@ -481,6 +488,7 @@ VirtIODevice *virtio_blk_init(DeviceState *dev, BlockConf *conf) VirtIOBlock *s; int cylinders, heads, secs; static int virtio_blk_id; + DriveInfo *dinfo; s = (VirtIOBlock *)virtio_common_init("virtio-blk", VIRTIO_ID_BLOCK, sizeof(struct virtio_blk_config), @@ -495,6 +503,12 @@ VirtIODevice *virtio_blk_init(DeviceState *dev, BlockConf *conf) s->sector_mask = (s->conf->logical_block_size / BDRV_SECTOR_SIZE) - 1; bdrv_guess_geometry(s->bs, &cylinders, &heads, &secs); + /* NB: per existing s/n string convention the string is terminated + * by '\0' only when less than sizeof (s->sn) + */ + dinfo = drive_get_by_blockdev(s->bs); + strncpy(s->sn, dinfo->serial, sizeof (s->sn)); + s->vq = virtio_add_queue(&s->vdev, 128, virtio_blk_handle_output); qemu_add_vm_change_state_handler(virtio_blk_dma_restart_cb, s); diff --git a/hw/virtio-blk.h b/hw/virtio-blk.h index 7a7ece3d93..fff46da7db 100644 --- a/hw/virtio-blk.h +++ b/hw/virtio-blk.h @@ -59,6 +59,9 @@ struct virtio_blk_config /* Flush the volatile write cache */ #define VIRTIO_BLK_T_FLUSH 4 +/* return the device ID string */ +#define VIRTIO_BLK_T_GET_ID 8 + /* Barrier before this op. */ #define VIRTIO_BLK_T_BARRIER 0x80000000 |