Virtio_blk_init return PCIDevice pointer
[qemu-kvm/fedora.git] / hw / virtio-blk.c
blob0f55d2ab33ee55b7261fd7ab46c695be6cb8da64
1 /*
2 * Virtio Block Device
4 * Copyright IBM, Corp. 2007
6 * Authors:
7 * Anthony Liguori <aliguori@us.ibm.com>
9 * This work is licensed under the terms of the GNU GPL, version 2. See
10 * the COPYING file in the top-level directory.
14 #include "virtio.h"
15 #include "block.h"
16 #include "block_int.h"
17 #include "pc.h"
19 /* from Linux's linux/virtio_blk.h */
21 /* The ID for virtio_block */
22 #define VIRTIO_ID_BLOCK 2
24 /* Feature bits */
25 #define VIRTIO_BLK_F_BARRIER 0 /* Does host support barriers? */
26 #define VIRTIO_BLK_F_SIZE_MAX 1 /* Indicates maximum segment size */
27 #define VIRTIO_BLK_F_SEG_MAX 2 /* Indicates maximum # of segments */
29 struct virtio_blk_config
31 uint64_t capacity;
32 uint32_t size_max;
33 uint32_t seg_max;
36 /* These two define direction. */
37 #define VIRTIO_BLK_T_IN 0
38 #define VIRTIO_BLK_T_OUT 1
40 /* This bit says it's a scsi command, not an actual read or write. */
41 #define VIRTIO_BLK_T_SCSI_CMD 2
43 /* Barrier before this op. */
44 #define VIRTIO_BLK_T_BARRIER 0x80000000
46 /* This is the first element of the read scatter-gather list. */
47 struct virtio_blk_outhdr
49 /* VIRTIO_BLK_T* */
50 uint32_t type;
51 /* io priority. */
52 uint32_t ioprio;
53 /* Sector (ie. 512 byte offset) */
54 uint64_t sector;
55 /* Where to put reply. */
56 uint64_t id;
59 #define VIRTIO_BLK_S_OK 0
60 #define VIRTIO_BLK_S_IOERR 1
61 #define VIRTIO_BLK_S_UNSUPP 2
63 /* This is the first element of the write scatter-gather list */
64 struct virtio_blk_inhdr
66 unsigned char status;
69 typedef struct VirtIOBlock
71 VirtIODevice vdev;
72 BlockDriverState *bs;
73 } VirtIOBlock;
75 static VirtIOBlock *to_virtio_blk(VirtIODevice *vdev)
77 return (VirtIOBlock *)vdev;
80 static void virtio_blk_handle_output(VirtIODevice *vdev, VirtQueue *vq)
82 VirtIOBlock *s = to_virtio_blk(vdev);
83 VirtQueueElement elem;
84 unsigned int count;
86 while ((count = virtqueue_pop(vq, &elem)) != 0) {
87 struct virtio_blk_inhdr *in;
88 struct virtio_blk_outhdr *out;
89 unsigned int wlen;
90 off_t off;
91 int i;
93 out = (void *)elem.out_sg[0].iov_base;
94 in = (void *)elem.in_sg[elem.in_num - 1].iov_base;
95 off = out->sector;
97 if (out->type & VIRTIO_BLK_T_SCSI_CMD) {
98 wlen = sizeof(*in);
99 in->status = VIRTIO_BLK_S_UNSUPP;
100 } else if (out->type & VIRTIO_BLK_T_OUT) {
101 wlen = sizeof(*in);
103 for (i = 1; i < elem.out_num; i++) {
104 bdrv_write(s->bs, off,
105 elem.out_sg[i].iov_base,
106 elem.out_sg[i].iov_len / 512);
107 off += elem.out_sg[i].iov_len / 512;
110 in->status = VIRTIO_BLK_S_OK;
111 } else {
112 wlen = sizeof(*in);
114 for (i = 0; i < elem.in_num - 1; i++) {
115 bdrv_read(s->bs, off,
116 elem.in_sg[i].iov_base,
117 elem.in_sg[i].iov_len / 512);
118 off += elem.in_sg[i].iov_len / 512;
119 wlen += elem.in_sg[i].iov_len;
122 in->status = VIRTIO_BLK_S_OK;
125 virtqueue_push(vq, &elem, wlen);
126 virtio_notify(vdev, vq);
130 static void virtio_blk_update_config(VirtIODevice *vdev, uint8_t *config)
132 VirtIOBlock *s = to_virtio_blk(vdev);
133 struct virtio_blk_config blkcfg;
134 int64_t capacity;
136 bdrv_get_geometry(s->bs, &capacity);
137 blkcfg.capacity = capacity;
138 blkcfg.seg_max = 128 - 2;
139 memcpy(config, &blkcfg, sizeof(blkcfg));
142 static uint32_t virtio_blk_get_features(VirtIODevice *vdev)
144 return (1 << VIRTIO_BLK_F_SEG_MAX);
147 void *virtio_blk_init(PCIBus *bus, uint16_t vendor, uint16_t device,
148 BlockDriverState *bs)
150 VirtIOBlock *s;
152 s = (VirtIOBlock *)virtio_init_pci(bus, "virtio-blk", vendor, device,
153 0, VIRTIO_ID_BLOCK,
154 0x01, 0x80, 0x00,
155 16, sizeof(VirtIOBlock));
157 s->vdev.update_config = virtio_blk_update_config;
158 s->vdev.get_features = virtio_blk_get_features;
159 s->bs = bs;
160 bs->devfn = s->vdev.pci_dev.devfn;
162 virtio_add_queue(&s->vdev, 128, virtio_blk_handle_output);
164 return s;