Changeset 23830 in vbox
- Timestamp:
- Oct 16, 2009 7:48:17 PM (15 years ago)
- svn:sync-xref-src-repo-rev:
- 53587
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Network/DevVirtioNet.cpp
r23578 r23830 52 52 //- TODO: Move to Virtio.h ---------------------------------------------------- 53 53 54 #define VPCI_F_NOTIFY_ON_EMPTY 0x1000000 54 #define VPCI_F_NOTIFY_ON_EMPTY 0x01000000 55 #define VPCI_F_BAD_FEATURE 0x40000000 55 56 56 57 #define VRINGDESC_MAX_SIZE (2 * 1024 * 1024) … … 68 69 typedef VRINGDESC *PVRINGDESC; 69 70 70 #define VRINGAVAIL_F_NO_ NOTIFY0x0171 #define VRINGAVAIL_F_NO_INTERRUPT 0x01 71 72 72 73 struct VRingAvail … … 85 86 typedef struct VRingUsedElem VRINGUSEDELEM; 86 87 87 #define VRINGUSED_F_NO_ INTERRUPT0x0188 #define VRINGUSED_F_NO_NOTIFY 0x01 88 89 89 90 struct VRingUsed … … 191 192 RT_C_DECLS_BEGIN 192 193 PDMBOTHCBDECL(uint32_t) vnetGetHostFeatures(void *pState); 194 PDMBOTHCBDECL(uint32_t) vnetGetHostMinimalFeatures(void *pState); 195 PDMBOTHCBDECL(void) vnetSetHostFeatures(void *pState, uint32_t uFeatures); 193 196 PDMBOTHCBDECL(int) vnetGetConfig(void *pState, uint32_t port, uint32_t cb, void *data); 194 197 PDMBOTHCBDECL(int) vnetSetConfig(void *pState, uint32_t port, uint32_t cb, void *data); … … 212 215 const char *pcszNameFmt; 213 216 uint32_t (*pfnGetHostFeatures)(void *pvState); 217 uint32_t (*pfnGetHostMinimalFeatures)(void *pvState); 218 void (*pfnSetHostFeatures)(void *pvState, uint32_t uFeatures); 214 219 int (*pfnGetConfig)(void *pvState, uint32_t port, uint32_t cb, void *data); 215 220 int (*pfnSetConfig)(void *pvState, uint32_t port, uint32_t cb, void *data); … … 223 228 { /* Virtio Network Device */ 224 229 0x1AF4, 0x1000, 0x1AF4, 1 + VIRTIO_NET_ID, 0x0200, 3, "virtio-net", "vnet%d", 225 vnetGetHostFeatures, vnetGetConfig, vnetSetConfig, vnetReset 230 vnetGetHostFeatures, vnetGetHostMinimalFeatures, vnetSetHostFeatures, 231 vnetGetConfig, vnetSetConfig, vnetReset 226 232 #ifdef DEBUG 227 233 , vnetGetQueueName … … 230 236 { /* Virtio Block Device */ 231 237 0x1AF4, 0x1001, 0x1AF4, 1 + VIRTIO_BLK_ID, 0x0180, 2, "virtio-blk", "vblk%d", 232 NULL, NULL, NULL, NULL 238 NULL, NULL, NULL, NULL, NULL, NULL 233 239 #ifdef DEBUG 234 240 , NULL … … 278 284 pQueue->uNextAvailIndex = 0; 279 285 pQueue->uNextUsedIndex = 0; 286 pQueue->uPageNumber = 0; 280 287 } 281 288 … … 324 331 } 325 332 326 staticuint16_t vringReadAvail(PVPCISTATE pState, PVRING pVRing, uint32_t uIndex)333 uint16_t vringReadAvail(PVPCISTATE pState, PVRING pVRing, uint32_t uIndex) 327 334 { 328 335 uint16_t tmp; … … 332 339 &tmp, sizeof(tmp)); 333 340 return tmp; 341 } 342 343 uint16_t vringReadAvailFlags(PVPCISTATE pState, PVRING pVRing) 344 { 345 uint16_t tmp; 346 347 PDMDevHlpPhysRead(pState->CTX_SUFF(pDevIns), 348 pVRing->addrAvail + RT_OFFSETOF(VRINGAVAIL, uFlags), 349 &tmp, sizeof(tmp)); 350 return tmp; 351 } 352 353 DECLINLINE(void) vringSetNotification(PVPCISTATE pState, PVRING pVRing, bool fEnabled) 354 { 355 uint16_t tmp; 356 357 PDMDevHlpPhysRead(pState->CTX_SUFF(pDevIns), 358 pVRing->addrUsed + RT_OFFSETOF(VRINGUSED, uFlags), 359 &tmp, sizeof(tmp)); 360 361 if (fEnabled) 362 tmp &= ~ VRINGUSED_F_NO_NOTIFY; 363 else 364 tmp |= VRINGUSED_F_NO_NOTIFY; 365 366 PDMDevHlpPhysWrite(pState->CTX_SUFF(pDevIns), 367 pVRing->addrUsed + RT_OFFSETOF(VRINGUSED, uFlags), 368 &tmp, sizeof(tmp)); 334 369 } 335 370 … … 430 465 void vqueueNotify(PVPCISTATE pState, PVQUEUE pQueue) 431 466 { 432 int rc = vpciRaiseInterrupt(pState, VERR_INTERNAL_ERROR, VPCI_ISR_QUEUE); 433 if (RT_FAILURE(rc)) 434 Log(("%s vqueueNotify: Failed to raise an interrupt (%Vrc).\n", INSTANCE(pState), rc)); 467 LogFlow(("%s vqueueNotify: %s availFlags=%x guestFeatures=%x vqueue is %sempty\n", 468 INSTANCE(pState), QUEUENAME(pState, pQueue), 469 vringReadAvailFlags(pState, &pQueue->VRing), 470 pState->uGuestFeatures, vqueueIsEmpty(pState, pQueue)?"":"not ")); 471 if (!(vringReadAvailFlags(pState, &pQueue->VRing) & VRINGAVAIL_F_NO_INTERRUPT) 472 || ((pState->uGuestFeatures & VPCI_F_NOTIFY_ON_EMPTY) && vqueueIsEmpty(pState, pQueue))) 473 { 474 int rc = vpciRaiseInterrupt(pState, VERR_INTERNAL_ERROR, VPCI_ISR_QUEUE); 475 if (RT_FAILURE(rc)) 476 Log(("%s vqueueNotify: Failed to raise an interrupt (%Vrc).\n", INSTANCE(pState), rc)); 477 } 435 478 } 436 479 … … 493 536 return rc; 494 537 538 LogFlow(("%s vpciRaiseInterrupt: u8IntCause=%x\n", 539 INSTANCE(pState), u8IntCause)); 540 495 541 pState->uISR |= u8IntCause; 496 542 PDMDevHlpPCISetIrq(pState->CTX_SUFF(pDevIns), 0, 1); … … 506 552 PDMBOTHCBDECL(void) vpciLowerInterrupt(VPCISTATE *pState) 507 553 { 554 LogFlow(("%s vpciLowerInterrupt\n", INSTANCE(pState))); 508 555 PDMDevHlpPCISetIrq(pState->CTX_SUFF(pDevIns), 0, 0); 556 } 557 558 DECLINLINE(uint32_t) vpciGetHostFeatures(PVPCISTATE pState) 559 { 560 return g_VPCIDevices[pState->enmDevType].pfnGetHostFeatures(pState) 561 | VPCI_F_NOTIFY_ON_EMPTY; 509 562 } 510 563 … … 534 587 case VPCI_HOST_FEATURES: 535 588 /* Tell the guest what features we support. */ 536 *pu32 = g_VPCIDevices[pState->enmDevType].pfnGetHostFeatures(pState);589 *pu32 = vpciGetHostFeatures(pState) | VPCI_F_BAD_FEATURE; 537 590 break; 538 591 … … 609 662 { 610 663 case VPCI_GUEST_FEATURES: 611 // TODO: Feature negotiation code goes here. 612 // The guest may potentially desire features we don't support! 613 pState->uGuestFeatures = u32; 664 /* Check if the guest negotiates properly, fall back to basics if it does not. */ 665 if (VPCI_F_BAD_FEATURE & u32) 666 { 667 Log(("%s Guest failed to negotiate properly! (guest=%x)\n", 668 INSTANCE(pState), u32)); 669 pState->uGuestFeatures = g_VPCIDevices[pState->enmDevType].pfnGetHostMinimalFeatures(pState); 670 } 671 /* The guest may potentially desire features we don't support! */ 672 else if (~vpciGetHostFeatures(pState) & u32) 673 { 674 Log(("%s Guest asked for features host does not support! (host=%x guest=%x)\n", 675 INSTANCE(pState), vpciGetHostFeatures(pState), u32)); 676 pState->uGuestFeatures = vpciGetHostFeatures(pState); 677 } 678 else 679 pState->uGuestFeatures = u32; 680 g_VPCIDevices[pState->enmDevType].pfnSetHostFeatures(pState, pState->uGuestFeatures); 614 681 break; 615 682 … … 1127 1194 } 1128 1195 1196 PDMBOTHCBDECL(uint32_t) vnetGetHostMinimalFeatures(void *pvState) 1197 { 1198 return VNET_F_MAC; 1199 } 1200 1201 PDMBOTHCBDECL(void) vnetSetHostFeatures(void *pvState, uint32_t uFeatures) 1202 { 1203 // TODO: Nothing to do here yet 1204 VNETSTATE *pState = (VNETSTATE *)pvState; 1205 LogFlow(("%s vnetSetHostFeatures: uFeatures=%x\n", INSTANCE(pState), uFeatures)); 1206 } 1207 1129 1208 PDMBOTHCBDECL(int) vnetGetConfig(void *pvState, uint32_t port, uint32_t cb, void *data) 1130 1209 { … … 1217 1296 * This must be called before the pfnRecieve() method is called. 1218 1297 * 1298 * @remarks As a side effect this function enables queue notification 1299 * if it cannot receive because the queue is empty. 1300 * It disables notification if it can receive. 1301 * 1219 1302 * @returns VERR_NET_NO_BUFFER_SPACE if it cannot. 1220 1303 * @param pInterface Pointer to the interface structure containing the called function pointer. … … 1223 1306 static int vnetCanReceive(VNETSTATE *pState) 1224 1307 { 1308 int rc; 1225 1309 LogFlow(("%s vnetCanReceive\n", INSTANCE(pState))); 1226 int rc = (vqueueIsReady(&pState->VPCI, pState->pRxQueue) 1227 && !vqueueIsEmpty(&pState->VPCI, pState->pRxQueue)) 1228 ? VINF_SUCCESS : VERR_NET_NO_BUFFER_SPACE; 1229 LogFlow(("%s vnetCanReceive -> %d\n", INSTANCE(pState), rc)); 1310 if (!(pState->VPCI.uStatus & VPCI_STATUS_DRV_OK)) 1311 rc = VERR_NET_NO_BUFFER_SPACE; 1312 else if (!vqueueIsReady(&pState->VPCI, pState->pRxQueue)) 1313 rc = VERR_NET_NO_BUFFER_SPACE; 1314 else if (vqueueIsEmpty(&pState->VPCI, pState->pRxQueue)) 1315 { 1316 vringSetNotification(&pState->VPCI, &pState->pRxQueue->VRing, true); 1317 rc = VERR_NET_NO_BUFFER_SPACE; 1318 } 1319 else 1320 { 1321 vringSetNotification(&pState->VPCI, &pState->pRxQueue->VRing, false); 1322 rc = VINF_SUCCESS; 1323 } 1324 1325 LogFlow(("%s vnetCanReceive -> %Vrc\n", INSTANCE(pState), rc)); 1230 1326 return rc; 1231 1327 }
Note:
See TracChangeset
for help on using the changeset viewer.