From b30d05ad0a9ee697ba41a09f05273d63d2f36fb2 Mon Sep 17 00:00:00 2001 From: Pekka Enberg Date: Sun, 15 Aug 2010 14:44:41 +0300 Subject: [PATCH] kvm: Extract virtio-blk driver to separate file This patch extracts virtio-blk driver to a separate file. Signed-off-by: Pekka Enberg --- Makefile | 1 + blk-virtio.c | 42 ++++++++++++++++++++++++++++ include/kvm/blk-virtio.h | 6 ++++ include/kvm/pci.h | 1 + main.c | 2 ++ pci.c | 60 +++++++++++++++++----------------------- 6 files changed, 77 insertions(+), 35 deletions(-) create mode 100644 blk-virtio.c create mode 100644 include/kvm/blk-virtio.h diff --git a/Makefile b/Makefile index 67193b3..7c4e13e 100644 --- a/Makefile +++ b/Makefile @@ -9,6 +9,7 @@ export E Q PROGRAM = kvm +OBJS += blk-virtio.o OBJS += cpuid.o OBJS += early_printk.o OBJS += interrupt.o diff --git a/blk-virtio.c b/blk-virtio.c new file mode 100644 index 0000000..65b1dd7 --- /dev/null +++ b/blk-virtio.c @@ -0,0 +1,42 @@ +#include "kvm/blk-virtio.h" + +#include "kvm/ioport.h" +#include "kvm/pci.h" + +#define PCI_VENDOR_ID_REDHAT_QUMRANET 0x1af4 +#define PCI_DEVICE_ID_VIRTIO_BLK 0x1001 +#define PCI_SUBSYSTEM_VENDOR_ID_REDHAT_QUMRANET 0x1af4 +#define PCI_SUBSYSTEM_ID_VIRTIO_BLK 0x0002 + +static struct pci_device_header virtio_device = { + .vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET, + .device_id = PCI_DEVICE_ID_VIRTIO_BLK, + .header_type = PCI_HEADER_TYPE_NORMAL, + .revision_id = 0, + .class = 0x010000, + .subsys_vendor_id = PCI_SUBSYSTEM_VENDOR_ID_REDHAT_QUMRANET, + .subsys_id = PCI_SUBSYSTEM_ID_VIRTIO_BLK, + .bar[0] = IOPORT_VIRTIO | PCI_BASE_ADDRESS_SPACE_IO, +}; + +static bool virtio_in(struct kvm *self, uint16_t port, void *data, int size, uint32_t count) +{ + return true; +} + +static bool virtio_out(struct kvm *self, uint16_t port, void *data, int size, uint32_t count) +{ + return true; +} + +static struct ioport_operations virtio_io_ops = { + .io_in = virtio_in, + .io_out = virtio_out, +}; + +void blk_virtio__init(void) +{ + pci__register(&virtio_device, 1); + + ioport__register(IOPORT_VIRTIO, &virtio_io_ops); +} diff --git a/include/kvm/blk-virtio.h b/include/kvm/blk-virtio.h new file mode 100644 index 0000000..f108291 --- /dev/null +++ b/include/kvm/blk-virtio.h @@ -0,0 +1,6 @@ +#ifndef KVM__BLK_VIRTIO_H +#define KVM__BLK_VIRTIO_H + +void blk_virtio__init(void); + +#endif /* KVM__BLK_VIRTIO_H */ diff --git a/include/kvm/pci.h b/include/kvm/pci.h index e8551d8..22489b5 100644 --- a/include/kvm/pci.h +++ b/include/kvm/pci.h @@ -50,5 +50,6 @@ struct pci_device_header { }; void pci__init(void); +void pci__register(struct pci_device_header *dev, uint8_t dev_num); #endif /* KVM__PCI_H */ diff --git a/main.c b/main.c index fa916ab..1fd9301 100644 --- a/main.c +++ b/main.c @@ -1,6 +1,7 @@ #include "kvm/kvm.h" #include "kvm/early_printk.h" +#include "kvm/blk-virtio.h" #include "kvm/util.h" #include "kvm/pci.h" @@ -116,6 +117,7 @@ int main(int argc, char *argv[]) early_printk__init(); pci__init(); + blk_virtio__init(); for (;;) { kvm__run(kvm); diff --git a/pci.c b/pci.c index 7b1a05f..34a9033 100644 --- a/pci.c +++ b/pci.c @@ -2,9 +2,14 @@ #include "kvm/ioport.h" #include "kvm/util.h" +#include #include -static struct pci_config_address pci_config_address; +#define PCI_MAX_DEVICES 256 + +static struct pci_device_header *pci_devices[PCI_MAX_DEVICES]; + +static struct pci_config_address pci_config_address; static void *pci_config_address_ptr(uint16_t port) { @@ -45,36 +50,28 @@ static bool pci_config_data_out(struct kvm *self, uint16_t port, void *data, int return true; } -#define PCI_VENDOR_ID_REDHAT_QUMRANET 0x1af4 -#define PCI_DEVICE_ID_VIRTIO_BLK 0x1001 -#define PCI_SUBSYSTEM_VENDOR_ID_REDHAT_QUMRANET 0x1af4 -#define PCI_SUBSYSTEM_ID_VIRTIO_BLK 0x0002 - -static struct pci_device_header virtio_device = { - .vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET, - .device_id = PCI_DEVICE_ID_VIRTIO_BLK, - .header_type = PCI_HEADER_TYPE_NORMAL, - .revision_id = 0, - .class = 0x010000, - .subsys_vendor_id = PCI_SUBSYSTEM_VENDOR_ID_REDHAT_QUMRANET, - .subsys_id = PCI_SUBSYSTEM_ID_VIRTIO_BLK, - .bar[0] = IOPORT_VIRTIO | PCI_BASE_ADDRESS_SPACE_IO, -}; - -static bool pci_device_matches(uint8_t bus_number, uint8_t device_number, uint8_t function_number) +static bool pci_device_exists(uint8_t bus_number, uint8_t device_number, uint8_t function_number) { + struct pci_device_header *dev; + if (pci_config_address.bus_number != bus_number) return false; - if (pci_config_address.device_number != device_number) + if (pci_config_address.function_number != function_number) return false; - return pci_config_address.function_number == function_number; + if (device_number >= PCI_MAX_DEVICES) + return false; + + dev = pci_devices[device_number]; + + return dev != NULL; } static bool pci_config_data_in(struct kvm *self, uint16_t port, void *data, int size, uint32_t count) { unsigned long start; + uint8_t dev_num; /* * If someone accesses PCI configuration space offsets that are not @@ -82,12 +79,15 @@ static bool pci_config_data_in(struct kvm *self, uint16_t port, void *data, int */ start = port - PCI_CONFIG_DATA; - if (pci_device_matches(0, 1, 0)) { + dev_num = pci_config_address.device_number; + + if (pci_device_exists(0, dev_num, 0)) { unsigned long offset; offset = start + (pci_config_address.register_number << 2); if (offset < sizeof(struct pci_device_header)) { - void *p = &virtio_device; + void *p = pci_devices[dev_num]; + memcpy(data, p + offset, size); } else memset(data, 0x00, size); @@ -102,25 +102,15 @@ static struct ioport_operations pci_config_data_ops = { .io_out = pci_config_data_out, }; -static bool virtio_in(struct kvm *self, uint16_t port, void *data, int size, uint32_t count) +void pci__register(struct pci_device_header *dev, uint8_t dev_num) { - return true; -} + assert(dev_num < PCI_MAX_DEVICES); -static bool virtio_out(struct kvm *self, uint16_t port, void *data, int size, uint32_t count) -{ - return true; + pci_devices[dev_num] = dev; } -static struct ioport_operations virtio_io_ops = { - .io_in = virtio_in, - .io_out = virtio_out, -}; - void pci__init(void) { - ioport__register(IOPORT_VIRTIO, &virtio_io_ops); - ioport__register(PCI_CONFIG_DATA + 0, &pci_config_data_ops); ioport__register(PCI_CONFIG_DATA + 1, &pci_config_data_ops); ioport__register(PCI_CONFIG_DATA + 2, &pci_config_data_ops);