9
* Copyright (C) 2006-2009 Oracle Corporation
9
* Copyright (C) 2006-2010 Oracle Corporation
11
11
* This file is part of VirtualBox Open Source Edition (OSE), as
12
12
* available from http://www.virtualbox.org. This file is free software;
308
308
rc = RTSemMutexRequest(pCtl->AsyncIORequestMutex, RT_INDEFINITE_WAIT);
310
LogRel(("ATA: Ctl: request queue dump (topmost is current):\n"));
310
LogRel(("AHCI ATA: Ctl: request queue dump (topmost is current):\n"));
311
311
curr = pCtl->AsyncIOReqTail;
314
314
if (curr == pCtl->AsyncIOReqHead)
315
LogRel(("ATA: Ctl: processed requests (topmost is oldest):\n"));
315
LogRel(("AHCI ATA: Ctl: processed requests (topmost is oldest):\n"));
316
316
switch (pCtl->aAsyncIORequests[curr].ReqType)
318
318
case AHCIATA_AIO_NEW:
965
static int ataReadSectors(AHCIATADevState *s, uint64_t u64Sector, void *pvBuf, uint32_t cSectors)
965
static void ataWarningDiskFull(PPDMDEVINS pDevIns)
968
LogRel(("AHCI ATA: Host disk full\n"));
969
rc = PDMDevHlpVMSetRuntimeError(pDevIns, VMSETRTERR_FLAGS_SUSPEND | VMSETRTERR_FLAGS_NO_WAIT, "DevATA_DISKFULL",
970
N_("Host system reported disk full. VM execution is suspended. You can resume after freeing some space"));
974
static void ataWarningFileTooBig(PPDMDEVINS pDevIns)
977
LogRel(("AHCI ATA: File too big\n"));
978
rc = PDMDevHlpVMSetRuntimeError(pDevIns, VMSETRTERR_FLAGS_SUSPEND | VMSETRTERR_FLAGS_NO_WAIT, "DevATA_FILETOOBIG",
979
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"));
983
static void ataWarningISCSI(PPDMDEVINS pDevIns)
986
LogRel(("AHCI ATA: iSCSI target unavailable\n"));
987
rc = PDMDevHlpVMSetRuntimeError(pDevIns, VMSETRTERR_FLAGS_SUSPEND | VMSETRTERR_FLAGS_NO_WAIT, "DevATA_ISCSIDOWN",
988
N_("The iSCSI target has stopped responding. VM execution is suspended. You can resume when it is available again"));
992
static bool ataIsRedoSetWarning(AHCIATADevState *s, int rc)
994
PAHCIATACONTROLLER pCtl = ATADEVSTATE_2_CONTROLLER(s);
995
Assert(!PDMCritSectIsOwner(&pCtl->lock));
996
if (rc == VERR_DISK_FULL)
998
pCtl->fRedoIdle = true;
999
ataWarningDiskFull(ATADEVSTATE_2_DEVINS(s));
1002
if (rc == VERR_FILE_TOO_BIG)
1004
pCtl->fRedoIdle = true;
1005
ataWarningFileTooBig(ATADEVSTATE_2_DEVINS(s));
1008
if (rc == VERR_BROKEN_PIPE || rc == VERR_NET_CONNECTION_REFUSED)
1010
pCtl->fRedoIdle = true;
1011
/* iSCSI connection abort (first error) or failure to reestablish
1012
* connection (second error). Pause VM. On resume we'll retry. */
1013
ataWarningISCSI(ATADEVSTATE_2_DEVINS(s));
1020
static int ataReadSectors(AHCIATADevState *s, uint64_t u64Sector, void *pvBuf,
1021
uint32_t cSectors, bool *pfRedo)
967
1023
PAHCIATACONTROLLER pCtl = ATADEVSTATE_2_CONTROLLER(s);
978
1034
STAM_REL_COUNTER_ADD(s->pStatBytesRead, cSectors * 512);
1039
*pfRedo = ataIsRedoSetWarning(s, rc);
980
1041
STAM_PROFILE_START(&pCtl->StatLockWait, a);
981
1042
PDMCritSectEnter(&pCtl->lock, VINF_SUCCESS);
982
1043
STAM_PROFILE_STOP(&pCtl->StatLockWait, a);
987
static int ataWriteSectors(AHCIATADevState *s, uint64_t u64Sector, const void *pvBuf, uint32_t cSectors)
1048
static int ataWriteSectors(AHCIATADevState *s, uint64_t u64Sector,
1049
const void *pvBuf, uint32_t cSectors, bool *pfRedo)
989
1051
PAHCIATACONTROLLER pCtl = ATADEVSTATE_2_CONTROLLER(s);
1000
1062
STAM_REL_COUNTER_ADD(s->pStatBytesWritten, cSectors * 512);
1067
*pfRedo = ataIsRedoSetWarning(s, rc);
1002
1069
STAM_PROFILE_START(&pCtl->StatLockWait, a);
1003
1070
PDMCritSectEnter(&pCtl->lock, VINF_SUCCESS);
1004
1071
STAM_PROFILE_STOP(&pCtl->StatLockWait, a);
1023
static void ataWarningDiskFull(PPDMDEVINS pDevIns)
1026
LogRel(("ATA: Host disk full\n"));
1027
rc = PDMDevHlpVMSetRuntimeError(pDevIns, 0 /*fFlags*/, "DevATA_DISKFULL",
1028
N_("Host system reported disk full. VM execution is suspended. You can resume after freeing some space"));
1033
static void ataWarningFileTooBig(PPDMDEVINS pDevIns)
1036
LogRel(("ATA: File too big\n"));
1037
rc = PDMDevHlpVMSetRuntimeError(pDevIns, 0 /*fFlags*/, "DevATA_FILETOOBIG",
1038
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"));
1043
static void ataWarningISCSI(PPDMDEVINS pDevIns)
1046
LogRel(("ATA: iSCSI target unavailable\n"));
1047
rc = PDMDevHlpVMSetRuntimeError(pDevIns, 0 /*fFlags*/, "DevATA_ISCSIDOWN",
1048
N_("The iSCSI target has stopped responding. VM execution is suspended. You can resume when it is available again"));
1053
1090
static bool ataReadSectorsSS(AHCIATADevState *s)
1056
1093
uint32_t cSectors;
1059
1097
cSectors = s->cbElementaryTransfer / 512;
1060
1098
Assert(cSectors);
1061
1099
iLBA = ataGetSector(s);
1062
1100
Log(("%s: %d sectors at LBA %d\n", __FUNCTION__, cSectors, iLBA));
1063
rc = ataReadSectors(s, iLBA, s->CTXALLSUFF(pbIOBuffer), cSectors);
1101
rc = ataReadSectors(s, iLBA, s->CTXALLSUFF(pbIOBuffer), cSectors, &fRedo);
1064
1102
if (RT_SUCCESS(rc))
1066
1104
ataSetSector(s, iLBA + cSectors);
1073
if (rc == VERR_DISK_FULL)
1075
ataWarningDiskFull(ATADEVSTATE_2_DEVINS(s));
1078
if (rc == VERR_FILE_TOO_BIG)
1080
ataWarningFileTooBig(ATADEVSTATE_2_DEVINS(s));
1083
if (rc == VERR_BROKEN_PIPE || rc == VERR_NET_CONNECTION_REFUSED)
1085
/* iSCSI connection abort (first error) or failure to reestablish
1086
* connection (second error). Pause VM. On resume we'll retry. */
1087
ataWarningISCSI(ATADEVSTATE_2_DEVINS(s));
1090
1113
if (s->cErrors++ < MAX_LOG_REL_ERRORS)
1091
1114
LogRel(("AHCI ATA: LUN#%d: disk read error (rc=%Rrc iSector=%#RX64 cSectors=%#RX32)\n",
1092
1115
s->iLUN, rc, iLBA, cSectors));
1093
1116
ataCmdError(s, ID_ERR);
1095
/** @todo implement redo for iSCSI */
1103
1125
uint32_t cSectors;
1106
1129
cSectors = s->cbElementaryTransfer / 512;
1107
1130
Assert(cSectors);
1108
1131
iLBA = ataGetSector(s);
1109
1132
Log(("%s: %d sectors at LBA %d\n", __FUNCTION__, cSectors, iLBA));
1110
rc = ataWriteSectors(s, iLBA, s->CTXALLSUFF(pbIOBuffer), cSectors);
1133
rc = ataWriteSectors(s, iLBA, s->CTXALLSUFF(pbIOBuffer), cSectors, &fRedo);
1111
1134
if (RT_SUCCESS(rc))
1113
1136
ataSetSector(s, iLBA + cSectors);
1120
if (rc == VERR_DISK_FULL)
1122
ataWarningDiskFull(ATADEVSTATE_2_DEVINS(s));
1125
if (rc == VERR_FILE_TOO_BIG)
1127
ataWarningFileTooBig(ATADEVSTATE_2_DEVINS(s));
1130
if (rc == VERR_BROKEN_PIPE || rc == VERR_NET_CONNECTION_REFUSED)
1132
/* iSCSI connection abort (first error) or failure to reestablish
1133
* connection (second error). Pause VM. On resume we'll retry. */
1134
ataWarningISCSI(ATADEVSTATE_2_DEVINS(s));
1137
1145
if (s->cErrors++ < MAX_LOG_REL_ERRORS)
1138
1146
LogRel(("AHCI ATA: LUN#%d: disk write error (rc=%Rrc iSector=%#RX64 cSectors=%#RX32)\n",
1139
1147
s->iLUN, rc, iLBA, cSectors));
1140
1148
ataCmdError(s, ID_ERR);
1142
/** @todo implement redo for iSCSI */
2766
2773
if (!pIf->pDrvBlock)
2769
LogRel(("ATA: LUN#%d: CD/DVD, total number of sectors %Ld, passthrough unchanged\n", pIf->iLUN, pIf->cTotalSectors));
2776
LogRel(("AHCI ATA: LUN#%d: CD/DVD, total number of sectors %Ld, passthrough unchanged\n", pIf->iLUN, pIf->cTotalSectors));
2771
2778
if (pIf->fATAPI)
2772
2779
pIf->cTotalSectors = pIf->pDrvBlock->pfnGetSize(pIf->pDrvBlock) / 2048;
3404
3411
uCmdWait0 = (uNow - pCtl->aIfs[0].u64CmdTS) / 1000;
3405
3412
if (pCtl->aIfs[1].u64CmdTS)
3406
3413
uCmdWait1 = (uNow - pCtl->aIfs[1].u64CmdTS) / 1000;
3407
LogRel(("ATA: Ctl: RESET, DevSel=%d AIOIf=%d CmdIf0=%#04x (%d usec ago) CmdIf1=%#04x (%d usec ago)\n",
3414
LogRel(("AHCI ATA: Ctl: RESET, DevSel=%d AIOIf=%d CmdIf0=%#04x (%d usec ago) CmdIf1=%#04x (%d usec ago)\n",
3408
3415
pCtl->iSelectedIf, pCtl->iAIOIf,
3409
3416
pCtl->aIfs[0].uATARegCommand, uCmdWait0,
3410
3417
pCtl->aIfs[1].uATARegCommand, uCmdWait1));
3823
3830
if (!(pCtl->BmDma.u8Cmd & BM_CMD_START) || pCtl->fReset)
3825
LogRel(("ATA: Ctl: ABORT DMA%s\n", pCtl->fReset ? " due to RESET" : ""));
3832
LogRel(("AHCI ATA: Ctl: ABORT DMA%s\n", pCtl->fReset ? " due to RESET" : ""));
3826
3833
if (!pCtl->fReset)
3827
3834
ataDMATransferStop(s);
3828
3835
/* This forces the loop to exit immediately. */
3854
* Suspend I/O operations on a controller. Also suspends EMT, because it's
3855
* waiting for I/O to make progress. The next attempt to perform an I/O
3856
* operation will be made when EMT is resumed up again (as the resume
3857
* callback below restarts I/O).
3859
* @param pCtl Controller for which to suspend I/O.
3861
static void ataSuspendRedo(PAHCIATACONTROLLER pCtl)
3863
PPDMDEVINS pDevIns = CONTROLLER_2_DEVINS(pCtl);
3866
pCtl->fRedoIdle = true;
3867
rc = VMR3ReqCallWait(PDMDevHlpGetVM(pDevIns), VMCPUID_ANY,
3868
(PFNRT)PDMDevHlpVMSuspend, 1, pDevIns);
3869
AssertReleaseRC(rc);
3874
3861
* Signal ataWaitForAsyncIOIsIdle that we're idle (if we actually are).
3876
3863
* @param pCtl The controller.
4035
4022
* request. Occurs very rarely, not worth optimizing. */
4036
4023
LogRel(("%s: Ctl: redo entire operation\n", __FUNCTION__));
4037
4024
ataAsyncIOPutRequest(pCtl, pReq);
4038
ataSuspendRedo(pCtl);
4139
4125
if (RT_UNLIKELY(pCtl->fRedo))
4141
LogRel(("ATA: Ctl: redo DMA operation\n"));
4127
LogRel(("AHCI ATA: Ctl: redo DMA operation\n"));
4142
4128
ataAsyncIOPutRequest(pCtl, &ataDMARequest);
4143
ataSuspendRedo(pCtl);
4257
4241
case AHCIATA_AIO_RESET_CLEARED:
4258
4242
pCtl->uAsyncIOState = AHCIATA_AIO_NEW;
4259
4243
pCtl->fReset = false;
4260
LogRel(("ATA: Ctl: finished processing RESET\n"));
4244
LogRel(("AHCI ATA: Ctl: finished processing RESET\n"));
4261
4245
for (uint32_t i = 0; i < RT_ELEMENTS(pCtl->aIfs); i++)
4263
4247
if (pCtl->aIfs[i].fATAPI)
4870
LogRel(("ATA: Ctl is still executing, DevSel=%d AIOIf=%d CmdIf0=%#04x CmdIf1=%#04x\n",
4854
LogRel(("AHCI ATA: Ctl is still executing, DevSel=%d AIOIf=%d CmdIf0=%#04x CmdIf1=%#04x\n",
4871
4855
pCtl->iSelectedIf, pCtl->iAIOIf,
4872
4856
pCtl->aIfs[0].uATARegCommand, pCtl->aIfs[1].uATARegCommand));
4921
4905
ASMAtomicWriteU32(&pCtl->fShutdown, true);
4922
4906
rc = RTSemEventSignal(pCtl->AsyncIOSem);
4908
rc = RTSemEventSignal(pCtl->SuspendIOSem);
4925
4911
rc = RTThreadWait(pCtl->AsyncIOThread, 30000 /* 30 s*/, NULL);
4926
4912
if (RT_SUCCESS(rc))
5082
5068
pIf->PCHSGeometry.cCylinders = 0; /* dummy */
5083
5069
pIf->PCHSGeometry.cHeads = 0; /* dummy */
5084
5070
pIf->PCHSGeometry.cSectors = 0; /* dummy */
5085
LogRel(("ATA: LUN#%d: CD/DVD, total number of sectors %Ld, passthrough %s\n", pIf->iLUN, pIf->cTotalSectors, (pIf->fATAPIPassthrough ? "enabled" : "disabled")));
5071
LogRel(("AHCI ATA: LUN#%d: CD/DVD, total number of sectors %Ld, passthrough %s\n", pIf->iLUN, pIf->cTotalSectors, (pIf->fATAPIPassthrough ? "enabled" : "disabled")));
5402
5388
SSMR3GetMem(pSSM, pCtl->aIfs[j].CTX_SUFF(pbIOBuffer), pCtl->aIfs[j].cbIOBuffer);
5405
LogRel(("ATA: No buffer for %d\n", j));
5391
LogRel(("AHCI ATA: No buffer for %d\n", j));
5406
5392
if (SSMR3HandleGetAfter(pSSM) != SSMAFTER_DEBUG_IT)
5407
5393
return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("No buffer for %d"), j);