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