aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--board-qemu/slof/virtio-block.fs10
-rw-r--r--include/helpers.h5
-rw-r--r--lib/libusb/tools.h5
-rw-r--r--lib/libvirtio/virtio-blk.c34
-rw-r--r--lib/libvirtio/virtio-blk.h10
-rw-r--r--lib/libvirtio/virtio.c13
-rw-r--r--lib/libvirtio/virtio.code6
-rw-r--r--lib/libvirtio/virtio.h1
8 files changed, 59 insertions, 25 deletions
diff --git a/board-qemu/slof/virtio-block.fs b/board-qemu/slof/virtio-block.fs
index dc432b6..ea388fb 100644
--- a/board-qemu/slof/virtio-block.fs
+++ b/board-qemu/slof/virtio-block.fs
@@ -18,7 +18,7 @@ FALSE VALUE initialized?
\ Required interface for deblocker
-200 CONSTANT block-size
+200 VALUE block-size
8000 CONSTANT max-transfer
INSTANCE VARIABLE deblocker
@@ -40,7 +40,7 @@ virtiodev virtio-setup-vd
\ Basic device initialization - which has only to be done once
: init ( -- )
- virtiodev virtio-blk-init
+ virtiodev virtio-blk-init to block-size
TRUE to initialized?
['] shutdown add-quiesce-xt
;
@@ -53,14 +53,14 @@ virtiodev virtio-setup-vd
\ Standard node "open" function
: open ( -- okay? )
open 0= IF false EXIT THEN
+ dup initialized? 0= AND IF
+ init
+ THEN
0 0 s" deblocker" $open-package dup deblocker ! dup IF
s" disk-label" find-package IF
my-args rot interpose
THEN
THEN
- dup initialized? 0= AND IF
- init
- THEN
0<>
;
diff --git a/include/helpers.h b/include/helpers.h
index 1663ea8..f6d4375 100644
--- a/include/helpers.h
+++ b/include/helpers.h
@@ -34,4 +34,9 @@ extern void SLOF_pci_config_write32(long offset, long value);
extern void SLOF_pci_config_write16(long offset, long value);
extern void *SLOF_translate_my_address(void *addr);
+#define offset_of(type, member) ((long) &((type *)0)->member)
+#define container_of(ptr, type, member) ({ \
+ const typeof(((type *)0)->member)* struct_ptr = (ptr); \
+ (type *)((char *)struct_ptr - offset_of(type, member)); })
+
#endif
diff --git a/lib/libusb/tools.h b/lib/libusb/tools.h
index 497a1a0..f531175 100644
--- a/lib/libusb/tools.h
+++ b/lib/libusb/tools.h
@@ -74,9 +74,4 @@ static inline void ci_write_reg(uint32_t *reg, uint32_t value)
ci_write_32(reg, bswap_32(value));
}
-#define offset_of(type, member) ((long) &((type *)0)->member)
-#define container_of(ptr, type, member) ({ \
- const typeof(((type *)0)->member)* struct_ptr = (ptr); \
- (type *)((char *)struct_ptr - offset_of(type, member)); })
-
#endif
diff --git a/lib/libvirtio/virtio-blk.c b/lib/libvirtio/virtio-blk.c
index 544068f..826f2ea 100644
--- a/lib/libvirtio/virtio-blk.c
+++ b/lib/libvirtio/virtio-blk.c
@@ -16,6 +16,8 @@
#include "virtio.h"
#include "virtio-blk.h"
+#define DEFAULT_SECTOR_SIZE 512
+
/**
* Initialize virtio-block device.
* @param dev pointer to virtio device information
@@ -24,6 +26,8 @@ int
virtioblk_init(struct virtio_device *dev)
{
struct vring_avail *vq_avail;
+ int blk_size = DEFAULT_SECTOR_SIZE;
+ int features;
/* Reset device */
// XXX That will clear the virtq base. We need to move
@@ -37,8 +41,8 @@ virtioblk_init(struct virtio_device *dev)
/* Tell HV that we know how to drive the device. */
virtio_set_status(dev, VIRTIO_STAT_ACKNOWLEDGE|VIRTIO_STAT_DRIVER);
- /* Device specific setup - we do not support special features right now */
- virtio_set_guest_features(dev, 0);
+ /* Device specific setup - we support F_BLK_SIZE */
+ virtio_set_guest_features(dev, VIRTIO_BLK_F_BLK_SIZE);
vq_avail = virtio_get_vring_avail(dev, 0);
vq_avail->flags = VRING_AVAIL_F_NO_INTERRUPT;
@@ -48,7 +52,14 @@ virtioblk_init(struct virtio_device *dev)
virtio_set_status(dev, VIRTIO_STAT_ACKNOWLEDGE|VIRTIO_STAT_DRIVER
|VIRTIO_STAT_DRIVER_OK);
- return 0;
+ virtio_get_host_features(dev, &features);
+ if (features & VIRTIO_BLK_F_BLK_SIZE) {
+ blk_size = virtio_get_config(dev,
+ offset_of(struct virtio_blk_cfg, blk_size),
+ sizeof(blk_size));
+ }
+
+ return blk_size;
}
@@ -90,17 +101,28 @@ virtioblk_read(struct virtio_device *dev, char *buf, long blocknum, long cnt)
volatile uint8_t status = -1;
volatile uint16_t *current_used_idx;
uint16_t last_used_idx;
+ int blk_size = DEFAULT_SECTOR_SIZE;
//printf("virtioblk_read: dev=%p buf=%p blocknum=%li count=%li\n",
// dev, buf, blocknum, cnt);
/* Check whether request is within disk capacity */
- capacity = virtio_get_config(dev, 0, sizeof(capacity));
+ capacity = virtio_get_config(dev,
+ offset_of(struct virtio_blk_cfg, capacity),
+ sizeof(capacity));
if (blocknum + cnt - 1 > capacity) {
puts("virtioblk_read: Access beyond end of device!");
return 0;
}
+ blk_size = virtio_get_config(dev,
+ offset_of(struct virtio_blk_cfg, blk_size),
+ sizeof(blk_size));
+ if (blk_size % DEFAULT_SECTOR_SIZE) {
+ fprintf(stderr, "virtio-blk: Unaligned sector read %d\n", blk_size);
+ return 0;
+ }
+
vq_size = virtio_get_qsize(dev, 0);
vq_desc = virtio_get_vring_desc(dev, 0);
vq_avail = virtio_get_vring_avail(dev, 0);
@@ -112,7 +134,7 @@ virtioblk_read(struct virtio_device *dev, char *buf, long blocknum, long cnt)
/* Set up header */
blkhdr.type = VIRTIO_BLK_T_IN | VIRTIO_BLK_T_BARRIER;
blkhdr.ioprio = 1;
- blkhdr.sector = blocknum;
+ blkhdr.sector = blocknum * blk_size / DEFAULT_SECTOR_SIZE;
/* Determine descriptor index */
id = (vq_avail->idx * 3) % vq_size;
@@ -127,7 +149,7 @@ virtioblk_read(struct virtio_device *dev, char *buf, long blocknum, long cnt)
/* Set up virtqueue descriptor for data */
desc = &vq_desc[(id + 1) % vq_size];
desc->addr = (uint64_t)buf;
- desc->len = cnt * 512;
+ desc->len = cnt * blk_size;
desc->flags = VRING_DESC_F_NEXT | VRING_DESC_F_WRITE;
desc->next = (id + 2) % vq_size;
diff --git a/lib/libvirtio/virtio-blk.h b/lib/libvirtio/virtio-blk.h
index 7c2b7e0..ac8bf28 100644
--- a/lib/libvirtio/virtio-blk.h
+++ b/lib/libvirtio/virtio-blk.h
@@ -21,9 +21,7 @@
#include <stdint.h>
-/* Device configuration layout */
-/*
-struct virtio_blk_config {
+struct virtio_blk_cfg {
uint64_t capacity;
uint32_t size_max;
uint32_t seg_max;
@@ -34,8 +32,7 @@ struct virtio_blk_config {
} geometry;
uint32_t blk_size;
uint32_t sectors_max;
-};
-*/
+} __attribute__ ((packed)) ;
/* Block request */
struct virtio_blk_req {
@@ -53,6 +50,9 @@ struct virtio_blk_req {
#define VIRTIO_BLK_T_FLUSH_OUT 5
#define VIRTIO_BLK_T_BARRIER 0x80000000
+/* VIRTIO_BLK Feature bits */
+#define VIRTIO_BLK_F_BLK_SIZE (1 << 6)
+
extern int virtioblk_init(struct virtio_device *dev);
extern void virtioblk_shutdown(struct virtio_device *dev);
extern int virtioblk_read(struct virtio_device *dev, char *buf, long blocknum, long cnt);
diff --git a/lib/libvirtio/virtio.c b/lib/libvirtio/virtio.c
index 249f803..b010796 100644
--- a/lib/libvirtio/virtio.c
+++ b/lib/libvirtio/virtio.c
@@ -162,7 +162,18 @@ void virtio_set_guest_features(struct virtio_device *dev, int features)
{
if (dev->type == VIRTIO_TYPE_PCI) {
- ci_write_32(dev->base+VIRTIOHDR_GUEST_FEATURES, features);
+ ci_write_32(dev->base+VIRTIOHDR_GUEST_FEATURES, bswap_32(features));
+ }
+}
+
+/**
+ * Get host feature bits
+ */
+void virtio_get_host_features(struct virtio_device *dev, int *features)
+
+{
+ if (dev->type == VIRTIO_TYPE_PCI && features) {
+ *features = bswap_32(ci_read_32(dev->base+VIRTIOHDR_DEVICE_FEATURES));
}
}
diff --git a/lib/libvirtio/virtio.code b/lib/libvirtio/virtio.code
index 304849e..258b9bb 100644
--- a/lib/libvirtio/virtio.code
+++ b/lib/libvirtio/virtio.code
@@ -46,10 +46,10 @@ MIRP
/******** virtio-blk ********/
-// : virtio-blk-init ( dev -- )
+// : virtio-blk-init ( dev -- blk-size)
PRIM(virtio_X2d_blk_X2d_init)
- void *dev = TOS.a; POP;
- virtioblk_init(dev);
+ void *dev = TOS.a;
+ TOS.u = virtioblk_init(dev);
MIRP
// : virtio-blk-shutdown ( dev -- )
diff --git a/lib/libvirtio/virtio.h b/lib/libvirtio/virtio.h
index b351930..d5759b4 100644
--- a/lib/libvirtio/virtio.h
+++ b/lib/libvirtio/virtio.h
@@ -81,6 +81,7 @@ extern void virtio_queue_notify(struct virtio_device *dev, int queue);
extern void virtio_set_status(struct virtio_device *dev, int status);
extern void virtio_set_qaddr(struct virtio_device *dev, int queue, unsigned int qaddr);
extern void virtio_set_guest_features(struct virtio_device *dev, int features);
+extern void virtio_get_host_features(struct virtio_device *dev, int *features);
extern uint64_t virtio_get_config(struct virtio_device *dev, int offset, int size);
extern int __virtio_read_config(struct virtio_device *dev, void *dst,
int offset, int len);