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 <new> 8 #include <stdio.h> 9 #include <string.h> 10 11 #include <bus/PCI.h> 12 #include <SupportDefs.h> 13 14 #include <kernel.h> 15 #include <virtio.h> 16 17 #include "virtio_pci.h" 18 19 20 //#define TRACE_VIRTIO 21 #ifdef TRACE_VIRTIO 22 # define TRACE(x...) dprintf("\33[33mvirtio_pci:\33[0m " x) 23 #else 24 # define TRACE(x...) ; 25 #endif 26 #define TRACE_ALWAYS(x...) dprintf("\33[33mvirtio_pci:\33[0m " x) 27 #define ERROR(x...) dprintf("\33[33mvirtio_pci:\33[0m " x) 28 #define CALLED(x...) TRACE("CALLED %s\n", __PRETTY_FUNCTION__) 29 30 31 #define VIRTIO_PCI_DEVICE_MODULE_NAME "busses/virtio/virtio_pci/driver_v1" 32 #define VIRTIO_PCI_SIM_MODULE_NAME "busses/virtio/virtio_pci/device/v1" 33 34 #define VIRTIO_PCI_CONTROLLER_TYPE_NAME "virtio pci controller" 35 36 typedef enum { 37 VIRTIO_IRQ_LEGACY, 38 VIRTIO_IRQ_MSI_X_SHARED, 39 VIRTIO_IRQ_MSI_X, 40 } virtio_irq_type; 41 42 typedef struct { 43 virtio_sim sim; 44 uint16 queue; 45 } virtio_pci_queue_cookie; 46 47 typedef struct { 48 pci_device_module_info* pci; 49 pci_device* device; 50 bool virtio1; 51 addr_t base_addr; 52 area_id registersArea[4]; 53 addr_t commonCfgAddr; 54 addr_t isrAddr; 55 addr_t notifyAddr; 56 uint32 notifyOffsetMultiplier; 57 uint8 irq; 58 virtio_irq_type irq_type; 59 virtio_sim sim; 60 uint16 queue_count; 61 addr_t* notifyOffsets; 62 63 device_node* node; 64 pci_info info; 65 66 virtio_pci_queue_cookie *cookies; 67 } virtio_pci_sim_info; 68 69 70 device_manager_info* gDeviceManager; 71 virtio_for_controller_interface* gVirtio; 72 73 74 static status_t 75 virtio_pci_find_capability(virtio_pci_sim_info* bus, uint8 cfgType, 76 void* buffer, size_t size) 77 { 78 uint8 capabilityOffset; 79 if (bus->pci->find_pci_capability(bus->device, PCI_cap_id_vendspec, &capabilityOffset) != B_OK) 80 return B_ENTRY_NOT_FOUND; 81 82 if (size < sizeof(virtio_pci_cap)) 83 return B_RESULT_NOT_REPRESENTABLE; 84 union regs { 85 uint32 reg[8]; 86 struct virtio_pci_cap capability; 87 } * v = (union regs*)buffer; 88 89 while (capabilityOffset != 0) { 90 for (int i = 0; i < 4; i++) { 91 v->reg[i] = bus->pci->read_pci_config(bus->device, capabilityOffset + i * 4, 4); 92 } 93 if (v->capability.cfg_type == cfgType) 94 break; 95 capabilityOffset = v->capability.cap_next; 96 } 97 if (capabilityOffset == 0) 98 return B_ENTRY_NOT_FOUND; 99 100 if (v->capability.length > sizeof(virtio_pci_cap)) { 101 size_t length = min_c(ROUNDUP(v->capability.length, sizeof(uint32)), size); 102 for (size_t i = 4; i < length / sizeof(uint32); i++) 103 v->reg[i] = bus->pci->read_pci_config(bus->device, capabilityOffset + i * 4, 4); 104 } 105 return B_OK; 106 } 107 108 109 static int32 110 virtio_pci_interrupt(void *data) 111 { 112 virtio_pci_sim_info* bus = (virtio_pci_sim_info*)data; 113 uint8 isr; 114 if (bus->virtio1) { 115 uint8* isrAddr = (uint8*)bus->isrAddr; 116 isr = *isrAddr; 117 } else { 118 isr = bus->pci->read_io_8(bus->device, 119 bus->base_addr + VIRTIO_PCI_ISR); 120 } 121 if (isr == 0) 122 return B_UNHANDLED_INTERRUPT; 123 124 if (isr & VIRTIO_PCI_ISR_CONFIG) 125 gVirtio->config_interrupt_handler(bus->sim); 126 127 if (isr & VIRTIO_PCI_ISR_INTR) 128 gVirtio->queue_interrupt_handler(bus->sim, INT16_MAX); 129 130 return B_HANDLED_INTERRUPT; 131 } 132 133 134 static int32 135 virtio_pci_config_interrupt(void *data) 136 { 137 virtio_pci_sim_info* bus = (virtio_pci_sim_info*)data; 138 gVirtio->config_interrupt_handler(bus->sim); 139 140 return B_HANDLED_INTERRUPT; 141 } 142 143 144 static int32 145 virtio_pci_queue_interrupt(void *data) 146 { 147 virtio_pci_queue_cookie* cookie = (virtio_pci_queue_cookie*)data; 148 gVirtio->queue_interrupt_handler(cookie->sim, cookie->queue); 149 150 return B_HANDLED_INTERRUPT; 151 } 152 153 154 static int32 155 virtio_pci_queues_interrupt(void *data) 156 { 157 virtio_pci_sim_info* bus = (virtio_pci_sim_info*)data; 158 gVirtio->queue_interrupt_handler(bus->sim, INT16_MAX); 159 160 return B_HANDLED_INTERRUPT; 161 } 162 163 164 static status_t 165 virtio_pci_setup_msix_interrupts(virtio_pci_sim_info* bus) 166 { 167 CALLED(); 168 uint8 irq = 0; // first irq slot 169 if (bus->virtio1) { 170 volatile uint16 *msixVector = (uint16*)(bus->commonCfgAddr 171 + offsetof(struct virtio_pci_common_cfg, config_msix_vector)); 172 *msixVector = irq; 173 } else { 174 bus->pci->write_io_16(bus->device, bus->base_addr 175 + VIRTIO_MSI_CONFIG_VECTOR, irq); 176 if (bus->pci->read_io_16(bus->device, bus->base_addr 177 + VIRTIO_MSI_CONFIG_VECTOR) == VIRTIO_MSI_NO_VECTOR) { 178 ERROR("msix config vector incorrect\n"); 179 return B_BAD_VALUE; 180 } 181 } 182 if (bus->irq_type == VIRTIO_IRQ_MSI_X || bus->irq_type == VIRTIO_IRQ_MSI_X_SHARED) 183 irq++; 184 185 for (uint16 queue = 0; queue < bus->queue_count; queue++) { 186 if (bus->virtio1) { 187 volatile uint16* queueSelect = (uint16*)(bus->commonCfgAddr 188 + offsetof(struct virtio_pci_common_cfg, queue_select)); 189 *queueSelect = queue; 190 volatile uint16* msixVector = (uint16*)(bus->commonCfgAddr 191 + offsetof(struct virtio_pci_common_cfg, queue_msix_vector)); 192 *msixVector = irq; 193 } else { 194 bus->pci->write_io_16(bus->device, bus->base_addr 195 + VIRTIO_PCI_QUEUE_SEL, queue); 196 bus->pci->write_io_16(bus->device, bus->base_addr 197 + VIRTIO_MSI_QUEUE_VECTOR, irq); 198 199 if (bus->pci->read_io_16(bus->device, bus->base_addr 200 + VIRTIO_MSI_QUEUE_VECTOR) == VIRTIO_MSI_NO_VECTOR) { 201 ERROR("msix queue vector incorrect\n"); 202 return B_BAD_VALUE; 203 } 204 } 205 if (bus->irq_type == VIRTIO_IRQ_MSI_X) 206 irq++; 207 } 208 209 return B_OK; 210 } 211 212 213 static void 214 set_sim(void* cookie, virtio_sim sim) 215 { 216 CALLED(); 217 virtio_pci_sim_info* bus = (virtio_pci_sim_info*)cookie; 218 bus->sim = sim; 219 } 220 221 222 static status_t 223 read_host_features(void* cookie, uint64 *features) 224 { 225 CALLED(); 226 virtio_pci_sim_info* bus = (virtio_pci_sim_info*)cookie; 227 228 TRACE("read_host_features() %p node %p pci %p device %p\n", bus, 229 bus->node, bus->pci, bus->device); 230 231 if (bus->virtio1) { 232 volatile uint32 *select = (uint32*)(bus->commonCfgAddr 233 + offsetof(struct virtio_pci_common_cfg, device_feature_select)); 234 volatile uint32 *feature = (uint32*)(bus->commonCfgAddr 235 + offsetof(struct virtio_pci_common_cfg, device_feature)); 236 *select = 0; 237 *features = *feature; 238 *select = 1; 239 *features |= ((uint64)*feature << 32) ; 240 TRACE("read_host_features() %" B_PRIx64 "\n", *features); 241 } else { 242 *features = bus->pci->read_io_32(bus->device, 243 bus->base_addr + VIRTIO_PCI_HOST_FEATURES); 244 } 245 return B_OK; 246 } 247 248 249 static status_t 250 write_guest_features(void* cookie, uint64 features) 251 { 252 CALLED(); 253 virtio_pci_sim_info* bus = (virtio_pci_sim_info*)cookie; 254 if (bus->virtio1) { 255 volatile uint32 *select = (uint32*)(bus->commonCfgAddr 256 + offsetof(struct virtio_pci_common_cfg, device_feature_select)); 257 volatile uint32 *feature = (uint32*)(bus->commonCfgAddr 258 + offsetof(struct virtio_pci_common_cfg, device_feature)); 259 *select = 0; 260 *feature = features & 0xffffffff; 261 *select = 1; 262 *feature = (features >> 32) ; 263 } else { 264 bus->pci->write_io_32(bus->device, bus->base_addr 265 + VIRTIO_PCI_GUEST_FEATURES, features); 266 } 267 return B_OK; 268 } 269 270 271 static uint8 272 get_status(void* cookie) 273 { 274 CALLED(); 275 virtio_pci_sim_info* bus = (virtio_pci_sim_info*)cookie; 276 if (bus->virtio1) { 277 uint8 *addr = (uint8*)(bus->commonCfgAddr 278 + offsetof(struct virtio_pci_common_cfg, device_status)); 279 return *addr; 280 } else { 281 return bus->pci->read_io_8(bus->device, bus->base_addr + VIRTIO_PCI_STATUS); 282 } 283 } 284 285 286 static void 287 set_status(void* cookie, uint8 status) 288 { 289 CALLED(); 290 virtio_pci_sim_info* bus = (virtio_pci_sim_info*)cookie; 291 if (bus->virtio1) { 292 uint8 *addr = (uint8*)(bus->commonCfgAddr 293 + offsetof(struct virtio_pci_common_cfg, device_status)); 294 uint8 old = 0; 295 if (status != 0) 296 old = *addr; 297 *addr = status | old; 298 } else { 299 uint8 old = 0; 300 if (status != 0) 301 old = bus->pci->read_io_8(bus->device, bus->base_addr + VIRTIO_PCI_STATUS); 302 bus->pci->write_io_8(bus->device, bus->base_addr + VIRTIO_PCI_STATUS, status | old); 303 } 304 } 305 306 307 static status_t 308 read_device_config(void* cookie, uint8 _offset, void* _buffer, 309 size_t bufferSize) 310 { 311 CALLED(); 312 virtio_pci_sim_info* bus = (virtio_pci_sim_info*)cookie; 313 314 addr_t offset = bus->base_addr + _offset; 315 if (!bus->virtio1) 316 offset += VIRTIO_PCI_CONFIG(bus); 317 uint8* buffer = (uint8*)_buffer; 318 while (bufferSize > 0) { 319 uint8 size = 4; 320 if (bufferSize == 1) { 321 size = 1; 322 if (bus->virtio1) { 323 *buffer = *(uint8*)offset; 324 } else { 325 *buffer = bus->pci->read_io_8(bus->device, offset); 326 } 327 } else if (bufferSize <= 3) { 328 size = 2; 329 if (bus->virtio1) { 330 *(uint16*)buffer = *(uint16*)offset; 331 } else { 332 *(uint16*)buffer = bus->pci->read_io_16(bus->device, offset); 333 } 334 } else { 335 if (bus->virtio1) { 336 *(uint32*)buffer = *(uint32*)offset; 337 } else { 338 *(uint32*)buffer = bus->pci->read_io_32(bus->device, 339 offset); 340 } 341 } 342 buffer += size; 343 bufferSize -= size; 344 offset += size; 345 } 346 347 return B_OK; 348 } 349 350 351 static status_t 352 write_device_config(void* cookie, uint8 _offset, const void* _buffer, 353 size_t bufferSize) 354 { 355 CALLED(); 356 virtio_pci_sim_info* bus = (virtio_pci_sim_info*)cookie; 357 358 addr_t offset = bus->base_addr + _offset; 359 if (!bus->virtio1) 360 offset += VIRTIO_PCI_CONFIG(bus); 361 const uint8* buffer = (const uint8*)_buffer; 362 while (bufferSize > 0) { 363 uint8 size = 4; 364 if (bufferSize == 1) { 365 size = 1; 366 if (bus->virtio1) { 367 *(uint8*)offset = *buffer; 368 } else { 369 bus->pci->write_io_8(bus->device, offset, *buffer); 370 } 371 } else if (bufferSize <= 3) { 372 size = 2; 373 if (bus->virtio1) { 374 *(uint16*)offset = *(uint16*)buffer; 375 } else { 376 bus->pci->write_io_16(bus->device, offset, *(const uint16*)buffer); 377 } 378 } else { 379 if (bus->virtio1) { 380 *(uint32*)offset = *(uint32*)buffer; 381 } else { 382 bus->pci->write_io_32(bus->device, offset, *(const uint32*)buffer); 383 } 384 } 385 buffer += size; 386 bufferSize -= size; 387 offset += size; 388 } 389 return B_OK; 390 } 391 392 393 static uint16 394 get_queue_ring_size(void* cookie, uint16 queue) 395 { 396 CALLED(); 397 virtio_pci_sim_info* bus = (virtio_pci_sim_info*)cookie; 398 if (bus->virtio1) { 399 volatile uint16* queueSelect = (uint16*)(bus->commonCfgAddr 400 + offsetof(struct virtio_pci_common_cfg, queue_select)); 401 *queueSelect = queue; 402 volatile uint16* ringSize = (volatile uint16*)(bus->commonCfgAddr 403 + offsetof(struct virtio_pci_common_cfg, queue_size)); 404 return *ringSize; 405 } else { 406 bus->pci->write_io_16(bus->device, bus->base_addr + VIRTIO_PCI_QUEUE_SEL, 407 queue); 408 return bus->pci->read_io_16(bus->device, bus->base_addr 409 + VIRTIO_PCI_QUEUE_NUM); 410 } 411 } 412 413 414 static status_t 415 setup_queue(void* cookie, uint16 queue, phys_addr_t phy, phys_addr_t phyAvail, 416 phys_addr_t phyUsed) 417 { 418 CALLED(); 419 virtio_pci_sim_info* bus = (virtio_pci_sim_info*)cookie; 420 if (queue >= bus->queue_count) 421 return B_BAD_VALUE; 422 423 if (bus->virtio1) { 424 volatile uint16* queueSelect = (uint16*)(bus->commonCfgAddr 425 + offsetof(struct virtio_pci_common_cfg, queue_select)); 426 *queueSelect = queue; 427 428 volatile uint64* queueDesc = (volatile uint64*)(bus->commonCfgAddr 429 + offsetof(struct virtio_pci_common_cfg, queue_desc)); 430 *queueDesc = phy; 431 volatile uint64* queueAvail = (volatile uint64*)(bus->commonCfgAddr 432 + offsetof(struct virtio_pci_common_cfg, queue_avail)); 433 *queueAvail = phyAvail; 434 volatile uint64* queueUsed = (volatile uint64*)(bus->commonCfgAddr 435 + offsetof(struct virtio_pci_common_cfg, queue_used)); 436 *queueUsed = phyUsed; 437 volatile uint16* queueEnable = (volatile uint16*)(bus->commonCfgAddr 438 + offsetof(struct virtio_pci_common_cfg, queue_enable)); 439 *queueEnable = 1; 440 441 volatile uint16* queueNotifyOffset = (volatile uint16*)(bus->commonCfgAddr 442 + offsetof(struct virtio_pci_common_cfg, queue_notify_off)); 443 bus->notifyOffsets[queue] = *queueNotifyOffset * bus->notifyOffsetMultiplier; 444 } else { 445 bus->pci->write_io_16(bus->device, bus->base_addr + VIRTIO_PCI_QUEUE_SEL, queue); 446 bus->pci->write_io_32(bus->device, bus->base_addr + VIRTIO_PCI_QUEUE_PFN, 447 (uint32)phy >> VIRTIO_PCI_QUEUE_ADDR_SHIFT); 448 } 449 return B_OK; 450 } 451 452 453 static status_t 454 setup_interrupt(void* cookie, uint16 queueCount) 455 { 456 CALLED(); 457 virtio_pci_sim_info* bus = (virtio_pci_sim_info*)cookie; 458 pci_info *pciInfo = &bus->info; 459 460 bus->queue_count = queueCount; 461 462 // try MSI-X 463 uint8 msixCount = bus->pci->get_msix_count(bus->device); 464 if (msixCount >= 2) { 465 if (msixCount >= (queueCount + 1)) { 466 uint8 vector; 467 bus->cookies = new(std::nothrow) 468 virtio_pci_queue_cookie[queueCount]; 469 if (bus->cookies != NULL 470 && bus->pci->configure_msix(bus->device, queueCount + 1, 471 &vector) == B_OK 472 && bus->pci->enable_msix(bus->device) == B_OK) { 473 TRACE_ALWAYS("using MSI-X count %u starting at %d\n", 474 queueCount + 1, vector); 475 bus->irq = vector; 476 bus->irq_type = VIRTIO_IRQ_MSI_X; 477 } else { 478 ERROR("couldn't use MSI-X\n"); 479 } 480 } else { 481 uint8 vector; 482 if (bus->pci->configure_msix(bus->device, 2, &vector) == B_OK 483 && bus->pci->enable_msix(bus->device) == B_OK) { 484 TRACE_ALWAYS("using MSI-X vector shared %u\n", vector); 485 bus->irq = vector; 486 bus->irq_type = VIRTIO_IRQ_MSI_X_SHARED; 487 } else { 488 ERROR("couldn't use MSI-X SHARED\n"); 489 } 490 } 491 } 492 493 if (bus->irq_type == VIRTIO_IRQ_LEGACY) { 494 bus->irq = pciInfo->u.h0.interrupt_line; 495 TRACE_ALWAYS("using legacy interrupt %u\n", bus->irq); 496 } 497 if (bus->irq == 0 || bus->irq == 0xff) { 498 ERROR("PCI IRQ not assigned\n"); 499 delete bus; 500 return B_ERROR; 501 } 502 503 if (bus->irq_type != VIRTIO_IRQ_LEGACY) { 504 status_t status = install_io_interrupt_handler(bus->irq, 505 virtio_pci_config_interrupt, bus, 0); 506 if (status != B_OK) { 507 ERROR("can't install interrupt handler\n"); 508 return status; 509 } 510 int32 irq = bus->irq + 1; 511 if (bus->irq_type == VIRTIO_IRQ_MSI_X) { 512 for (int32 queue = 0; queue < queueCount; queue++, irq++) { 513 bus->cookies[queue].sim = bus->sim; 514 bus->cookies[queue].queue = queue; 515 status_t status = install_io_interrupt_handler(irq, 516 virtio_pci_queue_interrupt, &bus->cookies[queue], 0); 517 if (status != B_OK) { 518 ERROR("can't install interrupt handler\n"); 519 return status; 520 } 521 } 522 } else { 523 status_t status = install_io_interrupt_handler(irq, 524 virtio_pci_queues_interrupt, bus, 0); 525 if (status != B_OK) { 526 ERROR("can't install interrupt handler\n"); 527 return status; 528 } 529 } 530 TRACE("setup_interrupt() installed MSI-X interrupt handlers\n"); 531 virtio_pci_setup_msix_interrupts(bus); 532 } else { 533 // setup interrupt handler 534 status_t status = install_io_interrupt_handler(bus->irq, 535 virtio_pci_interrupt, bus, 0); 536 if (status != B_OK) { 537 ERROR("can't install interrupt handler\n"); 538 return status; 539 } 540 TRACE("setup_interrupt() installed legacy interrupt handler\n"); 541 } 542 543 return B_OK; 544 } 545 546 547 static status_t 548 free_interrupt(void* cookie) 549 { 550 CALLED(); 551 virtio_pci_sim_info* bus = (virtio_pci_sim_info*)cookie; 552 553 if (bus->irq_type != VIRTIO_IRQ_LEGACY) { 554 remove_io_interrupt_handler(bus->irq, virtio_pci_config_interrupt, bus); 555 int32 irq = bus->irq + 1; 556 if (bus->irq_type == VIRTIO_IRQ_MSI_X) { 557 for (int32 queue = 0; queue < bus->queue_count; queue++, irq++) 558 remove_io_interrupt_handler(irq, virtio_pci_queue_interrupt, &bus->cookies[queue]); 559 delete[] bus->cookies; 560 bus->cookies = NULL; 561 } else { 562 remove_io_interrupt_handler(irq, virtio_pci_queues_interrupt, bus); 563 } 564 bus->pci->disable_msi(bus->device); 565 bus->pci->unconfigure_msi(bus->device); 566 } else 567 remove_io_interrupt_handler(bus->irq, virtio_pci_interrupt, bus); 568 569 return B_OK; 570 } 571 572 573 static void 574 notify_queue(void* cookie, uint16 queue) 575 { 576 CALLED(); 577 virtio_pci_sim_info* bus = (virtio_pci_sim_info*)cookie; 578 if (queue >= bus->queue_count) 579 return; 580 if (bus->virtio1) { 581 volatile uint16* notifyAddr = (volatile uint16*)(bus->notifyAddr + bus->notifyOffsets[queue]); 582 *notifyAddr = queue; 583 } else { 584 bus->pci->write_io_16(bus->device, bus->base_addr 585 + VIRTIO_PCI_QUEUE_NOTIFY, queue); 586 } 587 } 588 589 590 // #pragma mark - 591 592 593 static status_t 594 init_bus(device_node* node, void** bus_cookie) 595 { 596 CALLED(); 597 status_t status = B_OK; 598 599 virtio_pci_sim_info* bus = new(std::nothrow) virtio_pci_sim_info; 600 if (bus == NULL) { 601 return B_NO_MEMORY; 602 } 603 604 pci_device_module_info* pci; 605 pci_device* device; 606 { 607 device_node* parent = gDeviceManager->get_parent_node(node); 608 device_node* pciParent = gDeviceManager->get_parent_node(parent); 609 gDeviceManager->get_driver(pciParent, (driver_module_info**)&pci, 610 (void**)&device); 611 gDeviceManager->put_node(pciParent); 612 gDeviceManager->put_node(parent); 613 } 614 615 bus->node = node; 616 bus->pci = pci; 617 bus->device = device; 618 bus->cookies = NULL; 619 bus->irq_type = VIRTIO_IRQ_LEGACY; 620 621 pci_info *pciInfo = &bus->info; 622 pci->get_pci_info(device, pciInfo); 623 624 bus->virtio1 = pciInfo->revision == 1; 625 626 if (bus->virtio1) { 627 struct virtio_pci_cap common, isr, deviceCap; 628 struct virtio_pci_notify_cap notify; 629 bool deviceCfgFound = false; 630 if (virtio_pci_find_capability(bus, VIRTIO_PCI_CAP_COMMON_CFG, &common, 631 sizeof(common)) != B_OK) { 632 return B_DEVICE_NOT_FOUND; 633 } 634 if (virtio_pci_find_capability(bus, VIRTIO_PCI_CAP_ISR_CFG, &isr, 635 sizeof(isr)) != B_OK) { 636 return B_DEVICE_NOT_FOUND; 637 } 638 if (virtio_pci_find_capability(bus, VIRTIO_PCI_CAP_DEVICE_CFG, &deviceCap, 639 sizeof(deviceCap)) != B_OK) { 640 memset(&deviceCap, 0, sizeof(deviceCap)); 641 } else { 642 deviceCfgFound = true; 643 } 644 if (virtio_pci_find_capability(bus, VIRTIO_PCI_CAP_NOTIFY_CFG, ¬ify, 645 sizeof(notify)) != B_OK) { 646 return B_DEVICE_NOT_FOUND; 647 } 648 649 size_t bars[6] = {0}; 650 if (common.length > 0) 651 bars[common.bar] = common.offset + common.length; 652 if (isr.length > 0) 653 bars[isr.bar] = max_c(bars[isr.bar], isr.offset + isr.length); 654 if (notify.cap.length > 0) { 655 bars[notify.cap.bar] = max_c(bars[notify.cap.bar], notify.cap.offset 656 + notify.cap.length); 657 } 658 if (deviceCfgFound && deviceCap.length > 0) 659 bars[deviceCap.bar] = max_c(bars[deviceCap.bar], deviceCap.offset + deviceCap.length); 660 661 int index = 0; 662 addr_t registers[6] = {0}; 663 for (int i = 0; i < 6; i++) { 664 if (bars[i] == 0) 665 continue; 666 phys_addr_t barAddr = pciInfo->u.h0.base_registers[i]; 667 size_t barSize = pciInfo->u.h0.base_register_sizes[i]; 668 if ((pciInfo->u.h0.base_register_flags[i] & PCI_address_type) == PCI_address_type_64) { 669 barAddr |= (uint64)pciInfo->u.h0.base_registers[i + 1] << 32; 670 barSize |= (uint64)pciInfo->u.h0.base_register_sizes[i + 1] << 32; 671 } 672 673 bus->registersArea[i] = map_physical_memory("Virtio PCI memory mapped registers", 674 barAddr, barSize, B_ANY_KERNEL_ADDRESS, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, 675 (void **)®isters[i]); 676 index++; 677 } 678 679 bus->commonCfgAddr = registers[common.bar] + common.offset; 680 bus->isrAddr = registers[isr.bar] + isr.offset; 681 bus->notifyAddr = registers[notify.cap.bar] + notify.cap.offset; 682 bus->notifyOffsetMultiplier = notify.notify_off_multiplier; 683 if (deviceCfgFound) 684 bus->base_addr = registers[deviceCap.bar] + deviceCap.offset; 685 686 // enable bus master and memory 687 uint16 pcicmd = pci->read_pci_config(device, PCI_command, 2); 688 pcicmd &= ~(PCI_command_int_disable | PCI_command_io); 689 pci->write_pci_config(device, PCI_command, 2, 690 pcicmd | PCI_command_master | PCI_command_memory); 691 692 volatile uint16 *queueCount = (uint16*)(bus->commonCfgAddr 693 + offsetof(struct virtio_pci_common_cfg, num_queues)); 694 bus->notifyOffsets = new addr_t[*queueCount]; 695 696 } else { 697 // legacy interrupt 698 bus->base_addr = pciInfo->u.h0.base_registers[0]; 699 700 // enable bus master and io 701 uint16 pcicmd = pci->read_pci_config(device, PCI_command, 2); 702 pcicmd &= ~(PCI_command_memory | PCI_command_int_disable); 703 pcicmd |= PCI_command_master | PCI_command_io; 704 pci->write_pci_config(device, PCI_command, 2, pcicmd); 705 } 706 707 708 set_status(bus, VIRTIO_CONFIG_STATUS_RESET); 709 set_status(bus, VIRTIO_CONFIG_STATUS_ACK); 710 711 TRACE("init_bus() %p node %p pci %p device %p\n", bus, node, 712 bus->pci, bus->device); 713 714 *bus_cookie = bus; 715 return status; 716 } 717 718 719 static void 720 uninit_bus(void* bus_cookie) 721 { 722 virtio_pci_sim_info* bus = (virtio_pci_sim_info*)bus_cookie; 723 if (bus->irq_type != VIRTIO_IRQ_LEGACY) { 724 int32 irq = bus->irq + 1; 725 if (bus->irq_type == VIRTIO_IRQ_MSI_X) { 726 for (int32 queue = 0; queue < bus->queue_count; queue++, irq++) 727 remove_io_interrupt_handler(irq, virtio_pci_queue_interrupt, &bus->cookies[queue]); 728 delete[] bus->cookies; 729 } else { 730 remove_io_interrupt_handler(irq, virtio_pci_queues_interrupt, bus); 731 } 732 remove_io_interrupt_handler(bus->irq, virtio_pci_config_interrupt, 733 bus); 734 735 bus->pci->disable_msi(bus->device); 736 bus->pci->unconfigure_msi(bus->device); 737 } else 738 remove_io_interrupt_handler(bus->irq, virtio_pci_interrupt, bus); 739 740 if (bus->virtio1) { 741 for (int i = 0; i < 6; i++) { 742 if (bus->registersArea[i] >= 0) 743 delete_area(bus->registersArea[i]); 744 else 745 break; 746 } 747 delete[] bus->notifyOffsets; 748 } 749 750 delete bus; 751 } 752 753 754 static void 755 bus_removed(void* bus_cookie) 756 { 757 return; 758 } 759 760 761 // #pragma mark - 762 763 764 static status_t 765 register_child_devices(void* cookie) 766 { 767 CALLED(); 768 device_node* node = (device_node*)cookie; 769 device_node* parent = gDeviceManager->get_parent_node(node); 770 pci_device_module_info* pci; 771 pci_device* device; 772 gDeviceManager->get_driver(parent, (driver_module_info**)&pci, 773 (void**)&device); 774 775 uint16 pciSubDeviceId = pci->read_pci_config(device, PCI_subsystem_id, 2); 776 uint8 pciRevision = pci->read_pci_config(device, PCI_revision, 1); 777 uint16 pciDeviceId = pci->read_pci_config(device, PCI_device_id, 2); 778 779 uint16 virtioDeviceId = pciSubDeviceId; 780 if (pciDeviceId >= VIRTIO_PCI_DEVICEID_MODERN_MIN) 781 virtioDeviceId = pciDeviceId - VIRTIO_PCI_DEVICEID_MODERN_MIN; 782 783 char prettyName[25]; 784 sprintf(prettyName, "Virtio Device %" B_PRIu16, virtioDeviceId); 785 786 device_attr attrs[] = { 787 // properties of this controller for virtio bus manager 788 { B_DEVICE_PRETTY_NAME, B_STRING_TYPE, 789 { .string = prettyName }}, 790 { B_DEVICE_FIXED_CHILD, B_STRING_TYPE, 791 { .string = VIRTIO_FOR_CONTROLLER_MODULE_NAME }}, 792 793 // private data to identify the device 794 { VIRTIO_DEVICE_TYPE_ITEM, B_UINT16_TYPE, 795 { .ui16 = virtioDeviceId }}, 796 { VIRTIO_VRING_ALIGNMENT_ITEM, B_UINT16_TYPE, 797 { .ui16 = VIRTIO_PCI_VRING_ALIGN }}, 798 { VIRTIO_VERSION_ITEM, B_UINT8_TYPE, 799 { .ui8 = pciRevision }}, 800 { NULL } 801 }; 802 803 return gDeviceManager->register_node(node, VIRTIO_PCI_SIM_MODULE_NAME, 804 attrs, NULL, &node); 805 } 806 807 808 static status_t 809 init_device(device_node* node, void** device_cookie) 810 { 811 CALLED(); 812 *device_cookie = node; 813 return B_OK; 814 } 815 816 817 static status_t 818 register_device(device_node* parent) 819 { 820 device_attr attrs[] = { 821 {B_DEVICE_PRETTY_NAME, B_STRING_TYPE, {.string = "Virtio PCI"}}, 822 {} 823 }; 824 825 return gDeviceManager->register_node(parent, VIRTIO_PCI_DEVICE_MODULE_NAME, 826 attrs, NULL, NULL); 827 } 828 829 830 static float 831 supports_device(device_node* parent) 832 { 833 CALLED(); 834 const char* bus; 835 uint16 vendorID, deviceID; 836 837 // make sure parent is a PCI Virtio device node 838 if (gDeviceManager->get_attr_string(parent, B_DEVICE_BUS, &bus, false) != B_OK 839 || gDeviceManager->get_attr_uint16(parent, B_DEVICE_VENDOR_ID, 840 &vendorID, false) < B_OK 841 || gDeviceManager->get_attr_uint16(parent, B_DEVICE_ID, &deviceID, 842 false) < B_OK) { 843 return -1; 844 } 845 846 if (strcmp(bus, "pci") != 0) 847 return 0.0f; 848 849 if (vendorID == VIRTIO_PCI_VENDORID) { 850 if (deviceID < VIRTIO_PCI_DEVICEID_MIN 851 || deviceID > VIRTIO_PCI_DEVICEID_MODERN_MAX) { 852 return 0.0f; 853 } 854 855 pci_device_module_info* pci; 856 pci_device* device; 857 gDeviceManager->get_driver(parent, (driver_module_info**)&pci, 858 (void**)&device); 859 uint8 pciRevision = pci->read_pci_config(device, PCI_revision, 860 1); 861 if (deviceID >= VIRTIO_PCI_DEVICEID_MIN 862 && deviceID <= VIRTIO_PCI_DEVICEID_LEGACY_MAX 863 && pciRevision != 0) { 864 return 0.0f; 865 } 866 if (deviceID >= VIRTIO_PCI_DEVICEID_MODERN_MIN 867 && deviceID <= VIRTIO_PCI_DEVICEID_MODERN_MAX 868 && pciRevision != 1) 869 return 0.0f; 870 871 TRACE("Virtio device found! vendor 0x%04x, device 0x%04x\n", vendorID, 872 deviceID); 873 return 0.8f; 874 } 875 876 return 0.0f; 877 } 878 879 880 // #pragma mark - 881 882 883 module_dependency module_dependencies[] = { 884 { VIRTIO_FOR_CONTROLLER_MODULE_NAME, (module_info**)&gVirtio }, 885 { B_DEVICE_MANAGER_MODULE_NAME, (module_info**)&gDeviceManager }, 886 {} 887 }; 888 889 890 static virtio_sim_interface gVirtioPCIDeviceModule = { 891 { 892 { 893 VIRTIO_PCI_SIM_MODULE_NAME, 894 0, 895 NULL 896 }, 897 898 NULL, // supports device 899 NULL, // register device 900 init_bus, 901 uninit_bus, 902 NULL, // register child devices 903 NULL, // rescan 904 bus_removed, 905 }, 906 907 set_sim, 908 read_host_features, 909 write_guest_features, 910 get_status, 911 set_status, 912 read_device_config, 913 write_device_config, 914 get_queue_ring_size, 915 setup_queue, 916 setup_interrupt, 917 free_interrupt, 918 notify_queue 919 }; 920 921 922 static driver_module_info sVirtioDevice = { 923 { 924 VIRTIO_PCI_DEVICE_MODULE_NAME, 925 0, 926 NULL 927 }, 928 929 supports_device, 930 register_device, 931 init_device, 932 NULL, // uninit 933 register_child_devices, 934 NULL, // rescan 935 NULL, // device removed 936 }; 937 938 module_info* modules[] = { 939 (module_info* )&sVirtioDevice, 940 (module_info* )&gVirtioPCIDeviceModule, 941 NULL 942 }; 943