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