Revision 37d5ddd6 hw/virtio-blk.c

b/hw/virtio-blk.c
25 25
    BlockDriverState *bs;
26 26
    VirtQueue *vq;
27 27
    void *rq;
28
    char serial_str[BLOCK_SERIAL_STRLEN + 1];
29 28
    QEMUBH *bh;
30
    size_t config_size;
31 29
} VirtIOBlock;
32 30

  
33 31
static VirtIOBlock *to_virtio_blk(VirtIODevice *vdev)
......
35 33
    return (VirtIOBlock *)vdev;
36 34
}
37 35

  
38
/* store identify data in little endian format
39
 */
40
static inline void put_le16(uint16_t *p, unsigned int v)
41
{
42
    *p = cpu_to_le16(v);
43
}
44

  
45
/* copy to *dst from *src, nul pad dst tail as needed to len bytes
46
 */
47
static inline void padstr(char *dst, const char *src, int len)
48
{
49
    while (len--)
50
        *dst++ = *src ? *src++ : '\0';
51
}
52

  
53
/* setup simulated identify data as appropriate for virtio block device
54
 *
55
 * ref: AT Attachment 8 - ATA/ATAPI Command Set (ATA8-ACS)
56
 */
57
static inline void virtio_identify_template(struct virtio_blk_config *bc)
58
{
59
    uint16_t *p = &bc->identify[0];
60
    uint64_t lba_sectors = bc->capacity;
61

  
62
    memset(p, 0, sizeof(bc->identify));
63
    put_le16(p + 0, 0x0);                            /* ATA device */
64
    padstr((char *)(p + 23), QEMU_VERSION, 8);       /* firmware revision */
65
    padstr((char *)(p + 27), "QEMU VIRT_BLK", 40);   /* model# */
66
    put_le16(p + 47, 0x80ff);                        /* max xfer 255 sectors */
67
    put_le16(p + 49, 0x0b00);                        /* support IORDY/LBA/DMA */
68
    put_le16(p + 59, 0x1ff);                         /* cur xfer 255 sectors */
69
    put_le16(p + 80, 0x1f0);                         /* support ATA8/7/6/5/4 */
70
    put_le16(p + 81, 0x16);
71
    put_le16(p + 82, 0x400);
72
    put_le16(p + 83, 0x400);
73
    put_le16(p + 100, lba_sectors);
74
    put_le16(p + 101, lba_sectors >> 16);
75
    put_le16(p + 102, lba_sectors >> 32);
76
    put_le16(p + 103, lba_sectors >> 48);
77
}
78

  
79 36
typedef struct VirtIOBlockReq
80 37
{
81 38
    VirtIOBlock *dev;
......
448 405
    blkcfg.heads = heads;
449 406
    blkcfg.sectors = secs;
450 407
    blkcfg.size_max = 0;
451
    virtio_identify_template(&blkcfg);
452
    memcpy(&blkcfg.identify[VIRTIO_BLK_ID_SN], s->serial_str,
453
        VIRTIO_BLK_ID_SN_BYTES);
454
    memcpy(config, &blkcfg, s->config_size);
408
    memcpy(config, &blkcfg, sizeof(struct virtio_blk_config));
455 409
}
456 410

  
457 411
static uint32_t virtio_blk_get_features(VirtIODevice *vdev, uint32_t features)
......
463 417

  
464 418
    if (bdrv_enable_write_cache(s->bs))
465 419
        features |= (1 << VIRTIO_BLK_F_WCACHE);
466
    if (strcmp(s->serial_str, "0"))
467
        features |= 1 << VIRTIO_BLK_F_IDENTIFY;
468 420
    
469 421
    if (bdrv_is_read_only(s->bs))
470 422
        features |= 1 << VIRTIO_BLK_F_RO;
......
510 462
    VirtIOBlock *s;
511 463
    int cylinders, heads, secs;
512 464
    static int virtio_blk_id;
513
    char *ps = (char *)drive_get_serial(dinfo->bdrv);
514
    size_t size = strlen(ps) ? sizeof(struct virtio_blk_config) :
515
	    offsetof(struct virtio_blk_config, _blk_size);
516 465

  
517 466
    s = (VirtIOBlock *)virtio_common_init("virtio-blk", VIRTIO_ID_BLOCK,
518
                                          size,
467
                                          sizeof(struct virtio_blk_config),
519 468
                                          sizeof(VirtIOBlock));
520 469

  
521
    s->config_size = size;
522 470
    s->vdev.get_config = virtio_blk_update_config;
523 471
    s->vdev.get_features = virtio_blk_get_features;
524 472
    s->vdev.reset = virtio_blk_reset;
525 473
    s->bs = dinfo->bdrv;
526 474
    s->rq = NULL;
527
    if (strlen(ps))
528
        strncpy(s->serial_str, ps, sizeof(s->serial_str));
529
    else
530
        snprintf(s->serial_str, sizeof(s->serial_str), "0");
531 475
    bdrv_guess_geometry(s->bs, &cylinders, &heads, &secs);
532 476
    bdrv_set_geometry_hint(s->bs, cylinders, heads, secs);
533 477

  

Also available in: Unified diff