- Timestamp:
- May 8, 2013 8:27:08 PM (12 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Storage/DevLsiLogicSCSI.cpp
r45899 r45959 60 60 #define LSILOGIC_RTGCPHYS_FROM_U32(Hi, Lo) ( (RTGCPHYS)RT_MAKE_U64(Lo, Hi) ) 61 61 62 /** Upper number a buffer is freed if it was too big before. */ 63 #define LSILOGIC_MAX_ALLOC_TOO_MUCH 20 62 64 63 65 /******************************************************************************* 64 66 * Structures and Typedefs * 65 67 *******************************************************************************/ 68 69 /** 70 * I/O buffer copy worker. 71 * 72 * @returns nothing. 73 * @param pDevIns Device instance data. 74 * @param GCPhysIoBuf Guest physical address of the I/O buffer. 75 * @param pvBuf R3 buffer pointer. 76 * @param cbCopy How much to copy. 77 */ 78 typedef DECLCALLBACK(void) FNLSILOGICIOBUFCOPY(PPDMDEVINS pDevIns, RTGCPHYS GCPhysIoBuf, 79 void *pvBuf, size_t cbCopy); 80 /** Pointer to a I/O buffer copy worker. */ 81 typedef FNLSILOGICIOBUFCOPY *PFNLSILOGICIOBUFCOPY; 66 82 67 83 /** … … 121 137 122 138 /** Pointer to a task state. */ 123 typedef struct LSILOGIC TASKSTATE *PLSILOGICTASKSTATE;139 typedef struct LSILOGICREQ *PLSILOGICREQ; 124 140 125 141 /** … … 294 310 bool afPAdding2[HC_ARCH_BITS == 32 ? 2 : 6]; 295 311 /** List of tasks which can be redone. */ 296 R3PTRTYPE(volatile PLSILOGIC TASKSTATE) pTasksRedoHead;312 R3PTRTYPE(volatile PLSILOGICREQ) pTasksRedoHead; 297 313 298 314 } LSILOGISCSI; … … 301 317 302 318 /** 303 * Scatter gather list entry data.304 */305 typedef struct LSILOGICTASKSTATESGENTRY306 {307 /** Flag whether the buffer in the list is from the guest or an308 * allocated temporary buffer because the segments in the guest309 * are not sector aligned.310 */311 bool fGuestMemory;312 /** Flag whether the buffer contains data or is the destination for the transfer. */313 bool fBufferContainsData;314 /** Pointer to the start of the buffer. */315 void *pvBuf;316 /** Size of the buffer. */317 uint32_t cbBuf;318 /** Flag dependent data. */319 union320 {321 /** Data to handle direct mappings of guest buffers. */322 PGMPAGEMAPLOCK PageLock;323 /** The segment in the guest which is not sector aligned. */324 RTGCPHYS GCPhysAddrBufferUnaligned;325 } u;326 } LSILOGICTASKSTATESGENTRY;327 /** Pointer to a scatter/gather list entry. */328 typedef LSILOGICTASKSTATESGENTRY *PLSILOGICTASKSTATESGENTRY;329 330 /**331 319 * Task state object which holds all necessary data while 332 320 * processing the request from the guest. 333 321 */ 334 typedef struct LSILOGIC TASKSTATE322 typedef struct LSILOGICREQ 335 323 { 336 324 /** Next in the redo list. */ 337 PLSILOGIC TASKSTATEpRedoNext;325 PLSILOGICREQ pRedoNext; 338 326 /** Target device. */ 339 327 PLSILOGICDEVICE pTargetDevice; … … 347 335 * Used to read the S/G entries in the second step. */ 348 336 RTGCPHYS GCPhysMessageFrameAddr; 349 /** Number of scatter gather list entries. */ 350 uint32_t cSGListEntries; 351 /** How many entries would fit into the sg list. */ 352 uint32_t cSGListSize; 353 /** How many times the list was too big. */ 354 uint32_t cSGListTooBig; 355 /** Pointer to the first entry of the scatter gather list. */ 356 PRTSGSEG pSGListHead; 357 /** How many entries would fit into the sg info list. */ 358 uint32_t cSGInfoSize; 359 /** Number of entries for the information entries. */ 360 uint32_t cSGInfoEntries; 361 /** How many times the list was too big. */ 362 uint32_t cSGInfoTooBig; 363 /** Pointer to the first mapping information entry. */ 364 PLSILOGICTASKSTATESGENTRY paSGEntries; 365 /** Size of the temporary buffer for unaligned guest segments. */ 366 uint32_t cbBufferUnaligned; 367 /** Pointer to the temporary buffer. */ 368 void *pvBufferUnaligned; 337 /** Physical start address of the S/G list. */ 338 RTGCPHYS GCPhysSgStart; 339 /** Chain offset */ 340 uint32_t cChainOffset; 341 /** Segment describing the I/O buffer. */ 342 RTSGSEG SegIoBuf; 343 /** Additional memory allocation for this task. */ 344 void *pvAlloc; 345 /** Siize of the allocation. */ 346 size_t cbAlloc; 347 /** Number of times we had too much memory allocated for the request. */ 348 unsigned cAllocTooMuch; 369 349 /** Pointer to the sense buffer. */ 370 350 uint8_t abSenseBuffer[18]; 371 351 /** Flag whether the request was issued from the BIOS. */ 372 352 bool fBIOS; 373 } LSILOGIC TASKSTATE;353 } LSILOGICREQ; 374 354 375 355 … … 469 449 } 470 450 else 471 {472 451 Log(("%s: We are already in FAULT state\n")); 473 }474 452 } 475 453 … … 597 575 598 576 PDMCritSectLeave(&pThis->ReplyPostQueueCritSect); 599 }600 601 static void lsilogicR3TaskStateClear(PLSILOGICTASKSTATE pTaskState)602 {603 RTMemFree(pTaskState->pSGListHead);604 RTMemFree(pTaskState->paSGEntries);605 if (pTaskState->pvBufferUnaligned)606 RTMemPageFree(pTaskState->pvBufferUnaligned, pTaskState->cbBufferUnaligned);607 pTaskState->cSGListSize = 0;608 pTaskState->cSGInfoSize = 0;609 pTaskState->cSGInfoEntries = 0;610 pTaskState->cSGListTooBig = 0;611 pTaskState->pSGListHead = NULL;612 pTaskState->paSGEntries = NULL;613 pTaskState->pvBufferUnaligned = NULL;614 pTaskState->cbBufferUnaligned = 0;615 }616 617 /**618 * @callback_method_impl{FNMEMCACHECTOR}619 */620 static DECLCALLBACK(int) lsilogicR3TaskStateCtor(RTMEMCACHE hMemCache, void *pvObj, void *pvUser)621 {622 memset(pvObj, 0, sizeof(LSILOGICTASKSTATE));623 return VINF_SUCCESS;624 }625 626 /**627 * @callback_method_impl{FNMEMCACHEDTOR}628 */629 static DECLCALLBACK(void) lsilogicR3TaskStateDtor(RTMEMCACHE hMemCache, void *pvObj, void *pvUser)630 {631 PLSILOGICTASKSTATE pTaskState = (PLSILOGICTASKSTATE)pvObj;632 lsilogicR3TaskStateClear(pTaskState);633 577 } 634 578 … … 1454 1398 #ifdef IN_RING3 1455 1399 1456 /**1457 * Copies a contiguous buffer into the scatter gather list provided by the guest.1458 *1459 * @returns nothing1460 * @param pTaskState Pointer to the task state which contains the SGL.1461 * @param pvBuf Pointer to the buffer to copy.1462 * @param cbCopy Number of bytes to copy.1463 */1464 static void lsilogicR3ScatterGatherListCopyFromBuffer(PLSILOGICTASKSTATE pTaskState, void *pvBuf, size_t cbCopy)1465 {1466 unsigned cSGEntry = 0;1467 PRTSGSEG pSGEntry = &pTaskState->pSGListHead[cSGEntry];1468 uint8_t *pu8Buf = (uint8_t *)pvBuf;1469 1470 while (cSGEntry < pTaskState->cSGListEntries)1471 {1472 size_t cbToCopy = (cbCopy < pSGEntry->cbSeg) ? cbCopy : pSGEntry->cbSeg;1473 1474 memcpy(pSGEntry->pvSeg, pu8Buf, cbToCopy);1475 1476 cbCopy -= cbToCopy;1477 /* We finished. */1478 if (!cbCopy)1479 break;1480 1481 /* Advance the buffer. */1482 pu8Buf += cbToCopy;1483 1484 /* Go to the next entry in the list. */1485 pSGEntry++;1486 cSGEntry++;1487 }1488 }1489 1490 /**1491 * Copy a temporary buffer into a part of the guest scatter gather list1492 * described by the given descriptor entry.1493 *1494 * @returns nothing.1495 * @param pDevIns Pointer to the device instance data.1496 * @param pSGInfo Pointer to the segment info structure which describes the guest segments1497 * to write to which are unaligned.1498 */1499 static void lsilogicR3CopyFromBufferIntoSGList(PPDMDEVINS pDevIns, PLSILOGICTASKSTATESGENTRY pSGInfo)1500 {1501 RTGCPHYS GCPhysBuffer = pSGInfo->u.GCPhysAddrBufferUnaligned;1502 1503 AssertMsg(!pSGInfo->fGuestMemory, ("This is not possible\n"));1504 1505 /* Copy into SG entry. */1506 PDMDevHlpPCIPhysWrite(pDevIns, GCPhysBuffer, pSGInfo->pvBuf, pSGInfo->cbBuf);1507 1508 }1509 1510 /**1511 * Copy a part of the guest scatter gather list into a temporary buffer.1512 *1513 * @returns nothing.1514 * @param pDevIns Pointer to the device instance data.1515 * @param pSGInfo Pointer to the segment info structure which describes the guest segments1516 * to read from which are unaligned.1517 */1518 static void lsilogicR3CopyFromSGListIntoBuffer(PPDMDEVINS pDevIns, PLSILOGICTASKSTATESGENTRY pSGInfo)1519 {1520 RTGCPHYS GCPhysBuffer = pSGInfo->u.GCPhysAddrBufferUnaligned;1521 1522 AssertMsg(!pSGInfo->fGuestMemory, ("This is not possible\n"));1523 1524 /* Copy into temporary buffer. */1525 PDMDevHlpPhysRead(pDevIns, GCPhysBuffer, pSGInfo->pvBuf, pSGInfo->cbBuf);1526 }1527 1528 static int lsilogicR3ScatterGatherListAllocate(PLSILOGICTASKSTATE pTaskState, uint32_t cSGList, uint32_t cSGInfo, uint32_t cbUnaligned)1529 {1530 if (pTaskState->cSGListSize < cSGList)1531 {1532 /* The entries are not allocated yet or the number is too small. */1533 if (pTaskState->cSGListSize)1534 RTMemFree(pTaskState->pSGListHead);1535 1536 /* Allocate R3 scatter gather list. */1537 pTaskState->pSGListHead = (PRTSGSEG)RTMemAllocZ(cSGList * sizeof(RTSGSEG));1538 if (!pTaskState->pSGListHead)1539 return VERR_NO_MEMORY;1540 1541 /* Reset usage statistics. */1542 pTaskState->cSGListSize = cSGList;1543 pTaskState->cSGListEntries = cSGList;1544 pTaskState->cSGListTooBig = 0;1545 }1546 else if (pTaskState->cSGListSize > cSGList)1547 {1548 /*1549 * The list is too big. Increment counter.1550 * So that the destroying function can free1551 * the list if it is too big too many times1552 * in a row.1553 */1554 pTaskState->cSGListEntries = cSGList;1555 pTaskState->cSGListTooBig++;1556 }1557 else1558 {1559 /*1560 * Needed entries matches current size.1561 * Reset counter.1562 */1563 pTaskState->cSGListEntries = cSGList;1564 pTaskState->cSGListTooBig = 0;1565 }1566 1567 if (pTaskState->cSGInfoSize < cSGInfo)1568 {1569 /* The entries are not allocated yet or the number is too small. */1570 if (pTaskState->cSGInfoSize)1571 RTMemFree(pTaskState->paSGEntries);1572 1573 pTaskState->paSGEntries = (PLSILOGICTASKSTATESGENTRY)RTMemAllocZ(cSGInfo * sizeof(LSILOGICTASKSTATESGENTRY));1574 if (!pTaskState->paSGEntries)1575 return VERR_NO_MEMORY;1576 1577 /* Reset usage statistics. */1578 pTaskState->cSGInfoSize = cSGInfo;1579 pTaskState->cSGInfoEntries = cSGInfo;1580 pTaskState->cSGInfoTooBig = 0;1581 }1582 else if (pTaskState->cSGInfoSize > cSGInfo)1583 {1584 /*1585 * The list is too big. Increment counter.1586 * So that the destroying function can free1587 * the list if it is too big too many times1588 * in a row.1589 */1590 pTaskState->cSGInfoEntries = cSGInfo;1591 pTaskState->cSGInfoTooBig++;1592 }1593 else1594 {1595 /*1596 * Needed entries matches current size.1597 * Reset counter.1598 */1599 pTaskState->cSGInfoEntries = cSGInfo;1600 pTaskState->cSGInfoTooBig = 0;1601 }1602 1603 1604 if (pTaskState->cbBufferUnaligned < cbUnaligned)1605 {1606 if (pTaskState->pvBufferUnaligned)1607 RTMemPageFree(pTaskState->pvBufferUnaligned, pTaskState->cbBufferUnaligned);1608 1609 Log(("%s: Allocating buffer for unaligned segments cbUnaligned=%u\n", __FUNCTION__, cbUnaligned));1610 1611 pTaskState->pvBufferUnaligned = RTMemPageAlloc(cbUnaligned);1612 if (!pTaskState->pvBufferUnaligned)1613 return VERR_NO_MEMORY;1614 1615 pTaskState->cbBufferUnaligned = cbUnaligned;1616 }1617 1618 /* Make debugging easier. */1619 # ifdef LOG_ENABLED1620 memset(pTaskState->pSGListHead, 0, pTaskState->cSGListSize * sizeof(RTSGSEG));1621 memset(pTaskState->paSGEntries, 0, pTaskState->cSGInfoSize * sizeof(LSILOGICTASKSTATESGENTRY));1622 if (pTaskState->pvBufferUnaligned)1623 memset(pTaskState->pvBufferUnaligned, 0, pTaskState->cbBufferUnaligned);1624 # endif1625 return VINF_SUCCESS;1626 }1627 1628 /**1629 * Destroy a scatter gather list.1630 *1631 * @returns nothing.1632 * @param pThis Pointer to the LsiLogic device state.1633 * @param pTaskState Pointer to the task state.1634 */1635 static void lsilogicR3ScatterGatherListDestroy(PLSILOGICSCSI pThis, PLSILOGICTASKSTATE pTaskState)1636 {1637 PPDMDEVINS pDevIns = pThis->CTX_SUFF(pDevIns);1638 PLSILOGICTASKSTATESGENTRY pSGInfoCurr = pTaskState->paSGEntries;1639 1640 for (unsigned i = 0; i < pTaskState->cSGInfoEntries; i++)1641 {1642 if (pSGInfoCurr->fGuestMemory)1643 {1644 /* Release the lock. */1645 PDMDevHlpPhysReleasePageMappingLock(pDevIns, &pSGInfoCurr->u.PageLock);1646 }1647 else if (!pSGInfoCurr->fBufferContainsData)1648 {1649 /* Copy the data into the guest segments now. */1650 lsilogicR3CopyFromBufferIntoSGList(pThis->CTX_SUFF(pDevIns), pSGInfoCurr);1651 }1652 1653 pSGInfoCurr++;1654 }1655 1656 /* Free allocated memory if the list was too big too many times. */1657 if (pTaskState->cSGListTooBig >= LSILOGIC_NR_OF_ALLOWED_BIGGER_LISTS)1658 lsilogicR3TaskStateClear(pTaskState);1659 }1660 1661 1400 # ifdef LOG_ENABLED 1662 1401 /** … … 1716 1455 # endif /* LOG_ENABLED */ 1717 1456 1718 /** 1719 * Create scatter gather list descriptors. 1457 static void lsilogicSgBufWalker(PPDMDEVINS pDevIns, PLSILOGICREQ pLsiReq, size_t cbCopy, 1458 PFNLSILOGICIOBUFCOPY pfnIoBufCopy) 1459 { 1460 bool fEndOfList = false; 1461 RTGCPHYS GCPhysSgEntryNext = pLsiReq->GCPhysSgStart; 1462 RTGCPHYS GCPhysSegmentStart = pLsiReq->GCPhysSgStart; 1463 uint32_t cChainOffsetNext = pLsiReq->cChainOffset; 1464 uint8_t *pbBuf = (uint8_t *)pLsiReq->SegIoBuf.pvSeg; 1465 1466 /* Go through the list until we reach the end. */ 1467 while ( !fEndOfList 1468 && cbCopy) 1469 { 1470 bool fEndOfSegment = false; 1471 1472 while ( !fEndOfSegment 1473 && cbCopy) 1474 { 1475 MptSGEntryUnion SGEntry; 1476 1477 Log(("%s: Reading SG entry from %RGp\n", __FUNCTION__, GCPhysSgEntryNext)); 1478 1479 /* Read the entry. */ 1480 PDMDevHlpPhysRead(pDevIns, GCPhysSgEntryNext, &SGEntry, sizeof(MptSGEntryUnion)); 1481 1482 # ifdef LOG_ENABLED 1483 lsilogicDumpSGEntry(&SGEntry); 1484 # endif 1485 1486 AssertMsg(SGEntry.Simple32.u2ElementType == MPTSGENTRYTYPE_SIMPLE, ("Invalid SG entry type\n")); 1487 1488 /* Check if this is a zero element and abort. */ 1489 if ( !SGEntry.Simple32.u24Length 1490 && SGEntry.Simple32.fEndOfList 1491 && SGEntry.Simple32.fEndOfBuffer) 1492 return; 1493 1494 uint32_t cbCopyThis = SGEntry.Simple32.u24Length; 1495 RTGCPHYS GCPhysAddrDataBuffer = SGEntry.Simple32.u32DataBufferAddressLow; 1496 1497 if (SGEntry.Simple32.f64BitAddress) 1498 { 1499 GCPhysAddrDataBuffer |= ((uint64_t)SGEntry.Simple64.u32DataBufferAddressHigh) << 32; 1500 GCPhysSgEntryNext += sizeof(MptSGEntrySimple64); 1501 } 1502 else 1503 GCPhysSgEntryNext += sizeof(MptSGEntrySimple32); 1504 1505 1506 pfnIoBufCopy(pDevIns, GCPhysAddrDataBuffer, pbBuf, cbCopyThis); 1507 pbBuf += cbCopyThis; 1508 cbCopyThis -= cbCopyThis; 1509 1510 /* Check if we reached the end of the list. */ 1511 if (SGEntry.Simple32.fEndOfList) 1512 { 1513 /* We finished. */ 1514 fEndOfSegment = true; 1515 fEndOfList = true; 1516 } 1517 else if (SGEntry.Simple32.fLastElement) 1518 fEndOfSegment = true; 1519 } /* while (!fEndOfSegment) */ 1520 1521 /* Get next chain element. */ 1522 if (cChainOffsetNext) 1523 { 1524 MptSGEntryChain SGEntryChain; 1525 1526 PDMDevHlpPhysRead(pDevIns, GCPhysSegmentStart + cChainOffsetNext, &SGEntryChain, sizeof(MptSGEntryChain)); 1527 1528 AssertMsg(SGEntryChain.u2ElementType == MPTSGENTRYTYPE_CHAIN, ("Invalid SG entry type\n")); 1529 1530 /* Set the next address now. */ 1531 GCPhysSgEntryNext = SGEntryChain.u32SegmentAddressLow; 1532 if (SGEntryChain.f64BitAddress) 1533 GCPhysSgEntryNext |= ((uint64_t)SGEntryChain.u32SegmentAddressHigh) << 32; 1534 1535 GCPhysSegmentStart = GCPhysSgEntryNext; 1536 cChainOffsetNext = SGEntryChain.u8NextChainOffset * sizeof(uint32_t); 1537 } 1538 } /* while (!fEndOfList) */ 1539 } 1540 1541 static DECLCALLBACK(void) lsilogicCopyFromGuest(PPDMDEVINS pDevIns, RTGCPHYS GCPhysIoBuf, 1542 void *pvBuf, size_t cbCopy) 1543 { 1544 PDMDevHlpPhysRead(pDevIns, GCPhysIoBuf, pvBuf, cbCopy); 1545 } 1546 1547 static DECLCALLBACK(void) lsilogicCopyToGuest(PPDMDEVINS pDevIns, RTGCPHYS GCPhysIoBuf, 1548 void *pvBuf, size_t cbCopy) 1549 { 1550 PDMDevHlpPCIPhysWrite(pDevIns, GCPhysIoBuf, pvBuf, cbCopy); 1551 } 1552 1553 /** 1554 * Copy from a guest S/G buffer to the I/O buffer. 1555 * 1556 * @returns nothing. 1557 * @param pDevIns Device instance data. 1558 * @param pLsiReq Request data. 1559 * @param cbCopy How much to copy over. 1560 */ 1561 DECLINLINE(void) lsilogicCopyFromSgBuf(PPDMDEVINS pDevIns, PLSILOGICREQ pLsiReq, size_t cbCopy) 1562 { 1563 lsilogicSgBufWalker(pDevIns, pLsiReq, cbCopy, lsilogicCopyFromGuest); 1564 } 1565 1566 /** 1567 * Copy from an I/O buffer to the guest S/G buffer. 1568 * 1569 * @returns nothing. 1570 * @param pDevIns Device instance data. 1571 * @param pLsiReq Request data. 1572 * @param cbCopy How much to copy over. 1573 */ 1574 DECLINLINE(void) lsilogicCopyToSgBuf(PPDMDEVINS pDevIns, PLSILOGICREQ pLsiReq, size_t cbCopy) 1575 { 1576 lsilogicSgBufWalker(pDevIns, pLsiReq, cbCopy, lsilogicCopyToGuest); 1577 } 1578 1579 /** 1580 * Allocates memory for the given request using already allocated memory if possible. 1581 * 1582 * @returns Pointer to the memory or NULL on failure 1583 * @param pLsiReq The request to allocate memory for. 1584 * @param cb The amount of memory to allocate. 1585 */ 1586 static void *lsilogicReqMemAlloc(PLSILOGICREQ pLsiReq, size_t cb) 1587 { 1588 if (pLsiReq->cbAlloc > cb) 1589 pLsiReq->cAllocTooMuch++; 1590 else if (pLsiReq->cbAlloc < cb) 1591 { 1592 if (pLsiReq->cbAlloc) 1593 RTMemPageFree(pLsiReq->pvAlloc, pLsiReq->cbAlloc); 1594 1595 pLsiReq->cbAlloc = RT_ALIGN_Z(cb, _4K); 1596 pLsiReq->pvAlloc = RTMemPageAlloc(pLsiReq->cbAlloc); 1597 pLsiReq->cAllocTooMuch = 0; 1598 if (RT_UNLIKELY(!pLsiReq->pvAlloc)) 1599 pLsiReq->cbAlloc = 0; 1600 } 1601 1602 return pLsiReq->pvAlloc; 1603 } 1604 1605 /** 1606 * Frees memory allocated for the given request. 1607 * 1608 * @returns nothing. 1609 * @param pLsiReq The request. 1610 */ 1611 static void lsilogicReqMemFree(PLSILOGICREQ pLsiReq) 1612 { 1613 if (pLsiReq->cAllocTooMuch >= LSILOGIC_MAX_ALLOC_TOO_MUCH) 1614 { 1615 RTMemPageFree(pLsiReq->pvAlloc, pLsiReq->cbAlloc); 1616 pLsiReq->cbAlloc = 0; 1617 pLsiReq->cAllocTooMuch = 0; 1618 } 1619 } 1620 1621 /** 1622 * Allocate I/O memory and copies the guest buffer for writes. 1720 1623 * 1721 1624 * @returns VBox status code. 1722 * @param pThis Pointer to the LsiLogic device state. 1723 * @param pTaskState Pointer to the task state. 1724 * @param GCPhysSGLStart Guest physical address of the first SG entry. 1725 * @param uChainOffset Offset in bytes from the beginning of the SGL segment to the chain element. 1726 * @thread EMT 1727 */ 1728 static int lsilogicR3ScatterGatherListCreate(PLSILOGICSCSI pThis, PLSILOGICTASKSTATE pTaskState, 1729 RTGCPHYS GCPhysSGLStart, uint32_t uChainOffset) 1730 { 1731 int rc = VINF_SUCCESS; 1732 PPDMDEVINS pDevIns = pThis->CTX_SUFF(pDevIns); 1733 PVM pVM = PDMDevHlpGetVM(pDevIns); 1734 bool fUnaligned; /* Flag whether the current buffer is unaligned. */ 1735 uint32_t cbUnaligned; /* Size of the unaligned buffers. */ 1736 uint32_t cSGEntriesR3 = 0; 1737 uint32_t cSGInfo = 0; 1738 uint32_t cbSegment = 0; 1739 PLSILOGICTASKSTATESGENTRY pSGInfoCurr = NULL; 1740 uint8_t *pu8BufferUnalignedPos = NULL; 1741 uint8_t *pbBufferUnalignedSGInfoPos = NULL; 1742 uint32_t cbUnalignedComplete = 0; 1743 bool fDoMapping = false; 1744 bool fEndOfList; 1745 RTGCPHYS GCPhysSGEntryNext; 1746 RTGCPHYS GCPhysSegmentStart; 1747 uint32_t uChainOffsetNext; 1748 1749 /* 1750 * Two passes - one to count needed scatter gather list entries and needed unaligned 1751 * buffers and one to actually map the SG list into R3. 1752 */ 1753 for (int i = 0; i < 2; i++) 1754 { 1755 fUnaligned = false; 1756 cbUnaligned = 0; 1757 fEndOfList = false; 1758 1759 GCPhysSGEntryNext = GCPhysSGLStart; 1760 uChainOffsetNext = uChainOffset; 1761 GCPhysSegmentStart = GCPhysSGLStart; 1762 1763 if (fDoMapping) 1764 { 1765 Log(("%s: cSGInfo=%u\n", __FUNCTION__, cSGInfo)); 1766 1767 /* The number of needed SG entries in R3 is known. Allocate needed memory. */ 1768 rc = lsilogicR3ScatterGatherListAllocate(pTaskState, cSGInfo, cSGInfo, cbUnalignedComplete); 1769 AssertMsgRC(rc, ("Failed to allocate scatter gather array rc=%Rrc\n", rc)); 1770 1771 /* We are now able to map the pages into R3. */ 1772 pSGInfoCurr = pTaskState->paSGEntries; 1773 /* Initialize first segment to remove the need for additional if checks later in the code. */ 1774 pSGInfoCurr->fGuestMemory= false; 1775 pu8BufferUnalignedPos = (uint8_t *)pTaskState->pvBufferUnaligned; 1776 pbBufferUnalignedSGInfoPos = pu8BufferUnalignedPos; 1777 } 1778 1779 /* Go through the list until we reach the end. */ 1780 while (!fEndOfList) 1781 { 1782 bool fEndOfSegment = false; 1783 1784 while (!fEndOfSegment) 1785 { 1786 MptSGEntryUnion SGEntry; 1787 1788 Log(("%s: Reading SG entry from %RGp\n", __FUNCTION__, GCPhysSGEntryNext)); 1789 1790 /* Read the entry. */ 1791 PDMDevHlpPhysRead(pDevIns, GCPhysSGEntryNext, &SGEntry, sizeof(MptSGEntryUnion)); 1792 1793 # ifdef LOG_ENABLED 1794 lsilogicDumpSGEntry(&SGEntry); 1795 # endif 1796 1797 AssertMsg(SGEntry.Simple32.u2ElementType == MPTSGENTRYTYPE_SIMPLE, ("Invalid SG entry type\n")); 1798 1799 /* Check if this is a zero element. */ 1800 if ( !SGEntry.Simple32.u24Length 1801 && SGEntry.Simple32.fEndOfList 1802 && SGEntry.Simple32.fEndOfBuffer) 1803 { 1804 pTaskState->cSGListEntries = 0; 1805 pTaskState->cSGInfoEntries = 0; 1806 return VINF_SUCCESS; 1807 } 1808 1809 uint32_t cbDataToTransfer = SGEntry.Simple32.u24Length; 1810 bool fBufferContainsData = !!SGEntry.Simple32.fBufferContainsData; 1811 RTGCPHYS GCPhysAddrDataBuffer = SGEntry.Simple32.u32DataBufferAddressLow; 1812 1813 if (SGEntry.Simple32.f64BitAddress) 1814 { 1815 GCPhysAddrDataBuffer |= ((uint64_t)SGEntry.Simple64.u32DataBufferAddressHigh) << 32; 1816 GCPhysSGEntryNext += sizeof(MptSGEntrySimple64); 1817 } 1818 else 1819 GCPhysSGEntryNext += sizeof(MptSGEntrySimple32); 1820 1821 if (fDoMapping) 1822 { 1823 pSGInfoCurr->fGuestMemory = false; 1824 pSGInfoCurr->fBufferContainsData = fBufferContainsData; 1825 pSGInfoCurr->cbBuf = cbDataToTransfer; 1826 pSGInfoCurr->pvBuf = pbBufferUnalignedSGInfoPos; 1827 pbBufferUnalignedSGInfoPos += cbDataToTransfer; 1828 pSGInfoCurr->u.GCPhysAddrBufferUnaligned = GCPhysAddrDataBuffer; 1829 if (fBufferContainsData) 1830 lsilogicR3CopyFromSGListIntoBuffer(pDevIns, pSGInfoCurr); 1831 pSGInfoCurr++; 1832 } 1833 else 1834 { 1835 cbUnalignedComplete += cbDataToTransfer; 1836 cSGInfo++; 1837 } 1838 1839 /* Check if we reached the end of the list. */ 1840 if (SGEntry.Simple32.fEndOfList) 1841 { 1842 /* We finished. */ 1843 fEndOfSegment = true; 1844 fEndOfList = true; 1845 } 1846 else if (SGEntry.Simple32.fLastElement) 1847 { 1848 fEndOfSegment = true; 1849 } 1850 } /* while (!fEndOfSegment) */ 1851 1852 /* Get next chain element. */ 1853 if (uChainOffsetNext) 1854 { 1855 MptSGEntryChain SGEntryChain; 1856 1857 PDMDevHlpPhysRead(pDevIns, GCPhysSegmentStart + uChainOffsetNext, &SGEntryChain, sizeof(MptSGEntryChain)); 1858 1859 AssertMsg(SGEntryChain.u2ElementType == MPTSGENTRYTYPE_CHAIN, ("Invalid SG entry type\n")); 1860 1861 /* Set the next address now. */ 1862 GCPhysSGEntryNext = SGEntryChain.u32SegmentAddressLow; 1863 if (SGEntryChain.f64BitAddress) 1864 GCPhysSGEntryNext |= ((uint64_t)SGEntryChain.u32SegmentAddressHigh) << 32; 1865 1866 GCPhysSegmentStart = GCPhysSGEntryNext; 1867 uChainOffsetNext = SGEntryChain.u8NextChainOffset * sizeof(uint32_t); 1868 } 1869 1870 } /* while (!fEndOfList) */ 1871 1872 fDoMapping = true; 1873 if (fUnaligned) 1874 cbUnalignedComplete += cbUnaligned; 1875 } 1876 1877 uint32_t cSGEntries; 1878 PRTSGSEG pSGEntryCurr = pTaskState->pSGListHead; 1879 pSGInfoCurr = pTaskState->paSGEntries; 1880 1881 /* Initialize first entry. */ 1882 pSGEntryCurr->pvSeg = pSGInfoCurr->pvBuf; 1883 pSGEntryCurr->cbSeg = pSGInfoCurr->cbBuf; 1884 pSGInfoCurr++; 1885 cSGEntries = 1; 1886 1887 /* Construct the scatter gather list. */ 1888 for (unsigned i = 0; i < (pTaskState->cSGInfoEntries-1); i++) 1889 { 1890 if (pSGEntryCurr->cbSeg % 512 != 0) 1891 { 1892 AssertMsg((uint8_t *)pSGEntryCurr->pvSeg + pSGEntryCurr->cbSeg == pSGInfoCurr->pvBuf, 1893 ("Buffer ist not sector aligned but the buffer addresses are not adjacent\n")); 1894 1895 pSGEntryCurr->cbSeg += pSGInfoCurr->cbBuf; 1896 } 1897 else 1898 { 1899 if (((uint8_t *)pSGEntryCurr->pvSeg + pSGEntryCurr->cbSeg) == pSGInfoCurr->pvBuf) 1900 { 1901 pSGEntryCurr->cbSeg += pSGInfoCurr->cbBuf; 1902 } 1903 else 1904 { 1905 pSGEntryCurr++; 1906 cSGEntries++; 1907 pSGEntryCurr->pvSeg = pSGInfoCurr->pvBuf; 1908 pSGEntryCurr->cbSeg = pSGInfoCurr->cbBuf; 1909 } 1910 } 1911 1912 pSGInfoCurr++; 1913 } 1914 1915 pTaskState->cSGListEntries = cSGEntries; 1916 1917 return rc; 1918 } 1919 1920 /* 1921 * Disabled because the sense buffer provided by the LsiLogic driver for Windows XP 1922 * crosses page boundaries. 1923 */ 1924 # if 0 1925 /** 1926 * Free the sense buffer. 1625 * @param pDevIns The device instance. 1626 * @param pLsiReq The request state. 1627 * @param cbTransfer Amount of bytes to allocate. 1628 */ 1629 static int lsilogicIoBufAllocate(PPDMDEVINS pDevIns, PLSILOGICREQ pLsiReq, 1630 size_t cbTransfer) 1631 { 1632 uint8_t uTxDir = MPT_SCSIIO_REQUEST_CONTROL_TXDIR_GET(pLsiReq->GuestRequest.SCSIIO.u32Control); 1633 1634 AssertMsg( uTxDir == MPT_SCSIIO_REQUEST_CONTROL_TXDIR_WRITE 1635 || uTxDir == MPT_SCSIIO_REQUEST_CONTROL_TXDIR_READ, 1636 ("Allocating I/O memory for a non I/O request is not allowed\n")); 1637 1638 pLsiReq->SegIoBuf.pvSeg = lsilogicReqMemAlloc(pLsiReq, cbTransfer); 1639 if (!pLsiReq->SegIoBuf.pvSeg) 1640 return VERR_NO_MEMORY; 1641 1642 pLsiReq->SegIoBuf.cbSeg = cbTransfer; 1643 if (uTxDir == MPT_SCSIIO_REQUEST_CONTROL_TXDIR_WRITE) 1644 lsilogicCopyFromSgBuf(pDevIns, pLsiReq, cbTransfer); 1645 1646 return VINF_SUCCESS; 1647 } 1648 1649 /** 1650 * Frees the I/O memory of the given request and updates the guest buffer if necessary. 1927 1651 * 1928 1652 * @returns nothing. 1929 * @param pTaskState Pointer to the task state. 1930 */ 1931 static void lsilogicFreeGCSenseBuffer(PLSILOGICSCSI pThis, PLSILOGICTASKSTATE pTaskState) 1932 { 1933 PVM pVM = PDMDevHlpGetVM(pThis->CTX_SUFF(pDevIns)); 1934 1935 PGMPhysReleasePageMappingLock(pVM, &pTaskState->PageLockSense); 1936 pTaskState->pbSenseBuffer = NULL; 1937 } 1938 1939 /** 1940 * Map the sense buffer into R3. 1941 * 1942 * @returns VBox status code. 1943 * @param pTaskState Pointer to the task state. 1944 * @note Current assumption is that the sense buffer is not scattered and does not cross a page boundary. 1945 */ 1946 static int lsilogicR3MapGCSenseBufferIntoR3(PLSILOGICSCSI pThis, PLSILOGICTASKSTATE pTaskState) 1947 { 1948 int rc = VINF_SUCCESS; 1949 PPDMDEVINS pDevIns = pThis->CTX_SUFF(pDevIns); 1950 RTGCPHYS GCPhysAddrSenseBuffer; 1951 1952 GCPhysAddrSenseBuffer = pTaskState->GuestRequest.SCSIIO.u32SenseBufferLowAddress; 1953 GCPhysAddrSenseBuffer |= ((uint64_t)pThis->u32SenseBufferHighAddr << 32); 1954 1955 # ifdef RT_STRICT 1956 uint32_t cbSenseBuffer = pTaskState->GuestRequest.SCSIIO.u8SenseBufferLength; 1957 # endif 1958 RTGCPHYS GCPhysAddrSenseBufferBase = PAGE_ADDRESS(GCPhysAddrSenseBuffer); 1959 1960 AssertMsg(GCPhysAddrSenseBuffer >= GCPhysAddrSenseBufferBase, 1961 ("Impossible GCPhysAddrSenseBuffer < GCPhysAddrSenseBufferBase\n")); 1962 1963 /* Sanity checks for the assumption. */ 1964 AssertMsg(((GCPhysAddrSenseBuffer + cbSenseBuffer) <= (GCPhysAddrSenseBufferBase + PAGE_SIZE)), 1965 ("Sense buffer crosses page boundary\n")); 1966 1967 rc = PDMDevHlpPhysGCPhys2CCPtr(pDevIns, GCPhysAddrSenseBufferBase, (void **)&pTaskState->pbSenseBuffer, &pTaskState->PageLockSense); 1968 AssertMsgRC(rc, ("Mapping sense buffer failed rc=%Rrc\n", rc)); 1969 1970 /* Correct start address of the sense buffer. */ 1971 pTaskState->pbSenseBuffer += (GCPhysAddrSenseBuffer - GCPhysAddrSenseBufferBase); 1972 1973 return rc; 1974 } 1975 # endif 1653 * @param pDevIns The device instance. 1654 * @param pLsiReq The request state. 1655 * @param fCopyToGuest Flag whether to update the guest buffer if necessary. 1656 * Nothing is copied if false even if the request was a read. 1657 */ 1658 static void lsilogicIoBufFree(PPDMDEVINS pDevIns, PLSILOGICREQ pLsiReq, 1659 bool fCopyToGuest) 1660 { 1661 uint8_t uTxDir = MPT_SCSIIO_REQUEST_CONTROL_TXDIR_GET(pLsiReq->GuestRequest.SCSIIO.u32Control); 1662 1663 AssertMsg( uTxDir == MPT_SCSIIO_REQUEST_CONTROL_TXDIR_WRITE 1664 || uTxDir == MPT_SCSIIO_REQUEST_CONTROL_TXDIR_READ, 1665 ("Allocating I/O memory for a non I/O request is not allowed\n")); 1666 1667 if ( uTxDir == MPT_SCSIIO_REQUEST_CONTROL_TXDIR_READ 1668 && fCopyToGuest) 1669 lsilogicCopyToSgBuf(pDevIns, pLsiReq, pLsiReq->SegIoBuf.cbSeg); 1670 1671 lsilogicReqMemFree(pLsiReq); 1672 pLsiReq->SegIoBuf.pvSeg = NULL; 1673 pLsiReq->SegIoBuf.cbSeg = 0; 1674 } 1976 1675 1977 1676 # ifdef LOG_ENABLED … … 2060 1759 * @returns VBox status code. 2061 1760 * @param pThis Pointer to the LsiLogic device state. 2062 * @param p TaskStatePointer to the task state data.2063 */ 2064 static int lsilogicR3ProcessSCSIIORequest(PLSILOGICSCSI pThis, PLSILOGIC TASKSTATE pTaskState)1761 * @param pLsiReq Pointer to the task state data. 1762 */ 1763 static int lsilogicR3ProcessSCSIIORequest(PLSILOGICSCSI pThis, PLSILOGICREQ pLsiReq) 2065 1764 { 2066 1765 int rc = VINF_SUCCESS; 2067 1766 2068 1767 # ifdef LOG_ENABLED 2069 lsilogicR3DumpSCSIIORequest(&p TaskState->GuestRequest.SCSIIO);1768 lsilogicR3DumpSCSIIORequest(&pLsiReq->GuestRequest.SCSIIO); 2070 1769 # endif 2071 1770 2072 pTaskState->fBIOS = false; 2073 2074 if (RT_LIKELY( (pTaskState->GuestRequest.SCSIIO.u8TargetID < pThis->cDeviceStates) 2075 && (pTaskState->GuestRequest.SCSIIO.u8Bus == 0))) 1771 pLsiReq->fBIOS = false; 1772 pLsiReq->GCPhysSgStart = pLsiReq->GCPhysMessageFrameAddr + sizeof(MptSCSIIORequest); 1773 pLsiReq->cChainOffset = pLsiReq->GuestRequest.SCSIIO.u8ChainOffset; 1774 if (pLsiReq->cChainOffset) 1775 pLsiReq->cChainOffset = pLsiReq->cChainOffset * sizeof(uint32_t) - sizeof(MptSCSIIORequest); 1776 1777 if (RT_LIKELY( (pLsiReq->GuestRequest.SCSIIO.u8TargetID < pThis->cDeviceStates) 1778 && (pLsiReq->GuestRequest.SCSIIO.u8Bus == 0))) 2076 1779 { 2077 1780 PLSILOGICDEVICE pTargetDevice; 2078 pTargetDevice = &pThis->paDeviceStates[p TaskState->GuestRequest.SCSIIO.u8TargetID];1781 pTargetDevice = &pThis->paDeviceStates[pLsiReq->GuestRequest.SCSIIO.u8TargetID]; 2079 1782 2080 1783 if (pTargetDevice->pDrvBase) 2081 1784 { 2082 1785 2083 if (p TaskState->GuestRequest.SCSIIO.u32DataLength)1786 if (pLsiReq->GuestRequest.SCSIIO.u32DataLength) 2084 1787 { 2085 uint32_t uChainOffset; 2086 2087 /* Create Scatter gather list. */ 2088 uChainOffset = pTaskState->GuestRequest.SCSIIO.u8ChainOffset; 2089 2090 if (uChainOffset) 2091 uChainOffset = uChainOffset * sizeof(uint32_t) - sizeof(MptSCSIIORequest); 2092 2093 rc = lsilogicR3ScatterGatherListCreate(pThis, pTaskState, 2094 pTaskState->GCPhysMessageFrameAddr + sizeof(MptSCSIIORequest), 2095 uChainOffset); 2096 AssertRC(rc); 1788 1789 rc = lsilogicIoBufAllocate(pThis->CTX_SUFF(pDevIns), pLsiReq, 1790 pLsiReq->GuestRequest.SCSIIO.u32DataLength); 1791 AssertRC(rc); /** @todo: Insufficient resources error. */ 1792 } 1793 1794 /* Setup the SCSI request. */ 1795 pLsiReq->pTargetDevice = pTargetDevice; 1796 pLsiReq->PDMScsiRequest.uLogicalUnit = pLsiReq->GuestRequest.SCSIIO.au8LUN[1]; 1797 1798 uint8_t uDataDirection = MPT_SCSIIO_REQUEST_CONTROL_TXDIR_GET(pLsiReq->GuestRequest.SCSIIO.u32Control); 1799 1800 if (uDataDirection == MPT_SCSIIO_REQUEST_CONTROL_TXDIR_NONE) 1801 pLsiReq->PDMScsiRequest.uDataDirection = PDMSCSIREQUESTTXDIR_NONE; 1802 else if (uDataDirection == MPT_SCSIIO_REQUEST_CONTROL_TXDIR_WRITE) 1803 pLsiReq->PDMScsiRequest.uDataDirection = PDMSCSIREQUESTTXDIR_TO_DEVICE; 1804 else if (uDataDirection == MPT_SCSIIO_REQUEST_CONTROL_TXDIR_READ) 1805 pLsiReq->PDMScsiRequest.uDataDirection = PDMSCSIREQUESTTXDIR_FROM_DEVICE; 1806 1807 pLsiReq->PDMScsiRequest.cbCDB = pLsiReq->GuestRequest.SCSIIO.u8CDBLength; 1808 pLsiReq->PDMScsiRequest.pbCDB = pLsiReq->GuestRequest.SCSIIO.au8CDB; 1809 pLsiReq->PDMScsiRequest.cbScatterGather = pLsiReq->GuestRequest.SCSIIO.u32DataLength; 1810 if (pLsiReq->PDMScsiRequest.cbScatterGather) 1811 { 1812 pLsiReq->PDMScsiRequest.cScatterGatherEntries = 1; 1813 pLsiReq->PDMScsiRequest.paScatterGatherHead = &pLsiReq->SegIoBuf; 2097 1814 } 2098 1815 else 2099 pTaskState->cSGListEntries = 0; 2100 2101 # if 0 2102 /* Map sense buffer. */ 2103 rc = lsilogicR3MapGCSenseBufferIntoR3(pThis, pTaskState); 2104 AssertRC(rc); 2105 # endif 2106 2107 /* Setup the SCSI request. */ 2108 pTaskState->pTargetDevice = pTargetDevice; 2109 pTaskState->PDMScsiRequest.uLogicalUnit = pTaskState->GuestRequest.SCSIIO.au8LUN[1]; 2110 2111 uint8_t uDataDirection = MPT_SCSIIO_REQUEST_CONTROL_TXDIR_GET(pTaskState->GuestRequest.SCSIIO.u32Control); 2112 2113 if (uDataDirection == MPT_SCSIIO_REQUEST_CONTROL_TXDIR_NONE) 2114 pTaskState->PDMScsiRequest.uDataDirection = PDMSCSIREQUESTTXDIR_NONE; 2115 else if (uDataDirection == MPT_SCSIIO_REQUEST_CONTROL_TXDIR_WRITE) 2116 pTaskState->PDMScsiRequest.uDataDirection = PDMSCSIREQUESTTXDIR_TO_DEVICE; 2117 else if (uDataDirection == MPT_SCSIIO_REQUEST_CONTROL_TXDIR_READ) 2118 pTaskState->PDMScsiRequest.uDataDirection = PDMSCSIREQUESTTXDIR_FROM_DEVICE; 2119 2120 pTaskState->PDMScsiRequest.cbCDB = pTaskState->GuestRequest.SCSIIO.u8CDBLength; 2121 pTaskState->PDMScsiRequest.pbCDB = pTaskState->GuestRequest.SCSIIO.au8CDB; 2122 pTaskState->PDMScsiRequest.cbScatterGather = pTaskState->GuestRequest.SCSIIO.u32DataLength; 2123 pTaskState->PDMScsiRequest.cScatterGatherEntries = pTaskState->cSGListEntries; 2124 pTaskState->PDMScsiRequest.paScatterGatherHead = pTaskState->pSGListHead; 2125 pTaskState->PDMScsiRequest.cbSenseBuffer = sizeof(pTaskState->abSenseBuffer); 2126 memset(pTaskState->abSenseBuffer, 0, pTaskState->PDMScsiRequest.cbSenseBuffer); 2127 pTaskState->PDMScsiRequest.pbSenseBuffer = pTaskState->abSenseBuffer; 2128 pTaskState->PDMScsiRequest.pvUser = pTaskState; 1816 { 1817 pLsiReq->PDMScsiRequest.cScatterGatherEntries = 0; 1818 pLsiReq->PDMScsiRequest.paScatterGatherHead = NULL; 1819 } 1820 pLsiReq->PDMScsiRequest.cbSenseBuffer = sizeof(pLsiReq->abSenseBuffer); 1821 memset(pLsiReq->abSenseBuffer, 0, pLsiReq->PDMScsiRequest.cbSenseBuffer); 1822 pLsiReq->PDMScsiRequest.pbSenseBuffer = pLsiReq->abSenseBuffer; 1823 pLsiReq->PDMScsiRequest.pvUser = pLsiReq; 2129 1824 2130 1825 ASMAtomicIncU32(&pTargetDevice->cOutstandingRequests); 2131 rc = pTargetDevice->pDrvSCSIConnector->pfnSCSIRequestSend(pTargetDevice->pDrvSCSIConnector, &p TaskState->PDMScsiRequest);1826 rc = pTargetDevice->pDrvSCSIConnector->pfnSCSIRequestSend(pTargetDevice->pDrvSCSIConnector, &pLsiReq->PDMScsiRequest); 2132 1827 AssertMsgRC(rc, ("Sending request to SCSI layer failed rc=%Rrc\n", rc)); 2133 1828 return VINF_SUCCESS; … … 2136 1831 { 2137 1832 /* Device is not present report SCSI selection timeout. */ 2138 p TaskState->IOCReply.SCSIIOError.u16IOCStatus = MPT_SCSI_IO_ERROR_IOCSTATUS_DEVICE_NOT_THERE;1833 pLsiReq->IOCReply.SCSIIOError.u16IOCStatus = MPT_SCSI_IO_ERROR_IOCSTATUS_DEVICE_NOT_THERE; 2139 1834 } 2140 1835 } … … 2142 1837 { 2143 1838 /* Report out of bounds target ID or bus. */ 2144 if (p TaskState->GuestRequest.SCSIIO.u8Bus != 0)2145 p TaskState->IOCReply.SCSIIOError.u16IOCStatus = MPT_SCSI_IO_ERROR_IOCSTATUS_INVALID_BUS;1839 if (pLsiReq->GuestRequest.SCSIIO.u8Bus != 0) 1840 pLsiReq->IOCReply.SCSIIOError.u16IOCStatus = MPT_SCSI_IO_ERROR_IOCSTATUS_INVALID_BUS; 2146 1841 else 2147 p TaskState->IOCReply.SCSIIOError.u16IOCStatus = MPT_SCSI_IO_ERROR_IOCSTATUS_INVALID_TARGETID;1842 pLsiReq->IOCReply.SCSIIOError.u16IOCStatus = MPT_SCSI_IO_ERROR_IOCSTATUS_INVALID_TARGETID; 2148 1843 } 2149 1844 … … 2153 1848 { 2154 1849 LogRel(("LsiLogic#%d: %d/%d (Bus/Target) doesn't exist\n", pThis->CTX_SUFF(pDevIns)->iInstance, 2155 p TaskState->GuestRequest.SCSIIO.u8TargetID, pTaskState->GuestRequest.SCSIIO.u8Bus));1850 pLsiReq->GuestRequest.SCSIIO.u8TargetID, pLsiReq->GuestRequest.SCSIIO.u8Bus)); 2156 1851 /* Log the CDB too */ 2157 1852 LogRel(("LsiLogic#%d: Guest issued CDB {%#x", 2158 pThis->CTX_SUFF(pDevIns)->iInstance, p TaskState->GuestRequest.SCSIIO.au8CDB[0]));2159 for (unsigned i = 1; i < p TaskState->GuestRequest.SCSIIO.u8CDBLength; i++)2160 LogRel((", %#x", p TaskState->GuestRequest.SCSIIO.au8CDB[i]));1853 pThis->CTX_SUFF(pDevIns)->iInstance, pLsiReq->GuestRequest.SCSIIO.au8CDB[0])); 1854 for (unsigned i = 1; i < pLsiReq->GuestRequest.SCSIIO.u8CDBLength; i++) 1855 LogRel((", %#x", pLsiReq->GuestRequest.SCSIIO.au8CDB[i])); 2161 1856 LogRel(("}\n")); 2162 1857 } 2163 1858 2164 1859 /* The rest is equal to both errors. */ 2165 p TaskState->IOCReply.SCSIIOError.u8TargetID = pTaskState->GuestRequest.SCSIIO.u8TargetID;2166 p TaskState->IOCReply.SCSIIOError.u8Bus = pTaskState->GuestRequest.SCSIIO.u8Bus;2167 p TaskState->IOCReply.SCSIIOError.u8MessageLength = sizeof(MptSCSIIOErrorReply) / 4;2168 p TaskState->IOCReply.SCSIIOError.u8Function = pTaskState->GuestRequest.SCSIIO.u8Function;2169 p TaskState->IOCReply.SCSIIOError.u8CDBLength = pTaskState->GuestRequest.SCSIIO.u8CDBLength;2170 p TaskState->IOCReply.SCSIIOError.u8SenseBufferLength = pTaskState->GuestRequest.SCSIIO.u8SenseBufferLength;2171 p TaskState->IOCReply.SCSIIOError.u32MessageContext = pTaskState->GuestRequest.SCSIIO.u32MessageContext;2172 p TaskState->IOCReply.SCSIIOError.u8SCSIStatus = SCSI_STATUS_OK;2173 p TaskState->IOCReply.SCSIIOError.u8SCSIState = MPT_SCSI_IO_ERROR_SCSI_STATE_TERMINATED;2174 p TaskState->IOCReply.SCSIIOError.u32IOCLogInfo = 0;2175 p TaskState->IOCReply.SCSIIOError.u32TransferCount = 0;2176 p TaskState->IOCReply.SCSIIOError.u32SenseCount = 0;2177 p TaskState->IOCReply.SCSIIOError.u32ResponseInfo = 0;2178 2179 lsilogicFinishAddressReply(pThis, &p TaskState->IOCReply, false);2180 RTMemCacheFree(pThis->hTaskCache, p TaskState);1860 pLsiReq->IOCReply.SCSIIOError.u8TargetID = pLsiReq->GuestRequest.SCSIIO.u8TargetID; 1861 pLsiReq->IOCReply.SCSIIOError.u8Bus = pLsiReq->GuestRequest.SCSIIO.u8Bus; 1862 pLsiReq->IOCReply.SCSIIOError.u8MessageLength = sizeof(MptSCSIIOErrorReply) / 4; 1863 pLsiReq->IOCReply.SCSIIOError.u8Function = pLsiReq->GuestRequest.SCSIIO.u8Function; 1864 pLsiReq->IOCReply.SCSIIOError.u8CDBLength = pLsiReq->GuestRequest.SCSIIO.u8CDBLength; 1865 pLsiReq->IOCReply.SCSIIOError.u8SenseBufferLength = pLsiReq->GuestRequest.SCSIIO.u8SenseBufferLength; 1866 pLsiReq->IOCReply.SCSIIOError.u32MessageContext = pLsiReq->GuestRequest.SCSIIO.u32MessageContext; 1867 pLsiReq->IOCReply.SCSIIOError.u8SCSIStatus = SCSI_STATUS_OK; 1868 pLsiReq->IOCReply.SCSIIOError.u8SCSIState = MPT_SCSI_IO_ERROR_SCSI_STATE_TERMINATED; 1869 pLsiReq->IOCReply.SCSIIOError.u32IOCLogInfo = 0; 1870 pLsiReq->IOCReply.SCSIIOError.u32TransferCount = 0; 1871 pLsiReq->IOCReply.SCSIIOError.u32SenseCount = 0; 1872 pLsiReq->IOCReply.SCSIIOError.u32ResponseInfo = 0; 1873 1874 lsilogicFinishAddressReply(pThis, &pLsiReq->IOCReply, false); 1875 RTMemCacheFree(pThis->hTaskCache, pLsiReq); 2181 1876 2182 1877 return rc; … … 2190 1885 int rcCompletion, bool fRedo, int rcReq) 2191 1886 { 2192 PLSILOGIC TASKSTATE pTaskState = (PLSILOGICTASKSTATE)pSCSIRequest->pvUser;2193 PLSILOGICDEVICE pLsiLogicDevice = p TaskState->pTargetDevice;1887 PLSILOGICREQ pLsiReq = (PLSILOGICREQ)pSCSIRequest->pvUser; 1888 PLSILOGICDEVICE pLsiLogicDevice = pLsiReq->pTargetDevice; 2194 1889 PLSILOGICSCSI pThis = pLsiLogicDevice->CTX_SUFF(pLsiLogic); 2195 1890 … … 2198 1893 if (fRedo) 2199 1894 { 2200 if (!p TaskState->fBIOS && pTaskState->PDMScsiRequest.cbScatterGather)2201 lsilogic R3ScatterGatherListDestroy(pThis, pTaskState);1895 if (!pLsiReq->fBIOS && pLsiReq->PDMScsiRequest.cbScatterGather) 1896 lsilogicIoBufFree(pThis->CTX_SUFF(pDevIns), pLsiReq, false /* fCopyToGuest */); 2202 1897 2203 1898 /* Add to the list. */ 2204 1899 do 2205 1900 { 2206 p TaskState->pRedoNext = ASMAtomicReadPtrT(&pThis->pTasksRedoHead, PLSILOGICTASKSTATE);2207 } while (!ASMAtomicCmpXchgPtr(&pThis->pTasksRedoHead, p TaskState, pTaskState->pRedoNext));1901 pLsiReq->pRedoNext = ASMAtomicReadPtrT(&pThis->pTasksRedoHead, PLSILOGICREQ); 1902 } while (!ASMAtomicCmpXchgPtr(&pThis->pTasksRedoHead, pLsiReq, pLsiReq->pRedoNext)); 2208 1903 2209 1904 /* Suspend the VM if not done already. */ … … 2213 1908 else 2214 1909 { 2215 if (RT_UNLIKELY(p TaskState->fBIOS))1910 if (RT_UNLIKELY(pLsiReq->fBIOS)) 2216 1911 { 2217 1912 int rc = vboxscsiRequestFinished(&pThis->VBoxSCSI, pSCSIRequest, rcCompletion); … … 2220 1915 else 2221 1916 { 2222 # if 02223 lsilogicFreeGCSenseBuffer(pThis, pTaskState);2224 # else2225 1917 RTGCPHYS GCPhysAddrSenseBuffer; 2226 1918 2227 GCPhysAddrSenseBuffer = p TaskState->GuestRequest.SCSIIO.u32SenseBufferLowAddress;1919 GCPhysAddrSenseBuffer = pLsiReq->GuestRequest.SCSIIO.u32SenseBufferLowAddress; 2228 1920 GCPhysAddrSenseBuffer |= ((uint64_t)pThis->u32SenseBufferHighAddr << 32); 2229 1921 2230 1922 /* Copy the sense buffer over. */ 2231 PDMDevHlpPCIPhysWrite(pThis->CTX_SUFF(pDevIns), GCPhysAddrSenseBuffer, p TaskState->abSenseBuffer,2232 RT_UNLIKELY( p TaskState->GuestRequest.SCSIIO.u8SenseBufferLength2233 < p TaskState->PDMScsiRequest.cbSenseBuffer)2234 ? p TaskState->GuestRequest.SCSIIO.u8SenseBufferLength2235 : p TaskState->PDMScsiRequest.cbSenseBuffer);2236 # endif 2237 if (p TaskState->PDMScsiRequest.cbScatterGather)2238 lsilogic R3ScatterGatherListDestroy(pThis, pTaskState);1923 PDMDevHlpPCIPhysWrite(pThis->CTX_SUFF(pDevIns), GCPhysAddrSenseBuffer, pLsiReq->abSenseBuffer, 1924 RT_UNLIKELY( pLsiReq->GuestRequest.SCSIIO.u8SenseBufferLength 1925 < pLsiReq->PDMScsiRequest.cbSenseBuffer) 1926 ? pLsiReq->GuestRequest.SCSIIO.u8SenseBufferLength 1927 : pLsiReq->PDMScsiRequest.cbSenseBuffer); 1928 1929 if (pLsiReq->PDMScsiRequest.cbScatterGather) 1930 lsilogicIoBufFree(pThis->CTX_SUFF(pDevIns), pLsiReq, true /* fCopyToGuest */); 2239 1931 2240 1932 2241 1933 if (RT_LIKELY(rcCompletion == SCSI_STATUS_OK)) 2242 lsilogicR3FinishContextReply(pThis, p TaskState->GuestRequest.SCSIIO.u32MessageContext);1934 lsilogicR3FinishContextReply(pThis, pLsiReq->GuestRequest.SCSIIO.u32MessageContext); 2243 1935 else 2244 1936 { 2245 1937 /* The SCSI target encountered an error during processing post a reply. */ 2246 memset(&p TaskState->IOCReply, 0, sizeof(MptReplyUnion));2247 p TaskState->IOCReply.SCSIIOError.u8TargetID = pTaskState->GuestRequest.SCSIIO.u8TargetID;2248 p TaskState->IOCReply.SCSIIOError.u8Bus = pTaskState->GuestRequest.SCSIIO.u8Bus;2249 p TaskState->IOCReply.SCSIIOError.u8MessageLength = 8;2250 p TaskState->IOCReply.SCSIIOError.u8Function = pTaskState->GuestRequest.SCSIIO.u8Function;2251 p TaskState->IOCReply.SCSIIOError.u8CDBLength = pTaskState->GuestRequest.SCSIIO.u8CDBLength;2252 p TaskState->IOCReply.SCSIIOError.u8SenseBufferLength = pTaskState->GuestRequest.SCSIIO.u8SenseBufferLength;2253 p TaskState->IOCReply.SCSIIOError.u8MessageFlags = pTaskState->GuestRequest.SCSIIO.u8MessageFlags;2254 p TaskState->IOCReply.SCSIIOError.u32MessageContext = pTaskState->GuestRequest.SCSIIO.u32MessageContext;2255 p TaskState->IOCReply.SCSIIOError.u8SCSIStatus = rcCompletion;2256 p TaskState->IOCReply.SCSIIOError.u8SCSIState = MPT_SCSI_IO_ERROR_SCSI_STATE_AUTOSENSE_VALID;2257 p TaskState->IOCReply.SCSIIOError.u16IOCStatus = 0;2258 p TaskState->IOCReply.SCSIIOError.u32IOCLogInfo = 0;2259 p TaskState->IOCReply.SCSIIOError.u32TransferCount = 0;2260 p TaskState->IOCReply.SCSIIOError.u32SenseCount = sizeof(pTaskState->abSenseBuffer);2261 p TaskState->IOCReply.SCSIIOError.u32ResponseInfo = 0;2262 2263 lsilogicFinishAddressReply(pThis, &p TaskState->IOCReply, true);1938 memset(&pLsiReq->IOCReply, 0, sizeof(MptReplyUnion)); 1939 pLsiReq->IOCReply.SCSIIOError.u8TargetID = pLsiReq->GuestRequest.SCSIIO.u8TargetID; 1940 pLsiReq->IOCReply.SCSIIOError.u8Bus = pLsiReq->GuestRequest.SCSIIO.u8Bus; 1941 pLsiReq->IOCReply.SCSIIOError.u8MessageLength = 8; 1942 pLsiReq->IOCReply.SCSIIOError.u8Function = pLsiReq->GuestRequest.SCSIIO.u8Function; 1943 pLsiReq->IOCReply.SCSIIOError.u8CDBLength = pLsiReq->GuestRequest.SCSIIO.u8CDBLength; 1944 pLsiReq->IOCReply.SCSIIOError.u8SenseBufferLength = pLsiReq->GuestRequest.SCSIIO.u8SenseBufferLength; 1945 pLsiReq->IOCReply.SCSIIOError.u8MessageFlags = pLsiReq->GuestRequest.SCSIIO.u8MessageFlags; 1946 pLsiReq->IOCReply.SCSIIOError.u32MessageContext = pLsiReq->GuestRequest.SCSIIO.u32MessageContext; 1947 pLsiReq->IOCReply.SCSIIOError.u8SCSIStatus = rcCompletion; 1948 pLsiReq->IOCReply.SCSIIOError.u8SCSIState = MPT_SCSI_IO_ERROR_SCSI_STATE_AUTOSENSE_VALID; 1949 pLsiReq->IOCReply.SCSIIOError.u16IOCStatus = 0; 1950 pLsiReq->IOCReply.SCSIIOError.u32IOCLogInfo = 0; 1951 pLsiReq->IOCReply.SCSIIOError.u32TransferCount = 0; 1952 pLsiReq->IOCReply.SCSIIOError.u32SenseCount = sizeof(pLsiReq->abSenseBuffer); 1953 pLsiReq->IOCReply.SCSIIOError.u32ResponseInfo = 0; 1954 1955 lsilogicFinishAddressReply(pThis, &pLsiReq->IOCReply, true); 2264 1956 } 2265 1957 } 2266 1958 2267 RTMemCacheFree(pThis->hTaskCache, p TaskState);1959 RTMemCacheFree(pThis->hTaskCache, pLsiReq); 2268 1960 } 2269 1961 … … 3643 3335 (u32RequestMessageFrameDesc & ~0x07)); 3644 3336 3645 PLSILOGIC TASKSTATE pTaskState;3337 PLSILOGICREQ pLsiReq; 3646 3338 3647 3339 /* Get new task state. */ 3648 rc = RTMemCacheAllocEx(pThis->hTaskCache, (void **)&p TaskState);3340 rc = RTMemCacheAllocEx(pThis->hTaskCache, (void **)&pLsiReq); 3649 3341 AssertRC(rc); 3650 3342 3651 p TaskState->GCPhysMessageFrameAddr = GCPhysMessageFrameAddr;3343 pLsiReq->GCPhysMessageFrameAddr = GCPhysMessageFrameAddr; 3652 3344 3653 3345 /* Read the message header from the guest first. */ 3654 PDMDevHlpPhysRead(pDevIns, GCPhysMessageFrameAddr, &p TaskState->GuestRequest, sizeof(MptMessageHdr));3346 PDMDevHlpPhysRead(pDevIns, GCPhysMessageFrameAddr, &pLsiReq->GuestRequest, sizeof(MptMessageHdr)); 3655 3347 3656 3348 /* Determine the size of the request. */ 3657 3349 uint32_t cbRequest = 0; 3658 3350 3659 switch (p TaskState->GuestRequest.Header.u8Function)3351 switch (pLsiReq->GuestRequest.Header.u8Function) 3660 3352 { 3661 3353 case MPT_MESSAGE_HDR_FUNCTION_SCSI_IO_REQUEST: … … 3694 3386 break; 3695 3387 default: 3696 AssertMsgFailed(("Unknown function issued %u\n", p TaskState->GuestRequest.Header.u8Function));3388 AssertMsgFailed(("Unknown function issued %u\n", pLsiReq->GuestRequest.Header.u8Function)); 3697 3389 lsilogicSetIOCFaultCode(pThis, LSILOGIC_IOCSTATUS_INVALID_FUNCTION); 3698 3390 } … … 3701 3393 { 3702 3394 /* Read the complete message frame from guest memory now. */ 3703 PDMDevHlpPhysRead(pDevIns, GCPhysMessageFrameAddr, &p TaskState->GuestRequest, cbRequest);3395 PDMDevHlpPhysRead(pDevIns, GCPhysMessageFrameAddr, &pLsiReq->GuestRequest, cbRequest); 3704 3396 3705 3397 /* Handle SCSI I/O requests now. */ 3706 if (p TaskState->GuestRequest.Header.u8Function == MPT_MESSAGE_HDR_FUNCTION_SCSI_IO_REQUEST)3398 if (pLsiReq->GuestRequest.Header.u8Function == MPT_MESSAGE_HDR_FUNCTION_SCSI_IO_REQUEST) 3707 3399 { 3708 rc = lsilogicR3ProcessSCSIIORequest(pThis, p TaskState);3400 rc = lsilogicR3ProcessSCSIIORequest(pThis, pLsiReq); 3709 3401 AssertRC(rc); 3710 3402 } … … 3712 3404 { 3713 3405 MptReplyUnion Reply; 3714 rc = lsilogicR3ProcessMessageRequest(pThis, &p TaskState->GuestRequest.Header, &Reply);3406 rc = lsilogicR3ProcessMessageRequest(pThis, &pLsiReq->GuestRequest.Header, &Reply); 3715 3407 AssertRC(rc); 3716 RTMemCacheFree(pThis->hTaskCache, p TaskState);3408 RTMemCacheFree(pThis->hTaskCache, pLsiReq); 3717 3409 } 3718 3410 … … 3780 3472 { 3781 3473 int rc; 3782 PLSILOGIC TASKSTATE pTaskState;3474 PLSILOGICREQ pLsiReq; 3783 3475 uint32_t uTargetDevice; 3784 3476 3785 rc = RTMemCacheAllocEx(pThis->hTaskCache, (void **)&p TaskState);3477 rc = RTMemCacheAllocEx(pThis->hTaskCache, (void **)&pLsiReq); 3786 3478 AssertMsgRCReturn(rc, ("Getting task from cache failed rc=%Rrc\n", rc), rc); 3787 3479 3788 p TaskState->fBIOS = true;3789 3790 rc = vboxscsiSetupRequest(&pThis->VBoxSCSI, &p TaskState->PDMScsiRequest, &uTargetDevice);3480 pLsiReq->fBIOS = true; 3481 3482 rc = vboxscsiSetupRequest(&pThis->VBoxSCSI, &pLsiReq->PDMScsiRequest, &uTargetDevice); 3791 3483 AssertMsgRCReturn(rc, ("Setting up SCSI request failed rc=%Rrc\n", rc), rc); 3792 3484 3793 p TaskState->PDMScsiRequest.pvUser = pTaskState;3485 pLsiReq->PDMScsiRequest.pvUser = pLsiReq; 3794 3486 3795 3487 if (uTargetDevice < pThis->cDeviceStates) 3796 3488 { 3797 p TaskState->pTargetDevice = &pThis->paDeviceStates[uTargetDevice];3798 3799 if (p TaskState->pTargetDevice->pDrvBase)3800 { 3801 ASMAtomicIncU32(&p TaskState->pTargetDevice->cOutstandingRequests);3802 3803 rc = p TaskState->pTargetDevice->pDrvSCSIConnector->pfnSCSIRequestSend(pTaskState->pTargetDevice->pDrvSCSIConnector,3804 &p TaskState->PDMScsiRequest);3489 pLsiReq->pTargetDevice = &pThis->paDeviceStates[uTargetDevice]; 3490 3491 if (pLsiReq->pTargetDevice->pDrvBase) 3492 { 3493 ASMAtomicIncU32(&pLsiReq->pTargetDevice->cOutstandingRequests); 3494 3495 rc = pLsiReq->pTargetDevice->pDrvSCSIConnector->pfnSCSIRequestSend(pLsiReq->pTargetDevice->pDrvSCSIConnector, 3496 &pLsiReq->PDMScsiRequest); 3805 3497 AssertMsgRCReturn(rc, ("Sending request to SCSI layer failed rc=%Rrc\n", rc), rc); 3806 3498 return VINF_SUCCESS; … … 3809 3501 3810 3502 /* Device is not present. */ 3811 AssertMsg(p TaskState->PDMScsiRequest.pbCDB[0] == SCSI_INQUIRY,3503 AssertMsg(pLsiReq->PDMScsiRequest.pbCDB[0] == SCSI_INQUIRY, 3812 3504 ("Device is not present but command is not inquiry\n")); 3813 3505 … … 3820 3512 memcpy(pThis->VBoxSCSI.pbBuf, &ScsiInquiryData, 5); 3821 3513 3822 rc = vboxscsiRequestFinished(&pThis->VBoxSCSI, &p TaskState->PDMScsiRequest, SCSI_STATUS_OK);3514 rc = vboxscsiRequestFinished(&pThis->VBoxSCSI, &pLsiReq->PDMScsiRequest, SCSI_STATUS_OK); 3823 3515 AssertMsgRCReturn(rc, ("Finishing BIOS SCSI request failed rc=%Rrc\n", rc), rc); 3824 3516 3825 RTMemCacheFree(pThis->hTaskCache, p TaskState);3517 RTMemCacheFree(pThis->hTaskCache, pLsiReq); 3826 3518 return rc; 3827 3519 } … … 4824 4516 * lsilogicRegisterWrite. 4825 4517 */ 4826 PLSILOGIC TASKSTATE pTaskState= pThis->pTasksRedoHead;4518 PLSILOGICREQ pLsiReq = pThis->pTasksRedoHead; 4827 4519 4828 4520 pThis->pTasksRedoHead = NULL; 4829 4521 4830 while (p TaskState)4522 while (pLsiReq) 4831 4523 { 4832 PLSILOGIC TASKSTATEpFree;4833 4834 if (!p TaskState->fBIOS)4524 PLSILOGICREQ pFree; 4525 4526 if (!pLsiReq->fBIOS) 4835 4527 { 4836 4528 /* Write only the lower 32bit part of the address. */ 4837 4529 ASMAtomicWriteU32(&pThis->CTX_SUFF(pRequestQueueBase)[pThis->uRequestQueueNextEntryFreeWrite], 4838 p TaskState->GCPhysMessageFrameAddr & UINT32_C(0xffffffff));4530 pLsiReq->GCPhysMessageFrameAddr & UINT32_C(0xffffffff)); 4839 4531 4840 4532 pThis->uRequestQueueNextEntryFreeWrite++; … … 4845 4537 else 4846 4538 { 4847 AssertMsg(!p TaskState->pRedoNext, ("Only one BIOS task can be active!\n"));4848 vboxscsiSetRequestRedo(&pThis->VBoxSCSI, &p TaskState->PDMScsiRequest);4539 AssertMsg(!pLsiReq->pRedoNext, ("Only one BIOS task can be active!\n")); 4540 vboxscsiSetRequestRedo(&pThis->VBoxSCSI, &pLsiReq->PDMScsiRequest); 4849 4541 } 4850 4542 4851 pFree = p TaskState;4852 p TaskState = pTaskState->pRedoNext;4543 pFree = pLsiReq; 4544 pLsiReq = pLsiReq->pRedoNext; 4853 4545 4854 4546 RTMemCacheFree(pThis->hTaskCache, pFree); … … 5266 4958 * Allocate task cache. 5267 4959 */ 5268 rc = RTMemCacheCreate(&pThis->hTaskCache, sizeof(LSILOGIC TASKSTATE), 0, UINT32_MAX,5269 lsilogicR3TaskStateCtor, lsilogicR3TaskStateDtor, NULL, 0);4960 rc = RTMemCacheCreate(&pThis->hTaskCache, sizeof(LSILOGICREQ), 0, UINT32_MAX, 4961 NULL, NULL, NULL, 0); 5270 4962 if (RT_FAILURE(rc)) 5271 4963 return PDMDEV_SET_ERROR(pDevIns, rc, N_("Cannot create task cache"));
Note:
See TracChangeset
for help on using the changeset viewer.