Changeset 23358 in vbox
- Timestamp:
- Sep 28, 2009 9:03:12 AM (16 years ago)
- svn:sync-xref-src-repo-rev:
- 52880
- Location:
- trunk/src/VBox
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Network/DevVirtioNet.cpp
r22866 r23358 43 43 #define INSTANCE(pState) pState->szInstance 44 44 #define IFACE_TO_STATE(pIface, ifaceName) ((VPCISTATE *)((char*)pIface - RT_OFFSETOF(VPCISTATE, ifaceName))) 45 #if 0 46 /* Little helpers ************************************************************/ 47 #undef htons 48 #undef ntohs 49 #undef htonl 50 #undef ntohl 51 #define htons(x) ((((x) & 0xff00) >> 8) | (((x) & 0x00ff) << 8)) 52 #define ntohs(x) htons(x) 53 #define htonl(x) ASMByteSwapU32(x) 54 #define ntohl(x) htonl(x) 55 56 #define E1K_RELOCATE(p, o) *(RTHCUINTPTR *)&p += o 57 58 #define E1K_INC_CNT32(cnt) \ 59 do { \ 60 if (cnt < UINT32_MAX) \ 61 cnt++; \ 62 } while (0) 63 64 #define E1K_ADD_CNT64(cntLo, cntHi, val) \ 65 do { \ 66 uint64_t u64Cnt = RT_MAKE_U64(cntLo, cntHi); \ 67 uint64_t tmp = u64Cnt; \ 68 u64Cnt += val; \ 69 if (tmp > u64Cnt ) \ 70 u64Cnt = UINT64_MAX; \ 71 cntLo = (uint32_t)u64Cnt; \ 72 cntHi = (uint32_t)(u64Cnt >> 32); \ 73 } while (0) 74 75 #ifdef E1K_INT_STATS 76 # define E1K_INC_ISTAT_CNT(cnt) ++cnt 77 #else /* E1K_INT_STATS */ 78 # define E1K_INC_ISTAT_CNT(cnt) 79 #endif /* E1K_INT_STATS */ 80 #endif 45 46 #define VIRTIO_RELOCATE(p, o) *(RTHCUINTPTR *)&p += o 81 47 82 48 /*****************************************************************************/ … … 90 56 /*****************************************************************************/ 91 57 58 //- TODO: Move to Virtio.h ---------------------------------------------------- 59 60 #define VRINGDESC_MAX_SIZE (2 * 1024 * 1024) 61 #define VRINGDESC_F_NEXT 0x01 62 #define VRINGDESC_F_WRITE 0x02 63 92 64 struct VRingDesc 93 65 { … … 98 70 }; 99 71 typedef struct VRingDesc VRINGDESC; 72 typedef VRINGDESC *PVRINGDESC; 73 74 #define VRINGAVAIL_F_NO_NOTIFY 0x01 75 76 struct VRingAvail 77 { 78 uint16_t uFlags; 79 uint16_t uNextFreeIndex; 80 uint16_t auRing[1]; 81 }; 82 typedef struct VRingAvail VRINGAVAIL; 83 84 struct VRingUsedElem 85 { 86 uint32_t uId; 87 uint32_t uLen; 88 }; 89 typedef struct VRingUsedElem VRINGUSEDELEM; 90 91 #define VRINGUSED_F_NO_INTERRUPT 0x01 92 93 struct VRingUsed 94 { 95 uint16_t uFlags; 96 uint16_t uIndex; 97 VRINGUSEDELEM aRing[1]; 98 }; 99 typedef struct VRingUsed VRINGUSED; 100 typedef VRINGUSED *PVRINGUSED; 101 102 #define VRING_MAX_SIZE 1024 100 103 101 104 struct VRing 102 105 { 103 106 uint16_t uSize; 104 VRINGDESC *pDescriptors; 107 RTGCPHYS addrDescriptors; 108 RTGCPHYS addrAvail; 109 RTGCPHYS addrUsed; 105 110 }; 106 111 typedef struct VRing VRING; 112 typedef VRING *PVRING; 107 113 108 114 struct VQueue 109 115 { 110 116 VRING VRing; 117 uint16_t uNextAvailIndex; 118 uint16_t uNextUsedIndex; 111 119 uint16_t uPageNumber; 112 120 void (*pfnCallback)(void *pvState, struct VQueue *pQueue); … … 115 123 typedef VQUEUE *PVQUEUE; 116 124 125 struct VQueueElemSeg 126 { 127 RTGCPHYS addr; 128 void *pv; 129 uint32_t cb; 130 }; 131 typedef struct VQueueElemSeg VQUEUESEG; 132 133 struct VQueueElem 134 { 135 uint32_t uIndex; 136 uint32_t nIn; 137 uint32_t nOut; 138 VQUEUESEG aSegsIn[VRING_MAX_SIZE]; 139 VQUEUESEG aSegsOut[VRING_MAX_SIZE]; 140 }; 141 typedef struct VQueueElem VQUEUEELEM; 142 typedef VQUEUEELEM *PVQUEUEELEM; 143 144 117 145 enum VirtioDeviceType 118 146 { … … 123 151 struct VPCIState_st 124 152 { 153 PDMCRITSECT cs; /**< Critical section - what is it protecting? */ 125 154 /* Read-only part, never changes after initialization. */ 126 155 VirtioDeviceType enmDevType; /**< Device type: net or blk. */ … … 141 170 142 171 /* Read/write part, protected with critical section. */ 143 PDMCRITSECT cs; /**< Critical section - what is it protecting? */144 172 /** Status LED. */ 145 173 PDMLED led; … … 160 188 }; 161 189 typedef struct VPCIState_st VPCISTATE; 190 typedef VPCISTATE *PVPCISTATE; 191 192 //- TODO: Move to VirtioPCI.cpp ----------------------------------------------- 162 193 163 194 struct VirtioPCIDevices … … 199 230 #define VPCI_CONFIG 0x14 200 231 232 #define VPCI_STATUS_ACK 0x01 233 #define VPCI_STATUS_DRV 0x02 234 #define VPCI_STATUS_DRV_OK 0x04 235 #define VPCI_STATUS_FAILED 0x80 236 201 237 /** @todo use+extend RTNETIPV4 */ 202 238 203 239 /** @todo use+extend RTNETTCP */ 204 205 #define VNET_SAVEDSTATE_VERSION 1206 240 207 241 #ifndef VBOX_DEVICE_STRUCT_TESTCASE … … 211 245 PDMBOTHCBDECL(int) vpciIOPortIn (PPDMDEVINS pDevIns, void *pvUser, RTIOPORT port, uint32_t *pu32, unsigned cb); 212 246 PDMBOTHCBDECL(int) vpciIOPortOut(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT port, uint32_t u32, unsigned cb); 247 PDMBOTHCBDECL(int) vpciRaiseInterrupt(VPCISTATE *pState, int rcBusy, uint8_t u8IntCause); 213 248 RT_C_DECLS_END 249 250 251 static void vqueueInit(PVQUEUE pQueue, uint32_t uPageNumber) 252 { 253 pQueue->VRing.addrDescriptors = uPageNumber << PAGE_SHIFT; 254 pQueue->VRing.addrAvail = pQueue->VRing.addrDescriptors 255 + sizeof(VRINGDESC) * pQueue->VRing.uSize; 256 pQueue->VRing.addrUsed = RT_ALIGN( 257 pQueue->VRing.addrAvail + RT_OFFSETOF(VRINGAVAIL, auRing[pQueue->VRing.uSize]), 258 PAGE_SIZE); /* The used ring must start from the next page. */ 259 pQueue->uNextAvailIndex = 0; 260 pQueue->uNextUsedIndex = 0; 261 } 262 263 uint16_t vringReadAvailIndex(PVPCISTATE pState, PVRING pVRing) 264 { 265 uint16_t tmp; 266 267 PDMDevHlpPhysRead(pState->CTX_SUFF(pDevIns), 268 pVRing->addrAvail + RT_OFFSETOF(VRINGAVAIL, uNextFreeIndex), 269 &tmp, sizeof(tmp)); 270 return tmp; 271 } 272 273 DECLINLINE(bool) vqueueIsReady(PVPCISTATE pState, PVQUEUE pQueue) 274 { 275 return !!pQueue->VRing.addrAvail; 276 } 277 278 DECLINLINE(bool) vqueueIsEmpty(PVPCISTATE pState, PVQUEUE pQueue) 279 { 280 return (vringReadAvailIndex(pState, &pQueue->VRing) == pQueue->uNextAvailIndex); 281 } 282 283 void vqueueElemFree(PVQUEUEELEM pElem) 284 { 285 } 286 287 void vringReadDesc(PVPCISTATE pState, PVRING pVRing, uint32_t uIndex, PVRINGDESC pDesc) 288 { 289 Log(("%s vringReadDesc: ring=%p idx=%u\n", INSTANCE(pState), pVRing, uIndex)); 290 PDMDevHlpPhysRead(pState->CTX_SUFF(pDevIns), 291 pVRing->addrDescriptors + sizeof(VRINGDESC) * (uIndex % pVRing->uSize), 292 pDesc, sizeof(VRINGDESC)); 293 } 294 295 static uint16_t vringReadAvail(PVPCISTATE pState, PVRING pVRing, uint32_t uIndex) 296 { 297 uint16_t tmp; 298 299 PDMDevHlpPhysRead(pState->CTX_SUFF(pDevIns), 300 pVRing->addrAvail + RT_OFFSETOF(VRINGAVAIL, auRing[uIndex]), 301 &tmp, sizeof(tmp)); 302 return tmp; 303 } 304 305 bool vqueueGet(PVPCISTATE pState, PVQUEUE pQueue, PVQUEUEELEM pElem) 306 { 307 if (vqueueIsEmpty(pState, pQueue)) 308 return false; 309 310 pElem->nIn = pElem->nOut = 0; 311 312 Log2(("%s vqueueGet: avail_idx=%u\n", INSTANCE(pState), pQueue->uNextAvailIndex)); 313 314 VRINGDESC desc; 315 uint16_t idx = vringReadAvail(pState, &pQueue->VRing, pQueue->uNextAvailIndex++); 316 pElem->uIndex = idx; 317 do 318 { 319 VQUEUESEG *pSeg; 320 321 vringReadDesc(pState, &pQueue->VRing, idx, &desc); 322 if (desc.u16Flags & VRINGDESC_F_WRITE) 323 { 324 Log2(("%s vqueueGet: IN idx=%u seg=%u addr=%p cb=%u\n", INSTANCE(pState), idx, 325 idx, desc.u64Addr, desc.uLen)); 326 pSeg = &pElem->aSegsIn[pElem->nIn++]; 327 } 328 else 329 { 330 Log2(("%s vqueueGet: OUT idx=%u seg=%u addr=%p cb=%u\n", INSTANCE(pState), idx, 331 idx, desc.u64Addr, desc.uLen)); 332 pSeg = &pElem->aSegsOut[pElem->nOut++]; 333 } 334 335 pSeg->addr = desc.u64Addr; 336 pSeg->cb = desc.uLen; 337 pSeg->pv = NULL; 338 339 idx = desc.u16Next; 340 } while (desc.u16Flags & VRINGDESC_F_NEXT); 341 342 Log2(("%s vqueueGet: idx=%u nIn=%u nOut=%u\n", INSTANCE(pState), 343 pElem->uIndex, pElem->nIn, pElem->nOut)); 344 return true; 345 } 346 347 uint16_t vringReadUsedIndex(PVPCISTATE pState, PVRING pVRing) 348 { 349 uint16_t tmp; 350 PDMDevHlpPhysRead(pState->CTX_SUFF(pDevIns), 351 pVRing->addrUsed + RT_OFFSETOF(VRINGUSED, uIndex), 352 &tmp, sizeof(tmp)); 353 return tmp; 354 } 355 356 void vringWriteUsedIndex(PVPCISTATE pState, PVRING pVRing, uint16_t u16Value) 357 { 358 PDMDevHlpPhysWrite(pState->CTX_SUFF(pDevIns), 359 pVRing->addrUsed + RT_OFFSETOF(VRINGUSED, uIndex), 360 &u16Value, sizeof(u16Value)); 361 } 362 363 void vringWriteUsedElem(PVPCISTATE pState, PVRING pVRing, uint32_t uIndex, uint32_t uId, uint32_t uLen) 364 { 365 VRINGUSEDELEM elem; 366 367 elem.uId = uId; 368 elem.uLen = uLen; 369 PDMDevHlpPhysWrite(pState->CTX_SUFF(pDevIns), 370 pVRing->addrUsed + RT_OFFSETOF(VRINGUSED, aRing[uIndex]), 371 &elem, sizeof(elem)); 372 } 373 374 void vqueuePut(PVPCISTATE pState, PVQUEUE pQueue, PVQUEUEELEM pElem, uint32_t uLen) 375 { 376 unsigned int i, uOffset; 377 378 Log2(("%s vqueuePut: idx=%u acb=%u\n", INSTANCE(pState), pElem->uIndex, uLen)); 379 for (i = uOffset = 0; i < pElem->nIn && uOffset < uLen; i++) 380 { 381 uint32_t cbSegLen = RT_MIN(uLen - uOffset, pElem->aSegsIn[i].cb); 382 if (pElem->aSegsIn[i].pv) 383 { 384 Log2(("%s vqueuePut: used_idx=%u idx=%u seg=%u addr=%p pv=%p cb=%u acb=%u\n", INSTANCE(pState), 385 pQueue->uNextUsedIndex, pElem->uIndex, i, pElem->aSegsIn[i].addr, pElem->aSegsIn[i].pv, pElem->aSegsIn[i].cb, cbSegLen)); 386 PDMDevHlpPhysWrite(pState->CTX_SUFF(pDevIns), pElem->aSegsIn[i].addr, 387 pElem->aSegsIn[i].pv, cbSegLen); 388 } 389 uOffset += cbSegLen; 390 } 391 392 vringWriteUsedElem(pState, &pQueue->VRing, pQueue->uNextUsedIndex, pElem->uIndex, uLen); 393 pQueue->uNextUsedIndex = (pQueue->uNextUsedIndex + 1) % pQueue->VRing.uSize; 394 } 395 396 void vqueueNotify(PVPCISTATE pState, PVQUEUE pQueue) 397 { 398 int rc = vpciRaiseInterrupt(pState, VERR_INTERNAL_ERROR, VPCI_ISR_QUEUE); 399 if (RT_FAILURE(rc)) 400 Log(("%s vqueueNotify: Failed to raise an interrupt (%Vrc).\n", INSTANCE(pState), rc)); 401 } 402 403 void vqueueSync(PVPCISTATE pState, PVQUEUE pQueue) 404 { 405 Log2(("%s vqueueSync: used_idx=%u\n", INSTANCE(pState), pQueue->uNextUsedIndex)); 406 vringWriteUsedIndex(pState, &pQueue->VRing, pQueue->uNextUsedIndex); 407 vqueueNotify(pState, pQueue); 408 } 214 409 215 410 /** … … 323 518 *(uint8_t*)pu32 = pState->uISR; 324 519 pState->uISR = 0; /* read clears all interrupts */ 520 vpciLowerInterrupt(pState); 325 521 break; 326 522 … … 379 575 */ 380 576 pState->pQueues[pState->uQueueSelector].uPageNumber = u32; 381 pState->pQueues[pState->uQueueSelector].VRing.pDescriptors = (VRINGDESC*)(u32 << PAGE_SHIFT); 577 if (u32) 578 vqueueInit(&pState->pQueues[pState->uQueueSelector], u32); 579 else 580 g_VPCIDevices[pState->enmDevType].pfnReset(pState); 382 581 break; 383 582 … … 392 591 393 592 case VPCI_QUEUE_NOTIFY: 394 // TODO 593 Assert(cb == 2); 594 u32 &= 0xFFFF; 595 if (u32 < g_VPCIDevices[pState->enmDevType].nQueues) 596 if (pState->pQueues[u32].VRing.addrDescriptors) 597 pState->pQueues[u32].pfnCallback(pState, &pState->pQueues[u32]); 598 else 599 Log(("%s The queue (#%d) being notified has not been initialized.\n", 600 INSTANCE(pState), u32)); 601 else 602 Log(("%s Invalid queue number (%d)\n", INSTANCE(pState), u32)); 395 603 break; 396 604 … … 511 719 * @thread EMT 512 720 */ 513 DECLINLINE(void) v irtioPCICfgSetU8(PCIDEVICE& refPciDev, uint32_t uOffset, uint8_t u8Value)721 DECLINLINE(void) vpciCfgSetU8(PCIDEVICE& refPciDev, uint32_t uOffset, uint8_t u8Value) 514 722 { 515 723 Assert(uOffset < sizeof(refPciDev.config)); … … 524 732 * @thread EMT 525 733 */ 526 DECLINLINE(void) v irtioPCICfgSetU16(PCIDEVICE& refPciDev, uint32_t uOffset, uint16_t u16Value)734 DECLINLINE(void) vpciCfgSetU16(PCIDEVICE& refPciDev, uint32_t uOffset, uint16_t u16Value) 527 735 { 528 736 Assert(uOffset+sizeof(u16Value) <= sizeof(refPciDev.config)); … … 537 745 * @thread EMT 538 746 */ 539 DECLINLINE(void) v irtioPCICfgSetU32(PCIDEVICE& refPciDev, uint32_t uOffset, uint32_t u32Value)747 DECLINLINE(void) vpciCfgSetU32(PCIDEVICE& refPciDev, uint32_t uOffset, uint32_t u32Value) 540 748 { 541 749 Assert(uOffset+sizeof(u32Value) <= sizeof(refPciDev.config)); … … 556 764 PCIDevSetVendorId(&pci, g_VPCIDevices[enmType].uPCIVendorId); 557 765 PCIDevSetDeviceId(&pci, g_VPCIDevices[enmType].uPCIDeviceId); 558 v irtioPCICfgSetU16(pci, VBOX_PCI_SUBSYSTEM_VENDOR_ID, g_VPCIDevices[enmType].uPCISubsystemVendorId);559 v irtioPCICfgSetU16(pci, VBOX_PCI_SUBSYSTEM_ID, g_VPCIDevices[enmType].uPCISubsystemId);766 vpciCfgSetU16(pci, VBOX_PCI_SUBSYSTEM_VENDOR_ID, g_VPCIDevices[enmType].uPCISubsystemVendorId); 767 vpciCfgSetU16(pci, VBOX_PCI_SUBSYSTEM_ID, g_VPCIDevices[enmType].uPCISubsystemId); 560 768 561 769 /* ABI version, must be equal 0 as of 2.6.30 kernel. */ 562 v irtioPCICfgSetU8( pci, VBOX_PCI_REVISION_ID, 0x00);770 vpciCfgSetU8( pci, VBOX_PCI_REVISION_ID, 0x00); 563 771 /* Ethernet adapter */ 564 v irtioPCICfgSetU8( pci, VBOX_PCI_CLASS_PROG, 0x00);565 v irtioPCICfgSetU16(pci, VBOX_PCI_CLASS_DEVICE, g_VPCIDevices[enmType].uPCIClass);772 vpciCfgSetU8( pci, VBOX_PCI_CLASS_PROG, 0x00); 773 vpciCfgSetU16(pci, VBOX_PCI_CLASS_DEVICE, g_VPCIDevices[enmType].uPCIClass); 566 774 /* Interrupt Pin: INTA# */ 567 v irtioPCICfgSetU8( pci, VBOX_PCI_INTERRUPT_PIN, 0x01);775 vpciCfgSetU8( pci, VBOX_PCI_INTERRUPT_PIN, 0x01); 568 776 } 569 777 … … 690 898 { 691 899 pQueue->VRing.uSize = uSize; 692 pQueue->VRing. pDescriptors = NULL;900 pQueue->VRing.addrDescriptors = 0; 693 901 pQueue->uPageNumber = 0; 694 902 pQueue->pfnCallback = pfnCallback; … … 698 906 } 699 907 908 700 909 #endif /* IN_RING3 */ 701 910 … … 703 912 //------------------------- Tear off here: vnet ------------------------------- 704 913 914 //- TODO: Move to VirtioNet.h ------------------------------------------------- 915 916 #define VNET_MAX_FRAME_SIZE 65536 // TODO: Is it the right limit? 917 #define VNET_SAVEDSTATE_VERSION 1 918 705 919 /* Virtio net features */ 706 #define NET_F_CSUM 0x00000001 /* Host handles pkts w/ partial csum */707 #define NET_F_GUEST_CSUM 0x00000002 /* Guest handles pkts w/ partial csum */708 #define NET_F_MAC 0x00000020 /* Host has given MAC address. */709 #define NET_F_GSO 0x00000040 /* Host handles pkts w/ any GSO type */710 #define NET_F_GUEST_TSO4 0x00000080 /* Guest can handle TSOv4 in. */711 #define NET_F_GUEST_TSO6 0x00000100 /* Guest can handle TSOv6 in. */712 #define NET_F_GUEST_ECN 0x00000200 /* Guest can handle TSO[6] w/ ECN in. */713 #define NET_F_GUEST_UFO 0x00000400 /* Guest can handle UFO in. */714 #define NET_F_HOST_TSO4 0x00000800 /* Host can handle TSOv4 in. */715 #define NET_F_HOST_TSO6 0x00001000 /* Host can handle TSOv6 in. */716 #define NET_F_HOST_ECN 0x00002000 /* Host can handle TSO[6] w/ ECN in. */717 #define NET_F_HOST_UFO 0x00004000 /* Host can handle UFO in. */718 #define NET_F_MRG_RXBUF 0x00008000 /* Host can merge receive buffers. */719 #define NET_F_STATUS 0x00010000 /* virtio_net_config.status available */720 #define NET_F_CTRL_VQ 0x00020000 /* Control channel available */721 #define NET_F_CTRL_RX 0x00040000 /* Control channel RX mode support */722 #define NET_F_CTRL_VLAN 0x00080000 /* Control channel VLAN filtering */723 724 #define NET_S_LINK_UP 1920 #define VNET_F_CSUM 0x00000001 /* Host handles pkts w/ partial csum */ 921 #define VNET_F_GUEST_CSUM 0x00000002 /* Guest handles pkts w/ partial csum */ 922 #define VNET_F_MAC 0x00000020 /* Host has given MAC address. */ 923 #define VNET_F_GSO 0x00000040 /* Host handles pkts w/ any GSO type */ 924 #define VNET_F_GUEST_TSO4 0x00000080 /* Guest can handle TSOv4 in. */ 925 #define VNET_F_GUEST_TSO6 0x00000100 /* Guest can handle TSOv6 in. */ 926 #define VNET_F_GUEST_ECN 0x00000200 /* Guest can handle TSO[6] w/ ECN in. */ 927 #define VNET_F_GUEST_UFO 0x00000400 /* Guest can handle UFO in. */ 928 #define VNET_F_HOST_TSO4 0x00000800 /* Host can handle TSOv4 in. */ 929 #define VNET_F_HOST_TSO6 0x00001000 /* Host can handle TSOv6 in. */ 930 #define VNET_F_HOST_ECN 0x00002000 /* Host can handle TSO[6] w/ ECN in. */ 931 #define VNET_F_HOST_UFO 0x00004000 /* Host can handle UFO in. */ 932 #define VNET_F_MRG_RXBUF 0x00008000 /* Host can merge receive buffers. */ 933 #define VNET_F_STATUS 0x00010000 /* virtio_net_config.status available */ 934 #define VNET_F_CTRL_VQ 0x00020000 /* Control channel available */ 935 #define VNET_F_CTRL_RX 0x00040000 /* Control channel RX mode support */ 936 #define VNET_F_CTRL_VLAN 0x00080000 /* Control channel VLAN filtering */ 937 938 #define VNET_S_LINK_UP 1 725 939 726 940 … … 792 1006 }; 793 1007 typedef struct VNetState_st VNETSTATE; 1008 typedef VNETSTATE *PVNETSTATE; 1009 1010 #define VNETHDR_GSO_NONE 0 1011 1012 struct VNetHdr 1013 { 1014 uint8_t u8Flags; 1015 uint8_t u8GSOType; 1016 uint16_t u16HdrLen; 1017 uint16_t u16GSOSize; 1018 uint16_t u16CSumStart; 1019 uint16_t u16CSumOffset; 1020 }; 1021 typedef struct VNetHdr VNETHDR; 1022 typedef VNETHDR *PVNETHDR; 794 1023 795 1024 AssertCompileMemberOffset(VNETSTATE, VPCI, 0); 1025 1026 //- TODO: Leave here ---------------------------------------------------------- 796 1027 797 1028 #undef INSTANCE … … 804 1035 { 805 1036 // TODO: implement 806 return NET_F_MAC |NET_F_STATUS;1037 return VNET_F_MAC | VNET_F_STATUS; 807 1038 } 808 1039 … … 871 1102 VNETSTATE *pState = (VNETSTATE *)pvUser; 872 1103 873 STATUS |= NET_S_LINK_UP;1104 STATUS |= VNET_S_LINK_UP; 874 1105 vpciRaiseInterrupt(&pState->VPCI, VERR_SEM_BUSY, VPCI_ISR_CONFIG); 875 1106 } … … 896 1127 * This must be called before the pfnRecieve() method is called. 897 1128 * 898 * @returns Number of bytes the device can receive.1129 * @returns VERR_NET_NO_BUFFER_SPACE if it cannot. 899 1130 * @param pInterface Pointer to the interface structure containing the called function pointer. 900 1131 * @thread EMT … … 902 1133 static int vnetCanReceive(VNETSTATE *pState) 903 1134 { 904 size_t cb; 905 906 cb = 0; // TODO 907 return cb > 0 ? VINF_SUCCESS : VERR_NET_NO_BUFFER_SPACE; 1135 return (vqueueIsReady(&pState->VPCI, pState->pRxQueue) 1136 && !vqueueIsEmpty(&pState->VPCI, pState->pRxQueue)) 1137 ? VINF_SUCCESS : VERR_NET_NO_BUFFER_SPACE; 908 1138 } 909 1139 … … 964 1194 965 1195 /** 1196 * Determines if the packet is to be delivered to upper layer. The following 1197 * filters supported: 1198 * - Exact Unicast/Multicast 1199 * - Promiscuous Unicast/Multicast 1200 * - Multicast 1201 * - VLAN 1202 * 1203 * @returns true if packet is intended for this node. 1204 * @param pState Pointer to the state structure. 1205 * @param pvBuf The ethernet packet. 1206 * @param cb Number of bytes available in the packet. 1207 */ 1208 static bool vnetAddressFilter(PVNETSTATE pState, const void *pvBuf, size_t cb) 1209 { 1210 return true; // TODO: Implement! 1211 } 1212 1213 /** 1214 * Pad and store received packet. 1215 * 1216 * @remarks Make sure that the packet appears to upper layer as one coming 1217 * from real Ethernet: pad it and insert FCS. 1218 * 1219 * @returns VBox status code. 1220 * @param pState The device state structure. 1221 * @param pvBuf The available data. 1222 * @param cb Number of bytes available in the buffer. 1223 */ 1224 static int vnetHandleRxPacket(PVNETSTATE pState, const void *pvBuf, size_t cb) 1225 { 1226 VNETHDR hdr; 1227 memset(&hdr, 0, sizeof(hdr)); 1228 /*hdr.u8Flags = 0; 1229 hdr.u8GSOType = VNETHDR_GSO_NONE;*/ 1230 1231 unsigned int uOffset = 0; 1232 for (unsigned int nElem = 0; uOffset < cb; nElem++) 1233 { 1234 VQUEUEELEM elem; 1235 unsigned int nSeg = 0, uElemSize = 0; 1236 1237 if (!vqueueGet(&pState->VPCI, pState->pRxQueue, &elem)) 1238 { 1239 Log(("%s vnetHandleRxPacket: Suddenly there is no space in receive queue!\n", INSTANCE(pState))); 1240 return VERR_INTERNAL_ERROR; 1241 } 1242 1243 if (elem.nIn < 1) 1244 { 1245 Log(("%s vnetHandleRxPacket: No writable descriptors in receive queue!\n", INSTANCE(pState))); 1246 return VERR_INTERNAL_ERROR; 1247 } 1248 1249 if (nElem == 0) 1250 { 1251 /* The very first segment of the very first element gets the header. */ 1252 if (elem.aSegsIn[nSeg].cb != sizeof(VNETHDR)) 1253 { 1254 Log(("%s vnetHandleRxPacket: The first descriptor does match the header size!\n", INSTANCE(pState))); 1255 return VERR_INTERNAL_ERROR; 1256 } 1257 1258 elem.aSegsIn[nSeg++].pv = &hdr; 1259 uElemSize += sizeof(VNETHDR); 1260 } 1261 1262 while (nSeg < elem.nIn && uOffset < cb) 1263 { 1264 unsigned int uSize = RT_MIN(elem.aSegsIn[nSeg].cb, cb - uOffset); 1265 elem.aSegsIn[nSeg++].pv = (uint8_t*)pvBuf + uOffset; 1266 uOffset += uSize; 1267 uElemSize += uSize; 1268 } 1269 elem.uIndex = nElem; 1270 vqueuePut(&pState->VPCI, pState->pRxQueue, &elem, uElemSize); 1271 } 1272 vqueueSync(&pState->VPCI, pState->pRxQueue); 1273 1274 return VINF_SUCCESS; 1275 } 1276 1277 /** 966 1278 * Receive data from the network. 967 1279 * … … 976 1288 VNETSTATE *pState = IFACE_TO_STATE(pInterface, INetworkPort); 977 1289 int rc = VINF_SUCCESS; 978 // TODO: Implement 1290 1291 Log2(("%s vnetReceive: pvBuf=%p cb=%u\n", INSTANCE(pState), pvBuf, cb)); 1292 rc = vnetCanReceive(pState); 1293 if (RT_FAILURE(rc)) 1294 return rc; 1295 1296 if (vnetAddressFilter(pState, pvBuf, cb)) 1297 rc = vnetHandleRxPacket(pState, pvBuf, cb); 1298 979 1299 return rc; 980 1300 } … … 1005 1325 { 1006 1326 VNETSTATE *pState = IFACE_TO_STATE(pInterface, INetworkConfig); 1007 if (STATUS & NET_S_LINK_UP)1327 if (STATUS & VNET_S_LINK_UP) 1008 1328 return PDMNETWORKLINKSTATE_UP; 1009 1329 return PDMNETWORKLINKSTATE_DOWN; … … 1021 1341 { 1022 1342 VNETSTATE *pState = IFACE_TO_STATE(pInterface, INetworkConfig); 1023 bool fOldUp = !!(STATUS & NET_S_LINK_UP);1343 bool fOldUp = !!(STATUS & VNET_S_LINK_UP); 1024 1344 bool fNewUp = enmState == PDMNETWORKLINKSTATE_UP; 1025 1345 … … 1029 1349 { 1030 1350 Log(("%s Link is up\n", INSTANCE(pState))); 1031 STATUS |= NET_S_LINK_UP;1351 STATUS |= VNET_S_LINK_UP; 1032 1352 vpciRaiseInterrupt(&pState->VPCI, VERR_SEM_BUSY, VPCI_ISR_CONFIG); 1033 1353 } … … 1035 1355 { 1036 1356 Log(("%s Link is down\n", INSTANCE(pState))); 1037 STATUS &= ~ NET_S_LINK_UP;1357 STATUS &= ~VNET_S_LINK_UP; 1038 1358 vpciRaiseInterrupt(&pState->VPCI, VERR_SEM_BUSY, VPCI_ISR_CONFIG); 1039 1359 } … … 1044 1364 } 1045 1365 1046 static DECLCALLBACK(void) vnet Receive(void *pvState, PVQUEUE pQueue)1366 static DECLCALLBACK(void) vnetQueueReceive(void *pvState, PVQUEUE pQueue) 1047 1367 { 1048 1368 VNETSTATE *pState = (VNETSTATE*)pvState; 1049 } 1050 1051 static DECLCALLBACK(void) vnetTransmit(void *pvState, PVQUEUE pQueue) 1369 Log(("%s Receive buffers has been added.\n", INSTANCE(pState))); 1370 } 1371 1372 static DECLCALLBACK(void) vnetQueueTransmit(void *pvState, PVQUEUE pQueue) 1052 1373 { 1053 1374 VNETSTATE *pState = (VNETSTATE*)pvState; 1054 } 1055 1056 static DECLCALLBACK(void) vnetControl(void *pvState, PVQUEUE pQueue) 1375 if ((pState->VPCI.uStatus & VPCI_STATUS_DRV_OK) == 0) 1376 { 1377 Log(("%s Ignoring transmit requests from non-existent driver (status=0x%x).\n", 1378 INSTANCE(pState), pState->VPCI.uStatus)); 1379 return; 1380 } 1381 1382 VQUEUEELEM elem; 1383 while (vqueueGet(&pState->VPCI, pQueue, &elem)) 1384 { 1385 unsigned int uOffset = 0; 1386 if (elem.nOut < 2 || elem.aSegsOut[0].cb != sizeof(VNETHDR)) 1387 { 1388 Log(("%s vnetQueueTransmit: The first segment is not the header! (%u < 2 || %u != %u).\n", 1389 INSTANCE(pState), elem.nOut, elem.aSegsOut[0].cb, sizeof(VNETHDR))); 1390 vqueueElemFree(&elem); 1391 break; /* For now we simply ignore the header, but it must be there anyway! */ 1392 } 1393 else 1394 { 1395 uint8_t *pFrame = (uint8_t *)RTMemAllocZ(VNET_MAX_FRAME_SIZE); 1396 if (!pFrame) 1397 { 1398 Log(("%s vnetQueueTransmit: Failed to allocate %u bytes.\n", 1399 INSTANCE(pState), VNET_MAX_FRAME_SIZE)); 1400 vqueueElemFree(&elem); 1401 break; /* For now we simply ignore the header, but it must be there anyway! */ 1402 } 1403 1404 /* Assemble a complete frame. */ 1405 for (unsigned int i = 1; i < elem.nOut && uOffset < VNET_MAX_FRAME_SIZE; i++) 1406 { 1407 unsigned int uSize = elem.aSegsOut[i].cb; 1408 if (uSize > VNET_MAX_FRAME_SIZE - uOffset) 1409 { 1410 Log(("%s vnetQueueTransmit: Packet is too big (>64k), truncating...\n", INSTANCE(pState))); 1411 uSize = VNET_MAX_FRAME_SIZE - uOffset; 1412 } 1413 PDMDevHlpPhysRead(pState->VPCI.CTX_SUFF(pDevIns), elem.aSegsOut[i].addr, 1414 pFrame + uOffset, uSize); 1415 uOffset += uSize; 1416 } 1417 STAM_PROFILE_ADV_START(&pState->StatTransmitSend, a); 1418 int rc = pState->pDrv->pfnSend(pState->pDrv, pFrame, uOffset); 1419 STAM_PROFILE_ADV_STOP(&pState->StatTransmitSend, a); 1420 RTMemFree(pFrame); 1421 } 1422 vqueuePut(&pState->VPCI, pQueue, &elem, uOffset); 1423 vqueueSync(&pState->VPCI, pQueue); 1424 } 1425 } 1426 1427 static DECLCALLBACK(void) vnetQueueControl(void *pvState, PVQUEUE pQueue) 1057 1428 { 1058 1429 VNETSTATE *pState = (VNETSTATE*)pvState; 1430 Log(("%s Pending control message\n", INSTANCE(pState))); 1059 1431 } 1060 1432 … … 1082 1454 pState->VPCI.IBase.pfnQueryInterface = vnetQueryInterface; 1083 1455 rc = vpciConstruct(pDevIns, &pState->VPCI, iInstance, VIRTIO_NET_ID, sizeof(VNetPCIConfig)); 1084 pState->pRxQueue = vpciAddQueue(&pState->VPCI, 256, vnet Receive);1085 pState->pTxQueue = vpciAddQueue(&pState->VPCI, 256, vnet Transmit);1086 pState->pCtlQueue = vpciAddQueue(&pState->VPCI, 16, vnet Control);1456 pState->pRxQueue = vpciAddQueue(&pState->VPCI, 256, vnetQueueReceive); 1457 pState->pTxQueue = vpciAddQueue(&pState->VPCI, 256, vnetQueueTransmit); 1458 pState->pCtlQueue = vpciAddQueue(&pState->VPCI, 16, vnetQueueControl); 1087 1459 1088 1460 Log(("%s Constructing new instance\n", INSTANCE(pState))); … … 1122 1494 // TODO: 1123 1495 /* 1124 rc = PDMDevHlpSSMRegisterEx(pDevIns, V NET_SAVEDSTATE_VERSION, sizeof(VNETSTATE), NULL,1496 rc = PDMDevHlpSSMRegisterEx(pDevIns, VVNET_SAVEDSTATE_VERSION, sizeof(VNETSTATE), NULL, 1125 1497 NULL, NULL, NULL, 1126 1498 NULL, vnetSaveExec, NULL, … … 1326 1698 * network card 1327 1699 */ 1328 if ((STATUS & NET_S_LINK_UP) && RT_SUCCESS(rc))1329 { 1330 STATUS &= ~ NET_S_LINK_UP;1700 if ((STATUS & VNET_S_LINK_UP) && RT_SUCCESS(rc)) 1701 { 1702 STATUS &= ~VNET_S_LINK_UP; 1331 1703 vpciRaiseInterrupt(&pState->VPCI, VERR_SEM_BUSY, VPCI_ISR_CONFIG); 1332 1704 /* Restore the link back in 5 seconds. */ -
trunk/src/VBox/Frontends/VirtualBox/Makefile.kmk
r23333 r23358 191 191 else ifdef VBOX_GUI_USE_QGL 192 192 VirtualBox_DEFS += VBOX_GUI_USE_QGL 193 endif 194 ifdef VBOX_WITH_VIRTIO 195 VirtualBox_DEFS += VBOX_WITH_VIRTIO 193 196 endif 194 197 -
trunk/src/VBox/Frontends/VirtualBox/src/VBoxGlobal.cpp
r23223 r23358 2665 2665 mNetworkAdapterTypes [KNetworkAdapterType_I82545EM] = 2666 2666 tr ("Intel PRO/1000 MT Server (82545EM)", "NetworkAdapterType"); 2667 #ifdef VBOX_WITH_VIRTIO 2668 mNetworkAdapterTypes [KNetworkAdapterType_Virtio] = 2669 tr ("Virtio Network Adapter", "NetworkAdapterType"); 2670 #endif /* VBOX_WITH_VIRTIO */ 2667 2671 2668 2672 mNetworkAttachmentTypes [KNetworkAttachmentType_Null] =
Note:
See TracChangeset
for help on using the changeset viewer.