/* * Copyright 2013, 2018, Jérôme Duval, jerome.duval@gmail.com. * Distributed under the terms of the MIT License. */ #include "VirtioPrivate.h" device_manager_info *gDeviceManager = NULL; // #pragma mark - static status_t virtio_device_init(device_node *node, void **_device) { CALLED(); VirtioDevice *device = new(std::nothrow) VirtioDevice(node); if (device == NULL) return B_NO_MEMORY; status_t result = device->InitCheck(); if (result != B_OK) { ERROR("failed to set up virtio device object\n"); delete device; return result; } *_device = device; return B_OK; } static void virtio_device_uninit(void *_device) { CALLED(); VirtioDevice *device = (VirtioDevice *)_device; delete device; } static void virtio_device_removed(void *_device) { CALLED(); //VirtioDevice *device = (VirtioDevice *)_device; } // #pragma mark - status_t virtio_negotiate_features(void* _device, uint64 supported, uint64* negotiated, const char* (*get_feature_name)(uint64)) { CALLED(); VirtioDevice *device = (VirtioDevice *)_device; return device->NegotiateFeatures(supported, negotiated, get_feature_name); } status_t virtio_clear_feature(void* _device, uint64 feature) { CALLED(); VirtioDevice *device = (VirtioDevice *)_device; return device->ClearFeature(feature); } status_t virtio_read_device_config(void* _device, uint8 offset, void* buffer, size_t bufferSize) { CALLED(); VirtioDevice *device = (VirtioDevice *)_device; return device->ReadDeviceConfig(offset, buffer, bufferSize); } status_t virtio_write_device_config(void* _device, uint8 offset, const void* buffer, size_t bufferSize) { CALLED(); VirtioDevice *device = (VirtioDevice *)_device; return device->WriteDeviceConfig(offset, buffer, bufferSize); } status_t virtio_alloc_queues(virtio_device _device, size_t count, virtio_queue *queues) { CALLED(); VirtioDevice *device = (VirtioDevice *)_device; return device->AllocateQueues(count, queues); } void virtio_free_queues(virtio_device _device) { CALLED(); VirtioDevice *device = (VirtioDevice *)_device; device->FreeQueues(); } status_t virtio_setup_interrupt(virtio_device _device, virtio_intr_func config_handler, void *driverCookie) { CALLED(); VirtioDevice *device = (VirtioDevice *)_device; return device->SetupInterrupt(config_handler, driverCookie); } status_t virtio_free_interrupts(virtio_device _device) { CALLED(); VirtioDevice *device = (VirtioDevice *)_device; return device->FreeInterrupts(); } status_t virtio_queue_setup_interrupt(virtio_queue _queue, virtio_callback_func handler, void *cookie) { CALLED(); VirtioQueue *queue = (VirtioQueue *)_queue; return queue->SetupInterrupt(handler, cookie); } status_t virtio_queue_request_v(virtio_queue _queue, const physical_entry* vector, size_t readVectorCount, size_t writtenVectorCount, void *cookie) { CALLED(); VirtioQueue *queue = (VirtioQueue *)_queue; return queue->QueueRequest(vector, readVectorCount, writtenVectorCount, cookie); } status_t virtio_queue_request(virtio_queue _queue, const physical_entry *readEntry, const physical_entry *writtenEntry, void *cookie) { physical_entry entries[2]; if (readEntry != NULL) { entries[0] = *readEntry; if (writtenEntry != NULL) entries[1] = *writtenEntry; } else if (writtenEntry != NULL) entries[0] = *writtenEntry; return virtio_queue_request_v(_queue, entries, readEntry != NULL ? 1 : 0, writtenEntry != NULL? 1 : 0, cookie); } bool virtio_queue_is_full(virtio_queue _queue) { VirtioQueue *queue = (VirtioQueue *)_queue; return queue->IsFull(); } bool virtio_queue_is_empty(virtio_queue _queue) { VirtioQueue *queue = (VirtioQueue *)_queue; return queue->IsEmpty(); } uint16 virtio_queue_size(virtio_queue _queue) { VirtioQueue *queue = (VirtioQueue *)_queue; return queue->Size(); } bool virtio_queue_dequeue(virtio_queue _queue, void** _cookie, uint32* _usedLength) { VirtioQueue *queue = (VirtioQueue *)_queue; return queue->Dequeue(_cookie, _usedLength); } // #pragma mark - status_t virtio_added_device(device_node *parent) { CALLED(); uint16 deviceType; if (gDeviceManager->get_attr_uint16(parent, VIRTIO_DEVICE_TYPE_ITEM, &deviceType, true) != B_OK) { ERROR("device type missing\n"); return B_ERROR; } device_attr attributes[] = { // info about device { B_DEVICE_BUS, B_STRING_TYPE, { .string = "virtio" }}, { VIRTIO_DEVICE_TYPE_ITEM, B_UINT16_TYPE, { .ui16 = deviceType }}, { NULL } }; return gDeviceManager->register_node(parent, VIRTIO_DEVICE_MODULE_NAME, attributes, NULL, NULL); } status_t virtio_queue_interrupt_handler(virtio_sim sim, uint16 queue) { VirtioDevice* device = (VirtioDevice*)sim; return device->QueueInterrupt(queue); } status_t virtio_config_interrupt_handler(virtio_sim sim) { VirtioDevice* device = (VirtioDevice*)sim; return device->ConfigInterrupt(); } static status_t std_ops(int32 op, ...) { switch (op) { case B_MODULE_INIT: case B_MODULE_UNINIT: return B_OK; default: break; } return B_ERROR; } // #pragma mark - virtio_device_interface virtio_device_module = { { { VIRTIO_DEVICE_MODULE_NAME, 0, std_ops }, NULL, // supported devices NULL, // register node virtio_device_init, virtio_device_uninit, NULL, // register child devices NULL, // rescan virtio_device_removed, NULL, // suspend NULL, // resume }, virtio_negotiate_features, virtio_clear_feature, virtio_read_device_config, virtio_write_device_config, virtio_alloc_queues, virtio_free_queues, virtio_setup_interrupt, virtio_free_interrupts, virtio_queue_setup_interrupt, virtio_queue_request, virtio_queue_request_v, virtio_queue_is_full, virtio_queue_is_empty, virtio_queue_size, virtio_queue_dequeue }; virtio_for_controller_interface virtio_for_controller_module = { { { VIRTIO_FOR_CONTROLLER_MODULE_NAME, 0, &std_ops }, NULL, // supported devices virtio_added_device, NULL, NULL, NULL }, virtio_queue_interrupt_handler, virtio_config_interrupt_handler }; module_dependency module_dependencies[] = { { B_DEVICE_MANAGER_MODULE_NAME, (module_info **)&gDeviceManager }, {} }; extern struct driver_module_info sVirtioBalloonDriver; extern struct driver_module_info sVirtioBalloonDeviceInterface; module_info *modules[] = { (module_info *)&virtio_for_controller_module, (module_info *)&virtio_device_module, (module_info *)&sVirtioBalloonDriver, (module_info *)&sVirtioBalloonDeviceInterface, NULL };