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