- Timestamp:
- Oct 12, 2016 12:54:51 PM (8 years ago)
- Location:
- trunk/src/VBox/Devices
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Storage/DevBusLogic.cpp
r63690 r64224 112 112 /** Our base interface. */ 113 113 PDMIBASE IBase; 114 /** SCSI port interface. */ 115 PDMISCSIPORT ISCSIPort; 114 /** Media port interface. */ 115 PDMIMEDIAPORT IMediaPort; 116 /** Extended media port interface. */ 117 PDMIMEDIAEXPORT IMediaExPort; 116 118 /** Led interface. */ 117 119 PDMILEDPORTS ILed; 118 120 /** Pointer to the attached driver's base interface. */ 119 121 R3PTRTYPE(PPDMIBASE) pDrvBase; 120 /** Pointer to the underlying SCSI connector interface. */ 121 R3PTRTYPE(PPDMISCSICONNECTOR) pDrvSCSIConnector; 122 /** Pointer to the attached driver's media interface. */ 123 R3PTRTYPE(PPDMIMEDIA) pDrvMedia; 124 /** Pointer to the attached driver's extended media interface. */ 125 R3PTRTYPE(PPDMIMEDIAEX) pDrvMediaEx; 122 126 /** The status LED state for this device. */ 123 127 PDMLED Led; … … 313 317 314 318 /** Pointer to a task state structure. */ 315 typedef struct BUSLOGIC TASKSTATE *PBUSLOGICTASKSTATE;319 typedef struct BUSLOGICREQ *PBUSLOGICREQ; 316 320 317 321 /** … … 436 440 PDMCRITSECT CritSectIntr; 437 441 438 /** Cache for task states. */439 R3PTRTYPE(RTMEMCACHE) hTaskCache;440 441 442 /** Device state for BIOS access. */ 442 443 VBOXSCSI VBoxSCSI; … … 460 461 * a port is entering the idle state. */ 461 462 bool volatile fSignalIdle; 462 /** Flag whether we have tasks which need to be processed again. */463 bool volatile fRedo;464 463 /** Flag whether the worker thread is sleeping. */ 465 464 volatile bool fWrkThreadSleeping; … … 467 466 * worker thread needs to process. */ 468 467 volatile bool fBiosReqPending; 469 /** List of tasks which can be redone. */470 R3PTRTYPE(volatile PBUSLOGICTASKSTATE) pTasksRedoHead;471 468 472 469 /** The support driver session handle. */ … … 477 474 SUPSEMEVENT hEvtProcess; 478 475 476 /** Pointer to the array of addresses to redo. */ 477 R3PTRTYPE(PRTGCPHYS) paGCPhysAddrCCBRedo; 478 /** Number of addresses the redo array holds. */ 479 uint32_t cReqsRedo; 480 479 481 #ifdef LOG_ENABLED 482 volatile uint32_t cInMailboxesReady; 483 #else 480 484 # if HC_ARCH_BITS == 64 481 485 uint32_t Alignment4; 482 486 # endif 483 484 volatile uint32_t cInMailboxesReady;485 487 #endif 486 488 … … 956 958 * Task state for a CCB request. 957 959 */ 958 typedef struct BUSLOGIC TASKSTATE959 { 960 /** Next in the redo list. */961 P BUSLOGICTASKSTATE pRedoNext;960 typedef struct BUSLOGICREQ 961 { 962 /** PDM extended media interface I/O request hande. */ 963 PDMMEDIAEXIOREQ hIoReq; 962 964 /** Device this task is assigned to. */ 963 R3PTRTYPE(PBUSLOGICDEVICE) pTargetDeviceR3;965 PBUSLOGICDEVICE pTargetDevice; 964 966 /** The command control block from the guest. */ 965 CCBU CommandControlBlockGuest; 966 /** Mailbox read from guest memory. */ 967 Mailbox32 MailboxGuest; 968 /** The SCSI request we pass to the underlying SCSI engine. */ 969 PDMSCSIREQUEST PDMScsiRequest; 970 /** Data buffer segment */ 971 RTSGSEG DataSeg; 967 CCBU CCBGuest; 968 /** Guest physical address of th CCB. */ 969 RTGCPHYS GCPhysAddrCCB; 972 970 /** Pointer to the R3 sense buffer. */ 973 uint8_t *pbSenseBuffer;971 uint8_t *pbSenseBuffer; 974 972 /** Flag whether this is a request from the BIOS. */ 975 bool fBIOS;973 bool fBIOS; 976 974 /** 24-bit request flag (default is 32-bit). */ 977 bool fIs24Bit; 978 /** S/G entry size (depends on the above flag). */ 979 uint8_t cbSGEntry; 980 } BUSLOGICTASKSTATE; 975 bool fIs24Bit; 976 /** SCSI status code. */ 977 uint8_t u8ScsiSts; 978 } BUSLOGICREQ; 979 980 #ifdef IN_RING3 981 /** 982 * Memory buffer callback. 983 * 984 * @returns nothing. 985 * @param pThis The LsiLogic controller instance. 986 * @param GCPhys The guest physical address of the memory buffer. 987 * @param pSgBuf The pointer to the host R3 S/G buffer. 988 * @param cbCopy How many bytes to copy between the two buffers. 989 * @param pcbSkip Initially contains the amount of bytes to skip 990 * starting from the guest physical address before 991 * accessing the S/G buffer and start copying data. 992 * On return this contains the remaining amount if 993 * cbCopy < *pcbSkip or 0 otherwise. 994 */ 995 typedef DECLCALLBACK(void) BUSLOGICR3MEMCOPYCALLBACK(PBUSLOGIC pThis, RTGCPHYS GCPhys, PRTSGBUF pSgBuf, size_t cbCopy, 996 size_t *pcbSkip); 997 /** Pointer to a memory copy buffer callback. */ 998 typedef BUSLOGICR3MEMCOPYCALLBACK *PBUSLOGICR3MEMCOPYCALLBACK; 999 #endif 981 1000 982 1001 #ifndef VBOX_DEVICE_STRUCT_TESTCASE 983 984 #define PDMIBASE_2_PBUSLOGICDEVICE(pInterface) ( (PBUSLOGICDEVICE)((uintptr_t)(pInterface) - RT_OFFSETOF(BUSLOGICDEVICE, IBase)) )985 #define PDMISCSIPORT_2_PBUSLOGICDEVICE(pInterface) ( (PBUSLOGICDEVICE)((uintptr_t)(pInterface) - RT_OFFSETOF(BUSLOGICDEVICE, ISCSIPort)) )986 #define PDMILEDPORTS_2_PBUSLOGICDEVICE(pInterface) ( (PBUSLOGICDEVICE)((uintptr_t)(pInterface) - RT_OFFSETOF(BUSLOGICDEVICE, ILed)) )987 #define PDMIBASE_2_PBUSLOGIC(pInterface) ( (PBUSLOGIC)((uintptr_t)(pInterface) - RT_OFFSETOF(BUSLOGIC, IBase)) )988 #define PDMILEDPORTS_2_PBUSLOGIC(pInterface) ( (PBUSLOGIC)((uintptr_t)(pInterface) - RT_OFFSETOF(BUSLOGIC, ILeds)) )989 1002 990 1003 … … 1188 1201 * @returns nothing. 1189 1202 * @param pBusLogic Pointer to the BusLogic device instance. 1190 * @param pTaskState Pointer to the task state with the mailbox to send. 1203 * @param GCPhysAddrCCB The physical guest address of the CCB the mailbox is for. 1204 * @param pCCBGuet The command control block. 1191 1205 * @param uHostAdapterStatus The host adapter status code to set. 1192 1206 * @param uDeviceStatus The target device status to set. 1193 1207 * @param uMailboxCompletionCode Completion status code to set in the mailbox. 1194 1208 */ 1195 static void buslogicR3SendIncomingMailbox(PBUSLOGIC pBusLogic, PBUSLOGICTASKSTATE pTaskState, 1196 uint8_t uHostAdapterStatus, uint8_t uDeviceStatus, 1197 uint8_t uMailboxCompletionCode) 1198 { 1199 pTaskState->MailboxGuest.u.in.uHostAdapterStatus = uHostAdapterStatus; 1200 pTaskState->MailboxGuest.u.in.uTargetDeviceStatus = uDeviceStatus; 1201 pTaskState->MailboxGuest.u.in.uCompletionCode = uMailboxCompletionCode; 1209 static void buslogicR3SendIncomingMailbox(PBUSLOGIC pBusLogic, RTGCPHYS GCPhysAddrCCB, 1210 PCCBU pCCBGuest, uint8_t uHostAdapterStatus, 1211 uint8_t uDeviceStatus, uint8_t uMailboxCompletionCode) 1212 { 1213 Mailbox32 MbxIn; 1214 1215 MbxIn.u32PhysAddrCCB = (uint32_t)GCPhysAddrCCB; 1216 MbxIn.u.in.uHostAdapterStatus = uHostAdapterStatus; 1217 MbxIn.u.in.uTargetDeviceStatus = uDeviceStatus; 1218 MbxIn.u.in.uCompletionCode = uMailboxCompletionCode; 1202 1219 1203 1220 int rc = PDMCritSectEnter(&pBusLogic->CritSectIntr, VINF_SUCCESS); … … 1206 1223 RTGCPHYS GCPhysAddrMailboxIncoming = pBusLogic->GCPhysAddrMailboxIncomingBase 1207 1224 + ( pBusLogic->uMailboxIncomingPositionCurrent 1208 * (p TaskState->fIs24Bit ? sizeof(Mailbox24) : sizeof(Mailbox32)) );1225 * (pBusLogic->fMbxIs24Bit ? sizeof(Mailbox24) : sizeof(Mailbox32)) ); 1209 1226 1210 1227 if (uMailboxCompletionCode != BUSLOGIC_MAILBOX_INCOMING_COMPLETION_ABORTED_NOT_FOUND) 1211 1228 { 1212 RTGCPHYS GCPhysAddrCCB = pTaskState->MailboxGuest.u32PhysAddrCCB;1213 1229 LogFlowFunc(("Completing CCB %RGp hstat=%u, dstat=%u, outgoing mailbox at %RGp\n", GCPhysAddrCCB, 1214 1230 uHostAdapterStatus, uDeviceStatus, GCPhysAddrMailboxIncoming)); 1215 1231 1216 1232 /* Update CCB. */ 1217 p TaskState->CommandControlBlockGuest.c.uHostAdapterStatus = uHostAdapterStatus;1218 p TaskState->CommandControlBlockGuest.c.uDeviceStatus = uDeviceStatus;1233 pCCBGuest->c.uHostAdapterStatus = uHostAdapterStatus; 1234 pCCBGuest->c.uDeviceStatus = uDeviceStatus; 1219 1235 /* Rewrite CCB up to the CDB; perhaps more than necessary. */ 1220 1236 PDMDevHlpPCIPhysWrite(pBusLogic->CTX_SUFF(pDevIns), GCPhysAddrCCB, 1221 &pTaskState->CommandControlBlockGuest, RT_OFFSETOF(CCBC, abCDB));1237 pCCBGuest, RT_OFFSETOF(CCBC, abCDB)); 1222 1238 } 1223 1239 1224 1240 # ifdef RT_STRICT 1225 1241 uint8_t uCode; 1226 unsigned uCodeOffs = p TaskState->fIs24Bit ? RT_OFFSETOF(Mailbox24, uCmdState) : RT_OFFSETOF(Mailbox32, u.out.uActionCode);1242 unsigned uCodeOffs = pBusLogic->fMbxIs24Bit ? RT_OFFSETOF(Mailbox24, uCmdState) : RT_OFFSETOF(Mailbox32, u.out.uActionCode); 1227 1243 PDMDevHlpPhysRead(pBusLogic->CTX_SUFF(pDevIns), GCPhysAddrMailboxIncoming + uCodeOffs, &uCode, sizeof(uCode)); 1228 1244 Assert(uCode == BUSLOGIC_MAILBOX_INCOMING_COMPLETION_FREE); … … 1230 1246 1231 1247 /* Update mailbox. */ 1232 if (p TaskState->fIs24Bit)1248 if (pBusLogic->fMbxIs24Bit) 1233 1249 { 1234 1250 Mailbox24 Mbx24; 1235 1251 1236 Mbx24.uCmdState = pTaskState->MailboxGuest.u.in.uCompletionCode;1237 U32_TO_ADDR(Mbx24.aPhysAddrCCB, pTaskState->MailboxGuest.u32PhysAddrCCB);1252 Mbx24.uCmdState = MbxIn.u.in.uCompletionCode; 1253 U32_TO_ADDR(Mbx24.aPhysAddrCCB, MbxIn.u32PhysAddrCCB); 1238 1254 Log(("24-bit mailbox: completion code=%u, CCB at %RGp\n", Mbx24.uCmdState, (RTGCPHYS)ADDR_TO_U32(Mbx24.aPhysAddrCCB))); 1239 1255 PDMDevHlpPCIPhysWrite(pBusLogic->CTX_SUFF(pDevIns), GCPhysAddrMailboxIncoming, &Mbx24, sizeof(Mailbox24)); … … 1241 1257 else 1242 1258 { 1243 Log(("32-bit mailbox: completion code=%u, CCB at %RGp\n", pTaskState->MailboxGuest.u.in.uCompletionCode, (RTGCPHYS)pTaskState->MailboxGuest.u32PhysAddrCCB));1259 Log(("32-bit mailbox: completion code=%u, CCB at %RGp\n", MbxIn.u.in.uCompletionCode, GCPhysAddrCCB)); 1244 1260 PDMDevHlpPCIPhysWrite(pBusLogic->CTX_SUFF(pDevIns), GCPhysAddrMailboxIncoming, 1245 & pTaskState->MailboxGuest, sizeof(Mailbox32));1261 &MbxIn, sizeof(Mailbox32)); 1246 1262 } 1247 1263 … … 1331 1347 * Allocate data buffer. 1332 1348 * 1333 * @param pTaskState Pointer to the task state. 1349 * @param pDevIns PDM device instance. 1350 * @param fIs24Bit Flag whether the 24bit SG format is used. 1334 1351 * @param GCSGList Guest physical address of S/G list. 1335 1352 * @param cEntries Number of list entries to read. 1336 1353 * @param pSGEList Pointer to 32-bit S/G list storage. 1337 1354 */ 1338 static void buslogicR3ReadSGEntries(PBUSLOGICTASKSTATE pTaskState, RTGCPHYS GCSGList, uint32_t cEntries, SGE32 *pSGEList) 1339 { 1340 PPDMDEVINS pDevIns = pTaskState->CTX_SUFF(pTargetDevice)->CTX_SUFF(pBusLogic)->CTX_SUFF(pDevIns); 1341 SGE24 aSGE24[32]; 1342 Assert(cEntries <= RT_ELEMENTS(aSGE24)); 1343 1355 static void buslogicR3ReadSGEntries(PPDMDEVINS pDevIns, bool fIs24Bit, RTGCPHYS GCSGList, 1356 uint32_t cEntries, SGE32 *pSGEList) 1357 { 1344 1358 /* Read the S/G entries. Convert 24-bit entries to 32-bit format. */ 1345 if (pTaskState->fIs24Bit) 1346 { 1359 if (fIs24Bit) 1360 { 1361 SGE24 aSGE24[32]; 1362 Assert(cEntries <= RT_ELEMENTS(aSGE24)); 1363 1347 1364 Log2(("Converting %u 24-bit S/G entries to 32-bit\n", cEntries)); 1348 1365 PDMDevHlpPhysRead(pDevIns, GCSGList, &aSGE24, cEntries * sizeof(SGE24)); … … 1358 1375 1359 1376 /** 1360 * Allocatedata buffer.1377 * Determines the size of th guest data buffer. 1361 1378 * 1362 1379 * @returns VBox status code. 1363 * @param pTaskState Pointer to the task state. 1364 */ 1365 static int buslogicR3DataBufferAlloc(PBUSLOGICTASKSTATE pTaskState) 1366 { 1367 PPDMDEVINS pDevIns = pTaskState->CTX_SUFF(pTargetDevice)->CTX_SUFF(pBusLogic)->CTX_SUFF(pDevIns); 1368 uint32_t cbDataCCB; 1369 uint32_t u32PhysAddrCCB; 1380 * @param pDevIns PDM device instance. 1381 * @param pCCBGuest The CCB of the guest. 1382 * @param fIs24Bit Flag whether the 24bit SG format is used. 1383 * @para cbSGEntry Size of one SG entry in bytes. 1384 * @param pcbBuf Where to store the size of the guest data buffer on success. 1385 */ 1386 static int buslogicR3QueryDataBufferSize(PPDMDEVINS pDevIns, PCCBU pCCBGuest, bool fIs24Bit, size_t *pcbBuf) 1387 { 1388 int rc = VINF_SUCCESS; 1389 uint32_t cbDataCCB; 1390 uint32_t u32PhysAddrCCB; 1391 size_t cbBuf = 0; 1370 1392 1371 1393 /* Extract the data length and physical address from the CCB. */ 1372 if ( pTaskState->fIs24Bit)1373 { 1374 u32PhysAddrCCB = ADDR_TO_U32(p TaskState->CommandControlBlockGuest.o.aPhysAddrData);1375 cbDataCCB = LEN_TO_U32(p TaskState->CommandControlBlockGuest.o.acbData);1394 if (fIs24Bit) 1395 { 1396 u32PhysAddrCCB = ADDR_TO_U32(pCCBGuest->o.aPhysAddrData); 1397 cbDataCCB = LEN_TO_U32(pCCBGuest->o.acbData); 1376 1398 } 1377 1399 else 1378 1400 { 1379 u32PhysAddrCCB = p TaskState->CommandControlBlockGuest.n.u32PhysAddrData;1380 cbDataCCB = p TaskState->CommandControlBlockGuest.n.cbData;1381 } 1382 1383 if ( (p TaskState->CommandControlBlockGuest.c.uDataDirection != BUSLOGIC_CCB_DIRECTION_NO_DATA)1401 u32PhysAddrCCB = pCCBGuest->n.u32PhysAddrData; 1402 cbDataCCB = pCCBGuest->n.cbData; 1403 } 1404 1405 if ( (pCCBGuest->c.uDataDirection != BUSLOGIC_CCB_DIRECTION_NO_DATA) 1384 1406 && cbDataCCB) 1385 1407 { 1386 /** @todo Check following assumption and what residual means. */1387 1408 /* 1388 1409 * The BusLogic adapter can handle two different data buffer formats. … … 1391 1412 * scatter gather list which describes the buffer. 1392 1413 */ 1393 if ( (p TaskState->CommandControlBlockGuest.c.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB_SCATTER_GATHER)1394 || (p TaskState->CommandControlBlockGuest.c.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB_RESIDUAL_SCATTER_GATHER))1414 if ( (pCCBGuest->c.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB_SCATTER_GATHER) 1415 || (pCCBGuest->c.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB_RESIDUAL_SCATTER_GATHER)) 1395 1416 { 1396 1417 uint32_t cScatterGatherGCRead; 1397 1418 uint32_t iScatterGatherEntry; 1398 1419 SGE32 aScatterGatherReadGC[32]; /* A buffer for scatter gather list entries read from guest memory. */ 1399 uint32_t cScatterGatherGCLeft = cbDataCCB / pTaskState->cbSGEntry;1420 uint32_t cScatterGatherGCLeft = cbDataCCB / (fIs24Bit ? sizeof(SGE24) : sizeof(SGE32)); 1400 1421 RTGCPHYS GCPhysAddrScatterGatherCurrent = u32PhysAddrCCB; 1401 size_t cbDataToTransfer = 0;1402 1422 1403 1423 /* Count number of bytes to transfer. */ … … 1409 1429 cScatterGatherGCLeft -= cScatterGatherGCRead; 1410 1430 1411 buslogicR3ReadSGEntries(p TaskState, GCPhysAddrScatterGatherCurrent, cScatterGatherGCRead, aScatterGatherReadGC);1431 buslogicR3ReadSGEntries(pDevIns, fIs24Bit, GCPhysAddrScatterGatherCurrent, cScatterGatherGCRead, aScatterGatherReadGC); 1412 1432 1413 1433 for (iScatterGatherEntry = 0; iScatterGatherEntry < cScatterGatherGCRead; iScatterGatherEntry++) 1414 { 1415 RTGCPHYS GCPhysAddrDataBase; 1416 1417 Log(("%s: iScatterGatherEntry=%u\n", __FUNCTION__, iScatterGatherEntry)); 1418 1419 GCPhysAddrDataBase = (RTGCPHYS)aScatterGatherReadGC[iScatterGatherEntry].u32PhysAddrSegmentBase; 1420 cbDataToTransfer += aScatterGatherReadGC[iScatterGatherEntry].cbSegment; 1421 1422 Log(("%s: GCPhysAddrDataBase=%RGp cbDataToTransfer=%u\n", 1423 __FUNCTION__, GCPhysAddrDataBase, 1424 aScatterGatherReadGC[iScatterGatherEntry].cbSegment)); 1425 } 1434 cbBuf += aScatterGatherReadGC[iScatterGatherEntry].cbSegment; 1426 1435 1427 1436 /* Set address to the next entries to read. */ 1428 GCPhysAddrScatterGatherCurrent += cScatterGatherGCRead * pTaskState->cbSGEntry;1437 GCPhysAddrScatterGatherCurrent += cScatterGatherGCRead * (fIs24Bit ? sizeof(SGE24) : sizeof(SGE32)); 1429 1438 } while (cScatterGatherGCLeft > 0); 1430 1439 1431 Log(("%s: cbDataToTransfer=%d\n", __FUNCTION__, cbDataToTransfer)); 1432 1433 /* Allocate buffer */ 1434 pTaskState->DataSeg.cbSeg = cbDataToTransfer; 1435 pTaskState->DataSeg.pvSeg = RTMemAlloc(pTaskState->DataSeg.cbSeg); 1436 if (!pTaskState->DataSeg.pvSeg) 1437 return VERR_NO_MEMORY; 1438 1439 /* Copy the data if needed */ 1440 if ( (pTaskState->CommandControlBlockGuest.c.uDataDirection == BUSLOGIC_CCB_DIRECTION_OUT) 1441 || (pTaskState->CommandControlBlockGuest.c.uDataDirection == BUSLOGIC_CCB_DIRECTION_UNKNOWN)) 1442 { 1443 cScatterGatherGCLeft = cbDataCCB / pTaskState->cbSGEntry; 1444 GCPhysAddrScatterGatherCurrent = u32PhysAddrCCB; 1445 uint8_t *pbData = (uint8_t *)pTaskState->DataSeg.pvSeg; 1446 1447 do 1448 { 1449 cScatterGatherGCRead = (cScatterGatherGCLeft < RT_ELEMENTS(aScatterGatherReadGC)) 1450 ? cScatterGatherGCLeft 1451 : RT_ELEMENTS(aScatterGatherReadGC); 1452 cScatterGatherGCLeft -= cScatterGatherGCRead; 1453 1454 buslogicR3ReadSGEntries(pTaskState, GCPhysAddrScatterGatherCurrent, cScatterGatherGCRead, aScatterGatherReadGC); 1455 1456 for (iScatterGatherEntry = 0; iScatterGatherEntry < cScatterGatherGCRead; iScatterGatherEntry++) 1457 { 1458 RTGCPHYS GCPhysAddrDataBase; 1459 1460 Log(("%s: iScatterGatherEntry=%u\n", __FUNCTION__, iScatterGatherEntry)); 1461 1462 GCPhysAddrDataBase = (RTGCPHYS)aScatterGatherReadGC[iScatterGatherEntry].u32PhysAddrSegmentBase; 1463 cbDataToTransfer = aScatterGatherReadGC[iScatterGatherEntry].cbSegment; 1464 1465 Log(("%s: GCPhysAddrDataBase=%RGp cbDataToTransfer=%u\n", __FUNCTION__, GCPhysAddrDataBase, cbDataToTransfer)); 1466 1467 PDMDevHlpPhysRead(pDevIns, GCPhysAddrDataBase, pbData, cbDataToTransfer); 1468 pbData += cbDataToTransfer; 1469 } 1470 1471 /* Set address to the next entries to read. */ 1472 GCPhysAddrScatterGatherCurrent += cScatterGatherGCRead * pTaskState->cbSGEntry; 1473 } while (cScatterGatherGCLeft > 0); 1474 } 1475 1476 } 1477 else if ( pTaskState->CommandControlBlockGuest.c.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB 1478 || pTaskState->CommandControlBlockGuest.c.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB_RESIDUAL_DATA_LENGTH) 1479 { 1480 /* The buffer is not scattered. */ 1481 RTGCPHYS GCPhysAddrDataBase = u32PhysAddrCCB; 1482 1483 AssertMsg(GCPhysAddrDataBase != 0, ("Physical address is 0\n")); 1484 1485 pTaskState->DataSeg.cbSeg = cbDataCCB; 1486 pTaskState->DataSeg.pvSeg = RTMemAlloc(pTaskState->DataSeg.cbSeg); 1487 if (!pTaskState->DataSeg.pvSeg) 1488 return VERR_NO_MEMORY; 1489 1490 Log(("Non scattered buffer:\n")); 1491 Log(("u32PhysAddrData=%#x\n", u32PhysAddrCCB)); 1492 Log(("cbData=%u\n", cbDataCCB)); 1493 Log(("GCPhysAddrDataBase=0x%RGp\n", GCPhysAddrDataBase)); 1494 1495 /* Copy the data into the buffer. */ 1496 PDMDevHlpPhysRead(pDevIns, GCPhysAddrDataBase, pTaskState->DataSeg.pvSeg, pTaskState->DataSeg.cbSeg); 1497 } 1498 } 1499 1500 return VINF_SUCCESS; 1501 } 1502 1503 /** 1504 * Free allocated resources used for the scatter gather list. 1505 * 1506 * @returns nothing. 1507 * @param pTaskState Pointer to the task state. 1508 */ 1509 static void buslogicR3DataBufferFree(PBUSLOGICTASKSTATE pTaskState) 1510 { 1511 PPDMDEVINS pDevIns = pTaskState->CTX_SUFF(pTargetDevice)->CTX_SUFF(pBusLogic)->CTX_SUFF(pDevIns); 1440 Log(("%s: cbBuf=%d\n", __FUNCTION__, cbBuf)); 1441 } 1442 else if ( pCCBGuest->c.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB 1443 || pCCBGuest->c.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB_RESIDUAL_DATA_LENGTH) 1444 cbBuf = cbDataCCB; 1445 } 1446 1447 if (RT_SUCCESS(rc)) 1448 *pcbBuf = cbBuf; 1449 1450 return rc; 1451 } 1452 1453 /** 1454 * Copy from guest to host memory worker. 1455 * 1456 * @copydoc{BUSLOGICR3MEMCOPYCALLBACK} 1457 */ 1458 static DECLCALLBACK(void) buslogicR3CopyBufferFromGuestWorker(PBUSLOGIC pThis, RTGCPHYS GCPhys, PRTSGBUF pSgBuf, 1459 size_t cbCopy, size_t *pcbSkip) 1460 { 1461 size_t cbSkipped = RT_MIN(cbCopy, *pcbSkip); 1462 cbCopy -= cbSkipped; 1463 GCPhys += cbSkipped; 1464 *pcbSkip -= cbSkipped; 1465 1466 while (cbCopy) 1467 { 1468 size_t cbSeg = cbCopy; 1469 void *pvSeg = RTSgBufGetNextSegment(pSgBuf, &cbSeg); 1470 1471 AssertPtr(pvSeg); 1472 PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), GCPhys, pvSeg, cbSeg); 1473 GCPhys += cbSeg; 1474 cbCopy -= cbSeg; 1475 } 1476 } 1477 1478 /** 1479 * Copy from host to guest memory worker. 1480 * 1481 * @copydoc{BUSLOGICR3MEMCOPYCALLBACK} 1482 */ 1483 static DECLCALLBACK(void) buslogicR3CopyBufferToGuestWorker(PBUSLOGIC pThis, RTGCPHYS GCPhys, PRTSGBUF pSgBuf, 1484 size_t cbCopy, size_t *pcbSkip) 1485 { 1486 size_t cbSkipped = RT_MIN(cbCopy, *pcbSkip); 1487 cbCopy -= cbSkipped; 1488 GCPhys += cbSkipped; 1489 *pcbSkip -= cbSkipped; 1490 1491 while (cbCopy) 1492 { 1493 size_t cbSeg = cbCopy; 1494 void *pvSeg = RTSgBufGetNextSegment(pSgBuf, &cbSeg); 1495 1496 AssertPtr(pvSeg); 1497 PDMDevHlpPCIPhysWrite(pThis->CTX_SUFF(pDevIns), GCPhys, pvSeg, cbSeg); 1498 GCPhys += cbSeg; 1499 cbCopy -= cbSeg; 1500 } 1501 } 1502 1503 /** 1504 * Walks the guest S/G buffer calling the given copy worker for every buffer. 1505 * 1506 * @returns The amout of bytes actually copied. 1507 * @param pThis Pointer to the Buslogic device state. 1508 * @param pReq Pointe to the request state. 1509 * @param pfnCopyWorker The copy method to apply for each guest buffer. 1510 * @param pSgBuf The host S/G buffer. 1511 * @param cbSkip How many bytes to skip in advance before starting to copy. 1512 * @param cbCopy How many bytes to copy. 1513 */ 1514 static size_t buslogicR3SgBufWalker(PBUSLOGIC pThis, PBUSLOGICREQ pReq, 1515 PBUSLOGICR3MEMCOPYCALLBACK pfnCopyWorker, 1516 PRTSGBUF pSgBuf, size_t cbSkip, size_t cbCopy) 1517 { 1518 PPDMDEVINS pDevIns = pThis->CTX_SUFF(pDevIns); 1512 1519 uint32_t cbDataCCB; 1513 1520 uint32_t u32PhysAddrCCB; 1521 size_t cbCopied = 0; 1522 1523 /* 1524 * Add the amount to skip to the host buffer size to avoid a 1525 * few conditionals later on. 1526 */ 1527 cbCopy += cbSkip; 1514 1528 1515 1529 /* Extract the data length and physical address from the CCB. */ 1516 if (p TaskState->fIs24Bit)1517 { 1518 u32PhysAddrCCB = ADDR_TO_U32(p TaskState->CommandControlBlockGuest.o.aPhysAddrData);1519 cbDataCCB = LEN_TO_U32(p TaskState->CommandControlBlockGuest.o.acbData);1530 if (pReq->fIs24Bit) 1531 { 1532 u32PhysAddrCCB = ADDR_TO_U32(pReq->CCBGuest.o.aPhysAddrData); 1533 cbDataCCB = LEN_TO_U32(pReq->CCBGuest.o.acbData); 1520 1534 } 1521 1535 else 1522 1536 { 1523 u32PhysAddrCCB = p TaskState->CommandControlBlockGuest.n.u32PhysAddrData;1524 cbDataCCB = p TaskState->CommandControlBlockGuest.n.cbData;1537 u32PhysAddrCCB = pReq->CCBGuest.n.u32PhysAddrData; 1538 cbDataCCB = pReq->CCBGuest.n.cbData; 1525 1539 } 1526 1540 … … 1529 1543 * returns no data, hence the buffer must be left alone! 1530 1544 */ 1531 if (p TaskState->CommandControlBlockGuest.c.abCDB[0] == 0)1545 if (pReq->CCBGuest.c.abCDB[0] == 0) 1532 1546 cbDataCCB = 0; 1533 1547 #endif 1534 1548 1535 LogFlowFunc(("p TaskState=%#p cbDataCCB=%u direction=%u cbSeg=%u\n", pTaskState, cbDataCCB,1536 p TaskState->CommandControlBlockGuest.c.uDataDirection, pTaskState->DataSeg.cbSeg));1549 LogFlowFunc(("pReq=%#p cbDataCCB=%u direction=%u cbCopy=%zu\n", pReq, cbDataCCB, 1550 pReq->CCBGuest.c.uDataDirection, cbCopy)); 1537 1551 1538 1552 if ( (cbDataCCB > 0) 1539 && ( (pTaskState->CommandControlBlockGuest.c.uDataDirection == BUSLOGIC_CCB_DIRECTION_IN) 1540 || (pTaskState->CommandControlBlockGuest.c.uDataDirection == BUSLOGIC_CCB_DIRECTION_UNKNOWN))) 1541 { 1542 if ( (pTaskState->CommandControlBlockGuest.c.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB_SCATTER_GATHER) 1543 || (pTaskState->CommandControlBlockGuest.c.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB_RESIDUAL_SCATTER_GATHER)) 1553 && ( pReq->CCBGuest.c.uDataDirection == BUSLOGIC_CCB_DIRECTION_IN 1554 || pReq->CCBGuest.c.uDataDirection == BUSLOGIC_CCB_DIRECTION_OUT 1555 || pReq->CCBGuest.c.uDataDirection == BUSLOGIC_CCB_DIRECTION_UNKNOWN)) 1556 { 1557 if ( (pReq->CCBGuest.c.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB_SCATTER_GATHER) 1558 || (pReq->CCBGuest.c.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB_RESIDUAL_SCATTER_GATHER)) 1544 1559 { 1545 1560 uint32_t cScatterGatherGCRead; 1546 1561 uint32_t iScatterGatherEntry; 1547 1562 SGE32 aScatterGatherReadGC[32]; /* Number of scatter gather list entries read from guest memory. */ 1548 uint32_t cScatterGatherGCLeft = cbDataCCB / pTaskState->cbSGEntry;1563 uint32_t cScatterGatherGCLeft = cbDataCCB / (pReq->fIs24Bit ? sizeof(SGE24) : sizeof(SGE32)); 1549 1564 RTGCPHYS GCPhysAddrScatterGatherCurrent = u32PhysAddrCCB; 1550 uint8_t *pbData = (uint8_t *)pTaskState->DataSeg.pvSeg;1551 1565 1552 1566 do … … 1557 1571 cScatterGatherGCLeft -= cScatterGatherGCRead; 1558 1572 1559 buslogicR3ReadSGEntries(pTaskState, GCPhysAddrScatterGatherCurrent, cScatterGatherGCRead, aScatterGatherReadGC); 1560 1561 for (iScatterGatherEntry = 0; iScatterGatherEntry < cScatterGatherGCRead; iScatterGatherEntry++) 1573 buslogicR3ReadSGEntries(pDevIns, pReq->fIs24Bit, GCPhysAddrScatterGatherCurrent, 1574 cScatterGatherGCRead, aScatterGatherReadGC); 1575 1576 for (iScatterGatherEntry = 0; iScatterGatherEntry < cScatterGatherGCRead && cbCopy > 0; iScatterGatherEntry++) 1562 1577 { 1563 RTGCPHYS 1564 size_t cbDataToTransfer;1578 RTGCPHYS GCPhysAddrDataBase; 1579 size_t cbCopyThis; 1565 1580 1566 1581 Log(("%s: iScatterGatherEntry=%u\n", __FUNCTION__, iScatterGatherEntry)); 1567 1582 1568 1583 GCPhysAddrDataBase = (RTGCPHYS)aScatterGatherReadGC[iScatterGatherEntry].u32PhysAddrSegmentBase; 1569 cbDataToTransfer = aScatterGatherReadGC[iScatterGatherEntry].cbSegment; 1570 1571 Log(("%s: GCPhysAddrDataBase=%RGp cbDataToTransfer=%u\n", __FUNCTION__, GCPhysAddrDataBase, cbDataToTransfer)); 1572 1573 PDMDevHlpPCIPhysWrite(pDevIns, GCPhysAddrDataBase, pbData, cbDataToTransfer); 1574 pbData += cbDataToTransfer; 1584 cbCopyThis = RT_MIN(cbCopy, aScatterGatherReadGC[iScatterGatherEntry].cbSegment); 1585 1586 Log(("%s: GCPhysAddrDataBase=%RGp cbCopyThis=%zu\n", __FUNCTION__, GCPhysAddrDataBase, cbCopyThis)); 1587 1588 pfnCopyWorker(pThis, GCPhysAddrDataBase, pSgBuf, cbCopyThis, &cbSkip); 1589 cbCopied += cbCopyThis; 1590 cbCopy -= cbCopyThis; 1575 1591 } 1576 1592 1577 1593 /* Set address to the next entries to read. */ 1578 GCPhysAddrScatterGatherCurrent += cScatterGatherGCRead * pTaskState->cbSGEntry; 1579 } while (cScatterGatherGCLeft > 0); 1580 1581 } 1582 else if ( pTaskState->CommandControlBlockGuest.c.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB 1583 || pTaskState->CommandControlBlockGuest.c.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB_RESIDUAL_DATA_LENGTH) 1594 GCPhysAddrScatterGatherCurrent += cScatterGatherGCRead * (pReq->fIs24Bit ? sizeof(SGE24) : sizeof(SGE32)); 1595 } while ( cScatterGatherGCLeft > 0 1596 && cbCopy > 0); 1597 1598 } 1599 else if ( pReq->CCBGuest.c.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB 1600 || pReq->CCBGuest.c.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB_RESIDUAL_DATA_LENGTH) 1584 1601 { 1585 1602 /* The buffer is not scattered. */ … … 1594 1611 1595 1612 /* Copy the data into the guest memory. */ 1596 PDMDevHlpPCIPhysWrite(pDevIns, GCPhysAddrDataBase, pTaskState->DataSeg.pvSeg, pTaskState->DataSeg.cbSeg); 1597 } 1598 1599 } 1613 pfnCopyWorker(pThis, GCPhysAddrDataBase, pSgBuf, RT_MIN(cbDataCCB, cbCopy), &cbSkip); 1614 cbCopied += RT_MIN(cbDataCCB, cbCopy); 1615 } 1616 } 1617 1600 1618 /* Update residual data length. */ 1601 if ( (p TaskState->CommandControlBlockGuest.c.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB_RESIDUAL_DATA_LENGTH)1602 || (p TaskState->CommandControlBlockGuest.c.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB_RESIDUAL_SCATTER_GATHER))1619 if ( (pReq->CCBGuest.c.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB_RESIDUAL_DATA_LENGTH) 1620 || (pReq->CCBGuest.c.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB_RESIDUAL_SCATTER_GATHER)) 1603 1621 { 1604 1622 uint32_t cbResidual; … … 1606 1624 /** @todo we need to get the actual transfer length from the VSCSI layer?! */ 1607 1625 cbResidual = 0; //LEN_TO_U32(pTaskState->CCBGuest.acbData) - ???; 1608 if (p TaskState->fIs24Bit)1609 U32_TO_LEN(p TaskState->CommandControlBlockGuest.o.acbData, cbResidual);1626 if (pReq->fIs24Bit) 1627 U32_TO_LEN(pReq->CCBGuest.o.acbData, cbResidual); 1610 1628 else 1611 pTaskState->CommandControlBlockGuest.n.cbData = cbResidual; 1612 } 1613 1614 RTMemFree(pTaskState->DataSeg.pvSeg); 1615 pTaskState->DataSeg.pvSeg = NULL; 1616 pTaskState->DataSeg.cbSeg = 0; 1629 pReq->CCBGuest.n.cbData = cbResidual; 1630 } 1631 1632 return cbCopied - RT_MIN(cbSkip, cbCopied); 1633 } 1634 1635 /** 1636 * Copies a data buffer into the S/G buffer set up by the guest. 1637 * 1638 * @returns Amount of bytes copied to the guest. 1639 * @param pThis The LsiLogic controller device instance. 1640 * @param pReq Request structure. 1641 * @param pSgBuf The S/G buffer to copy from. 1642 * @param cbSkip How many bytes to skip in advance before starting to copy. 1643 * @param cbCopy How many bytes to copy. 1644 */ 1645 static size_t buslogicR3CopySgBufToGuest(PBUSLOGIC pThis, PBUSLOGICREQ pReq, PRTSGBUF pSgBuf, 1646 size_t cbSkip, size_t cbCopy) 1647 { 1648 return buslogicR3SgBufWalker(pThis, pReq, buslogicR3CopyBufferToGuestWorker, 1649 pSgBuf, cbSkip, cbCopy); 1650 } 1651 1652 /** 1653 * Copies the guest S/G buffer into a host data buffer. 1654 * 1655 * @returns Amount of bytes copied from the guest. 1656 * @param pThis The LsiLogic controller device instance. 1657 * @param pReq Request structure. 1658 * @param pSgBuf The S/G buffer to copy into. 1659 * @param cbSkip How many bytes to skip in advance before starting to copy. 1660 * @param cbCopy How many bytes to copy. 1661 */ 1662 static size_t buslogicR3CopySgBufFromGuest(PBUSLOGIC pThis, PBUSLOGICREQ pReq, PRTSGBUF pSgBuf, 1663 size_t cbSkip, size_t cbCopy) 1664 { 1665 return buslogicR3SgBufWalker(pThis, pReq, buslogicR3CopyBufferFromGuestWorker, 1666 pSgBuf, cbSkip, cbCopy); 1617 1667 } 1618 1668 … … 1635 1685 * 1636 1686 * @returns nothing. 1637 * @param p TaskState Pointer to the taskstate.1687 * @param pReq Pointer to the request state. 1638 1688 * @param fCopy If sense data should be copied to guest memory. 1639 1689 */ 1640 static void buslogicR3SenseBufferFree(PBUSLOGIC TASKSTATE pTaskState, bool fCopy)1690 static void buslogicR3SenseBufferFree(PBUSLOGICREQ pReq, bool fCopy) 1641 1691 { 1642 1692 uint32_t cbSenseBuffer; 1643 1693 1644 cbSenseBuffer = buslogicR3ConvertSenseBufferLength(p TaskState->CommandControlBlockGuest.c.cbSenseData);1694 cbSenseBuffer = buslogicR3ConvertSenseBufferLength(pReq->CCBGuest.c.cbSenseData); 1645 1695 1646 1696 /* Copy the sense buffer into guest memory if requested. */ 1647 1697 if (fCopy && cbSenseBuffer) 1648 1698 { 1649 PPDMDEVINS pDevIns = p TaskState->CTX_SUFF(pTargetDevice)->CTX_SUFF(pBusLogic)->CTX_SUFF(pDevIns);1699 PPDMDEVINS pDevIns = pReq->pTargetDevice->CTX_SUFF(pBusLogic)->CTX_SUFF(pDevIns); 1650 1700 RTGCPHYS GCPhysAddrSenseBuffer; 1651 1701 … … 1654 1704 * the CCB, right after the variable-length CDB. 1655 1705 */ 1656 if (p TaskState->fIs24Bit)1657 { 1658 GCPhysAddrSenseBuffer = p TaskState->MailboxGuest.u32PhysAddrCCB;1659 GCPhysAddrSenseBuffer += p TaskState->CommandControlBlockGuest.c.cbCDB + RT_OFFSETOF(CCB24, abCDB);1706 if (pReq->fIs24Bit) 1707 { 1708 GCPhysAddrSenseBuffer = pReq->GCPhysAddrCCB; 1709 GCPhysAddrSenseBuffer += pReq->CCBGuest.c.cbCDB + RT_OFFSETOF(CCB24, abCDB); 1660 1710 } 1661 1711 else 1662 GCPhysAddrSenseBuffer = p TaskState->CommandControlBlockGuest.n.u32PhysAddrSenseData;1663 1664 Log3(("%s: sense buffer: %.*Rhxs\n", __FUNCTION__, cbSenseBuffer, p TaskState->pbSenseBuffer));1665 PDMDevHlpPCIPhysWrite(pDevIns, GCPhysAddrSenseBuffer, p TaskState->pbSenseBuffer, cbSenseBuffer);1666 } 1667 1668 RTMemFree(p TaskState->pbSenseBuffer);1669 p TaskState->pbSenseBuffer = NULL;1712 GCPhysAddrSenseBuffer = pReq->CCBGuest.n.u32PhysAddrSenseData; 1713 1714 Log3(("%s: sense buffer: %.*Rhxs\n", __FUNCTION__, cbSenseBuffer, pReq->pbSenseBuffer)); 1715 PDMDevHlpPCIPhysWrite(pDevIns, GCPhysAddrSenseBuffer, pReq->pbSenseBuffer, cbSenseBuffer); 1716 } 1717 1718 RTMemFree(pReq->pbSenseBuffer); 1719 pReq->pbSenseBuffer = NULL; 1670 1720 } 1671 1721 … … 1674 1724 * 1675 1725 * @returns VBox status code. 1676 * @param pTaskState Pointer to the task state. 1677 * @note Current assumption is that the sense buffer is not scattered and does not cross a page boundary. 1678 */ 1679 static int buslogicR3SenseBufferAlloc(PBUSLOGICTASKSTATE pTaskState) 1680 { 1681 pTaskState->pbSenseBuffer = NULL; 1682 1683 uint32_t cbSenseBuffer = buslogicR3ConvertSenseBufferLength(pTaskState->CommandControlBlockGuest.c.cbSenseData); 1726 * @param pReq Pointer to the task state. 1727 */ 1728 static int buslogicR3SenseBufferAlloc(PBUSLOGICREQ pReq) 1729 { 1730 pReq->pbSenseBuffer = NULL; 1731 1732 uint32_t cbSenseBuffer = buslogicR3ConvertSenseBufferLength(pReq->CCBGuest.c.cbSenseData); 1684 1733 if (cbSenseBuffer) 1685 1734 { 1686 p TaskState->pbSenseBuffer = (uint8_t *)RTMemAllocZ(cbSenseBuffer);1687 if (!p TaskState->pbSenseBuffer)1735 pReq->pbSenseBuffer = (uint8_t *)RTMemAllocZ(cbSenseBuffer); 1736 if (!pReq->pbSenseBuffer) 1688 1737 return VERR_NO_MEMORY; 1689 1738 } … … 2488 2537 #ifdef IN_RING3 2489 2538 2490 static int buslogicR3PrepareBIOSSCSIRequest(PBUSLOGIC pBusLogic) 2491 { 2492 int rc; 2493 PBUSLOGICTASKSTATE pTaskState; 2494 uint32_t uTargetDevice; 2495 2496 rc = RTMemCacheAllocEx(pBusLogic->hTaskCache, (void **)&pTaskState); 2497 AssertMsgRCReturn(rc, ("Getting task from cache failed rc=%Rrc\n", rc), rc); 2498 2499 pTaskState->fBIOS = true; 2500 2501 rc = vboxscsiSetupRequest(&pBusLogic->VBoxSCSI, &pTaskState->PDMScsiRequest, &uTargetDevice); 2539 static int buslogicR3PrepareBIOSSCSIRequest(PBUSLOGIC pThis) 2540 { 2541 uint32_t uTargetDevice; 2542 uint32_t uLun; 2543 uint8_t *pbCdb; 2544 size_t cbCdb; 2545 size_t cbBuf; 2546 2547 int rc = vboxscsiSetupRequest(&pThis->VBoxSCSI, &uLun, &pbCdb, &cbCdb, &cbBuf, &uTargetDevice); 2502 2548 AssertMsgRCReturn(rc, ("Setting up SCSI request failed rc=%Rrc\n", rc), rc); 2503 2549 2504 pTaskState->PDMScsiRequest.pvUser = pTaskState; 2505 2506 pTaskState->CTX_SUFF(pTargetDevice) = &pBusLogic->aDeviceStates[uTargetDevice]; 2507 2508 if (!pTaskState->CTX_SUFF(pTargetDevice)->fPresent) 2509 { 2510 /* Device is not present. */ 2511 AssertMsg(pTaskState->PDMScsiRequest.pbCDB[0] == SCSI_INQUIRY, 2512 ("Device is not present but command is not inquiry\n")); 2513 2514 SCSIINQUIRYDATA ScsiInquiryData; 2515 2516 memset(&ScsiInquiryData, 0, sizeof(SCSIINQUIRYDATA)); 2517 ScsiInquiryData.u5PeripheralDeviceType = SCSI_INQUIRY_DATA_PERIPHERAL_DEVICE_TYPE_UNKNOWN; 2518 ScsiInquiryData.u3PeripheralQualifier = SCSI_INQUIRY_DATA_PERIPHERAL_QUALIFIER_NOT_CONNECTED_NOT_SUPPORTED; 2519 2520 memcpy(pBusLogic->VBoxSCSI.pbBuf, &ScsiInquiryData, 5); 2521 2522 rc = vboxscsiRequestFinished(&pBusLogic->VBoxSCSI, &pTaskState->PDMScsiRequest, SCSI_STATUS_OK); 2523 AssertMsgRCReturn(rc, ("Finishing BIOS SCSI request failed rc=%Rrc\n", rc), rc); 2524 2525 RTMemCacheFree(pBusLogic->hTaskCache, pTaskState); 2526 } 2527 else 2528 { 2529 LogFlowFunc(("before increment %u\n", pTaskState->CTX_SUFF(pTargetDevice)->cOutstandingRequests)); 2530 ASMAtomicIncU32(&pTaskState->CTX_SUFF(pTargetDevice)->cOutstandingRequests); 2531 LogFlowFunc(("after increment %u\n", pTaskState->CTX_SUFF(pTargetDevice)->cOutstandingRequests)); 2532 2533 rc = pTaskState->CTX_SUFF(pTargetDevice)->pDrvSCSIConnector->pfnSCSIRequestSend(pTaskState->CTX_SUFF(pTargetDevice)->pDrvSCSIConnector, 2534 &pTaskState->PDMScsiRequest); 2535 AssertMsgRC(rc, ("Sending request to SCSI layer failed rc=%Rrc\n", rc)); 2536 } 2550 if ( uTargetDevice < RT_ELEMENTS(pThis->aDeviceStates) 2551 && pThis->aDeviceStates[uTargetDevice].pDrvBase) 2552 { 2553 PBUSLOGICDEVICE pTgtDev = &pThis->aDeviceStates[uTargetDevice]; 2554 PDMMEDIAEXIOREQ hIoReq; 2555 PBUSLOGICREQ pReq; 2556 2557 rc = pTgtDev->pDrvMediaEx->pfnIoReqAlloc(pTgtDev->pDrvMediaEx, &hIoReq, (void **)&pReq, 2558 0, PDMIMEDIAEX_F_SUSPEND_ON_RECOVERABLE_ERR); 2559 AssertMsgRCReturn(rc, ("Getting task from cache failed rc=%Rrc\n", rc), rc); 2560 2561 pReq->fBIOS = true; 2562 pReq->hIoReq = hIoReq; 2563 pReq->pTargetDevice = pTgtDev; 2564 2565 ASMAtomicIncU32(&pTgtDev->cOutstandingRequests); 2566 2567 rc = pTgtDev->pDrvMediaEx->pfnIoReqSendScsiCmd(pTgtDev->pDrvMediaEx, pReq->hIoReq, uLun, 2568 pbCdb, cbCdb, PDMMEDIAEXIOREQSCSITXDIR_UNKNOWN, 2569 cbBuf, NULL, 0, &pReq->u8ScsiSts, 30 * RT_MS_1SEC); 2570 if (rc == VINF_SUCCESS || rc != VINF_PDM_MEDIAEX_IOREQ_IN_PROGRESS) 2571 { 2572 uint8_t u8ScsiSts = pReq->u8ScsiSts; 2573 pTgtDev->pDrvMediaEx->pfnIoReqFree(pTgtDev->pDrvMediaEx, pReq->hIoReq); 2574 rc = vboxscsiRequestFinished(&pThis->VBoxSCSI, u8ScsiSts); 2575 } 2576 else if (rc == VINF_PDM_MEDIAEX_IOREQ_IN_PROGRESS) 2577 rc = VINF_SUCCESS; 2578 2579 return rc; 2580 } 2581 2582 /* Device is not present. */ 2583 AssertMsg(pbCdb[0] == SCSI_INQUIRY, 2584 ("Device is not present but command is not inquiry\n")); 2585 2586 SCSIINQUIRYDATA ScsiInquiryData; 2587 2588 memset(&ScsiInquiryData, 0, sizeof(SCSIINQUIRYDATA)); 2589 ScsiInquiryData.u5PeripheralDeviceType = SCSI_INQUIRY_DATA_PERIPHERAL_DEVICE_TYPE_UNKNOWN; 2590 ScsiInquiryData.u3PeripheralQualifier = SCSI_INQUIRY_DATA_PERIPHERAL_QUALIFIER_NOT_CONNECTED_NOT_SUPPORTED; 2591 2592 memcpy(pThis->VBoxSCSI.pbBuf, &ScsiInquiryData, 5); 2593 2594 rc = vboxscsiRequestFinished(&pThis->VBoxSCSI, SCSI_STATUS_OK); 2595 AssertMsgRCReturn(rc, ("Finishing BIOS SCSI request failed rc=%Rrc\n", rc), rc); 2537 2596 2538 2597 return rc; … … 2715 2774 } 2716 2775 2717 static void buslogicR3WarningDiskFull(PPDMDEVINS pDevIns)2718 {2719 int rc;2720 LogRel(("BusLogic#%d: Host disk full\n", pDevIns->iInstance));2721 rc = PDMDevHlpVMSetRuntimeError(pDevIns, VMSETRTERR_FLAGS_SUSPEND | VMSETRTERR_FLAGS_NO_WAIT, "DevBusLogic_DISKFULL",2722 N_("Host system reported disk full. VM execution is suspended. You can resume after freeing some space"));2723 AssertRC(rc);2724 }2725 2726 static void buslogicR3WarningFileTooBig(PPDMDEVINS pDevIns)2727 {2728 int rc;2729 LogRel(("BusLogic#%d: File too big\n", pDevIns->iInstance));2730 rc = PDMDevHlpVMSetRuntimeError(pDevIns, VMSETRTERR_FLAGS_SUSPEND | VMSETRTERR_FLAGS_NO_WAIT, "DevBusLogic_FILETOOBIG",2731 N_("Host system reported that the file size limit of the host file system has been exceeded. VM execution is suspended. You need to move your virtual hard disk to a filesystem which allows bigger files"));2732 AssertRC(rc);2733 }2734 2735 static void buslogicR3WarningISCSI(PPDMDEVINS pDevIns)2736 {2737 int rc;2738 LogRel(("BusLogic#%d: iSCSI target unavailable\n", pDevIns->iInstance));2739 rc = PDMDevHlpVMSetRuntimeError(pDevIns, VMSETRTERR_FLAGS_SUSPEND | VMSETRTERR_FLAGS_NO_WAIT, "DevBusLogic_ISCSIDOWN",2740 N_("The iSCSI target has stopped responding. VM execution is suspended. You can resume when it is available again"));2741 AssertRC(rc);2742 }2743 2744 static void buslogicR3WarningUnknown(PPDMDEVINS pDevIns, int rc)2745 {2746 int rc2;2747 LogRel(("BusLogic#%d: Unknown but recoverable error has occurred (rc=%Rrc)\n", pDevIns->iInstance, rc));2748 rc2 = PDMDevHlpVMSetRuntimeError(pDevIns, VMSETRTERR_FLAGS_SUSPEND | VMSETRTERR_FLAGS_NO_WAIT, "DevBusLogic_UNKNOWN",2749 N_("An unknown but recoverable I/O error has occurred (rc=%Rrc). VM execution is suspended. You can resume when the error is fixed"), rc);2750 AssertRC(rc2);2751 }2752 2753 static void buslogicR3RedoSetWarning(PBUSLOGIC pThis, int rc)2754 {2755 if (rc == VERR_DISK_FULL)2756 buslogicR3WarningDiskFull(pThis->CTX_SUFF(pDevIns));2757 else if (rc == VERR_FILE_TOO_BIG)2758 buslogicR3WarningFileTooBig(pThis->CTX_SUFF(pDevIns));2759 else if (rc == VERR_BROKEN_PIPE || rc == VERR_NET_CONNECTION_REFUSED)2760 {2761 /* iSCSI connection abort (first error) or failure to reestablish2762 * connection (second error). Pause VM. On resume we'll retry. */2763 buslogicR3WarningISCSI(pThis->CTX_SUFF(pDevIns));2764 }2765 else if (rc != VERR_VD_DEK_MISSING)2766 buslogicR3WarningUnknown(pThis->CTX_SUFF(pDevIns), rc);2767 }2768 2769 2776 2770 2777 /** … … 2841 2848 } 2842 2849 2843 static DECLCALLBACK(int) buslogicR3DeviceSCSIRequestCompleted(PPDMISCSIPORT pInterface, PPDMSCSIREQUEST pSCSIRequest, 2844 int rcCompletion, bool fRedo, int rcReq) 2845 { 2846 RT_NOREF(pInterface); 2847 int rc; 2848 PBUSLOGICTASKSTATE pTaskState = (PBUSLOGICTASKSTATE)pSCSIRequest->pvUser; 2849 PBUSLOGICDEVICE pBusLogicDevice = pTaskState->CTX_SUFF(pTargetDevice); 2850 PBUSLOGIC pBusLogic = pBusLogicDevice->CTX_SUFF(pBusLogic); 2851 2852 LogFlowFunc(("before decrement %u\n", pBusLogicDevice->cOutstandingRequests)); 2853 ASMAtomicDecU32(&pBusLogicDevice->cOutstandingRequests); 2854 LogFlowFunc(("after decrement %u\n", pBusLogicDevice->cOutstandingRequests)); 2855 2856 if (fRedo) 2857 { 2858 if (!pTaskState->fBIOS) 2859 { 2860 buslogicR3DataBufferFree(pTaskState); 2861 2862 if (pTaskState->pbSenseBuffer) 2863 buslogicR3SenseBufferFree(pTaskState, false /* fCopy */); 2864 } 2865 2866 /* Add to the list. */ 2867 do 2868 { 2869 pTaskState->pRedoNext = ASMAtomicReadPtrT(&pBusLogic->pTasksRedoHead, PBUSLOGICTASKSTATE); 2870 } while (!ASMAtomicCmpXchgPtr(&pBusLogic->pTasksRedoHead, pTaskState, pTaskState->pRedoNext)); 2871 2872 /* Suspend the VM if not done already. */ 2873 if (!ASMAtomicXchgBool(&pBusLogic->fRedo, true)) 2874 buslogicR3RedoSetWarning(pBusLogic, rcReq); 2850 static int buslogicR3ReqComplete(PBUSLOGIC pThis, PBUSLOGICREQ pReq, int rcReq) 2851 { 2852 RT_NOREF(rcReq); 2853 PBUSLOGICDEVICE pTgtDev = pReq->pTargetDevice; 2854 2855 LogFlowFunc(("before decrement %u\n", pTgtDev->cOutstandingRequests)); 2856 ASMAtomicDecU32(&pTgtDev->cOutstandingRequests); 2857 LogFlowFunc(("after decrement %u\n", pTgtDev->cOutstandingRequests)); 2858 2859 if (pReq->fBIOS) 2860 { 2861 int rc = vboxscsiRequestFinished(&pThis->VBoxSCSI, pReq->u8ScsiSts); 2862 AssertMsgRC(rc, ("Finishing BIOS SCSI request failed rc=%Rrc\n", rc)); 2875 2863 } 2876 2864 else 2877 2865 { 2878 if (pTaskState->fBIOS) 2879 { 2880 rc = vboxscsiRequestFinished(&pBusLogic->VBoxSCSI, pSCSIRequest, rcCompletion); 2881 AssertMsgRC(rc, ("Finishing BIOS SCSI request failed rc=%Rrc\n", rc)); 2882 } 2866 if (pReq->pbSenseBuffer) 2867 buslogicR3SenseBufferFree(pReq, (pReq->u8ScsiSts != SCSI_STATUS_OK)); 2868 2869 if (pReq->u8ScsiSts == SCSI_STATUS_OK) 2870 buslogicR3SendIncomingMailbox(pThis, pReq->GCPhysAddrCCB, &pReq->CCBGuest, 2871 BUSLOGIC_MAILBOX_INCOMING_ADAPTER_STATUS_CMD_COMPLETED, 2872 BUSLOGIC_MAILBOX_INCOMING_DEVICE_STATUS_OPERATION_GOOD, 2873 BUSLOGIC_MAILBOX_INCOMING_COMPLETION_WITHOUT_ERROR); 2874 else if (pReq->u8ScsiSts == SCSI_STATUS_CHECK_CONDITION) 2875 buslogicR3SendIncomingMailbox(pThis, pReq->GCPhysAddrCCB, &pReq->CCBGuest, 2876 BUSLOGIC_MAILBOX_INCOMING_ADAPTER_STATUS_CMD_COMPLETED, 2877 BUSLOGIC_MAILBOX_INCOMING_DEVICE_STATUS_CHECK_CONDITION, 2878 BUSLOGIC_MAILBOX_INCOMING_COMPLETION_WITH_ERROR); 2883 2879 else 2884 { 2885 buslogicR3DataBufferFree(pTaskState); 2886 2887 if (pTaskState->pbSenseBuffer) 2888 buslogicR3SenseBufferFree(pTaskState, (rcCompletion != SCSI_STATUS_OK)); 2889 2890 if (rcCompletion == SCSI_STATUS_OK) 2891 buslogicR3SendIncomingMailbox(pBusLogic, pTaskState, 2892 BUSLOGIC_MAILBOX_INCOMING_ADAPTER_STATUS_CMD_COMPLETED, 2893 BUSLOGIC_MAILBOX_INCOMING_DEVICE_STATUS_OPERATION_GOOD, 2894 BUSLOGIC_MAILBOX_INCOMING_COMPLETION_WITHOUT_ERROR); 2895 else if (rcCompletion == SCSI_STATUS_CHECK_CONDITION) 2896 buslogicR3SendIncomingMailbox(pBusLogic, pTaskState, 2897 BUSLOGIC_MAILBOX_INCOMING_ADAPTER_STATUS_CMD_COMPLETED, 2898 BUSLOGIC_MAILBOX_INCOMING_DEVICE_STATUS_CHECK_CONDITION, 2899 BUSLOGIC_MAILBOX_INCOMING_COMPLETION_WITH_ERROR); 2900 else 2901 AssertMsgFailed(("invalid completion status %d\n", rcCompletion)); 2902 } 2880 AssertMsgFailed(("invalid completion status %d\n", pReq->u8ScsiSts)); 2881 } 2882 2903 2883 #ifdef LOG_ENABLED 2904 buslogicR3DumpCCBInfo(&pTaskState->CommandControlBlockGuest, pTaskState->fIs24Bit);2884 buslogicR3DumpCCBInfo(&pReq->CCBGuest, pReq->fIs24Bit); 2905 2885 #endif 2906 2886 2907 /* Remove task from the cache. */ 2908 RTMemCacheFree(pBusLogic->hTaskCache, pTaskState); 2909 } 2910 2911 if (pBusLogicDevice->cOutstandingRequests == 0 && pBusLogic->fSignalIdle) 2912 PDMDevHlpAsyncNotificationCompleted(pBusLogic->pDevInsR3); 2887 if (pTgtDev->cOutstandingRequests == 0 && pThis->fSignalIdle) 2888 PDMDevHlpAsyncNotificationCompleted(pThis->pDevInsR3); 2913 2889 2914 2890 return VINF_SUCCESS; 2915 2891 } 2916 2892 2917 static DECLCALLBACK(int) buslogicR3QueryDeviceLocation(PPDMI SCSIPORT pInterface, const char **ppcszController,2893 static DECLCALLBACK(int) buslogicR3QueryDeviceLocation(PPDMIMEDIAPORT pInterface, const char **ppcszController, 2918 2894 uint32_t *piInstance, uint32_t *piLUN) 2919 2895 { 2920 PBUSLOGICDEVICE pBusLogicDevice = PDMISCSIPORT_2_PBUSLOGICDEVICE(pInterface);2896 PBUSLOGICDEVICE pBusLogicDevice = RT_FROM_MEMBER(pInterface, BUSLOGICDEVICE, IMediaPort); 2921 2897 PPDMDEVINS pDevIns = pBusLogicDevice->CTX_SUFF(pBusLogic)->CTX_SUFF(pDevIns); 2922 2898 … … 2932 2908 } 2933 2909 2934 static int buslogicR3DeviceSCSIRequestSetup(PBUSLOGIC pBusLogic, PBUSLOGICTASKSTATE pTaskState) 2910 /** 2911 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqCopyFromBuf} 2912 */ 2913 static DECLCALLBACK(int) buslogicR3IoReqCopyFromBuf(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq, 2914 void *pvIoReqAlloc, uint32_t offDst, PRTSGBUF pSgBuf, 2915 size_t cbCopy) 2916 { 2917 RT_NOREF1(hIoReq); 2918 PBUSLOGICDEVICE pTgtDev = RT_FROM_MEMBER(pInterface, BUSLOGICDEVICE, IMediaExPort); 2919 PBUSLOGICREQ pReq = (PBUSLOGICREQ)pvIoReqAlloc; 2920 2921 size_t cbCopied = 0; 2922 if (RT_UNLIKELY(pReq->fBIOS)) 2923 cbCopied = vboxscsiCopyToBuf(&pTgtDev->CTX_SUFF(pBusLogic)->VBoxSCSI, pSgBuf, offDst, cbCopy); 2924 else 2925 cbCopied = buslogicR3CopySgBufToGuest(pTgtDev->CTX_SUFF(pBusLogic), pReq, pSgBuf, offDst, cbCopy); 2926 return cbCopied == cbCopy ? VINF_SUCCESS : VERR_PDM_MEDIAEX_IOBUF_OVERFLOW; 2927 } 2928 2929 /** 2930 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqCopyToBuf} 2931 */ 2932 static DECLCALLBACK(int) buslogicR3IoReqCopyToBuf(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq, 2933 void *pvIoReqAlloc, uint32_t offSrc, PRTSGBUF pSgBuf, 2934 size_t cbCopy) 2935 { 2936 RT_NOREF1(hIoReq); 2937 PBUSLOGICDEVICE pTgtDev = RT_FROM_MEMBER(pInterface, BUSLOGICDEVICE, IMediaExPort); 2938 PBUSLOGICREQ pReq = (PBUSLOGICREQ)pvIoReqAlloc; 2939 2940 size_t cbCopied = 0; 2941 if (RT_UNLIKELY(pReq->fBIOS)) 2942 cbCopied = vboxscsiCopyFromBuf(&pTgtDev->CTX_SUFF(pBusLogic)->VBoxSCSI, pSgBuf, offSrc, cbCopy); 2943 else 2944 cbCopied = buslogicR3CopySgBufFromGuest(pTgtDev->CTX_SUFF(pBusLogic), pReq, pSgBuf, offSrc, cbCopy); 2945 return cbCopied == cbCopy ? VINF_SUCCESS : VERR_PDM_MEDIAEX_IOBUF_UNDERRUN; 2946 } 2947 2948 /** 2949 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqCompleteNotify} 2950 */ 2951 static DECLCALLBACK(int) buslogicR3IoReqCompleteNotify(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq, 2952 void *pvIoReqAlloc, int rcReq) 2953 { 2954 RT_NOREF(hIoReq); 2955 PBUSLOGICDEVICE pTgtDev = RT_FROM_MEMBER(pInterface, BUSLOGICDEVICE, IMediaExPort); 2956 buslogicR3ReqComplete(pTgtDev->CTX_SUFF(pBusLogic), (PBUSLOGICREQ)pvIoReqAlloc, rcReq); 2957 return VINF_SUCCESS; 2958 } 2959 2960 /** 2961 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqStateChanged} 2962 */ 2963 static DECLCALLBACK(void) buslogicR3IoReqStateChanged(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq, 2964 void *pvIoReqAlloc, PDMMEDIAEXIOREQSTATE enmState) 2965 { 2966 RT_NOREF3(hIoReq, pvIoReqAlloc, enmState); 2967 PBUSLOGICDEVICE pTgtDev = RT_FROM_MEMBER(pInterface, BUSLOGICDEVICE, IMediaExPort); 2968 2969 switch (enmState) 2970 { 2971 case PDMMEDIAEXIOREQSTATE_SUSPENDED: 2972 { 2973 /* Make sure the request is not accounted for so the VM can suspend successfully. */ 2974 uint32_t cTasksActive = ASMAtomicDecU32(&pTgtDev->cOutstandingRequests); 2975 if (!cTasksActive && pTgtDev->CTX_SUFF(pBusLogic)->fSignalIdle) 2976 PDMDevHlpAsyncNotificationCompleted(pTgtDev->CTX_SUFF(pBusLogic)->pDevInsR3); 2977 break; 2978 } 2979 case PDMMEDIAEXIOREQSTATE_ACTIVE: 2980 /* Make sure the request is accounted for so the VM suspends only when the request is complete. */ 2981 ASMAtomicIncU32(&pTgtDev->cOutstandingRequests); 2982 break; 2983 default: 2984 AssertMsgFailed(("Invalid request state given %u\n", enmState)); 2985 } 2986 } 2987 2988 /** 2989 * @interface_method_impl{PDMIMEDIAEXPORT,pfnMediumEjected} 2990 */ 2991 static DECLCALLBACK(void) buslogicR3MediumEjected(PPDMIMEDIAEXPORT pInterface) 2992 { 2993 PBUSLOGICDEVICE pTgtDev = RT_FROM_MEMBER(pInterface, BUSLOGICDEVICE, IMediaExPort); 2994 PBUSLOGIC pThis = pTgtDev->CTX_SUFF(pBusLogic); 2995 2996 RT_NOREF(pThis); /** @todo */ 2997 } 2998 2999 static int buslogicR3DeviceSCSIRequestSetup(PBUSLOGIC pBusLogic, RTGCPHYS GCPhysAddrCCB) 2935 3000 { 2936 3001 int rc = VINF_SUCCESS; 2937 3002 uint8_t uTargetIdCCB; 2938 PBUSLOGICDEVICE pTargetDevice;3003 CCBU CCBGuest; 2939 3004 2940 3005 /* Fetch the CCB from guest memory. */ 2941 3006 /** @todo How much do we really have to read? */ 2942 RTGCPHYS GCPhysAddrCCB = (RTGCPHYS)pTaskState->MailboxGuest.u32PhysAddrCCB;2943 3007 PDMDevHlpPhysRead(pBusLogic->CTX_SUFF(pDevIns), GCPhysAddrCCB, 2944 &pTaskState->CommandControlBlockGuest, sizeof(CCB32));2945 2946 uTargetIdCCB = p TaskState->fIs24Bit ? pTaskState->CommandControlBlockGuest.o.uTargetId : pTaskState->CommandControlBlockGuest.n.uTargetId;3008 &CCBGuest, sizeof(CCB32)); 3009 3010 uTargetIdCCB = pBusLogic->fMbxIs24Bit ? CCBGuest.o.uTargetId : CCBGuest.n.uTargetId; 2947 3011 if (RT_LIKELY(uTargetIdCCB < RT_ELEMENTS(pBusLogic->aDeviceStates))) 2948 3012 { 2949 pTargetDevice = &pBusLogic->aDeviceStates[uTargetIdCCB]; 2950 pTaskState->CTX_SUFF(pTargetDevice) = pTargetDevice; 3013 PBUSLOGICDEVICE pTgtDev = &pBusLogic->aDeviceStates[uTargetIdCCB]; 2951 3014 2952 3015 #ifdef LOG_ENABLED 2953 buslogicR3DumpCCBInfo(& pTaskState->CommandControlBlockGuest, pTaskState->fIs24Bit);3016 buslogicR3DumpCCBInfo(&CCBGuest, pBusLogic->fMbxIs24Bit); 2954 3017 #endif 2955 3018 2956 /* Alloc required buffers. */2957 rc = buslogicR3DataBufferAlloc(pTaskState);2958 AssertMsgRC(rc, ("Alloc failed rc=%Rrc\n", rc));2959 2960 rc = buslogicR3SenseBufferAlloc(pTaskState);2961 AssertMsgRC(rc, ("Mapping sense buffer failed rc=%Rrc\n", rc));2962 2963 3019 /* Check if device is present on bus. If not return error immediately and don't process this further. */ 2964 if (!pBusLogic->aDeviceStates[uTargetIdCCB].fPresent) 2965 { 2966 buslogicR3DataBufferFree(pTaskState); 2967 2968 if (pTaskState->pbSenseBuffer) 2969 buslogicR3SenseBufferFree(pTaskState, true); 2970 2971 buslogicR3SendIncomingMailbox(pBusLogic, pTaskState, 3020 if (RT_LIKELY(pTgtDev->fPresent)) 3021 { 3022 PDMMEDIAEXIOREQ hIoReq; 3023 PBUSLOGICREQ pReq; 3024 rc = pTgtDev->pDrvMediaEx->pfnIoReqAlloc(pTgtDev->pDrvMediaEx, &hIoReq, (void **)&pReq, 3025 GCPhysAddrCCB, PDMIMEDIAEX_F_SUSPEND_ON_RECOVERABLE_ERR); 3026 if (RT_SUCCESS(rc)) 3027 { 3028 pReq->pTargetDevice = pTgtDev; 3029 pReq->GCPhysAddrCCB = GCPhysAddrCCB; 3030 pReq->fBIOS = false; 3031 pReq->hIoReq = hIoReq; 3032 pReq->fIs24Bit = pBusLogic->fMbxIs24Bit; 3033 3034 /* Make a copy of the CCB */ 3035 memcpy(&pReq->CCBGuest, &CCBGuest, sizeof(CCBGuest)); 3036 3037 /* Alloc required buffers. */ 3038 rc = buslogicR3SenseBufferAlloc(pReq); 3039 AssertMsgRC(rc, ("Mapping sense buffer failed rc=%Rrc\n", rc)); 3040 3041 size_t cbBuf = 0; 3042 rc = buslogicR3QueryDataBufferSize(pBusLogic->CTX_SUFF(pDevIns), &pReq->CCBGuest, pReq->fIs24Bit, &cbBuf); 3043 AssertRC(rc); 3044 3045 uint32_t uLun = pReq->fIs24Bit ? pReq->CCBGuest.o.uLogicalUnit 3046 : pReq->CCBGuest.n.uLogicalUnit; 3047 3048 PDMMEDIAEXIOREQSCSITXDIR enmXferDir = PDMMEDIAEXIOREQSCSITXDIR_UNKNOWN; 3049 size_t cbSense = buslogicR3ConvertSenseBufferLength(CCBGuest.c.cbSenseData); 3050 3051 if (CCBGuest.c.uDataDirection == BUSLOGIC_CCB_DIRECTION_NO_DATA) 3052 enmXferDir = PDMMEDIAEXIOREQSCSITXDIR_NONE; 3053 else if (CCBGuest.c.uDataDirection == BUSLOGIC_CCB_DIRECTION_OUT) 3054 enmXferDir = PDMMEDIAEXIOREQSCSITXDIR_TO_DEVICE; 3055 else if (CCBGuest.c.uDataDirection == BUSLOGIC_CCB_DIRECTION_IN) 3056 enmXferDir = PDMMEDIAEXIOREQSCSITXDIR_FROM_DEVICE; 3057 3058 ASMAtomicIncU32(&pTgtDev->cOutstandingRequests); 3059 rc = pTgtDev->pDrvMediaEx->pfnIoReqSendScsiCmd(pTgtDev->pDrvMediaEx, pReq->hIoReq, uLun, 3060 &pReq->CCBGuest.c.abCDB[0], pReq->CCBGuest.c.cbCDB, 3061 enmXferDir, cbBuf, pReq->pbSenseBuffer, cbSense, 3062 &pReq->u8ScsiSts, 30 * RT_MS_1SEC); 3063 if (rc != VINF_PDM_MEDIAEX_IOREQ_IN_PROGRESS) 3064 buslogicR3ReqComplete(pBusLogic, pReq, rc); 3065 } 3066 else 3067 buslogicR3SendIncomingMailbox(pBusLogic, GCPhysAddrCCB, &CCBGuest, 3068 BUSLOGIC_MAILBOX_INCOMING_ADAPTER_STATUS_SCSI_SELECTION_TIMEOUT, 3069 BUSLOGIC_MAILBOX_INCOMING_DEVICE_STATUS_OPERATION_GOOD, 3070 BUSLOGIC_MAILBOX_INCOMING_COMPLETION_WITH_ERROR); 3071 } 3072 else 3073 buslogicR3SendIncomingMailbox(pBusLogic, GCPhysAddrCCB, &CCBGuest, 2972 3074 BUSLOGIC_MAILBOX_INCOMING_ADAPTER_STATUS_SCSI_SELECTION_TIMEOUT, 2973 3075 BUSLOGIC_MAILBOX_INCOMING_DEVICE_STATUS_OPERATION_GOOD, 2974 3076 BUSLOGIC_MAILBOX_INCOMING_COMPLETION_WITH_ERROR); 2975 2976 RTMemCacheFree(pBusLogic->hTaskCache, pTaskState);2977 }2978 else2979 {2980 /* Setup SCSI request. */2981 pTaskState->PDMScsiRequest.uLogicalUnit = pTaskState->fIs24Bit ? pTaskState->CommandControlBlockGuest.o.uLogicalUnit2982 : pTaskState->CommandControlBlockGuest.n.uLogicalUnit;2983 2984 if (pTaskState->CommandControlBlockGuest.c.uDataDirection == BUSLOGIC_CCB_DIRECTION_UNKNOWN)2985 pTaskState->PDMScsiRequest.uDataDirection = PDMSCSIREQUESTTXDIR_UNKNOWN;2986 else if (pTaskState->CommandControlBlockGuest.c.uDataDirection == BUSLOGIC_CCB_DIRECTION_IN)2987 pTaskState->PDMScsiRequest.uDataDirection = PDMSCSIREQUESTTXDIR_FROM_DEVICE;2988 else if (pTaskState->CommandControlBlockGuest.c.uDataDirection == BUSLOGIC_CCB_DIRECTION_OUT)2989 pTaskState->PDMScsiRequest.uDataDirection = PDMSCSIREQUESTTXDIR_TO_DEVICE;2990 else if (pTaskState->CommandControlBlockGuest.c.uDataDirection == BUSLOGIC_CCB_DIRECTION_NO_DATA)2991 pTaskState->PDMScsiRequest.uDataDirection = PDMSCSIREQUESTTXDIR_NONE;2992 else2993 AssertMsgFailed(("Invalid data direction type %d\n", pTaskState->CommandControlBlockGuest.c.uDataDirection));2994 2995 pTaskState->PDMScsiRequest.cbCDB = pTaskState->CommandControlBlockGuest.c.cbCDB;2996 pTaskState->PDMScsiRequest.pbCDB = pTaskState->CommandControlBlockGuest.c.abCDB;2997 if (pTaskState->DataSeg.cbSeg)2998 {2999 pTaskState->PDMScsiRequest.cbScatterGather = (uint32_t)pTaskState->DataSeg.cbSeg;3000 pTaskState->PDMScsiRequest.cScatterGatherEntries = 1;3001 pTaskState->PDMScsiRequest.paScatterGatherHead = &pTaskState->DataSeg;3002 }3003 else3004 {3005 pTaskState->PDMScsiRequest.cbScatterGather = 0;3006 pTaskState->PDMScsiRequest.cScatterGatherEntries = 0;3007 pTaskState->PDMScsiRequest.paScatterGatherHead = NULL;3008 }3009 pTaskState->PDMScsiRequest.cbSenseBuffer = buslogicR3ConvertSenseBufferLength(pTaskState->CommandControlBlockGuest.c.cbSenseData);3010 pTaskState->PDMScsiRequest.pbSenseBuffer = pTaskState->pbSenseBuffer;3011 pTaskState->PDMScsiRequest.pvUser = pTaskState;3012 3013 ASMAtomicIncU32(&pTargetDevice->cOutstandingRequests);3014 rc = pTargetDevice->pDrvSCSIConnector->pfnSCSIRequestSend(pTargetDevice->pDrvSCSIConnector, &pTaskState->PDMScsiRequest);3015 AssertMsgRC(rc, ("Sending request to SCSI layer failed rc=%Rrc\n", rc));3016 }3017 3077 } 3018 3078 else 3019 { 3020 RTMemCacheFree(pBusLogic->hTaskCache, pTaskState); 3021 3022 buslogicR3SendIncomingMailbox(pBusLogic, pTaskState, 3079 buslogicR3SendIncomingMailbox(pBusLogic, GCPhysAddrCCB, &CCBGuest, 3023 3080 BUSLOGIC_MAILBOX_INCOMING_ADAPTER_STATUS_INVALID_COMMAND_PARAMETER, 3024 3081 BUSLOGIC_MAILBOX_INCOMING_DEVICE_STATUS_OPERATION_GOOD, 3025 3082 BUSLOGIC_MAILBOX_INCOMING_COMPLETION_WITH_ERROR); 3026 }3027 3083 3028 3084 return rc; 3029 3085 } 3030 3086 3031 static int buslogicR3DeviceSCSIRequestAbort(PBUSLOGIC pBusLogic, PBUSLOGICTASKSTATE pTaskState) 3032 { 3033 int rc = VINF_SUCCESS; 3034 uint8_t uTargetIdCCB; 3035 PBUSLOGICDEVICE pTargetDevice; 3036 RTGCPHYS GCPhysAddrCCB = (RTGCPHYS)pTaskState->MailboxGuest.u32PhysAddrCCB; 3087 static int buslogicR3DeviceSCSIRequestAbort(PBUSLOGIC pBusLogic, RTGCPHYS GCPhysAddrCCB) 3088 { 3089 int rc = VINF_SUCCESS; 3090 uint8_t uTargetIdCCB; 3091 CCBU CCBGuest; 3037 3092 3038 3093 PDMDevHlpPhysRead(pBusLogic->CTX_SUFF(pDevIns), GCPhysAddrCCB, 3039 & pTaskState->CommandControlBlockGuest, sizeof(CCB32));3040 3041 uTargetIdCCB = p TaskState->fIs24Bit ? pTaskState->CommandControlBlockGuest.o.uTargetId : pTaskState->CommandControlBlockGuest.n.uTargetId;3094 &CCBGuest, sizeof(CCB32)); 3095 3096 uTargetIdCCB = pBusLogic->fMbxIs24Bit ? CCBGuest.o.uTargetId : CCBGuest.n.uTargetId; 3042 3097 if (RT_LIKELY(uTargetIdCCB < RT_ELEMENTS(pBusLogic->aDeviceStates))) 3043 { 3044 pTargetDevice = &pBusLogic->aDeviceStates[uTargetIdCCB]; 3045 pTaskState->CTX_SUFF(pTargetDevice) = pTargetDevice; 3046 3047 buslogicR3SendIncomingMailbox(pBusLogic, pTaskState, 3098 buslogicR3SendIncomingMailbox(pBusLogic, GCPhysAddrCCB, &CCBGuest, 3048 3099 BUSLOGIC_MAILBOX_INCOMING_ADAPTER_STATUS_ABORT_QUEUE_GENERATED, 3049 3100 BUSLOGIC_MAILBOX_INCOMING_DEVICE_STATUS_OPERATION_GOOD, 3050 3101 BUSLOGIC_MAILBOX_INCOMING_COMPLETION_ABORTED_NOT_FOUND); 3051 3052 RTMemCacheFree(pBusLogic->hTaskCache, pTaskState);3053 }3054 3102 else 3055 { 3056 RTMemCacheFree(pBusLogic->hTaskCache, pTaskState); 3057 3058 buslogicR3SendIncomingMailbox(pBusLogic, pTaskState, 3103 buslogicR3SendIncomingMailbox(pBusLogic, GCPhysAddrCCB, &CCBGuest, 3059 3104 BUSLOGIC_MAILBOX_INCOMING_ADAPTER_STATUS_INVALID_COMMAND_PARAMETER, 3060 3105 BUSLOGIC_MAILBOX_INCOMING_DEVICE_STATUS_OPERATION_GOOD, 3061 3106 BUSLOGIC_MAILBOX_INCOMING_COMPLETION_WITH_ERROR); 3062 }3063 3107 3064 3108 return rc; … … 3071 3115 * @returns Mailbox guest physical address. 3072 3116 * @param pBusLogic Pointer to the BusLogic instance data. 3073 * @param p TaskStat Pointer to the task state being set up.3074 */ 3075 static RTGCPHYS buslogicR3ReadOutgoingMailbox(PBUSLOGIC pBusLogic, P BUSLOGICTASKSTATE pTaskState)3117 * @param pMbx Pointer to the mailbox to read into. 3118 */ 3119 static RTGCPHYS buslogicR3ReadOutgoingMailbox(PBUSLOGIC pBusLogic, PMailbox32 pMbx) 3076 3120 { 3077 3121 RTGCPHYS GCMailbox; … … 3083 3127 GCMailbox = pBusLogic->GCPhysAddrMailboxOutgoingBase + (pBusLogic->uMailboxOutgoingPositionCurrent * sizeof(Mailbox24)); 3084 3128 PDMDevHlpPhysRead(pBusLogic->CTX_SUFF(pDevIns), GCMailbox, &Mbx24, sizeof(Mailbox24)); 3085 p TaskState->MailboxGuest.u32PhysAddrCCB = ADDR_TO_U32(Mbx24.aPhysAddrCCB);3086 p TaskState->MailboxGuest.u.out.uActionCode = Mbx24.uCmdState;3129 pMbx->u32PhysAddrCCB = ADDR_TO_U32(Mbx24.aPhysAddrCCB); 3130 pMbx->u.out.uActionCode = Mbx24.uCmdState; 3087 3131 } 3088 3132 else 3089 3133 { 3090 3134 GCMailbox = pBusLogic->GCPhysAddrMailboxOutgoingBase + (pBusLogic->uMailboxOutgoingPositionCurrent * sizeof(Mailbox32)); 3091 PDMDevHlpPhysRead(pBusLogic->CTX_SUFF(pDevIns), GCMailbox, &pTaskState->MailboxGuest, sizeof(Mailbox32));3135 PDMDevHlpPhysRead(pBusLogic->CTX_SUFF(pDevIns), GCMailbox, pMbx, sizeof(Mailbox32)); 3092 3136 } 3093 3137 … … 3103 3147 static int buslogicR3ProcessMailboxNext(PBUSLOGIC pBusLogic) 3104 3148 { 3105 PBUSLOGICTASKSTATE pTaskState = NULL; 3106 RTGCPHYS GCPhysAddrMailboxCurrent; 3107 int rc; 3108 3109 rc = RTMemCacheAllocEx(pBusLogic->hTaskCache, (void **)&pTaskState); 3110 AssertMsgReturn(RT_SUCCESS(rc) && (pTaskState != NULL), ("Failed to get task state from cache\n"), rc); 3111 3112 pTaskState->fBIOS = false; 3113 pTaskState->fIs24Bit = pBusLogic->fMbxIs24Bit; 3114 pTaskState->cbSGEntry = pBusLogic->fMbxIs24Bit ? sizeof(SGE24) : sizeof(SGE32); 3149 RTGCPHYS GCPhysAddrMailboxCurrent; 3150 Mailbox32 MailboxGuest; 3151 int rc = VINF_SUCCESS; 3115 3152 3116 3153 if (!pBusLogic->fStrictRoundRobinMode) … … 3122 3159 { 3123 3160 /* Fetch mailbox from guest memory. */ 3124 GCPhysAddrMailboxCurrent = buslogicR3ReadOutgoingMailbox(pBusLogic, pTaskState);3161 GCPhysAddrMailboxCurrent = buslogicR3ReadOutgoingMailbox(pBusLogic, &MailboxGuest); 3125 3162 3126 3163 /* Check the next mailbox. */ 3127 3164 buslogicR3OutgoingMailboxAdvance(pBusLogic); 3128 } while ( pTaskState->MailboxGuest.u.out.uActionCode == BUSLOGIC_MAILBOX_OUTGOING_ACTION_FREE3165 } while ( MailboxGuest.u.out.uActionCode == BUSLOGIC_MAILBOX_OUTGOING_ACTION_FREE 3129 3166 && uMailboxPosCur != pBusLogic->uMailboxOutgoingPositionCurrent); 3130 3167 } … … 3132 3169 { 3133 3170 /* Fetch mailbox from guest memory. */ 3134 GCPhysAddrMailboxCurrent = buslogicR3ReadOutgoingMailbox(pBusLogic, pTaskState);3171 GCPhysAddrMailboxCurrent = buslogicR3ReadOutgoingMailbox(pBusLogic, &MailboxGuest); 3135 3172 } 3136 3173 … … 3141 3178 * log entry. 3142 3179 */ 3143 if ( pTaskState->MailboxGuest.u.out.uActionCode == BUSLOGIC_MAILBOX_OUTGOING_ACTION_FREE)3180 if (MailboxGuest.u.out.uActionCode == BUSLOGIC_MAILBOX_OUTGOING_ACTION_FREE) 3144 3181 { 3145 3182 Log(("No loaded mailbox left\n")); 3146 RTMemCacheFree(pBusLogic->hTaskCache, pTaskState);3147 3183 return VERR_NO_DATA; 3148 3184 } 3149 3185 3150 LogFlow(("Got loaded mailbox at slot %u, CCB phys %RGp\n", pBusLogic->uMailboxOutgoingPositionCurrent, (RTGCPHYS) pTaskState->MailboxGuest.u32PhysAddrCCB));3186 LogFlow(("Got loaded mailbox at slot %u, CCB phys %RGp\n", pBusLogic->uMailboxOutgoingPositionCurrent, (RTGCPHYS)MailboxGuest.u32PhysAddrCCB)); 3151 3187 #ifdef LOG_ENABLED 3152 buslogicR3DumpMailboxInfo(& pTaskState->MailboxGuest, true);3188 buslogicR3DumpMailboxInfo(&MailboxGuest, true); 3153 3189 #endif 3154 3190 3155 3191 /* We got the mailbox, mark it as free in the guest. */ 3156 3192 uint8_t uActionCode = BUSLOGIC_MAILBOX_OUTGOING_ACTION_FREE; 3157 unsigned uCodeOffs = p TaskState->fIs24Bit ? RT_OFFSETOF(Mailbox24, uCmdState) : RT_OFFSETOF(Mailbox32, u.out.uActionCode);3193 unsigned uCodeOffs = pBusLogic->fMbxIs24Bit ? RT_OFFSETOF(Mailbox24, uCmdState) : RT_OFFSETOF(Mailbox32, u.out.uActionCode); 3158 3194 PDMDevHlpPCIPhysWrite(pBusLogic->CTX_SUFF(pDevIns), GCPhysAddrMailboxCurrent + uCodeOffs, &uActionCode, sizeof(uActionCode)); 3159 3195 3160 if ( pTaskState->MailboxGuest.u.out.uActionCode == BUSLOGIC_MAILBOX_OUTGOING_ACTION_START_COMMAND)3161 rc = buslogicR3DeviceSCSIRequestSetup(pBusLogic, pTaskState);3162 else if ( pTaskState->MailboxGuest.u.out.uActionCode == BUSLOGIC_MAILBOX_OUTGOING_ACTION_ABORT_COMMAND)3196 if (MailboxGuest.u.out.uActionCode == BUSLOGIC_MAILBOX_OUTGOING_ACTION_START_COMMAND) 3197 rc = buslogicR3DeviceSCSIRequestSetup(pBusLogic, (RTGCPHYS)MailboxGuest.u32PhysAddrCCB); 3198 else if (MailboxGuest.u.out.uActionCode == BUSLOGIC_MAILBOX_OUTGOING_ACTION_ABORT_COMMAND) 3163 3199 { 3164 3200 LogFlow(("Aborting mailbox\n")); 3165 rc = buslogicR3DeviceSCSIRequestAbort(pBusLogic, pTaskState);3201 rc = buslogicR3DeviceSCSIRequestAbort(pBusLogic, (RTGCPHYS)MailboxGuest.u32PhysAddrCCB); 3166 3202 } 3167 3203 else 3168 AssertMsgFailed(("Invalid outgoing mailbox action code %u\n", pTaskState->MailboxGuest.u.out.uActionCode));3204 AssertMsgFailed(("Invalid outgoing mailbox action code %u\n", MailboxGuest.u.out.uActionCode)); 3169 3205 3170 3206 AssertRC(rc); … … 3197 3233 } 3198 3234 3199 /**3200 * Kicks the controller to process pending tasks after the VM was resumed3201 * or loaded from a saved state.3202 *3203 * @returns nothing.3204 * @param pThis The BusLogic device instance.3205 */3206 static void buslogicR3Kick(PBUSLOGIC pThis)3207 {3208 if (pThis->fRedo)3209 {3210 pThis->fRedo = false;3211 if (pThis->VBoxSCSI.fBusy)3212 {3213 3214 /* The BIOS had a request active when we got suspended. Resume it. */3215 int rc = buslogicR3PrepareBIOSSCSIRequest(pThis);3216 AssertRC(rc);3217 }3218 else3219 {3220 /* Queue all pending tasks again. */3221 PBUSLOGICTASKSTATE pTaskState = pThis->pTasksRedoHead;3222 3223 pThis->pTasksRedoHead = NULL;3224 3225 while (pTaskState)3226 {3227 PBUSLOGICTASKSTATE pCur = pTaskState;3228 3229 int rc = buslogicR3DeviceSCSIRequestSetup(pThis, pCur);3230 AssertRC(rc);3231 3232 pTaskState = pTaskState->pRedoNext;3233 }3234 }3235 }3236 }3237 3238 3235 /** @callback_method_impl{FNSSMDEVLIVEEXEC} */ 3239 3236 static DECLCALLBACK(int) buslogicR3LiveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uPass) … … 3253 3250 { 3254 3251 PBUSLOGIC pBusLogic = PDMINS_2_DATA(pDevIns, PBUSLOGIC); 3252 uint32_t cReqsSuspended = 0; 3255 3253 3256 3254 /* Every device first. */ … … 3263 3261 SSMR3PutBool(pSSM, pDevice->fPresent); 3264 3262 SSMR3PutU32(pSSM, pDevice->cOutstandingRequests); 3263 3264 if (pDevice->fPresent) 3265 cReqsSuspended += pDevice->pDrvMediaEx->pfnIoReqGetSuspendedCount(pDevice->pDrvMediaEx); 3265 3266 } 3266 3267 /* Now the main device state. */ … … 3292 3293 vboxscsiR3SaveExec(&pBusLogic->VBoxSCSI, pSSM); 3293 3294 3294 /* 3295 * Save the physical addresses of the command control blocks of still pending tasks. 3296 * They are processed again on resume. 3297 * 3298 * The number of pending tasks needs to be determined first. 3299 */ 3300 uint32_t cTasks = 0; 3301 3302 PBUSLOGICTASKSTATE pTaskState = pBusLogic->pTasksRedoHead; 3303 if (pBusLogic->fRedo) 3304 { 3305 while (pTaskState) 3306 { 3307 cTasks++; 3308 pTaskState = pTaskState->pRedoNext; 3309 } 3310 } 3311 SSMR3PutU32(pSSM, cTasks); 3312 3313 /* Write the address of every task now. */ 3314 pTaskState = pBusLogic->pTasksRedoHead; 3315 while (pTaskState) 3316 { 3317 SSMR3PutU32(pSSM, pTaskState->MailboxGuest.u32PhysAddrCCB); 3318 pTaskState = pTaskState->pRedoNext; 3295 SSMR3PutU32(pSSM, cReqsSuspended); 3296 3297 /* Save the physical CCB address of all suspended requests. */ 3298 for (unsigned i = 0; i < RT_ELEMENTS(pBusLogic->aDeviceStates) && cReqsSuspended; i++) 3299 { 3300 PBUSLOGICDEVICE pDevice = &pBusLogic->aDeviceStates[i]; 3301 if (pDevice->fPresent) 3302 { 3303 uint32_t cThisReqsSuspended = pDevice->pDrvMediaEx->pfnIoReqGetSuspendedCount(pDevice->pDrvMediaEx); 3304 3305 cReqsSuspended -= cThisReqsSuspended; 3306 if (cThisReqsSuspended) 3307 { 3308 PDMMEDIAEXIOREQ hIoReq; 3309 PBUSLOGICREQ pReq; 3310 int rc = pDevice->pDrvMediaEx->pfnIoReqQuerySuspendedStart(pDevice->pDrvMediaEx, &hIoReq, 3311 (void **)&pReq); 3312 AssertRCBreak(rc); 3313 3314 for (;;) 3315 { 3316 SSMR3PutU32(pSSM, (uint32_t)pReq->GCPhysAddrCCB); 3317 3318 cThisReqsSuspended--; 3319 if (!cThisReqsSuspended) 3320 break; 3321 3322 rc = pDevice->pDrvMediaEx->pfnIoReqQuerySuspendedNext(pDevice->pDrvMediaEx, hIoReq, 3323 &hIoReq, (void **)&pReq); 3324 AssertRCBreak(rc); 3325 } 3326 } 3327 } 3319 3328 } 3320 3329 … … 3329 3338 3330 3339 buslogicR3RegisterISARange(pThis, pThis->uISABaseCode); 3331 buslogicR3Kick(pThis); 3340 3341 /* Kick of any requests we might need to redo. */ 3342 if (pThis->VBoxSCSI.fBusy) 3343 { 3344 3345 /* The BIOS had a request active when we got suspended. Resume it. */ 3346 int rc = buslogicR3PrepareBIOSSCSIRequest(pThis); 3347 AssertRC(rc); 3348 } 3349 else if (pThis->cReqsRedo) 3350 { 3351 for (unsigned i = 0; i < pThis->cReqsRedo; i++) 3352 { 3353 int rc = buslogicR3DeviceSCSIRequestSetup(pThis, pThis->paGCPhysAddrCCBRedo[i]); 3354 AssertRC(rc); 3355 } 3356 3357 RTMemFree(pThis->paGCPhysAddrCCBRedo); 3358 pThis->paGCPhysAddrCCBRedo = NULL; 3359 pThis->cReqsRedo = 0; 3360 } 3361 3332 3362 return VINF_SUCCESS; 3333 3363 } … … 3401 3431 } 3402 3432 3403 if (pBusLogic->VBoxSCSI.fBusy)3404 pBusLogic->fRedo = true;3405 3406 3433 if (uVersion > BUSLOGIC_SAVED_STATE_MINOR_PRE_ERROR_HANDLING) 3407 3434 { … … 3412 3439 3413 3440 if (cTasks) 3414 pBusLogic->fRedo = true; 3415 3416 for (uint32_t i = 0; i < cTasks; i++) 3417 { 3418 PBUSLOGICTASKSTATE pTaskState = (PBUSLOGICTASKSTATE)RTMemCacheAlloc(pBusLogic->hTaskCache); 3419 if (!pTaskState) 3441 { 3442 pBusLogic->paGCPhysAddrCCBRedo = (PRTGCPHYS)RTMemAllocZ(cTasks * sizeof(RTGCPHYS)); 3443 if (RT_LIKELY(pBusLogic->paGCPhysAddrCCBRedo)) 3420 3444 { 3445 pBusLogic->cReqsRedo = cTasks; 3446 3447 for (uint32_t i = 0; i < cTasks; i++) 3448 { 3449 uint32_t u32PhysAddrCCB; 3450 3451 rc = SSMR3GetU32(pSSM, &u32PhysAddrCCB); 3452 if (RT_FAILURE(rc)) 3453 break; 3454 3455 pBusLogic->paGCPhysAddrCCBRedo[i] = u32PhysAddrCCB; 3456 } 3457 } 3458 else 3421 3459 rc = VERR_NO_MEMORY; 3422 break;3423 }3424 3425 rc = SSMR3GetU32(pSSM, &pTaskState->MailboxGuest.u32PhysAddrCCB);3426 if (RT_FAILURE(rc))3427 {3428 RTMemCacheFree(pBusLogic->hTaskCache, pTaskState);3429 break;3430 }3431 3432 /* Link into the list. */3433 pTaskState->pRedoNext = pBusLogic->pTasksRedoHead;3434 pBusLogic->pTasksRedoHead = pTaskState;3435 3460 } 3436 3461 } … … 3458 3483 static DECLCALLBACK(int) buslogicR3DeviceQueryStatusLed(PPDMILEDPORTS pInterface, unsigned iLUN, PPDMLED *ppLed) 3459 3484 { 3460 PBUSLOGICDEVICE pDevice = PDMILEDPORTS_2_PBUSLOGICDEVICE(pInterface);3485 PBUSLOGICDEVICE pDevice = RT_FROM_MEMBER(pInterface, BUSLOGICDEVICE, ILed); 3461 3486 if (iLUN == 0) 3462 3487 { … … 3473 3498 static DECLCALLBACK(void *) buslogicR3DeviceQueryInterface(PPDMIBASE pInterface, const char *pszIID) 3474 3499 { 3475 PBUSLOGICDEVICE pDevice = PDMIBASE_2_PBUSLOGICDEVICE(pInterface);3500 PBUSLOGICDEVICE pDevice = RT_FROM_MEMBER(pInterface, BUSLOGICDEVICE, IBase); 3476 3501 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDevice->IBase); 3477 PDMIBASE_RETURN_INTERFACE(pszIID, PDMISCSIPORT, &pDevice->ISCSIPort); 3502 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAPORT, &pDevice->IMediaPort); 3503 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAEXPORT, &pDevice->IMediaExPort); 3478 3504 PDMIBASE_RETURN_INTERFACE(pszIID, PDMILEDPORTS, &pDevice->ILed); 3479 3505 return NULL; … … 3490 3516 static DECLCALLBACK(int) buslogicR3StatusQueryStatusLed(PPDMILEDPORTS pInterface, unsigned iLUN, PPDMLED *ppLed) 3491 3517 { 3492 PBUSLOGIC pBusLogic = PDMILEDPORTS_2_PBUSLOGIC(pInterface);3518 PBUSLOGIC pBusLogic = RT_FROM_MEMBER(pInterface, BUSLOGIC, ILeds); 3493 3519 if (iLUN < BUSLOGIC_MAX_DEVICES) 3494 3520 { … … 3505 3531 static DECLCALLBACK(void *) buslogicR3StatusQueryInterface(PPDMIBASE pInterface, const char *pszIID) 3506 3532 { 3507 PBUSLOGIC pThis = PDMIBASE_2_PBUSLOGIC(pInterface);3533 PBUSLOGIC pThis = RT_FROM_MEMBER(pInterface, BUSLOGIC, IBase); 3508 3534 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pThis->IBase); 3509 3535 PDMIBASE_RETURN_INTERFACE(pszIID, PDMILEDPORTS, &pThis->ILeds); … … 3736 3762 3737 3763 /** 3738 * Common worker for ahciR3Suspend and ahciR3PowerOff.3739 */ 3740 static void buslogicR3SuspendOrPowerOff(PPDMDEVINS pDevIns , bool fPowerOff)3764 * Common worker for buslogicR3Suspend and buslogicR3PowerOff. 3765 */ 3766 static void buslogicR3SuspendOrPowerOff(PPDMDEVINS pDevIns) 3741 3767 { 3742 3768 PBUSLOGIC pThis = PDMINS_2_DATA(pDevIns, PBUSLOGIC); … … 3748 3774 { 3749 3775 ASMAtomicWriteBool(&pThis->fSignalIdle, false); 3750 3751 3776 AssertMsg(!pThis->fNotificationSent, ("The PDM Queue should be empty at this point\n")); 3752 3753 if (pThis->fRedo)3754 {3755 if (fPowerOff)3756 {3757 /* Free tasks which would have been queued again on resume. */3758 PBUSLOGICTASKSTATE pTaskState = pThis->pTasksRedoHead;3759 3760 pThis->pTasksRedoHead = NULL;3761 3762 while (pTaskState)3763 {3764 PBUSLOGICTASKSTATE pFree;3765 3766 pFree = pTaskState;3767 pTaskState = pTaskState->pRedoNext;3768 3769 RTMemCacheFree(pThis->hTaskCache, pFree);3770 }3771 pThis->fRedo = false;3772 }3773 else if (pThis->VBoxSCSI.fBusy)3774 {3775 /* Destroy the task because the BIOS interface has all necessary information. */3776 Assert(pThis->pTasksRedoHead->fBIOS);3777 Assert(!pThis->pTasksRedoHead->pRedoNext);3778 3779 RTMemCacheFree(pThis->hTaskCache, pThis->pTasksRedoHead);3780 pThis->pTasksRedoHead = NULL;3781 }3782 }3783 3777 } 3784 3778 } … … 3792 3786 { 3793 3787 Log(("buslogicR3Suspend\n")); 3794 buslogicR3SuspendOrPowerOff(pDevIns, false /* fPoweroff */); 3795 } 3796 3797 /** 3798 * Resume notification. 3799 * 3800 * @param pDevIns The device instance data. 3801 */ 3802 static DECLCALLBACK(void) buslogicR3Resume(PPDMDEVINS pDevIns) 3803 { 3804 Log(("buslogicR3Resume\n")); 3805 PBUSLOGIC pThis = PDMINS_2_DATA(pDevIns, PBUSLOGIC); 3806 buslogicR3Kick(pThis); 3807 } 3808 3788 buslogicR3SuspendOrPowerOff(pDevIns); 3789 } 3809 3790 3810 3791 /** … … 3832 3813 * Zero some important members. 3833 3814 */ 3834 pDevice->pDrvBase = NULL; 3835 pDevice->fPresent = false; 3836 pDevice->pDrvSCSIConnector = NULL; 3815 pDevice->fPresent = false; 3816 pDevice->pDrvBase = NULL; 3817 pDevice->pDrvMedia = NULL; 3818 pDevice->pDrvMediaEx = NULL; 3837 3819 } 3838 3820 … … 3859 3841 /* the usual paranoia */ 3860 3842 AssertRelease(!pDevice->pDrvBase); 3861 AssertRelease(!pDevice->pDrvSCSIConnector); 3843 AssertRelease(!pDevice->pDrvMedia); 3844 AssertRelease(!pDevice->pDrvMediaEx); 3862 3845 Assert(pDevice->iLUN == iLUN); 3863 3846 3864 3847 /* 3865 * Try attach the block deviceand get the interfaces,3848 * Try attach the SCSI driver and get the interfaces, 3866 3849 * required as well as optional. 3867 3850 */ … … 3869 3852 if (RT_SUCCESS(rc)) 3870 3853 { 3871 /* Get SCSI connector interface. */ 3872 pDevice->pDrvSCSIConnector = PDMIBASE_QUERY_INTERFACE(pDevice->pDrvBase, PDMISCSICONNECTOR); 3873 AssertMsgReturn(pDevice->pDrvSCSIConnector, ("Missing SCSI interface below\n"), VERR_PDM_MISSING_INTERFACE); 3854 /* Query the media interface. */ 3855 pDevice->pDrvMedia = PDMIBASE_QUERY_INTERFACE(pDevice->pDrvBase, PDMIMEDIA); 3856 AssertMsgReturn(VALID_PTR(pDevice->pDrvMedia), 3857 ("BusLogic configuration error: LUN#%d misses the basic media interface!\n", pDevice->iLUN), 3858 VERR_PDM_MISSING_INTERFACE); 3859 3860 /* Get the extended media interface. */ 3861 pDevice->pDrvMediaEx = PDMIBASE_QUERY_INTERFACE(pDevice->pDrvBase, PDMIMEDIAEX); 3862 AssertMsgReturn(VALID_PTR(pDevice->pDrvMediaEx), 3863 ("BusLogic configuration error: LUN#%d misses the extended media interface!\n", pDevice->iLUN), 3864 VERR_PDM_MISSING_INTERFACE); 3865 3866 rc = pDevice->pDrvMediaEx->pfnIoReqAllocSizeSet(pDevice->pDrvMediaEx, sizeof(BUSLOGICREQ)); 3867 AssertMsgRCReturn(rc, ("BusLogic configuration error: LUN#%u: Failed to set I/O request size!"), 3868 pDevice->iLUN); 3869 3874 3870 pDevice->fPresent = true; 3875 3871 } … … 3879 3875 if (RT_FAILURE(rc)) 3880 3876 { 3881 pDevice->pDrvBase = NULL; 3882 pDevice->pDrvSCSIConnector = NULL; 3877 pDevice->fPresent = false; 3878 pDevice->pDrvBase = NULL; 3879 pDevice->pDrvMedia = NULL; 3880 pDevice->pDrvMediaEx = NULL; 3883 3881 } 3884 3882 return rc; … … 3945 3943 { 3946 3944 Log(("buslogicR3PowerOff\n")); 3947 buslogicR3SuspendOrPowerOff(pDevIns , true /* fPoweroff */);3945 buslogicR3SuspendOrPowerOff(pDevIns); 3948 3946 } 3949 3947 … … 3963 3961 PDMR3CritSectDelete(&pThis->CritSectIntr); 3964 3962 3965 /*3966 * Free all tasks which are still hanging around3967 * (Power off after the VM was suspended).3968 */3969 if (pThis->fRedo)3970 {3971 /* Free tasks which would have been queued again on resume. */3972 PBUSLOGICTASKSTATE pTaskState = pThis->pTasksRedoHead;3973 3974 pThis->pTasksRedoHead = NULL;3975 3976 while (pTaskState)3977 {3978 PBUSLOGICTASKSTATE pFree;3979 3980 pFree = pTaskState;3981 pTaskState = pTaskState->pRedoNext;3982 3983 RTMemCacheFree(pThis->hTaskCache, pFree);3984 }3985 pThis->fRedo = false;3986 }3987 3988 3963 if (pThis->hEvtProcess != NIL_SUPSEMEVENT) 3989 3964 { … … 3992 3967 } 3993 3968 3994 int rc = RTMemCacheDestroy(pThis->hTaskCache); 3995 AssertMsgRC(rc, ("Destroying task cache failed rc=%Rrc\n", rc)); 3996 3997 return rc; 3969 return VINF_SUCCESS; 3998 3970 } 3999 3971 … … 4012 3984 * Init instance data (do early because of constructor). 4013 3985 */ 4014 pThis->hTaskCache = NIL_RTMEMCACHE;4015 3986 pThis->pDevInsR3 = pDevIns; 4016 3987 pThis->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns); … … 4113 4084 return PDMDEV_SET_ERROR(pDevIns, rc, N_("BusLogic cannot register ISA I/O handlers")); 4114 4085 4115 /* Initialize task cache. */4116 rc = RTMemCacheCreate(&pThis->hTaskCache, sizeof(BUSLOGICTASKSTATE), 0, UINT32_MAX,4117 NULL, NULL, NULL, 0);4118 if (RT_FAILURE(rc))4119 return PDMDEV_SET_ERROR(pDevIns, rc,4120 N_("BusLogic: Failed to initialize task cache\n"));4121 4122 4086 /* Initialize task queue. */ 4123 4087 rc = PDMDevHlpQueueCreate(pDevIns, sizeof(PDMQUEUEITEMCORE), 5, 0, … … 4163 4127 pDevice->pBusLogicRC = PDMINS_2_DATA_RCPTR(pDevIns); 4164 4128 pDevice->Led.u32Magic = PDMLED_MAGIC; 4165 pDevice->IBase.pfnQueryInterface = buslogicR3DeviceQueryInterface; 4166 pDevice->ISCSIPort.pfnSCSIRequestCompleted = buslogicR3DeviceSCSIRequestCompleted; 4167 pDevice->ISCSIPort.pfnQueryDeviceLocation = buslogicR3QueryDeviceLocation; 4168 pDevice->ILed.pfnQueryStatusLed = buslogicR3DeviceQueryStatusLed; 4129 pDevice->IBase.pfnQueryInterface = buslogicR3DeviceQueryInterface; 4130 pDevice->IMediaPort.pfnQueryDeviceLocation = buslogicR3QueryDeviceLocation; 4131 pDevice->IMediaExPort.pfnIoReqCompleteNotify = buslogicR3IoReqCompleteNotify; 4132 pDevice->IMediaExPort.pfnIoReqCopyFromBuf = buslogicR3IoReqCopyFromBuf; 4133 pDevice->IMediaExPort.pfnIoReqCopyToBuf = buslogicR3IoReqCopyToBuf; 4134 pDevice->IMediaExPort.pfnIoReqQueryDiscardRanges = NULL; 4135 pDevice->IMediaExPort.pfnIoReqStateChanged = buslogicR3IoReqStateChanged; 4136 pDevice->IMediaExPort.pfnMediumEjected = buslogicR3MediumEjected; 4137 pDevice->ILed.pfnQueryStatusLed = buslogicR3DeviceQueryStatusLed; 4169 4138 4170 4139 /* Attach SCSI driver. */ … … 4172 4141 if (RT_SUCCESS(rc)) 4173 4142 { 4174 /* Get SCSI connector interface. */ 4175 pDevice->pDrvSCSIConnector = PDMIBASE_QUERY_INTERFACE(pDevice->pDrvBase, PDMISCSICONNECTOR); 4176 AssertMsgReturn(pDevice->pDrvSCSIConnector, ("Missing SCSI interface below\n"), VERR_PDM_MISSING_INTERFACE); 4143 /* Query the media interface. */ 4144 pDevice->pDrvMedia = PDMIBASE_QUERY_INTERFACE(pDevice->pDrvBase, PDMIMEDIA); 4145 AssertMsgReturn(VALID_PTR(pDevice->pDrvMedia), 4146 ("Buslogic configuration error: LUN#%d misses the basic media interface!\n", pDevice->iLUN), 4147 VERR_PDM_MISSING_INTERFACE); 4148 4149 /* Get the extended media interface. */ 4150 pDevice->pDrvMediaEx = PDMIBASE_QUERY_INTERFACE(pDevice->pDrvBase, PDMIMEDIAEX); 4151 AssertMsgReturn(VALID_PTR(pDevice->pDrvMediaEx), 4152 ("Buslogic configuration error: LUN#%d misses the extended media interface!\n", pDevice->iLUN), 4153 VERR_PDM_MISSING_INTERFACE); 4154 4155 rc = pDevice->pDrvMediaEx->pfnIoReqAllocSizeSet(pDevice->pDrvMediaEx, sizeof(BUSLOGICREQ)); 4156 if (RT_FAILURE(rc)) 4157 return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS, 4158 N_("Buslogic configuration error: LUN#%u: Failed to set I/O request size!"), 4159 pDevice->iLUN); 4177 4160 4178 4161 pDevice->fPresent = true; … … 4180 4163 else if (rc == VERR_PDM_NO_ATTACHED_DRIVER) 4181 4164 { 4182 pDevice->pDrvBase = NULL; 4183 pDevice->fPresent = false; 4165 pDevice->fPresent = false; 4166 pDevice->pDrvBase = NULL; 4167 pDevice->pDrvMedia = NULL; 4168 pDevice->pDrvMediaEx = NULL; 4184 4169 rc = VINF_SUCCESS; 4185 4170 Log(("BusLogic: no driver attached to device %s\n", szName)); … … 4265 4250 buslogicR3Suspend, 4266 4251 /* pfnResume */ 4267 buslogicR3Resume,4252 NULL, 4268 4253 /* pfnAttach */ 4269 4254 buslogicR3Attach, -
trunk/src/VBox/Devices/Storage/DevLsiLogicSCSI.cpp
r63690 r64224 80 80 *********************************************************************************************************************************/ 81 81 82 /** 83 * I/O buffer copy worker. 82 /** Pointer to the device instance data of the LsiLogic emulation. */ 83 typedef struct LSILOGICSCSI *PLSILOGICSCSI; 84 85 #ifdef IN_RING3 86 /** 87 * Memory buffer callback. 84 88 * 85 89 * @returns nothing. 86 * @param pDevIns Device instance data. 87 * @param GCPhysIoBuf Guest physical address of the I/O buffer. 88 * @param pvBuf R3 buffer pointer. 89 * @param cbCopy How much to copy. 90 */ 91 typedef DECLCALLBACK(void) FNLSILOGICIOBUFCOPY(PPDMDEVINS pDevIns, RTGCPHYS GCPhysIoBuf, 92 void *pvBuf, size_t cbCopy); 93 /** Pointer to a I/O buffer copy worker. */ 94 typedef FNLSILOGICIOBUFCOPY *PFNLSILOGICIOBUFCOPY; 90 * @param pThis The LsiLogic controller instance. 91 * @param GCPhys The guest physical address of the memory buffer. 92 * @param pSgBuf The pointer to the host R3 S/G buffer. 93 * @param cbCopy How many bytes to copy between the two buffers. 94 * @param pcbSkip Initially contains the amount of bytes to skip 95 * starting from the guest physical address before 96 * accessing the S/G buffer and start copying data. 97 * On return this contains the remaining amount if 98 * cbCopy < *pcbSkip or 0 otherwise. 99 */ 100 typedef DECLCALLBACK(void) LSILOGICR3MEMCOPYCALLBACK(PLSILOGICSCSI pThis, RTGCPHYS GCPhys, PRTSGBUF pSgBuf, size_t cbCopy, 101 size_t *pcbSkip); 102 /** Pointer to a memory copy buffer callback. */ 103 typedef LSILOGICR3MEMCOPYCALLBACK *PLSILOGICR3MEMCOPYCALLBACK; 104 #endif 95 105 96 106 /** … … 138 148 { 139 149 /** Pointer to the owning lsilogic device instance. - R3 pointer */ 140 R3PTRTYPE( struct LSILOGICSCSI *)pLsiLogicR3;150 R3PTRTYPE(PLSILOGICSCSI) pLsiLogicR3; 141 151 142 152 /** LUN of the device. */ … … 151 161 /** Our base interface. */ 152 162 PDMIBASE IBase; 153 /** SCSI port interface. */ 154 PDMISCSIPORT ISCSIPort; 163 /** Media port interface. */ 164 PDMIMEDIAPORT IMediaPort; 165 /** Extended media port interface. */ 166 PDMIMEDIAEXPORT IMediaExPort; 155 167 /** Led interface. */ 156 168 PDMILEDPORTS ILed; 157 169 /** Pointer to the attached driver's base interface. */ 158 170 R3PTRTYPE(PPDMIBASE) pDrvBase; 159 /** Pointer to the underlying SCSI connector interface. */ 160 R3PTRTYPE(PPDMISCSICONNECTOR) pDrvSCSIConnector; 171 /** Pointer to the attached driver's media interface. */ 172 R3PTRTYPE(PPDMIMEDIA) pDrvMedia; 173 /** Pointer to the attached driver's extended media interface. */ 174 R3PTRTYPE(PPDMIMEDIAEX) pDrvMediaEx; 161 175 /** The status LED state for this device. */ 162 176 PDMLED Led; … … 323 337 VBOXSCSI VBoxSCSI; 324 338 325 /** Cache for allocated tasks. */326 R3PTRTYPE(RTMEMCACHE) hTaskCache;327 339 /** Status LUN: The base interface. */ 328 340 PDMIBASE IBase; … … 375 387 376 388 } LSILOGISCSI; 377 /** Pointer to the device instance data of the LsiLogic emulation. */378 typedef LSILOGICSCSI *PLSILOGICSCSI;379 389 380 390 /** … … 384 394 typedef struct LSILOGICREQ 385 395 { 396 /** I/O request handle. */ 397 PDMMEDIAEXIOREQ hIoReq; 386 398 /** Next in the redo list. */ 387 399 PLSILOGICREQ pRedoNext; … … 390 402 /** The message request from the guest. */ 391 403 MptRequestUnion GuestRequest; 392 /** Reply message if the request produces one. */393 MptReplyUnion IOCReply;394 /** SCSI request structure for the SCSI driver. */395 PDMSCSIREQUEST PDMScsiRequest;396 404 /** Address of the message request frame in guests memory. 397 405 * Used to read the S/G entries in the second step. */ … … 401 409 /** Chain offset */ 402 410 uint32_t cChainOffset; 403 /** Segment describing the I/O buffer. */404 RTSGSEG SegIoBuf;405 /** Additional memory allocation for this task. */406 void *pvAlloc;407 /** Siize of the allocation. */408 size_t cbAlloc;409 /** Number of times we had too much memory allocated for the request. */410 unsigned cAllocTooMuch;411 411 /** Pointer to the sense buffer. */ 412 412 uint8_t abSenseBuffer[18]; 413 413 /** Flag whether the request was issued from the BIOS. */ 414 414 bool fBIOS; 415 /** SCSI status code. */ 416 uint8_t u8ScsiSts; 415 417 } LSILOGICREQ; 416 418 … … 1857 1859 1858 1860 /** 1861 * Copy from guest to host memory worker. 1862 * 1863 * @copydoc{LSILOGICR3MEMCOPYCALLBACK} 1864 */ 1865 static DECLCALLBACK(void) lsilogicR3CopyBufferFromGuestWorker(PLSILOGICSCSI pThis, RTGCPHYS GCPhys, PRTSGBUF pSgBuf, 1866 size_t cbCopy, size_t *pcbSkip) 1867 { 1868 size_t cbSkipped = RT_MIN(cbCopy, *pcbSkip); 1869 cbCopy -= cbSkipped; 1870 GCPhys += cbSkipped; 1871 *pcbSkip -= cbSkipped; 1872 1873 while (cbCopy) 1874 { 1875 size_t cbSeg = cbCopy; 1876 void *pvSeg = RTSgBufGetNextSegment(pSgBuf, &cbSeg); 1877 1878 AssertPtr(pvSeg); 1879 PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), GCPhys, pvSeg, cbSeg); 1880 GCPhys += cbSeg; 1881 cbCopy -= cbSeg; 1882 } 1883 } 1884 1885 /** 1886 * Copy from host to guest memory worker. 1887 * 1888 * @copydoc{LSILOGICR3MEMCOPYCALLBACK} 1889 */ 1890 static DECLCALLBACK(void) lsilogicR3CopyBufferToGuestWorker(PLSILOGICSCSI pThis, RTGCPHYS GCPhys, PRTSGBUF pSgBuf, 1891 size_t cbCopy, size_t *pcbSkip) 1892 { 1893 size_t cbSkipped = RT_MIN(cbCopy, *pcbSkip); 1894 cbCopy -= cbSkipped; 1895 GCPhys += cbSkipped; 1896 *pcbSkip -= cbSkipped; 1897 1898 while (cbCopy) 1899 { 1900 size_t cbSeg = cbCopy; 1901 void *pvSeg = RTSgBufGetNextSegment(pSgBuf, &cbSeg); 1902 1903 AssertPtr(pvSeg); 1904 PDMDevHlpPCIPhysWrite(pThis->CTX_SUFF(pDevIns), GCPhys, pvSeg, cbSeg); 1905 GCPhys += cbSeg; 1906 cbCopy -= cbSeg; 1907 } 1908 } 1909 1910 /** 1859 1911 * Walks the guest S/G buffer calling the given copy worker for every buffer. 1860 1912 * 1861 * @returns nothing. 1862 * @param pDevIns Device instance data. 1863 * @param pLsiReq LSI request state. 1864 * @param cbCopy How much bytes to copy. 1865 * @param pfnIoBufCopy Copy worker to call. 1866 */ 1867 static void lsilogicSgBufWalker(PPDMDEVINS pDevIns, PLSILOGICREQ pLsiReq, size_t cbCopy, 1868 PFNLSILOGICIOBUFCOPY pfnIoBufCopy) 1913 * @returns The amout of bytes actually copied. 1914 * @param pThis Pointer to the LsiLogic device state. 1915 * @param pLsiReq LSI request state. 1916 * @param pfnCopyWorker The copy method to apply for each guest buffer. 1917 * @param pSgBuf The host S/G buffer. 1918 * @param cbSkip How many bytes to skip in advance before starting to copy. 1919 * @param cbCopy How many bytes to copy. 1920 */ 1921 static size_t lsilogicSgBufWalker(PLSILOGICSCSI pThis, PLSILOGICREQ pLsiReq, 1922 PLSILOGICR3MEMCOPYCALLBACK pfnCopyWorker, 1923 PRTSGBUF pSgBuf, size_t cbSkip, size_t cbCopy) 1869 1924 { 1870 1925 bool fEndOfList = false; … … 1872 1927 RTGCPHYS GCPhysSegmentStart = pLsiReq->GCPhysSgStart; 1873 1928 uint32_t cChainOffsetNext = pLsiReq->cChainOffset; 1874 uint8_t *pbBuf = (uint8_t *)pLsiReq->SegIoBuf.pvSeg; 1929 PPDMDEVINS pDevIns = pThis->CTX_SUFF(pDevIns); 1930 size_t cbCopied = 0; 1931 1932 /* 1933 * Add the amount to skip to the host buffer size to avoid a 1934 * few conditionals later on. 1935 */ 1936 cbCopy += cbSkip; 1875 1937 1876 1938 /* Go through the list until we reach the end. */ … … 1900 1962 && SGEntry.Simple32.fEndOfList 1901 1963 && SGEntry.Simple32.fEndOfBuffer) 1902 return ;1964 return cbCopied - RT_MIN(cbSkip, cbCopied); 1903 1965 1904 1966 uint32_t cbCopyThis = SGEntry.Simple32.u24Length; … … 1913 1975 GCPhysSgEntryNext += sizeof(MptSGEntrySimple32); 1914 1976 1915 1916 pfnIoBufCopy(pDevIns, GCPhysAddrDataBuffer, pbBuf, cbCopyThis); 1917 pbBuf += cbCopyThis; 1977 pfnCopyWorker(pThis, GCPhysAddrDataBuffer, pSgBuf, cbCopyThis, &cbSkip); 1918 1978 cbCopy -= cbCopyThis; 1979 cbCopied += cbCopyThis; 1919 1980 1920 1981 /* Check if we reached the end of the list. */ … … 1947 2008 } 1948 2009 } /* while (!fEndOfList) */ 1949 } 1950 1951 static DECLCALLBACK(void) lsilogicCopyFromGuest(PPDMDEVINS pDevIns, RTGCPHYS GCPhysIoBuf, 1952 void *pvBuf, size_t cbCopy) 1953 { 1954 PDMDevHlpPhysRead(pDevIns, GCPhysIoBuf, pvBuf, cbCopy); 1955 } 1956 1957 static DECLCALLBACK(void) lsilogicCopyToGuest(PPDMDEVINS pDevIns, RTGCPHYS GCPhysIoBuf, 1958 void *pvBuf, size_t cbCopy) 1959 { 1960 PDMDevHlpPCIPhysWrite(pDevIns, GCPhysIoBuf, pvBuf, cbCopy); 1961 } 1962 1963 /** 1964 * Copy from a guest S/G buffer to the I/O buffer. 1965 * 1966 * @returns nothing. 1967 * @param pDevIns Device instance data. 1968 * @param pLsiReq Request data. 1969 * @param cbCopy How much to copy over. 1970 */ 1971 DECLINLINE(void) lsilogicCopyFromSgBuf(PPDMDEVINS pDevIns, PLSILOGICREQ pLsiReq, size_t cbCopy) 1972 { 1973 lsilogicSgBufWalker(pDevIns, pLsiReq, cbCopy, lsilogicCopyFromGuest); 1974 } 1975 1976 /** 1977 * Copy from an I/O buffer to the guest S/G buffer. 1978 * 1979 * @returns nothing. 1980 * @param pDevIns Device instance data. 1981 * @param pLsiReq Request data. 1982 * @param cbCopy How much to copy over. 1983 */ 1984 DECLINLINE(void) lsilogicCopyToSgBuf(PPDMDEVINS pDevIns, PLSILOGICREQ pLsiReq, size_t cbCopy) 1985 { 1986 lsilogicSgBufWalker(pDevIns, pLsiReq, cbCopy, lsilogicCopyToGuest); 1987 } 1988 1989 /** 1990 * Allocates memory for the given request using already allocated memory if possible. 1991 * 1992 * @returns Pointer to the memory or NULL on failure 1993 * @param pLsiReq The request to allocate memory for. 1994 * @param cb The amount of memory to allocate. 1995 */ 1996 static void *lsilogicReqMemAlloc(PLSILOGICREQ pLsiReq, size_t cb) 1997 { 1998 if (pLsiReq->cbAlloc > cb) 1999 pLsiReq->cAllocTooMuch++; 2000 else if (pLsiReq->cbAlloc < cb) 2001 { 2002 if (pLsiReq->cbAlloc) 2003 RTMemPageFree(pLsiReq->pvAlloc, pLsiReq->cbAlloc); 2004 2005 pLsiReq->cbAlloc = RT_ALIGN_Z(cb, _4K); 2006 pLsiReq->pvAlloc = RTMemPageAlloc(pLsiReq->cbAlloc); 2007 pLsiReq->cAllocTooMuch = 0; 2008 if (RT_UNLIKELY(!pLsiReq->pvAlloc)) 2009 pLsiReq->cbAlloc = 0; 2010 } 2011 2012 return pLsiReq->pvAlloc; 2013 } 2014 2015 /** 2016 * Frees memory allocated for the given request. 2017 * 2018 * @returns nothing. 2019 * @param pLsiReq The request. 2020 */ 2021 static void lsilogicReqMemFree(PLSILOGICREQ pLsiReq) 2022 { 2023 if (pLsiReq->cAllocTooMuch >= LSILOGIC_MAX_ALLOC_TOO_MUCH) 2024 { 2025 RTMemPageFree(pLsiReq->pvAlloc, pLsiReq->cbAlloc); 2026 pLsiReq->cbAlloc = 0; 2027 pLsiReq->cAllocTooMuch = 0; 2028 } 2029 } 2030 2031 /** 2032 * Allocate I/O memory and copies the guest buffer for writes. 2033 * 2034 * @returns VBox status code. 2035 * @param pDevIns The device instance. 2036 * @param pLsiReq The request state. 2037 * @param cbTransfer Amount of bytes to allocate. 2038 */ 2039 static int lsilogicIoBufAllocate(PPDMDEVINS pDevIns, PLSILOGICREQ pLsiReq, 2040 size_t cbTransfer) 2041 { 2042 uint8_t uTxDir = MPT_SCSIIO_REQUEST_CONTROL_TXDIR_GET(pLsiReq->GuestRequest.SCSIIO.u32Control); 2043 2044 AssertMsg( uTxDir == MPT_SCSIIO_REQUEST_CONTROL_TXDIR_WRITE 2045 || uTxDir == MPT_SCSIIO_REQUEST_CONTROL_TXDIR_READ 2046 || uTxDir == MPT_SCSIIO_REQUEST_CONTROL_TXDIR_NONE, 2047 ("Allocating I/O memory for a non I/O request is not allowed\n")); 2048 2049 pLsiReq->SegIoBuf.pvSeg = lsilogicReqMemAlloc(pLsiReq, cbTransfer); 2050 if (!pLsiReq->SegIoBuf.pvSeg) 2051 return VERR_NO_MEMORY; 2052 2053 pLsiReq->SegIoBuf.cbSeg = cbTransfer; 2054 if ( uTxDir == MPT_SCSIIO_REQUEST_CONTROL_TXDIR_WRITE 2055 || uTxDir == MPT_SCSIIO_REQUEST_CONTROL_TXDIR_NONE) 2056 lsilogicCopyFromSgBuf(pDevIns, pLsiReq, cbTransfer); 2057 2058 return VINF_SUCCESS; 2059 } 2060 2061 /** 2062 * Frees the I/O memory of the given request and updates the guest buffer if necessary. 2063 * 2064 * @returns nothing. 2065 * @param pDevIns The device instance. 2066 * @param pLsiReq The request state. 2067 * @param fCopyToGuest Flag whether to update the guest buffer if necessary. 2068 * Nothing is copied if false even if the request was a read. 2069 */ 2070 static void lsilogicIoBufFree(PPDMDEVINS pDevIns, PLSILOGICREQ pLsiReq, 2071 bool fCopyToGuest) 2072 { 2073 uint8_t uTxDir = MPT_SCSIIO_REQUEST_CONTROL_TXDIR_GET(pLsiReq->GuestRequest.SCSIIO.u32Control); 2074 2075 AssertMsg( uTxDir == MPT_SCSIIO_REQUEST_CONTROL_TXDIR_WRITE 2076 || uTxDir == MPT_SCSIIO_REQUEST_CONTROL_TXDIR_READ 2077 || uTxDir == MPT_SCSIIO_REQUEST_CONTROL_TXDIR_NONE, 2078 ("Allocating I/O memory for a non I/O request is not allowed\n")); 2079 2080 if ( ( uTxDir == MPT_SCSIIO_REQUEST_CONTROL_TXDIR_READ 2081 || uTxDir == MPT_SCSIIO_REQUEST_CONTROL_TXDIR_NONE) 2082 && fCopyToGuest) 2083 lsilogicCopyToSgBuf(pDevIns, pLsiReq, pLsiReq->SegIoBuf.cbSeg); 2084 2085 lsilogicReqMemFree(pLsiReq); 2086 pLsiReq->SegIoBuf.pvSeg = NULL; 2087 pLsiReq->SegIoBuf.cbSeg = 0; 2088 } 2010 2011 return cbCopied - RT_MIN(cbSkip, cbCopied); 2012 } 2013 2014 /** 2015 * Copies a data buffer into the S/G buffer set up by the guest. 2016 * 2017 * @returns Amount of bytes copied to the guest. 2018 * @param pThis The LsiLogic controller device instance. 2019 * @param pReq Request structure. 2020 * @param pSgBuf The S/G buffer to copy from. 2021 * @param cbSkip How many bytes to skip in advance before starting to copy. 2022 * @param cbCopy How many bytes to copy. 2023 */ 2024 static size_t lsilogicR3CopySgBufToGuest(PLSILOGICSCSI pThis, PLSILOGICREQ pReq, PRTSGBUF pSgBuf, 2025 size_t cbSkip, size_t cbCopy) 2026 { 2027 return lsilogicSgBufWalker(pThis, pReq, lsilogicR3CopyBufferToGuestWorker, 2028 pSgBuf, cbSkip, cbCopy); 2029 } 2030 2031 /** 2032 * Copies the guest S/G buffer into a host data buffer. 2033 * 2034 * @returns Amount of bytes copied from the guest. 2035 * @param pThis The LsiLogic controller device instance. 2036 * @param pReq Request structure. 2037 * @param pSgBuf The S/G buffer to copy into. 2038 * @param cbSkip How many bytes to skip in advance before starting to copy. 2039 * @param cbCopy How many bytes to copy. 2040 */ 2041 static size_t lsilogicR3CopySgBufFromGuest(PLSILOGICSCSI pThis, PLSILOGICREQ pReq, PRTSGBUF pSgBuf, 2042 size_t cbSkip, size_t cbCopy) 2043 { 2044 return lsilogicSgBufWalker(pThis, pReq, lsilogicR3CopyBufferFromGuestWorker, 2045 pSgBuf, cbSkip, cbCopy); 2046 } 2047 2048 #if 0 /* unused */ 2049 /** 2050 * Copy a simple memory buffer to the guest memory buffer. 2051 * 2052 * @returns Amount of bytes copied to the guest. 2053 * @param pThis The LsiLogic controller device instance. 2054 * @param pReq Request structure. 2055 * @param pvSrc The buffer to copy from. 2056 * @param cbSrc How many bytes to copy. 2057 * @param cbSkip How many bytes to skip initially. 2058 */ 2059 static size_t lsilogicR3CopyBufferToGuest(PLSILOGICSCSI pThis, PLSILOGICREQ pReq, const void *pvSrc, 2060 size_t cbSrc, size_t cbSkip) 2061 { 2062 RTSGSEG Seg; 2063 RTSGBUF SgBuf; 2064 Seg.pvSeg = (void *)pvSrc; 2065 Seg.cbSeg = cbSrc; 2066 RTSgBufInit(&SgBuf, &Seg, 1); 2067 return lsilogicR3CopySgBufToGuest(pThis, pReq, &SgBuf, cbSkip, cbSrc); 2068 } 2069 2070 /** 2071 * Copy a guest memry buffe into simple host memory buffer. 2072 * 2073 * @returns Amount of bytes copied to the guest. 2074 * @param pThis The LsiLogic controller device instance. 2075 * @param pReq Request structure. 2076 * @param pvSrc The buffer to copy from. 2077 * @param cbSrc How many bytes to copy. 2078 * @param cbSkip How many bytes to skip initially. 2079 */ 2080 static size_t lsilogicR3CopyBufferFromGuest(PLSILOGICSCSI pThis, PLSILOGICREQ pReq, void *pvDst, 2081 size_t cbDst, size_t cbSkip) 2082 { 2083 RTSGSEG Seg; 2084 RTSGBUF SgBuf; 2085 Seg.pvSeg = (void *)pvDst; 2086 Seg.cbSeg = cbDst; 2087 RTSgBufInit(&SgBuf, &Seg, 1); 2088 return lsilogicR3CopySgBufFromGuest(pThis, pReq, &SgBuf, cbSkip, cbDst); 2089 } 2090 #endif 2089 2091 2090 2092 # ifdef LOG_ENABLED … … 2112 2114 # endif 2113 2115 2114 static void lsilogicR3WarningDiskFull(PPDMDEVINS pDevIns) 2115 { 2116 int rc; 2117 LogRel(("LsiLogic#%d: Host disk full\n", pDevIns->iInstance)); 2118 rc = PDMDevHlpVMSetRuntimeError(pDevIns, VMSETRTERR_FLAGS_SUSPEND | VMSETRTERR_FLAGS_NO_WAIT, "DevLsiLogic_DISKFULL", 2119 N_("Host system reported disk full. VM execution is suspended. You can resume after freeing some space")); 2120 AssertRC(rc); 2121 } 2122 2123 static void lsilogicR3WarningFileTooBig(PPDMDEVINS pDevIns) 2124 { 2125 int rc; 2126 LogRel(("LsiLogic#%d: File too big\n", pDevIns->iInstance)); 2127 rc = PDMDevHlpVMSetRuntimeError(pDevIns, VMSETRTERR_FLAGS_SUSPEND | VMSETRTERR_FLAGS_NO_WAIT, "DevLsiLogic_FILETOOBIG", 2128 N_("Host system reported that the file size limit of the host file system has been exceeded. VM execution is suspended. You need to move your virtual hard disk to a filesystem which allows bigger files")); 2129 AssertRC(rc); 2130 } 2131 2132 static void lsilogicR3WarningISCSI(PPDMDEVINS pDevIns) 2133 { 2134 int rc; 2135 LogRel(("LsiLogic#%d: iSCSI target unavailable\n", pDevIns->iInstance)); 2136 rc = PDMDevHlpVMSetRuntimeError(pDevIns, VMSETRTERR_FLAGS_SUSPEND | VMSETRTERR_FLAGS_NO_WAIT, "DevLsiLogic_ISCSIDOWN", 2137 N_("The iSCSI target has stopped responding. VM execution is suspended. You can resume when it is available again")); 2138 AssertRC(rc); 2139 } 2140 2141 static void lsilogicR3WarningUnknown(PPDMDEVINS pDevIns, int rc) 2142 { 2143 int rc2; 2144 LogRel(("LsiLogic#%d: Unknown but recoverable error has occurred (rc=%Rrc)\n", pDevIns->iInstance, rc)); 2145 rc2 = PDMDevHlpVMSetRuntimeError(pDevIns, VMSETRTERR_FLAGS_SUSPEND | VMSETRTERR_FLAGS_NO_WAIT, "DevLsiLogic_UNKNOWN", 2146 N_("An unknown but recoverable I/O error has occurred (rc=%Rrc). VM execution is suspended. You can resume when the error is fixed"), rc); 2147 AssertRC(rc2); 2148 } 2149 2150 static void lsilogicR3RedoSetWarning(PLSILOGICSCSI pThis, int rc) 2151 { 2152 if (rc == VERR_DISK_FULL) 2153 lsilogicR3WarningDiskFull(pThis->CTX_SUFF(pDevIns)); 2154 else if (rc == VERR_FILE_TOO_BIG) 2155 lsilogicR3WarningFileTooBig(pThis->CTX_SUFF(pDevIns)); 2156 else if (rc == VERR_BROKEN_PIPE || rc == VERR_NET_CONNECTION_REFUSED) 2157 { 2158 /* iSCSI connection abort (first error) or failure to reestablish 2159 * connection (second error). Pause VM. On resume we'll retry. */ 2160 lsilogicR3WarningISCSI(pThis->CTX_SUFF(pDevIns)); 2161 } 2162 else if (rc != VERR_VD_DEK_MISSING) 2163 lsilogicR3WarningUnknown(pThis->CTX_SUFF(pDevIns), rc); 2116 /** 2117 * Handles the completion of th given request. 2118 * 2119 * @returns nothing. 2120 * @param pThis Pointer to the LsiLogic device state. 2121 * @param pReq The request to complete. 2122 * @param rcReq Status code of the request. 2123 */ 2124 static void lsilogicR3ReqComplete(PLSILOGICSCSI pThis, PLSILOGICREQ pReq, int rcReq) 2125 { 2126 PLSILOGICDEVICE pTgtDev = pReq->pTargetDevice; 2127 2128 if (RT_UNLIKELY(pReq->fBIOS)) 2129 { 2130 pTgtDev->pDrvMediaEx->pfnIoReqFree(pTgtDev->pDrvMediaEx, pReq->hIoReq); 2131 int rc = vboxscsiRequestFinished(&pThis->VBoxSCSI, rcReq); 2132 AssertMsgRC(rc, ("Finishing BIOS SCSI request failed rc=%Rrc\n", rc)); 2133 } 2134 else 2135 { 2136 RTGCPHYS GCPhysAddrSenseBuffer; 2137 2138 GCPhysAddrSenseBuffer = pReq->GuestRequest.SCSIIO.u32SenseBufferLowAddress; 2139 GCPhysAddrSenseBuffer |= ((uint64_t)pThis->u32SenseBufferHighAddr << 32); 2140 2141 /* Copy the sense buffer over. */ 2142 PDMDevHlpPCIPhysWrite(pThis->CTX_SUFF(pDevIns), GCPhysAddrSenseBuffer, pReq->abSenseBuffer, 2143 RT_UNLIKELY( pReq->GuestRequest.SCSIIO.u8SenseBufferLength 2144 < sizeof(pReq->abSenseBuffer)) 2145 ? pReq->GuestRequest.SCSIIO.u8SenseBufferLength 2146 : sizeof(pReq->abSenseBuffer)); 2147 2148 if (RT_SUCCESS(rcReq) && RT_LIKELY(pReq->u8ScsiSts == SCSI_STATUS_OK)) 2149 { 2150 uint32_t u32MsgCtx = pReq->GuestRequest.SCSIIO.u32MessageContext; 2151 2152 /* Free the request before posting completion. */ 2153 pTgtDev->pDrvMediaEx->pfnIoReqFree(pTgtDev->pDrvMediaEx, pReq->hIoReq); 2154 lsilogicR3FinishContextReply(pThis, u32MsgCtx); 2155 } 2156 else 2157 { 2158 MptReplyUnion IOCReply; 2159 RT_ZERO(IOCReply); 2160 2161 /* The SCSI target encountered an error during processing post a reply. */ 2162 IOCReply.SCSIIOError.u8TargetID = pReq->GuestRequest.SCSIIO.u8TargetID; 2163 IOCReply.SCSIIOError.u8Bus = pReq->GuestRequest.SCSIIO.u8Bus; 2164 IOCReply.SCSIIOError.u8MessageLength = 8; 2165 IOCReply.SCSIIOError.u8Function = pReq->GuestRequest.SCSIIO.u8Function; 2166 IOCReply.SCSIIOError.u8CDBLength = pReq->GuestRequest.SCSIIO.u8CDBLength; 2167 IOCReply.SCSIIOError.u8SenseBufferLength = pReq->GuestRequest.SCSIIO.u8SenseBufferLength; 2168 IOCReply.SCSIIOError.u8MessageFlags = pReq->GuestRequest.SCSIIO.u8MessageFlags; 2169 IOCReply.SCSIIOError.u32MessageContext = pReq->GuestRequest.SCSIIO.u32MessageContext; 2170 IOCReply.SCSIIOError.u8SCSIStatus = pReq->u8ScsiSts; 2171 IOCReply.SCSIIOError.u8SCSIState = MPT_SCSI_IO_ERROR_SCSI_STATE_AUTOSENSE_VALID; 2172 IOCReply.SCSIIOError.u16IOCStatus = 0; 2173 IOCReply.SCSIIOError.u32IOCLogInfo = 0; 2174 IOCReply.SCSIIOError.u32TransferCount = 0; 2175 IOCReply.SCSIIOError.u32SenseCount = sizeof(pReq->abSenseBuffer); 2176 IOCReply.SCSIIOError.u32ResponseInfo = 0; 2177 2178 /* Free the request before posting completion. */ 2179 pTgtDev->pDrvMediaEx->pfnIoReqFree(pTgtDev->pDrvMediaEx, pReq->hIoReq); 2180 lsilogicFinishAddressReply(pThis, &IOCReply, false); 2181 } 2182 } 2183 2184 ASMAtomicDecU32(&pTgtDev->cOutstandingRequests); 2185 2186 if (pTgtDev->cOutstandingRequests == 0 && pThis->fSignalIdle) 2187 PDMDevHlpAsyncNotificationCompleted(pThis->pDevInsR3); 2164 2188 } 2165 2189 … … 2172 2196 * 2173 2197 * @returns VBox status code. 2174 * @param pThis Pointer to the LsiLogic device state. 2175 * @param pLsiReq Pointer to the task state data. 2176 */ 2177 static int lsilogicR3ProcessSCSIIORequest(PLSILOGICSCSI pThis, PLSILOGICREQ pLsiReq) 2178 { 2198 * @param pThis Pointer to the LsiLogic device state. 2199 * @param GCPhysMessageFrameAddr Guest physical address where the request is located. 2200 * @param pGuestReq The request read fro th guest memory. 2201 */ 2202 static int lsilogicR3ProcessSCSIIORequest(PLSILOGICSCSI pThis, RTGCPHYS GCPhysMessageFrameAddr, 2203 PMptRequestUnion pGuestReq) 2204 { 2205 MptReplyUnion IOCReply; 2179 2206 int rc = VINF_SUCCESS; 2180 2207 2181 2208 # ifdef LOG_ENABLED 2182 lsilogicR3DumpSCSIIORequest(&p LsiReq->GuestRequest.SCSIIO);2209 lsilogicR3DumpSCSIIORequest(&pGuestReq->SCSIIO); 2183 2210 # endif 2184 2211 2185 pLsiReq->fBIOS = false; 2186 pLsiReq->GCPhysSgStart = pLsiReq->GCPhysMessageFrameAddr + sizeof(MptSCSIIORequest); 2187 pLsiReq->cChainOffset = pLsiReq->GuestRequest.SCSIIO.u8ChainOffset; 2188 if (pLsiReq->cChainOffset) 2189 pLsiReq->cChainOffset = pLsiReq->cChainOffset * sizeof(uint32_t) - sizeof(MptSCSIIORequest); 2190 2191 if (RT_LIKELY( (pLsiReq->GuestRequest.SCSIIO.u8TargetID < pThis->cDeviceStates) 2192 && (pLsiReq->GuestRequest.SCSIIO.u8Bus == 0))) 2193 { 2194 PLSILOGICDEVICE pTargetDevice; 2195 pTargetDevice = &pThis->paDeviceStates[pLsiReq->GuestRequest.SCSIIO.u8TargetID]; 2196 2197 if (pTargetDevice->pDrvBase) 2198 { 2199 2200 if (pLsiReq->GuestRequest.SCSIIO.u32DataLength) 2212 if (RT_LIKELY( (pGuestReq->SCSIIO.u8TargetID < pThis->cDeviceStates) 2213 && (pGuestReq->SCSIIO.u8Bus == 0))) 2214 { 2215 PLSILOGICDEVICE pTgtDev = &pThis->paDeviceStates[pGuestReq->SCSIIO.u8TargetID]; 2216 2217 if (pTgtDev->pDrvBase) 2218 { 2219 /* Allocate and prepare a new request. */ 2220 PDMMEDIAEXIOREQ hIoReq; 2221 PLSILOGICREQ pLsiReq = NULL; 2222 rc = pTgtDev->pDrvMediaEx->pfnIoReqAlloc(pTgtDev->pDrvMediaEx, &hIoReq, (void **)&pLsiReq, 2223 pGuestReq->SCSIIO.u32MessageContext, 2224 PDMIMEDIAEX_F_SUSPEND_ON_RECOVERABLE_ERR); 2225 if (RT_SUCCESS(rc)) 2201 2226 { 2202 2203 rc = lsilogicIoBufAllocate(pThis->CTX_SUFF(pDevIns), pLsiReq, 2204 pLsiReq->GuestRequest.SCSIIO.u32DataLength); 2205 AssertRC(rc); /** @todo Insufficient resources error. */ 2206 } 2207 2208 /* Setup the SCSI request. */ 2209 pLsiReq->pTargetDevice = pTargetDevice; 2210 pLsiReq->PDMScsiRequest.uLogicalUnit = pLsiReq->GuestRequest.SCSIIO.au8LUN[1]; 2211 2212 uint8_t uDataDirection = MPT_SCSIIO_REQUEST_CONTROL_TXDIR_GET(pLsiReq->GuestRequest.SCSIIO.u32Control); 2213 2214 if (uDataDirection == MPT_SCSIIO_REQUEST_CONTROL_TXDIR_NONE) 2215 pLsiReq->PDMScsiRequest.uDataDirection = PDMSCSIREQUESTTXDIR_NONE; 2216 else if (uDataDirection == MPT_SCSIIO_REQUEST_CONTROL_TXDIR_WRITE) 2217 pLsiReq->PDMScsiRequest.uDataDirection = PDMSCSIREQUESTTXDIR_TO_DEVICE; 2218 else if (uDataDirection == MPT_SCSIIO_REQUEST_CONTROL_TXDIR_READ) 2219 pLsiReq->PDMScsiRequest.uDataDirection = PDMSCSIREQUESTTXDIR_FROM_DEVICE; 2220 2221 pLsiReq->PDMScsiRequest.cbCDB = pLsiReq->GuestRequest.SCSIIO.u8CDBLength; 2222 pLsiReq->PDMScsiRequest.pbCDB = pLsiReq->GuestRequest.SCSIIO.au8CDB; 2223 pLsiReq->PDMScsiRequest.cbScatterGather = pLsiReq->GuestRequest.SCSIIO.u32DataLength; 2224 if (pLsiReq->PDMScsiRequest.cbScatterGather) 2225 { 2226 pLsiReq->PDMScsiRequest.cScatterGatherEntries = 1; 2227 pLsiReq->PDMScsiRequest.paScatterGatherHead = &pLsiReq->SegIoBuf; 2227 pLsiReq->hIoReq = hIoReq; 2228 pLsiReq->pTargetDevice = pTgtDev; 2229 pLsiReq->GCPhysMessageFrameAddr = GCPhysMessageFrameAddr; 2230 pLsiReq->fBIOS = false; 2231 pLsiReq->GCPhysSgStart = GCPhysMessageFrameAddr + sizeof(MptSCSIIORequest); 2232 pLsiReq->cChainOffset = pGuestReq->SCSIIO.u8ChainOffset; 2233 if (pLsiReq->cChainOffset) 2234 pLsiReq->cChainOffset = pLsiReq->cChainOffset * sizeof(uint32_t) - sizeof(MptSCSIIORequest); 2235 memcpy(&pLsiReq->GuestRequest, pGuestReq, sizeof(MptRequestUnion)); 2236 RT_BZERO(&pLsiReq->abSenseBuffer[0], sizeof(pLsiReq->abSenseBuffer)); 2237 2238 PDMMEDIAEXIOREQSCSITXDIR enmXferDir = PDMMEDIAEXIOREQSCSITXDIR_UNKNOWN; 2239 uint8_t uDataDirection = MPT_SCSIIO_REQUEST_CONTROL_TXDIR_GET(pLsiReq->GuestRequest.SCSIIO.u32Control); 2240 2241 if (uDataDirection == MPT_SCSIIO_REQUEST_CONTROL_TXDIR_NONE) 2242 enmXferDir = PDMMEDIAEXIOREQSCSITXDIR_NONE; 2243 else if (uDataDirection == MPT_SCSIIO_REQUEST_CONTROL_TXDIR_WRITE) 2244 enmXferDir = PDMMEDIAEXIOREQSCSITXDIR_TO_DEVICE; 2245 else if (uDataDirection == MPT_SCSIIO_REQUEST_CONTROL_TXDIR_READ) 2246 enmXferDir = PDMMEDIAEXIOREQSCSITXDIR_FROM_DEVICE; 2247 2248 ASMAtomicIncU32(&pTgtDev->cOutstandingRequests); 2249 rc = pTgtDev->pDrvMediaEx->pfnIoReqSendScsiCmd(pTgtDev->pDrvMediaEx, pLsiReq->hIoReq, pLsiReq->GuestRequest.SCSIIO.au8LUN[1], 2250 &pLsiReq->GuestRequest.SCSIIO.au8CDB[0], pLsiReq->GuestRequest.SCSIIO.u8CDBLength, 2251 enmXferDir, pLsiReq->GuestRequest.SCSIIO.u32DataLength, 2252 &pLsiReq->abSenseBuffer[0], sizeof(pLsiReq->abSenseBuffer), &pLsiReq->u8ScsiSts, 2253 30 * RT_MS_1SEC); 2254 if (rc != VINF_PDM_MEDIAEX_IOREQ_IN_PROGRESS) 2255 lsilogicR3ReqComplete(pThis, pLsiReq, rc); 2256 2257 return VINF_SUCCESS; 2228 2258 } 2229 2259 else 2230 { 2231 pLsiReq->PDMScsiRequest.cScatterGatherEntries = 0; 2232 pLsiReq->PDMScsiRequest.paScatterGatherHead = NULL; 2233 } 2234 pLsiReq->PDMScsiRequest.cbSenseBuffer = sizeof(pLsiReq->abSenseBuffer); 2235 memset(pLsiReq->abSenseBuffer, 0, pLsiReq->PDMScsiRequest.cbSenseBuffer); 2236 pLsiReq->PDMScsiRequest.pbSenseBuffer = pLsiReq->abSenseBuffer; 2237 pLsiReq->PDMScsiRequest.pvUser = pLsiReq; 2238 2239 ASMAtomicIncU32(&pTargetDevice->cOutstandingRequests); 2240 rc = pTargetDevice->pDrvSCSIConnector->pfnSCSIRequestSend(pTargetDevice->pDrvSCSIConnector, &pLsiReq->PDMScsiRequest); 2241 AssertMsgRC(rc, ("Sending request to SCSI layer failed rc=%Rrc\n", rc)); 2242 return VINF_SUCCESS; 2260 IOCReply.SCSIIOError.u16IOCStatus = MPT_SCSI_IO_ERROR_IOCSTATUS_DEVICE_NOT_THERE; 2243 2261 } 2244 2262 else 2245 2263 { 2246 2264 /* Device is not present report SCSI selection timeout. */ 2247 pLsiReq->IOCReply.SCSIIOError.u16IOCStatus = MPT_SCSI_IO_ERROR_IOCSTATUS_DEVICE_NOT_THERE;2265 IOCReply.SCSIIOError.u16IOCStatus = MPT_SCSI_IO_ERROR_IOCSTATUS_DEVICE_NOT_THERE; 2248 2266 } 2249 2267 } … … 2251 2269 { 2252 2270 /* Report out of bounds target ID or bus. */ 2253 if (p LsiReq->GuestRequest.SCSIIO.u8Bus != 0)2254 pLsiReq->IOCReply.SCSIIOError.u16IOCStatus = MPT_SCSI_IO_ERROR_IOCSTATUS_INVALID_BUS;2271 if (pGuestReq->SCSIIO.u8Bus != 0) 2272 IOCReply.SCSIIOError.u16IOCStatus = MPT_SCSI_IO_ERROR_IOCSTATUS_INVALID_BUS; 2255 2273 else 2256 pLsiReq->IOCReply.SCSIIOError.u16IOCStatus = MPT_SCSI_IO_ERROR_IOCSTATUS_INVALID_TARGETID;2274 IOCReply.SCSIIOError.u16IOCStatus = MPT_SCSI_IO_ERROR_IOCSTATUS_INVALID_TARGETID; 2257 2275 } 2258 2276 … … 2262 2280 { 2263 2281 LogRel(("LsiLogic#%d: %d/%d (Bus/Target) doesn't exist\n", pThis->CTX_SUFF(pDevIns)->iInstance, 2264 p LsiReq->GuestRequest.SCSIIO.u8TargetID, pLsiReq->GuestRequest.SCSIIO.u8Bus));2282 pGuestReq->SCSIIO.u8TargetID, pGuestReq->SCSIIO.u8Bus)); 2265 2283 /* Log the CDB too */ 2266 2284 LogRel(("LsiLogic#%d: Guest issued CDB {%#x", 2267 pThis->CTX_SUFF(pDevIns)->iInstance, p LsiReq->GuestRequest.SCSIIO.au8CDB[0]));2268 for (unsigned i = 1; i < p LsiReq->GuestRequest.SCSIIO.u8CDBLength; i++)2269 LogRel((", %#x", p LsiReq->GuestRequest.SCSIIO.au8CDB[i]));2285 pThis->CTX_SUFF(pDevIns)->iInstance, pGuestReq->SCSIIO.au8CDB[0])); 2286 for (unsigned i = 1; i < pGuestReq->SCSIIO.u8CDBLength; i++) 2287 LogRel((", %#x", pGuestReq->SCSIIO.au8CDB[i])); 2270 2288 LogRel(("}\n")); 2271 2289 } 2272 2290 2273 2291 /* The rest is equal to both errors. */ 2274 pLsiReq->IOCReply.SCSIIOError.u8TargetID = pLsiReq->GuestRequest.SCSIIO.u8TargetID; 2275 pLsiReq->IOCReply.SCSIIOError.u8Bus = pLsiReq->GuestRequest.SCSIIO.u8Bus; 2276 pLsiReq->IOCReply.SCSIIOError.u8MessageLength = sizeof(MptSCSIIOErrorReply) / 4; 2277 pLsiReq->IOCReply.SCSIIOError.u8Function = pLsiReq->GuestRequest.SCSIIO.u8Function; 2278 pLsiReq->IOCReply.SCSIIOError.u8CDBLength = pLsiReq->GuestRequest.SCSIIO.u8CDBLength; 2279 pLsiReq->IOCReply.SCSIIOError.u8SenseBufferLength = pLsiReq->GuestRequest.SCSIIO.u8SenseBufferLength; 2280 pLsiReq->IOCReply.SCSIIOError.u32MessageContext = pLsiReq->GuestRequest.SCSIIO.u32MessageContext; 2281 pLsiReq->IOCReply.SCSIIOError.u8SCSIStatus = SCSI_STATUS_OK; 2282 pLsiReq->IOCReply.SCSIIOError.u8SCSIState = MPT_SCSI_IO_ERROR_SCSI_STATE_TERMINATED; 2283 pLsiReq->IOCReply.SCSIIOError.u32IOCLogInfo = 0; 2284 pLsiReq->IOCReply.SCSIIOError.u32TransferCount = 0; 2285 pLsiReq->IOCReply.SCSIIOError.u32SenseCount = 0; 2286 pLsiReq->IOCReply.SCSIIOError.u32ResponseInfo = 0; 2287 2288 lsilogicFinishAddressReply(pThis, &pLsiReq->IOCReply, false); 2289 RTMemCacheFree(pThis->hTaskCache, pLsiReq); 2292 IOCReply.SCSIIOError.u8TargetID = pGuestReq->SCSIIO.u8TargetID; 2293 IOCReply.SCSIIOError.u8Bus = pGuestReq->SCSIIO.u8Bus; 2294 IOCReply.SCSIIOError.u8MessageLength = sizeof(MptSCSIIOErrorReply) / 4; 2295 IOCReply.SCSIIOError.u8Function = pGuestReq->SCSIIO.u8Function; 2296 IOCReply.SCSIIOError.u8CDBLength = pGuestReq->SCSIIO.u8CDBLength; 2297 IOCReply.SCSIIOError.u8SenseBufferLength = pGuestReq->SCSIIO.u8SenseBufferLength; 2298 IOCReply.SCSIIOError.u32MessageContext = pGuestReq->SCSIIO.u32MessageContext; 2299 IOCReply.SCSIIOError.u8SCSIStatus = SCSI_STATUS_OK; 2300 IOCReply.SCSIIOError.u8SCSIState = MPT_SCSI_IO_ERROR_SCSI_STATE_TERMINATED; 2301 IOCReply.SCSIIOError.u32IOCLogInfo = 0; 2302 IOCReply.SCSIIOError.u32TransferCount = 0; 2303 IOCReply.SCSIIOError.u32SenseCount = 0; 2304 IOCReply.SCSIIOError.u32ResponseInfo = 0; 2305 2306 lsilogicFinishAddressReply(pThis, &IOCReply, false); 2290 2307 2291 2308 return rc; … … 2294 2311 2295 2312 /** 2296 * @interface_method_impl{PDMISCSIPORT,pfnSCSIRequestCompleted} 2297 */ 2298 static DECLCALLBACK(int) lsilogicR3DeviceSCSIRequestCompleted(PPDMISCSIPORT pInterface, PPDMSCSIREQUEST pSCSIRequest, 2299 int rcCompletion, bool fRedo, int rcReq) 2300 { 2301 RT_NOREF(pInterface); 2302 PLSILOGICREQ pLsiReq = (PLSILOGICREQ)pSCSIRequest->pvUser; 2303 PLSILOGICDEVICE pLsiLogicDevice = pLsiReq->pTargetDevice; 2304 PLSILOGICSCSI pThis = pLsiLogicDevice->CTX_SUFF(pLsiLogic); 2305 2306 /* If the task failed but it is possible to redo it again after a suspend 2307 * add it to the list. */ 2308 if (fRedo) 2309 { 2310 if (!pLsiReq->fBIOS && pLsiReq->PDMScsiRequest.cbScatterGather) 2311 lsilogicIoBufFree(pThis->CTX_SUFF(pDevIns), pLsiReq, false /* fCopyToGuest */); 2312 2313 /* Add to the list. */ 2314 do 2315 { 2316 pLsiReq->pRedoNext = ASMAtomicReadPtrT(&pThis->pTasksRedoHead, PLSILOGICREQ); 2317 } while (!ASMAtomicCmpXchgPtr(&pThis->pTasksRedoHead, pLsiReq, pLsiReq->pRedoNext)); 2318 2319 /* Suspend the VM if not done already. */ 2320 if (!ASMAtomicXchgBool(&pThis->fRedo, true)) 2321 lsilogicR3RedoSetWarning(pThis, rcReq); 2322 } 2323 else 2324 { 2325 if (RT_UNLIKELY(pLsiReq->fBIOS)) 2326 { 2327 int rc = vboxscsiRequestFinished(&pThis->VBoxSCSI, pSCSIRequest, rcCompletion); 2328 AssertMsgRC(rc, ("Finishing BIOS SCSI request failed rc=%Rrc\n", rc)); 2329 } 2330 else 2331 { 2332 RTGCPHYS GCPhysAddrSenseBuffer; 2333 2334 GCPhysAddrSenseBuffer = pLsiReq->GuestRequest.SCSIIO.u32SenseBufferLowAddress; 2335 GCPhysAddrSenseBuffer |= ((uint64_t)pThis->u32SenseBufferHighAddr << 32); 2336 2337 /* Copy the sense buffer over. */ 2338 PDMDevHlpPCIPhysWrite(pThis->CTX_SUFF(pDevIns), GCPhysAddrSenseBuffer, pLsiReq->abSenseBuffer, 2339 RT_UNLIKELY( pLsiReq->GuestRequest.SCSIIO.u8SenseBufferLength 2340 < pLsiReq->PDMScsiRequest.cbSenseBuffer) 2341 ? pLsiReq->GuestRequest.SCSIIO.u8SenseBufferLength 2342 : pLsiReq->PDMScsiRequest.cbSenseBuffer); 2343 2344 if (pLsiReq->PDMScsiRequest.cbScatterGather) 2345 lsilogicIoBufFree(pThis->CTX_SUFF(pDevIns), pLsiReq, true /* fCopyToGuest */); 2346 2347 2348 if (RT_LIKELY(rcCompletion == SCSI_STATUS_OK)) 2349 lsilogicR3FinishContextReply(pThis, pLsiReq->GuestRequest.SCSIIO.u32MessageContext); 2350 else 2351 { 2352 /* The SCSI target encountered an error during processing post a reply. */ 2353 memset(&pLsiReq->IOCReply, 0, sizeof(MptReplyUnion)); 2354 pLsiReq->IOCReply.SCSIIOError.u8TargetID = pLsiReq->GuestRequest.SCSIIO.u8TargetID; 2355 pLsiReq->IOCReply.SCSIIOError.u8Bus = pLsiReq->GuestRequest.SCSIIO.u8Bus; 2356 pLsiReq->IOCReply.SCSIIOError.u8MessageLength = 8; 2357 pLsiReq->IOCReply.SCSIIOError.u8Function = pLsiReq->GuestRequest.SCSIIO.u8Function; 2358 pLsiReq->IOCReply.SCSIIOError.u8CDBLength = pLsiReq->GuestRequest.SCSIIO.u8CDBLength; 2359 pLsiReq->IOCReply.SCSIIOError.u8SenseBufferLength = pLsiReq->GuestRequest.SCSIIO.u8SenseBufferLength; 2360 pLsiReq->IOCReply.SCSIIOError.u8MessageFlags = pLsiReq->GuestRequest.SCSIIO.u8MessageFlags; 2361 pLsiReq->IOCReply.SCSIIOError.u32MessageContext = pLsiReq->GuestRequest.SCSIIO.u32MessageContext; 2362 pLsiReq->IOCReply.SCSIIOError.u8SCSIStatus = rcCompletion; 2363 pLsiReq->IOCReply.SCSIIOError.u8SCSIState = MPT_SCSI_IO_ERROR_SCSI_STATE_AUTOSENSE_VALID; 2364 pLsiReq->IOCReply.SCSIIOError.u16IOCStatus = 0; 2365 pLsiReq->IOCReply.SCSIIOError.u32IOCLogInfo = 0; 2366 pLsiReq->IOCReply.SCSIIOError.u32TransferCount = 0; 2367 pLsiReq->IOCReply.SCSIIOError.u32SenseCount = sizeof(pLsiReq->abSenseBuffer); 2368 pLsiReq->IOCReply.SCSIIOError.u32ResponseInfo = 0; 2369 2370 lsilogicFinishAddressReply(pThis, &pLsiReq->IOCReply, false); 2371 } 2372 } 2373 2374 RTMemCacheFree(pThis->hTaskCache, pLsiReq); 2375 } 2376 2377 ASMAtomicDecU32(&pLsiLogicDevice->cOutstandingRequests); 2378 2379 if (pLsiLogicDevice->cOutstandingRequests == 0 && pThis->fSignalIdle) 2380 PDMDevHlpAsyncNotificationCompleted(pThis->pDevInsR3); 2381 2382 return VINF_SUCCESS; 2383 } 2384 2385 /** 2386 * @interface_method_impl{PDMISCSIPORT,pfnQueryDeviceLocation} 2387 */ 2388 static DECLCALLBACK(int) lsilogicR3QueryDeviceLocation(PPDMISCSIPORT pInterface, const char **ppcszController, 2313 * @interface_method_impl{PDMIMEDIA,pfnQueryDeviceLocation} 2314 */ 2315 static DECLCALLBACK(int) lsilogicR3QueryDeviceLocation(PPDMIMEDIAPORT pInterface, const char **ppcszController, 2389 2316 uint32_t *piInstance, uint32_t *piLUN) 2390 2317 { 2391 PLSILOGICDEVICE p LsiLogicDevice = RT_FROM_MEMBER(pInterface, LSILOGICDEVICE, ISCSIPort);2392 PPDMDEVINS pDevIns = p LsiLogicDevice->CTX_SUFF(pLsiLogic)->CTX_SUFF(pDevIns);2318 PLSILOGICDEVICE pTgtDev = RT_FROM_MEMBER(pInterface, LSILOGICDEVICE, IMediaPort); 2319 PPDMDEVINS pDevIns = pTgtDev->CTX_SUFF(pLsiLogic)->CTX_SUFF(pDevIns); 2393 2320 2394 2321 AssertPtrReturn(ppcszController, VERR_INVALID_POINTER); … … 2398 2325 *ppcszController = pDevIns->pReg->szName; 2399 2326 *piInstance = pDevIns->iInstance; 2400 *piLUN = p LsiLogicDevice->iLUN;2327 *piLUN = pTgtDev->iLUN; 2401 2328 2402 2329 return VINF_SUCCESS; 2403 2330 } 2331 2332 2333 /** 2334 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqCopyFromBuf} 2335 */ 2336 static DECLCALLBACK(int) lsilogicR3IoReqCopyFromBuf(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq, 2337 void *pvIoReqAlloc, uint32_t offDst, PRTSGBUF pSgBuf, 2338 size_t cbCopy) 2339 { 2340 RT_NOREF1(hIoReq); 2341 PLSILOGICDEVICE pTgtDev = RT_FROM_MEMBER(pInterface, LSILOGICDEVICE, IMediaExPort); 2342 PLSILOGICREQ pReq = (PLSILOGICREQ)pvIoReqAlloc; 2343 2344 size_t cbCopied = 0; 2345 if (RT_UNLIKELY(pReq->fBIOS)) 2346 cbCopied = vboxscsiCopyToBuf(&pTgtDev->CTX_SUFF(pLsiLogic)->VBoxSCSI, pSgBuf, offDst, cbCopy); 2347 else 2348 cbCopied = lsilogicR3CopySgBufToGuest(pTgtDev->CTX_SUFF(pLsiLogic), pReq, pSgBuf, offDst, cbCopy); 2349 return cbCopied == cbCopy ? VINF_SUCCESS : VERR_PDM_MEDIAEX_IOBUF_OVERFLOW; 2350 } 2351 2352 /** 2353 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqCopyToBuf} 2354 */ 2355 static DECLCALLBACK(int) lsilogicR3IoReqCopyToBuf(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq, 2356 void *pvIoReqAlloc, uint32_t offSrc, PRTSGBUF pSgBuf, 2357 size_t cbCopy) 2358 { 2359 RT_NOREF1(hIoReq); 2360 PLSILOGICDEVICE pTgtDev = RT_FROM_MEMBER(pInterface, LSILOGICDEVICE, IMediaExPort); 2361 PLSILOGICREQ pReq = (PLSILOGICREQ)pvIoReqAlloc; 2362 2363 size_t cbCopied = 0; 2364 if (RT_UNLIKELY(pReq->fBIOS)) 2365 cbCopied = vboxscsiCopyFromBuf(&pTgtDev->CTX_SUFF(pLsiLogic)->VBoxSCSI, pSgBuf, offSrc, cbCopy); 2366 else 2367 cbCopied = lsilogicR3CopySgBufFromGuest(pTgtDev->CTX_SUFF(pLsiLogic), pReq, pSgBuf, offSrc, cbCopy); 2368 return cbCopied == cbCopy ? VINF_SUCCESS : VERR_PDM_MEDIAEX_IOBUF_UNDERRUN; 2369 } 2370 2371 /** 2372 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqCompleteNotify} 2373 */ 2374 static DECLCALLBACK(int) lsilogicR3IoReqCompleteNotify(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq, 2375 void *pvIoReqAlloc, int rcReq) 2376 { 2377 RT_NOREF(hIoReq); 2378 PLSILOGICDEVICE pTgtDev = RT_FROM_MEMBER(pInterface, LSILOGICDEVICE, IMediaExPort); 2379 lsilogicR3ReqComplete(pTgtDev->CTX_SUFF(pLsiLogic), (PLSILOGICREQ)pvIoReqAlloc, rcReq); 2380 return VINF_SUCCESS; 2381 } 2382 2383 /** 2384 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqStateChanged} 2385 */ 2386 static DECLCALLBACK(void) lsilogicR3IoReqStateChanged(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq, 2387 void *pvIoReqAlloc, PDMMEDIAEXIOREQSTATE enmState) 2388 { 2389 RT_NOREF3(hIoReq, pvIoReqAlloc, enmState); 2390 PLSILOGICDEVICE pTgtDev = RT_FROM_MEMBER(pInterface, LSILOGICDEVICE, IMediaExPort); 2391 2392 switch (enmState) 2393 { 2394 case PDMMEDIAEXIOREQSTATE_SUSPENDED: 2395 { 2396 /* Make sure the request is not accounted for so the VM can suspend successfully. */ 2397 uint32_t cTasksActive = ASMAtomicDecU32(&pTgtDev->cOutstandingRequests); 2398 if (!cTasksActive && pTgtDev->CTX_SUFF(pLsiLogic)->fSignalIdle) 2399 PDMDevHlpAsyncNotificationCompleted(pTgtDev->CTX_SUFF(pLsiLogic)->pDevInsR3); 2400 break; 2401 } 2402 case PDMMEDIAEXIOREQSTATE_ACTIVE: 2403 /* Make sure the request is accounted for so the VM suspends only when the request is complete. */ 2404 ASMAtomicIncU32(&pTgtDev->cOutstandingRequests); 2405 break; 2406 default: 2407 AssertMsgFailed(("Invalid request state given %u\n", enmState)); 2408 } 2409 } 2410 2411 /** 2412 * @interface_method_impl{PDMIMEDIAEXPORT,pfnMediumEjected} 2413 */ 2414 static DECLCALLBACK(void) lsilogicR3MediumEjected(PPDMIMEDIAEXPORT pInterface) 2415 { 2416 PLSILOGICDEVICE pTgtDev = RT_FROM_MEMBER(pInterface, LSILOGICDEVICE, IMediaExPort); 2417 PLSILOGICSCSI pThis = pTgtDev->CTX_SUFF(pLsiLogic); 2418 2419 RT_NOREF(pThis); /** @todo */ 2420 } 2421 2404 2422 2405 2423 /** … … 3807 3825 { 3808 3826 int rc; 3809 PLSILOGICREQ pLsiReq; 3810 uint32_t uTargetDevice; 3811 3812 rc = RTMemCacheAllocEx(pThis->hTaskCache, (void **)&pLsiReq); 3813 AssertMsgRCReturn(rc, ("Getting task from cache failed rc=%Rrc\n", rc), rc); 3814 3815 pLsiReq->fBIOS = true; 3816 3817 rc = vboxscsiSetupRequest(&pThis->VBoxSCSI, &pLsiReq->PDMScsiRequest, &uTargetDevice); 3827 uint32_t uTargetDevice; 3828 uint32_t uLun; 3829 uint8_t *pbCdb; 3830 size_t cbCdb; 3831 size_t cbBuf; 3832 3833 rc = vboxscsiSetupRequest(&pThis->VBoxSCSI, &uLun, &pbCdb, &cbCdb, &cbBuf, &uTargetDevice); 3818 3834 AssertMsgRCReturn(rc, ("Setting up SCSI request failed rc=%Rrc\n", rc), rc); 3819 3835 3820 pLsiReq->PDMScsiRequest.pvUser = pLsiReq; 3821 3822 if (uTargetDevice < pThis->cDeviceStates) 3823 { 3824 pLsiReq->pTargetDevice = &pThis->paDeviceStates[uTargetDevice]; 3825 3826 if (pLsiReq->pTargetDevice->pDrvBase) 3827 { 3828 ASMAtomicIncU32(&pLsiReq->pTargetDevice->cOutstandingRequests); 3829 3830 rc = pLsiReq->pTargetDevice->pDrvSCSIConnector->pfnSCSIRequestSend(pLsiReq->pTargetDevice->pDrvSCSIConnector, 3831 &pLsiReq->PDMScsiRequest); 3832 AssertMsgRCReturn(rc, ("Sending request to SCSI layer failed rc=%Rrc\n", rc), rc); 3833 return VINF_SUCCESS; 3834 } 3836 if ( uTargetDevice < pThis->cDeviceStates 3837 && pThis->paDeviceStates[uTargetDevice].pDrvBase) 3838 { 3839 PLSILOGICDEVICE pTgtDev = &pThis->paDeviceStates[uTargetDevice]; 3840 PDMMEDIAEXIOREQ hIoReq; 3841 PLSILOGICREQ pReq; 3842 3843 rc = pTgtDev->pDrvMediaEx->pfnIoReqAlloc(pTgtDev->pDrvMediaEx, &hIoReq, (void **)&pReq, 3844 0, PDMIMEDIAEX_F_SUSPEND_ON_RECOVERABLE_ERR); 3845 AssertMsgRCReturn(rc, ("Getting task from cache failed rc=%Rrc\n", rc), rc); 3846 3847 pReq->fBIOS = true; 3848 pReq->hIoReq = hIoReq; 3849 pReq->pTargetDevice = pTgtDev; 3850 3851 ASMAtomicIncU32(&pTgtDev->cOutstandingRequests); 3852 3853 rc = pTgtDev->pDrvMediaEx->pfnIoReqSendScsiCmd(pTgtDev->pDrvMediaEx, pReq->hIoReq, uLun, 3854 pbCdb, cbCdb, PDMMEDIAEXIOREQSCSITXDIR_UNKNOWN, 3855 cbBuf, NULL, 0, &pReq->u8ScsiSts, 30 * RT_MS_1SEC); 3856 if (rc == VINF_SUCCESS || rc != VINF_PDM_MEDIAEX_IOREQ_IN_PROGRESS) 3857 { 3858 uint8_t u8ScsiSts = pReq->u8ScsiSts; 3859 pTgtDev->pDrvMediaEx->pfnIoReqFree(pTgtDev->pDrvMediaEx, pReq->hIoReq); 3860 rc = vboxscsiRequestFinished(&pThis->VBoxSCSI, u8ScsiSts); 3861 } 3862 else if (rc == VINF_PDM_MEDIAEX_IOREQ_IN_PROGRESS) 3863 rc = VINF_SUCCESS; 3864 3865 return rc; 3835 3866 } 3836 3867 3837 3868 /* Device is not present. */ 3838 AssertMsg(p LsiReq->PDMScsiRequest.pbCDB[0] == SCSI_INQUIRY,3839 3869 AssertMsg(pbCdb[0] == SCSI_INQUIRY, 3870 ("Device is not present but command is not inquiry\n")); 3840 3871 3841 3872 SCSIINQUIRYDATA ScsiInquiryData; … … 3847 3878 memcpy(pThis->VBoxSCSI.pbBuf, &ScsiInquiryData, 5); 3848 3879 3849 rc = vboxscsiRequestFinished(&pThis->VBoxSCSI, &pLsiReq->PDMScsiRequest,SCSI_STATUS_OK);3880 rc = vboxscsiRequestFinished(&pThis->VBoxSCSI, SCSI_STATUS_OK); 3850 3881 AssertMsgRCReturn(rc, ("Finishing BIOS SCSI request failed rc=%Rrc\n", rc), rc); 3851 3882 3852 RTMemCacheFree(pThis->hTaskCache, pLsiReq);3853 3883 return rc; 3854 3884 } … … 4243 4273 && (pThis->uRequestQueueNextAddressRead != uRequestQueueNextEntryWrite)) 4244 4274 { 4275 MptRequestUnion GuestRequest; 4245 4276 uint32_t u32RequestMessageFrameDesc = pThis->CTX_SUFF(pRequestQueueBase)[pThis->uRequestQueueNextAddressRead]; 4246 4277 RTGCPHYS GCPhysMessageFrameAddr = LSILOGIC_RTGCPHYS_FROM_U32(pThis->u32HostMFAHighAddr, 4247 4278 (u32RequestMessageFrameDesc & ~0x07)); 4248 4279 4249 PLSILOGICREQ pLsiReq;4250 4251 /* Get new task state. */4252 rc = RTMemCacheAllocEx(pThis->hTaskCache, (void **)&pLsiReq);4253 AssertRC(rc);4254 4255 pLsiReq->GCPhysMessageFrameAddr = GCPhysMessageFrameAddr;4256 4257 4280 /* Read the message header from the guest first. */ 4258 PDMDevHlpPhysRead(pDevIns, GCPhysMessageFrameAddr, & pLsiReq->GuestRequest, sizeof(MptMessageHdr));4281 PDMDevHlpPhysRead(pDevIns, GCPhysMessageFrameAddr, &GuestRequest, sizeof(MptMessageHdr)); 4259 4282 4260 4283 /* Determine the size of the request. */ 4261 4284 uint32_t cbRequest = 0; 4262 4263 switch (pLsiReq->GuestRequest.Header.u8Function) 4285 switch (GuestRequest.Header.u8Function) 4264 4286 { 4265 4287 case MPT_MESSAGE_HDR_FUNCTION_SCSI_IO_REQUEST: … … 4298 4320 break; 4299 4321 default: 4300 AssertMsgFailed(("Unknown function issued %u\n", pLsiReq->GuestRequest.Header.u8Function));4322 AssertMsgFailed(("Unknown function issued %u\n", GuestRequest.Header.u8Function)); 4301 4323 lsilogicSetIOCFaultCode(pThis, LSILOGIC_IOCSTATUS_INVALID_FUNCTION); 4302 4324 } … … 4305 4327 { 4306 4328 /* Read the complete message frame from guest memory now. */ 4307 PDMDevHlpPhysRead(pDevIns, GCPhysMessageFrameAddr, & pLsiReq->GuestRequest, cbRequest);4329 PDMDevHlpPhysRead(pDevIns, GCPhysMessageFrameAddr, &GuestRequest, cbRequest); 4308 4330 4309 4331 /* Handle SCSI I/O requests now. */ 4310 if ( pLsiReq->GuestRequest.Header.u8Function == MPT_MESSAGE_HDR_FUNCTION_SCSI_IO_REQUEST)4332 if (GuestRequest.Header.u8Function == MPT_MESSAGE_HDR_FUNCTION_SCSI_IO_REQUEST) 4311 4333 { 4312 rc = lsilogicR3ProcessSCSIIORequest(pThis, pLsiReq);4334 rc = lsilogicR3ProcessSCSIIORequest(pThis, GCPhysMessageFrameAddr, &GuestRequest); 4313 4335 AssertRC(rc); 4314 4336 } … … 4316 4338 { 4317 4339 MptReplyUnion Reply; 4318 rc = lsilogicR3ProcessMessageRequest(pThis, & pLsiReq->GuestRequest.Header, &Reply);4340 rc = lsilogicR3ProcessMessageRequest(pThis, &GuestRequest.Header, &Reply); 4319 4341 AssertRC(rc); 4320 RTMemCacheFree(pThis->hTaskCache, pLsiReq);4321 4342 } 4322 4343 … … 4355 4376 static void lsilogicR3Kick(PLSILOGICSCSI pThis) 4356 4377 { 4357 if ( pThis->VBoxSCSI.fBusy4358 && !pThis->fBiosReqPending)4359 pThis->fBiosReqPending = true;4360 4361 4378 if (pThis->fNotificationSent) 4362 4379 { … … 4408 4425 ("There are still outstanding requests on this device\n")); 4409 4426 SSMR3PutU32(pSSM, pDevice->cOutstandingRequests); 4410 } 4427 4428 /* Query all suspended requests and store them in the request queue. */ 4429 if (pDevice->pDrvMediaEx) 4430 { 4431 uint32_t cReqsRedo = pDevice->pDrvMediaEx->pfnIoReqGetSuspendedCount(pDevice->pDrvMediaEx); 4432 if (cReqsRedo) 4433 { 4434 PDMMEDIAEXIOREQ hIoReq; 4435 PLSILOGICREQ pReq; 4436 int rc = pDevice->pDrvMediaEx->pfnIoReqQuerySuspendedStart(pDevice->pDrvMediaEx, &hIoReq, 4437 (void **)&pReq); 4438 AssertRCBreak(rc); 4439 4440 for (;;) 4441 { 4442 if (!pReq->fBIOS) 4443 { 4444 /* Write only the lower 32bit part of the address. */ 4445 ASMAtomicWriteU32(&pThis->CTX_SUFF(pRequestQueueBase)[pThis->uRequestQueueNextEntryFreeWrite], 4446 pReq->GCPhysMessageFrameAddr & UINT32_C(0xffffffff)); 4447 4448 pThis->uRequestQueueNextEntryFreeWrite++; 4449 pThis->uRequestQueueNextEntryFreeWrite %= pThis->cRequestQueueEntries; 4450 } 4451 else 4452 { 4453 AssertMsg(!pReq->pRedoNext, ("Only one BIOS task can be active!\n")); 4454 vboxscsiSetRequestRedo(&pThis->VBoxSCSI); 4455 } 4456 4457 cReqsRedo--; 4458 if (!cReqsRedo) 4459 break; 4460 4461 rc = pDevice->pDrvMediaEx->pfnIoReqQuerySuspendedNext(pDevice->pDrvMediaEx, hIoReq, 4462 &hIoReq, (void **)&pReq); 4463 AssertRCBreak(rc); 4464 } 4465 } 4466 } 4467 } 4468 4411 4469 /* Now the main device state. */ 4412 4470 SSMR3PutU32 (pSSM, pThis->enmState); … … 4924 4982 4925 4983 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDevice->IBase); 4926 PDMIBASE_RETURN_INTERFACE(pszIID, PDMISCSIPORT, &pDevice->ISCSIPort); 4984 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAPORT, &pDevice->IMediaPort); 4985 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAEXPORT, &pDevice->IMediaExPort); 4927 4986 PDMIBASE_RETURN_INTERFACE(pszIID, PDMILEDPORTS, &pDevice->ILed); 4928 4987 return NULL; … … 5024 5083 5025 5084 AssertMsg(!pThis->fNotificationSent, ("The PDM Queue should be empty at this point\n")); 5026 5027 if (pThis->fRedo)5028 {5029 /*5030 * We have tasks which we need to redo. Put the message frame addresses5031 * into the request queue (we save the requests).5032 * Guest execution is suspended at this point so there is no race between us and5033 * lsilogicRegisterWrite.5034 */5035 PLSILOGICREQ pLsiReq = pThis->pTasksRedoHead;5036 5037 pThis->pTasksRedoHead = NULL;5038 5039 while (pLsiReq)5040 {5041 PLSILOGICREQ pFree;5042 5043 if (!pLsiReq->fBIOS)5044 {5045 /* Write only the lower 32bit part of the address. */5046 ASMAtomicWriteU32(&pThis->CTX_SUFF(pRequestQueueBase)[pThis->uRequestQueueNextEntryFreeWrite],5047 pLsiReq->GCPhysMessageFrameAddr & UINT32_C(0xffffffff));5048 5049 pThis->uRequestQueueNextEntryFreeWrite++;5050 pThis->uRequestQueueNextEntryFreeWrite %= pThis->cRequestQueueEntries;5051 }5052 else5053 {5054 AssertMsg(!pLsiReq->pRedoNext, ("Only one BIOS task can be active!\n"));5055 vboxscsiSetRequestRedo(&pThis->VBoxSCSI, &pLsiReq->PDMScsiRequest);5056 }5057 5058 pThis->fNotificationSent = true;5059 5060 pFree = pLsiReq;5061 pLsiReq = pLsiReq->pRedoNext;5062 5063 RTMemCacheFree(pThis->hTaskCache, pFree);5064 }5065 pThis->fRedo = false;5066 }5067 5085 } 5068 5086 } … … 5113 5131 */ 5114 5132 pDevice->pDrvBase = NULL; 5115 pDevice->pDrvSCSIConnector = NULL; 5133 pDevice->pDrvMedia = NULL; 5134 pDevice->pDrvMediaEx = NULL; 5116 5135 } 5117 5136 … … 5134 5153 /* the usual paranoia */ 5135 5154 AssertRelease(!pDevice->pDrvBase); 5136 AssertRelease(!pDevice->pDrvSCSIConnector); 5155 AssertRelease(!pDevice->pDrvMedia); 5156 AssertRelease(!pDevice->pDrvMediaEx); 5137 5157 Assert(pDevice->iLUN == iLUN); 5138 5158 … … 5144 5164 if (RT_SUCCESS(rc)) 5145 5165 { 5146 /* Get SCSI connector interface. */ 5147 pDevice->pDrvSCSIConnector = PDMIBASE_QUERY_INTERFACE(pDevice->pDrvBase, PDMISCSICONNECTOR); 5148 AssertMsgReturn(pDevice->pDrvSCSIConnector, ("Missing SCSI interface below\n"), VERR_PDM_MISSING_INTERFACE); 5166 /* Query the media interface. */ 5167 pDevice->pDrvMedia = PDMIBASE_QUERY_INTERFACE(pDevice->pDrvBase, PDMIMEDIA); 5168 AssertMsgReturn(VALID_PTR(pDevice->pDrvMedia), 5169 ("LsiLogic configuration error: LUN#%d misses the basic media interface!\n", pDevice->iLUN), 5170 VERR_PDM_MISSING_INTERFACE); 5171 5172 /* Get the extended media interface. */ 5173 pDevice->pDrvMediaEx = PDMIBASE_QUERY_INTERFACE(pDevice->pDrvBase, PDMIMEDIAEX); 5174 AssertMsgReturn(VALID_PTR(pDevice->pDrvMediaEx), 5175 ("LsiLogic configuration error: LUN#%d misses the extended media interface!\n", pDevice->iLUN), 5176 VERR_PDM_MISSING_INTERFACE); 5177 5178 rc = pDevice->pDrvMediaEx->pfnIoReqAllocSizeSet(pDevice->pDrvMediaEx, sizeof(LSILOGICREQ)); 5179 AssertMsgRCReturn(rc, ("LsiLogic configuration error: LUN#%u: Failed to set I/O request size!"), 5180 pDevice->iLUN); 5149 5181 } 5150 5182 else … … 5154 5186 { 5155 5187 pDevice->pDrvBase = NULL; 5156 pDevice->pDrvSCSIConnector = NULL; 5188 pDevice->pDrvMedia = NULL; 5189 pDevice->pDrvMediaEx = NULL; 5157 5190 } 5158 5191 return rc; … … 5247 5280 pThis->paDeviceStates = NULL; 5248 5281 5249 /* Destroy task cache. */5250 if (pThis->hTaskCache != NIL_RTMEMCACHE)5251 {5252 int rc = RTMemCacheDestroy(pThis->hTaskCache); AssertRC(rc);5253 pThis->hTaskCache = NIL_RTMEMCACHE;5254 }5255 5256 5282 if (pThis->hEvtProcess != NIL_SUPSEMEVENT) 5257 5283 { … … 5278 5304 * Initialize enought of the state to make the destructure not trip up. 5279 5305 */ 5280 pThis->hTaskCache = NIL_RTMEMCACHE;5281 5306 pThis->hEvtProcess = NIL_SUPSEMEVENT; 5282 5307 pThis->fBiosReqPending = false; … … 5483 5508 return rc; 5484 5509 5485 /*5486 * Allocate task cache.5487 */5488 rc = RTMemCacheCreate(&pThis->hTaskCache, sizeof(LSILOGICREQ), 0, UINT32_MAX,5489 NULL, NULL, NULL, 0);5490 if (RT_FAILURE(rc))5491 return PDMDEV_SET_ERROR(pDevIns, rc, N_("Cannot create task cache"));5492 5493 5510 if (pThis->enmCtrlType == LSILOGICCTRLTYPE_SCSI_SPI) 5494 5511 pThis->cDeviceStates = pThis->cPorts * LSILOGICSCSI_PCI_SPI_DEVICES_PER_BUS_MAX; … … 5525 5542 5526 5543 /* Initialize static parts of the device. */ 5527 pDevice->iLUN = i; 5528 pDevice->pLsiLogicR3 = pThis; 5529 pDevice->Led.u32Magic = PDMLED_MAGIC; 5530 pDevice->IBase.pfnQueryInterface = lsilogicR3DeviceQueryInterface; 5531 pDevice->ISCSIPort.pfnSCSIRequestCompleted = lsilogicR3DeviceSCSIRequestCompleted; 5532 pDevice->ISCSIPort.pfnQueryDeviceLocation = lsilogicR3QueryDeviceLocation; 5533 pDevice->ILed.pfnQueryStatusLed = lsilogicR3DeviceQueryStatusLed; 5544 pDevice->iLUN = i; 5545 pDevice->pLsiLogicR3 = pThis; 5546 pDevice->Led.u32Magic = PDMLED_MAGIC; 5547 pDevice->IBase.pfnQueryInterface = lsilogicR3DeviceQueryInterface; 5548 pDevice->IMediaPort.pfnQueryDeviceLocation = lsilogicR3QueryDeviceLocation; 5549 pDevice->IMediaExPort.pfnIoReqCompleteNotify = lsilogicR3IoReqCompleteNotify; 5550 pDevice->IMediaExPort.pfnIoReqCopyFromBuf = lsilogicR3IoReqCopyFromBuf; 5551 pDevice->IMediaExPort.pfnIoReqCopyToBuf = lsilogicR3IoReqCopyToBuf; 5552 pDevice->IMediaExPort.pfnIoReqQueryDiscardRanges = NULL; 5553 pDevice->IMediaExPort.pfnIoReqStateChanged = lsilogicR3IoReqStateChanged; 5554 pDevice->IMediaExPort.pfnMediumEjected = lsilogicR3MediumEjected; 5555 pDevice->ILed.pfnQueryStatusLed = lsilogicR3DeviceQueryStatusLed; 5534 5556 5535 5557 RTStrPrintf(szName, sizeof(szName), "Device%u", i); … … 5539 5561 if (RT_SUCCESS(rc)) 5540 5562 { 5541 /* Get SCSI connector interface. */ 5542 pDevice->pDrvSCSIConnector = PDMIBASE_QUERY_INTERFACE(pDevice->pDrvBase, PDMISCSICONNECTOR); 5543 AssertMsgReturn(pDevice->pDrvSCSIConnector, ("Missing SCSI interface below\n"), VERR_PDM_MISSING_INTERFACE); 5563 /* Query the media interface. */ 5564 pDevice->pDrvMedia = PDMIBASE_QUERY_INTERFACE(pDevice->pDrvBase, PDMIMEDIA); 5565 AssertMsgReturn(VALID_PTR(pDevice->pDrvMedia), 5566 ("LsiLogic configuration error: LUN#%d misses the basic media interface!\n", pDevice->iLUN), 5567 VERR_PDM_MISSING_INTERFACE); 5568 5569 /* Get the extended media interface. */ 5570 pDevice->pDrvMediaEx = PDMIBASE_QUERY_INTERFACE(pDevice->pDrvBase, PDMIMEDIAEX); 5571 AssertMsgReturn(VALID_PTR(pDevice->pDrvMediaEx), 5572 ("LsiLogic configuration error: LUN#%d misses the extended media interface!\n", pDevice->iLUN), 5573 VERR_PDM_MISSING_INTERFACE); 5574 5575 rc = pDevice->pDrvMediaEx->pfnIoReqAllocSizeSet(pDevice->pDrvMediaEx, sizeof(LSILOGICREQ)); 5576 if (RT_FAILURE(rc)) 5577 return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS, 5578 N_("LsiLogic configuration error: LUN#%u: Failed to set I/O request size!"), 5579 pDevice->iLUN); 5544 5580 } 5545 5581 else if (rc == VERR_PDM_NO_ATTACHED_DRIVER) -
trunk/src/VBox/Devices/Storage/VBoxSCSI.cpp
r63657 r64224 277 277 * @returns VBox status code. 278 278 * @param pVBoxSCSI Pointer to the SCSI state. 279 * @param pScsiRequest Pointer to a scsi request to setup. 279 * @paam puLun Where to store the LUN on success. 280 * @param ppbCdb Where to store the pointer to the CDB on success. 281 * @param pcbCdb Where to store the size of the CDB on success. 282 * @param pcbBuf Where to store th size of the data buffer on success. 280 283 * @param puTargetDevice Where to store the target device ID. 281 284 */ 282 int vboxscsiSetupRequest(PVBOXSCSI pVBoxSCSI, PPDMSCSIREQUEST pScsiRequest, uint32_t *puTargetDevice) 285 int vboxscsiSetupRequest(PVBOXSCSI pVBoxSCSI, uint32_t *puLun, uint8_t **ppbCdb, 286 size_t *pcbCdb, size_t *pcbBuf, uint32_t *puTargetDevice) 283 287 { 284 288 int rc = VINF_SUCCESS; 285 289 286 LogFlowFunc(("pVBoxSCSI=%#p p ScsiRequest=%#p puTargetDevice=%#p\n", pVBoxSCSI, pScsiRequest, puTargetDevice));290 LogFlowFunc(("pVBoxSCSI=%#p puTargetDevice=%#p\n", pVBoxSCSI, puTargetDevice)); 287 291 288 292 AssertMsg(pVBoxSCSI->enmState == VBOXSCSISTATE_COMMAND_READY, ("Invalid state %u\n", pVBoxSCSI->enmState)); … … 301 305 } 302 306 303 /* Allocate scatter gather element. */ 304 pScsiRequest->paScatterGatherHead = (PRTSGSEG)RTMemAllocZ(sizeof(RTSGSEG) * 1); /* Only one element. */ 305 if (!pScsiRequest->paScatterGatherHead) 306 { 307 RTMemFree(pVBoxSCSI->pbBuf); 308 pVBoxSCSI->pbBuf = NULL; 309 return VERR_NO_MEMORY; 310 } 311 312 /* Allocate sense buffer. */ 313 pScsiRequest->cbSenseBuffer = 18; 314 pScsiRequest->pbSenseBuffer = (uint8_t *)RTMemAllocZ(pScsiRequest->cbSenseBuffer); 315 316 pScsiRequest->cbCDB = pVBoxSCSI->cbCDB; 317 pScsiRequest->pbCDB = pVBoxSCSI->abCDB; 318 pScsiRequest->uLogicalUnit = 0; 319 pScsiRequest->cbScatterGather = pVBoxSCSI->cbBuf; 320 pScsiRequest->cScatterGatherEntries = 1; 321 322 pScsiRequest->paScatterGatherHead[0].cbSeg = pVBoxSCSI->cbBuf; 323 pScsiRequest->paScatterGatherHead[0].pvSeg = pVBoxSCSI->pbBuf; 324 307 *puLun = 0; 308 *ppbCdb = &pVBoxSCSI->abCDB[0]; 309 *pcbCdb = pVBoxSCSI->cbCDB; 310 *pcbBuf = pVBoxSCSI->cbBuf; 325 311 *puTargetDevice = pVBoxSCSI->uTargetDevice; 326 312 … … 332 318 * is ready at the incoming data port. 333 319 */ 334 int vboxscsiRequestFinished(PVBOXSCSI pVBoxSCSI, PPDMSCSIREQUEST pScsiRequest, int rcCompletion) 335 { 336 LogFlowFunc(("pVBoxSCSI=%#p pScsiRequest=%#p\n", pVBoxSCSI, pScsiRequest)); 337 RTMemFree(pScsiRequest->paScatterGatherHead); 338 RTMemFree(pScsiRequest->pbSenseBuffer); 320 int vboxscsiRequestFinished(PVBOXSCSI pVBoxSCSI, int rcCompletion) 321 { 322 LogFlowFunc(("pVBoxSCSI=%#p\n", pVBoxSCSI)); 339 323 340 324 if (pVBoxSCSI->uTxDir == VBOXSCSI_TXDIR_TO_DEVICE) … … 346 330 347 331 return VINF_SUCCESS; 332 } 333 334 size_t vboxscsiCopyToBuf(PVBOXSCSI pVBoxSCSI, PRTSGBUF pSgBuf, size_t cbSkip, size_t cbCopy) 335 { 336 AssertPtrReturn(pVBoxSCSI->pbBuf, 0); 337 AssertReturn(cbSkip + cbCopy <= pVBoxSCSI->cbBuf, 0); 338 339 void *pvBuf = pVBoxSCSI->pbBuf + cbSkip; 340 return RTSgBufCopyToBuf(pSgBuf, pvBuf, cbCopy); 341 } 342 343 size_t vboxscsiCopyFromBuf(PVBOXSCSI pVBoxSCSI, PRTSGBUF pSgBuf, size_t cbSkip, size_t cbCopy) 344 { 345 AssertPtrReturn(pVBoxSCSI->pbBuf, 0); 346 AssertReturn(cbSkip + cbCopy <= pVBoxSCSI->cbBuf, 0); 347 348 void *pvBuf = pVBoxSCSI->pbBuf + cbSkip; 349 return RTSgBufCopyFromBuf(pSgBuf, pvBuf, cbCopy); 348 350 } 349 351 … … 452 454 } 453 455 454 void vboxscsiSetRequestRedo(PVBOXSCSI pVBoxSCSI , PPDMSCSIREQUEST pScsiRequest)456 void vboxscsiSetRequestRedo(PVBOXSCSI pVBoxSCSI) 455 457 { 456 458 AssertMsg(pVBoxSCSI->fBusy, ("No request to redo\n")); 457 458 RTMemFree(pScsiRequest->paScatterGatherHead);459 RTMemFree(pScsiRequest->pbSenseBuffer);460 459 461 460 if (pVBoxSCSI->uTxDir == VBOXSCSI_TXDIR_FROM_DEVICE) -
trunk/src/VBox/Devices/Storage/VBoxSCSI.h
r62506 r64224 136 136 int vboxscsiReadRegister(PVBOXSCSI pVBoxSCSI, uint8_t iRegister, uint32_t *pu32Value); 137 137 int vboxscsiWriteRegister(PVBOXSCSI pVBoxSCSI, uint8_t iRegister, uint8_t uVal); 138 int vboxscsiSetupRequest(PVBOXSCSI pVBoxSCSI, PPDMSCSIREQUEST pScsiRequest, uint32_t *puTargetDevice); 139 int vboxscsiRequestFinished(PVBOXSCSI pVBoxSCSI, PPDMSCSIREQUEST pScsiRequest, int rcCompletion); 140 void vboxscsiSetRequestRedo(PVBOXSCSI pVBoxSCSI, PPDMSCSIREQUEST pScsiRequest); 138 int vboxscsiSetupRequest(PVBOXSCSI pVBoxSCSI, uint32_t *puLun, uint8_t **ppbCdb, size_t *pcbCdb, 139 size_t *pcbBuf, uint32_t *puTargetDevice); 140 int vboxscsiRequestFinished(PVBOXSCSI pVBoxSCSI, int rcCompletion); 141 size_t vboxscsiCopyToBuf(PVBOXSCSI pVBoxSCSI, PRTSGBUF pSgBuf, size_t cbSkip, size_t cbCopy); 142 size_t vboxscsiCopyFromBuf(PVBOXSCSI pVBoxSCSI, PRTSGBUF pSgBuf, size_t cbSkip, size_t cbCopy); 143 void vboxscsiSetRequestRedo(PVBOXSCSI pVBoxSCSI); 141 144 int vboxscsiWriteString(PPDMDEVINS pDevIns, PVBOXSCSI pVBoxSCSI, uint8_t iRegister, 142 145 uint8_t const *pbSrc, uint32_t *pcTransfers, unsigned cb); -
trunk/src/VBox/Devices/testcase/tstDeviceStructSizeRC.cpp
r64176 r64224 1731 1731 GEN_CHECK_OFF(BUSLOGICDEVICE, iLUN); 1732 1732 GEN_CHECK_OFF(BUSLOGICDEVICE, IBase); 1733 GEN_CHECK_OFF(BUSLOGICDEVICE, ISCSIPort); 1733 GEN_CHECK_OFF(BUSLOGICDEVICE, IMediaPort); 1734 GEN_CHECK_OFF(BUSLOGICDEVICE, IMediaExPort); 1734 1735 GEN_CHECK_OFF(BUSLOGICDEVICE, ILed); 1735 1736 GEN_CHECK_OFF(BUSLOGICDEVICE, pDrvBase); 1736 GEN_CHECK_OFF(BUSLOGICDEVICE, pDrvSCSIConnector); 1737 GEN_CHECK_OFF(BUSLOGICDEVICE, pDrvMedia); 1738 GEN_CHECK_OFF(BUSLOGICDEVICE, pDrvMediaEx); 1737 1739 GEN_CHECK_OFF(BUSLOGICDEVICE, Led); 1738 1740 GEN_CHECK_OFF(BUSLOGICDEVICE, cOutstandingRequests); … … 1773 1775 GEN_CHECK_OFF(BUSLOGIC, pNotifierQueueRC); 1774 1776 GEN_CHECK_OFF(BUSLOGIC, CritSectIntr); 1775 GEN_CHECK_OFF(BUSLOGIC, hTaskCache);1776 1777 GEN_CHECK_OFF(BUSLOGIC, VBoxSCSI); 1777 1778 GEN_CHECK_OFF(BUSLOGIC, aDeviceStates); … … 1781 1782 GEN_CHECK_OFF(BUSLOGIC, pLedsConnector); 1782 1783 GEN_CHECK_OFF(BUSLOGIC, fSignalIdle); 1783 GEN_CHECK_OFF(BUSLOGIC, fRedo);1784 1784 GEN_CHECK_OFF(BUSLOGIC, fWrkThreadSleeping); 1785 1785 GEN_CHECK_OFF(BUSLOGIC, fBiosReqPending); 1786 GEN_CHECK_OFF(BUSLOGIC, pTasksRedoHead);1787 1786 GEN_CHECK_OFF(BUSLOGIC, pSupDrvSession); 1788 1787 GEN_CHECK_OFF(BUSLOGIC, hEvtProcess); 1788 GEN_CHECK_OFF(BUSLOGIC, paGCPhysAddrCCBRedo); 1789 GEN_CHECK_OFF(BUSLOGIC, cReqsRedo); 1789 1790 # ifdef LOG_ENABLED 1790 1791 GEN_CHECK_OFF(BUSLOGIC, cInMailboxesReady); … … 1852 1853 GEN_CHECK_OFF(LSILOGICSCSI, enmCtrlType); 1853 1854 GEN_CHECK_OFF(LSILOGICSCSI, VBoxSCSI); 1854 GEN_CHECK_OFF(LSILOGICSCSI, hTaskCache);1855 1855 GEN_CHECK_OFF(LSILOGICSCSI, IBase); 1856 1856 GEN_CHECK_OFF(LSILOGICSCSI, ILeds);
Note:
See TracChangeset
for help on using the changeset viewer.