1917
static void lsilogicWarningDiskFull(PPDMDEVINS pDevIns)
1920
LogRel(("LsiLogic#%d: Host disk full\n", pDevIns->iInstance));
1921
rc = PDMDevHlpVMSetRuntimeError(pDevIns, VMSETRTERR_FLAGS_SUSPEND | VMSETRTERR_FLAGS_NO_WAIT, "DevLsiLogic_DISKFULL",
1922
N_("Host system reported disk full. VM execution is suspended. You can resume after freeing some space"));
1926
static void lsilogicWarningFileTooBig(PPDMDEVINS pDevIns)
1929
LogRel(("LsiLogic#%d: File too big\n", pDevIns->iInstance));
1930
rc = PDMDevHlpVMSetRuntimeError(pDevIns, VMSETRTERR_FLAGS_SUSPEND | VMSETRTERR_FLAGS_NO_WAIT, "DevLsiLogic_FILETOOBIG",
1931
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"));
1935
static void lsilogicWarningISCSI(PPDMDEVINS pDevIns)
1938
LogRel(("LsiLogic#%d: iSCSI target unavailable\n", pDevIns->iInstance));
1939
rc = PDMDevHlpVMSetRuntimeError(pDevIns, VMSETRTERR_FLAGS_SUSPEND | VMSETRTERR_FLAGS_NO_WAIT, "DevLsiLogic_ISCSIDOWN",
1940
N_("The iSCSI target has stopped responding. VM execution is suspended. You can resume when it is available again"));
1944
static void lsilogicWarningUnknown(PPDMDEVINS pDevIns, int rc)
1947
LogRel(("LsiLogic#%d: Unknown but recoverable error has occurred (rc=%Rrc)\n", pDevIns->iInstance, rc));
1948
rc2 = PDMDevHlpVMSetRuntimeError(pDevIns, VMSETRTERR_FLAGS_SUSPEND | VMSETRTERR_FLAGS_NO_WAIT, "DevLsiLogic_UNKNOWN",
1949
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);
1953
static void lsilogicRedoSetWarning(PLSILOGICSCSI pThis, int rc)
1955
if (rc == VERR_DISK_FULL)
1956
lsilogicWarningDiskFull(pThis->CTX_SUFF(pDevIns));
1957
else if (rc == VERR_FILE_TOO_BIG)
1958
lsilogicWarningFileTooBig(pThis->CTX_SUFF(pDevIns));
1959
else if (rc == VERR_BROKEN_PIPE || rc == VERR_NET_CONNECTION_REFUSED)
1961
/* iSCSI connection abort (first error) or failure to reestablish
1962
* connection (second error). Pause VM. On resume we'll retry. */
1963
lsilogicWarningISCSI(pThis->CTX_SUFF(pDevIns));
1966
lsilogicWarningUnknown(pThis->CTX_SUFF(pDevIns), rc);
1893
1970
* Processes a SCSI I/O request by setting up the request
1894
1971
* and sending it to the underlying SCSI driver.
2019
* Called upon completion of the request from the SCSI driver below.
2020
* This function frees all allocated ressources and notifies the guest
2021
* that the process finished by asserting an interrupt.
2023
* @returns VBox status code.
2024
* @param pInterface Pointer to the interface the called funtion belongs to.
2025
* @param pSCSIRequest Pointer to the SCSI request which finished.
2027
static DECLCALLBACK(int) lsilogicDeviceSCSIRequestCompleted(PPDMISCSIPORT pInterface, PPDMSCSIREQUEST pSCSIRequest, int rcCompletion)
2096
static DECLCALLBACK(int) lsilogicDeviceSCSIRequestCompleted(PPDMISCSIPORT pInterface, PPDMSCSIREQUEST pSCSIRequest,
2097
int rcCompletion, bool fRedo, int rcReq)
2029
2099
PLSILOGICTASKSTATE pTaskState = (PLSILOGICTASKSTATE)pSCSIRequest->pvUser;
2030
2100
PLSILOGICDEVICE pLsiLogicDevice = pTaskState->pTargetDevice;
2031
2101
PLSILOGICSCSI pLsiLogic = pLsiLogicDevice->CTX_SUFF(pLsiLogic);
2103
/* If the task failed but it is possible to redo it again after a suspend
2104
* add it to the list. */
2107
if (!pTaskState->fBIOS)
2108
lsilogicScatterGatherListDestroy(pLsiLogic, pTaskState);
2110
/* Add to the list. */
2113
pTaskState->pRedoNext = ASMAtomicReadPtrT(&pLsiLogic->pTasksRedoHead, PLSILOGICTASKSTATE);
2114
} while (!ASMAtomicCmpXchgPtr(&pLsiLogic->pTasksRedoHead, pTaskState, pTaskState->pRedoNext));
2116
/* Suspend the VM if not done already. */
2117
if (!ASMAtomicXchgBool(&pLsiLogic->fRedo, true))
2118
lsilogicRedoSetWarning(pLsiLogic, rcReq);
2122
if (RT_UNLIKELY(pTaskState->fBIOS))
2124
int rc = vboxscsiRequestFinished(&pLsiLogic->VBoxSCSI, pSCSIRequest);
2125
AssertMsgRC(rc, ("Finishing BIOS SCSI request failed rc=%Rrc\n", rc));
2130
lsilogicFreeGCSenseBuffer(pLsiLogic, pTaskState);
2132
RTGCPHYS GCPhysAddrSenseBuffer;
2134
GCPhysAddrSenseBuffer = pTaskState->GuestRequest.SCSIIO.u32SenseBufferLowAddress;
2135
GCPhysAddrSenseBuffer |= ((uint64_t)pLsiLogic->u32SenseBufferHighAddr << 32);
2137
/* Copy the sense buffer over. */
2138
PDMDevHlpPhysWrite(pLsiLogic->CTX_SUFF(pDevIns), GCPhysAddrSenseBuffer, pTaskState->abSenseBuffer,
2139
RT_UNLIKELY(pTaskState->GuestRequest.SCSIIO.u8SenseBufferLength < pTaskState->PDMScsiRequest.cbSenseBuffer)
2140
? pTaskState->GuestRequest.SCSIIO.u8SenseBufferLength
2141
: pTaskState->PDMScsiRequest.cbSenseBuffer);
2143
lsilogicScatterGatherListDestroy(pLsiLogic, pTaskState);
2146
if (RT_LIKELY(rcCompletion == SCSI_STATUS_OK))
2147
lsilogicFinishContextReply(pLsiLogic, pTaskState->GuestRequest.SCSIIO.u32MessageContext);
2150
/* The SCSI target encountered an error during processing post a reply. */
2151
memset(&pTaskState->IOCReply, 0, sizeof(MptReplyUnion));
2152
pTaskState->IOCReply.SCSIIOError.u8TargetID = pTaskState->GuestRequest.SCSIIO.u8TargetID;
2153
pTaskState->IOCReply.SCSIIOError.u8Bus = pTaskState->GuestRequest.SCSIIO.u8Bus;
2154
pTaskState->IOCReply.SCSIIOError.u8MessageLength = 8;
2155
pTaskState->IOCReply.SCSIIOError.u8Function = pTaskState->GuestRequest.SCSIIO.u8Function;
2156
pTaskState->IOCReply.SCSIIOError.u8CDBLength = pTaskState->GuestRequest.SCSIIO.u8CDBLength;
2157
pTaskState->IOCReply.SCSIIOError.u8SenseBufferLength = pTaskState->GuestRequest.SCSIIO.u8SenseBufferLength;
2158
pTaskState->IOCReply.SCSIIOError.u8MessageFlags = pTaskState->GuestRequest.SCSIIO.u8MessageFlags;
2159
pTaskState->IOCReply.SCSIIOError.u32MessageContext = pTaskState->GuestRequest.SCSIIO.u32MessageContext;
2160
pTaskState->IOCReply.SCSIIOError.u8SCSIStatus = rcCompletion;
2161
pTaskState->IOCReply.SCSIIOError.u8SCSIState = MPT_SCSI_IO_ERROR_SCSI_STATE_AUTOSENSE_VALID;
2162
pTaskState->IOCReply.SCSIIOError.u16IOCStatus = 0;
2163
pTaskState->IOCReply.SCSIIOError.u32IOCLogInfo = 0;
2164
pTaskState->IOCReply.SCSIIOError.u32TransferCount = 0;
2165
pTaskState->IOCReply.SCSIIOError.u32SenseCount = sizeof(pTaskState->abSenseBuffer);
2166
pTaskState->IOCReply.SCSIIOError.u32ResponseInfo = 0;
2168
lsilogicFinishAddressReply(pLsiLogic, &pTaskState->IOCReply, true);
2172
RTMemCacheFree(pLsiLogic->hTaskCache, pTaskState);
2033
2175
ASMAtomicDecU32(&pLsiLogicDevice->cOutstandingRequests);
2035
if (RT_UNLIKELY(pTaskState->fBIOS))
2037
int rc = vboxscsiRequestFinished(&pLsiLogic->VBoxSCSI, pSCSIRequest);
2038
AssertMsgRC(rc, ("Finishing BIOS SCSI request failed rc=%Rrc\n", rc));
2043
lsilogicFreeGCSenseBuffer(pLsiLogic, pTaskState);
2045
RTGCPHYS GCPhysAddrSenseBuffer;
2047
GCPhysAddrSenseBuffer = pTaskState->GuestRequest.SCSIIO.u32SenseBufferLowAddress;
2048
GCPhysAddrSenseBuffer |= ((uint64_t)pLsiLogic->u32SenseBufferHighAddr << 32);
2050
/* Copy the sense buffer over. */
2051
PDMDevHlpPhysWrite(pLsiLogic->CTX_SUFF(pDevIns), GCPhysAddrSenseBuffer, pTaskState->abSenseBuffer,
2052
RT_UNLIKELY(pTaskState->GuestRequest.SCSIIO.u8SenseBufferLength < pTaskState->PDMScsiRequest.cbSenseBuffer)
2053
? pTaskState->GuestRequest.SCSIIO.u8SenseBufferLength
2054
: pTaskState->PDMScsiRequest.cbSenseBuffer);
2056
lsilogicScatterGatherListDestroy(pLsiLogic, pTaskState);
2059
if (RT_LIKELY(rcCompletion == SCSI_STATUS_OK))
2060
lsilogicFinishContextReply(pLsiLogic, pTaskState->GuestRequest.SCSIIO.u32MessageContext);
2063
/* The SCSI target encountered an error during processing post a reply. */
2064
memset(&pTaskState->IOCReply, 0, sizeof(MptReplyUnion));
2065
pTaskState->IOCReply.SCSIIOError.u8TargetID = pTaskState->GuestRequest.SCSIIO.u8TargetID;
2066
pTaskState->IOCReply.SCSIIOError.u8Bus = pTaskState->GuestRequest.SCSIIO.u8Bus;
2067
pTaskState->IOCReply.SCSIIOError.u8MessageLength = 8;
2068
pTaskState->IOCReply.SCSIIOError.u8Function = pTaskState->GuestRequest.SCSIIO.u8Function;
2069
pTaskState->IOCReply.SCSIIOError.u8CDBLength = pTaskState->GuestRequest.SCSIIO.u8CDBLength;
2070
pTaskState->IOCReply.SCSIIOError.u8SenseBufferLength = pTaskState->GuestRequest.SCSIIO.u8SenseBufferLength;
2071
pTaskState->IOCReply.SCSIIOError.u8MessageFlags = pTaskState->GuestRequest.SCSIIO.u8MessageFlags;
2072
pTaskState->IOCReply.SCSIIOError.u32MessageContext = pTaskState->GuestRequest.SCSIIO.u32MessageContext;
2073
pTaskState->IOCReply.SCSIIOError.u8SCSIStatus = rcCompletion;
2074
pTaskState->IOCReply.SCSIIOError.u8SCSIState = MPT_SCSI_IO_ERROR_SCSI_STATE_AUTOSENSE_VALID;
2075
pTaskState->IOCReply.SCSIIOError.u16IOCStatus = 0;
2076
pTaskState->IOCReply.SCSIIOError.u32IOCLogInfo = 0;
2077
pTaskState->IOCReply.SCSIIOError.u32TransferCount = 0;
2078
pTaskState->IOCReply.SCSIIOError.u32SenseCount = sizeof(pTaskState->abSenseBuffer);
2079
pTaskState->IOCReply.SCSIIOError.u32ResponseInfo = 0;
2081
lsilogicFinishAddressReply(pLsiLogic, &pTaskState->IOCReply, true);
2085
RTMemCacheFree(pLsiLogic->hTaskCache, pTaskState);
2087
2177
if (pLsiLogicDevice->cOutstandingRequests == 0 && pLsiLogic->fSignalIdle)
2088
2178
PDMDevHlpAsyncNotificationCompleted(pLsiLogic->pDevInsR3);
2090
2180
return VINF_SUCCESS;
2183
static DECLCALLBACK(int) lsilogicQueryDeviceLocation(PPDMISCSIPORT pInterface, const char **ppcszController,
2184
uint32_t *piInstance, uint32_t *piLUN)
2186
PLSILOGICDEVICE pLsiLogicDevice = PDMISCSIPORT_2_PLSILOGICDEVICE(pInterface);
2187
PPDMDEVINS pDevIns = pLsiLogicDevice->CTX_SUFF(pLsiLogic)->CTX_SUFF(pDevIns);
2189
AssertPtrReturn(ppcszController, VERR_INVALID_POINTER);
2190
AssertPtrReturn(piInstance, VERR_INVALID_POINTER);
2191
AssertPtrReturn(piLUN, VERR_INVALID_POINTER);
2193
*ppcszController = pDevIns->pReg->szName;
2194
*piInstance = pDevIns->iInstance;
2195
*piLUN = pLsiLogicDevice->iLUN;
2197
return VINF_SUCCESS;
2094
2201
* Return the configuration page header and data
2095
2202
* which matches the given page type and number.
3274
3381
MptConfigurationPageManufacturing5, 5,
3275
3382
MPT_CONFIGURATION_PAGE_ATTRIBUTE_PERSISTENT_READONLY);
3277
/* Manufacturing Page 6 - Product sepcific settings. */
3384
/* Manufacturing Page 6 - Product specific settings. */
3278
3385
MPT_CONFIG_PAGE_HEADER_INIT_MANUFACTURING(&pPages->ManufacturingPage6,
3279
3386
MptConfigurationPageManufacturing6, 6,
3280
3387
MPT_CONFIGURATION_PAGE_ATTRIBUTE_CHANGEABLE);
3282
/* Manufacturing Page 8 - Product sepcific settings. */
3389
/* Manufacturing Page 8 - Product specific settings. */
3283
3390
MPT_CONFIG_PAGE_HEADER_INIT_MANUFACTURING(&pPages->ManufacturingPage8,
3284
3391
MptConfigurationPageManufacturing8, 8,
3285
3392
MPT_CONFIGURATION_PAGE_ATTRIBUTE_CHANGEABLE);
3287
/* Manufacturing Page 9 - Product sepcific settings. */
3394
/* Manufacturing Page 9 - Product specific settings. */
3288
3395
MPT_CONFIG_PAGE_HEADER_INIT_MANUFACTURING(&pPages->ManufacturingPage9,
3289
3396
MptConfigurationPageManufacturing9, 9,
3290
3397
MPT_CONFIGURATION_PAGE_ATTRIBUTE_CHANGEABLE);
3292
/* Manufacturing Page 10 - Product sepcific settings. */
3399
/* Manufacturing Page 10 - Product specific settings. */
3293
3400
MPT_CONFIG_PAGE_HEADER_INIT_MANUFACTURING(&pPages->ManufacturingPage10,
3294
3401
MptConfigurationPageManufacturing10, 10,
3295
3402
MPT_CONFIGURATION_PAGE_ATTRIBUTE_CHANGEABLE);
4549
4692
if (!lsilogicR3AllAsyncIOIsFinished(pDevIns))
4550
4693
PDMDevHlpSetAsyncNotification(pDevIns, lsilogicR3IsAsyncSuspendOrPowerOffDone);
4552
4696
ASMAtomicWriteBool(&pThis->fSignalIdle, false);
4698
AssertMsg(!pThis->fNotificationSend, ("The PDM Queue should be empty at this point\n"));
4703
* We have tasks which we need to redo. Put the message frame addresses
4704
* into the request queue (we save the requests).
4705
* Guest execution is suspended at this point so there is no race between us and
4706
* lsilogicRegisterWrite.
4708
PLSILOGICTASKSTATE pTaskState = pThis->pTasksRedoHead;
4710
pThis->pTasksRedoHead = NULL;
4714
PLSILOGICTASKSTATE pFree;
4716
if (!pTaskState->fBIOS)
4718
/* Write only the lower 32bit part of the address. */
4719
ASMAtomicWriteU32(&pThis->CTX_SUFF(pRequestQueueBase)[pThis->uRequestQueueNextEntryFreeWrite],
4720
pTaskState->GCPhysMessageFrameAddr & UINT32_C(0xffffffff));
4722
pThis->uRequestQueueNextEntryFreeWrite++;
4723
pThis->uRequestQueueNextEntryFreeWrite %= pThis->cRequestQueueEntries;
4725
pThis->fNotificationSend = true;
4729
AssertMsg(!pTaskState->pRedoNext, ("Only one BIOS task can be active!\n"));
4730
vboxscsiSetRequestRedo(&pThis->VBoxSCSI, &pTaskState->PDMScsiRequest);
4734
pTaskState = pTaskState->pRedoNext;
4736
RTMemCacheFree(pThis->hTaskCache, pFree);
4738
pThis->fRedo = false;
4993
5235
rc = vboxscsiInitialize(&pThis->VBoxSCSI);
4996
/* Register I/O port space in ISA region for BIOS access. */
4997
if (pThis->enmCtrlType == LSILOGICCTRLTYPE_SCSI_SPI)
4998
rc = PDMDevHlpIOPortRegister(pDevIns, LSILOGIC_ISA_IO_PORT, 3, NULL,
4999
lsilogicIsaIOPortWrite, lsilogicIsaIOPortRead,
5000
lsilogicIsaIOPortWriteStr, lsilogicIsaIOPortReadStr,
5002
else if (pThis->enmCtrlType == LSILOGICCTRLTYPE_SCSI_SAS)
5003
rc = PDMDevHlpIOPortRegister(pDevIns, LSILOGIC_SAS_ISA_IO_PORT, 3, NULL,
5004
lsilogicIsaIOPortWrite, lsilogicIsaIOPortRead,
5005
lsilogicIsaIOPortWriteStr, lsilogicIsaIOPortReadStr,
5006
"LsiLogic SAS BIOS");
5008
AssertMsgFailed(("Invalid controller type %d\n", pThis->enmCtrlType));
5239
* Register I/O port space in ISA region for BIOS access
5240
* if the controller is marked as bootable.
5244
if (pThis->enmCtrlType == LSILOGICCTRLTYPE_SCSI_SPI)
5245
rc = PDMDevHlpIOPortRegister(pDevIns, LSILOGIC_ISA_IO_PORT, 3, NULL,
5246
lsilogicIsaIOPortWrite, lsilogicIsaIOPortRead,
5247
lsilogicIsaIOPortWriteStr, lsilogicIsaIOPortReadStr,
5249
else if (pThis->enmCtrlType == LSILOGICCTRLTYPE_SCSI_SAS)
5250
rc = PDMDevHlpIOPortRegister(pDevIns, LSILOGIC_SAS_ISA_IO_PORT, 3, NULL,
5251
lsilogicIsaIOPortWrite, lsilogicIsaIOPortRead,
5252
lsilogicIsaIOPortWriteStr, lsilogicIsaIOPortReadStr,
5253
"LsiLogic SAS BIOS");
5255
AssertMsgFailed(("Invalid controller type %d\n", pThis->enmCtrlType));
5011
return PDMDEV_SET_ERROR(pDevIns, rc, N_("LsiLogic cannot register legacy I/O handlers"));
5258
return PDMDEV_SET_ERROR(pDevIns, rc, N_("LsiLogic cannot register legacy I/O handlers"));
5013
5261
/* Register save state handlers. */
5014
rc = PDMDevHlpSSMRegister3(pDevIns, LSILOGIC_SAVED_STATE_VERSION, sizeof(*pThis),
5015
lsilogicLiveExec, lsilogicSaveExec, lsilogicLoadExec);
5262
rc = PDMDevHlpSSMRegisterEx(pDevIns, LSILOGIC_SAVED_STATE_VERSION, sizeof(*pThis), NULL,
5263
NULL, lsilogicLiveExec, NULL,
5264
NULL, lsilogicSaveExec, NULL,
5265
NULL, lsilogicLoadExec, lsilogicLoadDone);
5016
5266
if (RT_FAILURE(rc))
5017
5267
return PDMDEV_SET_ERROR(pDevIns, rc, N_("LsiLogic cannot register save state handlers"));