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

« back to all changes in this revision

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

  • Committer: Bazaar Package Importer
  • Author(s): Felix Geyer
  • Date: 2010-03-11 17:16:37 UTC
  • mfrom: (0.3.4 upstream) (0.4.8 sid)
  • Revision ID: james.westby@ubuntu.com-20100311171637-43z64ia3ccpj8vqn
Tags: 3.1.4-dfsg-2ubuntu1
* Merge from Debian unstable (LP: #528561), remaining changes:
  - VirtualBox should go in Accessories, not in System tools (LP: #288590)
    - debian/virtualbox-ose-qt.files/virtualbox-ose.desktop
  - Add Apport hook
    - debian/virtualbox-ose.files/source_virtualbox-ose.py
    - debian/virtualbox-ose.install
  - Add Launchpad integration
    - debian/control
    - debian/lpi-bug.xpm
    - debian/patches/u02-lp-integration.dpatch
  - Replace *-source packages with transitional packages for *-dkms
* Fix crash in vboxvideo_drm with kernel 2.6.33 / backported drm code
  (LP: #535297)
* Add a list of linux-headers packages to the apport hook
* Update debian/patches/u02-lp-integration.dpatch with a
  DEP-3 compliant header
* Add ${misc:Depends} to virtualbox-ose-source and virtualbox-ose-guest-source
  Depends

Show diffs side-by-side

added added

removed removed

Lines of Context:
727
727
    Mailbox             MailboxGuest;
728
728
    /** The SCSI request we pass to the underlying SCSI engine. */
729
729
    PDMSCSIREQUEST      PDMScsiRequest;
730
 
    /** Number of bytes in all scatter gather entries. */
731
 
    uint32_t            cbScatterGather;
732
 
    /** Number of entries in the scatter gather list. */
733
 
    uint32_t            cScatterGather;
734
 
    /** Page map lock array. */
735
 
    PPGMPAGEMAPLOCK     paPageLock;
736
 
    /** Pointer to the scatter gather array. */
737
 
    PPDMDATASEG         paScatterGather;
738
 
    /** Pointer to the page map lock for the sense buffer. */
739
 
    PGMPAGEMAPLOCK      pPageLockSense;
 
730
    /** Data buffer segment */
 
731
    PDMDATASEG          DataSeg;
740
732
    /** Pointer to the R3 sense buffer. */
741
 
    uint8_t            *pu8SenseBuffer;
 
733
    uint8_t            *pbSenseBuffer;
742
734
    /** Flag whether this is a request from the BIOS. */
743
735
    bool                fBIOS;
744
736
} BUSLOGICTASKSTATE, *PBUSLOGICTASKSTATE;
989
981
#endif
990
982
 
991
983
/**
992
 
 * Maps the data buffer into R3.
 
984
 * Allocate data buffer.
993
985
 *
994
986
 * @returns VBox status code.
995
987
 * @param   pTaskState    Pointer to the task state.
996
 
 * @param   fReadonly     Flag whether the mappings should be readonly.
997
988
 */
998
 
static int buslogicMapGCDataBufIntoR3(PBUSLOGICTASKSTATE pTaskState, bool fReadonly)
 
989
static int buslogicDataBufferAlloc(PBUSLOGICTASKSTATE pTaskState)
999
990
{
1000
 
    int rc = VINF_SUCCESS;
1001
 
    uint32_t cScatterGatherEntriesR3 = 0;
1002
991
    PPDMDEVINS pDevIns = pTaskState->CTX_SUFF(pTargetDevice)->CTX_SUFF(pBusLogic)->CTX_SUFF(pDevIns);
1003
992
 
1004
 
    /*
1005
 
     * @todo: Check following assumption and what residual means.
1006
 
     *
1007
 
     * The BusLogic adapter can handle two different data buffer formats.
1008
 
     * The first one is that the data pointer entry in the CCB points to
1009
 
     * the buffer directly. In second mode the data pointer points to a
1010
 
     * scatter gather list which describes the buffer.
1011
 
     */
1012
 
    if (   (pTaskState->CommandControlBlockGuest.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB_SCATTER_GATHER)
1013
 
        || (pTaskState->CommandControlBlockGuest.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB_RESIDUAL_SCATTER_GATHER))
 
993
    if (   (pTaskState->CommandControlBlockGuest.uDataDirection != BUSLOGIC_CCB_DIRECTION_NO_DATA)
 
994
        && (pTaskState->CommandControlBlockGuest.cbData > 0))
1014
995
    {
1015
 
        uint32_t cScatterGatherGCRead;
1016
 
        uint32_t iScatterGatherEntry;
1017
 
        ScatterGatherEntry aScatterGatherReadGC[32]; /* Number of scatter gather list entries read from guest memory. */
1018
 
        uint32_t cScatterGatherGCLeft = pTaskState->CommandControlBlockGuest.cbData / sizeof(ScatterGatherEntry);
1019
 
        RTGCPHYS GCPhysAddrScatterGatherCurrent = (RTGCPHYS)pTaskState->CommandControlBlockGuest.u32PhysAddrData;
1020
 
 
1021
 
        /* First pass - count needed R3 scatter gather list entries. */
1022
 
        do
1023
 
        {
1024
 
            cScatterGatherGCRead =   (cScatterGatherGCLeft < RT_ELEMENTS(aScatterGatherReadGC))
1025
 
                                   ? cScatterGatherGCLeft
1026
 
                                   : RT_ELEMENTS(aScatterGatherReadGC);
1027
 
            cScatterGatherGCLeft -= cScatterGatherGCRead;
1028
 
 
1029
 
            /* Read the SG entries. */
1030
 
            PDMDevHlpPhysRead(pDevIns, GCPhysAddrScatterGatherCurrent, &aScatterGatherReadGC[0],
1031
 
                              cScatterGatherGCRead * sizeof(ScatterGatherEntry));
1032
 
 
1033
 
            for (iScatterGatherEntry = 0; iScatterGatherEntry < cScatterGatherGCRead; iScatterGatherEntry++)
1034
 
            {
1035
 
                RTGCPHYS    GCPhysAddrDataBase;
1036
 
                size_t      cbDataToTransfer;
1037
 
 
1038
 
                Log(("%s: iScatterGatherEntry=%u\n", __FUNCTION__, iScatterGatherEntry));
1039
 
 
1040
 
                GCPhysAddrDataBase = (RTGCPHYS)aScatterGatherReadGC[iScatterGatherEntry].u32PhysAddrSegmentBase;
1041
 
                cbDataToTransfer = aScatterGatherReadGC[iScatterGatherEntry].cbSegment;
1042
 
 
1043
 
                Log(("%s: GCPhysAddrDataBase=%RGp cbDataToTransfer=%u\n", __FUNCTION__, GCPhysAddrDataBase, cbDataToTransfer));
1044
 
 
1045
 
                /*
1046
 
                 * Check if the physical address is page aligned.
1047
 
                 */
1048
 
                if (GCPhysAddrDataBase & PAGE_OFFSET_MASK)
1049
 
                {
1050
 
                    RTGCPHYS    GCPhysAddrDataNextPage = PAGE_ADDRESS(GCPhysAddrDataBase) + PAGE_SIZE;
1051
 
                    uint32_t    u32GCPhysAddrDiff = GCPhysAddrDataNextPage - GCPhysAddrDataBase;
1052
 
 
1053
 
                    Log(("%s: Align page: GCPhysAddrDataBase=%RGp GCPhysAddrDataNextPage=%RGp\n",
1054
 
                         __FUNCTION__, GCPhysAddrDataBase, GCPhysAddrDataNextPage));
1055
 
 
1056
 
                    cScatterGatherEntriesR3++;
1057
 
                    /* Subtract size of the buffer in the actual page. */
1058
 
                    if (cbDataToTransfer < u32GCPhysAddrDiff)
1059
 
                        cbDataToTransfer = 0;
1060
 
                    else
1061
 
                        cbDataToTransfer -= u32GCPhysAddrDiff;
1062
 
                }
1063
 
 
1064
 
                /* The address is now page aligned. */
1065
 
                while (cbDataToTransfer)
1066
 
                {
1067
 
                    Log(("%s: GCPhysAddrDataBase=%RGp cbDataToTransfer=%u cScatterGatherEntriesR3=%u\n",
1068
 
                         __FUNCTION__, GCPhysAddrDataBase, cbDataToTransfer, cScatterGatherEntriesR3));
1069
 
 
1070
 
                    cScatterGatherEntriesR3++;
1071
 
 
1072
 
                    /* Check if this is the last page the buffer is in. */
1073
 
                    if (cbDataToTransfer < PAGE_SIZE)
1074
 
                        cbDataToTransfer = 0;
1075
 
                    else
1076
 
                        cbDataToTransfer -= PAGE_SIZE;
1077
 
                }
1078
 
            }
1079
 
 
1080
 
            /* Set address to the next entries to read. */
1081
 
            GCPhysAddrScatterGatherCurrent += cScatterGatherGCRead * sizeof(ScatterGatherEntry);
1082
 
        } while (cScatterGatherGCLeft);
1083
 
 
1084
 
        Log(("%s: cScatterGatherEntriesR3=%u\n", __FUNCTION__, cScatterGatherEntriesR3));
1085
 
 
1086
996
        /*
1087
 
         * Allocate page map lock and scatter gather array.
1088
 
         * @todo: Optimize with caching.
 
997
         * @todo: Check following assumption and what residual means.
 
998
         *
 
999
         * The BusLogic adapter can handle two different data buffer formats.
 
1000
         * The first one is that the data pointer entry in the CCB points to
 
1001
         * the buffer directly. In second mode the data pointer points to a
 
1002
         * scatter gather list which describes the buffer.
1089
1003
         */
1090
 
        AssertMsg(!pTaskState->paPageLock && !pTaskState->paScatterGather, ("paPageLock or/and paScatterGather are not NULL\n"));
1091
 
        pTaskState->cScatterGather = cScatterGatherEntriesR3;
1092
 
        pTaskState->cbScatterGather = 0;
1093
 
        pTaskState->paPageLock = (PPGMPAGEMAPLOCK)RTMemAllocZ(cScatterGatherEntriesR3 * sizeof(PGMPAGEMAPLOCK));
1094
 
        AssertMsgReturn(pTaskState->paPageLock, ("Allocating page lock array failed\n"), VERR_NO_MEMORY);
1095
 
        pTaskState->paScatterGather = (PPDMDATASEG)RTMemAllocZ(cScatterGatherEntriesR3 * sizeof(PDMDATASEG));
1096
 
        AssertMsgReturn(pTaskState->paScatterGather, ("Allocating page lock array failed\n"), VERR_NO_MEMORY);
1097
 
 
1098
 
        /* Second pass - map the elements into R3. **/
1099
 
        cScatterGatherGCLeft = pTaskState->CommandControlBlockGuest.cbData / sizeof(ScatterGatherEntry);
1100
 
        GCPhysAddrScatterGatherCurrent = (RTGCPHYS)pTaskState->CommandControlBlockGuest.u32PhysAddrData;
1101
 
        PPGMPAGEMAPLOCK    pPageLockCurrent = pTaskState->paPageLock;
1102
 
        PPDMDATASEG        pScatterGatherCurrent = pTaskState->paScatterGather;
1103
 
 
1104
 
        do
 
1004
        if (   (pTaskState->CommandControlBlockGuest.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB_SCATTER_GATHER)
 
1005
            || (pTaskState->CommandControlBlockGuest.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB_RESIDUAL_SCATTER_GATHER))
1105
1006
        {
1106
 
            cScatterGatherGCRead = (cScatterGatherGCLeft < RT_ELEMENTS(aScatterGatherReadGC)) ? cScatterGatherGCLeft : RT_ELEMENTS(aScatterGatherReadGC);
1107
 
            cScatterGatherGCLeft -= cScatterGatherGCRead;
1108
 
 
1109
 
            /* Read the SG entries. */
1110
 
            PDMDevHlpPhysRead(pDevIns, GCPhysAddrScatterGatherCurrent, &aScatterGatherReadGC[0], cScatterGatherGCRead * sizeof(ScatterGatherEntry));
1111
 
 
1112
 
            for (iScatterGatherEntry = 0; iScatterGatherEntry < cScatterGatherGCRead; iScatterGatherEntry++)
1113
 
            {
1114
 
                RTGCPHYS    GCPhysAddrDataBase;
1115
 
                uint32_t    cbDataToTransfer;
1116
 
 
1117
 
                GCPhysAddrDataBase = (RTGCPHYS)aScatterGatherReadGC[iScatterGatherEntry].u32PhysAddrSegmentBase;
1118
 
                cbDataToTransfer = aScatterGatherReadGC[iScatterGatherEntry].cbSegment;
1119
 
                pTaskState->cbScatterGather += cbDataToTransfer;
1120
 
 
1121
 
                /*
1122
 
                 * Check if the physical address is page aligned.
1123
 
                 */
1124
 
                if (GCPhysAddrDataBase & PAGE_OFFSET_MASK)
1125
 
                {
1126
 
                    RTGCPHYS    GCPhysAddrDataNextPage = PAGE_ADDRESS(GCPhysAddrDataBase) + PAGE_SIZE;
1127
 
                    uint32_t    u32GCPhysAddrDiff = GCPhysAddrDataNextPage - GCPhysAddrDataBase; /* Difference from the buffer start to the next page boundary. */
1128
 
 
1129
 
                    /* Check if the mapping ends at the page boundary and set segment size accordingly. */
1130
 
                    pScatterGatherCurrent->cbSeg = (cbDataToTransfer < u32GCPhysAddrDiff) ? cbDataToTransfer : u32GCPhysAddrDiff;
1131
 
 
1132
 
                    /* Create the mapping. */
1133
 
                    if (fReadonly)
1134
 
                        rc = PDMDevHlpPhysGCPhys2CCPtrReadOnly(pDevIns, PAGE_ADDRESS(GCPhysAddrDataBase), 0, (const void **)&pScatterGatherCurrent->pvSeg, pPageLockCurrent); /** @todo r=bird: PAGE_ADDRESS is the wrong macro here as well... */
1135
 
                    else
1136
 
                        rc = PDMDevHlpPhysGCPhys2CCPtr(pDevIns, PAGE_ADDRESS(GCPhysAddrDataBase), 0, &pScatterGatherCurrent->pvSeg, pPageLockCurrent);
1137
 
 
1138
 
                    if (RT_FAILURE(rc))
1139
 
                        AssertMsgFailed(("Creating mapping failed rc=%Rrc\n", rc));
1140
 
 
1141
 
                    /* Let pvBuf point to the start of the buffer in the page. */
1142
 
                    pScatterGatherCurrent->pvSeg = ((uint8_t *)pScatterGatherCurrent->pvSeg) + (GCPhysAddrDataBase - PAGE_ADDRESS(GCPhysAddrDataBase));
1143
 
 
1144
 
                    /* Subtract size of the buffer in the actual page. */
1145
 
                    cbDataToTransfer -= (uint32_t)pScatterGatherCurrent->cbSeg;
1146
 
                    pPageLockCurrent++;
1147
 
                    pScatterGatherCurrent++;
1148
 
                    /* Let physical address point to the next page in the buffer. */
1149
 
                    GCPhysAddrDataBase = GCPhysAddrDataNextPage;
1150
 
                }
1151
 
 
1152
 
                /* The address is now page aligned. */
1153
 
                while (cbDataToTransfer)
1154
 
                {
1155
 
                    /* Check if this is the last page the buffer is in. */
1156
 
                    if (cbDataToTransfer < PAGE_SIZE)
1157
 
                    {
1158
 
                        pScatterGatherCurrent->cbSeg = cbDataToTransfer;
1159
 
                        cbDataToTransfer = 0;
1160
 
                    }
1161
 
                    else
1162
 
                    {
1163
 
                        cbDataToTransfer -= PAGE_SIZE;
1164
 
                        pScatterGatherCurrent->cbSeg = PAGE_SIZE;
1165
 
                    }
1166
 
 
1167
 
                    /* Create the mapping. */
1168
 
                    if (fReadonly)
1169
 
                        rc = PDMDevHlpPhysGCPhys2CCPtrReadOnly(pDevIns, GCPhysAddrDataBase, 0, (const void **)&pScatterGatherCurrent->pvSeg, pPageLockCurrent);
1170
 
                    else
1171
 
                        rc = PDMDevHlpPhysGCPhys2CCPtr(pDevIns, GCPhysAddrDataBase, 0, &pScatterGatherCurrent->pvSeg, pPageLockCurrent);
1172
 
 
1173
 
                    if (RT_FAILURE(rc))
1174
 
                        AssertMsgFailed(("Creating mapping failed rc=%Rrc\n", rc));
1175
 
 
1176
 
                    /* Go to the next page. */
1177
 
                    GCPhysAddrDataBase += PAGE_SIZE;
1178
 
                    pPageLockCurrent++;
1179
 
                    pScatterGatherCurrent++;
1180
 
                }
 
1007
            uint32_t cScatterGatherGCRead;
 
1008
            uint32_t iScatterGatherEntry;
 
1009
            ScatterGatherEntry aScatterGatherReadGC[32]; /* Number of scatter gather list entries read from guest memory. */
 
1010
            uint32_t cScatterGatherGCLeft = pTaskState->CommandControlBlockGuest.cbData / sizeof(ScatterGatherEntry);
 
1011
            RTGCPHYS GCPhysAddrScatterGatherCurrent = (RTGCPHYS)pTaskState->CommandControlBlockGuest.u32PhysAddrData;
 
1012
            size_t cbDataToTransfer = 0;
 
1013
 
 
1014
            /* Count number of bytes to transfer. */
 
1015
            do
 
1016
            {
 
1017
                cScatterGatherGCRead =   (cScatterGatherGCLeft < RT_ELEMENTS(aScatterGatherReadGC))
 
1018
                                        ? cScatterGatherGCLeft
 
1019
                                        : RT_ELEMENTS(aScatterGatherReadGC);
 
1020
                cScatterGatherGCLeft -= cScatterGatherGCRead;
 
1021
 
 
1022
                /* Read the SG entries. */
 
1023
                PDMDevHlpPhysRead(pDevIns, GCPhysAddrScatterGatherCurrent, &aScatterGatherReadGC[0],
 
1024
                                    cScatterGatherGCRead * sizeof(ScatterGatherEntry));
 
1025
 
 
1026
                for (iScatterGatherEntry = 0; iScatterGatherEntry < cScatterGatherGCRead; iScatterGatherEntry++)
 
1027
                {
 
1028
                    RTGCPHYS    GCPhysAddrDataBase;
 
1029
 
 
1030
                    Log(("%s: iScatterGatherEntry=%u\n", __FUNCTION__, iScatterGatherEntry));
 
1031
 
 
1032
                    GCPhysAddrDataBase = (RTGCPHYS)aScatterGatherReadGC[iScatterGatherEntry].u32PhysAddrSegmentBase;
 
1033
                    cbDataToTransfer += aScatterGatherReadGC[iScatterGatherEntry].cbSegment;
 
1034
 
 
1035
                    Log(("%s: GCPhysAddrDataBase=%RGp cbDataToTransfer=%u\n",
 
1036
                         __FUNCTION__, GCPhysAddrDataBase,
 
1037
                         aScatterGatherReadGC[iScatterGatherEntry].cbSegment));
 
1038
                }
 
1039
 
 
1040
                /* Set address to the next entries to read. */
 
1041
                GCPhysAddrScatterGatherCurrent += cScatterGatherGCRead * sizeof(ScatterGatherEntry);
 
1042
            } while (cScatterGatherGCLeft > 0);
 
1043
 
 
1044
            Log((": cbDataToTransfer=%d\n", cbDataToTransfer));
 
1045
 
 
1046
            /* Allocate buffer */
 
1047
            pTaskState->DataSeg.cbSeg = cbDataToTransfer;
 
1048
            pTaskState->DataSeg.pvSeg = RTMemAlloc(pTaskState->DataSeg.cbSeg);
 
1049
            if (!pTaskState->DataSeg.pvSeg)
 
1050
                return VERR_NO_MEMORY;
 
1051
 
 
1052
            /* Copy the data if needed */
 
1053
            if (pTaskState->CommandControlBlockGuest.uDataDirection == BUSLOGIC_CCB_DIRECTION_OUT)
 
1054
            {
 
1055
                cScatterGatherGCLeft = pTaskState->CommandControlBlockGuest.cbData / sizeof(ScatterGatherEntry);
 
1056
                GCPhysAddrScatterGatherCurrent = (RTGCPHYS)pTaskState->CommandControlBlockGuest.u32PhysAddrData;
 
1057
                uint8_t *pbData = (uint8_t *)pTaskState->DataSeg.pvSeg;
 
1058
 
 
1059
                do
 
1060
                {
 
1061
                    cScatterGatherGCRead =   (cScatterGatherGCLeft < RT_ELEMENTS(aScatterGatherReadGC))
 
1062
                                            ? cScatterGatherGCLeft
 
1063
                                            : RT_ELEMENTS(aScatterGatherReadGC);
 
1064
                    cScatterGatherGCLeft -= cScatterGatherGCRead;
 
1065
 
 
1066
                    /* Read the SG entries. */
 
1067
                    PDMDevHlpPhysRead(pDevIns, GCPhysAddrScatterGatherCurrent, &aScatterGatherReadGC[0],
 
1068
                                        cScatterGatherGCRead * sizeof(ScatterGatherEntry));
 
1069
 
 
1070
                    for (iScatterGatherEntry = 0; iScatterGatherEntry < cScatterGatherGCRead; iScatterGatherEntry++)
 
1071
                    {
 
1072
                        RTGCPHYS    GCPhysAddrDataBase;
 
1073
 
 
1074
                        Log(("%s: iScatterGatherEntry=%u\n", __FUNCTION__, iScatterGatherEntry));
 
1075
 
 
1076
                        GCPhysAddrDataBase = (RTGCPHYS)aScatterGatherReadGC[iScatterGatherEntry].u32PhysAddrSegmentBase;
 
1077
                        cbDataToTransfer = aScatterGatherReadGC[iScatterGatherEntry].cbSegment;
 
1078
 
 
1079
                        Log(("%s: GCPhysAddrDataBase=%RGp cbDataToTransfer=%u\n", __FUNCTION__, GCPhysAddrDataBase, cbDataToTransfer));
 
1080
 
 
1081
                        PDMDevHlpPhysRead(pDevIns, GCPhysAddrDataBase, pbData, cbDataToTransfer);
 
1082
                        pbData += cbDataToTransfer;
 
1083
                    }
 
1084
 
 
1085
                    /* Set address to the next entries to read. */
 
1086
                    GCPhysAddrScatterGatherCurrent += cScatterGatherGCRead * sizeof(ScatterGatherEntry);
 
1087
                } while (cScatterGatherGCLeft > 0);
1181
1088
            }
1182
1089
 
1183
 
            /* Set address to the next entries to read. */
1184
 
            GCPhysAddrScatterGatherCurrent += cScatterGatherGCRead * sizeof(ScatterGatherEntry);
1185
 
 
1186
 
        } while (cScatterGatherGCLeft);
1187
 
 
1188
 
    }
1189
 
    else if (   (pTaskState->CommandControlBlockGuest.u32PhysAddrData != 0)
1190
 
             && (pTaskState->CommandControlBlockGuest.cbData != 0))
1191
 
    {
1192
 
        /* The buffer is not scattered. */
1193
 
        RTGCPHYS GCPhysAddrDataBase     = (RTGCPHYS)PAGE_ADDRESS(pTaskState->CommandControlBlockGuest.u32PhysAddrData);
1194
 
        RTGCPHYS GCPhysAddrDataEnd      = (RTGCPHYS)(pTaskState->CommandControlBlockGuest.u32PhysAddrData + pTaskState->CommandControlBlockGuest.cbData);
1195
 
        RTGCPHYS GCPhysAddrDataEndBase  = (RTGCPHYS)PAGE_ADDRESS(GCPhysAddrDataEnd);
1196
 
        RTGCPHYS GCPhysAddrDataNext     = (RTGCPHYS)PAGE_ADDRESS(GCPhysAddrDataEnd) + PAGE_SIZE;
1197
 
        uint32_t cPages = (GCPhysAddrDataNext - GCPhysAddrDataBase) / PAGE_SIZE;
1198
 
        uint32_t cbOffsetFirstPage = pTaskState->CommandControlBlockGuest.u32PhysAddrData & PAGE_OFFSET_MASK;
1199
 
 
1200
 
        Log(("Non scattered buffer:\n"));
1201
 
        Log(("u32PhysAddrData=%#x\n", pTaskState->CommandControlBlockGuest.u32PhysAddrData));
1202
 
        Log(("cbData=%u\n", pTaskState->CommandControlBlockGuest.cbData));
1203
 
        Log(("GCPhysAddrDataBase=0x%RGp\n", GCPhysAddrDataBase));
1204
 
        Log(("GCPhysAddrDataEnd=0x%RGp\n", GCPhysAddrDataEnd));
1205
 
        Log(("GCPhysAddrDataEndBase=0x%RGp\n", GCPhysAddrDataEndBase));
1206
 
        Log(("GCPhysAddrDataNext=0x%RGp\n", GCPhysAddrDataNext));
1207
 
        Log(("cPages=%u\n", cPages));
1208
 
 
1209
 
        pTaskState->paPageLock = (PPGMPAGEMAPLOCK)RTMemAllocZ(cPages * sizeof(PGMPAGEMAPLOCK));
1210
 
        AssertMsgReturn(pTaskState->paPageLock, ("Allocating page lock array failed\n"), VERR_NO_MEMORY);
1211
 
        pTaskState->paScatterGather = (PPDMDATASEG)RTMemAllocZ(cPages * sizeof(PDMDATASEG));
1212
 
        AssertMsgReturn(pTaskState->paScatterGather, ("Allocating scatter gather list failed\n"), VERR_NO_MEMORY);
1213
 
 
1214
 
        PPGMPAGEMAPLOCK    pPageLockCurrent = pTaskState->paPageLock;
1215
 
        PPDMDATASEG        pScatterGatherCurrent = pTaskState->paScatterGather;
1216
 
 
1217
 
        for (uint32_t i = 0; i < cPages; i++)
 
1090
        }
 
1091
        else if (pTaskState->CommandControlBlockGuest.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB)
1218
1092
        {
1219
 
            if (fReadonly)
1220
 
                rc = PDMDevHlpPhysGCPhys2CCPtrReadOnly(pDevIns, GCPhysAddrDataBase, 0, (const void **)&pScatterGatherCurrent->pvSeg, pPageLockCurrent);
1221
 
            else
1222
 
                rc = PDMDevHlpPhysGCPhys2CCPtr(pDevIns, GCPhysAddrDataBase, 0, &pScatterGatherCurrent->pvSeg, pPageLockCurrent);
1223
 
 
1224
 
            pScatterGatherCurrent->cbSeg = PAGE_SIZE;
1225
 
 
1226
 
            pPageLockCurrent++;
1227
 
            pScatterGatherCurrent++;
1228
 
            GCPhysAddrDataBase += PAGE_SIZE;
 
1093
            /* The buffer is not scattered. */
 
1094
            RTGCPHYS GCPhysAddrDataBase     = (RTGCPHYS)pTaskState->CommandControlBlockGuest.u32PhysAddrData;
 
1095
 
 
1096
            AssertMsg(GCPhysAddrDataBase != 0, ("Physical address is 0\n"));
 
1097
 
 
1098
            pTaskState->DataSeg.cbSeg = pTaskState->CommandControlBlockGuest.cbData;
 
1099
            pTaskState->DataSeg.pvSeg = RTMemAlloc(pTaskState->DataSeg.cbSeg);
 
1100
            if (!pTaskState->DataSeg.pvSeg)
 
1101
                return VERR_NO_MEMORY;
 
1102
 
 
1103
            Log(("Non scattered buffer:\n"));
 
1104
            Log(("u32PhysAddrData=%#x\n", pTaskState->CommandControlBlockGuest.u32PhysAddrData));
 
1105
            Log(("cbData=%u\n", pTaskState->CommandControlBlockGuest.cbData));
 
1106
            Log(("GCPhysAddrDataBase=0x%RGp\n", GCPhysAddrDataBase));
 
1107
 
 
1108
            /* Copy the data into the buffer. */
 
1109
            PDMDevHlpPhysRead(pDevIns, GCPhysAddrDataBase, pTaskState->DataSeg.pvSeg, pTaskState->DataSeg.cbSeg);
1229
1110
        }
1230
 
 
1231
 
        /* Correct pointer of the first entry. */
1232
 
        pTaskState->paScatterGather[0].pvSeg = (uint8_t *)pTaskState->paScatterGather[0].pvSeg + cbOffsetFirstPage;
1233
 
        pTaskState->paScatterGather[0].cbSeg -= cbOffsetFirstPage;
1234
 
        /* Correct size of the last entry. */
1235
 
        pTaskState->paScatterGather[cPages-1].cbSeg = GCPhysAddrDataEnd - GCPhysAddrDataEndBase;
1236
 
        pTaskState->cScatterGather = cPages;
1237
 
        pTaskState->cbScatterGather = pTaskState->CommandControlBlockGuest.cbData;
1238
1111
    }
1239
1112
 
1240
 
    return rc;
 
1113
    return VINF_SUCCESS;
1241
1114
}
1242
1115
 
1243
1116
/**
1244
 
 * Free mapped pages and other allocated resources used for the scatter gather list.
 
1117
 * Free allocated resources used for the scatter gather list.
1245
1118
 *
1246
1119
 * @returns nothing.
1247
1120
 * @param   pTaskState    Pointer to the task state.
1248
1121
 */
1249
 
static void buslogicFreeGCDataBuffer(PBUSLOGICTASKSTATE pTaskState)
 
1122
static void buslogicDataBufferFree(PBUSLOGICTASKSTATE pTaskState)
1250
1123
{
1251
 
    PPGMPAGEMAPLOCK pPageMapLock = pTaskState->paPageLock;
1252
 
    PPDMDEVINS      pDevIns = pTaskState->CTX_SUFF(pTargetDevice)->CTX_SUFF(pBusLogic)->CTX_SUFF(pDevIns);
 
1124
    PPDMDEVINS pDevIns = pTaskState->CTX_SUFF(pTargetDevice)->CTX_SUFF(pBusLogic)->CTX_SUFF(pDevIns);
1253
1125
 
1254
 
    for (uint32_t iPageLockCurrent = 0; iPageLockCurrent < pTaskState->cScatterGather; iPageLockCurrent++)
 
1126
    if (   (pTaskState->CommandControlBlockGuest.cbData > 0)
 
1127
        && (  (pTaskState->CommandControlBlockGuest.uDataDirection == BUSLOGIC_CCB_DIRECTION_IN)
 
1128
            || (pTaskState->CommandControlBlockGuest.uDataDirection == BUSLOGIC_CCB_DIRECTION_UNKNOWN)))
1255
1129
    {
1256
 
        PDMDevHlpPhysReleasePageMappingLock(pDevIns, pPageMapLock);
1257
 
        pPageMapLock++;
 
1130
        if (   (pTaskState->CommandControlBlockGuest.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB_SCATTER_GATHER)
 
1131
            || (pTaskState->CommandControlBlockGuest.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB_RESIDUAL_SCATTER_GATHER))
 
1132
        {
 
1133
            uint32_t cScatterGatherGCRead;
 
1134
            uint32_t iScatterGatherEntry;
 
1135
            ScatterGatherEntry aScatterGatherReadGC[32]; /* Number of scatter gather list entries read from guest memory. */
 
1136
            uint32_t cScatterGatherGCLeft = pTaskState->CommandControlBlockGuest.cbData / sizeof(ScatterGatherEntry);
 
1137
            RTGCPHYS GCPhysAddrScatterGatherCurrent = (RTGCPHYS)pTaskState->CommandControlBlockGuest.u32PhysAddrData;
 
1138
            uint8_t *pbData = (uint8_t *)pTaskState->DataSeg.pvSeg;
 
1139
 
 
1140
            do
 
1141
            {
 
1142
                cScatterGatherGCRead =   (cScatterGatherGCLeft < RT_ELEMENTS(aScatterGatherReadGC))
 
1143
                                        ? cScatterGatherGCLeft
 
1144
                                        : RT_ELEMENTS(aScatterGatherReadGC);
 
1145
                cScatterGatherGCLeft -= cScatterGatherGCRead;
 
1146
 
 
1147
                /* Read the SG entries. */
 
1148
                PDMDevHlpPhysRead(pDevIns, GCPhysAddrScatterGatherCurrent, &aScatterGatherReadGC[0],
 
1149
                                    cScatterGatherGCRead * sizeof(ScatterGatherEntry));
 
1150
 
 
1151
                for (iScatterGatherEntry = 0; iScatterGatherEntry < cScatterGatherGCRead; iScatterGatherEntry++)
 
1152
                {
 
1153
                    RTGCPHYS    GCPhysAddrDataBase;
 
1154
                    size_t      cbDataToTransfer;
 
1155
 
 
1156
                    Log(("%s: iScatterGatherEntry=%u\n", __FUNCTION__, iScatterGatherEntry));
 
1157
 
 
1158
                    GCPhysAddrDataBase = (RTGCPHYS)aScatterGatherReadGC[iScatterGatherEntry].u32PhysAddrSegmentBase;
 
1159
                    cbDataToTransfer = aScatterGatherReadGC[iScatterGatherEntry].cbSegment;
 
1160
 
 
1161
                    Log(("%s: GCPhysAddrDataBase=%RGp cbDataToTransfer=%u\n", __FUNCTION__, GCPhysAddrDataBase, cbDataToTransfer));
 
1162
 
 
1163
                    PDMDevHlpPhysWrite(pDevIns, GCPhysAddrDataBase, pbData, cbDataToTransfer);
 
1164
                    pbData += cbDataToTransfer;
 
1165
                }
 
1166
 
 
1167
                /* Set address to the next entries to read. */
 
1168
                GCPhysAddrScatterGatherCurrent += cScatterGatherGCRead * sizeof(ScatterGatherEntry);
 
1169
            } while (cScatterGatherGCLeft > 0);
 
1170
 
 
1171
        }
 
1172
        else if (pTaskState->CommandControlBlockGuest.uOpcode == BUSLOGIC_CCB_OPCODE_INITIATOR_CCB)
 
1173
        {
 
1174
            /* The buffer is not scattered. */
 
1175
            RTGCPHYS GCPhysAddrDataBase = (RTGCPHYS)pTaskState->CommandControlBlockGuest.u32PhysAddrData;
 
1176
 
 
1177
            AssertMsg(GCPhysAddrDataBase != 0, ("Physical address is 0\n"));
 
1178
 
 
1179
            Log(("Non scattered buffer:\n"));
 
1180
            Log(("u32PhysAddrData=%#x\n", pTaskState->CommandControlBlockGuest.u32PhysAddrData));
 
1181
            Log(("cbData=%u\n", pTaskState->CommandControlBlockGuest.cbData));
 
1182
            Log(("GCPhysAddrDataBase=0x%RGp\n", GCPhysAddrDataBase));
 
1183
 
 
1184
            /* Copy the data into the guest memory. */
 
1185
            PDMDevHlpPhysWrite(pDevIns, GCPhysAddrDataBase, pTaskState->DataSeg.pvSeg, pTaskState->DataSeg.cbSeg);
 
1186
        }
1258
1187
    }
1259
1188
 
1260
 
    /* @todo: optimize with caching. */
1261
 
    RTMemFree(pTaskState->paPageLock);
1262
 
    RTMemFree(pTaskState->paScatterGather);
1263
 
    pTaskState->paPageLock      = NULL;
1264
 
    pTaskState->paScatterGather = NULL;
1265
 
    pTaskState->cScatterGather  = 0;
1266
 
    pTaskState->cbScatterGather = 0;
 
1189
    RTMemFree(pTaskState->DataSeg.pvSeg);
 
1190
    pTaskState->DataSeg.pvSeg = NULL;
 
1191
    pTaskState->DataSeg.cbSeg = 0;
1267
1192
}
1268
1193
 
1269
1194
/**
1272
1197
 * @returns nothing.
1273
1198
 * @param   pTaskState   Pointer to the task state.
1274
1199
 */
1275
 
static void buslogicFreeGCSenseBuffer(PBUSLOGICTASKSTATE pTaskState)
 
1200
static void buslogicSenseBufferFree(PBUSLOGICTASKSTATE pTaskState)
1276
1201
{
1277
1202
    PPDMDEVINS pDevIns = pTaskState->CTX_SUFF(pTargetDevice)->CTX_SUFF(pBusLogic)->CTX_SUFF(pDevIns);
1278
 
 
1279
 
    PDMDevHlpPhysReleasePageMappingLock(pDevIns, &pTaskState->pPageLockSense);
1280
 
    pTaskState->pu8SenseBuffer = NULL;
 
1203
    RTGCPHYS GCPhysAddrSenseBuffer = (RTGCPHYS)pTaskState->CommandControlBlockGuest.u32PhysAddrSenseData;
 
1204
    uint32_t cbSenseBuffer = pTaskState->CommandControlBlockGuest.cbSenseData;
 
1205
 
 
1206
    /* Copy into guest memory. */
 
1207
    PDMDevHlpPhysWrite(pDevIns, GCPhysAddrSenseBuffer, pTaskState->pbSenseBuffer, cbSenseBuffer);
 
1208
 
 
1209
    RTMemFree(pTaskState->pbSenseBuffer);
 
1210
    pTaskState->pbSenseBuffer = NULL;
1281
1211
}
1282
1212
 
1283
1213
/**
1284
 
 * Map the sense buffer into R3.
 
1214
 * Alloc the sense buffer.
1285
1215
 *
1286
1216
 * @returns VBox status code.
1287
1217
 * @param   pTaskState    Pointer to the task state.
1288
1218
 * @note Current assumption is that the sense buffer is not scattered and does not cross a page boundary.
1289
1219
 */
1290
 
static int buslogicMapGCSenseBufferIntoR3(PBUSLOGICTASKSTATE pTaskState)
 
1220
static int buslogicSenseBufferAlloc(PBUSLOGICTASKSTATE pTaskState)
1291
1221
{
1292
 
    int rc = VINF_SUCCESS;
1293
1222
    PPDMDEVINS pDevIns = pTaskState->CTX_SUFF(pTargetDevice)->CTX_SUFF(pBusLogic)->CTX_SUFF(pDevIns);
1294
 
    RTGCPHYS GCPhysAddrSenseBuffer = (RTGCPHYS)pTaskState->CommandControlBlockGuest.u32PhysAddrSenseData;
1295
 
#ifdef RT_STRICT
1296
1223
    uint32_t cbSenseBuffer = pTaskState->CommandControlBlockGuest.cbSenseData;
1297
 
#endif
1298
 
    RTGCPHYS GCPhysAddrSenseBufferBase = PAGE_ADDRESS(GCPhysAddrSenseBuffer);
1299
 
 
1300
 
    AssertMsg(GCPhysAddrSenseBuffer >= GCPhysAddrSenseBufferBase,
1301
 
              ("Impossible GCPhysAddrSenseBuffer < GCPhysAddrSenseBufferBase\n"));
1302
 
 
1303
 
    /* Sanity checks for the assumption. */
1304
 
    AssertMsg(((GCPhysAddrSenseBuffer + cbSenseBuffer) < (GCPhysAddrSenseBufferBase + PAGE_SIZE)),
1305
 
              ("Sense buffer crosses page boundary\n"));
1306
 
 
1307
 
    rc = PDMDevHlpPhysGCPhys2CCPtr(pDevIns, GCPhysAddrSenseBufferBase, 0, (void **)&pTaskState->pu8SenseBuffer, &pTaskState->pPageLockSense);
1308
 
    AssertMsgRC(rc, ("Mapping sense buffer failed rc=%Rrc\n", rc));
1309
 
 
1310
 
    /* Correct start address of the sense buffer. */
1311
 
    pTaskState->pu8SenseBuffer += (GCPhysAddrSenseBuffer - GCPhysAddrSenseBufferBase);
1312
 
 
1313
 
    return rc;
 
1224
 
 
1225
    pTaskState->pbSenseBuffer = (uint8_t *)RTMemAllocZ(cbSenseBuffer);
 
1226
    if (!pTaskState->pbSenseBuffer)
 
1227
        return VERR_NO_MEMORY;
 
1228
 
 
1229
    return VINF_SUCCESS;
1314
1230
}
1315
1231
#endif /* IN_RING3 */
1316
1232
 
1586
1502
            break;
1587
1503
        }
1588
1504
        default:
1589
 
            AssertMsgFailed(("Register not available\n"));
1590
 
            rc = VERR_IOM_IOPORT_UNUSED;
 
1505
            *pu32 = UINT32_C(0xffffffff);
1591
1506
    }
1592
1507
 
1593
1508
    Log2(("%s: pu32=%p:{%.*Rhxs} iRegister=%d rc=%Rrc\n",
1629
1544
        case BUSLOGIC_REGISTER_COMMAND:
1630
1545
        {
1631
1546
            /* Fast path for mailbox execution command. */
1632
 
            if ((uVal == BUSLOGICCOMMAND_EXECUTE_MAILBOX_COMMAND) && (pBusLogic->uOperationCode = 0xff))
 
1547
            if ((uVal == BUSLOGICCOMMAND_EXECUTE_MAILBOX_COMMAND) && (pBusLogic->uOperationCode == 0xff))
1633
1548
            {
1634
1549
                ASMAtomicIncU32(&pBusLogic->cMailboxesReady);
1635
1550
                if (!ASMAtomicXchgBool(&pBusLogic->fNotificationSend, true))
1830
1745
 
1831
1746
    rc = vboxscsiReadRegister(&pBusLogic->VBoxSCSI, (Port - BUSLOGIC_ISA_IO_PORT), pu32);
1832
1747
 
1833
 
    Log2(("%s: pu32=%p:{%.*Rhxs} iRegister=%d rc=%Rrc\n",
1834
 
          __FUNCTION__, pu32, 1, pu32, (Port - BUSLOGIC_ISA_IO_PORT), rc));
 
1748
    //Log2(("%s: pu32=%p:{%.*Rhxs} iRegister=%d rc=%Rrc\n",
 
1749
    //      __FUNCTION__, pu32, 1, pu32, (Port - BUSLOGIC_ISA_IO_PORT), rc));
1835
1750
 
1836
1751
    return rc;
1837
1752
}
2052
1967
    }
2053
1968
    else
2054
1969
    {
2055
 
        buslogicFreeGCDataBuffer(pTaskState);
 
1970
        buslogicDataBufferFree(pTaskState);
2056
1971
 
2057
 
        if (pTaskState->pu8SenseBuffer)
2058
 
            buslogicFreeGCSenseBuffer(pTaskState);
 
1972
        if (pTaskState->pbSenseBuffer)
 
1973
            buslogicSenseBufferFree(pTaskState);
2059
1974
 
2060
1975
        buslogicSendIncomingMailbox(pBusLogic, pTaskState,
2061
1976
                                    BUSLOGIC_MAILBOX_INCOMING_ADAPTER_STATUS_CMD_COMPLETED,
2120
2035
 
2121
2036
    if (pTaskState->MailboxGuest.u.out.uActionCode == BUSLOGIC_MAILBOX_OUTGOING_ACTION_START_COMMAND)
2122
2037
    {
2123
 
        bool fReadonly = false;
2124
 
 
2125
2038
        /* Fetch CCB now. */
2126
2039
        RTGCPHYS GCPhysAddrCCB = (RTGCPHYS)pTaskState->MailboxGuest.u32PhysAddrCCB;
2127
2040
        PDMDevHlpPhysRead(pBusLogic->CTX_SUFF(pDevIns), GCPhysAddrCCB,
2134
2047
        buslogicDumpCCBInfo(&pTaskState->CommandControlBlockGuest);
2135
2048
#endif
2136
2049
 
2137
 
        switch (pTaskState->CommandControlBlockGuest.uDataDirection)
2138
 
        {
2139
 
            case BUSLOGIC_CCB_DIRECTION_UNKNOWN:
2140
 
            case BUSLOGIC_CCB_DIRECTION_IN:
2141
 
                fReadonly = false;
2142
 
                break;
2143
 
            case BUSLOGIC_CCB_DIRECTION_OUT:
2144
 
            case BUSLOGIC_CCB_DIRECTION_NO_DATA:
2145
 
                fReadonly = true;
2146
 
                break;
2147
 
            default:
2148
 
                AssertMsgFailed(("Invalid data transfer direction type %u\n",
2149
 
                                    pTaskState->CommandControlBlockGuest.uDataDirection));
2150
 
        }
2151
 
 
2152
 
        /* Map required buffers. */
2153
 
        rc = buslogicMapGCDataBufIntoR3(pTaskState, fReadonly);
2154
 
        AssertMsgRC(rc, ("Mapping failed rc=%Rrc\n", rc));
 
2050
        /* Alloc required buffers. */
 
2051
        rc = buslogicDataBufferAlloc(pTaskState);
 
2052
        AssertMsgRC(rc, ("Alloc failed rc=%Rrc\n", rc));
2155
2053
 
2156
2054
        if (pTaskState->CommandControlBlockGuest.cbSenseData)
2157
2055
        {
2158
 
            rc = buslogicMapGCSenseBufferIntoR3(pTaskState);
 
2056
            rc = buslogicSenseBufferAlloc(pTaskState);
2159
2057
            AssertMsgRC(rc, ("Mapping sense buffer failed rc=%Rrc\n", rc));
2160
2058
        }
2161
2059
 
2162
2060
        /* Check if device is present on bus. If not return error immediately and don't process this further. */
2163
2061
        if (!pBusLogic->aDeviceStates[pTaskState->CommandControlBlockGuest.uTargetId].fPresent)
2164
2062
        {
2165
 
            buslogicFreeGCDataBuffer(pTaskState);
 
2063
            buslogicDataBufferFree(pTaskState);
2166
2064
 
2167
 
            if (pTaskState->pu8SenseBuffer)
2168
 
                buslogicFreeGCSenseBuffer(pTaskState);
 
2065
            if (pTaskState->pbSenseBuffer)
 
2066
                buslogicSenseBufferFree(pTaskState);
2169
2067
 
2170
2068
            buslogicSendIncomingMailbox(pBusLogic, pTaskState,
2171
2069
                                        BUSLOGIC_MAILBOX_INCOMING_ADAPTER_STATUS_SCSI_SELECTION_TIMEOUT,
2193
2091
 
2194
2092
            pTaskState->PDMScsiRequest.cbCDB                 = pTaskState->CommandControlBlockGuest.cbCDB;
2195
2093
            pTaskState->PDMScsiRequest.pbCDB                 = pTaskState->CommandControlBlockGuest.aCDB;
2196
 
            pTaskState->PDMScsiRequest.cbScatterGather       = pTaskState->cbScatterGather;
2197
 
            pTaskState->PDMScsiRequest.cScatterGatherEntries = pTaskState->cScatterGather;
2198
 
            pTaskState->PDMScsiRequest.paScatterGatherHead   = pTaskState->paScatterGather;
 
2094
            if (pTaskState->DataSeg.cbSeg)
 
2095
            {
 
2096
                pTaskState->PDMScsiRequest.cbScatterGather       = pTaskState->DataSeg.cbSeg;
 
2097
                pTaskState->PDMScsiRequest.cScatterGatherEntries = 1;
 
2098
                pTaskState->PDMScsiRequest.paScatterGatherHead   = &pTaskState->DataSeg;
 
2099
            }
 
2100
            else
 
2101
            {
 
2102
                pTaskState->PDMScsiRequest.cbScatterGather       = 0;
 
2103
                pTaskState->PDMScsiRequest.cScatterGatherEntries = 0;
 
2104
                pTaskState->PDMScsiRequest.paScatterGatherHead   = NULL;
 
2105
            }
2199
2106
            pTaskState->PDMScsiRequest.cbSenseBuffer         = pTaskState->CommandControlBlockGuest.cbSenseData;
2200
 
            pTaskState->PDMScsiRequest.pbSenseBuffer         = pTaskState->pu8SenseBuffer;
 
2107
            pTaskState->PDMScsiRequest.pbSenseBuffer         = pTaskState->pbSenseBuffer;
2201
2108
            pTaskState->PDMScsiRequest.pvUser                = pTaskState;
2202
2109
 
2203
2110
            LogFlowFunc(("before increment %u\n", pTargetDevice->cOutstandingRequests));