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