Exemple #1
0
VirtIODevice *virtio_blk_init(DeviceState *dev, BlockConf *conf,
                              char **serial)
{
    VirtIOBlock *s;
    int cylinders, heads, secs;
    static int virtio_blk_id;
    DriveInfo *dinfo;

    if (!conf->bs) {
        error_report("virtio-blk-pci: drive property not set");
        return NULL;
    }
    if (!bdrv_is_inserted(conf->bs)) {
        error_report("Device needs media, but drive is empty");
        return NULL;
    }

    if (!*serial) {
        /* try to fall back to value set with legacy -drive serial=... */
        dinfo = drive_get_by_blockdev(conf->bs);
        if (*dinfo->serial) {
            *serial = strdup(dinfo->serial);
        }
    }

    s = (VirtIOBlock *)virtio_common_init("virtio-blk", VIRTIO_ID_BLOCK,
                                          sizeof(struct virtio_blk_config),
                                          sizeof(VirtIOBlock));

    s->vdev.get_config = virtio_blk_update_config;
    s->vdev.get_features = virtio_blk_get_features;
    s->vdev.reset = virtio_blk_reset;
    s->bs = conf->bs;
    s->conf = conf;
    s->serial = *serial;
    s->rq = NULL;
    s->sector_mask = (s->conf->logical_block_size / BDRV_SECTOR_SIZE) - 1;
    bdrv_guess_geometry(s->bs, &cylinders, &heads, &secs);

    s->vq = virtio_add_queue(&s->vdev, 128, virtio_blk_handle_output);

    qemu_add_vm_change_state_handler(virtio_blk_dma_restart_cb, s);
    s->qdev = dev;
    register_savevm(dev, "virtio-blk", virtio_blk_id++, 2,
                    virtio_blk_save, virtio_blk_load, s);
    bdrv_set_removable(s->bs, 0);
    bdrv_set_change_cb(s->bs, virtio_blk_change_cb, s);
    s->bs->buffer_alignment = conf->logical_block_size;

    add_boot_device_path(conf->bootindex, dev, "/disk@0,0");

    return &s->vdev;
}
Exemple #2
0
VirtIODevice *virtio_blk_init(DeviceState *dev, BlockConf *conf)
{
    VirtIOBlock *s;
    int cylinders, heads, secs;
    static int virtio_blk_id;
    DriveInfo *dinfo;

    if (!conf->bs) {
        error_report("virtio-blk-pci: drive property not set");
        return NULL;
    }
    if (!bdrv_is_inserted(conf->bs)) {
        error_report("Device needs media, but drive is empty");
        return NULL;
    }

    s = (VirtIOBlock *)virtio_common_init("virtio-blk", VIRTIO_ID_BLOCK,
                                          sizeof(struct virtio_blk_config),
                                          sizeof(VirtIOBlock));

    s->vdev.get_config = virtio_blk_update_config;
    s->vdev.get_features = virtio_blk_get_features;
    s->vdev.reset = virtio_blk_reset;
    s->bs = conf->bs;
    s->conf = conf;
    s->rq = NULL;
    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);
    s->qdev = dev;
    register_savevm(dev, "virtio-blk", virtio_blk_id++, 2,
                    virtio_blk_save, virtio_blk_load, s);
    bdrv_set_removable(s->bs, 0);
    s->bs->buffer_alignment = conf->logical_block_size;

    add_boot_device_path(conf->bootindex, dev, "/disk@0,0");

    return &s->vdev;
}
Exemple #3
0
static int scsi_generic_initfn(SCSIDevice *dev)
{
    SCSIGenericState *s = DO_UPCAST(SCSIGenericState, qdev, dev);
    int sg_version;
    struct sg_scsi_id scsiid;

    if (!s->qdev.conf.bs) {
        error_report("scsi-generic: drive property not set");
        return -1;
    }
    s->bs = s->qdev.conf.bs;

    /* check we are really using a /dev/sg* file */
    if (!bdrv_is_sg(s->bs)) {
        error_report("scsi-generic: not /dev/sg*");
        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) {
        error_report("scsi-generic: scsi generic interface too old");
        return -1;
    }

    /* get LUN of the /dev/sg? */
    if (bdrv_ioctl(s->bs, SG_GET_SCSI_ID, &scsiid)) {
        error_report("scsi-generic: SG_GET_SCSI_ID ioctl failed");
        return -1;
    }

    /* define device state */
    s->lun = scsiid.lun;
    DPRINTF("LUN %d\n", s->lun);
    s->qdev.type = scsiid.scsi_type;
    DPRINTF("device type %d\n", s->qdev.type);
    if (s->qdev.type == TYPE_TAPE) {
        s->qdev.blocksize = get_stream_blocksize(s->bs);
        if (s->qdev.blocksize == -1)
            s->qdev.blocksize = 0;
    } else {
        s->qdev.blocksize = get_blocksize(s->bs);
        /* removable media returns 0 if not present */
        if (s->qdev.blocksize <= 0) {
            if (s->qdev.type == TYPE_ROM || s->qdev.type  == TYPE_WORM)
                s->qdev.blocksize = 2048;
            else
                s->qdev.blocksize = 512;
        }
    }
    DPRINTF("block size %d\n", s->qdev.blocksize);
    s->driver_status = 0;
    memset(s->sensebuf, 0, sizeof(s->sensebuf));
    bdrv_set_removable(s->bs, 0);
    return 0;
}