Changeset 80340 in vbox for trunk/src/VBox/Devices/Storage
- Timestamp:
- Aug 19, 2019 7:43:37 AM (6 years ago)
- svn:sync-xref-src-repo-rev:
- 132801
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Storage/DevVirtioSCSI.cpp
r80308 r80340 54 54 /** @} */ 55 55 56 #define VIRTIOSCSI_HOST_SCSI_ FEATURES_OFFERED\56 #define VIRTIOSCSI_HOST_SCSI_ALL_FEATURES \ 57 57 (VIRTIOSCSI_F_INOUT | VIRTIOSCSI_F_HOTPLUG | VIRTIOSCSI_F_CHANGE | VIRTIOSCSI_F_T10_PI) 58 58 59 #define VIRTIOSCSI_HOST_SCSI_FEATURES_OFFERED 0 /**< TBD, support at least hotplug & in/out */ 60 59 61 /** 60 62 * TEMPORARY NOTE: following parameter is set to 1 for early development. Will be increased later 61 63 */ 62 64 #define VIRTIOSCSI_REQ_QUEUE_CNT 1 /**< Number of req queues exposed by dev. */ 63 #define VIRTIOSCSI_MAX_TARGETS 1 /**< Can probably determined from higher layers */ 65 #define VIRTIOSCSI_QUEUE_CNT VIRTIOSCSI_REQ_QUEUE_CNT + 2 66 #define VIRTIOSCSI_MAX_TARGETS 1 /**< Can probably determined from higher layers */ 64 67 #define VIRTIOSCSI_MAX_LUN 16383 /* < VirtIO specification, section 5.6.4 */ 65 68 #define VIRTIOSCSI_MAX_COMMANDS_PER_LUN 64 /* < T.B.D. What is a good value for this? */ … … 83 86 * of req queues is variable and determined by virtio_scsi_config.num_queues. See VirtIO 1.0 spec section 5.6.4 84 87 */ 85 #define VIRTIOSCSI_CONTROLQ_IDX 0 /* Index of control queue */ 86 #define VIRTIOSCSI_EVENTQ_IDX 1 /* Index of event queue */ 87 #define VIRTIOSCSI_VIRTQ_REQ_BASE 2 /* Base index of req queues */ 88 89 #define REQ_NBR_TO_QIDX(uReqQueueNum) (VIRTIOSCSI_VIRTQ_REQ_BASE + uReqQueueNum) 90 #define REQ_QIDX_TO_NBR(qIdx) (qIdx - VIRTIOSCSI_VIRTQ_REQ_BASE) 88 #define CONTROLQ_IDX 0 /**< Spec-defined Index of control queue */ 89 #define EVENTQ_IDX 1 /**< Spec-defined Index of event queue */ 90 #define VIRTQ_REQ_BASE 2 /**< Spec-defined base index of request queues */ 91 #define QUEUENAME(qIdx) (pVirtioScsi->szQueueNames[qIdx]) /**< Macro to get queue name from its index */ 92 93 #define IS_REQ_QUEUE(qIdx) ( qIdx >= VIRTQ_REQ_BASE \ 94 && qIdx < VIRTIOSCSI_QUEUE_CNT) 91 95 /** 92 96 * The following struct is the VirtIO SCSI Host Device device-specific configuration described in section 5.6.4 … … 331 335 VIRTIOSCSITARGET aTargetInstances[VIRTIOSCSI_MAX_TARGETS]; 332 336 337 /** Instance name */ 333 338 const char szInstance[16]; 339 340 /** Device-specific spec-based VirtIO queuenames */ 341 const char szQueueNames[VIRTIOSCSI_QUEUE_CNT][VIRTIO_MAX_QUEUE_NAME_SIZE]; 342 343 /** Track which VirtIO queues we've attached to */ 344 bool fQueueAttached[VIRTIOSCSI_QUEUE_CNT]; 334 345 335 346 /** Device base interface. */ 336 347 PDMIBASE IBase; 337 338 348 339 349 /** Pointer to the device instance. - R3 ptr. */ … … 375 385 376 386 VIRTIO_SCSI_CONFIG_T virtioScsiConfig; 387 377 388 378 389 … … 420 431 #define LOG_ACCESSOR(member) \ 421 432 virtioLogMappedIoValue(__FUNCTION__, #member, RT_SIZEOFMEMB(VIRTIO_SCSI_CONFIG_T, member), \ 422 pv, cb, u MemberOffset, fWrite, false, 0);433 pv, cb, uIntraOffset, fWrite, false, 0); 423 434 424 435 #define SCSI_CONFIG_ACCESSOR(member) \ 425 436 { \ 426 uint32_t u MemberOffset = uOffset - RT_UOFFSETOF(VIRTIO_SCSI_CONFIG_T, member); \437 uint32_t uIntraOffset = uOffset - RT_UOFFSETOF(VIRTIO_SCSI_CONFIG_T, member); \ 427 438 if (fWrite) \ 428 memcpy(((char *)&pVirtioScsi->virtioScsiConfig.member) + u MemberOffset, (const char *)pv, cb); \439 memcpy(((char *)&pVirtioScsi->virtioScsiConfig.member) + uIntraOffset, (const char *)pv, cb); \ 429 440 else \ 430 memcpy((char *)pv, (const char *)(((char *)&pVirtioScsi->virtioScsiConfig.member) + u MemberOffset), cb); \441 memcpy((char *)pv, (const char *)(((char *)&pVirtioScsi->virtioScsiConfig.member) + uIntraOffset), cb); \ 431 442 LOG_ACCESSOR(member); \ 432 443 } … … 434 445 #define SCSI_CONFIG_ACCESSOR_READONLY(member) \ 435 446 { \ 436 uint32_t u MemberOffset = uOffset - RT_UOFFSETOF(VIRTIO_SCSI_CONFIG_T, member); \447 uint32_t uIntraOffset = uOffset - RT_UOFFSETOF(VIRTIO_SCSI_CONFIG_T, member); \ 437 448 if (fWrite) \ 438 449 LogFunc(("Guest attempted to write readonly virtio_pci_common_cfg.%s\n", #member)); \ 439 450 else \ 440 451 { \ 441 memcpy((char *)pv, (const char *)(((char *)&pVirtioScsi->virtioScsiConfig.member) + u MemberOffset), cb); \452 memcpy((char *)pv, (const char *)(((char *)&pVirtioScsi->virtioScsiConfig.member) + uIntraOffset), cb); \ 442 453 LOG_ACCESSOR(member); \ 443 454 } \ … … 468 479 #endif 469 480 481 482 483 static void virtioScsiHandleRequestq(VIRTIOHANDLE hVirtio, uint16_t qIdx, const char *pszQueueName) 484 { 485 LogFunc(("\n")); 486 487 PVIRTQ_BUF_VECTOR_T pBufVec = virtioQueueGetBuffer(hVirtio, qIdx); 488 if (pBufVec == NULL) 489 { 490 Log(("\"%s\" not initialized\n", pszQueueName)); 491 return; 492 } 493 494 int rc = virtioQueueGet(hVirtio, qIdx, true); 495 if (rc == VERR_NOT_AVAILABLE) 496 { 497 Log2Func(("Request queue %s is empty\n", pszQueueName)); 498 return; 499 } 500 501 AssertReturnVoid(rc == VINF_SUCCESS); 502 503 Log2Func(("Read request queue, %d segs in, %d segs out\n", 504 pBufVec->cSegsIn, pBufVec->cSegsOut)); 505 } 506 507 static void virtioScsiHandleControlq(VIRTIOHANDLE hVirtio, uint16_t qIdx, const char *pszQueueName) 508 { 509 510 LogFunc( ("\n")); 511 512 PVIRTQ_BUF_VECTOR_T pBufVec = virtioQueueGetBuffer(hVirtio, qIdx); 513 if (pBufVec == NULL) 514 { 515 Log(("\"%s\" not initialized\n", pszQueueName)); 516 return; 517 } 518 519 int rc = virtioQueueGet(hVirtio, qIdx, true); 520 if (rc == VERR_NOT_AVAILABLE) 521 { 522 Log2Func(("Control queue %s is empty\n", pszQueueName)); 523 return; 524 } 525 526 AssertReturnVoid(rc == VINF_SUCCESS); 527 528 Log2Func(("Read control queue, %d segs in, %d segs out\n", 529 pBufVec->cSegsIn, pBufVec->cSegsOut)); 530 } 531 532 static void virtioScsiHandleEventq(VIRTIOHANDLE hVirtio, uint16_t qIdx, const char *pszQueueName) 533 { 534 LogFunc(("\n")); 535 536 PVIRTQ_BUF_VECTOR_T pBufVec = virtioQueueGetBuffer(hVirtio, qIdx); 537 if (pBufVec == NULL) 538 { 539 Log(("\"%s\" not initialized\n", pszQueueName)); 540 return; 541 } 542 543 int rc = virtioQueueGet(hVirtio, qIdx, true); 544 if (rc == VERR_NOT_AVAILABLE) 545 { 546 Log2Func(("Event queue %s is empty\n", pszQueueName)); 547 return; 548 } 549 550 AssertReturnVoid(rc == VINF_SUCCESS); 551 552 Log2Func(("Read event queue, %d segs in, %d segs out\n", 553 pBufVec->cSegsIn, pBufVec->cSegsOut)); 554 } 555 556 static DECLCALLBACK(void) virtioScsiQueueNotified(VIRTIOHANDLE hVirtio, void *pClient, uint16_t qIdx) 557 { 558 AssertReturnVoid(qIdx < VIRTIOSCSI_QUEUE_CNT); 559 PVIRTIOSCSI pVirtioScsi = (PVIRTIOSCSI)pClient; 560 561 if (!pVirtioScsi->fQueueAttached[qIdx]) 562 { 563 int rc = virtioQueueAttach(hVirtio, qIdx, QUEUENAME(qIdx)); 564 pVirtioScsi->fQueueAttached[qIdx] = (rc == VINF_SUCCESS); 565 AssertReturnVoid(pVirtioScsi->fQueueAttached); 566 } 567 568 Log2Func(("%s has available data\n", QUEUENAME(qIdx))); 569 570 if (qIdx == CONTROLQ_IDX) 571 virtioScsiHandleControlq(hVirtio, qIdx, QUEUENAME(qIdx)); 572 else 573 if (qIdx == EVENTQ_IDX) 574 virtioScsiHandleEventq(hVirtio, qIdx, QUEUENAME(qIdx)); 575 else 576 if (IS_REQ_QUEUE(qIdx)) 577 virtioScsiHandleRequestq(hVirtio, qIdx, QUEUENAME(qIdx)); 578 } 579 580 static DECLCALLBACK(void) virtioScsiStatusChanged(VIRTIOHANDLE hVirtio, void *pClient, bool fVirtioReady) 581 { 582 Log2Func(("\n")); 583 RT_NOREF(hVirtio); 584 PVIRTIOSCSI pVirtioScsi = (PVIRTIOSCSI)pClient; 585 if (fVirtioReady) 586 Log2Func(("VirtIO ready\n")); 587 else 588 { 589 Log2Func(("VirtIO is resetting\n")); 590 for (int i = 0; i < VIRTIOSCSI_QUEUE_CNT; i++) 591 pVirtioScsi->fQueueAttached[i] = false; 592 } 593 } 594 470 595 /** 471 596 * Implementation invokes this to reset the VirtIO device … … 476 601 pVirtioScsi->virtioScsiConfig.uCdbSize = VIRTIOSCSI_CDB_SIZE_DEFAULT; 477 602 virtioResetAll(pVirtioScsi->hVirtio); 478 479 603 } 480 604 … … 540 664 } 541 665 542 543 static DECLCALLBACK(void) virtioScsiStatusChanged(VIRTIOHANDLE hVirtio, bool fVirtioReady) 544 { 545 #define MAX_QUEUENAME_SIZE 20 546 Log2Func(("\n")); 547 char pszQueueName[MAX_QUEUENAME_SIZE]; 548 if (fVirtioReady) 549 { 550 Log2Func(("VirtIO reports ready... Initializing queues\n")); 551 virtioQueueAttach(hVirtio, VIRTIOSCSI_CONTROLQ_IDX, "controlq"); 552 virtioQueueAttach(hVirtio, VIRTIOSCSI_EVENTQ_IDX, "eventq"); 553 for (uint16_t qIdx = VIRTIOSCSI_VIRTQ_REQ_BASE; 554 qIdx < VIRTIOSCSI_VIRTQ_REQ_BASE + VIRTIOSCSI_REQ_QUEUE_CNT; 555 qIdx++) 556 { 557 RTStrPrintf(pszQueueName, sizeof(pszQueueName), "requestq_%d", qIdx - 2); 558 bool fEnabled = virtioQueueAttach(hVirtio, qIdx, (const char *)pszQueueName); 559 if (!fEnabled) 560 break; 561 } 562 } else 563 Log2Func(("VirtIO is resetting\n")); 564 } 666 /** 667 * virtio-scsi VirtIO Device-specific capabilities read callback 668 * (other VirtIO capabilities and features are handled in VirtIO implementation) 669 * 670 * @param pDevIns The device instance. 671 * @param uOffset Offset within device specific capabilities struct 672 * @param pv Buffer in which to save read data 673 * @param cb Number of bytes to read 674 */ 675 static DECLCALLBACK(int) virtioScsiR3DevCapRead(PPDMDEVINS pDevIns, uint32_t uOffset, const void *pv, size_t cb) 676 { 677 int rc = VINF_SUCCESS; 678 PVIRTIOSCSI pVirtioScsi = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI); 679 680 // LogFunc(("Read from Device-Specific capabilities: uOffset: 0x%x, cb: 0x%x\n", 681 // uOffset, cb)); 682 683 rc = virtioScsiR3CfgAccessed(pVirtioScsi, uOffset, pv, cb, false); 684 685 return rc; 686 } 687 688 /** 689 * virtio-scsi VirtIO Device-specific capabilities read callback 690 * (other VirtIO capabilities and features are handled in VirtIO implementation) 691 * 692 * @param pDevIns The device instance. 693 * @param uOffset Offset within device specific capabilities struct 694 * @param pv Buffer in which to save read data 695 * @param cb Number of bytes to write 696 */ 697 static DECLCALLBACK(int) virtioScsiR3DevCapWrite(PPDMDEVINS pDevIns, uint32_t uOffset, const void *pv, size_t cb) 698 { 699 int rc = VINF_SUCCESS; 700 PVIRTIOSCSI pVirtioScsi = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI); 701 702 // LogFunc(("Write to Device-Specific capabilities: uOffset: 0x%x, cb: 0x%x\n", 703 // uOffset, cb)); 704 705 rc = virtioScsiR3CfgAccessed(pVirtioScsi, uOffset, pv, cb, true); 706 707 return rc; 708 } 709 565 710 566 711 /** … … 913 1058 914 1059 915 static DECLCALLBACK(void) virtioScsiQueueNotified(VIRTIOHANDLE hVirtio, uint16_t qIdx)916 {917 Log2Func(("virtio callback: %s has avail data\n", virtioQueueGetName(hVirtio, qIdx)));918 }919 920 /**921 * virtio-scsi VirtIO Device-specific capabilities read callback922 * (other VirtIO capabilities and features are handled in VirtIO implementation)923 *924 * @param pDevIns The device instance.925 * @param uOffset Offset within device specific capabilities struct926 * @param pv Buffer in which to save read data927 * @param cb Number of bytes to read928 */929 static DECLCALLBACK(int) virtioScsiR3DevCapRead(PPDMDEVINS pDevIns, uint32_t uOffset, const void *pv, size_t cb)930 {931 int rc = VINF_SUCCESS;932 PVIRTIOSCSI pVirtioScsi = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);933 934 // LogFunc(("Read from Device-Specific capabilities: uOffset: 0x%x, cb: 0x%x\n",935 // uOffset, cb));936 937 rc = virtioScsiR3CfgAccessed(pVirtioScsi, uOffset, pv, cb, false);938 939 return rc;940 }941 942 /**943 * virtio-scsi VirtIO Device-specific capabilities read callback944 * (other VirtIO capabilities and features are handled in VirtIO implementation)945 *946 * @param pDevIns The device instance.947 * @param uOffset Offset within device specific capabilities struct948 * @param pv Buffer in which to save read data949 * @param cb Number of bytes to write950 */951 static DECLCALLBACK(int) virtioScsiR3DevCapWrite(PPDMDEVINS pDevIns, uint32_t uOffset, const void *pv, size_t cb)952 {953 int rc = VINF_SUCCESS;954 PVIRTIOSCSI pVirtioScsi = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);955 956 // LogFunc(("Write to Device-Specific capabilities: uOffset: 0x%x, cb: 0x%x\n",957 // uOffset, cb));958 959 rc = virtioScsiR3CfgAccessed(pVirtioScsi, uOffset, pv, cb, true);960 961 return rc;962 }963 964 965 1060 /** 966 1061 * Memory mapped I/O Handler for read operations. … … 1203 1298 pThis->virtioScsiConfig.uMaxLun = VIRTIOSCSI_MAX_LUN; 1204 1299 1205 rc = virtioConstruct(pDevIns, &pThis->hVirtio, pVirtioPciParams, pThis->szInstance,1300 rc = virtioConstruct(pDevIns, pThis, &pThis->hVirtio, pVirtioPciParams, pThis->szInstance, 1206 1301 VIRTIOSCSI_HOST_SCSI_FEATURES_OFFERED, 1207 1302 virtioScsiR3DevCapRead, … … 1219 1314 return PDMDEV_SET_ERROR(pDevIns, rc, N_("virtio-scsi: failed to initialize VirtIO")); 1220 1315 1316 RTStrCopy((char *)pThis->szQueueNames[CONTROLQ_IDX], VIRTIO_MAX_QUEUE_NAME_SIZE, "controlq"); 1317 RTStrCopy((char *)pThis->szQueueNames[EVENTQ_IDX], VIRTIO_MAX_QUEUE_NAME_SIZE, "eventq"); 1318 for (uint32_t qIdx = VIRTQ_REQ_BASE; qIdx < VIRTQ_REQ_BASE + VIRTIOSCSI_REQ_QUEUE_CNT; qIdx++) 1319 RTStrPrintf((char *)pThis->szQueueNames[qIdx], VIRTIO_MAX_QUEUE_NAME_SIZE, "requestq_%d", qIdx); 1221 1320 1222 1321 rc = PDMDevHlpPCIIORegionRegister(pDevIns, VIRTIOSCSI_REGION_MEM_IO, 32, … … 1274 1373 LogFunc(("Attaching LUN: %s\n", pTarget->pszLunName)); 1275 1374 1276 /* Attach this SCSI driver (upstream driver pre-determined statically outside this module) */1277 1375 AssertReturn(iLUN < RT_ELEMENTS(pThis->aTargetInstances), VERR_PDM_NO_SUCH_LUN); 1278 1376 rc = PDMDevHlpDriverAttach(pDevIns, iLUN, &pTarget->IBase, &pTarget->pDrvBase, (const char *)&pTarget->pszLunName); … … 1281 1379 pTarget->fPresent = true; 1282 1380 1381 /* DrvSCSI.cpp currently implements the IMedia and IMediaEx interfaces, so those 1382 * are the interfaces that will be used to pass SCSI requests down to the 1383 * DrvSCSI driver to eventually make it down to the VD layer */ 1283 1384 pTarget->pDrvMedia = PDMIBASE_QUERY_INTERFACE(pTarget->pDrvBase, PDMIMEDIA); 1284 1385 AssertMsgReturn(VALID_PTR(pTarget->pDrvMedia), … … 1394 1495 PDM_DEVREG_VERSION 1395 1496 }; 1396
Note:
See TracChangeset
for help on using the changeset viewer.