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