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