diff --git a/headers/private/virtio/virtio.h b/headers/private/virtio/virtio.h index bcb3f4a208..5e49019422 100644 --- a/headers/private/virtio/virtio.h +++ b/headers/private/virtio/virtio.h @@ -26,13 +26,14 @@ #define VIRTIO_DEVICE_ID_VSOCK 19 #define VIRTIO_DEVICE_ID_CRYPTO 20 -#define VIRTIO_FEATURE_TRANSPORT_MASK ((1 << 28) - 1) +#define VIRTIO_FEATURE_TRANSPORT_MASK ((1ULL << 28) - 1) #define VIRTIO_FEATURE_NOTIFY_ON_EMPTY (1 << 24) #define VIRTIO_FEATURE_ANY_LAYOUT (1 << 27) #define VIRTIO_FEATURE_RING_INDIRECT_DESC (1 << 28) #define VIRTIO_FEATURE_RING_EVENT_IDX (1 << 29) #define VIRTIO_FEATURE_BAD_FEATURE (1 << 30) +#define VIRTIO_FEATURE_VERSION_1 (1ULL << 32) #define VIRTIO_VIRTQUEUES_MAX_COUNT 8 @@ -40,6 +41,8 @@ #define VIRTIO_CONFIG_STATUS_ACK 0x01 #define VIRTIO_CONFIG_STATUS_DRIVER 0x02 #define VIRTIO_CONFIG_STATUS_DRIVER_OK 0x04 +#define VIRTIO_CONFIG_STATUS_FEATURES_OK 0x08 +#define VIRTIO_CONFIG_STATUS_DEVICE_NEEDS_RESET 0x40 #define VIRTIO_CONFIG_STATUS_FAILED 0x80 // attributes: @@ -50,6 +53,8 @@ #define VIRTIO_DEVICE_TYPE_ITEM "virtio/type" // alignment (uint16) #define VIRTIO_VRING_ALIGNMENT_ITEM "virtio/vring_alignment" +// version (uint8) +#define VIRTIO_VERSION_ITEM "virtio/version" // sim cookie, issued by virtio bus manager typedef void* virtio_sim; @@ -78,8 +83,8 @@ typedef struct { driver_module_info info; void (*set_sim)(void* cookie, virtio_sim sim); - status_t (*read_host_features)(void* cookie, uint32* features); - status_t (*write_guest_features)(void* cookie, uint32 features); + status_t (*read_host_features)(void* cookie, uint64* features); + status_t (*write_guest_features)(void* cookie, uint64 features); uint8 (*get_status)(void* cookie); void (*set_status)(void* cookie, uint8 status); status_t (*read_device_config)(void* cookie, uint8 offset, void* buffer, @@ -88,7 +93,8 @@ typedef struct { const void* buffer, size_t bufferSize); uint16 (*get_queue_ring_size)(void* cookie, uint16 queue); - status_t (*setup_queue)(void* cookie, uint16 queue, phys_addr_t phy); + status_t (*setup_queue)(void* cookie, uint16 queue, phys_addr_t phy, phys_addr_t phyAvail, + phys_addr_t phyUsed); status_t (*setup_interrupt)(void* cookie, uint16 queueCount); status_t (*free_interrupt)(void* cookie); void (*notify_queue)(void* cookie, uint16 queue); @@ -99,10 +105,10 @@ typedef struct { typedef struct { driver_module_info info; - status_t (*negotiate_features)(virtio_device cookie, uint32 supported, - uint32* negotiated, const char* (*get_feature_name)(uint32)); + status_t (*negotiate_features)(virtio_device cookie, uint64 supported, + uint64* negotiated, const char* (*get_feature_name)(uint64)); - status_t (*clear_feature)(virtio_device cookie, uint32 feature); + status_t (*clear_feature)(virtio_device cookie, uint64 feature); status_t (*read_device_config)(virtio_device cookie, uint8 offset, void* buffer, size_t bufferSize); diff --git a/src/add-ons/kernel/bus_managers/virtio/VirtioBalloonDevice.cpp b/src/add-ons/kernel/bus_managers/virtio/VirtioBalloonDevice.cpp index b7a7d0f46c..d041e37298 100644 --- a/src/add-ons/kernel/bus_managers/virtio/VirtioBalloonDevice.cpp +++ b/src/add-ons/kernel/bus_managers/virtio/VirtioBalloonDevice.cpp @@ -17,7 +17,7 @@ const char* -get_feature_name(uint32 feature) +get_feature_name(uint64 feature) { switch (feature) { case VIRTIO_BALLOON_F_MUST_TELL_HOST: diff --git a/src/add-ons/kernel/bus_managers/virtio/VirtioBalloonPrivate.h b/src/add-ons/kernel/bus_managers/virtio/VirtioBalloonPrivate.h index 0f8a360a3e..ba663b27f9 100644 --- a/src/add-ons/kernel/bus_managers/virtio/VirtioBalloonPrivate.h +++ b/src/add-ons/kernel/bus_managers/virtio/VirtioBalloonPrivate.h @@ -61,7 +61,7 @@ private: virtio_device* fVirtioDevice; status_t fStatus; - uint32 fFeatures; + uint64 fFeatures; ::virtio_queue fVirtioQueues[2]; physical_entry fEntry; diff --git a/src/add-ons/kernel/bus_managers/virtio/VirtioDevice.cpp b/src/add-ons/kernel/bus_managers/virtio/VirtioDevice.cpp index 0f2a529c37..fad7f01ce4 100644 --- a/src/add-ons/kernel/bus_managers/virtio/VirtioDevice.cpp +++ b/src/add-ons/kernel/bus_managers/virtio/VirtioDevice.cpp @@ -8,7 +8,7 @@ const char * -virtio_get_feature_name(uint32 feature) +virtio_get_feature_name(uint64 feature) { switch (feature) { case VIRTIO_FEATURE_NOTIFY_ON_EMPTY: @@ -62,6 +62,7 @@ VirtioDevice::VirtioDevice(device_node *node) fQueues(NULL), fFeatures(0), fAlignment(0), + fVirtio1(false), fConfigHandler(NULL), fDriverCookie(NULL) { @@ -80,6 +81,9 @@ VirtioDevice::VirtioDevice(device_node *node) ERROR("alignment missing\n"); return; } + uint8 version = 0; + if (gDeviceManager->get_attr_uint8(fNode, VIRTIO_VERSION_ITEM, &version, true) == B_OK) + fVirtio1 = version == 1; fController->set_sim(fCookie, this); @@ -104,8 +108,8 @@ VirtioDevice::InitCheck() status_t -VirtioDevice::NegotiateFeatures(uint32 supported, uint32* negotiated, - const char* (*get_feature_name)(uint32)) +VirtioDevice::NegotiateFeatures(uint64 supported, uint64* negotiated, + const char* (*get_feature_name)(uint64)) { fFeatures = 0; status_t status = fController->read_host_features(fCookie, &fFeatures); @@ -114,22 +118,43 @@ VirtioDevice::NegotiateFeatures(uint32 supported, uint32* negotiated, _DumpFeatures("read features", fFeatures, get_feature_name); + if (fVirtio1) { + supported |= VIRTIO_FEATURE_VERSION_1; + supported &= ~VIRTIO_FEATURE_NOTIFY_ON_EMPTY; + } + fFeatures &= supported; // filter our own features fFeatures &= (VIRTIO_FEATURE_TRANSPORT_MASK - | VIRTIO_FEATURE_RING_INDIRECT_DESC | VIRTIO_FEATURE_RING_EVENT_IDX); - - *negotiated = fFeatures; + | VIRTIO_FEATURE_RING_INDIRECT_DESC | VIRTIO_FEATURE_RING_EVENT_IDX + | VIRTIO_FEATURE_VERSION_1); _DumpFeatures("negotiated features", fFeatures, get_feature_name); - return fController->write_guest_features(fCookie, fFeatures); + status = fController->write_guest_features(fCookie, fFeatures); + if (status != B_OK) + return status; + + if (fVirtio1) { + fController->set_status(fCookie, VIRTIO_CONFIG_STATUS_FEATURES_OK); + if ((fController->get_status(fCookie) & VIRTIO_CONFIG_STATUS_FEATURES_OK) == 0) { + fController->set_status(fCookie, VIRTIO_CONFIG_STATUS_FAILED); + return B_BAD_VALUE; + } + if ((fFeatures & VIRTIO_FEATURE_VERSION_1) == 0) { + fController->set_status(fCookie, VIRTIO_CONFIG_STATUS_FAILED); + return B_BAD_VALUE; + } + } + *negotiated = fFeatures; + + return B_OK; } status_t -VirtioDevice::ClearFeature(uint32 feature) +VirtioDevice::ClearFeature(uint64 feature) { fFeatures &= ~feature; return fController->write_guest_features(fCookie, fFeatures); @@ -224,9 +249,10 @@ VirtioDevice::FreeInterrupts() status_t -VirtioDevice::SetupQueue(uint16 queueNumber, phys_addr_t physAddr) +VirtioDevice::SetupQueue(uint16 queueNumber, phys_addr_t physAddr, phys_addr_t phyAvail, + phys_addr_t phyUsed) { - return fController->setup_queue(fCookie, queueNumber, physAddr); + return fController->setup_queue(fCookie, queueNumber, physAddr, phyAvail, phyUsed); } @@ -278,12 +304,12 @@ VirtioDevice::_DestroyQueues(size_t count) void -VirtioDevice::_DumpFeatures(const char* title, uint32 features, - const char* (*get_feature_name)(uint32)) +VirtioDevice::_DumpFeatures(const char* title, uint64 features, + const char* (*get_feature_name)(uint64)) { char features_string[512] = ""; - for (uint32 i = 0; i < 32; i++) { - uint32 feature = features & (1 << i); + for (uint32 i = 0; i < 64; i++) { + uint64 feature = features & (1ULL << i); if (feature == 0) continue; const char* name = virtio_get_feature_name(feature); diff --git a/src/add-ons/kernel/bus_managers/virtio/VirtioModule.cpp b/src/add-ons/kernel/bus_managers/virtio/VirtioModule.cpp index 4c65fc81a4..efd7e8f7b4 100644 --- a/src/add-ons/kernel/bus_managers/virtio/VirtioModule.cpp +++ b/src/add-ons/kernel/bus_managers/virtio/VirtioModule.cpp @@ -54,8 +54,8 @@ virtio_device_removed(void *_device) status_t -virtio_negotiate_features(void* _device, uint32 supported, - uint32* negotiated, const char* (*get_feature_name)(uint32)) +virtio_negotiate_features(void* _device, uint64 supported, + uint64* negotiated, const char* (*get_feature_name)(uint64)) { CALLED(); VirtioDevice *device = (VirtioDevice *)_device; @@ -65,7 +65,7 @@ virtio_negotiate_features(void* _device, uint32 supported, status_t -virtio_clear_feature(void* _device, uint32 feature) +virtio_clear_feature(void* _device, uint64 feature) { CALLED(); VirtioDevice *device = (VirtioDevice *)_device; diff --git a/src/add-ons/kernel/bus_managers/virtio/VirtioPrivate.h b/src/add-ons/kernel/bus_managers/virtio/VirtioPrivate.h index e91244d012..0d08f9ebca 100644 --- a/src/add-ons/kernel/bus_managers/virtio/VirtioPrivate.h +++ b/src/add-ons/kernel/bus_managers/virtio/VirtioPrivate.h @@ -45,10 +45,10 @@ public: status_t InitCheck(); uint32 ID() const { return fID; } - status_t NegotiateFeatures(uint32 supported, - uint32* negotiated, - const char* (*get_feature_name)(uint32)); - status_t ClearFeature(uint32 feature); + status_t NegotiateFeatures(uint64 supported, + uint64* negotiated, + const char* (*get_feature_name)(uint64)); + status_t ClearFeature(uint64 feature); status_t ReadDeviceConfig(uint8 offset, void* buffer, size_t bufferSize); @@ -63,12 +63,13 @@ public: status_t FreeInterrupts(); uint16 Alignment() const { return fAlignment; } - uint32 Features() const { return fFeatures; } + uint64 Features() const { return fFeatures; } void* DriverCookie() { return fDriverCookie; } status_t SetupQueue(uint16 queueNumber, - phys_addr_t physAddr); + phys_addr_t physAddr, phys_addr_t phyAvail, + phys_addr_t phyUsed); void NotifyQueue(uint16 queueNumber); status_t QueueInterrupt(uint16 queueNumber); @@ -76,8 +77,8 @@ public: private: void _DumpFeatures(const char* title, - uint32 features, - const char* (*get_feature_name)(uint32)); + uint64 features, + const char* (*get_feature_name)(uint64)); void _DestroyQueues(size_t count); @@ -89,8 +90,9 @@ private: status_t fStatus; VirtioQueue** fQueues; size_t fQueueCount; - uint32 fFeatures; + uint64 fFeatures; uint16 fAlignment; + bool fVirtio1; virtio_intr_func fConfigHandler; void* fDriverCookie; diff --git a/src/add-ons/kernel/bus_managers/virtio/VirtioQueue.cpp b/src/add-ons/kernel/bus_managers/virtio/VirtioQueue.cpp index d13fccc066..771660e008 100644 --- a/src/add-ons/kernel/bus_managers/virtio/VirtioQueue.cpp +++ b/src/add-ons/kernel/bus_managers/virtio/VirtioQueue.cpp @@ -182,7 +182,9 @@ VirtioQueue::VirtioQueue(VirtioDevice* device, uint16 queueNumber, DisableInterrupt(); - device->SetupQueue(fQueueNumber, physAddr); + device->SetupQueue(fQueueNumber, physAddr, + physAddr + ((addr_t)fRing.avail - (addr_t)fRing.desc), + physAddr + ((addr_t)fRing.used - (addr_t)fRing.desc)); } diff --git a/src/add-ons/kernel/busses/random/VirtioRNGDevice.cpp b/src/add-ons/kernel/busses/random/VirtioRNGDevice.cpp index 256bde1c2c..5133e7cde2 100644 --- a/src/add-ons/kernel/busses/random/VirtioRNGDevice.cpp +++ b/src/add-ons/kernel/busses/random/VirtioRNGDevice.cpp @@ -14,7 +14,7 @@ const char * -get_feature_name(uint32 feature) +get_feature_name(uint64 feature) { switch (feature) { } diff --git a/src/add-ons/kernel/busses/random/VirtioRNGPrivate.h b/src/add-ons/kernel/busses/random/VirtioRNGPrivate.h index 66ffaa395c..041982931e 100644 --- a/src/add-ons/kernel/busses/random/VirtioRNGPrivate.h +++ b/src/add-ons/kernel/busses/random/VirtioRNGPrivate.h @@ -49,7 +49,7 @@ private: virtio_device* fVirtioDevice; status_t fStatus; - uint32 fFeatures; + uint64 fFeatures; ::virtio_queue fVirtioQueue; spinlock fInterruptLock; diff --git a/src/add-ons/kernel/busses/scsi/virtio/VirtioSCSIController.cpp b/src/add-ons/kernel/busses/scsi/virtio/VirtioSCSIController.cpp index 5082f1342f..7c15c8cad3 100644 --- a/src/add-ons/kernel/busses/scsi/virtio/VirtioSCSIController.cpp +++ b/src/add-ons/kernel/busses/scsi/virtio/VirtioSCSIController.cpp @@ -16,7 +16,7 @@ const char * -get_feature_name(uint32 feature) +get_feature_name(uint64 feature) { switch (feature) { case VIRTIO_SCSI_F_INOUT: diff --git a/src/add-ons/kernel/busses/scsi/virtio/VirtioSCSIPrivate.h b/src/add-ons/kernel/busses/scsi/virtio/VirtioSCSIPrivate.h index a7afe88552..4c8fde3af6 100644 --- a/src/add-ons/kernel/busses/scsi/virtio/VirtioSCSIPrivate.h +++ b/src/add-ons/kernel/busses/scsi/virtio/VirtioSCSIPrivate.h @@ -81,7 +81,7 @@ private: status_t fStatus; struct virtio_scsi_config fConfig; - uint32 fFeatures; + uint64 fFeatures; ::virtio_queue fControlVirtioQueue; ::virtio_queue fEventVirtioQueue; ::virtio_queue fRequestVirtioQueue; diff --git a/src/add-ons/kernel/busses/virtio/virtio_mmio/virtio_mmio.cpp b/src/add-ons/kernel/busses/virtio/virtio_mmio/virtio_mmio.cpp index 887a88fc2a..10d0c5b74d 100644 --- a/src/add-ons/kernel/busses/virtio/virtio_mmio/virtio_mmio.cpp +++ b/src/add-ons/kernel/busses/virtio/virtio_mmio/virtio_mmio.cpp @@ -33,7 +33,7 @@ device_manager_info* gDeviceManager; static const char * -virtio_get_feature_name(uint32 feature) +virtio_get_feature_name(uint64 feature) { switch (feature) { case VIRTIO_FEATURE_NOTIFY_ON_EMPTY: @@ -52,12 +52,12 @@ virtio_get_feature_name(uint32 feature) static void -virtio_dump_features(const char* title, uint32 features, - const char* (*get_feature_name)(uint32)) +virtio_dump_features(const char* title, uint64 features, + const char* (*get_feature_name)(uint64)) { char features_string[512] = ""; - for (uint32 i = 0; i < 32; i++) { - uint32 feature = features & (1 << i); + for (uint64 i = 0; i < 32; i++) { + uint64 feature = features & (1 << i); if (feature == 0) continue; const char* name = virtio_get_feature_name(feature); @@ -365,8 +365,8 @@ virtio_device_register_child_devices(void* cookie) static status_t -virtio_device_negotiate_features(virtio_device cookie, uint32 supported, - uint32* negotiated, const char* (*get_feature_name)(uint32)) +virtio_device_negotiate_features(virtio_device cookie, uint64 supported, + uint64* negotiated, const char* (*get_feature_name)(uint64)) { TRACE("virtio_device_negotiate_features(%p)\n", cookie); VirtioDevice* dev = (VirtioDevice*)cookie; @@ -374,7 +374,7 @@ virtio_device_negotiate_features(virtio_device cookie, uint32 supported, dev->fRegs->status |= kVirtioConfigSAcknowledge; dev->fRegs->status |= kVirtioConfigSDriver; - uint32 features = dev->fRegs->deviceFeatures; + uint64 features = dev->fRegs->deviceFeatures; virtio_dump_features("read features", features, get_feature_name); features &= supported; @@ -395,7 +395,7 @@ virtio_device_negotiate_features(virtio_device cookie, uint32 supported, static status_t -virtio_device_clear_feature(virtio_device cookie, uint32 feature) +virtio_device_clear_feature(virtio_device cookie, uint64 feature) { panic("not implemented"); return B_ERROR; diff --git a/src/add-ons/kernel/busses/virtio/virtio_pci/Jamfile b/src/add-ons/kernel/busses/virtio/virtio_pci/Jamfile index 45708f2f02..71532761df 100644 --- a/src/add-ons/kernel/busses/virtio/virtio_pci/Jamfile +++ b/src/add-ons/kernel/busses/virtio/virtio_pci/Jamfile @@ -2,7 +2,8 @@ SubDir HAIKU_TOP src add-ons kernel busses virtio virtio_pci ; SubDirC++Flags -fno-rtti ; -UsePrivateHeaders kernel virtio ; +UsePrivateHeaders virtio ; +UsePrivateKernelHeaders ; KernelAddon virtio_pci : virtio_pci.cpp diff --git a/src/add-ons/kernel/busses/virtio/virtio_pci/virtio_pci.cpp b/src/add-ons/kernel/busses/virtio/virtio_pci/virtio_pci.cpp index b676a71824..53eac5e217 100644 --- a/src/add-ons/kernel/busses/virtio/virtio_pci/virtio_pci.cpp +++ b/src/add-ons/kernel/busses/virtio/virtio_pci/virtio_pci.cpp @@ -9,6 +9,9 @@ #include #include +#include + +#include #include #include "virtio_pci.h" @@ -45,11 +48,18 @@ typedef struct { typedef struct { pci_device_module_info* pci; pci_device* device; + bool virtio1; addr_t base_addr; + area_id registersArea[4]; + addr_t commonCfgAddr; + addr_t isrAddr; + addr_t notifyAddr; + uint32 notifyOffsetMultiplier; uint8 irq; virtio_irq_type irq_type; virtio_sim sim; uint16 queue_count; + addr_t* notifyOffsets; device_node* node; pci_info info; @@ -62,12 +72,53 @@ device_manager_info* gDeviceManager; virtio_for_controller_interface* gVirtio; -int32 +static status_t +virtio_pci_find_capability(virtio_pci_sim_info* bus, uint8 cfgType, + void* buffer, size_t size) +{ + uint8 capabilityOffset; + if (bus->pci->find_pci_capability(bus->device, PCI_cap_id_vendspec, &capabilityOffset) != B_OK) + return B_ENTRY_NOT_FOUND; + + if (size < sizeof(virtio_pci_cap)) + return B_RESULT_NOT_REPRESENTABLE; + union regs { + uint32 reg[8]; + struct virtio_pci_cap capability; + } * v = (union regs*)buffer; + + while (capabilityOffset != 0) { + for (int i = 0; i < 4; i++) { + v->reg[i] = bus->pci->read_pci_config(bus->device, capabilityOffset + i * 4, 4); + } + if (v->capability.cfg_type == cfgType) + break; + capabilityOffset = v->capability.cap_next; + } + if (capabilityOffset == 0) + return B_ENTRY_NOT_FOUND; + + if (v->capability.length > sizeof(virtio_pci_cap)) { + size_t length = min_c(ROUNDUP(v->capability.length, sizeof(uint32)), size); + for (size_t i = 4; i < length / sizeof(uint32); i++) + v->reg[i] = bus->pci->read_pci_config(bus->device, capabilityOffset + i * 4, 4); + } + return B_OK; +} + + +static int32 virtio_pci_interrupt(void *data) { virtio_pci_sim_info* bus = (virtio_pci_sim_info*)data; - uint8 isr = bus->pci->read_io_8(bus->device, - bus->base_addr + VIRTIO_PCI_ISR); + uint8 isr; + if (bus->virtio1) { + uint8* isrAddr = (uint8*)bus->isrAddr; + isr = *isrAddr; + } else { + isr = bus->pci->read_io_8(bus->device, + bus->base_addr + VIRTIO_PCI_ISR); + } if (isr == 0) return B_UNHANDLED_INTERRUPT; @@ -81,7 +132,7 @@ virtio_pci_interrupt(void *data) } -int32 +static int32 virtio_pci_config_interrupt(void *data) { virtio_pci_sim_info* bus = (virtio_pci_sim_info*)data; @@ -91,7 +142,7 @@ virtio_pci_config_interrupt(void *data) } -int32 +static int32 virtio_pci_queue_interrupt(void *data) { virtio_pci_queue_cookie* cookie = (virtio_pci_queue_cookie*)data; @@ -101,33 +152,47 @@ virtio_pci_queue_interrupt(void *data) } -status_t +static status_t virtio_pci_setup_msix_interrupts(virtio_pci_sim_info* bus) { CALLED(); uint8 irq = 0; // first irq slot - bus->pci->write_io_16(bus->device, bus->base_addr - + VIRTIO_MSI_CONFIG_VECTOR, irq); - if (bus->pci->read_io_16(bus->device, bus->base_addr - + VIRTIO_MSI_CONFIG_VECTOR) == VIRTIO_MSI_NO_VECTOR) { - ERROR("msix config vector incorrect\n"); - return B_BAD_VALUE; + if (bus->virtio1) { + volatile uint16 *msixVector = (uint16*)(bus->commonCfgAddr + + offsetof(struct virtio_pci_common_cfg, config_msix_vector)); + *msixVector = irq; + } else { + bus->pci->write_io_16(bus->device, bus->base_addr + + VIRTIO_MSI_CONFIG_VECTOR, irq); + if (bus->pci->read_io_16(bus->device, bus->base_addr + + VIRTIO_MSI_CONFIG_VECTOR) == VIRTIO_MSI_NO_VECTOR) { + ERROR("msix config vector incorrect\n"); + return B_BAD_VALUE; + } } if (bus->irq_type == VIRTIO_IRQ_MSI_X) irq++; for (uint16 queue = 0; queue < bus->queue_count; queue++) { - bus->pci->write_io_16(bus->device, bus->base_addr - + VIRTIO_PCI_QUEUE_SEL, queue); - bus->pci->write_io_16(bus->device, bus->base_addr - + VIRTIO_MSI_QUEUE_VECTOR, irq); + if (bus->virtio1) { + volatile uint16* queueSelect = (uint16*)(bus->commonCfgAddr + + offsetof(struct virtio_pci_common_cfg, queue_select)); + *queueSelect = queue; + volatile uint16* msixVector = (uint16*)(bus->commonCfgAddr + + offsetof(struct virtio_pci_common_cfg, queue_msix_vector)); + *msixVector = irq; + } else { + bus->pci->write_io_16(bus->device, bus->base_addr + + VIRTIO_PCI_QUEUE_SEL, queue); + bus->pci->write_io_16(bus->device, bus->base_addr + + VIRTIO_MSI_QUEUE_VECTOR, irq); - if (bus->pci->read_io_16(bus->device, bus->base_addr - + VIRTIO_MSI_QUEUE_VECTOR) == VIRTIO_MSI_NO_VECTOR) { - ERROR("msix queue vector incorrect\n"); - return B_BAD_VALUE; + if (bus->pci->read_io_16(bus->device, bus->base_addr + + VIRTIO_MSI_QUEUE_VECTOR) == VIRTIO_MSI_NO_VECTOR) { + ERROR("msix queue vector incorrect\n"); + return B_BAD_VALUE; + } } - if (bus->irq_type == VIRTIO_IRQ_MSI_X) irq++; } @@ -146,7 +211,7 @@ set_sim(void* cookie, virtio_sim sim) static status_t -read_host_features(void* cookie, uint32 *features) +read_host_features(void* cookie, uint64 *features) { CALLED(); virtio_pci_sim_info* bus = (virtio_pci_sim_info*)cookie; @@ -154,65 +219,116 @@ read_host_features(void* cookie, uint32 *features) TRACE("read_host_features() %p node %p pci %p device %p\n", bus, bus->node, bus->pci, bus->device); - *features = bus->pci->read_io_32(bus->device, - bus->base_addr + VIRTIO_PCI_HOST_FEATURES); + if (bus->virtio1) { + volatile uint32 *select = (uint32*)(bus->commonCfgAddr + + offsetof(struct virtio_pci_common_cfg, device_feature_select)); + volatile uint32 *feature = (uint32*)(bus->commonCfgAddr + + offsetof(struct virtio_pci_common_cfg, device_feature)); + *select = 0; + *features = *feature; + *select = 1; + *features |= ((uint64)*feature << 32) ; + TRACE("read_host_features() %" B_PRIx64 "\n", *features); + } else { + *features = bus->pci->read_io_32(bus->device, + bus->base_addr + VIRTIO_PCI_HOST_FEATURES); + } return B_OK; } static status_t -write_guest_features(void* cookie, uint32 features) +write_guest_features(void* cookie, uint64 features) { CALLED(); virtio_pci_sim_info* bus = (virtio_pci_sim_info*)cookie; - bus->pci->write_io_32(bus->device, bus->base_addr - + VIRTIO_PCI_GUEST_FEATURES, features); + if (bus->virtio1) { + volatile uint32 *select = (uint32*)(bus->commonCfgAddr + + offsetof(struct virtio_pci_common_cfg, device_feature_select)); + volatile uint32 *feature = (uint32*)(bus->commonCfgAddr + + offsetof(struct virtio_pci_common_cfg, device_feature)); + *select = 0; + *feature = features & 0xffffffff; + *select = 1; + *feature = (features >> 32) ; + } else { + bus->pci->write_io_32(bus->device, bus->base_addr + + VIRTIO_PCI_GUEST_FEATURES, features); + } return B_OK; } -uint8 +static uint8 get_status(void* cookie) { CALLED(); virtio_pci_sim_info* bus = (virtio_pci_sim_info*)cookie; - return bus->pci->read_io_8(bus->device, bus->base_addr - + VIRTIO_PCI_STATUS); + if (bus->virtio1) { + uint8 *addr = (uint8*)(bus->commonCfgAddr + + offsetof(struct virtio_pci_common_cfg, device_status)); + return *addr; + } else { + return bus->pci->read_io_8(bus->device, bus->base_addr + VIRTIO_PCI_STATUS); + } } -void +static void set_status(void* cookie, uint8 status) { CALLED(); virtio_pci_sim_info* bus = (virtio_pci_sim_info*)cookie; - bus->pci->write_io_8(bus->device, bus->base_addr + VIRTIO_PCI_STATUS, - status); + if (bus->virtio1) { + uint8 *addr = (uint8*)(bus->commonCfgAddr + + offsetof(struct virtio_pci_common_cfg, device_status)); + uint8 old = 0; + if (status != 0) + old = *addr; + *addr = status | old; + } else { + uint8 old = 0; + if (status != 0) + old = bus->pci->read_io_8(bus->device, bus->base_addr + VIRTIO_PCI_STATUS); + bus->pci->write_io_8(bus->device, bus->base_addr + VIRTIO_PCI_STATUS, status | old); + } } -status_t +static status_t read_device_config(void* cookie, uint8 _offset, void* _buffer, size_t bufferSize) { CALLED(); virtio_pci_sim_info* bus = (virtio_pci_sim_info*)cookie; - addr_t offset = bus->base_addr + VIRTIO_PCI_CONFIG(bus) + _offset; + addr_t offset = bus->base_addr + _offset; + if (!bus->virtio1) + offset += VIRTIO_PCI_CONFIG(bus); uint8* buffer = (uint8*)_buffer; while (bufferSize > 0) { uint8 size = 4; if (bufferSize == 1) { size = 1; - *buffer = bus->pci->read_io_8(bus->device, - offset); + if (bus->virtio1) { + *buffer = *(uint8*)offset; + } else { + *buffer = bus->pci->read_io_8(bus->device, offset); + } } else if (bufferSize <= 3) { size = 2; - *(uint16*)buffer = bus->pci->read_io_16(bus->device, - offset); + if (bus->virtio1) { + *(uint16*)buffer = *(uint16*)offset; + } else { + *(uint16*)buffer = bus->pci->read_io_16(bus->device, offset); + } } else { - *(uint32*)buffer = bus->pci->read_io_32(bus->device, - offset); + if (bus->virtio1) { + *(uint32*)buffer = *(uint32*)offset; + } else { + *(uint32*)buffer = bus->pci->read_io_32(bus->device, + offset); + } } buffer += size; bufferSize -= size; @@ -223,28 +339,39 @@ read_device_config(void* cookie, uint8 _offset, void* _buffer, } -status_t +static status_t write_device_config(void* cookie, uint8 _offset, const void* _buffer, size_t bufferSize) { CALLED(); virtio_pci_sim_info* bus = (virtio_pci_sim_info*)cookie; - addr_t offset = bus->base_addr + VIRTIO_PCI_CONFIG(bus) + _offset; + addr_t offset = bus->base_addr + _offset; + if (!bus->virtio1) + offset += VIRTIO_PCI_CONFIG(bus); const uint8* buffer = (const uint8*)_buffer; while (bufferSize > 0) { uint8 size = 4; if (bufferSize == 1) { size = 1; - bus->pci->write_io_8(bus->device, - offset, *buffer); + if (bus->virtio1) { + *(uint8*)offset = *buffer; + } else { + bus->pci->write_io_8(bus->device, offset, *buffer); + } } else if (bufferSize <= 3) { size = 2; - bus->pci->write_io_16(bus->device, - offset, *(const uint16*)buffer); + if (bus->virtio1) { + *(uint16*)offset = *(uint16*)buffer; + } else { + bus->pci->write_io_16(bus->device, offset, *(const uint16*)buffer); + } } else { - bus->pci->write_io_32(bus->device, - offset, *(const uint32*)buffer); + if (bus->virtio1) { + *(uint32*)offset = *(uint32*)buffer; + } else { + bus->pci->write_io_32(bus->device, offset, *(const uint32*)buffer); + } } buffer += size; bufferSize -= size; @@ -254,32 +381,67 @@ write_device_config(void* cookie, uint8 _offset, const void* _buffer, } -uint16 +static uint16 get_queue_ring_size(void* cookie, uint16 queue) { CALLED(); virtio_pci_sim_info* bus = (virtio_pci_sim_info*)cookie; - bus->pci->write_io_16(bus->device, bus->base_addr + VIRTIO_PCI_QUEUE_SEL, - queue); - return bus->pci->read_io_16(bus->device, bus->base_addr - + VIRTIO_PCI_QUEUE_NUM); + if (bus->virtio1) { + volatile uint16* queueSelect = (uint16*)(bus->commonCfgAddr + + offsetof(struct virtio_pci_common_cfg, queue_select)); + *queueSelect = queue; + volatile uint16* ringSize = (volatile uint16*)(bus->commonCfgAddr + + offsetof(struct virtio_pci_common_cfg, queue_size)); + return *ringSize; + } else { + bus->pci->write_io_16(bus->device, bus->base_addr + VIRTIO_PCI_QUEUE_SEL, + queue); + return bus->pci->read_io_16(bus->device, bus->base_addr + + VIRTIO_PCI_QUEUE_NUM); + } } -status_t -setup_queue(void* cookie, uint16 queue, phys_addr_t phy) +static status_t +setup_queue(void* cookie, uint16 queue, phys_addr_t phy, phys_addr_t phyAvail, + phys_addr_t phyUsed) { CALLED(); virtio_pci_sim_info* bus = (virtio_pci_sim_info*)cookie; - bus->pci->write_io_16(bus->device, bus->base_addr + VIRTIO_PCI_QUEUE_SEL, - queue); - bus->pci->write_io_32(bus->device, bus->base_addr + VIRTIO_PCI_QUEUE_PFN, - (uint32)phy >> VIRTIO_PCI_QUEUE_ADDR_SHIFT); + if (queue >= bus->queue_count) + return B_BAD_VALUE; + + if (bus->virtio1) { + volatile uint16* queueSelect = (uint16*)(bus->commonCfgAddr + + offsetof(struct virtio_pci_common_cfg, queue_select)); + *queueSelect = queue; + + volatile uint64* queueDesc = (volatile uint64*)(bus->commonCfgAddr + + offsetof(struct virtio_pci_common_cfg, queue_desc)); + *queueDesc = phy; + volatile uint64* queueAvail = (volatile uint64*)(bus->commonCfgAddr + + offsetof(struct virtio_pci_common_cfg, queue_avail)); + *queueAvail = phyAvail; + volatile uint64* queueUsed = (volatile uint64*)(bus->commonCfgAddr + + offsetof(struct virtio_pci_common_cfg, queue_used)); + *queueUsed = phyUsed; + volatile uint16* queueEnable = (volatile uint16*)(bus->commonCfgAddr + + offsetof(struct virtio_pci_common_cfg, queue_enable)); + *queueEnable = 1; + + volatile uint16* queueNotifyOffset = (volatile uint16*)(bus->commonCfgAddr + + offsetof(struct virtio_pci_common_cfg, queue_notify_off)); + bus->notifyOffsets[queue] = *queueNotifyOffset * bus->notifyOffsetMultiplier; + } else { + bus->pci->write_io_16(bus->device, bus->base_addr + VIRTIO_PCI_QUEUE_SEL, queue); + bus->pci->write_io_32(bus->device, bus->base_addr + VIRTIO_PCI_QUEUE_PFN, + (uint32)phy >> VIRTIO_PCI_QUEUE_ADDR_SHIFT); + } return B_OK; } -status_t +static status_t setup_interrupt(void* cookie, uint16 queueCount) { CALLED(); @@ -308,7 +470,7 @@ setup_interrupt(void* cookie, uint16 queueCount) } } else { uint8 vector; - if (bus->pci->configure_msix(bus->device, queueCount + 1, &vector) == B_OK + if (bus->pci->configure_msix(bus->device, 1, &vector) == B_OK && bus->pci->enable_msix(bus->device) == B_OK) { TRACE_ALWAYS("using MSI-X vector shared %u\n", 1); bus->irq = vector; @@ -375,7 +537,7 @@ setup_interrupt(void* cookie, uint16 queueCount) } -status_t +static status_t free_interrupt(void* cookie) { CALLED(); @@ -402,13 +564,20 @@ free_interrupt(void* cookie) } -void +static void notify_queue(void* cookie, uint16 queue) { CALLED(); virtio_pci_sim_info* bus = (virtio_pci_sim_info*)cookie; - bus->pci->write_io_16(bus->device, bus->base_addr - + VIRTIO_PCI_QUEUE_NOTIFY, queue); + if (queue >= bus->queue_count) + return; + if (bus->virtio1) { + volatile uint16* notifyAddr = (volatile uint16*)(bus->notifyAddr + bus->notifyOffsets[queue]); + *notifyAddr = queue; + } else { + bus->pci->write_io_16(bus->device, bus->base_addr + + VIRTIO_PCI_QUEUE_NOTIFY, queue); + } } @@ -446,14 +615,89 @@ init_bus(device_node* node, void** bus_cookie) pci_info *pciInfo = &bus->info; pci->get_pci_info(device, pciInfo); - // legacy interrupt - bus->base_addr = pciInfo->u.h0.base_registers[0]; + bus->virtio1 = pciInfo->revision == 1; + + if (bus->virtio1) { + struct virtio_pci_cap common, isr, deviceCap; + struct virtio_pci_notify_cap notify; + bool deviceCfgFound = false; + if (virtio_pci_find_capability(bus, VIRTIO_PCI_CAP_COMMON_CFG, &common, + sizeof(common)) != B_OK) { + return B_DEVICE_NOT_FOUND; + } + if (virtio_pci_find_capability(bus, VIRTIO_PCI_CAP_ISR_CFG, &isr, + sizeof(isr)) != B_OK) { + return B_DEVICE_NOT_FOUND; + } + if (virtio_pci_find_capability(bus, VIRTIO_PCI_CAP_DEVICE_CFG, &deviceCap, + sizeof(deviceCap)) != B_OK) { + memset(&deviceCap, 0, sizeof(deviceCap)); + } else { + deviceCfgFound = true; + } + if (virtio_pci_find_capability(bus, VIRTIO_PCI_CAP_NOTIFY_CFG, ¬ify, + sizeof(notify)) != B_OK) { + return B_DEVICE_NOT_FOUND; + } + + size_t bars[6] = {0}; + if (common.length > 0) + bars[common.bar] = common.offset + common.length; + if (isr.length > 0) + bars[isr.bar] = max_c(bars[isr.bar], isr.offset + isr.length); + if (notify.cap.length > 0) { + bars[notify.cap.bar] = max_c(bars[notify.cap.bar], notify.cap.offset + + notify.cap.length); + } + if (deviceCfgFound && deviceCap.length > 0) + bars[deviceCap.bar] = max_c(bars[deviceCap.bar], deviceCap.offset + deviceCap.length); + + int index = 0; + addr_t registers[6] = {0}; + for (int i = 0; i < 6; i++) { + if (bars[i] == 0) + continue; + phys_addr_t barAddr = pciInfo->u.h0.base_registers[i]; + size_t barSize = pciInfo->u.h0.base_register_sizes[i]; + if ((pciInfo->u.h0.base_register_flags[i] & PCI_address_type) == PCI_address_type_64) { + barAddr |= (uint64)pciInfo->u.h0.base_registers[i + 1] << 32; + barSize |= (uint64)pciInfo->u.h0.base_register_sizes[i + 1] << 32; + } + + bus->registersArea[i] = map_physical_memory("Virtio PCI memory mapped registers", + barAddr, barSize, B_ANY_KERNEL_ADDRESS, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, + (void **)®isters[i]); + index++; + } + + bus->commonCfgAddr = registers[common.bar] + common.offset; + bus->isrAddr = registers[isr.bar] + isr.offset; + bus->notifyAddr = registers[notify.cap.bar] + notify.cap.offset; + bus->notifyOffsetMultiplier = notify.notify_off_multiplier; + if (deviceCfgFound) + bus->base_addr = registers[deviceCap.bar] + deviceCap.offset; + + // enable bus master and memory + uint16 pcicmd = pci->read_pci_config(device, PCI_command, 2); + pcicmd &= ~(PCI_command_int_disable | PCI_command_io); + pci->write_pci_config(device, PCI_command, 2, + pcicmd | PCI_command_master | PCI_command_memory); + + volatile uint16 *queueCount = (uint16*)(bus->commonCfgAddr + + offsetof(struct virtio_pci_common_cfg, num_queues)); + bus->notifyOffsets = new addr_t[*queueCount]; + + } else { + // legacy interrupt + bus->base_addr = pciInfo->u.h0.base_registers[0]; + + // enable bus master and io + uint16 pcicmd = pci->read_pci_config(device, PCI_command, 2); + pcicmd &= ~(PCI_command_memory | PCI_command_int_disable); + pcicmd |= PCI_command_master | PCI_command_io; + pci->write_pci_config(device, PCI_command, 2, pcicmd); + } - // enable bus master and io - uint16 pcicmd = pci->read_pci_config(device, PCI_command, 2); - pcicmd &= ~(PCI_command_memory | PCI_command_int_disable); - pcicmd |= PCI_command_master | PCI_command_io; - pci->write_pci_config(device, PCI_command, 2, pcicmd); set_status(bus, VIRTIO_CONFIG_STATUS_RESET); set_status(bus, VIRTIO_CONFIG_STATUS_ACK); @@ -488,6 +732,16 @@ uninit_bus(void* bus_cookie) } else remove_io_interrupt_handler(bus->irq, virtio_pci_interrupt, bus); + if (bus->virtio1) { + for (int i = 0; i < 6; i++) { + if (bus->registersArea[i] >= 0) + delete_area(bus->registersArea[i]); + else + break; + } + } + + delete[] bus->notifyOffsets; delete[] bus->cookies; delete bus; } @@ -514,11 +768,16 @@ register_child_devices(void* cookie) gDeviceManager->get_driver(parent, (driver_module_info**)&pci, (void**)&device); - uint16 pciSubDeviceId = pci->read_pci_config(device, PCI_subsystem_id, - 2); + uint16 pciSubDeviceId = pci->read_pci_config(device, PCI_subsystem_id, 2); + uint8 pciRevision = pci->read_pci_config(device, PCI_revision, 1); + uint16 pciDeviceId = pci->read_pci_config(device, PCI_device_id, 2); + + uint16 virtioDeviceId = pciSubDeviceId; + if (pciDeviceId >= VIRTIO_PCI_DEVICEID_MODERN_MIN) + virtioDeviceId = pciDeviceId - VIRTIO_PCI_DEVICEID_MODERN_MIN; char prettyName[25]; - sprintf(prettyName, "Virtio Device %" B_PRIu16, pciSubDeviceId); + sprintf(prettyName, "Virtio Device %" B_PRIu16, virtioDeviceId); device_attr attrs[] = { // properties of this controller for virtio bus manager @@ -529,9 +788,11 @@ register_child_devices(void* cookie) // private data to identify the device { VIRTIO_DEVICE_TYPE_ITEM, B_UINT16_TYPE, - { .ui16 = pciSubDeviceId }}, + { .ui16 = virtioDeviceId }}, { VIRTIO_VRING_ALIGNMENT_ITEM, B_UINT16_TYPE, { .ui16 = VIRTIO_PCI_VRING_ALIGN }}, + { VIRTIO_VERSION_ITEM, B_UINT8_TYPE, + { .ui8 = pciRevision }}, { NULL } }; @@ -583,7 +844,7 @@ supports_device(device_node* parent) if (vendorID == VIRTIO_PCI_VENDORID) { if (deviceID < VIRTIO_PCI_DEVICEID_MIN - || deviceID > VIRTIO_PCI_DEVICEID_MAX) { + || deviceID > VIRTIO_PCI_DEVICEID_MODERN_MAX) { return 0.0f; } @@ -591,9 +852,16 @@ supports_device(device_node* parent) pci_device* device; gDeviceManager->get_driver(parent, (driver_module_info**)&pci, (void**)&device); - uint8 pciSubDeviceId = pci->read_pci_config(device, PCI_revision, + uint8 pciRevision = pci->read_pci_config(device, PCI_revision, 1); - if (pciSubDeviceId != VIRTIO_PCI_ABI_VERSION) + if (deviceID >= VIRTIO_PCI_DEVICEID_MIN + && deviceID <= VIRTIO_PCI_DEVICEID_LEGACY_MAX + && pciRevision != 0) { + return 0.0f; + } + if (deviceID >= VIRTIO_PCI_DEVICEID_MODERN_MIN + && deviceID <= VIRTIO_PCI_DEVICEID_MODERN_MAX + && pciRevision != 1) return 0.0f; TRACE("Virtio device found! vendor 0x%04x, device 0x%04x\n", vendorID, diff --git a/src/add-ons/kernel/busses/virtio/virtio_pci/virtio_pci.h b/src/add-ons/kernel/busses/virtio/virtio_pci/virtio_pci.h index 981ab665e1..9c1151bc08 100644 --- a/src/add-ons/kernel/busses/virtio/virtio_pci/virtio_pci.h +++ b/src/add-ons/kernel/busses/virtio/virtio_pci/virtio_pci.h @@ -39,10 +39,9 @@ /* VirtIO PCI vendor/device ID. */ #define VIRTIO_PCI_VENDORID 0x1AF4 #define VIRTIO_PCI_DEVICEID_MIN 0x1000 -#define VIRTIO_PCI_DEVICEID_MAX 0x103F - -/* VirtIO ABI version, this must match exactly. */ -#define VIRTIO_PCI_ABI_VERSION 0 +#define VIRTIO_PCI_DEVICEID_LEGACY_MAX 0x103F +#define VIRTIO_PCI_DEVICEID_MODERN_MIN 0x1040 +#define VIRTIO_PCI_DEVICEID_MODERN_MAX 0x107F /* * VirtIO Header, located in BAR 0. @@ -84,4 +83,63 @@ /* The alignment to use between consumer and producer parts of vring. */ #define VIRTIO_PCI_VRING_ALIGN 4096 + +/* + * Virtio 1.0 specific + */ + +struct virtio_pci_cap { + uint8_t cap_vndr; /* Generic PCI field: PCI_CAP_ID_VNDR */ + uint8_t cap_next; /* Generic PCI field: next ptr. */ + uint8_t cap_len; /* Generic PCI field: capability length */ + uint8_t cfg_type; /* Identifies the structure. */ + uint8_t bar; /* Where to find it. */ + uint8_t padding[3]; /* Pad to full dword. */ + uint32_t offset; /* Offset within bar. */ + uint32_t length; /* Length of the structure, in bytes. */ +} _PACKED; + +/* Common configuration */ +#define VIRTIO_PCI_CAP_COMMON_CFG 1 +/* Notifications */ +#define VIRTIO_PCI_CAP_NOTIFY_CFG 2 +/* ISR Status */ +#define VIRTIO_PCI_CAP_ISR_CFG 3 +/* Device specific configuration */ +#define VIRTIO_PCI_CAP_DEVICE_CFG 4 +/* PCI configuration access */ +#define VIRTIO_PCI_CAP_PCI_CFG 5 + +struct virtio_pci_notify_cap { + struct virtio_pci_cap cap; + uint32_t notify_off_multiplier; /* Multiplier for queue_notify_off. */ +} _PACKED; + +struct virtio_pci_cfg_cap { + struct virtio_pci_cap cap; + uint8_t pci_cfg_data[4]; /* Data for BAR access. */ +} _PACKED; + +struct virtio_pci_common_cfg { + /* About the whole device. */ + uint32_t device_feature_select; /* read-write */ + uint32_t device_feature; /* read-only for driver */ + uint32_t driver_feature_select; /* read-write */ + uint32_t driver_feature; /* read-write */ + uint16_t config_msix_vector; /* read-write */ + uint16_t num_queues; /* read-only for driver */ + uint8_t device_status; /* read-write */ + uint8_t config_generation; /* read-only for driver */ + + /* About a specific virtqueue. */ + uint16_t queue_select; /* read-write */ + uint16_t queue_size; /* read-write, power of 2, or 0. */ + uint16_t queue_msix_vector; /* read-write */ + uint16_t queue_enable; /* read-write */ + uint16_t queue_notify_off; /* read-only for driver */ + uint64_t queue_desc; /* read-write */ + uint64_t queue_avail; /* read-write */ + uint64_t queue_used; /* read-write */ +} _PACKED; + #endif /* _VIRTIO_PCI_H */ diff --git a/src/add-ons/kernel/drivers/disk/virtual/virtio_block/virtio_block.cpp b/src/add-ons/kernel/drivers/disk/virtual/virtio_block/virtio_block.cpp index 5a1aee1cd5..9ac806ae17 100644 --- a/src/add-ons/kernel/drivers/disk/virtual/virtio_block/virtio_block.cpp +++ b/src/add-ons/kernel/drivers/disk/virtual/virtio_block/virtio_block.cpp @@ -55,7 +55,7 @@ typedef struct { struct virtio_blk_config config; - uint32 features; + uint64 features; uint64 capacity; uint32 block_size; uint32 physical_block_size; @@ -98,7 +98,7 @@ bool virtio_block_set_capacity(virtio_block_driver_info* info); const char * -get_feature_name(uint32 feature) +get_feature_name(uint64 feature) { switch (feature) { case VIRTIO_BLK_F_BARRIER: diff --git a/src/add-ons/kernel/drivers/input/virtio_input/virtio_input.cpp b/src/add-ons/kernel/drivers/input/virtio_input/virtio_input.cpp index 72a323be7f..0d9d1d4aff 100644 --- a/src/add-ons/kernel/drivers/input/virtio_input/virtio_input.cpp +++ b/src/add-ons/kernel/drivers/input/virtio_input/virtio_input.cpp @@ -51,7 +51,7 @@ struct VirtioInputDevice { virtio_device_interface* virtio; ::virtio_queue virtio_queue; - uint32 features; + uint64 features; uint32 packetCnt; int32 freePackets; diff --git a/src/add-ons/kernel/drivers/network/ether/virtio/virtio_net.cpp b/src/add-ons/kernel/drivers/network/ether/virtio/virtio_net.cpp index 328fed6a31..6a64e010d1 100644 --- a/src/add-ons/kernel/drivers/network/ether/virtio/virtio_net.cpp +++ b/src/add-ons/kernel/drivers/network/ether/virtio/virtio_net.cpp @@ -57,7 +57,7 @@ typedef struct { ::virtio_device virtio_device; virtio_device_interface* virtio; - uint32 features; + uint64 features; uint32 pairsCount; @@ -123,7 +123,7 @@ static void virtio_net_txDone(void* driverCookie, void* cookie); const char* -get_feature_name(uint32 feature) +get_feature_name(uint64 feature) { switch (feature) { case VIRTIO_NET_F_CSUM: @@ -195,6 +195,7 @@ virtio_net_drain_queues(virtio_net_driver_info* info) static status_t virtio_net_rx_enqueue_buf(virtio_net_driver_info* info, BufInfo* buf) { + CALLED(); physical_entry entries[2]; entries[0] = buf->hdrEntry; entries[1] = buf->entry; diff --git a/src/add-ons/kernel/drivers/network/ether/virtio/virtio_net.h b/src/add-ons/kernel/drivers/network/ether/virtio/virtio_net.h index a7f8f70abe..760d917b21 100644 --- a/src/add-ons/kernel/drivers/network/ether/virtio/virtio_net.h +++ b/src/add-ons/kernel/drivers/network/ether/virtio/virtio_net.h @@ -54,8 +54,10 @@ #define VIRTIO_NET_F_GUEST_ANNOUNCE 0x200000 /* Announce device on network */ #define VIRTIO_NET_F_MQ 0x400000 /* Device supports RFS */ #define VIRTIO_NET_F_CTRL_MAC_ADDR 0x800000 /* Set MAC address */ +#define VIRTIO_NET_F_SPEED_DUPLEX (1ULL << 63) /* Device set linkspeed and duplex */ #define VIRTIO_NET_S_LINK_UP 1 /* Link is up */ +#define VIRTIO_NET_S_ANNOUNCE 2 /* Announcement is needed */ struct virtio_net_config { /* The config defining mac address (if VIRTIO_NET_F_MAC) */ @@ -68,6 +70,8 @@ struct virtio_net_config { */ uint16_t max_virtqueue_pairs; uint16_t mtu; + uint32_t speed; + uint8_t duplex; } _PACKED; /*