1 /* 2 * Copyright 2013, 2018, Jérôme Duval, jerome.duval@gmail.com. 3 * Copyright 2017, Philippe Houdoin, philippe.houdoin@gmail.com. 4 * Distributed under the terms of the MIT License. 5 */ 6 7 8 #include <net/if_media.h> 9 #include <new> 10 11 #include <ethernet.h> 12 #include <lock.h> 13 #include <util/DoublyLinkedList.h> 14 #include <virtio.h> 15 16 #include "ether_driver.h" 17 #define ETHER_ADDR_LEN ETHER_ADDRESS_LENGTH 18 #include "virtio_net.h" 19 20 21 #define VIRTIO_NET_DRIVER_MODULE_NAME "drivers/network/virtio_net/driver_v1" 22 #define VIRTIO_NET_DEVICE_MODULE_NAME "drivers/network/virtio_net/device_v1" 23 #define VIRTIO_NET_DEVICE_ID_GENERATOR "virtio_net/device_id" 24 25 #define BUFFER_SIZE 2048 26 #define MAX_FRAME_SIZE 1536 27 28 29 struct virtio_net_rx_hdr { 30 struct virtio_net_hdr hdr; 31 uint8 pad[4]; 32 } _PACKED; 33 34 35 struct virtio_net_tx_hdr { 36 union { 37 struct virtio_net_hdr hdr; 38 struct virtio_net_hdr_mrg_rxbuf mhdr; 39 }; 40 } _PACKED; 41 42 43 struct BufInfo : DoublyLinkedListLinkImpl<BufInfo> { 44 char* buffer; 45 struct virtio_net_hdr* hdr; 46 physical_entry entry; 47 physical_entry hdrEntry; 48 uint32 rxUsedLength; 49 }; 50 51 52 typedef DoublyLinkedList<BufInfo> BufInfoList; 53 54 55 typedef struct { 56 device_node* node; 57 ::virtio_device virtio_device; 58 virtio_device_interface* virtio; 59 60 uint32 features; 61 62 uint32 pairsCount; 63 64 ::virtio_queue* rxQueues; 65 uint16* rxSizes; 66 67 BufInfo** rxBufInfos; 68 sem_id rxDone; 69 area_id rxArea; 70 BufInfoList rxFullList; 71 mutex rxLock; 72 73 ::virtio_queue* txQueues; 74 uint16* txSizes; 75 76 BufInfo** txBufInfos; 77 sem_id txDone; 78 area_id txArea; 79 BufInfoList txFreeList; 80 mutex txLock; 81 82 ::virtio_queue ctrlQueue; 83 84 bool nonblocking; 85 bool promiscuous; 86 uint32 maxframesize; 87 ether_address_t macaddr; 88 89 #define MAX_MULTI 128 90 uint32 multiCount; 91 ether_address_t multi[MAX_MULTI]; 92 93 } virtio_net_driver_info; 94 95 96 typedef struct { 97 virtio_net_driver_info* info; 98 } virtio_net_handle; 99 100 101 #include <stdio.h> 102 #include <string.h> 103 #include <stdlib.h> 104 105 #include <fs/devfs.h> 106 107 108 //#define TRACE_VIRTIO_NET 109 #ifdef TRACE_VIRTIO_NET 110 # define TRACE(x...) dprintf("virtio_net: " x) 111 #else 112 # define TRACE(x...) ; 113 #endif 114 #define ERROR(x...) dprintf("\33[33mvirtio_net:\33[0m " x) 115 #define CALLED() TRACE("CALLED %s\n", __PRETTY_FUNCTION__) 116 117 118 static device_manager_info* sDeviceManager; 119 120 121 static void virtio_net_rxDone(void* driverCookie, void* cookie); 122 static void virtio_net_txDone(void* driverCookie, void* cookie); 123 124 125 const char* 126 get_feature_name(uint32 feature) 127 { 128 switch (feature) { 129 case VIRTIO_NET_F_CSUM: 130 return "host checksum"; 131 case VIRTIO_NET_F_GUEST_CSUM: 132 return "guest checksum"; 133 case VIRTIO_NET_F_MTU: 134 return "mtu"; 135 case VIRTIO_NET_F_MAC: 136 return "macaddress"; 137 case VIRTIO_NET_F_GSO: 138 return "host allgso"; 139 case VIRTIO_NET_F_GUEST_TSO4: 140 return "guest tso4"; 141 case VIRTIO_NET_F_GUEST_TSO6: 142 return "guest tso6"; 143 case VIRTIO_NET_F_GUEST_ECN: 144 return "guest tso6+ecn"; 145 case VIRTIO_NET_F_GUEST_UFO: 146 return "guest ufo"; 147 case VIRTIO_NET_F_HOST_TSO4: 148 return "host tso4"; 149 case VIRTIO_NET_F_HOST_TSO6: 150 return "host tso6"; 151 case VIRTIO_NET_F_HOST_ECN: 152 return "host tso6+ecn"; 153 case VIRTIO_NET_F_HOST_UFO: 154 return "host UFO"; 155 case VIRTIO_NET_F_MRG_RXBUF: 156 return "host mergerxbuffers"; 157 case VIRTIO_NET_F_STATUS: 158 return "status"; 159 case VIRTIO_NET_F_CTRL_VQ: 160 return "control vq"; 161 case VIRTIO_NET_F_CTRL_RX: 162 return "rx mode"; 163 case VIRTIO_NET_F_CTRL_VLAN: 164 return "vlan filter"; 165 case VIRTIO_NET_F_CTRL_RX_EXTRA: 166 return "rx mode extra"; 167 case VIRTIO_NET_F_GUEST_ANNOUNCE: 168 return "guest announce"; 169 case VIRTIO_NET_F_MQ: 170 return "multiqueue"; 171 case VIRTIO_NET_F_CTRL_MAC_ADDR: 172 return "set macaddress"; 173 } 174 return NULL; 175 } 176 177 178 static status_t 179 virtio_net_drain_queues(virtio_net_driver_info* info) 180 { 181 BufInfo* buf = NULL; 182 while (info->virtio->queue_dequeue(info->txQueues[0], (void**)&buf, NULL)) 183 info->txFreeList.Add(buf); 184 185 while (info->virtio->queue_dequeue(info->rxQueues[0], NULL, NULL)) 186 ; 187 188 while (info->rxFullList.RemoveHead() != NULL) 189 ; 190 191 return B_OK; 192 } 193 194 195 static status_t 196 virtio_net_rx_enqueue_buf(virtio_net_driver_info* info, BufInfo* buf) 197 { 198 physical_entry entries[2]; 199 entries[0] = buf->hdrEntry; 200 entries[1] = buf->entry; 201 202 memset(buf->hdr, 0, sizeof(struct virtio_net_hdr)); 203 204 // queue the rx buffer 205 status_t status = info->virtio->queue_request_v(info->rxQueues[0], 206 entries, 0, 2, buf); 207 if (status != B_OK) { 208 ERROR("rx queueing on queue %d failed (%s)\n", 0, strerror(status)); 209 return status; 210 } 211 212 return B_OK; 213 } 214 215 216 static status_t 217 virtio_net_ctrl_exec_cmd(virtio_net_driver_info* info, int cmd, int value) 218 { 219 struct { 220 struct virtio_net_ctrl_hdr hdr; 221 uint8 pad1; 222 uint8 onoff; 223 uint8 pad2; 224 uint8 ack; 225 } s __attribute__((aligned(2))); 226 227 s.hdr.net_class = VIRTIO_NET_CTRL_RX; 228 s.hdr.cmd = cmd; 229 s.onoff = value == 0; 230 s.ack = VIRTIO_NET_ERR; 231 232 physical_entry entries[3]; 233 status_t status = get_memory_map(&s.hdr, sizeof(s.hdr), &entries[0], 1); 234 if (status != B_OK) 235 return status; 236 status = get_memory_map(&s.onoff, sizeof(s.onoff), &entries[1], 1); 237 if (status != B_OK) 238 return status; 239 status = get_memory_map(&s.ack, sizeof(s.ack), &entries[2], 1); 240 if (status != B_OK) 241 return status; 242 243 if (!info->virtio->queue_is_empty(info->ctrlQueue)) 244 return B_ERROR; 245 246 status = info->virtio->queue_request_v(info->ctrlQueue, entries, 2, 1, 247 NULL); 248 if (status != B_OK) 249 return status; 250 251 while (!info->virtio->queue_dequeue(info->ctrlQueue, NULL, NULL)) 252 spin(10); 253 254 return s.ack == VIRTIO_NET_OK ? B_OK : B_IO_ERROR; 255 } 256 257 258 static status_t 259 virtio_net_set_promisc(virtio_net_driver_info* info, int value) 260 { 261 return virtio_net_ctrl_exec_cmd(info, VIRTIO_NET_CTRL_RX_PROMISC, value); 262 } 263 264 265 static int 266 vtnet_set_allmulti(virtio_net_driver_info* info, int value) 267 { 268 return virtio_net_ctrl_exec_cmd(info, VIRTIO_NET_CTRL_RX_ALLMULTI, value); 269 } 270 271 272 #define ROUND_TO_PAGE_SIZE(x) (((x) + (B_PAGE_SIZE) - 1) & ~((B_PAGE_SIZE) - 1)) 273 274 275 // #pragma mark - device module API 276 277 278 static status_t 279 virtio_net_init_device(void* _info, void** _cookie) 280 { 281 CALLED(); 282 virtio_net_driver_info* info = (virtio_net_driver_info*)_info; 283 284 device_node* parent = sDeviceManager->get_parent_node(info->node); 285 sDeviceManager->get_driver(parent, (driver_module_info**)&info->virtio, 286 (void**)&info->virtio_device); 287 sDeviceManager->put_node(parent); 288 289 info->virtio->negotiate_features(info->virtio_device, 290 VIRTIO_NET_F_STATUS | VIRTIO_NET_F_MAC | VIRTIO_NET_F_MTU 291 | VIRTIO_NET_F_CTRL_VQ | VIRTIO_NET_F_CTRL_RX 292 /* | VIRTIO_NET_F_MQ */, 293 &info->features, &get_feature_name); 294 295 if ((info->features & VIRTIO_NET_F_MQ) != 0 296 && (info->features & VIRTIO_NET_F_CTRL_VQ) != 0 297 && info->virtio->read_device_config(info->virtio_device, 298 offsetof(struct virtio_net_config, max_virtqueue_pairs), 299 &info->pairsCount, sizeof(info->pairsCount)) == B_OK) { 300 system_info sysinfo; 301 if (get_system_info(&sysinfo) == B_OK 302 && info->pairsCount > sysinfo.cpu_count) { 303 info->pairsCount = sysinfo.cpu_count; 304 } 305 } else 306 info->pairsCount = 1; 307 308 // TODO read config 309 310 // Setup queues 311 uint32 queueCount = info->pairsCount * 2; 312 if ((info->features & VIRTIO_NET_F_CTRL_VQ) != 0) 313 queueCount++; 314 ::virtio_queue virtioQueues[queueCount]; 315 status_t status = info->virtio->alloc_queues(info->virtio_device, queueCount, 316 virtioQueues); 317 if (status != B_OK) { 318 ERROR("queue allocation failed (%s)\n", strerror(status)); 319 return status; 320 } 321 322 char* rxBuffer; 323 char* txBuffer; 324 325 info->rxQueues = new(std::nothrow) virtio_queue[info->pairsCount]; 326 info->txQueues = new(std::nothrow) virtio_queue[info->pairsCount]; 327 info->rxSizes = new(std::nothrow) uint16[info->pairsCount]; 328 info->txSizes = new(std::nothrow) uint16[info->pairsCount]; 329 if (info->rxQueues == NULL || info->txQueues == NULL 330 || info->rxSizes == NULL || info->txSizes == NULL) { 331 status = B_NO_MEMORY; 332 goto err1; 333 } 334 for (uint32 i = 0; i < info->pairsCount; i++) { 335 info->rxQueues[i] = virtioQueues[i * 2]; 336 info->txQueues[i] = virtioQueues[i * 2 + 1]; 337 info->rxSizes[i] = info->virtio->queue_size(info->rxQueues[i]) / 2; 338 info->txSizes[i] = info->virtio->queue_size(info->txQueues[i]) / 2; 339 } 340 if ((info->features & VIRTIO_NET_F_CTRL_VQ) != 0) 341 info->ctrlQueue = virtioQueues[info->pairsCount * 2]; 342 343 info->rxBufInfos = new(std::nothrow) BufInfo*[info->rxSizes[0]]; 344 info->txBufInfos = new(std::nothrow) BufInfo*[info->txSizes[0]]; 345 if (info->rxBufInfos == NULL || info->txBufInfos == NULL) { 346 status = B_NO_MEMORY; 347 goto err2; 348 } 349 memset(info->rxBufInfos, 0, sizeof(BufInfo*) * info->rxSizes[0]); 350 memset(info->txBufInfos, 0, sizeof(BufInfo*) * info->txSizes[0]); 351 352 // create receive buffer area 353 info->rxArea = create_area("virtionet rx buffer", (void**)&rxBuffer, 354 B_ANY_KERNEL_BLOCK_ADDRESS, ROUND_TO_PAGE_SIZE( 355 BUFFER_SIZE * info->rxSizes[0]), 356 B_FULL_LOCK, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA); 357 if (info->rxArea < B_OK) { 358 status = info->rxArea; 359 goto err3; 360 } 361 362 // initialize receive buffer descriptors 363 for (int i = 0; i < info->rxSizes[0]; i++) { 364 BufInfo* buf = new(std::nothrow) BufInfo; 365 if (buf == NULL) { 366 status = B_NO_MEMORY; 367 goto err4; 368 } 369 370 info->rxBufInfos[i] = buf; 371 buf->hdr = (struct virtio_net_hdr*)((addr_t)rxBuffer 372 + i * BUFFER_SIZE); 373 buf->buffer = (char*)((addr_t)buf->hdr + sizeof(virtio_net_rx_hdr)); 374 375 status = get_memory_map(buf->buffer, 376 BUFFER_SIZE - sizeof(virtio_net_rx_hdr), &buf->entry, 1); 377 if (status != B_OK) 378 goto err4; 379 380 status = get_memory_map(buf->hdr, sizeof(struct virtio_net_hdr), 381 &buf->hdrEntry, 1); 382 if (status != B_OK) 383 goto err4; 384 } 385 386 // create transmit buffer area 387 info->txArea = create_area("virtionet tx buffer", (void**)&txBuffer, 388 B_ANY_KERNEL_BLOCK_ADDRESS, ROUND_TO_PAGE_SIZE( 389 BUFFER_SIZE * info->txSizes[0]), 390 B_FULL_LOCK, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA); 391 if (info->txArea < B_OK) { 392 status = info->txArea; 393 goto err5; 394 } 395 396 // initialize transmit buffer descriptors 397 for (int i = 0; i < info->txSizes[0]; i++) { 398 BufInfo* buf = new(std::nothrow) BufInfo; 399 if (buf == NULL) { 400 status = B_NO_MEMORY; 401 goto err6; 402 } 403 404 info->txBufInfos[i] = buf; 405 buf->hdr = (struct virtio_net_hdr*)((addr_t)txBuffer 406 + i * BUFFER_SIZE); 407 buf->buffer = (char*)((addr_t)buf->hdr + sizeof(virtio_net_tx_hdr)); 408 409 status = get_memory_map(buf->buffer, 410 BUFFER_SIZE - sizeof(virtio_net_tx_hdr), &buf->entry, 1); 411 if (status != B_OK) 412 goto err6; 413 414 status = get_memory_map(buf->hdr, sizeof(struct virtio_net_hdr), 415 &buf->hdrEntry, 1); 416 if (status != B_OK) 417 goto err6; 418 419 info->txFreeList.Add(buf); 420 } 421 422 mutex_init(&info->rxLock, "virtionet rx lock"); 423 mutex_init(&info->txLock, "virtionet tx lock"); 424 425 // Setup interrupt 426 status = info->virtio->setup_interrupt(info->virtio_device, NULL, info); 427 if (status != B_OK) { 428 ERROR("interrupt setup failed (%s)\n", strerror(status)); 429 goto err6; 430 } 431 432 status = info->virtio->queue_setup_interrupt(info->rxQueues[0], 433 virtio_net_rxDone, info); 434 if (status != B_OK) { 435 ERROR("queue interrupt setup failed (%s)\n", strerror(status)); 436 goto err6; 437 } 438 439 status = info->virtio->queue_setup_interrupt(info->txQueues[0], 440 virtio_net_txDone, info); 441 if (status != B_OK) { 442 ERROR("queue interrupt setup failed (%s)\n", strerror(status)); 443 goto err6; 444 } 445 446 if ((info->features & VIRTIO_NET_F_CTRL_VQ) != 0) { 447 status = info->virtio->queue_setup_interrupt(info->ctrlQueue, 448 NULL, info); 449 if (status != B_OK) { 450 ERROR("queue interrupt setup failed (%s)\n", strerror(status)); 451 goto err6; 452 } 453 } 454 455 *_cookie = info; 456 return B_OK; 457 458 err6: 459 for (int i = 0; i < info->txSizes[0]; i++) 460 delete info->txBufInfos[i]; 461 err5: 462 delete_area(info->txArea); 463 err4: 464 for (int i = 0; i < info->rxSizes[0]; i++) 465 delete info->rxBufInfos[i]; 466 err3: 467 delete_area(info->rxArea); 468 err2: 469 delete[] info->rxBufInfos; 470 delete[] info->txBufInfos; 471 err1: 472 delete[] info->rxQueues; 473 delete[] info->txQueues; 474 delete[] info->rxSizes; 475 delete[] info->txSizes; 476 return status; 477 } 478 479 480 static void 481 virtio_net_uninit_device(void* _cookie) 482 { 483 CALLED(); 484 virtio_net_driver_info* info = (virtio_net_driver_info*)_cookie; 485 486 info->virtio->free_interrupts(info->virtio_device); 487 488 mutex_destroy(&info->rxLock); 489 mutex_destroy(&info->txLock); 490 491 while (true) { 492 BufInfo* buf = info->txFreeList.RemoveHead(); 493 if (buf == NULL) 494 break; 495 } 496 497 for (int i = 0; i < info->rxSizes[0]; i++) { 498 delete info->rxBufInfos[i]; 499 } 500 for (int i = 0; i < info->txSizes[0]; i++) { 501 delete info->txBufInfos[i]; 502 } 503 delete_area(info->rxArea); 504 delete_area(info->txArea); 505 delete[] info->rxBufInfos; 506 delete[] info->txBufInfos; 507 delete[] info->rxSizes; 508 delete[] info->txSizes; 509 delete[] info->rxQueues; 510 delete[] info->txQueues; 511 512 info->virtio->free_queues(info->virtio_device); 513 } 514 515 516 static status_t 517 virtio_net_open(void* _info, const char* path, int openMode, void** _cookie) 518 { 519 CALLED(); 520 virtio_net_driver_info* info = (virtio_net_driver_info*)_info; 521 522 virtio_net_handle* handle = (virtio_net_handle*)malloc( 523 sizeof(virtio_net_handle)); 524 if (handle == NULL) 525 return B_NO_MEMORY; 526 527 info->nonblocking = (openMode & O_NONBLOCK) != 0; 528 info->maxframesize = MAX_FRAME_SIZE; 529 info->rxDone = create_sem(0, "virtio_net_rx"); 530 info->txDone = create_sem(1, "virtio_net_tx"); 531 if (info->rxDone < B_OK || info->txDone < B_OK) 532 goto error; 533 handle->info = info; 534 535 if ((info->features & VIRTIO_NET_F_MAC) != 0) { 536 info->virtio->read_device_config(info->virtio_device, 537 offsetof(struct virtio_net_config, mac), 538 &info->macaddr, sizeof(info->macaddr)); 539 } 540 541 if ((info->features & VIRTIO_NET_F_MTU) != 0) { 542 dprintf("mtu feature\n"); 543 uint16 mtu; 544 info->virtio->read_device_config(info->virtio_device, 545 offsetof(struct virtio_net_config, mtu), 546 &mtu, sizeof(mtu)); 547 // check against minimum MTU 548 if (mtu > 68) 549 info->maxframesize = mtu; 550 else 551 info->virtio->clear_feature(info->virtio_device, VIRTIO_NET_F_MTU); 552 } else { 553 dprintf("no mtu feature\n"); 554 } 555 556 for (int i = 0; i < info->rxSizes[0]; i++) 557 virtio_net_rx_enqueue_buf(info, info->rxBufInfos[i]); 558 559 *_cookie = handle; 560 return B_OK; 561 562 error: 563 delete_sem(info->rxDone); 564 delete_sem(info->txDone); 565 info->rxDone = info->txDone = -1; 566 free(handle); 567 return B_ERROR; 568 } 569 570 571 static status_t 572 virtio_net_close(void* cookie) 573 { 574 virtio_net_handle* handle = (virtio_net_handle*)cookie; 575 CALLED(); 576 577 virtio_net_driver_info* info = handle->info; 578 delete_sem(info->rxDone); 579 delete_sem(info->txDone); 580 info->rxDone = info->txDone = -1; 581 582 return B_OK; 583 } 584 585 586 static status_t 587 virtio_net_free(void* cookie) 588 { 589 CALLED(); 590 virtio_net_handle* handle = (virtio_net_handle*)cookie; 591 592 virtio_net_driver_info* info = handle->info; 593 virtio_net_drain_queues(info); 594 free(handle); 595 return B_OK; 596 } 597 598 599 static void 600 virtio_net_rxDone(void* driverCookie, void* cookie) 601 { 602 CALLED(); 603 virtio_net_driver_info* info = (virtio_net_driver_info*)cookie; 604 605 release_sem_etc(info->rxDone, 1, B_DO_NOT_RESCHEDULE); 606 } 607 608 609 static status_t 610 virtio_net_read(void* cookie, off_t pos, void* buffer, size_t* _length) 611 { 612 CALLED(); 613 virtio_net_handle* handle = (virtio_net_handle*)cookie; 614 virtio_net_driver_info* info = handle->info; 615 616 mutex_lock(&info->rxLock); 617 while (info->rxFullList.Head() == NULL) { 618 mutex_unlock(&info->rxLock); 619 620 if (info->nonblocking) 621 return B_WOULD_BLOCK; 622 TRACE("virtio_net_read: waiting\n"); 623 status_t status = acquire_sem(info->rxDone); 624 if (status != B_OK) { 625 ERROR("acquire_sem(rxDone) failed (%s)\n", strerror(status)); 626 return status; 627 } 628 int32 semCount = 0; 629 get_sem_count(info->rxDone, &semCount); 630 if (semCount > 0) 631 acquire_sem_etc(info->rxDone, semCount, B_RELATIVE_TIMEOUT, 0); 632 633 mutex_lock(&info->rxLock); 634 while (info->rxDone != -1) { 635 uint32 usedLength = 0; 636 BufInfo* buf = NULL; 637 if (!info->virtio->queue_dequeue(info->rxQueues[0], (void**)&buf, 638 &usedLength) || buf == NULL) { 639 break; 640 } 641 642 buf->rxUsedLength = usedLength; 643 info->rxFullList.Add(buf); 644 } 645 TRACE("virtio_net_read: finished waiting\n"); 646 } 647 648 BufInfo* buf = info->rxFullList.RemoveHead(); 649 *_length = MIN(buf->rxUsedLength, *_length); 650 memcpy(buffer, buf->buffer, *_length); 651 virtio_net_rx_enqueue_buf(info, buf); 652 mutex_unlock(&info->rxLock); 653 return B_OK; 654 } 655 656 657 static void 658 virtio_net_txDone(void* driverCookie, void* cookie) 659 { 660 CALLED(); 661 virtio_net_driver_info* info = (virtio_net_driver_info*)cookie; 662 663 release_sem_etc(info->txDone, 1, B_DO_NOT_RESCHEDULE); 664 } 665 666 667 static status_t 668 virtio_net_write(void* cookie, off_t pos, const void* buffer, 669 size_t* _length) 670 { 671 CALLED(); 672 virtio_net_handle* handle = (virtio_net_handle*)cookie; 673 virtio_net_driver_info* info = handle->info; 674 675 mutex_lock(&info->txLock); 676 while (info->txFreeList.Head() == NULL) { 677 mutex_unlock(&info->txLock); 678 if (info->nonblocking) 679 return B_WOULD_BLOCK; 680 681 status_t status = acquire_sem(info->txDone); 682 if (status != B_OK) { 683 ERROR("acquire_sem(txDone) failed (%s)\n", strerror(status)); 684 return status; 685 } 686 687 int32 semCount = 0; 688 get_sem_count(info->txDone, &semCount); 689 if (semCount > 0) 690 acquire_sem_etc(info->txDone, semCount, B_RELATIVE_TIMEOUT, 0); 691 692 mutex_lock(&info->txLock); 693 while (info->txDone != -1) { 694 BufInfo* buf = NULL; 695 if (!info->virtio->queue_dequeue(info->txQueues[0], (void**)&buf, 696 NULL) || buf == NULL) { 697 break; 698 } 699 700 info->txFreeList.Add(buf); 701 } 702 } 703 BufInfo* buf = info->txFreeList.RemoveHead(); 704 705 TRACE("virtio_net_write: copying %lu\n", MIN(MAX_FRAME_SIZE, *_length)); 706 memcpy(buf->buffer, buffer, MIN(MAX_FRAME_SIZE, *_length)); 707 memset(buf->hdr, 0, sizeof(virtio_net_hdr)); 708 709 physical_entry entries[2]; 710 entries[0] = buf->hdrEntry; 711 entries[0].size = sizeof(virtio_net_hdr); 712 entries[1] = buf->entry; 713 entries[1].size = MIN(MAX_FRAME_SIZE, *_length); 714 715 // queue the virtio_net_hdr + buffer data 716 status_t status = info->virtio->queue_request_v(info->txQueues[0], 717 entries, 2, 0, buf); 718 mutex_unlock(&info->txLock); 719 if (status != B_OK) { 720 ERROR("tx queueing on queue %d failed (%s)\n", 0, strerror(status)); 721 return status; 722 } 723 724 return B_OK; 725 } 726 727 728 static status_t 729 virtio_net_ioctl(void* cookie, uint32 op, void* buffer, size_t length) 730 { 731 // CALLED(); 732 virtio_net_handle* handle = (virtio_net_handle*)cookie; 733 virtio_net_driver_info* info = handle->info; 734 735 // TRACE("ioctl(op = %lx)\n", op); 736 737 switch (op) { 738 case ETHER_GETADDR: 739 TRACE("ioctl: get macaddr\n"); 740 return user_memcpy(buffer, &info->macaddr, sizeof(info->macaddr)); 741 742 case ETHER_INIT: 743 TRACE("ioctl: init\n"); 744 return B_OK; 745 746 case ETHER_GETFRAMESIZE: 747 TRACE("ioctl: get frame size\n"); 748 if (length != sizeof(info->maxframesize)) 749 return B_BAD_VALUE; 750 751 return user_memcpy(buffer, &info->maxframesize, 752 sizeof(info->maxframesize)); 753 754 case ETHER_SETPROMISC: 755 { 756 TRACE("ioctl: set promisc\n"); 757 int32 value; 758 if (length != sizeof(value)) 759 return B_BAD_VALUE; 760 if (user_memcpy(&value, buffer, sizeof(value)) != B_OK) 761 return B_BAD_ADDRESS; 762 if (info->promiscuous == value) 763 return B_OK; 764 info->promiscuous = value; 765 return virtio_net_set_promisc(info, value); 766 } 767 case ETHER_NONBLOCK: 768 { 769 TRACE("ioctl: non blocking ? %s\n", 770 info->nonblocking ? "yes" : "no"); 771 int32 value; 772 if (length != sizeof(value)) 773 return B_BAD_VALUE; 774 if (user_memcpy(&value, buffer, sizeof(value)) != B_OK) 775 return B_BAD_ADDRESS; 776 info->nonblocking = value == 0; 777 return B_OK; 778 } 779 case ETHER_ADDMULTI: 780 { 781 uint32 i, multiCount = info->multiCount; 782 TRACE("ioctl: add multicast\n"); 783 784 if ((info->features & VIRTIO_NET_F_CTRL_RX) == 0) 785 return B_NOT_SUPPORTED; 786 787 if (multiCount == MAX_MULTI) 788 return B_ERROR; 789 790 for (i = 0; i < multiCount; i++) { 791 if (memcmp(&info->multi[i], buffer, 792 sizeof(info->multi[0])) == 0) { 793 break; 794 } 795 } 796 797 if (i == multiCount) { 798 memcpy(&info->multi[i], buffer, sizeof(info->multi[i])); 799 info->multiCount++; 800 } 801 if (info->multiCount == 1) { 802 TRACE("Enabling multicast\n"); 803 vtnet_set_allmulti(info, 1); 804 } 805 806 return B_OK; 807 } 808 case ETHER_REMMULTI: 809 { 810 uint32 i, multiCount = info->multiCount; 811 TRACE("ioctl: remove multicast\n"); 812 813 if ((info->features & VIRTIO_NET_F_CTRL_RX) == 0) 814 return B_NOT_SUPPORTED; 815 816 for (i = 0; i < multiCount; i++) { 817 if (memcmp(&info->multi[i], buffer, 818 sizeof(info->multi[0])) == 0) { 819 break; 820 } 821 } 822 823 if (i != multiCount) { 824 if (i < multiCount - 1) { 825 memmove(&info->multi[i], &info->multi[i + 1], 826 sizeof(info->multi[i]) * (multiCount - i - 1)); 827 } 828 info->multiCount--; 829 if (info->multiCount == 0) { 830 TRACE("Disabling multicast\n"); 831 vtnet_set_allmulti(info, 0); 832 } 833 return B_OK; 834 } 835 return B_BAD_VALUE; 836 } 837 case ETHER_GET_LINK_STATE: 838 { 839 TRACE("ioctl: get link state\n"); 840 ether_link_state_t state; 841 uint16 status = VIRTIO_NET_S_LINK_UP; 842 if ((info->features & VIRTIO_NET_F_STATUS) != 0) { 843 info->virtio->read_device_config(info->virtio_device, 844 offsetof(struct virtio_net_config, status), 845 &status, sizeof(status)); 846 } 847 state.media = ((status & VIRTIO_NET_S_LINK_UP) != 0 ? IFM_ACTIVE : 0) 848 | IFM_ETHER | IFM_FULL_DUPLEX | IFM_10G_T; 849 state.speed = 10000000000ULL; 850 state.quality = 1000; 851 852 return user_memcpy(buffer, &state, sizeof(ether_link_state_t)); 853 } 854 855 default: 856 ERROR("ioctl: unknown message %" B_PRIx32 "\n", op); 857 break; 858 } 859 860 861 return B_DEV_INVALID_IOCTL; 862 } 863 864 865 // #pragma mark - driver module API 866 867 868 static float 869 virtio_net_supports_device(device_node* parent) 870 { 871 CALLED(); 872 const char* bus; 873 uint16 deviceType; 874 875 // make sure parent is really the Virtio bus manager 876 if (sDeviceManager->get_attr_string(parent, B_DEVICE_BUS, &bus, false)) 877 return -1; 878 879 if (strcmp(bus, "virtio")) 880 return 0.0; 881 882 // check whether it's really a Direct Access Device 883 if (sDeviceManager->get_attr_uint16(parent, VIRTIO_DEVICE_TYPE_ITEM, 884 &deviceType, true) != B_OK || deviceType != VIRTIO_DEVICE_ID_NETWORK) 885 return 0.0; 886 887 TRACE("Virtio network device found!\n"); 888 889 return 0.6; 890 } 891 892 893 static status_t 894 virtio_net_register_device(device_node* node) 895 { 896 CALLED(); 897 898 device_attr attrs[] = { 899 { B_DEVICE_PRETTY_NAME, B_STRING_TYPE, {string: "Virtio Network"} }, 900 { NULL } 901 }; 902 903 return sDeviceManager->register_node(node, VIRTIO_NET_DRIVER_MODULE_NAME, 904 attrs, NULL, NULL); 905 } 906 907 908 static status_t 909 virtio_net_init_driver(device_node* node, void** cookie) 910 { 911 CALLED(); 912 913 virtio_net_driver_info* info = (virtio_net_driver_info*)malloc( 914 sizeof(virtio_net_driver_info)); 915 if (info == NULL) 916 return B_NO_MEMORY; 917 918 memset(info, 0, sizeof(*info)); 919 920 info->node = node; 921 922 *cookie = info; 923 return B_OK; 924 } 925 926 927 static void 928 virtio_net_uninit_driver(void* _cookie) 929 { 930 CALLED(); 931 virtio_net_driver_info* info = (virtio_net_driver_info*)_cookie; 932 free(info); 933 } 934 935 936 static status_t 937 virtio_net_register_child_devices(void* _cookie) 938 { 939 CALLED(); 940 virtio_net_driver_info* info = (virtio_net_driver_info*)_cookie; 941 status_t status; 942 943 int32 id = sDeviceManager->create_id(VIRTIO_NET_DEVICE_ID_GENERATOR); 944 if (id < 0) 945 return id; 946 947 char name[64]; 948 snprintf(name, sizeof(name), "net/virtio/%" B_PRId32, 949 id); 950 951 status = sDeviceManager->publish_device(info->node, name, 952 VIRTIO_NET_DEVICE_MODULE_NAME); 953 954 return status; 955 } 956 957 958 // #pragma mark - 959 960 961 module_dependency module_dependencies[] = { 962 {B_DEVICE_MANAGER_MODULE_NAME, (module_info**)&sDeviceManager}, 963 {} 964 }; 965 966 struct device_module_info sVirtioNetDevice = { 967 { 968 VIRTIO_NET_DEVICE_MODULE_NAME, 969 0, 970 NULL 971 }, 972 973 virtio_net_init_device, 974 virtio_net_uninit_device, 975 NULL, // remove, 976 977 virtio_net_open, 978 virtio_net_close, 979 virtio_net_free, 980 virtio_net_read, 981 virtio_net_write, 982 NULL, // io 983 virtio_net_ioctl, 984 985 NULL, // select 986 NULL, // deselect 987 }; 988 989 struct driver_module_info sVirtioNetDriver = { 990 { 991 VIRTIO_NET_DRIVER_MODULE_NAME, 992 0, 993 NULL 994 }, 995 996 virtio_net_supports_device, 997 virtio_net_register_device, 998 virtio_net_init_driver, 999 virtio_net_uninit_driver, 1000 virtio_net_register_child_devices, 1001 NULL, // rescan 1002 NULL, // removed 1003 }; 1004 1005 module_info* modules[] = { 1006 (module_info*)&sVirtioNetDriver, 1007 (module_info*)&sVirtioNetDevice, 1008 NULL 1009 }; 1010