1 /* 2 * Copyright 2013, 2018, Jérôme Duval, jerome.duval@gmail.com. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 #include "VirtioPrivate.h" 8 9 10 device_manager_info *gDeviceManager = NULL; 11 12 13 // #pragma mark - 14 15 16 static status_t 17 virtio_device_init(device_node *node, void **_device) 18 { 19 CALLED(); 20 VirtioDevice *device = new(std::nothrow) VirtioDevice(node); 21 if (device == NULL) 22 return B_NO_MEMORY; 23 24 status_t result = device->InitCheck(); 25 if (result != B_OK) { 26 ERROR("failed to set up virtio device object\n"); 27 delete device; 28 return result; 29 } 30 31 *_device = device; 32 return B_OK; 33 } 34 35 36 static void 37 virtio_device_uninit(void *_device) 38 { 39 CALLED(); 40 VirtioDevice *device = (VirtioDevice *)_device; 41 delete device; 42 } 43 44 45 static void 46 virtio_device_removed(void *_device) 47 { 48 CALLED(); 49 //VirtioDevice *device = (VirtioDevice *)_device; 50 } 51 52 53 // #pragma mark - 54 55 56 status_t 57 virtio_negotiate_features(void* _device, uint64 supported, 58 uint64* negotiated, const char* (*get_feature_name)(uint64)) 59 { 60 CALLED(); 61 VirtioDevice *device = (VirtioDevice *)_device; 62 63 return device->NegotiateFeatures(supported, negotiated, get_feature_name); 64 } 65 66 67 status_t 68 virtio_clear_feature(void* _device, uint64 feature) 69 { 70 CALLED(); 71 VirtioDevice *device = (VirtioDevice *)_device; 72 73 return device->ClearFeature(feature); 74 } 75 76 77 status_t 78 virtio_read_device_config(void* _device, uint8 offset, void* buffer, 79 size_t bufferSize) 80 { 81 CALLED(); 82 VirtioDevice *device = (VirtioDevice *)_device; 83 84 return device->ReadDeviceConfig(offset, buffer, bufferSize); 85 } 86 87 88 status_t 89 virtio_write_device_config(void* _device, uint8 offset, 90 const void* buffer, size_t bufferSize) 91 { 92 CALLED(); 93 VirtioDevice *device = (VirtioDevice *)_device; 94 95 return device->WriteDeviceConfig(offset, buffer, bufferSize); 96 } 97 98 99 status_t 100 virtio_alloc_queues(virtio_device _device, size_t count, virtio_queue *queues, 101 uint16 *requestedSizes) 102 { 103 CALLED(); 104 VirtioDevice *device = (VirtioDevice *)_device; 105 return device->AllocateQueues(count, queues, requestedSizes); 106 } 107 108 109 void 110 virtio_free_queues(virtio_device _device) 111 { 112 CALLED(); 113 VirtioDevice *device = (VirtioDevice *)_device; 114 device->FreeQueues(); 115 } 116 117 118 status_t 119 virtio_setup_interrupt(virtio_device _device, virtio_intr_func config_handler, 120 void *driverCookie) 121 { 122 CALLED(); 123 VirtioDevice *device = (VirtioDevice *)_device; 124 return device->SetupInterrupt(config_handler, driverCookie); 125 } 126 127 128 status_t 129 virtio_free_interrupts(virtio_device _device) 130 { 131 CALLED(); 132 VirtioDevice *device = (VirtioDevice *)_device; 133 return device->FreeInterrupts(); 134 } 135 136 137 status_t 138 virtio_queue_setup_interrupt(virtio_queue _queue, virtio_callback_func handler, 139 void *cookie) 140 { 141 CALLED(); 142 VirtioQueue *queue = (VirtioQueue *)_queue; 143 return queue->SetupInterrupt(handler, cookie); 144 } 145 146 147 status_t 148 virtio_queue_request_v(virtio_queue _queue, const physical_entry* vector, 149 size_t readVectorCount, size_t writtenVectorCount, void *cookie) 150 { 151 CALLED(); 152 VirtioQueue *queue = (VirtioQueue *)_queue; 153 return queue->QueueRequest(vector, readVectorCount, writtenVectorCount, 154 cookie); 155 } 156 157 158 status_t 159 virtio_queue_request(virtio_queue _queue, const physical_entry *readEntry, 160 const physical_entry *writtenEntry, void *cookie) 161 { 162 physical_entry entries[2]; 163 if (readEntry != NULL) { 164 entries[0] = *readEntry; 165 if (writtenEntry != NULL) 166 entries[1] = *writtenEntry; 167 } else if (writtenEntry != NULL) 168 entries[0] = *writtenEntry; 169 170 return virtio_queue_request_v(_queue, entries, readEntry != NULL ? 1 : 0, 171 writtenEntry != NULL? 1 : 0, cookie); 172 } 173 174 175 bool 176 virtio_queue_is_full(virtio_queue _queue) 177 { 178 VirtioQueue *queue = (VirtioQueue *)_queue; 179 return queue->IsFull(); 180 } 181 182 183 bool 184 virtio_queue_is_empty(virtio_queue _queue) 185 { 186 VirtioQueue *queue = (VirtioQueue *)_queue; 187 return queue->IsEmpty(); 188 } 189 190 191 uint16 192 virtio_queue_size(virtio_queue _queue) 193 { 194 VirtioQueue *queue = (VirtioQueue *)_queue; 195 return queue->Size(); 196 } 197 198 199 bool 200 virtio_queue_dequeue(virtio_queue _queue, void** _cookie, uint32* _usedLength) 201 { 202 VirtioQueue *queue = (VirtioQueue *)_queue; 203 return queue->Dequeue(_cookie, _usedLength); 204 } 205 206 207 // #pragma mark - 208 209 210 status_t 211 virtio_added_device(device_node *parent) 212 { 213 CALLED(); 214 215 uint16 deviceType; 216 if (gDeviceManager->get_attr_uint16(parent, 217 VIRTIO_DEVICE_TYPE_ITEM, &deviceType, true) != B_OK) { 218 ERROR("device type missing\n"); 219 return B_ERROR; 220 } 221 222 device_attr attributes[] = { 223 // info about device 224 { B_DEVICE_BUS, B_STRING_TYPE, { .string = "virtio" }}, 225 { VIRTIO_DEVICE_TYPE_ITEM, B_UINT16_TYPE, 226 { .ui16 = deviceType }}, 227 { NULL } 228 }; 229 230 return gDeviceManager->register_node(parent, VIRTIO_DEVICE_MODULE_NAME, 231 attributes, NULL, NULL); 232 } 233 234 235 status_t 236 virtio_queue_interrupt_handler(virtio_sim sim, uint16 queue) 237 { 238 VirtioDevice* device = (VirtioDevice*)sim; 239 return device->QueueInterrupt(queue); 240 } 241 242 243 status_t 244 virtio_config_interrupt_handler(virtio_sim sim) 245 { 246 VirtioDevice* device = (VirtioDevice*)sim; 247 return device->ConfigInterrupt(); 248 } 249 250 251 static status_t 252 std_ops(int32 op, ...) 253 { 254 switch (op) { 255 case B_MODULE_INIT: 256 case B_MODULE_UNINIT: 257 return B_OK; 258 259 default: 260 break; 261 } 262 263 return B_ERROR; 264 } 265 266 267 // #pragma mark - 268 269 270 virtio_device_interface virtio_device_module = { 271 { 272 { 273 VIRTIO_DEVICE_MODULE_NAME, 274 0, 275 std_ops 276 }, 277 278 NULL, // supported devices 279 NULL, // register node 280 virtio_device_init, 281 virtio_device_uninit, 282 NULL, // register child devices 283 NULL, // rescan 284 virtio_device_removed, 285 NULL, // suspend 286 NULL, // resume 287 }, 288 289 virtio_negotiate_features, 290 virtio_clear_feature, 291 virtio_read_device_config, 292 virtio_write_device_config, 293 virtio_alloc_queues, 294 virtio_free_queues, 295 virtio_setup_interrupt, 296 virtio_free_interrupts, 297 virtio_queue_setup_interrupt, 298 virtio_queue_request, 299 virtio_queue_request_v, 300 virtio_queue_is_full, 301 virtio_queue_is_empty, 302 virtio_queue_size, 303 virtio_queue_dequeue 304 }; 305 306 virtio_for_controller_interface virtio_for_controller_module = { 307 { 308 { 309 VIRTIO_FOR_CONTROLLER_MODULE_NAME, 310 0, 311 &std_ops 312 }, 313 314 NULL, // supported devices 315 virtio_added_device, 316 NULL, 317 NULL, 318 NULL 319 }, 320 321 virtio_queue_interrupt_handler, 322 virtio_config_interrupt_handler 323 }; 324 325 326 module_dependency module_dependencies[] = { 327 { B_DEVICE_MANAGER_MODULE_NAME, (module_info **)&gDeviceManager }, 328 {} 329 }; 330 331 332 extern struct driver_module_info sVirtioBalloonDriver; 333 extern struct driver_module_info sVirtioBalloonDeviceInterface; 334 335 336 module_info *modules[] = { 337 (module_info *)&virtio_for_controller_module, 338 (module_info *)&virtio_device_module, 339 (module_info *)&sVirtioBalloonDriver, 340 (module_info *)&sVirtioBalloonDeviceInterface, 341 NULL 342 }; 343 344