~ubuntu-branches/ubuntu/natty/virtualbox-ose/natty-updates

« back to all changes in this revision

Viewing changes to src/VBox/Devices/Storage/ATAController.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Felix Geyer
  • Date: 2010-10-15 02:12:28 UTC
  • mfrom: (0.3.10 upstream) (0.4.19 sid)
  • Revision ID: james.westby@ubuntu.com-20101015021228-5e6vbxgtes8mg189
Tags: 3.2.10-dfsg-1ubuntu1
* Merge from Debian unstable, remaining changes:
  - VirtualBox should go in Accessories, not in System tools.
    - debian/virtualbox-ose-qt.files/virtualbox-ose.desktop
  - Add Apport hook.
    - debian/virtualbox-ose.files/source_virtualbox-ose.py
    - debian/virtualbox-ose.install
  - Drop *-source packages.
* Add ubuntu-01-fix-build-gcc45.patch to fix FTBFS due to uninitalized
  variables. Thanks to Lubomir Rintel <lkundrak@v3.sk> for the patch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
6
6
 */
7
7
 
8
8
/*
9
 
 * Copyright (C) 2006-2009 Oracle Corporation
 
9
 * Copyright (C) 2006-2010 Oracle Corporation
10
10
 *
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;
307
307
 
308
308
    rc = RTSemMutexRequest(pCtl->AsyncIORequestMutex, RT_INDEFINITE_WAIT);
309
309
    AssertRC(rc);
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;
312
312
    do
313
313
    {
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)
317
317
        {
318
318
            case AHCIATA_AIO_NEW:
962
962
}
963
963
 
964
964
 
965
 
static int ataReadSectors(AHCIATADevState *s, uint64_t u64Sector, void *pvBuf, uint32_t cSectors)
 
965
static void ataWarningDiskFull(PPDMDEVINS pDevIns)
 
966
{
 
967
    int rc;
 
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"));
 
971
    AssertRC(rc);
 
972
}
 
973
 
 
974
static void ataWarningFileTooBig(PPDMDEVINS pDevIns)
 
975
{
 
976
    int rc;
 
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"));
 
980
    AssertRC(rc);
 
981
}
 
982
 
 
983
static void ataWarningISCSI(PPDMDEVINS pDevIns)
 
984
{
 
985
    int rc;
 
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"));
 
989
    AssertRC(rc);
 
990
}
 
991
 
 
992
static bool ataIsRedoSetWarning(AHCIATADevState *s, int rc)
 
993
{
 
994
    PAHCIATACONTROLLER pCtl = ATADEVSTATE_2_CONTROLLER(s);
 
995
    Assert(!PDMCritSectIsOwner(&pCtl->lock));
 
996
    if (rc == VERR_DISK_FULL)
 
997
    {
 
998
        pCtl->fRedoIdle = true;
 
999
        ataWarningDiskFull(ATADEVSTATE_2_DEVINS(s));
 
1000
        return true;
 
1001
    }
 
1002
    if (rc == VERR_FILE_TOO_BIG)
 
1003
    {
 
1004
        pCtl->fRedoIdle = true;
 
1005
        ataWarningFileTooBig(ATADEVSTATE_2_DEVINS(s));
 
1006
        return true;
 
1007
    }
 
1008
    if (rc == VERR_BROKEN_PIPE || rc == VERR_NET_CONNECTION_REFUSED)
 
1009
    {
 
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));
 
1014
        return true;
 
1015
    }
 
1016
    return false;
 
1017
}
 
1018
 
 
1019
 
 
1020
static int ataReadSectors(AHCIATADevState *s, uint64_t u64Sector, void *pvBuf,
 
1021
                          uint32_t cSectors, bool *pfRedo)
966
1022
{
967
1023
    PAHCIATACONTROLLER pCtl = ATADEVSTATE_2_CONTROLLER(s);
968
1024
    int rc;
977
1033
 
978
1034
    STAM_REL_COUNTER_ADD(s->pStatBytesRead, cSectors * 512);
979
1035
 
 
1036
    if (RT_SUCCESS(rc))
 
1037
        *pfRedo = false;
 
1038
    else
 
1039
        *pfRedo = ataIsRedoSetWarning(s, rc);
 
1040
 
980
1041
    STAM_PROFILE_START(&pCtl->StatLockWait, a);
981
1042
    PDMCritSectEnter(&pCtl->lock, VINF_SUCCESS);
982
1043
    STAM_PROFILE_STOP(&pCtl->StatLockWait, a);
984
1045
}
985
1046
 
986
1047
 
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)
988
1050
{
989
1051
    PAHCIATACONTROLLER pCtl = ATADEVSTATE_2_CONTROLLER(s);
990
1052
    int rc;
999
1061
 
1000
1062
    STAM_REL_COUNTER_ADD(s->pStatBytesWritten, cSectors * 512);
1001
1063
 
 
1064
    if (RT_SUCCESS(rc))
 
1065
        *pfRedo = false;
 
1066
    else
 
1067
        *pfRedo = ataIsRedoSetWarning(s, rc);
 
1068
 
1002
1069
    STAM_PROFILE_START(&pCtl->StatLockWait, a);
1003
1070
    PDMCritSectEnter(&pCtl->lock, VINF_SUCCESS);
1004
1071
    STAM_PROFILE_STOP(&pCtl->StatLockWait, a);
1020
1087
}
1021
1088
 
1022
1089
 
1023
 
static void ataWarningDiskFull(PPDMDEVINS pDevIns)
1024
 
{
1025
 
    int rc;
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"));
1029
 
    AssertRC(rc);
1030
 
}
1031
 
 
1032
 
 
1033
 
static void ataWarningFileTooBig(PPDMDEVINS pDevIns)
1034
 
{
1035
 
    int rc;
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"));
1039
 
    AssertRC(rc);
1040
 
}
1041
 
 
1042
 
 
1043
 
static void ataWarningISCSI(PPDMDEVINS pDevIns)
1044
 
{
1045
 
    int rc;
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"));
1049
 
    AssertRC(rc);
1050
 
}
1051
 
 
1052
 
 
1053
1090
static bool ataReadSectorsSS(AHCIATADevState *s)
1054
1091
{
1055
1092
    int rc;
1056
1093
    uint32_t cSectors;
1057
1094
    uint64_t iLBA;
 
1095
    bool fRedo;
1058
1096
 
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))
1065
1103
    {
1066
1104
        ataSetSector(s, iLBA + cSectors);
1070
1108
    }
1071
1109
    else
1072
1110
    {
1073
 
        if (rc == VERR_DISK_FULL)
1074
 
        {
1075
 
            ataWarningDiskFull(ATADEVSTATE_2_DEVINS(s));
1076
 
            return true;
1077
 
        }
1078
 
        if (rc == VERR_FILE_TOO_BIG)
1079
 
        {
1080
 
            ataWarningFileTooBig(ATADEVSTATE_2_DEVINS(s));
1081
 
            return true;
1082
 
        }
1083
 
        if (rc == VERR_BROKEN_PIPE || rc == VERR_NET_CONNECTION_REFUSED)
1084
 
        {
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));
1088
 
            return true;
1089
 
        }
 
1111
        if (fRedo)
 
1112
            return true;
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);
1094
1117
    }
1095
 
    /** @todo implement redo for iSCSI */
1096
1118
    return false;
1097
1119
}
1098
1120
 
1102
1124
    int rc;
1103
1125
    uint32_t cSectors;
1104
1126
    uint64_t iLBA;
 
1127
    bool fRedo;
1105
1128
 
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))
1112
1135
    {
1113
1136
        ataSetSector(s, iLBA + cSectors);
1117
1140
    }
1118
1141
    else
1119
1142
    {
1120
 
        if (rc == VERR_DISK_FULL)
1121
 
        {
1122
 
            ataWarningDiskFull(ATADEVSTATE_2_DEVINS(s));
1123
 
            return true;
1124
 
        }
1125
 
        if (rc == VERR_FILE_TOO_BIG)
1126
 
        {
1127
 
            ataWarningFileTooBig(ATADEVSTATE_2_DEVINS(s));
1128
 
            return true;
1129
 
        }
1130
 
        if (rc == VERR_BROKEN_PIPE || rc == VERR_NET_CONNECTION_REFUSED)
1131
 
        {
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));
1135
 
            return true;
1136
 
        }
 
1143
        if (fRedo)
 
1144
            return true;
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);
1141
1149
    }
1142
 
    /** @todo implement redo for iSCSI */
1143
1150
    return false;
1144
1151
}
1145
1152
 
2766
2773
    if (!pIf->pDrvBlock)
2767
2774
        return;
2768
2775
 
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));
2770
2777
 
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));
3822
3829
 
3823
3830
        if (!(pCtl->BmDma.u8Cmd & BM_CMD_START) || pCtl->fReset)
3824
3831
        {
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. */
3851
3858
 
3852
3859
 
3853
3860
/**
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).
3858
 
 *
3859
 
 * @param pCtl      Controller for which to suspend I/O.
3860
 
 */
3861
 
static void ataSuspendRedo(PAHCIATACONTROLLER pCtl)
3862
 
{
3863
 
    PPDMDEVINS  pDevIns = CONTROLLER_2_DEVINS(pCtl);
3864
 
    int         rc;
3865
 
 
3866
 
    pCtl->fRedoIdle = true;
3867
 
    rc = VMR3ReqCallWait(PDMDevHlpGetVM(pDevIns), VMCPUID_ANY,
3868
 
                         (PFNRT)PDMDevHlpVMSuspend, 1, pDevIns);
3869
 
    AssertReleaseRC(rc);
3870
 
}
3871
 
 
3872
 
 
3873
 
/**
3874
3861
 * Signal ataWaitForAsyncIOIsIdle that we're idle (if we actually are).
3875
3862
 *
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);
4039
4025
                            break;
4040
4026
                        }
4041
4027
                    }
4138
4124
 
4139
4125
                if (RT_UNLIKELY(pCtl->fRedo))
4140
4126
                {
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);
4144
4129
                    break;
4145
4130
                }
4146
4131
 
4184
4169
                    pCtl->fRedo = fRedo;
4185
4170
                    if (RT_UNLIKELY(fRedo))
4186
4171
                    {
4187
 
                        LogRel(("ATA: Ctl#%d: redo PIO operation\n"));
 
4172
                        LogRel(("AHCI ATA: Ctl: redo PIO operation\n"));
4188
4173
                        ataAsyncIOPutRequest(pCtl, &ataPIORequest);
4189
 
                        ataSuspendRedo(pCtl);
4190
4174
                        break;
4191
4175
                    }
4192
4176
                    s->iIOBufferCur = 0;
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++)
4262
4246
                {
4263
4247
                    if (pCtl->aIfs[i].fATAPI)
4867
4851
    }
4868
4852
 
4869
4853
    if (!fAllIdle)
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));
4873
4857
 
4921
4905
        ASMAtomicWriteU32(&pCtl->fShutdown, true);
4922
4906
        rc = RTSemEventSignal(pCtl->AsyncIOSem);
4923
4907
        AssertRC(rc);
 
4908
        rc = RTSemEventSignal(pCtl->SuspendIOSem);
 
4909
        AssertRC(rc);
4924
4910
 
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")));
5086
5072
    }
5087
5073
    else
5088
5074
    {
5402
5388
                SSMR3GetMem(pSSM, pCtl->aIfs[j].CTX_SUFF(pbIOBuffer), pCtl->aIfs[j].cbIOBuffer);
5403
5389
            else
5404
5390
            {
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);
5408
5394