VirtualBox

Changeset 39655 in vbox for trunk/src/VBox/Devices


Ignore:
Timestamp:
Dec 19, 2011 5:50:12 PM (13 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
75469
Message:

AHCI: Long overdue code cleanup, removes over 800 lines of unused or duplicated code and unifies the code path between async and non aasync I/O where possible

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Storage/DevAHCI.cpp

    r39584 r39655  
    6161#define AHCI_MAX_NR_PORTS_IMPL 30
    6262#define AHCI_NR_COMMAND_SLOTS 32
    63 #define AHCI_NR_OF_ALLOWED_BIGGER_LISTS 100
    6463
    6564/** The current saved state version. */
     
    117116#define ATAPI_SENSE_SIZE 64
    118117
    119 /* Command Header. */
     118/**
     119 * Command Header.
     120 */
     121#pragma pack(1)
    120122typedef struct
    121123{
     
    131133    uint32_t           u32Reserved[4];
    132134} CmdHdr;
     135#pragma pack()
    133136AssertCompileSize(CmdHdr, 32);
    134137
     
    191194#define AHCI_CMDFIS_ERR                   3
    192195
    193 /**
    194  * Scatter gather list entry data.
    195  */
    196 typedef struct AHCIPORTTASKSTATESGENTRY
    197 {
    198     /** Flag whether the buffer in the list is from the guest or an
    199      *  allocated temporary buffer because the segments in the guest
    200      *  are not sector aligned.
    201      */
    202     bool     fGuestMemory;
    203     /** Flag dependent data. */
    204     union
    205     {
    206         /** Data to handle direct mappings of guest buffers. */
    207         struct
    208         {
    209             /** The page lock. */
    210             PGMPAGEMAPLOCK  PageLock;
    211         } direct;
    212         /** Data to handle temporary buffers. */
    213         struct
    214         {
    215             /** The first segment in the guest which is not sector aligned. */
    216             RTGCPHYS        GCPhysAddrBaseFirstUnaligned;
    217             /** Number of unaligned buffers in the guest. */
    218             uint32_t        cUnaligned;
    219             /** Pointer to the start of the buffer. */
    220             void           *pvBuf;
    221         } temp;
    222     } u;
    223 } AHCIPORTTASKSTATESGENTRY, *PAHCIPORTTASKSTATESGENTRY;
    224 
    225 /** Pointer to a pointer of a scatter gather list entry. */
    226 typedef PAHCIPORTTASKSTATESGENTRY *PPAHCIPORTTASKSTATESGENTRY;
    227196/** Pointer to a task state. */
    228 typedef struct AHCIPORTTASKSTATE *PAHCIPORTTASKSTATE;
     197typedef struct AHCIREQ *PAHCIREQ;
    229198
    230199/**
     
    232201 *
    233202 * @returns VBox status.
    234  * @param   pAhciPortTaskState    The task state.
    235  */
    236 typedef DECLCALLBACK(int)   FNAHCIPOSTPROCESS(PAHCIPORTTASKSTATE pAhciPortTaskState);
     203 * @param   pAhciReq    The task state.
     204 * @param   ppvProc     Where to store the pointer to the buffer holding the processed data on success.
     205 *                      Must be freed with RTMemFree().
     206 * @param   pcbProc     Where to store the size of the buffer on success.
     207 */
     208typedef DECLCALLBACK(int)   FNAHCIPOSTPROCESS(PAHCIREQ pAhciReq, void **ppvProc, size_t *pcbProc);
    237209/** Pointer to a FNAHCIPOSTPROCESS() function. */
    238210typedef FNAHCIPOSTPROCESS *PFNAHCIPOSTPROCESS;
     
    274246} AHCITXSTATE, *PAHCITXSTATE;
    275247
     248/** Task encountered a buffer overflow. */
     249#define AHCI_REQ_OVERFLOW RT_BIT_32(0)
     250
    276251/**
    277252 * A task state.
    278253 */
    279 typedef struct AHCIPORTTASKSTATE
     254typedef struct AHCIREQ
    280255{
    281256    /** Task state. */
     
    295270    /** Physical address of the command header. - GC */
    296271    RTGCPHYS                   GCPhysCmdHdrAddr;
     272    /** Physical address if the PRDT */
     273    RTGCPHYS                   GCPhysPrdtl;
     274    /** Number of entries in the PRDTL. */
     275    unsigned                   cPrdtlEntries;
    297276    /** Data direction. */
    298277    AHCITXDIR                  enmTxDir;
     
    305284    /** ATA status register */
    306285    uint8_t                    uATARegStatus;
    307     /** How many entries would fit into the sg list. */
    308     uint32_t                   cSGListSize;
    309     /** Number of used SG list entries. */
    310     uint32_t                   cSGListUsed;
    311     /** Pointer to the first entry of the scatter gather list. */
    312     PRTSGSEG                   pSGListHead;
    313     /** Number of scatter gather list entries. */
    314     uint32_t                   cSGEntries;
    315     /** Total number of bytes the guest reserved for this request.
    316      * Sum of all SG entries. */
    317     uint32_t                   cbSGBuffers;
    318     /** Pointer to the first mapping information entry. */
    319     PAHCIPORTTASKSTATESGENTRY  paSGEntries;
    320     /** Size of the temporary buffer for unaligned guest segments. */
    321     uint32_t                   cbBufferUnaligned;
    322     /** Pointer to the temporary buffer. */
    323     void                      *pvBufferUnaligned;
    324     /** Number of times in a row the scatter gather list was too big. */
    325     uint32_t                   cSGListTooBig;
    326     /** Post processing callback.
    327      * If this is set we will use a buffer for the data
    328      * and the callback copies the data to the destination. */
    329     PFNAHCIPOSTPROCESS         pfnPostProcess;
    330     /** Pointer to the array of PDM ranges. */
    331     PRTRANGE                   paRanges;
    332     /** Number of entries in the array. */
    333     unsigned                   cRanges;
    334 } AHCIPORTTASKSTATE;
     286    /** Flags for this task. */
     287    uint32_t                   fFlags;
     288    /** Data dependent on the transfer direction. */
     289    union
     290    {
     291        /** Data for an I/O request. */
     292        struct
     293        {
     294            /** Data segment. */
     295            RTSGSEG            DataSeg;
     296            /** Post processing callback.
     297             * If this is set we will use a buffer for the data
     298             * and the callback returns a buffer with the final data. */
     299            PFNAHCIPOSTPROCESS pfnPostProcess;
     300        } Io;
     301        /** Data for a trim request. */
     302        struct
     303        {
     304            /** Pointer to the array of ranges to trim. */
     305            PRTRANGE           paRanges;
     306            /** Number of entries in the array. */
     307            unsigned           cRanges;
     308        } Trim;
     309    } u;
     310} AHCIREQ;
    335311
    336312/**
     
    508484     * Only used with the async interface.
    509485     */
    510     R3PTRTYPE(PAHCIPORTTASKSTATE)   aCachedTasks[AHCI_NR_COMMAND_SLOTS];
     486    R3PTRTYPE(PAHCIREQ)             aCachedTasks[AHCI_NR_COMMAND_SLOTS];
    511487    /** First task throwing an error. */
    512     R3PTRTYPE(volatile PAHCIPORTTASKSTATE) pTaskErr;
     488    R3PTRTYPE(volatile PAHCIREQ)    pTaskErr;
    513489
    514490#if HC_ARCH_BITS == 32
     
    915891static int  ahciPostFisIntoMemory(PAHCIPort pAhciPort, unsigned uFisType, uint8_t *cmdFis);
    916892static void ahciPostFirstD2HFisIntoMemory(PAHCIPort pAhciPort);
    917 static int  ahciScatterGatherListCopyFromBuffer(PAHCIPORTTASKSTATE pAhciPortTaskState, void *pvBuf, size_t cbBuf);
    918 static int  ahciScatterGatherListCreate(PAHCIPort pAhciPort, PAHCIPORTTASKSTATE pAhciPortTaskState, bool fReadonly);
    919 static void ahciScatterGatherListFree(PAHCIPORTTASKSTATE pAhciPortTaskState);
    920 static int  ahciScatterGatherListDestroy(PAHCIPort pAhciPort, PAHCIPORTTASKSTATE pAhciPortTaskState);
    921 static void ahciCopyFromBufferIntoSGList(PPDMDEVINS pDevIns, PAHCIPORTTASKSTATESGENTRY pSGInfo);
    922 static void ahciCopyFromSGListIntoBuffer(PPDMDEVINS pDevIns, PAHCIPORTTASKSTATESGENTRY pSGInfo);
    923 static void ahciScatterGatherListGetTotalBufferSize(PAHCIPort pAhciPort, PAHCIPORTTASKSTATE pAhciPortTaskState);
    924 static int  ahciScatterGatherListCreateSafe(PAHCIPort pAhciPort, PAHCIPORTTASKSTATE pAhciPortTaskState,
    925                                             bool fReadonly, unsigned cSGEntriesProcessed);
     893static size_t ahciCopyToPrdtl(PPDMDEVINS pDevIns, PAHCIREQ pAhciReq,
     894                              void *pvBuf, size_t cbBuf);
     895static size_t ahciCopyFromPrdtl(PPDMDEVINS pDevIns, PAHCIREQ pAhciReq,
     896                                void *pvBuf, size_t cbBuf);
    926897static bool ahciCancelActiveTasks(PAHCIPort pAhciPort);
    927898#endif
     
    936907#define PDMILEDPORTS_2_PAHCI(pInterface)         ( (PAHCI)((uintptr_t)(pInterface) - RT_OFFSETOF(AHCI, ILeds)) )
    937908
    938 #if 1
    939909#define AHCI_RTGCPHYS_FROM_U32(Hi, Lo)             ( (RTGCPHYS)RT_MAKE_U64(Lo, Hi) )
    940 #else
    941 #define AHCI_RTGCPHYS_FROM_U32(Hi, Lo)             ( (RTGCPHYS)(Lo) )
    942 #endif
    943910
    944911#ifdef IN_RING3
     
    26532620}
    26542621
     2622/**
     2623 * @interface_method_impl{PDMIBLOCKPORT,pfnQueryDeviceLocation}
     2624 */
    26552625static DECLCALLBACK(int) ahciR3PortQueryDeviceLocation(PPDMIBLOCKPORT pInterface, const char **ppcszController,
    26562626                                                       uint32_t *piInstance, uint32_t *piLUN)
     
    26862656    {
    26872657        case AHCI_CMDFIS_TYPE_H2D:
    2688             {
    2689                 ahciLog(("%s: Command Fis type: H2D\n", __FUNCTION__));
    2690                 ahciLog(("%s: Command Fis size: %d bytes\n", __FUNCTION__, AHCI_CMDFIS_TYPE_H2D_SIZE));
    2691                 if (cmdFis[AHCI_CMDFIS_BITS] & AHCI_CMDFIS_C)
    2692                 {
    2693                     ahciLog(("%s: Command register update\n", __FUNCTION__));
    2694                 }
    2695                 else
    2696                 {
    2697                     ahciLog(("%s: Control register update\n", __FUNCTION__));
    2698                 }
    2699                 ahciLog(("%s: CMD=%#04x \"%s\"\n", __FUNCTION__, cmdFis[AHCI_CMDFIS_CMD], ATACmdText(cmdFis[AHCI_CMDFIS_CMD])));
    2700                 ahciLog(("%s: FEAT=%#04x\n", __FUNCTION__, cmdFis[AHCI_CMDFIS_FET]));
    2701                 ahciLog(("%s: SECTN=%#04x\n", __FUNCTION__, cmdFis[AHCI_CMDFIS_SECTN]));
    2702                 ahciLog(("%s: CYLL=%#04x\n", __FUNCTION__, cmdFis[AHCI_CMDFIS_CYLL]));
    2703                 ahciLog(("%s: CYLH=%#04x\n", __FUNCTION__, cmdFis[AHCI_CMDFIS_CYLH]));
    2704                 ahciLog(("%s: HEAD=%#04x\n", __FUNCTION__, cmdFis[AHCI_CMDFIS_HEAD]));
    2705 
    2706                 ahciLog(("%s: SECTNEXP=%#04x\n", __FUNCTION__, cmdFis[AHCI_CMDFIS_SECTNEXP]));
    2707                 ahciLog(("%s: CYLLEXP=%#04x\n", __FUNCTION__, cmdFis[AHCI_CMDFIS_CYLLEXP]));
    2708                 ahciLog(("%s: CYLHEXP=%#04x\n", __FUNCTION__, cmdFis[AHCI_CMDFIS_CYLHEXP]));
    2709                 ahciLog(("%s: FETEXP=%#04x\n", __FUNCTION__, cmdFis[AHCI_CMDFIS_FETEXP]));
    2710 
    2711                 ahciLog(("%s: SECTC=%#04x\n", __FUNCTION__, cmdFis[AHCI_CMDFIS_SECTC]));
    2712                 ahciLog(("%s: SECTCEXP=%#04x\n", __FUNCTION__, cmdFis[AHCI_CMDFIS_SECTCEXP]));
    2713                 ahciLog(("%s: CTL=%#04x\n", __FUNCTION__, cmdFis[AHCI_CMDFIS_CTL]));
    2714                 if (cmdFis[AHCI_CMDFIS_CTL] & AHCI_CMDFIS_CTL_SRST)
    2715                 {
    2716                     ahciLog(("%s: Reset bit is set\n", __FUNCTION__));
    2717                 }
    2718             }
     2658        {
     2659            ahciLog(("%s: Command Fis type: H2D\n", __FUNCTION__));
     2660            ahciLog(("%s: Command Fis size: %d bytes\n", __FUNCTION__, AHCI_CMDFIS_TYPE_H2D_SIZE));
     2661            if (cmdFis[AHCI_CMDFIS_BITS] & AHCI_CMDFIS_C)
     2662                ahciLog(("%s: Command register update\n", __FUNCTION__));
     2663            else
     2664                ahciLog(("%s: Control register update\n", __FUNCTION__));
     2665            ahciLog(("%s: CMD=%#04x \"%s\"\n", __FUNCTION__, cmdFis[AHCI_CMDFIS_CMD], ATACmdText(cmdFis[AHCI_CMDFIS_CMD])));
     2666            ahciLog(("%s: FEAT=%#04x\n", __FUNCTION__, cmdFis[AHCI_CMDFIS_FET]));
     2667            ahciLog(("%s: SECTN=%#04x\n", __FUNCTION__, cmdFis[AHCI_CMDFIS_SECTN]));
     2668            ahciLog(("%s: CYLL=%#04x\n", __FUNCTION__, cmdFis[AHCI_CMDFIS_CYLL]));
     2669            ahciLog(("%s: CYLH=%#04x\n", __FUNCTION__, cmdFis[AHCI_CMDFIS_CYLH]));
     2670            ahciLog(("%s: HEAD=%#04x\n", __FUNCTION__, cmdFis[AHCI_CMDFIS_HEAD]));
     2671
     2672            ahciLog(("%s: SECTNEXP=%#04x\n", __FUNCTION__, cmdFis[AHCI_CMDFIS_SECTNEXP]));
     2673            ahciLog(("%s: CYLLEXP=%#04x\n", __FUNCTION__, cmdFis[AHCI_CMDFIS_CYLLEXP]));
     2674            ahciLog(("%s: CYLHEXP=%#04x\n", __FUNCTION__, cmdFis[AHCI_CMDFIS_CYLHEXP]));
     2675            ahciLog(("%s: FETEXP=%#04x\n", __FUNCTION__, cmdFis[AHCI_CMDFIS_FETEXP]));
     2676
     2677            ahciLog(("%s: SECTC=%#04x\n", __FUNCTION__, cmdFis[AHCI_CMDFIS_SECTC]));
     2678            ahciLog(("%s: SECTCEXP=%#04x\n", __FUNCTION__, cmdFis[AHCI_CMDFIS_SECTCEXP]));
     2679            ahciLog(("%s: CTL=%#04x\n", __FUNCTION__, cmdFis[AHCI_CMDFIS_CTL]));
     2680            if (cmdFis[AHCI_CMDFIS_CTL] & AHCI_CMDFIS_CTL_SRST)
     2681                ahciLog(("%s: Reset bit is set\n", __FUNCTION__));
    27192682            break;
     2683        }
    27202684        case AHCI_CMDFIS_TYPE_D2H:
    2721             {
    2722                 ahciLog(("%s: Command Fis type D2H\n", __FUNCTION__));
    2723                 ahciLog(("%s: Command Fis size: %d\n", __FUNCTION__, AHCI_CMDFIS_TYPE_D2H_SIZE));
    2724             }
     2685        {
     2686            ahciLog(("%s: Command Fis type D2H\n", __FUNCTION__));
     2687            ahciLog(("%s: Command Fis size: %d\n", __FUNCTION__, AHCI_CMDFIS_TYPE_D2H_SIZE));
    27252688            break;
     2689        }
    27262690        case AHCI_CMDFIS_TYPE_SETDEVBITS:
    2727             {
    2728                 ahciLog(("%s: Command Fis type Set Device Bits\n", __FUNCTION__));
    2729                 ahciLog(("%s: Command Fis size: %d\n", __FUNCTION__, AHCI_CMDFIS_TYPE_SETDEVBITS_SIZE));
    2730             }
     2691        {
     2692            ahciLog(("%s: Command Fis type Set Device Bits\n", __FUNCTION__));
     2693            ahciLog(("%s: Command Fis size: %d\n", __FUNCTION__, AHCI_CMDFIS_TYPE_SETDEVBITS_SIZE));
    27312694            break;
     2695        }
    27322696        case AHCI_CMDFIS_TYPE_DMAACTD2H:
    2733             {
    2734                 ahciLog(("%s: Command Fis type DMA Activate H2D\n", __FUNCTION__));
    2735                 ahciLog(("%s: Command Fis size: %d\n", __FUNCTION__, AHCI_CMDFIS_TYPE_DMAACTD2H_SIZE));
    2736             }
     2697        {
     2698            ahciLog(("%s: Command Fis type DMA Activate H2D\n", __FUNCTION__));
     2699            ahciLog(("%s: Command Fis size: %d\n", __FUNCTION__, AHCI_CMDFIS_TYPE_DMAACTD2H_SIZE));
    27372700            break;
     2701        }
    27382702        case AHCI_CMDFIS_TYPE_DMASETUP:
    2739             {
    2740                 ahciLog(("%s: Command Fis type DMA Setup\n", __FUNCTION__));
    2741                 ahciLog(("%s: Command Fis size: %d\n", __FUNCTION__, AHCI_CMDFIS_TYPE_DMASETUP_SIZE));
    2742             }
     2703        {
     2704            ahciLog(("%s: Command Fis type DMA Setup\n", __FUNCTION__));
     2705            ahciLog(("%s: Command Fis size: %d\n", __FUNCTION__, AHCI_CMDFIS_TYPE_DMASETUP_SIZE));
    27432706            break;
     2707        }
    27442708        case AHCI_CMDFIS_TYPE_PIOSETUP:
    2745             {
    2746                 ahciLog(("%s: Command Fis type PIO Setup\n", __FUNCTION__));
    2747                 ahciLog(("%s: Command Fis size: %d\n", __FUNCTION__, AHCI_CMDFIS_TYPE_PIOSETUP_SIZE));
    2748             }
     2709        {
     2710            ahciLog(("%s: Command Fis type PIO Setup\n", __FUNCTION__));
     2711            ahciLog(("%s: Command Fis size: %d\n", __FUNCTION__, AHCI_CMDFIS_TYPE_PIOSETUP_SIZE));
    27492712            break;
     2713        }
    27502714        case AHCI_CMDFIS_TYPE_DATA:
    2751             {
    2752                 ahciLog(("%s: Command Fis type Data\n", __FUNCTION__));
    2753             }
     2715        {
     2716            ahciLog(("%s: Command Fis type Data\n", __FUNCTION__));
    27542717            break;
     2718        }
    27552719        default:
    27562720            ahciLog(("%s: ERROR Unknown command FIS type\n", __FUNCTION__));
     
    28592823        {
    28602824            case AHCI_CMDFIS_TYPE_D2H:
    2861                 {
    2862                     GCPhysAddrRecFis += AHCI_RECFIS_RFIS_OFFSET;
    2863                     cbFis = AHCI_CMDFIS_TYPE_D2H_SIZE;
    2864                 }
     2825            {
     2826                GCPhysAddrRecFis += AHCI_RECFIS_RFIS_OFFSET;
     2827                cbFis = AHCI_CMDFIS_TYPE_D2H_SIZE;
    28652828                break;
     2829            }
    28662830            case AHCI_CMDFIS_TYPE_SETDEVBITS:
    2867                 {
    2868                     GCPhysAddrRecFis += AHCI_RECFIS_SDBFIS_OFFSET;
    2869                     cbFis = AHCI_CMDFIS_TYPE_SETDEVBITS_SIZE;
    2870                 }
     2831            {
     2832                GCPhysAddrRecFis += AHCI_RECFIS_SDBFIS_OFFSET;
     2833                cbFis = AHCI_CMDFIS_TYPE_SETDEVBITS_SIZE;
    28712834                break;
     2835            }
    28722836            case AHCI_CMDFIS_TYPE_DMASETUP:
    2873                 {
    2874                     GCPhysAddrRecFis += AHCI_RECFIS_DSFIS_OFFSET;
    2875                     cbFis = AHCI_CMDFIS_TYPE_DMASETUP_SIZE;
    2876                 }
     2837            {
     2838                GCPhysAddrRecFis += AHCI_RECFIS_DSFIS_OFFSET;
     2839                cbFis = AHCI_CMDFIS_TYPE_DMASETUP_SIZE;
    28772840                break;
     2841            }
    28782842            case AHCI_CMDFIS_TYPE_PIOSETUP:
    2879                 {
    2880                     GCPhysAddrRecFis += AHCI_RECFIS_PSFIS_OFFSET;
    2881                     cbFis = AHCI_CMDFIS_TYPE_PIOSETUP_SIZE;
    2882                 }
     2843            {
     2844                GCPhysAddrRecFis += AHCI_RECFIS_PSFIS_OFFSET;
     2845                cbFis = AHCI_CMDFIS_TYPE_PIOSETUP_SIZE;
    28832846                break;
     2847            }
    28842848            default:
    28852849                /*
     
    29542918}
    29552919
    2956 static void atapiCmdOK(PAHCIPort pAhciPort, PAHCIPORTTASKSTATE pAhciPortTaskState)
    2957 {
    2958     pAhciPortTaskState->uATARegError = 0;
    2959     pAhciPortTaskState->uATARegStatus = ATA_STAT_READY | ATA_STAT_SEEK;
    2960     pAhciPortTaskState->cmdFis[AHCI_CMDFIS_SECTN] = (pAhciPortTaskState->cmdFis[AHCI_CMDFIS_SECTN] & ~7)
    2961         | ((pAhciPortTaskState->enmTxDir != AHCITXDIR_WRITE) ? ATAPI_INT_REASON_IO : 0)
    2962         | (!pAhciPortTaskState->cbTransfer ? ATAPI_INT_REASON_CD : 0);
     2920static void atapiCmdOK(PAHCIPort pAhciPort, PAHCIREQ pAhciReq)
     2921{
     2922    pAhciReq->uATARegError = 0;
     2923    pAhciReq->uATARegStatus = ATA_STAT_READY | ATA_STAT_SEEK;
     2924    pAhciReq->cmdFis[AHCI_CMDFIS_SECTN] = (pAhciReq->cmdFis[AHCI_CMDFIS_SECTN] & ~7)
     2925        | ((pAhciReq->enmTxDir != AHCITXDIR_WRITE) ? ATAPI_INT_REASON_IO : 0)
     2926        | (!pAhciReq->cbTransfer ? ATAPI_INT_REASON_CD : 0);
    29632927    memset(pAhciPort->abATAPISense, '\0', sizeof(pAhciPort->abATAPISense));
    29642928    pAhciPort->abATAPISense[0] = 0x70;
     
    29662930}
    29672931
    2968 static void atapiCmdError(PAHCIPort pAhciPort, PAHCIPORTTASKSTATE pAhciPortTaskState, const uint8_t *pabATAPISense, size_t cbATAPISense)
     2932static void atapiCmdError(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, const uint8_t *pabATAPISense, size_t cbATAPISense)
    29692933{
    29702934    Log(("%s: sense=%#x (%s) asc=%#x ascq=%#x (%s)\n", __FUNCTION__, pabATAPISense[2] & 0x0f, SCSISenseText(pabATAPISense[2] & 0x0f),
    29712935             pabATAPISense[12], pabATAPISense[13], SCSISenseExtText(pabATAPISense[12], pabATAPISense[13])));
    2972     pAhciPortTaskState->uATARegError = pabATAPISense[2] << 4;
    2973     pAhciPortTaskState->uATARegStatus = ATA_STAT_READY | ATA_STAT_ERR;
    2974     pAhciPortTaskState->cmdFis[AHCI_CMDFIS_SECTN] = (pAhciPortTaskState->cmdFis[AHCI_CMDFIS_SECTN] & ~7) |
     2936    pAhciReq->uATARegError = pabATAPISense[2] << 4;
     2937    pAhciReq->uATARegStatus = ATA_STAT_READY | ATA_STAT_ERR;
     2938    pAhciReq->cmdFis[AHCI_CMDFIS_SECTN] = (pAhciReq->cmdFis[AHCI_CMDFIS_SECTN] & ~7) |
    29752939                                                     ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD;
    29762940    memset(pAhciPort->abATAPISense, '\0', sizeof(pAhciPort->abATAPISense));
     
    29802944/** @todo deprecated function - doesn't provide enough info. Replace by direct
    29812945 * calls to atapiCmdError()  with full data. */
    2982 static void atapiCmdErrorSimple(PAHCIPort pAhciPort, PAHCIPORTTASKSTATE pAhciPortTaskState, uint8_t uATAPISenseKey, uint8_t uATAPIASC)
     2946static void atapiCmdErrorSimple(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, uint8_t uATAPISenseKey, uint8_t uATAPIASC)
    29832947{
    29842948    uint8_t abATAPISense[ATAPI_SENSE_SIZE];
     
    29882952    abATAPISense[7] = 10;
    29892953    abATAPISense[12] = uATAPIASC;
    2990     atapiCmdError(pAhciPort, pAhciPortTaskState, abATAPISense, sizeof(abATAPISense));
     2954    atapiCmdError(pAhciPort, pAhciReq, abATAPISense, sizeof(abATAPISense));
    29912955}
    29922956
     
    31203084}
    31213085
    3122 typedef int (*PAtapiFunc)(PAHCIPORTTASKSTATE, PAHCIPort, int *);
    3123 
    3124 static int atapiGetConfigurationSS(PAHCIPORTTASKSTATE, PAHCIPort, int *);
    3125 static int atapiGetEventStatusNotificationSS(PAHCIPORTTASKSTATE, PAHCIPort, int *);
    3126 static int atapiIdentifySS(PAHCIPORTTASKSTATE, PAHCIPort, int *);
    3127 static int atapiInquirySS(PAHCIPORTTASKSTATE, PAHCIPort, int *);
    3128 static int atapiMechanismStatusSS(PAHCIPORTTASKSTATE, PAHCIPort, int *);
    3129 static int atapiModeSenseErrorRecoverySS(PAHCIPORTTASKSTATE, PAHCIPort, int *);
    3130 static int atapiModeSenseCDStatusSS(PAHCIPORTTASKSTATE, PAHCIPort, int *);
    3131 static int atapiReadCapacitySS(PAHCIPORTTASKSTATE, PAHCIPort, int *);
    3132 static int atapiReadDiscInformationSS(PAHCIPORTTASKSTATE, PAHCIPort, int *);
    3133 static int atapiReadTOCNormalSS(PAHCIPORTTASKSTATE, PAHCIPort, int *);
    3134 static int atapiReadTOCMultiSS(PAHCIPORTTASKSTATE, PAHCIPort, int *);
    3135 static int atapiReadTOCRawSS(PAHCIPORTTASKSTATE, PAHCIPort, int *);
    3136 static int atapiReadTrackInformationSS(PAHCIPORTTASKSTATE, PAHCIPort, int *);
    3137 static int atapiRequestSenseSS(PAHCIPORTTASKSTATE, PAHCIPort, int *);
    3138 static int atapiPassthroughSS(PAHCIPORTTASKSTATE, PAHCIPort, int *);
     3086typedef int (*PAtapiFunc)(PAHCIREQ, PAHCIPort, size_t, size_t *);
     3087
     3088static int atapiGetConfigurationSS(PAHCIREQ, PAHCIPort, size_t, size_t *);
     3089static int atapiGetEventStatusNotificationSS(PAHCIREQ, PAHCIPort, size_t, size_t *);
     3090static int atapiIdentifySS(PAHCIREQ, PAHCIPort, size_t, size_t *);
     3091static int atapiInquirySS(PAHCIREQ, PAHCIPort, size_t, size_t *);
     3092static int atapiMechanismStatusSS(PAHCIREQ, PAHCIPort, size_t, size_t *);
     3093static int atapiModeSenseErrorRecoverySS(PAHCIREQ, PAHCIPort, size_t, size_t *);
     3094static int atapiModeSenseCDStatusSS(PAHCIREQ, PAHCIPort, size_t, size_t *);
     3095static int atapiReadCapacitySS(PAHCIREQ, PAHCIPort, size_t, size_t *);
     3096static int atapiReadDiscInformationSS(PAHCIREQ, PAHCIPort, size_t, size_t *);
     3097static int atapiReadTOCNormalSS(PAHCIREQ, PAHCIPort, size_t, size_t *);
     3098static int atapiReadTOCMultiSS(PAHCIREQ, PAHCIPort, size_t, size_t *);
     3099static int atapiReadTOCRawSS(PAHCIREQ, PAHCIPort, size_t, size_t *);
     3100static int atapiReadTrackInformationSS(PAHCIREQ, PAHCIPort, size_t, size_t *);
     3101static int atapiRequestSenseSS(PAHCIREQ, PAHCIPort, size_t, size_t *);
     3102static int atapiPassthroughSS(PAHCIREQ, PAHCIPort, size_t, size_t *);
    31393103
    31403104/**
     
    31863150};
    31873151
    3188 static int atapiIdentifySS(PAHCIPORTTASKSTATE pAhciPortTaskState, PAHCIPort pAhciPort, int *pcbData)
     3152static int atapiIdentifySS(PAHCIREQ pAhciReq, PAHCIPort pAhciPort, size_t cbData, size_t *pcbData)
    31893153{
    31903154    uint16_t p[256];
     
    32273191
    32283192    /* Copy the buffer in to the scatter gather list. */
    3229     *pcbData =  ahciScatterGatherListCopyFromBuffer(pAhciPortTaskState, (void *)&p[0], sizeof(p));
    3230 
    3231     atapiCmdOK(pAhciPort, pAhciPortTaskState);
     3193    *pcbData =  ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, (void *)&p[0],
     3194                                RT_MIN(cbData, sizeof(p)));
     3195
     3196    atapiCmdOK(pAhciPort, pAhciReq);
    32323197    return VINF_SUCCESS;
    32333198}
    32343199
    3235 static int atapiReadCapacitySS(PAHCIPORTTASKSTATE pAhciPortTaskState, PAHCIPort pAhciPort, int *pcbData)
     3200static int atapiReadCapacitySS(PAHCIREQ pAhciReq, PAHCIPort pAhciPort, size_t cbData, size_t *pcbData)
    32363201{
    32373202    uint8_t aBuf[8];
     
    32413206
    32423207    /* Copy the buffer in to the scatter gather list. */
    3243     *pcbData = ahciScatterGatherListCopyFromBuffer(pAhciPortTaskState, (void *)&aBuf[0], sizeof(aBuf));
    3244 
    3245     atapiCmdOK(pAhciPort, pAhciPortTaskState);
     3208    *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, (void *)&aBuf[0],
     3209                               RT_MIN(cbData, sizeof(aBuf)));
     3210
     3211    atapiCmdOK(pAhciPort, pAhciReq);
    32463212    return VINF_SUCCESS;
    32473213}
    32483214
    32493215
    3250 static int atapiReadDiscInformationSS(PAHCIPORTTASKSTATE pAhciPortTaskState, PAHCIPort pAhciPort, int *pcbData)
     3216static int atapiReadDiscInformationSS(PAHCIREQ pAhciReq, PAHCIPort pAhciPort, size_t cbData, size_t *pcbData)
    32513217{
    32523218    uint8_t aBuf[34];
     
    32683234
    32693235    /* Copy the buffer in to the scatter gather list. */
    3270     *pcbData = ahciScatterGatherListCopyFromBuffer(pAhciPortTaskState, (void *)&aBuf[0], sizeof(aBuf));
    3271 
    3272     atapiCmdOK(pAhciPort, pAhciPortTaskState);
     3236    *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, (void *)&aBuf[0],
     3237                               RT_MIN(cbData, sizeof(aBuf)));
     3238
     3239    atapiCmdOK(pAhciPort, pAhciReq);
    32733240    return VINF_SUCCESS;
    32743241}
    32753242
    32763243
    3277 static int atapiReadTrackInformationSS(PAHCIPORTTASKSTATE pAhciPortTaskState, PAHCIPort pAhciPort, int *pcbData)
     3244static int atapiReadTrackInformationSS(PAHCIREQ pAhciReq, PAHCIPort pAhciPort, size_t cbData, size_t *pcbData)
    32783245{
    32793246    uint8_t aBuf[36];
    32803247
    32813248    /* Accept address/number type of 1 only, and only track 1 exists. */
    3282     if ((pAhciPortTaskState->aATAPICmd[1] & 0x03) != 1 || ataBE2H_U32(&pAhciPortTaskState->aATAPICmd[2]) != 1)
    3283     {
    3284         atapiCmdErrorSimple(pAhciPort, pAhciPortTaskState, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
     3249    if ((pAhciReq->aATAPICmd[1] & 0x03) != 1 || ataBE2H_U32(&pAhciReq->aATAPICmd[2]) != 1)
     3250    {
     3251        atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
    32853252        return VINF_SUCCESS;
    32863253    }
     
    32983265
    32993266    /* Copy the buffer in to the scatter gather list. */
    3300     *pcbData = ahciScatterGatherListCopyFromBuffer(pAhciPortTaskState, (void *)&aBuf[0], sizeof(aBuf));
    3301 
    3302     atapiCmdOK(pAhciPort, pAhciPortTaskState);
     3267    *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, (void *)&aBuf[0],
     3268                               RT_MIN(cbData, sizeof(aBuf)));
     3269
     3270    atapiCmdOK(pAhciPort, pAhciReq);
    33033271    return VINF_SUCCESS;
    33043272}
     
    34213389}
    34223390
    3423 static int atapiGetConfigurationSS(PAHCIPORTTASKSTATE pAhciPortTaskState, PAHCIPort pAhciPort, int *pcbData)
     3391static int atapiGetConfigurationSS(PAHCIREQ pAhciReq, PAHCIPort pAhciPort, size_t cbData, size_t *pcbData)
    34243392{
    34253393    uint8_t aBuf[80];
     
    34293397
    34303398    /* Accept valid request types only, and only starting feature 0. */
    3431     if ((pAhciPortTaskState->aATAPICmd[1] & 0x03) == 3 || ataBE2H_U16(&pAhciPortTaskState->aATAPICmd[2]) != 0)
    3432     {
    3433         atapiCmdErrorSimple(pAhciPort, pAhciPortTaskState, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
     3399    if ((pAhciReq->aATAPICmd[1] & 0x03) == 3 || ataBE2H_U16(&pAhciReq->aATAPICmd[2]) != 0)
     3400    {
     3401        atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
    34343402        return VINF_SUCCESS;
    34353403    }
     
    34793447
    34803448    /* Copy the buffer in to the scatter gather list. */
    3481     *pcbData = ahciScatterGatherListCopyFromBuffer(pAhciPortTaskState, (void *)&aBuf[0], sizeof(aBuf));
    3482 
    3483     atapiCmdOK(pAhciPort, pAhciPortTaskState);
     3449    *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, (void *)&aBuf[0],
     3450                               RT_MIN(cbData, sizeof(aBuf)));
     3451
     3452    atapiCmdOK(pAhciPort, pAhciReq);
    34843453    return VINF_SUCCESS;
    34853454}
    34863455
    34873456
    3488 static int atapiGetEventStatusNotificationSS(PAHCIPORTTASKSTATE pAhciPortTaskState, PAHCIPort pAhciPort, int *pcbData)
     3457static int atapiGetEventStatusNotificationSS(PAHCIREQ pAhciReq, PAHCIPort pAhciPort, size_t cbData, size_t *pcbData)
    34893458{
    34903459    uint8_t abBuf[8];
    34913460
    3492     Assert(pAhciPortTaskState->enmTxDir == AHCITXDIR_READ);
    3493     Assert(pAhciPortTaskState->cbTransfer <= 8);
    3494 
    3495     if (!(pAhciPortTaskState->aATAPICmd[1] & 1))
     3461    Assert(pAhciReq->enmTxDir == AHCITXDIR_READ);
     3462    Assert(pAhciReq->cbTransfer <= 8);
     3463
     3464    if (!(pAhciReq->aATAPICmd[1] & 1))
    34963465    {
    34973466        /* no asynchronous operation supported */
    3498         atapiCmdErrorSimple(pAhciPort, pAhciPortTaskState, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
     3467        atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
    34993468        return VINF_SUCCESS;
    35003469    }
     
    35553524    } while (!ASMAtomicCmpXchgU32(&pAhciPort->MediaEventStatus, NewStatus, OldStatus));
    35563525
    3557     *pcbData = ahciScatterGatherListCopyFromBuffer(pAhciPortTaskState, (void *)&abBuf[0], sizeof(abBuf));
    3558 
    3559     atapiCmdOK(pAhciPort, pAhciPortTaskState);
     3526    *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, (void *)&abBuf[0],
     3527                               RT_MIN(cbData, sizeof(abBuf)));
     3528
     3529    atapiCmdOK(pAhciPort, pAhciReq);
    35603530    return VINF_SUCCESS;
    35613531}
    35623532
    35633533
    3564 static int atapiInquirySS(PAHCIPORTTASKSTATE pAhciPortTaskState, PAHCIPort pAhciPort, int *pcbData)
     3534static int atapiInquirySS(PAHCIREQ pAhciReq, PAHCIPort pAhciPort, size_t cbData, size_t *pcbData)
    35653535{
    35663536    uint8_t aBuf[36];
     
    35793549
    35803550    /* Copy the buffer in to the scatter gather list. */
    3581     *pcbData = ahciScatterGatherListCopyFromBuffer(pAhciPortTaskState, (void *)&aBuf[0], sizeof(aBuf));
    3582 
    3583     atapiCmdOK(pAhciPort, pAhciPortTaskState);
     3551    *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, (void *)&aBuf[0],
     3552                               RT_MIN(cbData, sizeof(aBuf)));
     3553
     3554    atapiCmdOK(pAhciPort, pAhciReq);
    35843555    return VINF_SUCCESS;
    35853556}
    35863557
    35873558
    3588 static int atapiModeSenseErrorRecoverySS(PAHCIPORTTASKSTATE pAhciPortTaskState, PAHCIPort pAhciPort, int *pcbData)
     3559static int atapiModeSenseErrorRecoverySS(PAHCIREQ pAhciReq, PAHCIPort pAhciPort, size_t cbData, size_t *pcbData)
    35893560{
    35903561    uint8_t aBuf[16];
     
    36083579
    36093580    /* Copy the buffer in to the scatter gather list. */
    3610     *pcbData = ahciScatterGatherListCopyFromBuffer(pAhciPortTaskState, (void *)&aBuf[0], sizeof(aBuf));
    3611 
    3612     atapiCmdOK(pAhciPort, pAhciPortTaskState);
     3581    *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, (void *)&aBuf[0],
     3582                               RT_MIN(cbData, sizeof(aBuf)));
     3583
     3584    atapiCmdOK(pAhciPort, pAhciReq);
    36133585    return VINF_SUCCESS;
    36143586}
    36153587
    36163588
    3617 static int atapiModeSenseCDStatusSS(PAHCIPORTTASKSTATE pAhciPortTaskState, PAHCIPort pAhciPort, int *pcbData)
     3589static int atapiModeSenseCDStatusSS(PAHCIREQ pAhciReq, PAHCIPort pAhciPort, size_t cbData, size_t *pcbData)
    36183590{
    36193591    uint8_t aBuf[40];
     
    36583630
    36593631    /* Copy the buffer in to the scatter gather list. */
    3660     *pcbData = ahciScatterGatherListCopyFromBuffer(pAhciPortTaskState, (void *)&aBuf[0], sizeof(aBuf));
    3661 
    3662     atapiCmdOK(pAhciPort, pAhciPortTaskState);
     3632    *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, (void *)&aBuf[0],
     3633                               RT_MIN(cbData, sizeof(aBuf)));
     3634
     3635    atapiCmdOK(pAhciPort, pAhciReq);
    36633636    return VINF_SUCCESS;
    36643637}
    36653638
    36663639
    3667 static int atapiRequestSenseSS(PAHCIPORTTASKSTATE pAhciPortTaskState, PAHCIPort pAhciPort, int *pcbData)
     3640static int atapiRequestSenseSS(PAHCIREQ pAhciReq, PAHCIPort pAhciPort, size_t cbData, size_t *pcbData)
    36683641{
    36693642    /* Copy the buffer in to the scatter gather list. */
    3670     *pcbData = ahciScatterGatherListCopyFromBuffer(pAhciPortTaskState, pAhciPort->abATAPISense, sizeof(pAhciPort->abATAPISense));
    3671 
    3672     atapiCmdOK(pAhciPort, pAhciPortTaskState);
     3643    *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq,
     3644                               pAhciPort->abATAPISense, RT_MIN(cbData, sizeof(pAhciPort->abATAPISense)));
     3645
     3646    atapiCmdOK(pAhciPort, pAhciReq);
    36733647    return VINF_SUCCESS;
    36743648}
    36753649
    36763650
    3677 static int atapiMechanismStatusSS(PAHCIPORTTASKSTATE pAhciPortTaskState, PAHCIPort pAhciPort, int *pcbData)
     3651static int atapiMechanismStatusSS(PAHCIREQ pAhciReq, PAHCIPort pAhciPort, size_t cbData, size_t *pcbData)
    36783652{
    36793653    uint8_t aBuf[8];
     
    36883662
    36893663    /* Copy the buffer in to the scatter gather list. */
    3690     *pcbData = ahciScatterGatherListCopyFromBuffer(pAhciPortTaskState, (void *)&aBuf[0], sizeof(aBuf));
    3691 
    3692     atapiCmdOK(pAhciPort, pAhciPortTaskState);
     3664    *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, (void *)&aBuf[0],
     3665                               RT_MIN(cbData, sizeof(aBuf)));
     3666
     3667    atapiCmdOK(pAhciPort, pAhciReq);
    36933668    return VINF_SUCCESS;
    36943669}
    36953670
    36963671
    3697 static int atapiReadTOCNormalSS(PAHCIPORTTASKSTATE pAhciPortTaskState, PAHCIPort pAhciPort, int *pcbData)
     3672static int atapiReadTOCNormalSS(PAHCIREQ pAhciReq, PAHCIPort pAhciPort, size_t cbData, size_t *pcbData)
    36983673{
    36993674    uint8_t aBuf[20], *q, iStartTrack;
     
    37013676    uint32_t cbSize;
    37023677
    3703     fMSF = (pAhciPortTaskState->aATAPICmd[1] >> 1) & 1;
    3704     iStartTrack = pAhciPortTaskState->aATAPICmd[6];
     3678    fMSF = (pAhciReq->aATAPICmd[1] >> 1) & 1;
     3679    iStartTrack = pAhciReq->aATAPICmd[6];
    37053680    if (iStartTrack > 1 && iStartTrack != 0xaa)
    37063681    {
    3707         atapiCmdErrorSimple(pAhciPort, pAhciPortTaskState, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
     3682        atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
    37083683        return VINF_SUCCESS;
    37093684    }
     
    37503725
    37513726    /* Copy the buffer in to the scatter gather list. */
    3752     *pcbData = ahciScatterGatherListCopyFromBuffer(pAhciPortTaskState, (void *)&aBuf[0], cbSize);
    3753 
    3754     atapiCmdOK(pAhciPort, pAhciPortTaskState);
     3727    *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, (void *)&aBuf[0],
     3728                               RT_MIN(cbData, cbSize));
     3729
     3730    atapiCmdOK(pAhciPort, pAhciReq);
    37553731    return VINF_SUCCESS;
    37563732}
    37573733
    37583734
    3759 static int atapiReadTOCMultiSS(PAHCIPORTTASKSTATE pAhciPortTaskState, PAHCIPort pAhciPort, int *pcbData)
     3735static int atapiReadTOCMultiSS(PAHCIREQ pAhciReq, PAHCIPort pAhciPort, size_t cbData, size_t *pcbData)
    37603736{
    37613737    uint8_t aBuf[12];
    37623738    bool fMSF;
    37633739
    3764     fMSF = (pAhciPortTaskState->aATAPICmd[1] >> 1) & 1;
     3740    fMSF = (pAhciReq->aATAPICmd[1] >> 1) & 1;
    37653741    /* multi session: only a single session defined */
    37663742/** @todo double-check this stuff against what a real drive says for a CD-ROM (not a CD-R) with only a single data session. Maybe solve the problem with "cdrdao read-toc" not being able to figure out whether numbers are in BCD or hex. */
     
    37833759
    37843760    /* Copy the buffer in to the scatter gather list. */
    3785     *pcbData = ahciScatterGatherListCopyFromBuffer(pAhciPortTaskState, (void *)&aBuf[0], sizeof(aBuf));
    3786 
    3787     atapiCmdOK(pAhciPort, pAhciPortTaskState);
     3761    *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, (void *)&aBuf[0],
     3762                               RT_MIN(cbData, sizeof(aBuf)));
     3763
     3764    atapiCmdOK(pAhciPort, pAhciReq);
    37883765    return VINF_SUCCESS;
    37893766}
    37903767
    37913768
    3792 static int atapiReadTOCRawSS(PAHCIPORTTASKSTATE pAhciPortTaskState, PAHCIPort pAhciPort, int *pcbData)
     3769static int atapiReadTOCRawSS(PAHCIREQ pAhciReq, PAHCIPort pAhciPort, size_t cbData, size_t *pcbData)
    37933770{
    37943771    uint8_t aBuf[50]; /* Counted a maximum of 45 bytes but better be on the safe side. */
     
    37973774    uint32_t cbSize;
    37983775
    3799     fMSF = (pAhciPortTaskState->aATAPICmd[1] >> 1) & 1;
    3800     iStartTrack = pAhciPortTaskState->aATAPICmd[6];
     3776    fMSF = (pAhciReq->aATAPICmd[1] >> 1) & 1;
     3777    iStartTrack = pAhciReq->aATAPICmd[6];
    38013778
    38023779    q = aBuf + 2;
     
    38713848
    38723849    /* Copy the buffer in to the scatter gather list. */
    3873     *pcbData = ahciScatterGatherListCopyFromBuffer(pAhciPortTaskState, (void *)&aBuf[0], cbSize);
    3874 
    3875     atapiCmdOK(pAhciPort, pAhciPortTaskState);
     3850    *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, (void *)&aBuf[0],
     3851                               RT_MIN(cbData, cbSize));
     3852
     3853    atapiCmdOK(pAhciPort, pAhciReq);
    38763854    return VINF_SUCCESS;
    38773855}
     
    38853863}
    38863864
    3887 static int atapiPassthroughSS(PAHCIPORTTASKSTATE pAhciPortTaskState, PAHCIPort pAhciPort, int *pcbData)
     3865static int atapiPassthroughSS(PAHCIREQ pAhciReq, PAHCIPort pAhciPort, size_t cbData, size_t *pcbData)
    38883866{
    38893867    int rc = VINF_SUCCESS;
    38903868    uint8_t abATAPISense[ATAPI_SENSE_SIZE];
    38913869    uint32_t cbTransfer;
    3892 
    3893     cbTransfer = pAhciPortTaskState->cbTransfer;
     3870    void *pvBuf = NULL;
     3871
     3872    cbTransfer = pAhciReq->cbTransfer;
     3873
     3874    if (cbTransfer)
     3875    {
     3876        pvBuf = (uint8_t *)RTMemAlloc(cbTransfer);
     3877        if (!pvBuf)
     3878            return VERR_NO_MEMORY;
     3879
     3880        if (pAhciReq->enmTxDir == AHCITXDIR_WRITE)
     3881        {
     3882            ahciCopyFromPrdtl(pAhciPort->pDevInsR3, pAhciReq, pvBuf, cbTransfer);
     3883            if (pAhciReq->fFlags & AHCI_REQ_OVERFLOW)
     3884                return VINF_SUCCESS;
     3885        }
     3886    }
    38943887
    38953888    /* Simple heuristics: if there is at least one sector of data
     
    38973890    if (cbTransfer >= 2048)
    38983891    {
    3899         if (pAhciPortTaskState->enmTxDir != AHCITXDIR_WRITE)
     3892        if (pAhciReq->enmTxDir != AHCITXDIR_WRITE)
    39003893            pAhciPort->Led.Asserted.s.fReading = pAhciPort->Led.Actual.s.fReading = 1;
    39013894        else
     
    39103903        uint8_t aATAPICmd[ATAPI_PACKET_SIZE];
    39113904        uint32_t iATAPILBA, cSectors, cReqSectors, cbCurrTX;
    3912         uint8_t *pbBuf = (uint8_t *)pAhciPortTaskState->pSGListHead[0].pvSeg;
    3913 
    3914         Assert(pAhciPortTaskState->cSGListUsed == 1);
    3915 
    3916         switch (pAhciPortTaskState->aATAPICmd[0])
     3905        uint8_t *pbBuf = (uint8_t *)pvBuf;
     3906
     3907        switch (pAhciReq->aATAPICmd[0])
    39173908        {
    39183909            case SCSI_READ_10:
    39193910            case SCSI_WRITE_10:
    39203911            case SCSI_WRITE_AND_VERIFY_10:
    3921                 iATAPILBA = ataBE2H_U32(pAhciPortTaskState->aATAPICmd + 2);
    3922                 cSectors = ataBE2H_U16(pAhciPortTaskState->aATAPICmd + 7);
     3912                iATAPILBA = ataBE2H_U32(pAhciReq->aATAPICmd + 2);
     3913                cSectors = ataBE2H_U16(pAhciReq->aATAPICmd + 7);
    39233914                break;
    39243915            case SCSI_READ_12:
    39253916            case SCSI_WRITE_12:
    3926                 iATAPILBA = ataBE2H_U32(pAhciPortTaskState->aATAPICmd + 2);
    3927                 cSectors = ataBE2H_U32(pAhciPortTaskState->aATAPICmd + 6);
     3917                iATAPILBA = ataBE2H_U32(pAhciReq->aATAPICmd + 2);
     3918                cSectors = ataBE2H_U32(pAhciReq->aATAPICmd + 6);
    39283919                break;
    39293920            case SCSI_READ_CD:
    3930                 iATAPILBA = ataBE2H_U32(pAhciPortTaskState->aATAPICmd + 2);
    3931                 cSectors = ataBE2H_U24(pAhciPortTaskState->aATAPICmd + 6);
     3921                iATAPILBA = ataBE2H_U32(pAhciReq->aATAPICmd + 2);
     3922                cSectors = ataBE2H_U24(pAhciReq->aATAPICmd + 6);
    39323923                break;
    39333924            case SCSI_READ_CD_MSF:
    3934                 iATAPILBA = ataMSF2LBA(pAhciPortTaskState->aATAPICmd + 3);
    3935                 cSectors = ataMSF2LBA(pAhciPortTaskState->aATAPICmd + 6) - iATAPILBA;
     3925                iATAPILBA = ataMSF2LBA(pAhciReq->aATAPICmd + 3);
     3926                cSectors = ataMSF2LBA(pAhciReq->aATAPICmd + 6) - iATAPILBA;
    39363927                break;
    39373928            default:
    3938                 AssertMsgFailed(("Don't know how to split command %#04x\n", pAhciPortTaskState->aATAPICmd[0]));
     3929                AssertMsgFailed(("Don't know how to split command %#04x\n", pAhciReq->aATAPICmd[0]));
    39393930                if (pAhciPort->cErrors++ < MAX_LOG_REL_ERRORS)
    39403931                    LogRel(("AHCI: LUN#%d: CD-ROM passthrough split error\n", pAhciPort->iLUN));
    3941                 atapiCmdErrorSimple(pAhciPort, pAhciPortTaskState, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_ILLEGAL_OPCODE);
    3942                 return false;
    3943         }
    3944         memcpy(aATAPICmd, pAhciPortTaskState->aATAPICmd, ATAPI_PACKET_SIZE);
     3932                atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_ILLEGAL_OPCODE);
     3933                RTMemFree(pvBuf);
     3934                return VINF_SUCCESS;
     3935        }
     3936        memcpy(aATAPICmd, pAhciReq->aATAPICmd, ATAPI_PACKET_SIZE);
    39453937        cReqSectors = 0;
    39463938        for (uint32_t i = cSectors; i > 0; i -= cReqSectors)
    39473939        {
    3948             if (i * pAhciPortTaskState->cbATAPISector > SCSI_MAX_BUFFER_SIZE)
    3949                 cReqSectors = SCSI_MAX_BUFFER_SIZE / pAhciPortTaskState->cbATAPISector;
     3940            if (i * pAhciReq->cbATAPISector > SCSI_MAX_BUFFER_SIZE)
     3941                cReqSectors = SCSI_MAX_BUFFER_SIZE / pAhciReq->cbATAPISector;
    39503942            else
    39513943                cReqSectors = i;
    3952             cbCurrTX = pAhciPortTaskState->cbATAPISector * cReqSectors;
    3953             switch (pAhciPortTaskState->aATAPICmd[0])
     3944            cbCurrTX = pAhciReq->cbATAPISector * cReqSectors;
     3945            switch (pAhciReq->aATAPICmd[0])
    39543946            {
    39553947                case SCSI_READ_10:
     
    39753967            rc = pAhciPort->pDrvBlock->pfnSendCmd(pAhciPort->pDrvBlock,
    39763968                                                  aATAPICmd,
    3977                                                   pAhciPortTaskState->enmTxDir == AHCITXDIR_READ
     3969                                                  pAhciReq->enmTxDir == AHCITXDIR_READ
    39783970                                                  ? PDMBLOCKTXDIR_FROM_DEVICE
    39793971                                                  : PDMBLOCKTXDIR_TO_DEVICE,
     
    39863978                break;
    39873979            iATAPILBA += cReqSectors;
    3988             pbBuf += pAhciPortTaskState->cbATAPISector * cReqSectors;
     3980            pbBuf += pAhciReq->cbATAPISector * cReqSectors;
    39893981        }
    39903982    }
     
    39933985        PDMBLOCKTXDIR enmBlockTxDir = PDMBLOCKTXDIR_NONE;
    39943986
    3995         if (pAhciPortTaskState->enmTxDir == AHCITXDIR_READ)
     3987        if (pAhciReq->enmTxDir == AHCITXDIR_READ)
    39963988            enmBlockTxDir = PDMBLOCKTXDIR_FROM_DEVICE;
    3997         else if (pAhciPortTaskState->enmTxDir == AHCITXDIR_WRITE)
     3989        else if (pAhciReq->enmTxDir == AHCITXDIR_WRITE)
    39983990            enmBlockTxDir = PDMBLOCKTXDIR_TO_DEVICE;
    3999         else if (pAhciPortTaskState->enmTxDir == AHCITXDIR_NONE)
     3991        else if (pAhciReq->enmTxDir == AHCITXDIR_NONE)
    40003992            enmBlockTxDir = PDMBLOCKTXDIR_NONE;
    40013993        else
    4002             AssertMsgFailed(("Invalid transfer direction %d\n", pAhciPortTaskState->enmTxDir));
     3994            AssertMsgFailed(("Invalid transfer direction %d\n", pAhciReq->enmTxDir));
    40033995
    40043996        rc = pAhciPort->pDrvBlock->pfnSendCmd(pAhciPort->pDrvBlock,
    4005                                               pAhciPortTaskState->aATAPICmd,
     3997                                              pAhciReq->aATAPICmd,
    40063998                                              enmBlockTxDir,
    4007                                               pAhciPortTaskState->pSGListHead[0].pvSeg,
     3999                                              pvBuf,
    40084000                                              &cbTransfer,
    40094001                                              abATAPISense,
     
    40154007    if (cbTransfer >= 2048)
    40164008    {
    4017         if (pAhciPortTaskState->enmTxDir != AHCITXDIR_WRITE)
     4009        if (pAhciReq->enmTxDir != AHCITXDIR_WRITE)
    40184010        {
    40194011            pAhciPort->Led.Actual.s.fReading = 0;
     
    40294021    if (RT_SUCCESS(rc))
    40304022    {
    4031        Assert(cbTransfer <= pAhciPortTaskState->cbTransfer);
    4032        /* Reply with the same amount of data as the real drive. */
    4033        *pcbData = cbTransfer;
    4034 
    4035         if (pAhciPortTaskState->enmTxDir == AHCITXDIR_READ)
    4036         {
    4037             if (pAhciPortTaskState->aATAPICmd[0] == SCSI_INQUIRY)
     4023       Assert(cbTransfer <= pAhciReq->cbTransfer);
     4024
     4025        if (pAhciReq->enmTxDir == AHCITXDIR_READ)
     4026        {
     4027            if (pAhciReq->aATAPICmd[0] == SCSI_INQUIRY)
    40384028            {
    40394029                /* Make sure that the real drive cannot be identified.
    40404030                 * Motivation: changing the VM configuration should be as
    40414031                 *             invisible as possible to the guest. */
    4042                 ataSCSIPadStr((uint8_t *)pAhciPortTaskState->pSGListHead[0].pvSeg + 8, "VBOX", 8);
    4043                 ataSCSIPadStr((uint8_t *)pAhciPortTaskState->pSGListHead[0].pvSeg + 16, "CD-ROM", 16);
    4044                 ataSCSIPadStr((uint8_t *)pAhciPortTaskState->pSGListHead[0].pvSeg + 32, "1.0", 4);
     4032                if (cbTransfer >= 8 + 8)
     4033                    ataSCSIPadStr((uint8_t *)pvBuf + 8, "VBOX", 8);
     4034                if (cbTransfer >= 16 + 16)
     4035                    ataSCSIPadStr((uint8_t *)pvBuf + 16, "CD-ROM", 16);
     4036                if (cbTransfer >= 32 + 4)
     4037                    ataSCSIPadStr((uint8_t *)pvBuf + 32, "1.0", 4);
    40454038            }
    4046             else if (pAhciPortTaskState->aATAPICmd[0] == SCSI_READ_TOC_PMA_ATIP)
     4039            else if (pAhciReq->aATAPICmd[0] == SCSI_READ_TOC_PMA_ATIP)
    40474040            {
    40484041                /* Set the media type if we can detect it. */
    4049                 uint8_t *pbBuf = (uint8_t *)pAhciPortTaskState->pSGListHead[0].pvSeg;
     4042                uint8_t *pbBuf = (uint8_t *)pvBuf;
    40504043
    40514044                /** @todo: Implemented only for formatted TOC now. */
    4052                 if (   (pAhciPortTaskState->aATAPICmd[1] & 0xf) == 0
     4045                if (   (pAhciReq->aATAPICmd[1] & 0xf) == 0
    40534046                    && cbTransfer >= 6)
    40544047                {
     
    40734066                    ataMediumTypeSet(pAhciPort, ATA_MEDIA_TYPE_UNKNOWN);
    40744067            }
     4068
    40754069            if (cbTransfer)
    4076                 Log3(("ATAPI PT data read (%d): %.*Rhxs\n", cbTransfer, cbTransfer, (uint8_t *)pAhciPortTaskState->pSGListHead[0].pvSeg));
    4077         }
    4078         atapiCmdOK(pAhciPort, pAhciPortTaskState);
     4070            {
     4071                Log3(("ATAPI PT data read (%d): %.*Rhxs\n", cbTransfer, cbTransfer, (uint8_t *)pvBuf));
     4072
     4073                /* Reply with the same amount of data as the real drive. */
     4074                *pcbData = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq, pvBuf,
     4075                                           cbTransfer);
     4076            }
     4077            else
     4078                *pcbData = 0;
     4079        }
     4080        else
     4081            *pcbData = cbTransfer;
     4082        atapiCmdOK(pAhciPort, pAhciReq);
    40794083    }
    40804084    else
     
    40824086        if (pAhciPort->cErrors < MAX_LOG_REL_ERRORS)
    40834087        {
    4084             uint8_t u8Cmd = pAhciPortTaskState->aATAPICmd[0];
     4088            uint8_t u8Cmd = pAhciReq->aATAPICmd[0];
    40854089            do
    40864090            {
     
    40974101            } while (0);
    40984102        }
    4099         atapiCmdError(pAhciPort, pAhciPortTaskState, abATAPISense, sizeof(abATAPISense));
    4100     }
    4101     return false;
    4102 }
    4103 
    4104 static int atapiDoTransfer(PAHCIPort pAhciPort, PAHCIPORTTASKSTATE pAhciPortTaskState, ATAPIFN iSourceSink)
    4105 {
    4106     int cbTransfered = 0;
     4103        atapiCmdError(pAhciPort, pAhciReq, abATAPISense, sizeof(abATAPISense));
     4104    }
     4105
     4106    if (pvBuf)
     4107        RTMemFree(pvBuf);
     4108
     4109    return VINF_SUCCESS;
     4110}
     4111
     4112static int atapiDoTransfer(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, size_t cbMax, ATAPIFN iSourceSink)
     4113{
     4114    size_t cbTransfered = 0;
    41074115    int rc, rcSourceSink;
    41084116
    4109     /*
    4110      * Create scatter gather list. We use a safe mapping here because it is
    4111      * possible that the buffer is not a multiple of 512. The normal
    4112      * creator would assert later here.
    4113      */
    4114     ahciScatterGatherListGetTotalBufferSize(pAhciPort, pAhciPortTaskState);
    4115     if (pAhciPortTaskState->cbSGBuffers)
    4116     {
    4117         rc = ahciScatterGatherListCreateSafe(pAhciPort, pAhciPortTaskState, false, 0);
    4118         AssertRC(rc);
    4119     }
    4120 
    4121     rcSourceSink = g_apfnAtapiFuncs[iSourceSink](pAhciPortTaskState, pAhciPort, &cbTransfered);
    4122 
    4123     pAhciPortTaskState->cmdHdr.u32PRDBC = cbTransfered;
     4117    rcSourceSink = g_apfnAtapiFuncs[iSourceSink](pAhciReq, pAhciPort, cbMax,
     4118                                                 &cbTransfered);
     4119
     4120    pAhciReq->cmdHdr.u32PRDBC = cbTransfered;
     4121    pAhciReq->cbTransfer = cbTransfered;
    41244122
    41254123    LogFlow(("cbTransfered=%d\n", cbTransfered));
    41264124
    4127     if (pAhciPortTaskState->cbSGBuffers)
    4128     {
    4129         rc = ahciScatterGatherListDestroy(pAhciPort, pAhciPortTaskState);
    4130         AssertRC(rc);
    4131     }
    4132 
    41334125    /* Write updated command header into memory of the guest. */
    4134     PDMDevHlpPhysWrite(pAhciPort->CTX_SUFF(pDevIns), pAhciPortTaskState->GCPhysCmdHdrAddr, &pAhciPortTaskState->cmdHdr, sizeof(CmdHdr));
     4126    PDMDevHlpPhysWrite(pAhciPort->CTX_SUFF(pDevIns), pAhciReq->GCPhysCmdHdrAddr,
     4127                       &pAhciReq->cmdHdr, sizeof(CmdHdr));
    41354128
    41364129    return rcSourceSink;
    41374130}
    41384131
    4139 static int atapiReadSectors2352PostProcess(PAHCIPORTTASKSTATE pAhciPortTaskState)
    4140 {
    4141     uint32_t cSectors  = pAhciPortTaskState->cbTransfer / 2048;
    4142     uint32_t iATAPILBA = pAhciPortTaskState->uOffset / 2048;
    4143     uint8_t *pbBufDst  = (uint8_t *)pAhciPortTaskState->pvBufferUnaligned;
    4144     uint8_t *pbBufSrc  = (uint8_t *)pAhciPortTaskState->pSGListHead[0].pvSeg;
     4132static int atapiReadSectors2352PostProcess(PAHCIREQ pAhciReq, void **ppvProc, size_t *pcbProc)
     4133{
     4134    uint8_t *pbBuf = NULL;
     4135    uint32_t cSectors  = pAhciReq->cbTransfer / 2048;
     4136    uint32_t iATAPILBA = pAhciReq->uOffset / 2048;
     4137    uint8_t *pbBufDst;
     4138    uint8_t *pbBufSrc  = (uint8_t *)pAhciReq->u.Io.DataSeg.pvSeg;
     4139
     4140    pbBuf = (uint8_t *)RTMemAlloc(pAhciReq->cbTransfer);
     4141    if (RT_UNLIKELY(!pbBuf))
     4142        return VERR_NO_MEMORY;
     4143
     4144    pbBufDst = pbBuf;
    41454145
    41464146    for (uint32_t i = iATAPILBA; i < iATAPILBA + cSectors; i++)
     
    41634163    }
    41644164
     4165    *ppvProc = pbBuf;
     4166    *pcbProc = pAhciReq->cbTransfer;
     4167
    41654168    return VINF_SUCCESS;
    41664169}
    41674170
    4168 static int atapiReadSectors(PAHCIPort pAhciPort, PAHCIPORTTASKSTATE pAhciPortTaskState, uint32_t iATAPILBA, uint32_t cSectors, uint32_t cbSector)
     4171static int atapiReadSectors(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, uint32_t iATAPILBA, uint32_t cSectors, uint32_t cbSector)
    41694172{
    41704173    Log(("%s: %d sectors at LBA %d\n", __FUNCTION__, cSectors, iATAPILBA));
     
    41734176    {
    41744177        case 2048:
    4175             pAhciPortTaskState->uOffset = (uint64_t)iATAPILBA * cbSector;
    4176             pAhciPortTaskState->cbTransfer = cSectors * cbSector;
     4178            pAhciReq->uOffset = (uint64_t)iATAPILBA * cbSector;
     4179            pAhciReq->cbTransfer = cSectors * cbSector;
    41774180            break;
    41784181        case 2352:
    41794182        {
    4180             pAhciPortTaskState->pfnPostProcess = atapiReadSectors2352PostProcess;
    4181             pAhciPortTaskState->uOffset = (uint64_t)iATAPILBA * 2048;
    4182             pAhciPortTaskState->cbTransfer = cSectors * 2048;
     4183            pAhciReq->u.Io.pfnPostProcess = atapiReadSectors2352PostProcess;
     4184            pAhciReq->uOffset = (uint64_t)iATAPILBA * 2048;
     4185            pAhciReq->cbTransfer = cSectors * 2048;
    41834186            break;
    41844187        }
     
    41914194}
    41924195
    4193 static AHCITXDIR atapiParseCmdVirtualATAPI(PAHCIPort pAhciPort, PAHCIPORTTASKSTATE pAhciPortTaskState)
     4196static AHCITXDIR atapiParseCmdVirtualATAPI(PAHCIPort pAhciPort, PAHCIREQ pAhciReq)
    41944197{
    41954198    AHCITXDIR rc = AHCITXDIR_NONE;
     
    41974200    uint32_t cbMax;
    41984201
    4199     pbPacket = pAhciPortTaskState->aATAPICmd;
     4202    pbPacket = pAhciReq->aATAPICmd;
    42004203
    42014204    ahciLog(("%s: ATAPI CMD=%#04x \"%s\"\n", __FUNCTION__, pbPacket[0], SCSICmdText(pbPacket[0])));
     
    42074210            {
    42084211                if (pAhciPort->cNotifiedMediaChange-- > 2)
    4209                     atapiCmdErrorSimple(pAhciPort, pAhciPortTaskState, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
     4212                    atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
    42104213                else
    4211                     atapiCmdErrorSimple(pAhciPort, pAhciPortTaskState, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
     4214                    atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
    42124215            }
    42134216            else if (pAhciPort->pDrvMount->pfnIsMounted(pAhciPort->pDrvMount))
    4214                 atapiCmdOK(pAhciPort, pAhciPortTaskState);
     4217                atapiCmdOK(pAhciPort, pAhciReq);
    42154218            else
    4216                 atapiCmdErrorSimple(pAhciPort, pAhciPortTaskState, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
     4219                atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
    42174220            break;
    42184221        case SCSI_GET_EVENT_STATUS_NOTIFICATION:
    42194222            cbMax = ataBE2H_U16(pbPacket + 7);
    4220             atapiDoTransfer(pAhciPort, pAhciPortTaskState, ATAFN_SS_ATAPI_GET_EVENT_STATUS_NOTIFICATION);
     4223            atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_GET_EVENT_STATUS_NOTIFICATION);
    42214224            break;
    42224225        case SCSI_MODE_SENSE_10:
     
    42324235                        {
    42334236                            case SCSI_MODEPAGE_ERROR_RECOVERY:
    4234                                 atapiDoTransfer(pAhciPort, pAhciPortTaskState, ATAFN_SS_ATAPI_MODE_SENSE_ERROR_RECOVERY);
     4237                                atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_MODE_SENSE_ERROR_RECOVERY);
    42354238                                break;
    42364239                            case SCSI_MODEPAGE_CD_STATUS:
    4237                                 atapiDoTransfer(pAhciPort, pAhciPortTaskState, ATAFN_SS_ATAPI_MODE_SENSE_CD_STATUS);
     4240                                atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_MODE_SENSE_CD_STATUS);
    42384241                                break;
    42394242                            default:
     
    42474250                    default:
    42484251                    case SCSI_PAGECONTROL_SAVED:
    4249                         atapiCmdErrorSimple(pAhciPort, pAhciPortTaskState, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_SAVING_PARAMETERS_NOT_SUPPORTED);
     4252                        atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_SAVING_PARAMETERS_NOT_SUPPORTED);
    42504253                        break;
    42514254                }
     
    42544257        case SCSI_REQUEST_SENSE:
    42554258            cbMax = pbPacket[4];
    4256             atapiDoTransfer(pAhciPort, pAhciPortTaskState, ATAFN_SS_ATAPI_REQUEST_SENSE);
     4259            atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_REQUEST_SENSE);
    42574260            break;
    42584261        case SCSI_PREVENT_ALLOW_MEDIUM_REMOVAL:
     
    42634266                else
    42644267                    pAhciPort->pDrvMount->pfnUnlock(pAhciPort->pDrvMount);
    4265                 atapiCmdOK(pAhciPort, pAhciPortTaskState);
     4268                atapiCmdOK(pAhciPort, pAhciReq);
    42664269            }
    42674270            else
    4268                 atapiCmdErrorSimple(pAhciPort, pAhciPortTaskState, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
     4271                atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
    42694272            break;
    42704273        case SCSI_READ_10:
     
    42764279                {
    42774280                    pAhciPort->cNotifiedMediaChange-- ;
    4278                     atapiCmdErrorSimple(pAhciPort, pAhciPortTaskState, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
     4281                    atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
    42794282                    break;
    42804283                }
    42814284                else if (!pAhciPort->pDrvMount->pfnIsMounted(pAhciPort->pDrvMount))
    42824285                {
    4283                     atapiCmdErrorSimple(pAhciPort, pAhciPortTaskState, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
     4286                    atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
    42844287                    break;
    42854288                }
     
    42914294                if (cSectors == 0)
    42924295                {
    4293                     atapiCmdOK(pAhciPort, pAhciPortTaskState);
     4296                    atapiCmdOK(pAhciPort, pAhciReq);
    42944297                    break;
    42954298                }
     
    43064309                        uLastLogTS = RTTimeMilliTS();
    43074310                    }
    4308                     atapiCmdErrorSimple(pAhciPort, pAhciPortTaskState, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR);
     4311                    atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR);
    43094312                    break;
    43104313                }
    4311                 atapiReadSectors(pAhciPort, pAhciPortTaskState, iATAPILBA, cSectors, 2048);
     4314                atapiReadSectors(pAhciPort, pAhciReq, iATAPILBA, cSectors, 2048);
    43124315                rc = AHCITXDIR_READ;
    43134316            }
     
    43204323                {
    43214324                    pAhciPort->cNotifiedMediaChange-- ;
    4322                     atapiCmdErrorSimple(pAhciPort, pAhciPortTaskState, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
     4325                    atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
    43234326                    break;
    43244327                }
    43254328                else if (!pAhciPort->pDrvMount->pfnIsMounted(pAhciPort->pDrvMount))
    43264329                {
    4327                     atapiCmdErrorSimple(pAhciPort, pAhciPortTaskState, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
     4330                    atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
    43284331                    break;
    43294332                }
     
    43324335                if (cSectors == 0)
    43334336                {
    4334                     atapiCmdOK(pAhciPort, pAhciPortTaskState);
     4337                    atapiCmdOK(pAhciPort, pAhciReq);
    43354338                    break;
    43364339                }
     
    43474350                        uLastLogTS = RTTimeMilliTS();
    43484351                    }
    4349                     atapiCmdErrorSimple(pAhciPort, pAhciPortTaskState, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR);
     4352                    atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR);
    43504353                    break;
    43514354                }
     
    43544357                    case 0x00:
    43554358                        /* nothing */
    4356                         atapiCmdOK(pAhciPort, pAhciPortTaskState);
     4359                        atapiCmdOK(pAhciPort, pAhciReq);
    43574360                        break;
    43584361                    case 0x10:
    43594362                        /* normal read */
    4360                         atapiReadSectors(pAhciPort, pAhciPortTaskState, iATAPILBA, cSectors, 2048);
     4363                        atapiReadSectors(pAhciPort, pAhciReq, iATAPILBA, cSectors, 2048);
    43614364                        rc = AHCITXDIR_READ;
    43624365                        break;
    43634366                    case 0xf8:
    43644367                        /* read all data */
    4365                         atapiReadSectors(pAhciPort, pAhciPortTaskState, iATAPILBA, cSectors, 2352);
     4368                        atapiReadSectors(pAhciPort, pAhciReq, iATAPILBA, cSectors, 2352);
    43664369                        rc = AHCITXDIR_READ;
    43674370                        break;
    43684371                    default:
    43694372                        LogRel(("AHCI ATAPI: LUN#%d: CD-ROM sector format not supported\n", pAhciPort->iLUN));
    4370                         atapiCmdErrorSimple(pAhciPort, pAhciPortTaskState, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
     4373                        atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
    43714374                        break;
    43724375                }
     
    43794382                {
    43804383                    pAhciPort->cNotifiedMediaChange-- ;
    4381                     atapiCmdErrorSimple(pAhciPort, pAhciPortTaskState, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
     4384                    atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
    43824385                    break;
    43834386                }
    43844387                else if (!pAhciPort->pDrvMount->pfnIsMounted(pAhciPort->pDrvMount))
    43854388                {
    4386                     atapiCmdErrorSimple(pAhciPort, pAhciPortTaskState, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
     4389                    atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
    43874390                    break;
    43884391                }
     
    44004403                        uLastLogTS = RTTimeMilliTS();
    44014404                    }
    4402                     atapiCmdErrorSimple(pAhciPort, pAhciPortTaskState, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR);
     4405                    atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR);
    44034406                    break;
    44044407                }
    4405                 atapiCmdOK(pAhciPort, pAhciPortTaskState);
    4406                 pAhciPortTaskState->uATARegStatus |= ATA_STAT_SEEK; /* Linux expects this. */
     4408                atapiCmdOK(pAhciPort, pAhciReq);
     4409                pAhciReq->uATARegStatus |= ATA_STAT_SEEK; /* Linux expects this. */
    44074410            }
    44084411            break;
     
    44394442                }
    44404443                if (RT_SUCCESS(rc2))
    4441                     atapiCmdOK(pAhciPort, pAhciPortTaskState);
     4444                    atapiCmdOK(pAhciPort, pAhciReq);
    44424445                else
    4443                     atapiCmdErrorSimple(pAhciPort, pAhciPortTaskState, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIA_LOAD_OR_EJECT_FAILED);
     4446                    atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIA_LOAD_OR_EJECT_FAILED);
    44444447            }
    44454448            break;
     
    44474450            {
    44484451                cbMax = ataBE2H_U16(pbPacket + 8);
    4449                 atapiDoTransfer(pAhciPort, pAhciPortTaskState, ATAFN_SS_ATAPI_MECHANISM_STATUS);
     4452                atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_MECHANISM_STATUS);
    44504453            }
    44514454            break;
     
    44574460                {
    44584461                    pAhciPort->cNotifiedMediaChange-- ;
    4459                     atapiCmdErrorSimple(pAhciPort, pAhciPortTaskState, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
     4462                    atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
    44604463                    break;
    44614464                }
    44624465                else if (!pAhciPort->pDrvMount->pfnIsMounted(pAhciPort->pDrvMount))
    44634466                {
    4464                     atapiCmdErrorSimple(pAhciPort, pAhciPortTaskState, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
     4467                    atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
    44654468                    break;
    44664469                }
     
    44734476                {
    44744477                    case 0:
    4475                         atapiDoTransfer(pAhciPort, pAhciPortTaskState, ATAFN_SS_ATAPI_READ_TOC_NORMAL);
     4478                        atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_READ_TOC_NORMAL);
    44764479                        break;
    44774480                    case 1:
    4478                         atapiDoTransfer(pAhciPort, pAhciPortTaskState, ATAFN_SS_ATAPI_READ_TOC_MULTI);
     4481                        atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_READ_TOC_MULTI);
    44794482                        break;
    44804483                    case 2:
    4481                         atapiDoTransfer(pAhciPort, pAhciPortTaskState, ATAFN_SS_ATAPI_READ_TOC_RAW);
     4484                        atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_READ_TOC_RAW);
    44824485                        break;
    44834486                    default:
    44844487                    error_cmd:
    4485                         atapiCmdErrorSimple(pAhciPort, pAhciPortTaskState, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
     4488                        atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
    44864489                        break;
    44874490                }
     
    44924495            {
    44934496                pAhciPort->cNotifiedMediaChange-- ;
    4494                 atapiCmdErrorSimple(pAhciPort, pAhciPortTaskState, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
     4497                atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
    44954498                break;
    44964499            }
    44974500            else if (!pAhciPort->pDrvMount->pfnIsMounted(pAhciPort->pDrvMount))
    44984501            {
    4499                 atapiCmdErrorSimple(pAhciPort, pAhciPortTaskState, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
     4502                atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
    45004503                break;
    45014504            }
    4502             atapiDoTransfer(pAhciPort, pAhciPortTaskState, ATAFN_SS_ATAPI_READ_CAPACITY);
     4505            atapiDoTransfer(pAhciPort, pAhciReq, 8 /* cbMax */, ATAFN_SS_ATAPI_READ_CAPACITY);
    45034506            break;
    45044507        case SCSI_READ_DISC_INFORMATION:
     
    45064509            {
    45074510                pAhciPort->cNotifiedMediaChange-- ;
    4508                 atapiCmdErrorSimple(pAhciPort, pAhciPortTaskState, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
     4511                atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
    45094512                break;
    45104513            }
    45114514            else if (!pAhciPort->pDrvMount->pfnIsMounted(pAhciPort->pDrvMount))
    45124515            {
    4513                 atapiCmdErrorSimple(pAhciPort, pAhciPortTaskState, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
     4516                atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
    45144517                break;
    45154518            }
    45164519            cbMax = ataBE2H_U16(pbPacket + 7);
    4517             atapiDoTransfer(pAhciPort, pAhciPortTaskState, ATAFN_SS_ATAPI_READ_DISC_INFORMATION);
     4520            atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_READ_DISC_INFORMATION);
    45184521            break;
    45194522        case SCSI_READ_TRACK_INFORMATION:
     
    45214524            {
    45224525                pAhciPort->cNotifiedMediaChange-- ;
    4523                 atapiCmdErrorSimple(pAhciPort, pAhciPortTaskState, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
     4526                atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_UNIT_ATTENTION, SCSI_ASC_MEDIUM_MAY_HAVE_CHANGED); /* media changed */
    45244527                break;
    45254528            }
    45264529            else if (!pAhciPort->pDrvMount->pfnIsMounted(pAhciPort->pDrvMount))
    45274530            {
    4528                 atapiCmdErrorSimple(pAhciPort, pAhciPortTaskState, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
     4531                atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);
    45294532                break;
    45304533            }
    45314534            cbMax = ataBE2H_U16(pbPacket + 7);
    4532             atapiDoTransfer(pAhciPort, pAhciPortTaskState, ATAFN_SS_ATAPI_READ_TRACK_INFORMATION);
     4535            atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_READ_TRACK_INFORMATION);
    45334536            break;
    45344537        case SCSI_GET_CONFIGURATION:
    45354538            /* No media change stuff here, it can confuse Linux guests. */
    45364539            cbMax = ataBE2H_U16(pbPacket + 7);
    4537             atapiDoTransfer(pAhciPort, pAhciPortTaskState, ATAFN_SS_ATAPI_GET_CONFIGURATION);
     4540            atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_GET_CONFIGURATION);
    45384541            break;
    45394542        case SCSI_INQUIRY:
    45404543            cbMax = pbPacket[4];
    4541             atapiDoTransfer(pAhciPort, pAhciPortTaskState, ATAFN_SS_ATAPI_INQUIRY);
     4544            atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_INQUIRY);
    45424545            break;
    45434546        default:
    4544             atapiCmdErrorSimple(pAhciPort, pAhciPortTaskState, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_ILLEGAL_OPCODE);
     4547            atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_ILLEGAL_OPCODE);
    45454548            break;
    45464549    }
     
    45524555 * Parse ATAPI commands, passing them directly to the CD/DVD drive.
    45534556 */
    4554 static AHCITXDIR atapiParseCmdPassthrough(PAHCIPort pAhciPort, PAHCIPORTTASKSTATE pAhciPortTaskState)
     4557static AHCITXDIR atapiParseCmdPassthrough(PAHCIPort pAhciPort, PAHCIREQ pAhciReq)
    45554558{
    45564559    const uint8_t *pbPacket;
     
    45594562    AHCITXDIR enmTxDir = AHCITXDIR_NONE;
    45604563
    4561     pbPacket = pAhciPortTaskState->aATAPICmd;
     4564    pbPacket = pAhciReq->aATAPICmd;
    45624565    switch (pbPacket[0])
    45634566    {
     
    45734576            goto sendcmd;
    45744577        case SCSI_FORMAT_UNIT:
    4575             cbTransfer = pAhciPortTaskState->cmdFis[AHCI_CMDFIS_CYLL] | (pAhciPortTaskState->cmdFis[AHCI_CMDFIS_CYLH] << 8); /* use ATAPI transfer length */
     4578            cbTransfer = pAhciReq->cmdFis[AHCI_CMDFIS_CYLL] | (pAhciReq->cmdFis[AHCI_CMDFIS_CYLH] << 8); /* use ATAPI transfer length */
    45764579            enmTxDir = AHCITXDIR_WRITE;
    45774580            goto sendcmd;
     
    45844587            if (ASMAtomicReadU32(&pAhciPort->MediaEventStatus) != ATA_EVENT_STATUS_UNCHANGED)
    45854588            {
    4586                 pAhciPortTaskState->cbTransfer = RT_MIN(cbTransfer, 8);
    4587                 atapiDoTransfer(pAhciPort, pAhciPortTaskState, ATAFN_SS_ATAPI_GET_EVENT_STATUS_NOTIFICATION);
     4589                pAhciReq->cbTransfer = RT_MIN(cbTransfer, 8);
     4590                atapiDoTransfer(pAhciPort, pAhciReq, pAhciReq->cbTransfer, ATAFN_SS_ATAPI_GET_EVENT_STATUS_NOTIFICATION);
    45884591                break;
    45894592            }
     
    45914594            goto sendcmd;
    45924595        case SCSI_GET_PERFORMANCE:
    4593             cbTransfer = pAhciPortTaskState->cmdFis[AHCI_CMDFIS_CYLL] | (pAhciPortTaskState->cmdFis[AHCI_CMDFIS_CYLH] << 8); /* use ATAPI transfer length */
     4596            cbTransfer = pAhciReq->cmdFis[AHCI_CMDFIS_CYLL] | (pAhciReq->cmdFis[AHCI_CMDFIS_CYLH] << 8); /* use ATAPI transfer length */
    45944597            enmTxDir = AHCITXDIR_READ;
    45954598            goto sendcmd;
     
    46274630            cSectors = ataBE2H_U16(pbPacket + 7);
    46284631            Log2(("ATAPI PT: lba %d sectors %d\n", iATAPILBA, cSectors));
    4629             pAhciPortTaskState->cbATAPISector = 2048; /**< @todo this size is not always correct */
    4630             cbTransfer = cSectors * pAhciPortTaskState->cbATAPISector;
     4632            pAhciReq->cbATAPISector = 2048; /**< @todo this size is not always correct */
     4633            cbTransfer = cSectors * pAhciReq->cbATAPISector;
    46314634            enmTxDir = AHCITXDIR_READ;
    46324635            goto sendcmd;
     
    46354638            cSectors = ataBE2H_U32(pbPacket + 6);
    46364639            Log2(("ATAPI PT: lba %d sectors %d\n", iATAPILBA, cSectors));
    4637             pAhciPortTaskState->cbATAPISector = 2048; /**< @todo this size is not always correct */
    4638             cbTransfer = cSectors * pAhciPortTaskState->cbATAPISector;
     4640            pAhciReq->cbATAPISector = 2048; /**< @todo this size is not always correct */
     4641            cbTransfer = cSectors * pAhciReq->cbATAPISector;
    46394642            enmTxDir = AHCITXDIR_READ;
    46404643            goto sendcmd;
     
    46584661                case 0x0: /* All types. */
    46594662                    if (ASMAtomicReadU32(&pAhciPort->MediaTrackType) == ATA_MEDIA_TYPE_CDDA)
    4660                         pAhciPortTaskState->cbATAPISector = 2352;
     4663                        pAhciReq->cbATAPISector = 2352;
    46614664                    else
    4662                         pAhciPortTaskState->cbATAPISector = 2048; /* Might be incorrect if we couldn't determine the type. */
     4665                        pAhciReq->cbATAPISector = 2048; /* Might be incorrect if we couldn't determine the type. */
    46634666                    break;
    46644667                case 0x1: /* CD-DA */
    4665                     pAhciPortTaskState->cbATAPISector = 2352;
     4668                    pAhciReq->cbATAPISector = 2352;
    46664669                    break;
    46674670                case 0x2: /* Mode 1 */
    4668                     pAhciPortTaskState->cbATAPISector = 2048;
     4671                    pAhciReq->cbATAPISector = 2048;
    46694672                    break;
    46704673                case 0x3: /* Mode 2 formless */
    4671                     pAhciPortTaskState->cbATAPISector = 2336;
     4674                    pAhciReq->cbATAPISector = 2336;
    46724675                    break;
    46734676                case 0x4: /* Mode 2 form 1 */
    4674                     pAhciPortTaskState->cbATAPISector = 2048;
     4677                    pAhciReq->cbATAPISector = 2048;
    46754678                    break;
    46764679                case 0x5: /* Mode 2 form 2 */
    4677                     pAhciPortTaskState->cbATAPISector = 2324;
     4680                    pAhciReq->cbATAPISector = 2324;
    46784681                    break;
    46794682                default: /* Reserved */
    46804683                    AssertMsgFailed(("Unknown sector type\n"));
    4681                     pAhciPortTaskState->cbATAPISector = 0; /** @todo we should probably fail the command here already. */
     4684                    pAhciReq->cbATAPISector = 0; /** @todo we should probably fail the command here already. */
    46824685            }
    46834686
    4684             cbTransfer = ataBE2H_U24(pbPacket + 6) * pAhciPortTaskState->cbATAPISector;
     4687            cbTransfer = ataBE2H_U24(pbPacket + 6) * pAhciReq->cbATAPISector;
    46854688            enmTxDir = AHCITXDIR_READ;
    46864689            goto sendcmd;
     
    46904693            if (cSectors > 32)
    46914694                cSectors = 32; /* Limit transfer size to 64~74K. Safety first. In any case this can only harm software doing CDDA extraction. */
    4692             pAhciPortTaskState->cbATAPISector = 2048; /**< @todo this size is not always correct */
    4693             cbTransfer = cSectors * pAhciPortTaskState->cbATAPISector;
     4695            pAhciReq->cbATAPISector = 2048; /**< @todo this size is not always correct */
     4696            cbTransfer = cSectors * pAhciReq->cbATAPISector;
    46944697            enmTxDir = AHCITXDIR_READ;
    46954698            goto sendcmd;
     
    47284731            if ((pAhciPort->abATAPISense[2] & 0x0f) != SCSI_SENSE_NONE)
    47294732            {
    4730                 pAhciPortTaskState->cbTransfer = cbTransfer;
    4731                 pAhciPortTaskState->enmTxDir = AHCITXDIR_READ;
    4732                 atapiDoTransfer(pAhciPort, pAhciPortTaskState, ATAFN_SS_ATAPI_REQUEST_SENSE);
     4733                pAhciReq->cbTransfer = cbTransfer;
     4734                pAhciReq->enmTxDir = AHCITXDIR_READ;
     4735                atapiDoTransfer(pAhciPort, pAhciReq, cbTransfer, ATAFN_SS_ATAPI_REQUEST_SENSE);
    47334736                break;
    47344737            }
     
    47834786            cSectors = ataBE2H_U16(pbPacket + 7);
    47844787            Log2(("ATAPI PT: lba %d sectors %d\n", iATAPILBA, cSectors));
    4785             pAhciPortTaskState->cbATAPISector = 2048; /**< @todo this size is not always correct */
    4786             cbTransfer = cSectors * pAhciPortTaskState->cbATAPISector;
     4788            pAhciReq->cbATAPISector = 2048; /**< @todo this size is not always correct */
     4789            cbTransfer = cSectors * pAhciReq->cbATAPISector;
    47874790            enmTxDir = AHCITXDIR_WRITE;
    47884791            goto sendcmd;
     
    47914794            cSectors = ataBE2H_U32(pbPacket + 6);
    47924795            Log2(("ATAPI PT: lba %d sectors %d\n", iATAPILBA, cSectors));
    4793             pAhciPortTaskState->cbATAPISector = 2048; /**< @todo this size is not always correct */
    4794             cbTransfer = cSectors * pAhciPortTaskState->cbATAPISector;
     4796            pAhciReq->cbATAPISector = 2048; /**< @todo this size is not always correct */
     4797            cbTransfer = cSectors * pAhciReq->cbATAPISector;
    47954798            enmTxDir = AHCITXDIR_WRITE;
    47964799            goto sendcmd;
     
    48004803            Log2(("ATAPI PT: lba %d sectors %d\n", iATAPILBA, cSectors));
    48014804            /* The sector size is determined by the async I/O thread. */
    4802             pAhciPortTaskState->cbATAPISector = 0;
     4805            pAhciReq->cbATAPISector = 0;
    48034806            /* Preliminary, will be corrected once the sector size is known. */
    48044807            cbTransfer = cSectors;
     
    48154818                case 0x0f: /* activate deferred microcode */
    48164819                    LogRel(("PIIX3 ATA: LUN#%d: CD-ROM passthrough command attempted to update firmware, blocked\n", pAhciPort->iLUN));
    4817                     atapiCmdErrorSimple(pAhciPort, pAhciPortTaskState, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
     4820                    atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET);
    48184821                    break;
    48194822                default:
     
    48334836             * opcode 0x01" in syslog) and replies with a sense code of 0,
    48344837             * which sends cdrecord to an endless loop. */
    4835             atapiCmdErrorSimple(pAhciPort, pAhciPortTaskState, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_ILLEGAL_OPCODE);
     4838            atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_ILLEGAL_OPCODE);
    48364839            break;
    48374840        default:
    48384841            LogRel(("AHCI: LUN#%d: passthrough unimplemented for command %#x\n", pAhciPort->iLUN, pbPacket[0]));
    4839             atapiCmdErrorSimple(pAhciPort, pAhciPortTaskState, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_ILLEGAL_OPCODE);
     4842            atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_ILLEGAL_OPCODE);
    48404843            break;
    48414844        sendcmd:
     
    48444847            if (cbTransfer == 0)
    48454848                enmTxDir = AHCITXDIR_NONE;
    4846             pAhciPortTaskState->enmTxDir = enmTxDir;
    4847             pAhciPortTaskState->cbTransfer = cbTransfer;
    4848             atapiDoTransfer(pAhciPort, pAhciPortTaskState, ATAFN_SS_ATAPI_PASSTHROUGH);
     4849            pAhciReq->enmTxDir = enmTxDir;
     4850            pAhciReq->cbTransfer = cbTransfer;
     4851            atapiDoTransfer(pAhciPort, pAhciReq, cbTransfer, ATAFN_SS_ATAPI_PASSTHROUGH);
    48494852    }
    48504853
     
    48524855}
    48534856
    4854 static AHCITXDIR atapiParseCmd(PAHCIPort pAhciPort, PAHCIPORTTASKSTATE pAhciPortTaskState)
     4857static AHCITXDIR atapiParseCmd(PAHCIPort pAhciPort, PAHCIREQ pAhciReq)
    48554858{
    48564859    AHCITXDIR enmTxDir = AHCITXDIR_NONE;
    48574860    const uint8_t *pbPacket;
    48584861
    4859     pbPacket = pAhciPortTaskState->aATAPICmd;
     4862    pbPacket = pAhciReq->aATAPICmd;
    48604863#ifdef DEBUG
    48614864    Log(("%s: LUN#%d CMD=%#04x \"%s\"\n", __FUNCTION__, pAhciPort->iLUN, pbPacket[0], SCSICmdText(pbPacket[0])));
     
    48634866    Log(("%s: LUN#%d CMD=%#04x\n", __FUNCTION__, pAhciPort->iLUN, pbPacket[0]));
    48644867#endif /* !DEBUG */
    4865     Log2(("%s: limit=%#x packet: %.*Rhxs\n", __FUNCTION__, pAhciPortTaskState->cmdFis[AHCI_CMDFIS_CYLL] | (pAhciPortTaskState->cmdFis[AHCI_CMDFIS_CYLH] << 8), ATAPI_PACKET_SIZE, pbPacket));
     4868    Log2(("%s: limit=%#x packet: %.*Rhxs\n", __FUNCTION__, pAhciReq->cmdFis[AHCI_CMDFIS_CYLL] | (pAhciReq->cmdFis[AHCI_CMDFIS_CYLH] << 8), ATAPI_PACKET_SIZE, pbPacket));
    48664869
    48674870    if (pAhciPort->fATAPIPassthrough)
    4868         enmTxDir = atapiParseCmdPassthrough(pAhciPort, pAhciPortTaskState);
     4871        enmTxDir = atapiParseCmdPassthrough(pAhciPort, pAhciReq);
    48694872    else
    4870         enmTxDir = atapiParseCmdVirtualATAPI(pAhciPort, pAhciPortTaskState);
     4873        enmTxDir = atapiParseCmdVirtualATAPI(pAhciPort, pAhciReq);
    48714874
    48724875    return enmTxDir;
     
    48784881 * @returns nothing
    48794882 * @param pAhciPort             The port the device is attached to.
    4880  * @param pAhciPortTaskState    The state to get the tag number from.
    4881  */
    4882 static void ahciFinishStorageDeviceReset(PAHCIPort pAhciPort, PAHCIPORTTASKSTATE pAhciPortTaskState)
     4883 * @param pAhciReq    The state to get the tag number from.
     4884 */
     4885static void ahciFinishStorageDeviceReset(PAHCIPort pAhciPort, PAHCIREQ pAhciReq)
    48834886{
    48844887    int rc;
     
    48954898    else
    48964899        pAhciPort->regSIG = AHCI_PORT_SIG_DISK;
    4897     ASMAtomicOrU32(&pAhciPort->u32TasksFinished, (1 << pAhciPortTaskState->uTag));
     4900    ASMAtomicOrU32(&pAhciPort->u32TasksFinished, (1 << pAhciReq->uTag));
    48984901
    48994902    rc = ahciHbaSetInterrupt(pAhciPort->CTX_SUFF(pAhci), pAhciPort->iLUN, VERR_IGNORED);
     
    49064909 * @returns nothing.
    49074910 * @param   pAhciPort          The device to reset.
    4908  * @param   pAhciPortTaskState The task state.
    4909  */
    4910 static void ahciDeviceReset(PAHCIPort pAhciPort, PAHCIPORTTASKSTATE pAhciPortTaskState)
     4911 * @param   pAhciReq The task state.
     4912 */
     4913static void ahciDeviceReset(PAHCIPort pAhciPort, PAHCIREQ pAhciReq)
    49114914{
    49124915    ASMAtomicWriteBool(&pAhciPort->fResetDevice, true);
     
    49184921     */
    49194922    Assert(ASMAtomicReadU32(&pAhciPort->cTasksActive) == 0);
    4920     ahciFinishStorageDeviceReset(pAhciPort, pAhciPortTaskState);
     4923    ahciFinishStorageDeviceReset(pAhciPort, pAhciReq);
    49214924}
    49224925
     
    49264929 * @returns Nothing
    49274930 * @param   pAhciPort          The port of the SATA controller.
    4928  * @param   pAhciPortTaskState The state of the task.
     4931 * @param   pAhciReq The state of the task.
    49294932 * @param   pCmdFis            Pointer to the command FIS from the guest.
    49304933 * @param   fInterrupt         If an interrupt should be send to the guest.
    49314934 */
    4932 static void ahciSendD2HFis(PAHCIPort pAhciPort, PAHCIPORTTASKSTATE pAhciPortTaskState, uint8_t *pCmdFis, bool fInterrupt)
     4935static void ahciSendD2HFis(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, uint8_t *pCmdFis, bool fInterrupt)
    49334936{
    49344937    uint8_t d2hFis[20];
     
    49434946        d2hFis[AHCI_CMDFIS_TYPE]  = AHCI_CMDFIS_TYPE_D2H;
    49444947        d2hFis[AHCI_CMDFIS_BITS]  = (fInterrupt ? AHCI_CMDFIS_I : 0);
    4945         d2hFis[AHCI_CMDFIS_STS]   = pAhciPortTaskState->uATARegStatus;
    4946         d2hFis[AHCI_CMDFIS_ERR]   = pAhciPortTaskState->uATARegError;
     4948        d2hFis[AHCI_CMDFIS_STS]   = pAhciReq->uATARegStatus;
     4949        d2hFis[AHCI_CMDFIS_ERR]   = pAhciReq->uATARegError;
    49474950        d2hFis[AHCI_CMDFIS_SECTN] = pCmdFis[AHCI_CMDFIS_SECTN];
    49484951        d2hFis[AHCI_CMDFIS_CYLL]  = pCmdFis[AHCI_CMDFIS_CYLL];
     
    49564959
    49574960        /* Update registers. */
    4958         pAhciPort->regTFD = (pAhciPortTaskState->uATARegError << 8) | pAhciPortTaskState->uATARegStatus;
     4961        pAhciPort->regTFD = (pAhciReq->uATARegError << 8) | pAhciReq->uATARegStatus;
    49594962
    49604963        ahciPostFisIntoMemory(pAhciPort, AHCI_CMDFIS_TYPE_D2H, d2hFis);
    49614964
    4962         if (pAhciPortTaskState->uATARegStatus & ATA_STAT_ERR)
     4965        if (pAhciReq->uATARegStatus & ATA_STAT_ERR)
    49634966        {
    49644967            /* Error bit is set. */
     
    49794982
    49804983            /* Mark command as completed. */
    4981             ASMAtomicOrU32(&pAhciPort->u32TasksFinished, (1 << pAhciPortTaskState->uTag));
     4984            ASMAtomicOrU32(&pAhciPort->u32TasksFinished, (1 << pAhciReq->uTag));
    49824985        }
    49834986
     
    50035006    bool fAssertIntr = false;
    50045007    PAHCI pAhci = pAhciPort->CTX_SUFF(pAhci);
    5005     PAHCIPORTTASKSTATE pTaskErr = ASMAtomicReadPtrT(&pAhciPort->pTaskErr, PAHCIPORTTASKSTATE);
     5008    PAHCIREQ pTaskErr = ASMAtomicReadPtrT(&pAhciPort->pTaskErr, PAHCIREQ);
    50065009
    50075010    ahciLog(("%s: Building SDB FIS\n", __FUNCTION__));
     
    51365139}
    51375140
    5138 static void ahciScatterGatherListGetTotalBufferSize(PAHCIPort pAhciPort, PAHCIPORTTASKSTATE pAhciPortTaskState)
    5139 {
    5140     CmdHdr    *pCmdHdr = &pAhciPortTaskState->cmdHdr;
    5141     PPDMDEVINS pDevIns = pAhciPort->CTX_SUFF(pDevIns);
    5142     unsigned   cActualSGEntry;
    5143     SGLEntry   aSGLEntry[32];                  /* Holds read sg entries from guest. Biggest seen number of entries a guest set up. */
    5144     unsigned   cSGLEntriesGCRead;
    5145     unsigned   cSGLEntriesGCLeft;              /* Available scatter gather list entries in GC */
    5146     RTGCPHYS   GCPhysAddrPRDTLEntryStart;      /* Start address to read the entries from. */
    5147     uint32_t   cbSGBuffers = 0;                /* Total number of bytes reserved for this request. */
    5148 
    5149     /* Retrieve the total number of bytes reserved for this request. */
    5150     cSGLEntriesGCLeft = AHCI_CMDHDR_PRDTL_ENTRIES(pCmdHdr->u32DescInf);
    5151     ahciLog(("%s: cSGEntriesGC=%u\n", __FUNCTION__, cSGLEntriesGCLeft));
    5152 
    5153     if (cSGLEntriesGCLeft)
    5154     {
    5155         /* Set start address of the entries. */
    5156         GCPhysAddrPRDTLEntryStart = AHCI_RTGCPHYS_FROM_U32(pCmdHdr->u32CmdTblAddrUp, pCmdHdr->u32CmdTblAddr) + AHCI_CMDHDR_PRDT_OFFSET;
    5157 
    5158         do
    5159         {
    5160             cSGLEntriesGCRead = (cSGLEntriesGCLeft < RT_ELEMENTS(aSGLEntry)) ? cSGLEntriesGCLeft : RT_ELEMENTS(aSGLEntry);
    5161             cSGLEntriesGCLeft -= cSGLEntriesGCRead;
    5162 
    5163             /* Read the SG entries. */
    5164             PDMDevHlpPhysRead(pDevIns, GCPhysAddrPRDTLEntryStart, &aSGLEntry[0], cSGLEntriesGCRead * sizeof(SGLEntry));
    5165 
    5166             for (cActualSGEntry = 0; cActualSGEntry < cSGLEntriesGCRead; cActualSGEntry++)
    5167             {
    5168                 cbSGBuffers += (aSGLEntry[cActualSGEntry].u32DescInf & SGLENTRY_DESCINF_DBC) + 1;
    5169                 ahciLog(("%s: SG Entry: info %08X at phys %08X'%08X (%u bytes)\n", __FUNCTION__, aSGLEntry[cActualSGEntry].u32DescInf,
    5170                          aSGLEntry[cActualSGEntry].u32DBAUp, aSGLEntry[cActualSGEntry].u32DBA,
    5171                          (aSGLEntry[cActualSGEntry].u32DescInf & SGLENTRY_DESCINF_DBC) + 1));
    5172             }
    5173 
    5174             /* Set address to the next entries to read. */
    5175             GCPhysAddrPRDTLEntryStart += cSGLEntriesGCRead * sizeof(SGLEntry);
    5176         } while (cSGLEntriesGCLeft);
    5177     }
    5178 
    5179     pAhciPortTaskState->cbSGBuffers = cbSGBuffers;
    5180 }
    5181 
    5182 static int ahciScatterGatherListAllocate(PAHCIPORTTASKSTATE pAhciPortTaskState, uint32_t cSGList, uint32_t cbUnaligned)
    5183 {
    5184     if (pAhciPortTaskState->cSGListSize < cSGList)
    5185     {
    5186         /* The entries are not allocated yet or the number is too small. */
    5187         if (pAhciPortTaskState->cSGListSize)
    5188         {
    5189             RTMemFree(pAhciPortTaskState->pSGListHead);
    5190             RTMemFree(pAhciPortTaskState->paSGEntries);
    5191         }
    5192 
    5193         /* Allocate R3 scatter gather list. */
    5194         pAhciPortTaskState->pSGListHead = (PRTSGSEG)RTMemAllocZ(cSGList * sizeof(RTSGSEG));
    5195         if (!pAhciPortTaskState->pSGListHead)
    5196             return VERR_NO_MEMORY;
    5197 
    5198         pAhciPortTaskState->paSGEntries = (PAHCIPORTTASKSTATESGENTRY)RTMemAllocZ(cSGList * sizeof(AHCIPORTTASKSTATESGENTRY));
    5199         if (!pAhciPortTaskState->paSGEntries)
    5200             return VERR_NO_MEMORY;
    5201 
    5202         /* Reset usage statistics. */
    5203         pAhciPortTaskState->cSGListSize = cSGList;
    5204         pAhciPortTaskState->cSGListTooBig = 0;
    5205     }
    5206     else if (pAhciPortTaskState->cSGListSize > cSGList)
    5207     {
    5208         /*
    5209          * The list is too big. Increment counter.
    5210          * So that the destroying function can free
    5211          * the list if it is too big too many times
    5212          * in a row.
    5213          */
    5214         pAhciPortTaskState->cSGListTooBig++;
    5215     }
    5216     else
    5217     {
    5218         /*
    5219          * Needed entries matches current size.
    5220          * Reset counter.
    5221          */
    5222         pAhciPortTaskState->cSGListTooBig = 0;
    5223     }
    5224 
    5225     pAhciPortTaskState->cSGEntries = cSGList;
    5226 
    5227     if (pAhciPortTaskState->cbBufferUnaligned < cbUnaligned)
    5228     {
    5229         if (pAhciPortTaskState->pvBufferUnaligned)
    5230             RTMemPageFree(pAhciPortTaskState->pvBufferUnaligned, pAhciPortTaskState->cbBufferUnaligned);
    5231 
    5232         Log(("%s: Allocating buffer for unaligned segments cbUnaligned=%u\n", __FUNCTION__, cbUnaligned));
    5233 
    5234         pAhciPortTaskState->pvBufferUnaligned = RTMemPageAlloc(cbUnaligned);
    5235         if (!pAhciPortTaskState->pvBufferUnaligned)
    5236             return VERR_NO_MEMORY;
    5237 
    5238         pAhciPortTaskState->cbBufferUnaligned = cbUnaligned;
    5239     }
    5240 
    5241     /* Make debugging easier. */
    5242 #ifdef DEBUG
    5243     memset(pAhciPortTaskState->pSGListHead, 0, pAhciPortTaskState->cSGListSize * sizeof(RTSGSEG));
    5244     memset(pAhciPortTaskState->paSGEntries, 0, pAhciPortTaskState->cSGListSize * sizeof(AHCIPORTTASKSTATESGENTRY));
    5245     if (pAhciPortTaskState->pvBufferUnaligned)
    5246         memset(pAhciPortTaskState->pvBufferUnaligned, 0, pAhciPortTaskState->cbBufferUnaligned);
    5247 #endif
    5248 
    5249     return VINF_SUCCESS;
    5250 }
    5251 
    5252 /**
    5253  * Fallback scatter gather list creator.
    5254  * Used if the normal one fails in PDMDevHlpPhysGCPhys2CCPtr() or
    5255  * PDMDevHlpPhysGCPhys2CCPtrReadonly() or post processing
    5256  * is used.
     5141/**
     5142 * Copies a data buffer into the S/G buffer set up by the guest.
    52575143 *
    5258  * returns VBox status code.
    5259  * @param   pAhciPort              The ahci port.
    5260  * @param   pAhciPortTaskState     The task state which contains the S/G list entries.
    5261  * @param   fReadonly              If the mappings should be readonly.
    5262  * @param   cSGEntriesProcessed    Number of entries the normal creator processed
    5263  *                                 before an error occurred. Used to free
    5264  *                                 any resources allocated before.
    5265  * @thread  EMT
    5266  */
    5267 static int ahciScatterGatherListCreateSafe(PAHCIPort pAhciPort, PAHCIPORTTASKSTATE pAhciPortTaskState,
    5268                                            bool fReadonly, unsigned cSGEntriesProcessed)
    5269 {
    5270     CmdHdr                    *pCmdHdr = &pAhciPortTaskState->cmdHdr;
    5271     PPDMDEVINS                 pDevIns = pAhciPort->CTX_SUFF(pDevIns);
    5272     PAHCIPORTTASKSTATESGENTRY  pSGInfoCurr  = pAhciPortTaskState->paSGEntries;
    5273 
    5274     Assert(VALID_PTR(pAhciPortTaskState->pSGListHead) || !cSGEntriesProcessed);
    5275     Assert(VALID_PTR(pAhciPortTaskState->paSGEntries) || !cSGEntriesProcessed);
    5276 
    5277     for (unsigned cSGEntryCurr = 0; cSGEntryCurr < cSGEntriesProcessed; cSGEntryCurr++)
    5278     {
    5279         if (pSGInfoCurr->fGuestMemory)
    5280         {
    5281             /* Release the lock. */
    5282             PDMDevHlpPhysReleasePageMappingLock(pDevIns, &pSGInfoCurr->u.direct.PageLock);
    5283         }
    5284 
    5285         /* Go to the next entry. */
    5286         pSGInfoCurr++;
    5287     }
    5288 
    5289     if (pAhciPortTaskState->pvBufferUnaligned)
    5290     {
    5291         RTMemPageFree(pAhciPortTaskState->pvBufferUnaligned, pAhciPortTaskState->cbBufferUnaligned);
    5292         pAhciPortTaskState->pvBufferUnaligned = NULL;
    5293     }
    5294     if (pAhciPortTaskState->pSGListHead)
    5295     {
    5296         RTMemFree(pAhciPortTaskState->pSGListHead);
    5297         pAhciPortTaskState->pSGListHead = NULL;
    5298     }
    5299     if (pAhciPortTaskState->paSGEntries)
    5300     {
    5301         RTMemFree(pAhciPortTaskState->paSGEntries);
    5302         pAhciPortTaskState->paSGEntries = NULL;
    5303     }
    5304     pAhciPortTaskState->cSGListTooBig = 0;
    5305     pAhciPortTaskState->cSGEntries    = 1;
    5306     pAhciPortTaskState->cSGListUsed   = 1;
    5307     pAhciPortTaskState->cSGListSize   = 1;
    5308     pAhciPortTaskState->cbBufferUnaligned = pAhciPortTaskState->cbSGBuffers;
    5309 
    5310     /* Allocate new buffers and SG lists. */
    5311     pAhciPortTaskState->pvBufferUnaligned = RTMemPageAlloc(pAhciPortTaskState->cbSGBuffers);
    5312     if (!pAhciPortTaskState->pvBufferUnaligned)
    5313         return VERR_NO_MEMORY;
    5314 
    5315     pAhciPortTaskState->pSGListHead = (PRTSGSEG)RTMemAllocZ(1 * sizeof(RTSGSEG));
    5316     if (!pAhciPortTaskState->pSGListHead)
    5317     {
    5318         RTMemPageFree(pAhciPortTaskState->pvBufferUnaligned, pAhciPortTaskState->cbBufferUnaligned);
    5319         return VERR_NO_MEMORY;
    5320     }
    5321 
    5322     pAhciPortTaskState->paSGEntries = (PAHCIPORTTASKSTATESGENTRY)RTMemAllocZ(1 * sizeof(AHCIPORTTASKSTATESGENTRY));
    5323     if (!pAhciPortTaskState->paSGEntries)
    5324     {
    5325         RTMemPageFree(pAhciPortTaskState->pvBufferUnaligned, pAhciPortTaskState->cbBufferUnaligned);
    5326         RTMemFree(pAhciPortTaskState->pSGListHead);
    5327         return VERR_NO_MEMORY;
    5328     }
    5329 
    5330     /* Set pointers. */
    5331     if (pAhciPortTaskState->cbTransfer)
    5332     {
    5333         pAhciPortTaskState->pSGListHead[0].cbSeg = pAhciPortTaskState->cbTransfer;
    5334 
    5335         /* Allocate a separate buffer if we have to do post processing . */
    5336         if (pAhciPortTaskState->pfnPostProcess)
    5337         {
    5338             pAhciPortTaskState->pSGListHead[0].pvSeg = RTMemAlloc(pAhciPortTaskState->cbTransfer);
    5339             if (!pAhciPortTaskState->pSGListHead[0].pvSeg)
    5340             {
    5341                 RTMemFree(pAhciPortTaskState->paSGEntries);
    5342                 RTMemPageFree(pAhciPortTaskState->pvBufferUnaligned, pAhciPortTaskState->cbBufferUnaligned);
    5343                 RTMemFree(pAhciPortTaskState->pSGListHead);
    5344                 return VERR_NO_MEMORY;
    5345             }
    5346         }
    5347         else
    5348             pAhciPortTaskState->pSGListHead[0].pvSeg = pAhciPortTaskState->pvBufferUnaligned;
    5349     }
    5350     else
    5351     {
    5352         pAhciPortTaskState->pSGListHead[0].cbSeg = pAhciPortTaskState->cbBufferUnaligned;
    5353         pAhciPortTaskState->pSGListHead[0].pvSeg = pAhciPortTaskState->pvBufferUnaligned;
    5354     }
    5355 
    5356     pAhciPortTaskState->paSGEntries[0].fGuestMemory = false;
    5357     pAhciPortTaskState->paSGEntries[0].u.temp.cUnaligned   = AHCI_CMDHDR_PRDTL_ENTRIES(pCmdHdr->u32DescInf);
    5358     pAhciPortTaskState->paSGEntries[0].u.temp.GCPhysAddrBaseFirstUnaligned = AHCI_RTGCPHYS_FROM_U32(pCmdHdr->u32CmdTblAddrUp, pCmdHdr->u32CmdTblAddr) + AHCI_CMDHDR_PRDT_OFFSET;
    5359     pAhciPortTaskState->paSGEntries[0].u.temp.pvBuf = pAhciPortTaskState->pvBufferUnaligned;
    5360 
    5361     if (   pAhciPortTaskState->enmTxDir == AHCITXDIR_WRITE
    5362         || pAhciPortTaskState->enmTxDir == AHCITXDIR_TRIM)
    5363         ahciCopyFromSGListIntoBuffer(pDevIns, &pAhciPortTaskState->paSGEntries[0]);
    5364 
    5365     return VINF_SUCCESS;
    5366 }
    5367 
    5368 /**
    5369  * Create scatter gather list descriptors.
     5144 * @returns Amount of bytes copied to the PRDTL.
     5145 * @param   pDevIns        Pointer to the device instance data.
     5146 * @param   pAhciReq       AHCI request structure.
     5147 * @param   pvBuf          The buffer to copy from.
     5148 * @param   cbBuf          The size of the buffer.
     5149 */
     5150static size_t ahciCopyToPrdtl(PPDMDEVINS pDevIns, PAHCIREQ pAhciReq,
     5151                              void *pvBuf, size_t cbBuf)
     5152{
     5153    uint8_t *pbBuf = (uint8_t *)pvBuf;
     5154    SGLEntry aPrdtlEntries[32];
     5155    RTGCPHYS GCPhysPrdtl = pAhciReq->GCPhysPrdtl;
     5156    unsigned cPrdtlEntries = pAhciReq->cPrdtlEntries;
     5157    size_t cbCopied = 0;
     5158
     5159    AssertMsgReturn(cPrdtlEntries > 0, ("Copying 0 bytes is not possible\n"), 0);
     5160
     5161    do
     5162    {
     5163        uint32_t cPrdtlEntriesRead =   (cPrdtlEntries < RT_ELEMENTS(aPrdtlEntries))
     5164                                     ? cPrdtlEntries
     5165                                     : RT_ELEMENTS(aPrdtlEntries);
     5166
     5167        PDMDevHlpPhysRead(pDevIns, GCPhysPrdtl, &aPrdtlEntries[0], cPrdtlEntriesRead * sizeof(SGLEntry));
     5168
     5169        for (uint32_t i = 0; (i < cPrdtlEntriesRead) && cbBuf; i++)
     5170        {
     5171            RTGCPHYS GCPhysAddrDataBase = AHCI_RTGCPHYS_FROM_U32(aPrdtlEntries[i].u32DBAUp, aPrdtlEntries[i].u32DBA);
     5172            uint32_t cbThisCopy = (aPrdtlEntries[i].u32DescInf & SGLENTRY_DESCINF_DBC) + 1;
     5173
     5174            cbThisCopy = RT_MIN(cbThisCopy, cbBuf);
     5175
     5176            /* Copy into SG entry. */
     5177            PDMDevHlpPhysWrite(pDevIns, GCPhysAddrDataBase, pbBuf, cbThisCopy);
     5178
     5179            pbBuf    += cbThisCopy;
     5180            cbBuf    -= cbThisCopy;
     5181            cbCopied += cbThisCopy;
     5182        }
     5183
     5184        GCPhysPrdtl   += cPrdtlEntriesRead * sizeof(SGLEntry);
     5185        cPrdtlEntries -= cPrdtlEntriesRead;
     5186    } while (cPrdtlEntries && cbBuf);
     5187
     5188    if (cbCopied < cbBuf)
     5189        pAhciReq->fFlags |= AHCI_REQ_OVERFLOW;
     5190
     5191    return cbCopied;
     5192}
     5193
     5194/**
     5195 * Copies the S/G buffer into a data buffer.
     5196 *
     5197 * @returns Amount of bytes copied to the PRDTL.
     5198 * @param   pDevIns        Pointer to the device instance data.
     5199 * @param   pAhciReq       AHCI request structure.
     5200 * @param   pvBuf          The buffer to copy to.
     5201 * @param   cbBuf          The size of the buffer.
     5202 */
     5203static size_t ahciCopyFromPrdtl(PPDMDEVINS pDevIns, PAHCIREQ pAhciReq,
     5204                                void *pvBuf, size_t cbBuf)
     5205{
     5206    uint8_t *pbBuf = (uint8_t *)pvBuf;
     5207    SGLEntry aPrdtlEntries[32];
     5208    RTGCPHYS GCPhysPrdtl = pAhciReq->GCPhysPrdtl;
     5209    unsigned cPrdtlEntries = pAhciReq->cPrdtlEntries;
     5210    size_t cbCopied = 0;
     5211
     5212    AssertMsgReturn(cPrdtlEntries > 0, ("Copying 0 bytes is not possible\n"), 0);
     5213
     5214    do
     5215    {
     5216        uint32_t cPrdtlEntriesRead =   (cPrdtlEntries < RT_ELEMENTS(aPrdtlEntries))
     5217                                     ? cPrdtlEntries
     5218                                     : RT_ELEMENTS(aPrdtlEntries);
     5219
     5220        PDMDevHlpPhysRead(pDevIns, GCPhysPrdtl, &aPrdtlEntries[0], cPrdtlEntriesRead * sizeof(SGLEntry));
     5221
     5222        for (uint32_t i = 0; (i < cPrdtlEntriesRead) && cbBuf; i++)
     5223        {
     5224            RTGCPHYS GCPhysAddrDataBase = AHCI_RTGCPHYS_FROM_U32(aPrdtlEntries[i].u32DBAUp, aPrdtlEntries[i].u32DBA);
     5225            uint32_t cbThisCopy = (aPrdtlEntries[i].u32DescInf & SGLENTRY_DESCINF_DBC) + 1;
     5226
     5227            cbThisCopy = RT_MIN(cbThisCopy, cbBuf);
     5228
     5229            /* Copy into buffer. */
     5230            PDMDevHlpPhysRead(pDevIns, GCPhysAddrDataBase, pbBuf, cbThisCopy);
     5231
     5232            pbBuf    += cbThisCopy;
     5233            cbBuf    -= cbThisCopy;
     5234            cbCopied += cbThisCopy;
     5235        }
     5236
     5237        GCPhysPrdtl   += cPrdtlEntriesRead * sizeof(SGLEntry);
     5238        cPrdtlEntries -= cPrdtlEntriesRead;
     5239    } while (cPrdtlEntries && cbBuf);
     5240
     5241    if (cbCopied < cbBuf)
     5242        pAhciReq->fFlags |= AHCI_REQ_OVERFLOW;
     5243
     5244    return cbCopied;
     5245}
     5246
     5247/**
     5248 * Allocate I/O memory and copies the guest buffer for writes.
    53705249 *
    53715250 * @returns VBox status code.
    5372  * @param   pAhciPort              The ahci port.
    5373  * @param   pAhciPortTaskState     The task state which contains the S/G list entries.
    5374  * @param   fReadonly              If the mappings should be readonly.
    5375  * @thread  EMT
    5376  */
    5377 static int ahciScatterGatherListCreate(PAHCIPort pAhciPort, PAHCIPORTTASKSTATE pAhciPortTaskState, bool fReadonly)
    5378 {
    5379     int        rc = VINF_SUCCESS;
    5380     CmdHdr    *pCmdHdr = &pAhciPortTaskState->cmdHdr;
    5381     PPDMDEVINS pDevIns = pAhciPort->CTX_SUFF(pDevIns);
    5382     unsigned   cActualSGEntry;
    5383     unsigned   cSGEntriesR3 = 0;               /* Needed scatter gather list entries in R3. */
    5384     unsigned   cSGEntriesProcessed = 0;        /* Number of SG entries processed. */
    5385     SGLEntry   aSGLEntry[32];                  /* Holds read sg entries from guest. Biggest seen number of entries a guest set up. */
    5386     unsigned   cSGLEntriesGCRead;
    5387     unsigned   cSGLEntriesGCLeft;              /* Available scatter gather list entries in GC */
    5388     RTGCPHYS   GCPhysAddrPRDTLEntryStart;      /* Start address to read the entries from. */
    5389     uint32_t   cbSegment;                      /* Size of the current segments in bytes. */
    5390     bool       fUnaligned;                     /* Flag whether the current buffer is unaligned. */
    5391     uint32_t   cbUnaligned;                    /* Size of the unaligned buffers. */
    5392     uint32_t   cUnaligned;
    5393     bool       fDoMapping = false;
    5394     uint32_t   cbSGBuffers = 0;                /* Total number of bytes reserved for this request. */
    5395     RTGCPHYS   GCPhysAddrPRDTLUnalignedStart = NIL_RTGCPHYS;
    5396     PAHCIPORTTASKSTATESGENTRY  pSGInfoCurr  = NULL;
    5397     PAHCIPORTTASKSTATESGENTRY  pSGInfoPrev  = NULL;
    5398     PRTSGSEG                   pSGEntryCurr = NULL;
    5399     PRTSGSEG                   pSGEntryPrev = NULL;
    5400     RTGCPHYS                   GCPhysBufferPageAlignedPrev = NIL_RTGCPHYS;
    5401     uint8_t                   *pu8BufferUnalignedPos = NULL;
    5402     uint32_t                   cbUnalignedComplete = 0;
    5403 
    5404     STAM_PROFILE_START(&pAhciPort->StatProfileMapIntoR3, a);
    5405 
    5406     pAhciPortTaskState->cbSGBuffers = 0;
    5407 
    5408     /*
    5409      * Create a safe mapping when doing post processing because the size of the
    5410      * data to transfer and the amount of guest memory reserved can differ.
    5411      *
    5412      * @fixme: Read performance is really bad on OS X hosts because there is no
    5413      *         S/G support and the I/O manager has to create a newrequest
    5414      *         for every segment. The default limit of active requests is 16 on OS X
    5415      *         which causes a the bad read performance (writes are not affected
    5416      *         because of the writeback cache).
    5417      *         For now we will always use an intermediate buffer until
    5418      *         there is support for host S/G operations.
    5419      */
    5420     if (pAhciPortTaskState->pfnPostProcess || true)
    5421     {
    5422         ahciLog(("%s: Request with post processing.\n", __FUNCTION__));
    5423 
    5424         ahciScatterGatherListGetTotalBufferSize(pAhciPort, pAhciPortTaskState);
    5425 
    5426         return ahciScatterGatherListCreateSafe(pAhciPort, pAhciPortTaskState, fReadonly, 0);
    5427     }
    5428 
    5429     /*
    5430      * We need to calculate the number of SG list entries in R3 first because the data buffers in the guest don't need to be
    5431      * page aligned. Hence the number of SG list entries in the guest can differ from the ones we need
    5432      * because PDMDevHlpPhysGCPhys2CCPtr works only on a page base.
    5433      * In the first pass we calculate the number of segments in R3 and in the second pass we map the guest segments into R3.
    5434      */
    5435     for (int i = 0; i < 2; i++)
    5436     {
    5437         cSGLEntriesGCLeft = AHCI_CMDHDR_PRDTL_ENTRIES(pCmdHdr->u32DescInf);
    5438         ahciLog(("%s: cSGEntriesGC=%u\n", __FUNCTION__, cSGLEntriesGCLeft));
    5439 
    5440         /* Set start address of the entries. */
    5441         GCPhysAddrPRDTLEntryStart = AHCI_RTGCPHYS_FROM_U32(pCmdHdr->u32CmdTblAddrUp, pCmdHdr->u32CmdTblAddr) + AHCI_CMDHDR_PRDT_OFFSET;
    5442         fUnaligned  = false;
    5443         cbUnaligned = 0;
    5444         cUnaligned  = 0;
    5445         GCPhysBufferPageAlignedPrev = NIL_RTGCPHYS;
    5446 
    5447         if (fDoMapping)
    5448         {
    5449             ahciLog(("%s: cSGEntriesR3=%u\n", __FUNCTION__, cSGEntriesR3));
    5450             /* The number of needed SG entries in R3 is known. Allocate needed memory. */
    5451             rc = ahciScatterGatherListAllocate(pAhciPortTaskState, cSGEntriesR3, cbUnalignedComplete);
    5452             AssertMsgRC(rc, ("Failed to allocate scatter gather array rc=%Rrc\n", rc));
    5453 
    5454             /* We are now able to map the pages into R3. */
    5455             pSGInfoCurr  = pAhciPortTaskState->paSGEntries;
    5456             pSGEntryCurr = pAhciPortTaskState->pSGListHead;
    5457             pSGEntryPrev = pSGEntryCurr;
    5458             pSGInfoPrev  = pSGInfoCurr;
    5459             /* Initialize first segment to remove the need for additional if checks later in the code. */
    5460             pSGEntryCurr->pvSeg = NULL;
    5461             pSGEntryCurr->cbSeg = 0;
    5462             pSGInfoCurr->fGuestMemory= false;
    5463             pu8BufferUnalignedPos = (uint8_t *)pAhciPortTaskState->pvBufferUnaligned;
    5464             pAhciPortTaskState->cSGListUsed = 0;
    5465             pAhciPortTaskState->cbSGBuffers = cbSGBuffers;
    5466         }
    5467 
    5468         do
    5469         {
    5470             cSGLEntriesGCRead = (cSGLEntriesGCLeft < RT_ELEMENTS(aSGLEntry)) ? cSGLEntriesGCLeft : RT_ELEMENTS(aSGLEntry);
    5471             cSGLEntriesGCLeft -= cSGLEntriesGCRead;
    5472 
    5473             /* Read the SG entries. */
    5474             PDMDevHlpPhysRead(pDevIns, GCPhysAddrPRDTLEntryStart, &aSGLEntry[0], cSGLEntriesGCRead * sizeof(SGLEntry));
    5475 
    5476             for (cActualSGEntry = 0; cActualSGEntry < cSGLEntriesGCRead; cActualSGEntry++)
     5251 * @param   pAhciReq    The request state.
     5252 * @param   cbTransfer  Amount of bytes to allocate.
     5253 */
     5254static int ahciIoBufAllocate(PPDMDEVINS pDevIns, PAHCIREQ pAhciReq, size_t cbTransfer)
     5255{
     5256    AssertMsg(   pAhciReq->enmTxDir == AHCITXDIR_READ
     5257              || pAhciReq->enmTxDir == AHCITXDIR_WRITE,
     5258              ("Allocating I/O memory for a non I/O request is not allowed\n"));
     5259
     5260    pAhciReq->u.Io.DataSeg.pvSeg = RTMemAllocZ(cbTransfer);
     5261    if (!pAhciReq->u.Io.DataSeg.pvSeg)
     5262        return VERR_NO_MEMORY;
     5263
     5264    pAhciReq->u.Io.DataSeg.cbSeg = cbTransfer;
     5265    if (pAhciReq->enmTxDir == AHCITXDIR_WRITE)
     5266    {
     5267        ahciCopyFromPrdtl(pDevIns, pAhciReq,
     5268                          pAhciReq->u.Io.DataSeg.pvSeg,
     5269                          cbTransfer);
     5270    }
     5271    return VINF_SUCCESS;
     5272}
     5273
     5274static void ahciIoBufFree(PPDMDEVINS pDevIns, PAHCIREQ pAhciReq,
     5275                          bool fCopyToGuest)
     5276{
     5277    AssertMsg(   pAhciReq->enmTxDir == AHCITXDIR_READ
     5278              || pAhciReq->enmTxDir == AHCITXDIR_WRITE,
     5279              ("Freeing I/O memory for a non I/O request is not allowed\n"));
     5280
     5281    if (   pAhciReq->enmTxDir == AHCITXDIR_READ
     5282        && fCopyToGuest)
     5283    {
     5284        if (pAhciReq->u.Io.pfnPostProcess)
     5285        {
     5286            void *pv = NULL;
     5287            size_t cb = 0;
     5288            int rc = pAhciReq->u.Io.pfnPostProcess(pAhciReq, &pv, &cb);
     5289
     5290            if (RT_SUCCESS(rc))
    54775291            {
    5478                 RTGCPHYS    GCPhysAddrDataBase;
    5479                 uint32_t    cbDataToTransfer;
    5480 
    5481                 ahciLog(("%s: cActualSGEntry=%u cSGEntriesR3=%u\n", __FUNCTION__, cActualSGEntry, cSGEntriesR3));
    5482 
    5483                 cbDataToTransfer = (aSGLEntry[cActualSGEntry].u32DescInf & SGLENTRY_DESCINF_DBC) + 1;
    5484                 ahciLog(("%s: cbDataToTransfer=%u\n", __FUNCTION__, cbDataToTransfer));
    5485                 cbSGBuffers += cbDataToTransfer;
    5486 
    5487                 /* Check if the buffer is sector aligned. */
    5488                 if (cbDataToTransfer % 512 != 0)
    5489                 {
    5490                     if (!fUnaligned)
    5491                     {
    5492                         /* We are not in an unaligned buffer but this is the first unaligned one. */
    5493                         fUnaligned  = true;
    5494                         cbUnaligned = cbDataToTransfer;
    5495                         GCPhysAddrPRDTLUnalignedStart = GCPhysAddrPRDTLEntryStart + cActualSGEntry * sizeof(SGLEntry);
    5496                         cSGEntriesR3++;
    5497                         cUnaligned = 1;
    5498                         ahciLog(("%s: Unaligned buffer found cb=%d\n", __FUNCTION__, cbDataToTransfer));
    5499                     }
    5500                     else
    5501                     {
    5502                         /* We are already in an unaligned buffer and this one is unaligned too. */
    5503                         cbUnaligned += cbDataToTransfer;
    5504                         cUnaligned++;
    5505                     }
    5506 
    5507                     cbUnalignedComplete += cbDataToTransfer;
    5508                 }
    5509                 else /* Guest segment size is sector aligned. */
    5510                 {
    5511                     if (fUnaligned)
    5512                     {
    5513                         if (cbUnaligned % 512 == 0)
    5514                         {
    5515                             /*
    5516                              * The last buffer started at an offset
    5517                              * not aligned to a sector boundary but this buffer
    5518                              * is sector aligned. Check if the current size of all
    5519                              * unaligned segments is a multiple of a sector.
    5520                              * If that's the case we can now map the segments again into R3.
    5521                              */
    5522                             fUnaligned = false;
    5523 
    5524                             if (fDoMapping)
    5525                             {
    5526                                 /* Set up the entry. */
    5527                                 pSGInfoCurr->fGuestMemory = false;
    5528                                 pSGInfoCurr->u.temp.GCPhysAddrBaseFirstUnaligned = GCPhysAddrPRDTLUnalignedStart;
    5529                                 pSGInfoCurr->u.temp.cUnaligned = cUnaligned;
    5530                                 pSGInfoCurr->u.temp.pvBuf      = pu8BufferUnalignedPos;
    5531 
    5532                                 pSGEntryCurr->pvSeg    = pu8BufferUnalignedPos;
    5533                                 pSGEntryCurr->cbSeg    = cbUnaligned;
    5534                                 pu8BufferUnalignedPos += cbUnaligned;
    5535 
    5536                                 /*
    5537                                  * If the transfer is to the device we need to copy the content of the not mapped guest
    5538                                  * segments into the temporary buffer.
    5539                                  */
    5540                                 if (pAhciPortTaskState->enmTxDir == AHCITXDIR_WRITE)
    5541                                     ahciCopyFromSGListIntoBuffer(pDevIns, pSGInfoCurr);
    5542 
    5543                                 /* Advance to next entry saving the pointers to the current ones. */
    5544                                 pSGEntryPrev = pSGEntryCurr;
    5545                                 pSGInfoPrev  = pSGInfoCurr;
    5546                                 pSGInfoCurr++;
    5547                                 pSGEntryCurr++;
    5548                                 pAhciPortTaskState->cSGListUsed++;
    5549                                 cSGEntriesProcessed++;
    5550                             }
    5551                         }
    5552                         else
    5553                         {
    5554                             cbUnaligned         += cbDataToTransfer;
    5555                             cbUnalignedComplete += cbDataToTransfer;
    5556                             cUnaligned++;
    5557                         }
    5558                     }
    5559                     else
    5560                     {
    5561                         /*
    5562                          * The size of the guest segment is sector aligned but it is possible that the segment crosses
    5563                          * a page boundary in a way splitting the segment into parts which are not sector aligned.
    5564                          * We have to treat them like unaligned guest segments then.
    5565                          */
    5566                         GCPhysAddrDataBase = AHCI_RTGCPHYS_FROM_U32(aSGLEntry[cActualSGEntry].u32DBAUp, aSGLEntry[cActualSGEntry].u32DBA);
    5567 
    5568                         ahciLog(("%s: GCPhysAddrDataBase=%RGp\n", __FUNCTION__, GCPhysAddrDataBase));
    5569 
    5570                         /*
    5571                          * Check if the physical address is page aligned.
    5572                          */
    5573                         if (GCPhysAddrDataBase & PAGE_OFFSET_MASK)
    5574                         {
    5575                             RTGCPHYS    GCPhysAddrDataNextPage = PHYS_PAGE_ADDRESS(GCPhysAddrDataBase) + PAGE_SIZE;
    5576                             /* Difference from the buffer start to the next page boundary. */
    5577                             uint32_t    u32GCPhysAddrDiff = GCPhysAddrDataNextPage - GCPhysAddrDataBase;
    5578 
    5579                             if (u32GCPhysAddrDiff % 512 != 0)
    5580                             {
    5581                                 if (!fUnaligned)
    5582                                 {
    5583                                     /* We are not in an unaligned buffer but this is the first unaligned one. */
    5584                                     fUnaligned  = true;
    5585                                     cbUnaligned = cbDataToTransfer;
    5586                                     GCPhysAddrPRDTLUnalignedStart = GCPhysAddrPRDTLEntryStart + cActualSGEntry * sizeof(SGLEntry);
    5587                                     cSGEntriesR3++;
    5588                                     cUnaligned = 1;
    5589                                     ahciLog(("%s: Guest segment is sector aligned but crosses a page boundary cb=%d\n", __FUNCTION__, cbDataToTransfer));
    5590                                 }
    5591                                 else
    5592                                 {
    5593                                     /* We are already in an unaligned buffer and this one is unaligned too. */
    5594                                     cbUnaligned += cbDataToTransfer;
    5595                                     cUnaligned++;
    5596                                 }
    5597 
    5598                                 cbUnalignedComplete += cbDataToTransfer;
    5599                             }
    5600                             else
    5601                             {
    5602                                 ahciLog(("%s: Align page: GCPhysAddrDataBase=%RGp GCPhysAddrDataNextPage=%RGp\n",
    5603                                          __FUNCTION__, GCPhysAddrDataBase, GCPhysAddrDataNextPage));
    5604 
    5605                                 RTGCPHYS GCPhysBufferPageAligned = PHYS_PAGE_ADDRESS(GCPhysAddrDataBase);
    5606 
    5607                                 /* Check if the mapping ends at the page boundary and set segment size accordingly. */
    5608                                 cbSegment =   (cbDataToTransfer < u32GCPhysAddrDiff)
    5609                                             ? cbDataToTransfer
    5610                                             : u32GCPhysAddrDiff;
    5611                                 /* Subtract size of the buffer in the actual page. */
    5612                                 cbDataToTransfer -= cbSegment;
    5613 
    5614                                 if (GCPhysBufferPageAlignedPrev != GCPhysBufferPageAligned)
    5615                                 {
    5616                                     /* We don't need to map the buffer if it is in the same page as the previous one. */
    5617                                     if (fDoMapping)
    5618                                     {
    5619                                         uint8_t *pbMapping;
    5620 
    5621                                         pSGInfoCurr->fGuestMemory = true;
    5622 
    5623                                         /* Create the mapping. */
    5624                                         if (fReadonly)
    5625                                             rc = PDMDevHlpPhysGCPhys2CCPtrReadOnly(pDevIns, GCPhysBufferPageAligned,
    5626                                                                                    0, (const void **)&pbMapping,
    5627                                                                                    &pSGInfoCurr->u.direct.PageLock);
    5628                                         else
    5629                                             rc = PDMDevHlpPhysGCPhys2CCPtr(pDevIns, GCPhysBufferPageAligned,
    5630                                                                            0, (void **)&pbMapping,
    5631                                                                            &pSGInfoCurr->u.direct.PageLock);
    5632 
    5633                                         if (RT_FAILURE(rc))
    5634                                         {
    5635                                             /* Mapping failed. Fall back to a bounce buffer. */
    5636                                             ahciLog(("%s: Mapping guest physical address %RGp failed with rc=%Rrc\n",
    5637                                                      __FUNCTION__, GCPhysBufferPageAligned, rc));
    5638 
    5639                                             return ahciScatterGatherListCreateSafe(pAhciPort, pAhciPortTaskState, fReadonly,
    5640                                                                                    cSGEntriesProcessed);
    5641                                         }
    5642 
    5643                                         if ((pbMapping + (GCPhysAddrDataBase - GCPhysBufferPageAligned) == ((uint8_t *)pSGEntryPrev->pvSeg + pSGEntryCurr->cbSeg)))
    5644                                         {
    5645                                             pSGEntryPrev->cbSeg += cbSegment;
    5646                                             ahciLog(("%s: Merged mapping pbMapping=%#p into current segment pvSeg=%#p. New size is cbSeg=%d\n",
    5647                                                      __FUNCTION__, pbMapping, pSGEntryPrev->pvSeg, pSGEntryPrev->cbSeg));
    5648                                         }
    5649                                         else
    5650                                         {
    5651                                             pSGEntryCurr->cbSeg = cbSegment;
    5652 
    5653                                             /* Let pvBuf point to the start of the buffer in the page. */
    5654                                             pSGEntryCurr->pvSeg =   pbMapping
    5655                                                                   + (GCPhysAddrDataBase - GCPhysBufferPageAligned);
    5656 
    5657                                             ahciLog(("%s: pvSegBegin=%#p pvSegEnd=%#p\n", __FUNCTION__,
    5658                                                      pSGEntryCurr->pvSeg,
    5659                                                      (uint8_t *)pSGEntryCurr->pvSeg + pSGEntryCurr->cbSeg));
    5660 
    5661                                             pSGEntryPrev = pSGEntryCurr;
    5662                                             pSGEntryCurr++;
    5663                                             pAhciPortTaskState->cSGListUsed++;
    5664                                         }
    5665 
    5666                                         pSGInfoPrev  = pSGInfoCurr;
    5667                                         pSGInfoCurr++;
    5668                                         cSGEntriesProcessed++;
    5669                                     }
    5670                                     else
    5671                                         cSGEntriesR3++;
    5672                                 }
    5673                                 else if (fDoMapping)
    5674                                 {
    5675                                     pSGEntryPrev->cbSeg += cbSegment;
    5676                                     ahciLog(("%s: Buffer is already in previous mapping pvSeg=%#p. New size is cbSeg=%d\n",
    5677                                                 __FUNCTION__, pSGEntryPrev->pvSeg, pSGEntryPrev->cbSeg));
    5678                                 }
    5679 
    5680                                 /* Let physical address point to the next page in the buffer. */
    5681                                 GCPhysAddrDataBase = GCPhysAddrDataNextPage;
    5682                                 GCPhysBufferPageAlignedPrev = GCPhysBufferPageAligned;
    5683                             }
    5684                         }
    5685 
    5686                         if (!fUnaligned)
    5687                         {
    5688                             /* The address is now page aligned. */
    5689                             while (cbDataToTransfer)
    5690                             {
    5691                                 ahciLog(("%s: GCPhysAddrDataBase=%RGp cbDataToTransfer=%u cSGEntriesR3=%u\n",
    5692                                          __FUNCTION__, GCPhysAddrDataBase, cbDataToTransfer, cSGEntriesR3));
    5693 
    5694                                 /* Check if this is the last page the buffer is in. */
    5695                                 cbSegment = (cbDataToTransfer < PAGE_SIZE) ? cbDataToTransfer : PAGE_SIZE;
    5696                                 cbDataToTransfer -= cbSegment;
    5697 
    5698                                 if (fDoMapping)
    5699                                 {
    5700                                     void *pvMapping;
    5701 
    5702                                     pSGInfoCurr->fGuestMemory = true;
    5703 
    5704                                     /* Create the mapping. */
    5705                                     if (fReadonly)
    5706                                         rc = PDMDevHlpPhysGCPhys2CCPtrReadOnly(pDevIns, GCPhysAddrDataBase, 0, (const void **)&pvMapping, &pSGInfoCurr->u.direct.PageLock);
    5707                                     else
    5708                                         rc = PDMDevHlpPhysGCPhys2CCPtr(pDevIns, GCPhysAddrDataBase, 0, &pvMapping, &pSGInfoCurr->u.direct.PageLock);
    5709 
    5710                                     if (RT_FAILURE(rc))
    5711                                     {
    5712                                         /* Mapping failed. Fall back to a bounce buffer. */
    5713                                         ahciLog(("%s: Mapping guest physical address %RGp failed with rc=%Rrc\n",
    5714                                                     __FUNCTION__, GCPhysAddrDataBase, rc));
    5715 
    5716                                         return ahciScatterGatherListCreateSafe(pAhciPort, pAhciPortTaskState, fReadonly,
    5717                                                                                cSGEntriesProcessed);
    5718                                     }
    5719 
    5720                                     /* Check for adjacent mappings. */
    5721                                     if (pvMapping == ((uint8_t *)pSGEntryPrev->pvSeg + pSGEntryPrev->cbSeg)
    5722                                         && (pSGInfoPrev->fGuestMemory == true))
    5723                                     {
    5724                                         /* Yes they are adjacent. Just add the size of this mapping to the previous segment. */
    5725                                         pSGEntryPrev->cbSeg += cbSegment;
    5726                                         ahciLog(("%s: Merged mapping pvMapping=%#p into current segment pvSeg=%#p. New size is cbSeg=%d\n",
    5727                                                  __FUNCTION__, pvMapping, pSGEntryPrev->pvSeg, pSGEntryPrev->cbSeg));
    5728                                     }
    5729                                     else
    5730                                     {
    5731                                         /* No they are not. Use a new sg entry. */
    5732                                         pSGEntryCurr->cbSeg       = cbSegment;
    5733                                         pSGEntryCurr->pvSeg       = pvMapping;
    5734                                         ahciLog(("%s: pvSegBegin=%#p pvSegEnd=%#p\n", __FUNCTION__,
    5735                                                  pSGEntryCurr->pvSeg,
    5736                                                  (uint8_t *)pSGEntryCurr->pvSeg + pSGEntryCurr->cbSeg));
    5737                                         pSGEntryPrev = pSGEntryCurr;
    5738                                         pSGEntryCurr++;
    5739                                         pAhciPortTaskState->cSGListUsed++;
    5740                                     }
    5741 
    5742                                     pSGInfoPrev = pSGInfoCurr;
    5743                                     pSGInfoCurr++;
    5744                                     cSGEntriesProcessed++;
    5745                                 }
    5746                                 else
    5747                                     cSGEntriesR3++;
    5748 
    5749                                 GCPhysBufferPageAlignedPrev = GCPhysAddrDataBase;
    5750 
    5751                                 /* Go to the next page. */
    5752                                 GCPhysAddrDataBase += PAGE_SIZE;
    5753                             }
    5754                         } /* if (!fUnaligned) */
    5755                     } /* if !fUnaligned */
    5756                 } /* if guest segment is sector aligned. */
    5757             } /* for SGEntries read */
    5758 
    5759             /* Set address to the next entries to read. */
    5760             GCPhysAddrPRDTLEntryStart += cSGLEntriesGCRead * sizeof(SGLEntry);
    5761 
    5762         } while (cSGLEntriesGCLeft);
    5763 
    5764         fDoMapping = true;
    5765 
    5766     } /* for passes */
    5767 
    5768     /* Check if the last processed segment was unaligned. We need to add it now. */
    5769     if (fUnaligned)
    5770     {
    5771         /* Set up the entry. */
    5772         AssertMsg(!(cbUnaligned % 512), ("Buffer is not sector aligned\n"));
    5773         pSGInfoCurr->fGuestMemory = false;
    5774         pSGInfoCurr->u.temp.GCPhysAddrBaseFirstUnaligned = GCPhysAddrPRDTLUnalignedStart;
    5775         pSGInfoCurr->u.temp.cUnaligned = cUnaligned;
    5776         pSGInfoCurr->u.temp.pvBuf = pu8BufferUnalignedPos;
    5777 
    5778         pSGEntryCurr->pvSeg    = pu8BufferUnalignedPos;
    5779         pSGEntryCurr->cbSeg    = cbUnaligned;
    5780         pAhciPortTaskState->cSGListUsed++;
    5781 
    5782         /*
    5783          * If the transfer is to the device we need to copy the content of the not mapped guest
    5784          * segments into the temporary buffer.
    5785          */
    5786         if (pAhciPortTaskState->enmTxDir == AHCITXDIR_WRITE)
    5787             ahciCopyFromSGListIntoBuffer(pDevIns, pSGInfoCurr);
    5788     }
    5789 
    5790     STAM_PROFILE_STOP(&pAhciPort->StatProfileMapIntoR3, a);
    5791 
    5792     return rc;
    5793 }
    5794 
    5795 /**
    5796  * Free all memory of the scatter gather list.
    5797  *
    5798  * @returns nothing.
    5799  * @param   pAhciPortTaskState    Task state.
    5800  */
    5801 static void ahciScatterGatherListFree(PAHCIPORTTASKSTATE pAhciPortTaskState)
    5802 {
    5803     if (pAhciPortTaskState->pSGListHead)
    5804         RTMemFree(pAhciPortTaskState->pSGListHead);
    5805     if (pAhciPortTaskState->paSGEntries)
    5806         RTMemFree(pAhciPortTaskState->paSGEntries);
    5807     if (pAhciPortTaskState->pvBufferUnaligned)
    5808         RTMemPageFree(pAhciPortTaskState->pvBufferUnaligned, pAhciPortTaskState->cbBufferUnaligned);
    5809 
    5810     /* Safety. */
    5811     pAhciPortTaskState->cSGListSize = 0;
    5812     pAhciPortTaskState->cSGListTooBig = 0;
    5813     pAhciPortTaskState->pSGListHead = NULL;
    5814     pAhciPortTaskState->paSGEntries = NULL;
    5815     pAhciPortTaskState->pvBufferUnaligned = NULL;
    5816     pAhciPortTaskState->cbBufferUnaligned = 0;
    5817 }
    5818 
    5819 /**
    5820  * Destroy a scatter gather list and free all occupied resources (mappings, etc.)
    5821  *
    5822  * @returns VBox status code.
    5823  * @param   pAhciPort   The ahci port.
    5824  * @param   pAhciPortTaskState    The task state which contains the S/G list entries.
    5825  */
    5826 static int ahciScatterGatherListDestroy(PAHCIPort pAhciPort, PAHCIPORTTASKSTATE pAhciPortTaskState)
    5827 {
    5828     PAHCIPORTTASKSTATESGENTRY  pSGInfoCurr  = pAhciPortTaskState->paSGEntries;
    5829     PPDMDEVINS                 pDevIns      = pAhciPort->CTX_SUFF(pDevIns);
    5830 
    5831     STAM_PROFILE_START(&pAhciPort->StatProfileDestroyScatterGatherList, a);
    5832 
    5833     if (pAhciPortTaskState->pfnPostProcess)
    5834     {
    5835         int rc;
    5836         rc = pAhciPortTaskState->pfnPostProcess(pAhciPortTaskState);
    5837         AssertRC(rc);
    5838 
    5839         pAhciPortTaskState->pfnPostProcess = NULL;
    5840 
    5841         /* Free the buffer holding the unprocessed data. They are not needed anymore. */
    5842         RTMemFree(pAhciPortTaskState->pSGListHead[0].pvSeg);
    5843     }
    5844 
    5845     for (unsigned cActualSGEntry = 0; cActualSGEntry < pAhciPortTaskState->cSGEntries; cActualSGEntry++)
    5846     {
    5847         if (pSGInfoCurr->fGuestMemory)
    5848         {
    5849             /* Release the lock. */
    5850             PDMDevHlpPhysReleasePageMappingLock(pDevIns, &pSGInfoCurr->u.direct.PageLock);
    5851         }
    5852         else if (pAhciPortTaskState->enmTxDir == AHCITXDIR_READ)
    5853         {
    5854             /* Copy the data into the guest segments now. */
    5855             ahciCopyFromBufferIntoSGList(pDevIns, pSGInfoCurr);
    5856         }
    5857 
    5858         /* Go to the next entry. */
    5859         pSGInfoCurr++;
    5860     }
    5861 
    5862     /* Free allocated memory if the list was too big too many times. */
    5863     if (pAhciPortTaskState->cSGListTooBig >= AHCI_NR_OF_ALLOWED_BIGGER_LISTS)
    5864         ahciScatterGatherListFree(pAhciPortTaskState);
    5865 
    5866     STAM_PROFILE_STOP(&pAhciPort->StatProfileDestroyScatterGatherList, a);
    5867 
    5868     return VINF_SUCCESS;
    5869 }
    5870 
    5871 /**
    5872  * Copy a temporary buffer into a part of the guest scatter gather list
    5873  * described by the given descriptor entry.
    5874  *
    5875  * @returns nothing.
    5876  * @param   pDevIns    Pointer to the device instance data.
    5877  * @param   pSGInfo    Pointer to the segment info structure which describes the guest segments
    5878  *                     to write to which are unaligned.
    5879  */
    5880 static void ahciCopyFromBufferIntoSGList(PPDMDEVINS pDevIns, PAHCIPORTTASKSTATESGENTRY pSGInfo)
    5881 {
    5882     uint8_t *pu8Buf    = (uint8_t *)pSGInfo->u.temp.pvBuf;
    5883     SGLEntry aSGLEntries[5];
    5884     uint32_t cSGEntriesLeft = pSGInfo->u.temp.cUnaligned;
    5885     RTGCPHYS GCPhysPRDTLStart = pSGInfo->u.temp.GCPhysAddrBaseFirstUnaligned;
    5886 
    5887     AssertMsg(!pSGInfo->fGuestMemory, ("This is not possible\n"));
    5888 
    5889     do
    5890     {
    5891         uint32_t cSGEntriesRead =   (cSGEntriesLeft < RT_ELEMENTS(aSGLEntries))
    5892                                   ? cSGEntriesLeft
    5893                                   : RT_ELEMENTS(aSGLEntries);
    5894 
    5895         PDMDevHlpPhysRead(pDevIns, GCPhysPRDTLStart, &aSGLEntries[0], cSGEntriesRead * sizeof(SGLEntry));
    5896 
    5897         for (uint32_t i = 0; i < cSGEntriesRead; i++)
    5898         {
    5899             RTGCPHYS GCPhysAddrDataBase = AHCI_RTGCPHYS_FROM_U32(aSGLEntries[i].u32DBAUp, aSGLEntries[i].u32DBA);
    5900             uint32_t cbCopied = (aSGLEntries[i].u32DescInf & SGLENTRY_DESCINF_DBC) + 1;
    5901 
    5902             /* Copy into SG entry. */
    5903             PDMDevHlpPhysWrite(pDevIns, GCPhysAddrDataBase, pu8Buf, cbCopied);
    5904 
    5905             pu8Buf    += cbCopied;
    5906         }
    5907 
    5908         GCPhysPRDTLStart += cSGEntriesRead * sizeof(SGLEntry);
    5909         cSGEntriesLeft   -= cSGEntriesRead;
    5910     } while (cSGEntriesLeft);
    5911 }
    5912 
    5913 /**
    5914  * Copy a part of the guest scatter gather list into a temporary buffer.
    5915  *
    5916  * @returns nothing.
    5917  * @param   pDevIns    Pointer to the device instance data.
    5918  * @param   pSGInfo    Pointer to the segment info structure which describes the guest segments
    5919  *                     to read from which are unaligned.
    5920  */
    5921 static void ahciCopyFromSGListIntoBuffer(PPDMDEVINS pDevIns, PAHCIPORTTASKSTATESGENTRY pSGInfo)
    5922 {
    5923     uint8_t *pu8Buf    = (uint8_t *)pSGInfo->u.temp.pvBuf;
    5924     SGLEntry aSGLEntries[5];
    5925     uint32_t cSGEntriesLeft = pSGInfo->u.temp.cUnaligned;
    5926     RTGCPHYS GCPhysPRDTLStart = pSGInfo->u.temp.GCPhysAddrBaseFirstUnaligned;
    5927 
    5928     AssertMsg(!pSGInfo->fGuestMemory, ("This is not possible\n"));
    5929 
    5930     do
    5931     {
    5932         uint32_t cSGEntriesRead =   (cSGEntriesLeft < RT_ELEMENTS(aSGLEntries))
    5933                                   ? cSGEntriesLeft
    5934                                   : RT_ELEMENTS(aSGLEntries);
    5935 
    5936         PDMDevHlpPhysRead(pDevIns, GCPhysPRDTLStart, &aSGLEntries[0], cSGEntriesRead * sizeof(SGLEntry));
    5937 
    5938         for (uint32_t i = 0; i < cSGEntriesRead; i++)
    5939         {
    5940             RTGCPHYS GCPhysAddrDataBase = AHCI_RTGCPHYS_FROM_U32(aSGLEntries[i].u32DBAUp, aSGLEntries[i].u32DBA);
    5941             uint32_t cbCopied = (aSGLEntries[i].u32DescInf & SGLENTRY_DESCINF_DBC) + 1;
    5942 
    5943             /* Copy into buffer. */
    5944             PDMDevHlpPhysRead(pDevIns, GCPhysAddrDataBase, pu8Buf, cbCopied);
    5945 
    5946             pu8Buf    += cbCopied;
    5947         }
    5948 
    5949         GCPhysPRDTLStart += cSGEntriesRead * sizeof(SGLEntry);
    5950         cSGEntriesLeft   -= cSGEntriesRead;
    5951     } while (cSGEntriesLeft);
    5952 }
    5953 
    5954 /**
    5955  * Copy the content of a buffer to a scatter gather list.
    5956  *
    5957  * @returns Number of bytes transferred.
    5958  * @param   pAhciPortTaskState    The task state which contains the S/G list entries.
    5959  * @param   pvBuf                 Pointer to the buffer which should be copied.
    5960  * @param   cbBuf                 Size of the buffer.
    5961  */
    5962 static int ahciScatterGatherListCopyFromBuffer(PAHCIPORTTASKSTATE pAhciPortTaskState, void *pvBuf, size_t cbBuf)
    5963 {
    5964     unsigned cSGEntry = 0;
    5965     size_t cbCopied = 0;
    5966     PRTSGSEG pSGEntry = &pAhciPortTaskState->pSGListHead[cSGEntry];
    5967     uint8_t *pu8Buf = (uint8_t *)pvBuf;
    5968 
    5969     while (cSGEntry < pAhciPortTaskState->cSGEntries)
    5970     {
    5971         size_t cbToCopy = RT_MIN(cbBuf, pSGEntry->cbSeg);
    5972 
    5973         memcpy(pSGEntry->pvSeg, pu8Buf, cbToCopy);
    5974 
    5975         cbBuf -= cbToCopy;
    5976         cbCopied += cbToCopy;
    5977 
    5978         /* We finished. */
    5979         if (!cbBuf)
    5980             break;
    5981 
    5982         /* Advance the buffer. */
    5983         pu8Buf += cbToCopy;
    5984 
    5985         /* Go to the next entry in the list. */
    5986         pSGEntry++;
    5987         cSGEntry++;
    5988     }
    5989 
    5990     LogFlow(("%s: Copied %d bytes\n", __FUNCTION__, cbCopied));
    5991     return cbCopied;
    5992 }
     5292                ahciCopyToPrdtl(pDevIns, pAhciReq, pv, cb);
     5293                RTMemFree(pv);
     5294            }
     5295        }
     5296        else
     5297            ahciCopyToPrdtl(pDevIns, pAhciReq,
     5298                            pAhciReq->u.Io.DataSeg.pvSeg,
     5299                            pAhciReq->u.Io.DataSeg.cbSeg);
     5300    }
     5301
     5302    RTMemFree(pAhciReq->u.Io.DataSeg.pvSeg);
     5303    pAhciReq->u.Io.DataSeg.pvSeg = NULL;
     5304    pAhciReq->u.Io.DataSeg.cbSeg = 0;
     5305}
     5306
    59935307
    59945308/**
     
    60025316    for (unsigned i = 0; i < RT_ELEMENTS(pAhciPort->aCachedTasks); i++)
    60035317    {
    6004         PAHCIPORTTASKSTATE pAhciPortTaskState = pAhciPort->aCachedTasks[i];
    6005 
    6006         if (VALID_PTR(pAhciPortTaskState))
     5318        PAHCIREQ pAhciReq = pAhciPort->aCachedTasks[i];
     5319
     5320        if (VALID_PTR(pAhciReq))
    60075321        {
    60085322            bool fXchg = false;
    6009             ASMAtomicCmpXchgSize(&pAhciPortTaskState->enmTxState, AHCITXSTATE_CANCELED, AHCITXSTATE_ACTIVE, fXchg);
     5323            ASMAtomicCmpXchgSize(&pAhciReq->enmTxState, AHCITXSTATE_CANCELED, AHCITXSTATE_ACTIVE, fXchg);
    60105324
    60115325            if (fXchg)
     
    60215335                ASMAtomicWriteNullPtr(&pAhciPort->aCachedTasks[i]);
    60225336                LogRel(("AHCI#%dP%d: Cancelled task %u\n", pAhciPort->CTX_SUFF(pDevIns)->iInstance,
    6023                         pAhciPort->iLUN, pAhciPortTaskState->uTag));
     5337                        pAhciPort->iLUN, pAhciReq->uTag));
    60245338            }
    60255339            else
    6026                 AssertMsg(pAhciPortTaskState->enmTxState == AHCITXSTATE_FREE,
     5340                AssertMsg(pAhciReq->enmTxState == AHCITXSTATE_FREE,
    60275341                          ("Invalid task state, must be free!\n"));
    60285342        }
     
    60935407 *
    60945408 * @returns VBox status code.
    6095  * @param   pAhciPort             AHCI port state.
    6096  * @param   pAhciportTaskState    The task state handling the TRIM request.
    6097  */
    6098 static int ahciTrimRangesCreate(PAHCIPort pAhciPort, PAHCIPORTTASKSTATE pAhciPortTaskState)
    6099 {
    6100     RTSGBUF SgBuf;
     5409 * @param   pAhciPort    AHCI port state.
     5410 * @param   pAhciReq     The request handling the TRIM request.
     5411 */
     5412static int ahciTrimRangesCreate(PAHCIPort pAhciPort, PAHCIREQ pAhciReq)
     5413{
     5414    SGLEntry aPrdtlEntries[32];
    61015415    uint64_t aRanges[64];
    61025416    unsigned cRangesMax;
    61035417    unsigned cRanges = 0;
     5418    uint32_t cPrdtlEntries = pAhciReq->cPrdtlEntries;
     5419    RTGCPHYS GCPhysPrdtl   = pAhciReq->GCPhysPrdtl;
     5420    PPDMDEVINS pDevIns     = pAhciPort->CTX_SUFF(pDevIns);
    61045421    int rc = VINF_SUCCESS;
    61055422
    6106     /* First check that the trim bit is set and all other bits are 0. */
    6107     if (   !(pAhciPortTaskState->cmdFis[AHCI_CMDFIS_FET] & UINT16_C(0x01))
    6108         || (pAhciPortTaskState->cmdFis[AHCI_CMDFIS_FET] & ~UINT16_C(0x1)))
    6109         return VERR_INVALID_PARAMETER;
     5423    LogFlowFunc(("pAhciPort=%#p pAhciReq=%#p\n", pAhciPort, pAhciReq));
     5424
     5425    AssertMsgReturn(pAhciReq->enmTxDir == AHCITXDIR_TRIM, ("This is not a trim request\n"), VERR_INVALID_PARAMETER);
    61105426
    61115427    /* The data buffer contains LBA range entries. Each range is 8 bytes big. */
    6112     cRangesMax = pAhciPortTaskState->cbSGBuffers / 8;
    6113 
    6114     RTSgBufInit(&SgBuf, pAhciPortTaskState->pSGListHead, pAhciPortTaskState->cSGListUsed);
     5428    if (!pAhciReq->cmdFis[AHCI_CMDFIS_SECTC] && !pAhciReq->cmdFis[AHCI_CMDFIS_SECTCEXP])
     5429        cRangesMax = 65536 * 512 / 8;
     5430    else
     5431        cRangesMax = pAhciReq->cmdFis[AHCI_CMDFIS_SECTC] * 512 / 8;
     5432
     5433    if (!cPrdtlEntries)
     5434    {
     5435        pAhciReq->fFlags |= AHCI_REQ_OVERFLOW;
     5436        return VINF_SUCCESS;
     5437    }
    61155438
    61165439    do
    61175440    {
    6118         size_t cbCopied = RTSgBufCopyToBuf(&SgBuf, &aRanges[0], sizeof(aRanges));
    6119         Assert(cbCopied == sizeof(aRanges));
    6120 
    6121         /*
    6122          * Count the number of valid ranges in the buffer.
    6123          * A length of 0 is invalid and is only used for padding
    6124          */
    6125         for (unsigned i = 0; i < RT_ELEMENTS(aRanges); i++)
    6126         {
    6127             aRanges[i] = RT_H2LE_U64(aRanges[i]);
    6128             if (AHCI_RANGE_LENGTH_GET(aRanges[i]) != 0)
    6129                 cRanges++;
    6130             else
    6131                 break;
    6132         }
    6133 
    6134         cRangesMax -= 64;
    6135     } while (cRangesMax);
    6136 
    6137     AssertReturn(cRanges != 0, VERR_INVALID_PARAMETER);
    6138 
    6139     pAhciPortTaskState->paRanges = (PRTRANGE)RTMemAllocZ(sizeof(RTRANGE) * cRanges);
    6140     if (pAhciPortTaskState->paRanges)
    6141     {
    6142         uint32_t idxRange = 0;
    6143 
    6144         pAhciPortTaskState->cRanges = cRanges;
    6145         RTSgBufReset(&SgBuf);
    6146 
    6147         /* Convert the ranges from the guest to our format. */
    6148         do
    6149         {
    6150             size_t cbCopied = RTSgBufCopyToBuf(&SgBuf, &aRanges[0], sizeof(aRanges));
    6151             Assert(cbCopied == sizeof(aRanges));
    6152 
    6153             for (unsigned i = 0; i < RT_ELEMENTS(aRanges); i++)
     5441        uint32_t cPrdtlEntriesRead =   (cPrdtlEntries < RT_ELEMENTS(aPrdtlEntries))
     5442                                     ? cPrdtlEntries
     5443                                     : RT_ELEMENTS(aPrdtlEntries);
     5444
     5445        PDMDevHlpPhysRead(pDevIns, GCPhysPrdtl, &aPrdtlEntries[0], cPrdtlEntriesRead * sizeof(SGLEntry));
     5446
     5447        for (uint32_t i = 0; i < cPrdtlEntriesRead; i++)
     5448        {
     5449            RTGCPHYS GCPhysAddrDataBase = AHCI_RTGCPHYS_FROM_U32(aPrdtlEntries[i].u32DBAUp, aPrdtlEntries[i].u32DBA);
     5450            uint32_t cbThisCopy = (aPrdtlEntries[i].u32DescInf & SGLENTRY_DESCINF_DBC) + 1;
     5451
     5452            cbThisCopy = RT_MIN(cbThisCopy, sizeof(aRanges));
     5453
     5454            /* Copy into buffer. */
     5455            PDMDevHlpPhysRead(pDevIns, GCPhysAddrDataBase, aRanges, cbThisCopy);
     5456
     5457            for (unsigned idxRange = 0; idxRange < RT_ELEMENTS(aRanges); idxRange++)
    61545458            {
    6155                 aRanges[i] = RT_H2LE_U64(aRanges[i]);
    6156                 if (AHCI_RANGE_LENGTH_GET(aRanges[i]) != 0)
    6157                 {
    6158                     pAhciPortTaskState->paRanges[idxRange].offStart = (aRanges[i] & AHCI_RANGE_LBA_MASK) * 512;
    6159                     pAhciPortTaskState->paRanges[idxRange].cbRange = AHCI_RANGE_LENGTH_GET(aRanges[i]) * 512;
    6160                     idxRange++;
    6161                 }
     5459                aRanges[idxRange] = RT_H2LE_U64(aRanges[idxRange]);
     5460                if (AHCI_RANGE_LENGTH_GET(aRanges[idxRange]) != 0)
     5461                    cRanges++;
    61625462                else
    61635463                    break;
    61645464            }
     5465        }
     5466
     5467        GCPhysPrdtl   += cPrdtlEntriesRead * sizeof(SGLEntry);
     5468        cPrdtlEntries -= cPrdtlEntriesRead;
     5469    } while (cPrdtlEntries);
     5470
     5471    if (RT_UNLIKELY(!cRanges))
     5472    {
     5473        return VERR_BUFFER_OVERFLOW;
     5474    }
     5475
     5476    pAhciReq->u.Trim.cRanges = cRanges;
     5477    pAhciReq->u.Trim.paRanges = (PRTRANGE)RTMemAllocZ(sizeof(RTRANGE) * cRanges);
     5478    if (pAhciReq->u.Trim.paRanges)
     5479    {
     5480        uint32_t idxRange = 0;
     5481
     5482        cPrdtlEntries = pAhciReq->cPrdtlEntries;
     5483        GCPhysPrdtl   = pAhciReq->GCPhysPrdtl;
     5484
     5485        /* Convert the ranges from the guest to our format. */
     5486        do
     5487        {
     5488            uint32_t cPrdtlEntriesRead =   (cPrdtlEntries < RT_ELEMENTS(aPrdtlEntries))
     5489                                         ? cPrdtlEntries
     5490                                         : RT_ELEMENTS(aPrdtlEntries);
     5491
     5492            PDMDevHlpPhysRead(pDevIns, GCPhysPrdtl, &aPrdtlEntries[0], cPrdtlEntriesRead * sizeof(SGLEntry));
     5493
     5494            for (uint32_t i = 0; i < cPrdtlEntriesRead; i++)
     5495            {
     5496                RTGCPHYS GCPhysAddrDataBase = AHCI_RTGCPHYS_FROM_U32(aPrdtlEntries[i].u32DBAUp, aPrdtlEntries[i].u32DBA);
     5497                uint32_t cbThisCopy = (aPrdtlEntries[i].u32DescInf & SGLENTRY_DESCINF_DBC) + 1;
     5498
     5499                cbThisCopy = RT_MIN(cbThisCopy, sizeof(aRanges));
     5500
     5501                /* Copy into buffer. */
     5502                PDMDevHlpPhysRead(pDevIns, GCPhysAddrDataBase, aRanges, cbThisCopy);
     5503
     5504                for (unsigned idxRangeSrc = 0; idxRangeSrc < RT_ELEMENTS(aRanges); idxRangeSrc++)
     5505                {
     5506                    aRanges[idxRangeSrc] = RT_H2LE_U64(aRanges[idxRangeSrc]);
     5507                    if (AHCI_RANGE_LENGTH_GET(aRanges[idxRangeSrc]) != 0)
     5508                    {
     5509                        pAhciReq->u.Trim.paRanges[idxRange].offStart = (aRanges[idxRangeSrc] & AHCI_RANGE_LBA_MASK) * 512;
     5510                        pAhciReq->u.Trim.paRanges[idxRange].cbRange = AHCI_RANGE_LENGTH_GET(aRanges[idxRangeSrc]) * 512;
     5511                        idxRange++;
     5512                    }
     5513                    else
     5514                        break;
     5515                }
     5516            }
     5517
     5518            GCPhysPrdtl   += cPrdtlEntriesRead * sizeof(SGLEntry);
     5519            cPrdtlEntries -= cPrdtlEntriesRead;
    61655520        } while (idxRange < cRanges);
    61665521    }
    6167 
     5522    else
     5523        rc = VERR_NO_MEMORY;
     5524
     5525    LogFlowFunc(("returns rc=%Rrc\n", rc));
    61685526    return rc;
    61695527}
     
    61735531 *
    61745532 * @returns nothing.
    6175  * @param   pAhciPortTaskState    The task state.
    6176  */
    6177 static void ahciTrimRangesDestroy(PAHCIPORTTASKSTATE pAhciPortTaskState)
    6178 {
    6179     RTMemFree(pAhciPortTaskState->paRanges);
     5533 * @param   pAhciReq    The task state.
     5534 */
     5535static void ahciTrimRangesDestroy(PAHCIREQ pAhciReq)
     5536{
     5537    AssertReturnVoid(pAhciReq->enmTxDir == AHCITXDIR_TRIM);
     5538    RTMemFree(pAhciReq->u.Trim.paRanges);
    61805539}
    61815540
     
    61865545 * @returns VBox status code
    61875546 *
    6188  * @param pAhciPort             Pointer to the port where to request completed.
    6189  * @param pAhciPortTaskState    Pointer to the task which finished.
    6190  * @param rcReq                 IPRT status code of the completed request.
    6191  */
    6192 static int ahciTransferComplete(PAHCIPort pAhciPort, PAHCIPORTTASKSTATE pAhciPortTaskState, int rcReq)
     5547 * @param pAhciPort    Pointer to the port where to request completed.
     5548 * @param pAhciReq     Pointer to the task which finished.
     5549 * @param rcReq        IPRT status code of the completed request.
     5550 * @param fFreeReq     Flag whether to free the request if it was canceled.
     5551 */
     5552static int ahciTransferComplete(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, int rcReq, bool fFreeReq)
    61935553{
    61945554    bool fXchg = false;
    61955555    bool fRedo = false;
    61965556
    6197     ASMAtomicCmpXchgSize(&pAhciPortTaskState->enmTxState, AHCITXSTATE_FREE, AHCITXSTATE_ACTIVE, fXchg);
     5557    ASMAtomicCmpXchgSize(&pAhciReq->enmTxState, AHCITXSTATE_FREE, AHCITXSTATE_ACTIVE, fXchg);
    61985558
    61995559    if (fXchg)
    62005560    {
    6201         /* Free system resources occupied by the scatter gather list. */
    6202         if (pAhciPortTaskState->enmTxDir != AHCITXDIR_FLUSH)
    6203             ahciScatterGatherListDestroy(pAhciPort, pAhciPortTaskState);
    6204 
    6205         if (pAhciPortTaskState->enmTxDir == AHCITXDIR_READ)
    6206         {
    6207             STAM_REL_COUNTER_ADD(&pAhciPort->StatBytesRead, pAhciPortTaskState->cbTransfer);
     5561        if (pAhciReq->enmTxDir == AHCITXDIR_READ)
     5562        {
     5563            ahciIoBufFree(pAhciPort->pDevInsR3, pAhciReq, true /* fCopyToGuest */);
     5564            STAM_REL_COUNTER_ADD(&pAhciPort->StatBytesRead, pAhciReq->cbTransfer);
    62085565            pAhciPort->Led.Actual.s.fReading = 0;
    62095566        }
    6210         else if (pAhciPortTaskState->enmTxDir == AHCITXDIR_WRITE)
    6211         {
    6212             STAM_REL_COUNTER_ADD(&pAhciPort->StatBytesWritten, pAhciPortTaskState->cbTransfer);
     5567        else if (pAhciReq->enmTxDir == AHCITXDIR_WRITE)
     5568        {
     5569            ahciIoBufFree(pAhciPort->pDevInsR3, pAhciReq, false /* fCopyToGuest */);
     5570            STAM_REL_COUNTER_ADD(&pAhciPort->StatBytesWritten, pAhciReq->cbTransfer);
    62135571            pAhciPort->Led.Actual.s.fWriting = 0;
    62145572        }
    6215         else if (pAhciPortTaskState->enmTxDir == AHCITXDIR_TRIM)
    6216         {
    6217             ahciTrimRangesDestroy(pAhciPortTaskState);
     5573        else if (pAhciReq->enmTxDir == AHCITXDIR_TRIM)
     5574        {
     5575            ahciTrimRangesDestroy(pAhciReq);
    62185576            pAhciPort->Led.Actual.s.fWriting = 0;
    62195577        }
     
    62245582            if (pAhciPort->cErrors++ < MAX_LOG_REL_ERRORS)
    62255583            {
    6226                 if (pAhciPortTaskState->enmTxDir == AHCITXDIR_FLUSH)
     5584                if (pAhciReq->enmTxDir == AHCITXDIR_FLUSH)
    62275585                    LogRel(("AHCI#%u: Flush returned rc=%Rrc\n",
    62285586                            pAhciPort->iLUN, rcReq));
    6229                 else if (pAhciPortTaskState->enmTxDir == AHCITXDIR_TRIM)
     5587                else if (pAhciReq->enmTxDir == AHCITXDIR_TRIM)
    62305588                    LogRel(("AHCI#%u: Trim returned rc=%Rrc\n",
    62315589                            pAhciPort->iLUN, rcReq));
     
    62335591                    LogRel(("AHCI#%u: %s at offset %llu (%u bytes left) returned rc=%Rrc\n",
    62345592                            pAhciPort->iLUN,
    6235                             pAhciPortTaskState->enmTxDir == AHCITXDIR_READ
     5593                            pAhciReq->enmTxDir == AHCITXDIR_READ
    62365594                            ? "Read"
    62375595                            : "Write",
    6238                             pAhciPortTaskState->uOffset,
    6239                             pAhciPortTaskState->cbTransfer, rcReq));
     5596                            pAhciReq->uOffset,
     5597                            pAhciReq->cbTransfer, rcReq));
    62405598            }
    62415599
     
    62435601            if (!fRedo)
    62445602            {
    6245                 pAhciPortTaskState->cmdHdr.u32PRDBC = 0;
    6246                 pAhciPortTaskState->uATARegError = ID_ERR;
    6247                 pAhciPortTaskState->uATARegStatus = ATA_STAT_READY | ATA_STAT_ERR;
    6248                 ASMAtomicCmpXchgPtr(&pAhciPort->pTaskErr, pAhciPortTaskState, NULL);
     5603                pAhciReq->cmdHdr.u32PRDBC = 0;
     5604                pAhciReq->uATARegError    = ID_ERR;
     5605                pAhciReq->uATARegStatus  = ATA_STAT_READY | ATA_STAT_ERR;
     5606                ASMAtomicCmpXchgPtr(&pAhciPort->pTaskErr, pAhciReq, NULL);
    62495607            }
    62505608            else
    6251                 ASMAtomicOrU32(&pAhciPort->u32TasksNew, (1 << pAhciPortTaskState->uTag));
     5609                ASMAtomicOrU32(&pAhciPort->u32TasksNew, RT_BIT_32(pAhciReq->uTag));
    62525610        }
    62535611        else
    62545612        {
    6255             pAhciPortTaskState->cmdHdr.u32PRDBC = pAhciPortTaskState->cbTransfer;
    6256 
    6257             pAhciPortTaskState->uATARegError = 0;
    6258             pAhciPortTaskState->uATARegStatus = ATA_STAT_READY | ATA_STAT_SEEK;
     5613            pAhciReq->cmdHdr.u32PRDBC = pAhciReq->cbTransfer;
     5614
     5615            /* Status will be set by already for non I/O requests. */
     5616            if (pAhciReq->enmTxDir != AHCITXDIR_NONE)
     5617            {
     5618                pAhciReq->uATARegError = 0;
     5619                pAhciReq->uATARegStatus = ATA_STAT_READY | ATA_STAT_SEEK;
     5620            }
    62595621
    62605622            /* Write updated command header into memory of the guest. */
    6261             PDMDevHlpPhysWrite(pAhciPort->CTX_SUFF(pDevIns), pAhciPortTaskState->GCPhysCmdHdrAddr,
    6262                                &pAhciPortTaskState->cmdHdr, sizeof(CmdHdr));
     5623            PDMDevHlpPhysWrite(pAhciPort->CTX_SUFF(pDevIns), pAhciReq->GCPhysCmdHdrAddr,
     5624                               &pAhciReq->cmdHdr, sizeof(CmdHdr));
     5625
     5626            if (pAhciReq->fFlags & AHCI_REQ_OVERFLOW)
     5627            {
     5628                /*
     5629                 * The guest tried to transfer more data than there is space in the buffer.
     5630                 * Terminate task and set the overflow bit.
     5631                 */
     5632                /* Notify the guest. */
     5633                ASMAtomicOrU32(&pAhciPort->regIS, AHCI_PORT_IS_OFS);
     5634                if (pAhciPort->regIE & AHCI_PORT_IE_OFE)
     5635                    ahciHbaSetInterrupt(pAhciPort->CTX_SUFF(pAhci), pAhciPort->iLUN, VERR_IGNORED);
     5636            }
    62635637        }
    62645638
    62655639        /* Add the task to the cache. */
    6266         ASMAtomicWritePtr(&pAhciPort->aCachedTasks[pAhciPortTaskState->uTag], pAhciPortTaskState);
     5640        ASMAtomicWritePtr(&pAhciPort->aCachedTasks[pAhciReq->uTag], pAhciReq);
    62675641        ASMAtomicDecU32(&pAhciPort->cTasksActive);
    62685642
    62695643        if (!fRedo)
    62705644        {
    6271             if (pAhciPortTaskState->fQueued)
     5645            if (pAhciReq->fQueued)
    62725646            {
    6273                 if (RT_SUCCESS(rcReq) && !ASMAtomicReadPtrT(&pAhciPort->pTaskErr, PAHCIPORTTASKSTATE))
    6274                     ASMAtomicOrU32(&pAhciPort->u32QueuedTasksFinished, (1 << pAhciPortTaskState->uTag));
     5647                if (RT_SUCCESS(rcReq) && !ASMAtomicReadPtrT(&pAhciPort->pTaskErr, PAHCIREQ))
     5648                    ASMAtomicOrU32(&pAhciPort->u32QueuedTasksFinished, RT_BIT_32(pAhciReq->uTag));
    62755649
    62765650                /*
     
    62825656            }
    62835657            else
    6284                 ahciSendD2HFis(pAhciPort, pAhciPortTaskState, pAhciPortTaskState->cmdFis, true);
     5658                ahciSendD2HFis(pAhciPort, pAhciReq, pAhciReq->cmdFis, true);
    62855659        }
    62865660    }
     
    62915665         * The guest might use it for other things now because it doesn't know about that task anymore.
    62925666         */
    6293         AssertMsg(pAhciPortTaskState->enmTxState == AHCITXSTATE_CANCELED,
     5667        AssertMsg(pAhciReq->enmTxState == AHCITXSTATE_CANCELED,
    62945668                  ("Task is not active but wasn't canceled!\n"));
    62955669
    6296         ahciScatterGatherListFree(pAhciPortTaskState);
     5670        if (pAhciReq->enmTxDir == AHCITXDIR_TRIM)
     5671            ahciTrimRangesDestroy(pAhciReq);
     5672        else if (pAhciReq->enmTxDir != AHCITXDIR_FLUSH)
     5673            ahciIoBufFree(pAhciPort->pDevInsR3, pAhciReq, false /* fCopyToGuest */);
    62975674
    62985675        /* Leave a log message about the canceled request. */
    62995676        if (pAhciPort->cErrors++ < MAX_LOG_REL_ERRORS)
    63005677        {
    6301             if (pAhciPortTaskState->enmTxDir == AHCITXDIR_FLUSH)
     5678            if (pAhciReq->enmTxDir == AHCITXDIR_FLUSH)
    63025679                LogRel(("AHCI#%u: Canceled flush returned rc=%Rrc\n",
    63035680                        pAhciPort->iLUN, rcReq));
     
    63055682                LogRel(("AHCI#%u: Canceled %s at offset %llu (%u bytes left) returned rc=%Rrc\n",
    63065683                        pAhciPort->iLUN,
    6307                         pAhciPortTaskState->enmTxDir == AHCITXDIR_READ
     5684                        pAhciReq->enmTxDir == AHCITXDIR_READ
    63085685                        ? "read"
    63095686                        : "write",
    6310                         pAhciPortTaskState->uOffset,
    6311                         pAhciPortTaskState->cbTransfer, rcReq));
     5687                        pAhciReq->uOffset,
     5688                        pAhciReq->cbTransfer, rcReq));
    63125689         }
    63135690
    63145691        /* Finally free the task state structure because it is completely unused now. */
    6315         RTMemFree(pAhciPortTaskState);
     5692        if (fFreeReq)
     5693            RTMemFree(pAhciReq);
    63165694    }
    63175695
     
    63305708{
    63315709    PAHCIPort pAhciPort = PDMIBLOCKASYNCPORT_2_PAHCIPORT(pInterface);
    6332     PAHCIPORTTASKSTATE pAhciPortTaskState = (PAHCIPORTTASKSTATE)pvUser;
     5710    PAHCIREQ pAhciReq = (PAHCIREQ)pvUser;
    63335711
    63345712    ahciLog(("%s: pInterface=%p pvUser=%p uTag=%u\n",
    6335              __FUNCTION__, pInterface, pvUser, pAhciPortTaskState->uTag));
    6336 
    6337     int rc = ahciTransferComplete(pAhciPort, pAhciPortTaskState, rcReq);
     5713             __FUNCTION__, pInterface, pvUser, pAhciReq->uTag));
     5714
     5715    int rc = ahciTransferComplete(pAhciPort, pAhciReq, rcReq, true);
    63385716
    63395717    if (pAhciPort->cTasksActive == 0 && pAhciPort->pAhciR3->fSignalIdle)
     
    63485726 * @param   pCmdHdr Pointer to the command header.
    63495727 */
    6350 static AHCITXDIR ahciProcessCmd(PAHCIPort pAhciPort, PAHCIPORTTASKSTATE pAhciPortTaskState, uint8_t *pCmdFis)
     5728static AHCITXDIR ahciProcessCmd(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, uint8_t *pCmdFis)
    63515729{
    63525730    AHCITXDIR rc = AHCITXDIR_NONE;
    63535731    bool fLBA48 = false;
    6354     CmdHdr   *pCmdHdr = &pAhciPortTaskState->cmdHdr;
     5732    CmdHdr   *pCmdHdr = &pAhciReq->cmdHdr;
    63555733
    63565734    AssertMsg(pCmdFis[AHCI_CMDFIS_TYPE] == AHCI_CMDFIS_TYPE_H2D, ("FIS is not a host to device Fis!!\n"));
    63575735
    6358     pAhciPortTaskState->cbTransfer = 0;
     5736    pAhciReq->cbTransfer = 0;
    63595737
    63605738    switch (pCmdFis[AHCI_CMDFIS_CMD])
    63615739    {
    63625740        case ATA_IDENTIFY_DEVICE:
     5741        {
     5742            if (pAhciPort->pDrvBlock && !pAhciPort->fATAPI)
    63635743            {
    6364                 if (pAhciPort->pDrvBlock && !pAhciPort->fATAPI)
    6365                 {
    6366                     int rc2;
    6367                     uint16_t u16Temp[256];
    6368 
    6369                     /* Fill the buffer. */
    6370                     ahciIdentifySS(pAhciPort, u16Temp);
    6371 
    6372                     /* Create scatter gather list. */
    6373                     rc2 = ahciScatterGatherListCreate(pAhciPort, pAhciPortTaskState, false);
    6374                     if (RT_FAILURE(rc2))
    6375                         AssertMsgFailed(("Creating list failed rc=%Rrc\n", rc2));
    6376 
    6377                     /* Copy the buffer. */
    6378                     pCmdHdr->u32PRDBC = ahciScatterGatherListCopyFromBuffer(pAhciPortTaskState, &u16Temp[0], sizeof(u16Temp));
    6379 
    6380                     /* Destroy list. */
    6381                     rc2 = ahciScatterGatherListDestroy(pAhciPort, pAhciPortTaskState);
    6382                     if (RT_FAILURE(rc2))
    6383                         AssertMsgFailed(("Freeing list failed rc=%Rrc\n", rc2));
    6384 
    6385                     pAhciPortTaskState->uATARegError = 0;
    6386                     pAhciPortTaskState->uATARegStatus = ATA_STAT_READY | ATA_STAT_SEEK;
    6387 
    6388                     /* Write updated command header into memory of the guest. */
    6389                     PDMDevHlpPhysWrite(pAhciPort->CTX_SUFF(pDevIns), pAhciPortTaskState->GCPhysCmdHdrAddr, pCmdHdr, sizeof(CmdHdr));
    6390                 }
    6391                 else
    6392                 {
    6393                     pAhciPortTaskState->uATARegError = ABRT_ERR;
    6394                     pAhciPortTaskState->uATARegStatus = ATA_STAT_READY | ATA_STAT_SEEK  | ATA_STAT_ERR;
    6395                 }
    6396                 break;
     5744                int rc2;
     5745                uint16_t u16Temp[256];
     5746                size_t cbCopied;
     5747
     5748                /* Fill the buffer. */
     5749                ahciIdentifySS(pAhciPort, u16Temp);
     5750
     5751                /* Copy the buffer. */
     5752                cbCopied = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq,
     5753                                           &u16Temp[0], sizeof(u16Temp));
     5754
     5755                pAhciReq->cbTransfer = cbCopied;
    63975756            }
     5757            else
     5758            {
     5759                pAhciReq->uATARegError = ABRT_ERR;
     5760                pAhciReq->uATARegStatus = ATA_STAT_READY | ATA_STAT_SEEK  | ATA_STAT_ERR;
     5761            }
     5762            break;
     5763        }
    63985764        case ATA_READ_NATIVE_MAX_ADDRESS_EXT:
    63995765        case ATA_READ_NATIVE_MAX_ADDRESS:
     
    64085774                case 0xcc: /* reverting to power-on defaults enable */
    64095775                case 0x66: /* reverting to power-on defaults disable */
    6410                     pAhciPortTaskState->uATARegError = 0;
    6411                     pAhciPortTaskState->uATARegStatus = ATA_STAT_READY | ATA_STAT_SEEK;
     5776                    pAhciReq->uATARegError = 0;
     5777                    pAhciReq->uATARegStatus = ATA_STAT_READY | ATA_STAT_SEEK;
    64125778                    break;
    64135779                case 0x82: /* write cache disable */
     
    64325798                }
    64335799                default:
    6434                     pAhciPortTaskState->uATARegError = ABRT_ERR;
    6435                     pAhciPortTaskState->uATARegStatus = ATA_STAT_READY | ATA_STAT_ERR;
     5800                    pAhciReq->uATARegError = ABRT_ERR;
     5801                    pAhciReq->uATARegStatus = ATA_STAT_READY | ATA_STAT_ERR;
    64365802            }
    64375803            break;
     
    64415807            if (!pAhciPort->fATAPI)
    64425808            {
    6443                 pAhciPortTaskState->uATARegError = ABRT_ERR;
    6444                 pAhciPortTaskState->uATARegStatus = ATA_STAT_READY | ATA_STAT_ERR;
     5809                pAhciReq->uATARegError = ABRT_ERR;
     5810                pAhciReq->uATARegStatus = ATA_STAT_READY | ATA_STAT_ERR;
    64455811            }
    64465812            else
    64475813            {
    64485814                /* Reset the device. */
    6449                 ahciDeviceReset(pAhciPort, pAhciPortTaskState);
     5815                ahciDeviceReset(pAhciPort, pAhciReq);
    64505816            }
    64515817            break;
     
    64585824            if (!pAhciPort->fATAPI)
    64595825            {
    6460                 pAhciPortTaskState->uATARegError = ABRT_ERR;
    6461                 pAhciPortTaskState->uATARegStatus = ATA_STAT_READY | ATA_STAT_ERR;
     5826                pAhciReq->uATARegError = ABRT_ERR;
     5827                pAhciReq->uATARegStatus = ATA_STAT_READY | ATA_STAT_ERR;
    64625828            }
    64635829            else
    6464                 rc = atapiParseCmd(pAhciPort, pAhciPortTaskState);
     5830                rc = atapiParseCmd(pAhciPort, pAhciReq);
    64655831            break;
    64665832        case ATA_IDENTIFY_PACKET_DEVICE:
    64675833            if (!pAhciPort->fATAPI)
    64685834            {
    6469                 pAhciPortTaskState->uATARegError = ABRT_ERR;
    6470                 pAhciPortTaskState->uATARegStatus = ATA_STAT_READY | ATA_STAT_ERR;
     5835                pAhciReq->uATARegError = ABRT_ERR;
     5836                pAhciReq->uATARegStatus = ATA_STAT_READY | ATA_STAT_ERR;
    64715837            }
    64725838            else
    64735839            {
    6474                 atapiDoTransfer(pAhciPort, pAhciPortTaskState, ATAFN_SS_ATAPI_IDENTIFY);
    6475 
    6476                 pAhciPortTaskState->uATARegError = 0;
    6477                 pAhciPortTaskState->uATARegStatus = ATA_STAT_READY | ATA_STAT_SEEK;
     5840                atapiDoTransfer(pAhciPort, pAhciReq, 512, ATAFN_SS_ATAPI_IDENTIFY);
     5841
     5842                pAhciReq->uATARegError = 0;
     5843                pAhciReq->uATARegStatus = ATA_STAT_READY | ATA_STAT_SEEK;
    64785844            }
    64795845            break;
     
    64835849                     || (pCmdFis[AHCI_CMDFIS_SECTC] & (pCmdFis[AHCI_CMDFIS_SECTC] - 1)) != 0))
    64845850            {
    6485                 pAhciPortTaskState->uATARegError = ABRT_ERR;
    6486                 pAhciPortTaskState->uATARegStatus = ATA_STAT_READY | ATA_STAT_ERR;
     5851                pAhciReq->uATARegError = ABRT_ERR;
     5852                pAhciReq->uATARegStatus = ATA_STAT_READY | ATA_STAT_ERR;
    64875853            }
    64885854            else
     
    64905856                Log2(("%s: set multi sector count to %d\n", __FUNCTION__, pCmdFis[AHCI_CMDFIS_SECTC]));
    64915857                pAhciPort->cMultSectors = pCmdFis[AHCI_CMDFIS_SECTC];
    6492                 pAhciPortTaskState->uATARegError = 0;
    6493                 pAhciPortTaskState->uATARegStatus = ATA_STAT_READY | ATA_STAT_SEEK;
     5858                pAhciReq->uATARegError = 0;
     5859                pAhciReq->uATARegStatus = ATA_STAT_READY | ATA_STAT_SEEK;
    64945860            }
    64955861            break;
     
    64975863            break; /* Do nothing. */
    64985864        case ATA_CHECK_POWER_MODE:
    6499             pAhciPortTaskState->cmdFis[AHCI_CMDFIS_SECTC] = 0xff; /* drive active or idle */
     5865            pAhciReq->cmdFis[AHCI_CMDFIS_SECTC] = 0xff; /* drive active or idle */
    65005866            /* fall through */
    65015867        case ATA_INITIALIZE_DEVICE_PARAMETERS:
     
    65075873        case ATA_READ_VERIFY_SECTORS_WITHOUT_RETRIES:
    65085874        case ATA_SLEEP:
    6509             pAhciPortTaskState->uATARegError = 0;
    6510             pAhciPortTaskState->uATARegStatus = ATA_STAT_READY | ATA_STAT_SEEK;
     5875            pAhciReq->uATARegError = 0;
     5876            pAhciReq->uATARegStatus = ATA_STAT_READY | ATA_STAT_SEEK;
    65115877            break;
    65125878        case ATA_READ_DMA_EXT:
     
    65145880        case ATA_READ_DMA:
    65155881        {
    6516             pAhciPortTaskState->cbTransfer = ahciGetNSectors(pCmdFis, fLBA48) * 512;
    6517             pAhciPortTaskState->uOffset = ahciGetSector(pAhciPort, pCmdFis, fLBA48) * 512;
     5882            pAhciReq->cbTransfer = ahciGetNSectors(pCmdFis, fLBA48) * 512;
     5883            pAhciReq->uOffset = ahciGetSector(pAhciPort, pCmdFis, fLBA48) * 512;
    65185884            rc = AHCITXDIR_READ;
    65195885            break;
     
    65235889        case ATA_WRITE_DMA:
    65245890        {
    6525             pAhciPortTaskState->cbTransfer = ahciGetNSectors(pCmdFis, fLBA48) * 512;
    6526             pAhciPortTaskState->uOffset = ahciGetSector(pAhciPort, pCmdFis, fLBA48) * 512;
     5891            pAhciReq->cbTransfer = ahciGetNSectors(pCmdFis, fLBA48) * 512;
     5892            pAhciReq->uOffset = ahciGetSector(pAhciPort, pCmdFis, fLBA48) * 512;
    65275893            rc = AHCITXDIR_WRITE;
    65285894            break;
     
    65305896        case ATA_READ_FPDMA_QUEUED:
    65315897        {
    6532             pAhciPortTaskState->cbTransfer = ahciGetNSectorsQueued(pCmdFis) * 512;
    6533             pAhciPortTaskState->uOffset = ahciGetSectorQueued(pCmdFis) * 512;
     5898            pAhciReq->cbTransfer = ahciGetNSectorsQueued(pCmdFis) * 512;
     5899            pAhciReq->uOffset = ahciGetSectorQueued(pCmdFis) * 512;
    65345900            rc = AHCITXDIR_READ;
    65355901            break;
     
    65375903        case ATA_WRITE_FPDMA_QUEUED:
    65385904        {
    6539             pAhciPortTaskState->cbTransfer = ahciGetNSectorsQueued(pCmdFis) * 512;
    6540             pAhciPortTaskState->uOffset = ahciGetSectorQueued(pCmdFis) * 512;
     5905            pAhciReq->cbTransfer = ahciGetNSectorsQueued(pCmdFis) * 512;
     5906            pAhciReq->uOffset = ahciGetSectorQueued(pCmdFis) * 512;
    65415907            rc = AHCITXDIR_WRITE;
    65425908            break;
     
    65475913            unsigned offLogRead = ((pCmdFis[AHCI_CMDFIS_CYLLEXP] << 8) | pCmdFis[AHCI_CMDFIS_CYLL]) * 512;
    65485914            unsigned iPage = pCmdFis[AHCI_CMDFIS_SECTN];
     5915            size_t cbCopied;
    65495916
    65505917            LogFlow(("Trying to read %zu bytes starting at offset %u from page %u\n", cbLogRead, offLogRead, iPage));
     
    65615928                    {
    65625929                        LogFlow(("Reading error page\n"));
    6563                         PAHCIPORTTASKSTATE pTaskErr = ASMAtomicXchgPtrT(&pAhciPort->pTaskErr, NULL, PAHCIPORTTASKSTATE);
     5930                        PAHCIREQ pTaskErr = ASMAtomicXchgPtrT(&pAhciPort->pTaskErr, NULL, PAHCIREQ);
    65645931                        if (pTaskErr)
    65655932                        {
     
    65945961                }
    65955962
    6596                 /* Create scatter gather list. */
    6597                 int rc2 = ahciScatterGatherListCreate(pAhciPort, pAhciPortTaskState, false);
    6598                 if (RT_FAILURE(rc2))
    6599                     AssertMsgFailed(("Creating list failed rc=%Rrc\n", rc2));
    6600 
    66015963                /* Copy the buffer. */
    6602                 pCmdHdr->u32PRDBC = ahciScatterGatherListCopyFromBuffer(pAhciPortTaskState, &aBuf[offLogRead], cbLogRead);
    6603 
    6604                 /* Destroy list. */
    6605                 rc2 = ahciScatterGatherListDestroy(pAhciPort, pAhciPortTaskState);
    6606                 if (RT_FAILURE(rc2))
    6607                     AssertMsgFailed(("Freeing list failed rc=%Rrc\n", rc2));
    6608 
    6609                 pAhciPortTaskState->uATARegError = 0;
    6610                 pAhciPortTaskState->uATARegStatus = ATA_STAT_READY | ATA_STAT_SEEK;
    6611 
    6612                 /* Write updated command header into memory of the guest. */
    6613                 PDMDevHlpPhysWrite(pAhciPort->CTX_SUFF(pDevIns), pAhciPortTaskState->GCPhysCmdHdrAddr, pCmdHdr, sizeof(CmdHdr));
     5964                cbCopied = ahciCopyToPrdtl(pAhciPort->pDevInsR3, pAhciReq,
     5965                                           &aBuf[offLogRead], cbLogRead);
     5966
     5967                pAhciReq->cbTransfer = cbCopied;
    66145968            }
    66155969
     
    66185972        case ATA_DATA_SET_MANAGEMENT:
    66195973        {
    6620             if (   pAhciPort->pDrvBlock->pfnDiscard
     5974            if (   (   !pAhciPort->fAsyncInterface
     5975                    && pAhciPort->pDrvBlock->pfnDiscard)
    66215976                || (   pAhciPort->fAsyncInterface
    66225977                    && pAhciPort->pDrvBlockAsync->pfnStartDiscard))
    66235978            {
    6624                 rc = AHCITXDIR_TRIM;
     5979                /* Check that the trim bit is set and all other bits are 0. */
     5980                if (   !(pAhciReq->cmdFis[AHCI_CMDFIS_FET] & UINT16_C(0x01))
     5981                    || (pAhciReq->cmdFis[AHCI_CMDFIS_FET] & ~UINT16_C(0x1)))
     5982                {
     5983                    pAhciReq->uATARegError = ABRT_ERR;
     5984                    pAhciReq->uATARegStatus = ATA_STAT_READY | ATA_STAT_SEEK;
     5985                }
     5986                else
     5987                    rc = AHCITXDIR_TRIM;
    66255988                break;
    66265989            }
     
    66325995        case ATA_NV_CACHE:
    66335996        case ATA_IDLE:
    6634             pAhciPortTaskState->uATARegError = ABRT_ERR;
    6635             pAhciPortTaskState->uATARegStatus = ATA_STAT_READY | ATA_STAT_ERR;
     5997            pAhciReq->uATARegError = ABRT_ERR;
     5998            pAhciReq->uATARegStatus = ATA_STAT_READY | ATA_STAT_ERR;
    66365999            break;
    66376000        default: /* For debugging purposes. */
    66386001            AssertMsgFailed(("Unknown command issued\n"));
    6639             pAhciPortTaskState->uATARegError = ABRT_ERR;
    6640             pAhciPortTaskState->uATARegStatus = ATA_STAT_READY | ATA_STAT_ERR;
     6002            pAhciReq->uATARegError = ABRT_ERR;
     6003            pAhciReq->uATARegStatus = ATA_STAT_READY | ATA_STAT_ERR;
    66416004    }
    66426005
     
    66486011 *
    66496012 * @returns nothing
    6650  * @param pAhciPortTaskState The state of the actual task.
    6651  */
    6652 static void ahciPortTaskGetCommandFis(PAHCIPort pAhciPort, PAHCIPORTTASKSTATE pAhciPortTaskState)
     6013 * @param pAhciReq The state of the actual task.
     6014 */
     6015static void ahciPortTaskGetCommandFis(PAHCIPort pAhciPort, PAHCIREQ pAhciReq)
    66536016{
    66546017    RTGCPHYS  GCPhysAddrCmdTbl;
     
    66616024     * We can process the Command FIS afterwards.
    66626025     */
    6663     pAhciPortTaskState->GCPhysCmdHdrAddr = pAhciPort->GCPhysAddrClb + pAhciPortTaskState->uTag * sizeof(CmdHdr);
     6026    pAhciReq->GCPhysCmdHdrAddr = pAhciPort->GCPhysAddrClb + pAhciReq->uTag * sizeof(CmdHdr);
    66646027    LogFlow(("%s: PDMDevHlpPhysRead GCPhysAddrCmdLst=%RGp cbCmdHdr=%u\n", __FUNCTION__,
    6665              pAhciPortTaskState->GCPhysCmdHdrAddr, sizeof(CmdHdr)));
    6666     PDMDevHlpPhysRead(pAhciPort->CTX_SUFF(pDevIns), pAhciPortTaskState->GCPhysCmdHdrAddr, &pAhciPortTaskState->cmdHdr, sizeof(CmdHdr));
     6028             pAhciReq->GCPhysCmdHdrAddr, sizeof(CmdHdr)));
     6029    PDMDevHlpPhysRead(pAhciPort->CTX_SUFF(pDevIns), pAhciReq->GCPhysCmdHdrAddr, &pAhciReq->cmdHdr, sizeof(CmdHdr));
    66676030
    66686031#ifdef DEBUG
    66696032    /* Print some infos about the command header. */
    6670     ahciDumpCmdHdrInfo(pAhciPort, &pAhciPortTaskState->cmdHdr);
     6033    ahciDumpCmdHdrInfo(pAhciPort, &pAhciReq->cmdHdr);
    66716034#endif
    66726035
    6673     GCPhysAddrCmdTbl = AHCI_RTGCPHYS_FROM_U32(pAhciPortTaskState->cmdHdr.u32CmdTblAddrUp, pAhciPortTaskState->cmdHdr.u32CmdTblAddr);
    6674 
    6675     AssertMsg((pAhciPortTaskState->cmdHdr.u32DescInf & AHCI_CMDHDR_CFL_MASK) * sizeof(uint32_t) == AHCI_CMDFIS_TYPE_H2D_SIZE,
     6036    GCPhysAddrCmdTbl = AHCI_RTGCPHYS_FROM_U32(pAhciReq->cmdHdr.u32CmdTblAddrUp, pAhciReq->cmdHdr.u32CmdTblAddr);
     6037
     6038    AssertMsg((pAhciReq->cmdHdr.u32DescInf & AHCI_CMDHDR_CFL_MASK) * sizeof(uint32_t) == AHCI_CMDFIS_TYPE_H2D_SIZE,
    66766039              ("This is not a command FIS!!\n"));
    66776040
    66786041    /* Read the command Fis. */
    66796042    LogFlow(("%s: PDMDevHlpPhysRead GCPhysAddrCmdTbl=%RGp cbCmdFis=%u\n", __FUNCTION__, GCPhysAddrCmdTbl, AHCI_CMDFIS_TYPE_H2D_SIZE));
    6680     PDMDevHlpPhysRead(pAhciPort->CTX_SUFF(pDevIns), GCPhysAddrCmdTbl, &pAhciPortTaskState->cmdFis[0], AHCI_CMDFIS_TYPE_H2D_SIZE);
     6043    PDMDevHlpPhysRead(pAhciPort->CTX_SUFF(pDevIns), GCPhysAddrCmdTbl, &pAhciReq->cmdFis[0], AHCI_CMDFIS_TYPE_H2D_SIZE);
    66816044
    66826045    /* Set transfer direction. */
    6683     pAhciPortTaskState->enmTxDir = (pAhciPortTaskState->cmdHdr.u32DescInf & AHCI_CMDHDR_W) ? AHCITXDIR_WRITE : AHCITXDIR_READ;
     6046    pAhciReq->enmTxDir = (pAhciReq->cmdHdr.u32DescInf & AHCI_CMDHDR_W) ? AHCITXDIR_WRITE : AHCITXDIR_READ;
    66846047
    66856048    /* If this is an ATAPI command read the atapi command. */
    6686     if (pAhciPortTaskState->cmdHdr.u32DescInf & AHCI_CMDHDR_A)
     6049    if (pAhciReq->cmdHdr.u32DescInf & AHCI_CMDHDR_A)
    66876050    {
    66886051        GCPhysAddrCmdTbl += AHCI_CMDHDR_ACMD_OFFSET;
    6689         PDMDevHlpPhysRead(pAhciPort->CTX_SUFF(pDevIns), GCPhysAddrCmdTbl, &pAhciPortTaskState->aATAPICmd[0], ATAPI_PACKET_SIZE);
     6052        PDMDevHlpPhysRead(pAhciPort->CTX_SUFF(pDevIns), GCPhysAddrCmdTbl, &pAhciReq->aATAPICmd[0], ATAPI_PACKET_SIZE);
    66906053    }
    66916054
    66926055    /* We "received" the FIS. Clear the BSY bit in regTFD. */
    6693     if ((pAhciPortTaskState->cmdHdr.u32DescInf & AHCI_CMDHDR_C) && (pAhciPortTaskState->fQueued))
     6056    if ((pAhciReq->cmdHdr.u32DescInf & AHCI_CMDHDR_C) && (pAhciReq->fQueued))
    66946057    {
    66956058        /*
     
    66976060         * but this FIS does not assert an interrupt
    66986061         */
    6699         ahciSendD2HFis(pAhciPort, pAhciPortTaskState, pAhciPortTaskState->cmdFis, false);
     6062        ahciSendD2HFis(pAhciPort, pAhciReq, pAhciReq->cmdFis, false);
    67006063        pAhciPort->regTFD &= ~AHCI_PORT_TFD_BSY;
    67016064    }
     6065
     6066    pAhciReq->GCPhysPrdtl = AHCI_RTGCPHYS_FROM_U32(pAhciReq->cmdHdr.u32CmdTblAddrUp, pAhciReq->cmdHdr.u32CmdTblAddr) + AHCI_CMDHDR_PRDT_OFFSET;
     6067    pAhciReq->cPrdtlEntries = AHCI_CMDHDR_PRDTL_ENTRIES(pAhciReq->cmdHdr.u32DescInf);
    67026068
    67036069#ifdef DEBUG
    67046070    /* Print some infos about the FIS. */
    6705     ahciDumpFisInfo(pAhciPort, &pAhciPortTaskState->cmdFis[0]);
     6071    ahciDumpFisInfo(pAhciPort, &pAhciReq->cmdFis[0]);
    67066072
    67076073    /* Print the PRDT */
    6708     RTGCPHYS GCPhysAddrPRDTLEntryStart = AHCI_RTGCPHYS_FROM_U32(pAhciPortTaskState->cmdHdr.u32CmdTblAddrUp, pAhciPortTaskState->cmdHdr.u32CmdTblAddr) + AHCI_CMDHDR_PRDT_OFFSET;
    6709 
    6710     ahciLog(("PRDT address %RGp number of entries %u\n", GCPhysAddrPRDTLEntryStart, AHCI_CMDHDR_PRDTL_ENTRIES(pAhciPortTaskState->cmdHdr.u32DescInf)));
    6711 
    6712     for (unsigned i = 0; i < AHCI_CMDHDR_PRDTL_ENTRIES(pAhciPortTaskState->cmdHdr.u32DescInf); i++)
     6074    ahciLog(("PRDT address %RGp number of entries %u\n", pAhciReq->GCPhysPrdtl, pAhciReq->cPrdtlEntries));
     6075    RTGCPHYS GCPhysPrdtl = pAhciReq->GCPhysPrdtl;
     6076
     6077    for (unsigned i = 0; i < pAhciReq->cPrdtlEntries; i++)
    67136078    {
    67146079        SGLEntry SGEntry;
    67156080
    6716         ahciLog(("Entry %u at address %RGp\n", i, GCPhysAddrPRDTLEntryStart));
    6717         PDMDevHlpPhysRead(pAhciPort->CTX_SUFF(pDevIns), GCPhysAddrPRDTLEntryStart, &SGEntry, sizeof(SGLEntry));
     6081        ahciLog(("Entry %u at address %RGp\n", i, GCPhysPrdtl));
     6082        PDMDevHlpPhysRead(pAhciPort->CTX_SUFF(pDevIns), GCPhysPrdtl, &SGEntry, sizeof(SGLEntry));
    67186083
    67196084        RTGCPHYS GCPhysDataAddr = AHCI_RTGCPHYS_FROM_U32(SGEntry.u32DBAUp, SGEntry.u32DBA);
    67206085        ahciLog(("GCPhysAddr=%RGp Size=%u\n", GCPhysDataAddr, SGEntry.u32DescInf & SGLENTRY_DESCINF_DBC));
    67216086
    6722         GCPhysAddrPRDTLEntryStart += sizeof(SGLEntry);
     6087        GCPhysPrdtl += sizeof(SGLEntry);
    67236088    }
    67246089#endif
     
    67566121        while (idx)
    67576122        {
    6758             AHCITXDIR          enmTxDir;
    6759             PAHCIPORTTASKSTATE pAhciPortTaskState;
     6123            AHCITXDIR enmTxDir;
     6124            PAHCIREQ pAhciReq;
    67606125
    67616126            /* Decrement to get the slot number. */
     
    67696134            if (!pAhciPort->aCachedTasks[idx])
    67706135            {
    6771                 pAhciPortTaskState = (PAHCIPORTTASKSTATE)RTMemAllocZ(sizeof(AHCIPORTTASKSTATE));
    6772                 AssertMsg(pAhciPortTaskState, ("%s: Cannot allocate task state memory!\n"));
    6773                 pAhciPortTaskState->enmTxState = AHCITXSTATE_FREE;
     6136                pAhciReq = (PAHCIREQ)RTMemAllocZ(sizeof(AHCIREQ));
     6137                AssertMsg(pAhciReq, ("%s: Cannot allocate task state memory!\n"));
     6138                pAhciReq->enmTxState = AHCITXSTATE_FREE;
    67746139            }
    67756140            else
    6776                 pAhciPortTaskState = pAhciPort->aCachedTasks[idx];
     6141                pAhciReq = pAhciPort->aCachedTasks[idx];
    67776142
    67786143            bool fXchg;
    6779             ASMAtomicCmpXchgSize(&pAhciPortTaskState->enmTxState, AHCITXSTATE_ACTIVE, AHCITXSTATE_FREE, fXchg);
     6144            ASMAtomicCmpXchgSize(&pAhciReq->enmTxState, AHCITXSTATE_ACTIVE, AHCITXSTATE_FREE, fXchg);
    67806145            AssertMsg(fXchg, ("Task is already active\n"));
    67816146
    6782             pAhciPortTaskState->uATARegStatus = 0;
    6783             pAhciPortTaskState->uATARegError  = 0;
     6147            pAhciReq->uATARegStatus = 0;
     6148            pAhciReq->uATARegError  = 0;
     6149            pAhciReq->fFlags        = 0;
    67846150
    67856151            /* Set current command slot */
    6786             pAhciPortTaskState->uTag = idx;
    6787             ASMAtomicWriteU32(&pAhciPort->u32CurrentCommandSlot, pAhciPortTaskState->uTag);
    6788 
    6789             ahciPortTaskGetCommandFis(pAhciPort, pAhciPortTaskState);
     6152            pAhciReq->uTag = idx;
     6153            ASMAtomicWriteU32(&pAhciPort->u32CurrentCommandSlot, pAhciReq->uTag);
     6154
     6155            ahciPortTaskGetCommandFis(pAhciPort, pAhciReq);
    67906156
    67916157            /* Mark the task as processed by the HBA if this is a queued task so that it doesn't occur in the CI register anymore. */
    67926158            if (pAhciPort->regSACT & (1 << idx))
    67936159            {
    6794                 pAhciPortTaskState->fQueued = true;
    6795                 ASMAtomicOrU32(&pAhciPort->u32TasksFinished, (1 << pAhciPortTaskState->uTag));
     6160                pAhciReq->fQueued = true;
     6161                ASMAtomicOrU32(&pAhciPort->u32TasksFinished, (1 << pAhciReq->uTag));
    67966162            }
    67976163            else
    6798                 pAhciPortTaskState->fQueued = false;
    6799 
    6800             if (!(pAhciPortTaskState->cmdFis[AHCI_CMDFIS_BITS] & AHCI_CMDFIS_C))
     6164                pAhciReq->fQueued = false;
     6165
     6166            if (!(pAhciReq->cmdFis[AHCI_CMDFIS_BITS] & AHCI_CMDFIS_C))
    68016167            {
    68026168                /* If the reset bit is set put the device into reset state. */
    6803                 if (pAhciPortTaskState->cmdFis[AHCI_CMDFIS_CTL] & AHCI_CMDFIS_CTL_SRST)
     6169                if (pAhciReq->cmdFis[AHCI_CMDFIS_CTL] & AHCI_CMDFIS_CTL_SRST)
    68046170                {
    68056171                    ahciLog(("%s: Setting device into reset state\n", __FUNCTION__));
    68066172                    pAhciPort->fResetDevice = true;
    6807                     ahciSendD2HFis(pAhciPort, pAhciPortTaskState, pAhciPortTaskState->cmdFis, true);
    6808                     pAhciPort->aCachedTasks[idx] = pAhciPortTaskState;
    6809 
    6810                     ASMAtomicCmpXchgSize(&pAhciPortTaskState->enmTxState, AHCITXSTATE_FREE, AHCITXSTATE_ACTIVE, fXchg);
     6173                    ahciSendD2HFis(pAhciPort, pAhciReq, pAhciReq->cmdFis, true);
     6174                    pAhciPort->aCachedTasks[idx] = pAhciReq;
     6175
     6176                    ASMAtomicCmpXchgSize(&pAhciReq->enmTxState, AHCITXSTATE_FREE, AHCITXSTATE_ACTIVE, fXchg);
    68116177                    AssertMsg(fXchg, ("Task is not active\n"));
    68126178                    return true;
     
    68146180                else if (pAhciPort->fResetDevice) /* The bit is not set and we are in a reset state. */
    68156181                {
    6816                     ahciFinishStorageDeviceReset(pAhciPort, pAhciPortTaskState);
    6817                     pAhciPort->aCachedTasks[idx] = pAhciPortTaskState;
    6818 
    6819                     ASMAtomicCmpXchgSize(&pAhciPortTaskState->enmTxState, AHCITXSTATE_FREE, AHCITXSTATE_ACTIVE, fXchg);
     6182                    ahciFinishStorageDeviceReset(pAhciPort, pAhciReq);
     6183                    pAhciPort->aCachedTasks[idx] = pAhciReq;
     6184
     6185                    ASMAtomicCmpXchgSize(&pAhciReq->enmTxState, AHCITXSTATE_FREE, AHCITXSTATE_ACTIVE, fXchg);
    68206186                    AssertMsg(fXchg, ("Task is not active\n"));
    68216187                    return true;
     
    68266192            else
    68276193            {
    6828                 enmTxDir = ahciProcessCmd(pAhciPort, pAhciPortTaskState, pAhciPortTaskState->cmdFis);
     6194                ASMAtomicIncU32(&pAhciPort->cTasksActive);
     6195
     6196                enmTxDir = ahciProcessCmd(pAhciPort, pAhciReq, pAhciReq->cmdFis);
     6197                pAhciReq->enmTxDir = enmTxDir;
    68296198
    68306199                if (enmTxDir != AHCITXDIR_NONE)
    68316200                {
    6832                     pAhciPortTaskState->enmTxDir = enmTxDir;
    6833 
    6834                     ASMAtomicIncU32(&pAhciPort->cTasksActive);
    6835 
    6836                     if (enmTxDir != AHCITXDIR_FLUSH)
     6201                    if (   enmTxDir != AHCITXDIR_FLUSH
     6202                        && enmTxDir != AHCITXDIR_TRIM)
    68376203                    {
    6838                         bool fReadonly = true;
    68396204                        STAM_REL_COUNTER_INC(&pAhciPort->StatDMA);
    68406205
    6841                         if (   enmTxDir == AHCITXDIR_WRITE
    6842                             || enmTxDir == AHCITXDIR_TRIM)
    6843                             fReadonly = false;
    6844 
    6845                         rc = ahciScatterGatherListCreate(pAhciPort, pAhciPortTaskState, fReadonly);
     6206                        rc = ahciIoBufAllocate(pAhciPort->pDevInsR3, pAhciReq, pAhciReq->cbTransfer);
    68466207                        if (RT_FAILURE(rc))
    68476208                            AssertMsgFailed(("%s: Failed to process command %Rrc\n", __FUNCTION__, rc));
    68486209                    }
    68496210
    6850                     if (pAhciPortTaskState->cbSGBuffers < pAhciPortTaskState->cbTransfer)
    6851                     {
    6852                         /*
    6853                          * The guest tried to transfer more data than there is space in the buffer.
    6854                          * Terminate task and set the overflow bit.
    6855                          */
    6856                         ASMAtomicCmpXchgSize(&pAhciPortTaskState->enmTxState, AHCITXSTATE_FREE, AHCITXSTATE_ACTIVE, fXchg);
    6857                         AssertMsg(fXchg, ("Task is not active\n"));
    6858 
    6859                         /* Add the task to the cache. */
    6860                         pAhciPort->aCachedTasks[pAhciPortTaskState->uTag] = pAhciPortTaskState;
    6861 
    6862                         /* Notify the guest. */
    6863                         ASMAtomicOrU32(&pAhciPort->regIS, AHCI_PORT_IS_OFS);
    6864                         if (pAhciPort->regIE & AHCI_PORT_IE_OFE)
    6865                             ahciHbaSetInterrupt(pAhciPort->CTX_SUFF(pAhci), pAhciPort->iLUN, VERR_IGNORED);
    6866                     }
    6867                     else
     6211                    if (!(pAhciReq->fFlags & AHCI_REQ_OVERFLOW))
    68686212                    {
    68696213                        if (enmTxDir == AHCITXDIR_FLUSH)
    68706214                        {
    68716215                            rc = pAhciPort->pDrvBlockAsync->pfnStartFlush(pAhciPort->pDrvBlockAsync,
    6872                                                                           pAhciPortTaskState);
     6216                                                                          pAhciReq);
    68736217                        }
    68746218                        else if (enmTxDir == AHCITXDIR_TRIM)
    68756219                        {
    6876                             rc = ahciTrimRangesCreate(pAhciPort, pAhciPortTaskState);
     6220                            rc = ahciTrimRangesCreate(pAhciPort, pAhciReq);
    68776221                            if (RT_SUCCESS(rc))
    68786222                            {
    68796223                                pAhciPort->Led.Asserted.s.fWriting = pAhciPort->Led.Actual.s.fWriting = 1;
    6880                                 rc = pAhciPort->pDrvBlockAsync->pfnStartDiscard(pAhciPort->pDrvBlockAsync, pAhciPortTaskState->paRanges,
    6881                                                                                 pAhciPortTaskState->cRanges, pAhciPortTaskState);
     6224                                rc = pAhciPort->pDrvBlockAsync->pfnStartDiscard(pAhciPort->pDrvBlockAsync, pAhciReq->u.Trim.paRanges,
     6225                                                                                pAhciReq->u.Trim.cRanges, pAhciReq);
    68826226                            }
    68836227                        }
     
    68856229                        {
    68866230                            pAhciPort->Led.Asserted.s.fReading = pAhciPort->Led.Actual.s.fReading = 1;
    6887                             rc = pAhciPort->pDrvBlockAsync->pfnStartRead(pAhciPort->pDrvBlockAsync, pAhciPortTaskState->uOffset,
    6888                                                                          pAhciPortTaskState->pSGListHead, pAhciPortTaskState->cSGListUsed,
    6889                                                                          pAhciPortTaskState->cbTransfer,
    6890                                                                          pAhciPortTaskState);
     6231                            rc = pAhciPort->pDrvBlockAsync->pfnStartRead(pAhciPort->pDrvBlockAsync, pAhciReq->uOffset,
     6232                                                                         &pAhciReq->u.Io.DataSeg, 1,
     6233                                                                         pAhciReq->cbTransfer,
     6234                                                                         pAhciReq);
    68916235                        }
    68926236                        else
    68936237                        {
    68946238                            pAhciPort->Led.Asserted.s.fWriting = pAhciPort->Led.Actual.s.fWriting = 1;
    6895                             rc = pAhciPort->pDrvBlockAsync->pfnStartWrite(pAhciPort->pDrvBlockAsync, pAhciPortTaskState->uOffset,
    6896                                                                           pAhciPortTaskState->pSGListHead, pAhciPortTaskState->cSGListUsed,
    6897                                                                           pAhciPortTaskState->cbTransfer,
    6898                                                                           pAhciPortTaskState);
     6239                            rc = pAhciPort->pDrvBlockAsync->pfnStartWrite(pAhciPort->pDrvBlockAsync, pAhciReq->uOffset,
     6240                                                                          &pAhciReq->u.Io.DataSeg, 1,
     6241                                                                          pAhciReq->cbTransfer,
     6242                                                                          pAhciReq);
    68996243                        }
    69006244                        if (rc == VINF_VD_ASYNC_IO_FINISHED)
    6901                             rc = ahciTransferComplete(pAhciPort, pAhciPortTaskState, VINF_SUCCESS);
     6245                            rc = ahciTransferComplete(pAhciPort, pAhciReq, VINF_SUCCESS, true);
    69026246                        else if (RT_FAILURE(rc) && rc != VERR_VD_ASYNC_IO_IN_PROGRESS)
    6903                             rc = ahciTransferComplete(pAhciPort, pAhciPortTaskState, rc);
     6247                            rc = ahciTransferComplete(pAhciPort, pAhciReq, rc, true);
    69046248                    }
    69056249                }
    69066250                else
    6907                 {
    6908                     ASMAtomicCmpXchgSize(&pAhciPortTaskState->enmTxState, AHCITXSTATE_FREE, AHCITXSTATE_ACTIVE, fXchg);
    6909                     AssertMsg(fXchg, ("Task is not active\n"));
    6910 
    6911                     /* There is nothing left to do. Notify the guest. */
    6912                     ahciSendD2HFis(pAhciPort, pAhciPortTaskState, &pAhciPortTaskState->cmdFis[0], true);
    6913                     /* Add the task to the cache. */
    6914                     pAhciPort->aCachedTasks[pAhciPortTaskState->uTag] = pAhciPortTaskState;
    6915                 }
     6251                    rc = ahciTransferComplete(pAhciPort, pAhciReq, VINF_SUCCESS, true);
    69166252            } /* Command */
    69176253
    6918             u32Tasks &= ~(1 << idx); /* Clear task bit. */
     6254            u32Tasks &= ~RT_BIT_32(idx); /* Clear task bit. */
    69196255            idx = ASMBitFirstSetU32(u32Tasks);
    69206256        } /* while tasks available */
     
    69296265    PAHCIPort pAhciPort = (PAHCIPort)pThread->pvUser;
    69306266    PAHCI     pAhci     = pAhciPort->CTX_SUFF(pAhci);
    6931     PAHCIPORTTASKSTATE pAhciPortTaskState;
     6267    PAHCIREQ pAhciReq;
    69326268    int rc = VINF_SUCCESS;
    69336269    uint64_t u64StartTime = 0;
     
    69446280
    69456281    /* We use only one task structure. */
    6946     pAhciPortTaskState = (PAHCIPORTTASKSTATE)RTMemAllocZ(sizeof(AHCIPORTTASKSTATE));
    6947     if (!pAhciPortTaskState)
     6282    pAhciReq = (PAHCIREQ)RTMemAllocZ(sizeof(AHCIREQ));
     6283    if (!pAhciReq)
    69486284    {
    69496285        AssertMsgFailed(("Failed to allocate task state memory\n"));
    69506286        return VERR_NO_MEMORY;
    69516287    }
     6288
     6289    pAhciReq->enmTxState = AHCITXSTATE_FREE;
    69526290
    69536291    while (pThread->enmState == PDMTHREADSTATE_RUNNING)
     
    69926330            STAM_PROFILE_START(&pAhciPort->StatProfileProcessTime, a);
    69936331
    6994             pAhciPortTaskState->uATARegStatus = 0;
    6995             pAhciPortTaskState->uATARegError  = 0;
    6996             pAhciPortTaskState->uTag          = idx;
    6997             AssertMsg(pAhciPortTaskState->uTag < AHCI_NR_COMMAND_SLOTS, ("%s: Invalid Tag number %u!!\n", __FUNCTION__, pAhciPortTaskState->uTag));
     6332            pAhciReq->uATARegStatus = 0;
     6333            pAhciReq->uATARegError  = 0;
     6334            pAhciReq->fFlags        = 0;
     6335            pAhciReq->uTag          = idx;
     6336            AssertMsg(pAhciReq->uTag < AHCI_NR_COMMAND_SLOTS, ("%s: Invalid Tag number %u!!\n", __FUNCTION__, pAhciReq->uTag));
     6337
     6338            bool fXchg;
     6339            ASMAtomicCmpXchgSize(&pAhciReq->enmTxState, AHCITXSTATE_ACTIVE, AHCITXSTATE_FREE, fXchg);
     6340            AssertMsg(fXchg, ("Task is already active\n"));
    69986341
    69996342            /* Set current command slot */
    7000             ASMAtomicWriteU32(&pAhciPort->u32CurrentCommandSlot, pAhciPortTaskState->uTag);
     6343            ASMAtomicWriteU32(&pAhciPort->u32CurrentCommandSlot, pAhciReq->uTag);
    70016344
    70026345            /* Mark the task as processed by the HBA if this is a queued task so that it doesn't occur in the CI register anymore. */
    70036346            if (pAhciPort->regSACT & (1 << idx))
    70046347            {
    7005                 pAhciPortTaskState->fQueued = true;
    7006                 ASMAtomicOrU32(&pAhciPort->u32TasksFinished, (1 << pAhciPortTaskState->uTag));
     6348                pAhciReq->fQueued = true;
     6349                ASMAtomicOrU32(&pAhciPort->u32TasksFinished, (1 << pAhciReq->uTag));
    70076350            }
    70086351            else
    7009                 pAhciPortTaskState->fQueued = false;
    7010 
    7011             ahciPortTaskGetCommandFis(pAhciPort, pAhciPortTaskState);
    7012 
    7013             ahciLog(("%s: Got command at slot %d\n", __FUNCTION__, pAhciPortTaskState->uTag));
    7014 
    7015             if (!(pAhciPortTaskState->cmdFis[AHCI_CMDFIS_BITS] & AHCI_CMDFIS_C))
     6352                pAhciReq->fQueued = false;
     6353
     6354            ahciPortTaskGetCommandFis(pAhciPort, pAhciReq);
     6355
     6356            ahciLog(("%s: Got command at slot %d\n", __FUNCTION__, pAhciReq->uTag));
     6357
     6358            if (!(pAhciReq->cmdFis[AHCI_CMDFIS_BITS] & AHCI_CMDFIS_C))
    70166359            {
    70176360                /* If the reset bit is set put the device into reset state. */
    7018                 if (pAhciPortTaskState->cmdFis[AHCI_CMDFIS_CTL] & AHCI_CMDFIS_CTL_SRST)
     6361                if (pAhciReq->cmdFis[AHCI_CMDFIS_CTL] & AHCI_CMDFIS_CTL_SRST)
    70196362                {
    70206363                    ahciLog(("%s: Setting device into reset state\n", __FUNCTION__));
    70216364                    pAhciPort->fResetDevice = true;
    7022                     ahciSendD2HFis(pAhciPort, pAhciPortTaskState, &pAhciPortTaskState->cmdFis[0], true);
     6365                    ahciSendD2HFis(pAhciPort, pAhciReq, &pAhciReq->cmdFis[0], true);
    70236366                }
    70246367                else if (pAhciPort->fResetDevice) /* The bit is not set and we are in a reset state. */
    70256368                {
    7026                     ahciFinishStorageDeviceReset(pAhciPort, pAhciPortTaskState);
     6369                    ahciFinishStorageDeviceReset(pAhciPort, pAhciReq);
    70276370                }
    70286371                /* TODO: We are not in a reset state update the control registers. */
     6372
     6373                ASMAtomicCmpXchgSize(&pAhciReq->enmTxState, AHCITXSTATE_FREE, AHCITXSTATE_ACTIVE, fXchg);
     6374                AssertMsg(fXchg, ("Task is already free\n"));
    70296375            }
    70306376            else
    70316377            {
    7032                 enmTxDir = ahciProcessCmd(pAhciPort, pAhciPortTaskState, &pAhciPortTaskState->cmdFis[0]);
     6378                ASMAtomicIncU32(&pAhciPort->cTasksActive);
     6379                enmTxDir = ahciProcessCmd(pAhciPort, pAhciReq, &pAhciReq->cmdFis[0]);
     6380                pAhciReq->enmTxDir = enmTxDir;
    70336381
    70346382                if (enmTxDir == AHCITXDIR_FLUSH)
    7035                 {
    70366383                    rc = pAhciPort->pDrvBlock->pfnFlush(pAhciPort->pDrvBlock);
    7037 
    7038                     /* Log the error. */
    7039                     if (   RT_FAILURE(rc)
    7040                         && pAhciPort->cErrors++ < MAX_LOG_REL_ERRORS)
    7041                     {
    7042                         LogRel(("AHCI#%u: Flush returned rc=%Rrc\n",
    7043                                 pAhciPort->iLUN, rc));
    7044                     }
    7045 
    7046                     if (RT_FAILURE(rc))
    7047                     {
    7048                         if (!ahciIsRedoSetWarning(pAhciPort, rc))
    7049                         {
    7050                             pAhciPortTaskState->uATARegError = ID_ERR;
    7051                             pAhciPortTaskState->uATARegStatus = ATA_STAT_READY | ATA_STAT_ERR;
    7052                         }
    7053                         else
    7054                         {
    7055                             /* Add the task to the mask again. */
    7056                             ASMAtomicOrU32(&pAhciPort->u32TasksNew, (1 << pAhciPortTaskState->uTag));
    7057                         }
    7058                     }
    7059                     else
    7060                     {
    7061                         pAhciPortTaskState->uATARegError = 0;
    7062                         pAhciPortTaskState->uATARegStatus = ATA_STAT_READY | ATA_STAT_SEEK;
    7063                     }
    7064 
    7065                     if (!pAhciPort->fRedo)
    7066                     {
    7067                         if (pAhciPortTaskState->fQueued)
    7068                             ASMAtomicOrU32(&pAhciPort->u32QueuedTasksFinished, (1 << pAhciPortTaskState->uTag));
    7069                         else
    7070                         {
    7071                             /* Task is not queued send D2H FIS */
    7072                             ahciSendD2HFis(pAhciPort, pAhciPortTaskState, &pAhciPortTaskState->cmdFis[0], true);
    7073                         }
    7074                     }
    7075                 }
    70766384                else if (enmTxDir == AHCITXDIR_TRIM)
    70776385                {
    7078                     rc = ahciScatterGatherListCreate(pAhciPort, pAhciPortTaskState, (enmTxDir == AHCITXDIR_READ) ? false : true);
    7079                     if (RT_FAILURE(rc))
    7080                         AssertMsgFailed(("%s: Failed to get number of list elments %Rrc\n", __FUNCTION__, rc));
    7081 
    7082                     rc = ahciTrimRangesCreate(pAhciPort, pAhciPortTaskState);
     6386                    rc = ahciTrimRangesCreate(pAhciPort, pAhciReq);
    70836387                    if (RT_SUCCESS(rc))
    70846388                    {
    70856389                        pAhciPort->Led.Asserted.s.fWriting = pAhciPort->Led.Actual.s.fWriting = 1;
    7086                         rc = pAhciPort->pDrvBlock->pfnDiscard(pAhciPort->pDrvBlock, pAhciPortTaskState->paRanges, pAhciPortTaskState->cRanges);
     6390                        rc = pAhciPort->pDrvBlock->pfnDiscard(pAhciPort->pDrvBlock,
     6391                                                              pAhciReq->u.Trim.paRanges,
     6392                                                              pAhciReq->u.Trim.cRanges);
    70876393                        pAhciPort->Led.Actual.s.fWriting = 0;
    7088                     }
    7089 
    7090                     /* Cleanup. */
    7091                     ahciTrimRangesDestroy(pAhciPortTaskState);
    7092 
    7093                     int rc2 = ahciScatterGatherListDestroy(pAhciPort, pAhciPortTaskState);
    7094                     if (RT_FAILURE(rc2))
    7095                         AssertMsgFailed(("Destroying task list failed rc=%Rrc\n", rc));
    7096 
    7097                     /* Log the error. */
    7098                     if (   RT_FAILURE(rc)
    7099                         && pAhciPort->cErrors++ < MAX_LOG_REL_ERRORS)
    7100                     {
    7101                         LogRel(("AHCI#%u: Trim returned rc=%Rrc\n",
    7102                                 pAhciPort->iLUN, rc));
    7103                     }
    7104 
    7105                     if (RT_FAILURE(rc))
    7106                     {
    7107                         if (!ahciIsRedoSetWarning(pAhciPort, rc))
    7108                         {
    7109                             pAhciPortTaskState->uATARegError = ID_ERR;
    7110                             pAhciPortTaskState->uATARegStatus = ATA_STAT_READY | ATA_STAT_ERR;
    7111                         }
    7112                         else
    7113                         {
    7114                             /* Add the task to the mask again. */
    7115                             ASMAtomicOrU32(&pAhciPort->u32TasksNew, (1 << pAhciPortTaskState->uTag));
    7116                         }
    7117                     }
    7118                     else
    7119                     {
    7120                         pAhciPortTaskState->uATARegError = 0;
    7121                         pAhciPortTaskState->uATARegStatus = ATA_STAT_READY | ATA_STAT_SEEK;
    7122                     }
    7123 
    7124                     if (!pAhciPort->fRedo)
    7125                     {
    7126                         if (pAhciPortTaskState->fQueued)
    7127                             ASMAtomicOrU32(&pAhciPort->u32QueuedTasksFinished, (1 << pAhciPortTaskState->uTag));
    7128                         else
    7129                         {
    7130                             /* Task is not queued send D2H FIS */
    7131                             ahciSendD2HFis(pAhciPort, pAhciPortTaskState, &pAhciPortTaskState->cmdFis[0], true);
    7132                         }
    71336394                    }
    71346395                }
     
    71376398                    uint64_t uOffset = 0;
    71386399                    size_t cbTransfer = 0;
    7139                     PRTSGSEG pSegCurr;
    7140                     PAHCIPORTTASKSTATESGENTRY pSGInfoCurr;
    7141 
    7142                     rc = ahciScatterGatherListCreate(pAhciPort, pAhciPortTaskState, (enmTxDir == AHCITXDIR_READ) ? false : true);
     6400
     6401                    rc = ahciIoBufAllocate(pAhciPort->pDevInsR3, pAhciReq, pAhciReq->cbTransfer);
    71436402                    if (RT_FAILURE(rc))
    71446403                        AssertMsgFailed(("%s: Failed to get number of list elments %Rrc\n", __FUNCTION__, rc));
    71456404
    7146                     if (pAhciPortTaskState->cbSGBuffers < pAhciPortTaskState->cbTransfer)
    7147                     {
    7148                         /*
    7149                          * The guest tried to transfer more data than there is space in the buffer.
    7150                          * Terminate task and set the overflow bit.
    7151                          */
    7152                         int rc2 = ahciScatterGatherListDestroy(pAhciPort, pAhciPortTaskState);
    7153                         AssertMsgRC(rc2, ("Destroying task list failed rc=%Rrc\n", rc2));
    7154 
    7155                        /* Notify the guest. */
    7156                         ASMAtomicOrU32(&pAhciPort->regIS, AHCI_PORT_IS_OFS);
    7157                         if (pAhciPort->regIE & AHCI_PORT_IE_OFE)
    7158                             ahciHbaSetInterrupt(pAhciPort->CTX_SUFF(pAhci), pAhciPort->iLUN, VERR_IGNORED);
    7159                     }
    7160                     else
     6405                    if (!(pAhciReq->fFlags & AHCI_REQ_OVERFLOW))
    71616406                    {
    71626407                        STAM_REL_COUNTER_INC(&pAhciPort->StatDMA);
    71636408
    71646409                        /* Initialize all values. */
    7165                         uOffset     = pAhciPortTaskState->uOffset;
    7166                         cbTransfer  = pAhciPortTaskState->cbTransfer;
    7167                         pSegCurr    = &pAhciPortTaskState->pSGListHead[0];
    7168                         pSGInfoCurr = pAhciPortTaskState->paSGEntries;
     6410                        uOffset     = pAhciReq->uOffset;
     6411                        cbTransfer  = pAhciReq->cbTransfer;
    71696412
    71706413                        STAM_PROFILE_START(&pAhciPort->StatProfileReadWrite, b);
    71716414
    7172                         while (cbTransfer)
     6415                        AssertMsg(!(uOffset % 512), ("Offset is not sector aligned %llu\n", uOffset));
     6416                        AssertMsg(!(cbTransfer % 512), ("Number of bytes to process is not sector aligned %lu\n", cbTransfer));
     6417
     6418                        if (enmTxDir == AHCITXDIR_READ)
    71736419                        {
    7174                             size_t cbProcess = (cbTransfer < pSegCurr->cbSeg) ? cbTransfer : pSegCurr->cbSeg;
    7175 
    7176                             AssertMsg(!(pSegCurr->cbSeg % 512), ("Buffer is not sector aligned cbSeg=%d\n", pSegCurr->cbSeg));
    7177                             AssertMsg(!(uOffset % 512), ("Offset is not sector aligned %llu\n", uOffset));
    7178                             AssertMsg(!(cbProcess % 512), ("Number of bytes to process is not sector aligned %lu\n", cbProcess));
    7179 
    7180                             if (enmTxDir == AHCITXDIR_READ)
    7181                             {
    7182                                 pAhciPort->Led.Asserted.s.fReading = pAhciPort->Led.Actual.s.fReading = 1;
    7183                                 rc = pAhciPort->pDrvBlock->pfnRead(pAhciPort->pDrvBlock, uOffset,
    7184                                                                    pSegCurr->pvSeg, cbProcess);
    7185                                 pAhciPort->Led.Actual.s.fReading = 0;
    7186                                 if (RT_FAILURE(rc))
    7187                                     break;
    7188 
    7189                                 STAM_REL_COUNTER_ADD(&pAhciPort->StatBytesRead, cbProcess);
    7190                             }
    7191                             else
    7192                             {
    7193                                 pAhciPort->Led.Asserted.s.fWriting = pAhciPort->Led.Actual.s.fWriting = 1;
    7194                                 rc = pAhciPort->pDrvBlock->pfnWrite(pAhciPort->pDrvBlock, uOffset,
    7195                                                                     pSegCurr->pvSeg, cbProcess);
    7196                                 pAhciPort->Led.Actual.s.fWriting = 0;
    7197                                 if (RT_FAILURE(rc))
    7198                                     break;
    7199 
    7200                                 STAM_REL_COUNTER_ADD(&pAhciPort->StatBytesWritten, cbProcess);
    7201                             }
    7202 
    7203                             /* Go to the next entry. */
    7204                             uOffset    += cbProcess;
    7205                             cbTransfer -= cbProcess;
    7206                             pSegCurr++;
    7207                             pSGInfoCurr++;
     6420                            pAhciPort->Led.Asserted.s.fReading = pAhciPort->Led.Actual.s.fReading = 1;
     6421                            rc = pAhciPort->pDrvBlock->pfnRead(pAhciPort->pDrvBlock, uOffset,
     6422                                                               pAhciReq->u.Io.DataSeg.pvSeg,
     6423                                                               cbTransfer);
     6424                            pAhciPort->Led.Actual.s.fReading = 0;
     6425                            STAM_REL_COUNTER_ADD(&pAhciPort->StatBytesRead, cbTransfer);
    72086426                        }
     6427                        else
     6428                        {
     6429                            pAhciPort->Led.Asserted.s.fWriting = pAhciPort->Led.Actual.s.fWriting = 1;
     6430                            rc = pAhciPort->pDrvBlock->pfnWrite(pAhciPort->pDrvBlock, uOffset,
     6431                                                                pAhciReq->u.Io.DataSeg.pvSeg,
     6432                                                                cbTransfer);
     6433                            pAhciPort->Led.Actual.s.fWriting = 0;
     6434                            STAM_REL_COUNTER_ADD(&pAhciPort->StatBytesWritten, cbTransfer);
     6435                        }
    72096436
    72106437                        STAM_PROFILE_STOP(&pAhciPort->StatProfileReadWrite, b);
    7211 
    7212                         /* Log the error. */
    7213                         if (   RT_FAILURE(rc)
    7214                             && pAhciPort->cErrors++ < MAX_LOG_REL_ERRORS)
    7215                         {
    7216                             LogRel(("AHCI#%u: %s at offset %llu (%u bytes left) returned rc=%Rrc\n",
    7217                                     pAhciPort->iLUN,
    7218                                     enmTxDir == AHCITXDIR_READ
    7219                                     ? "Read"
    7220                                     : "Write",
    7221                                     uOffset, cbTransfer, rc));
    7222                         }
    7223 
    7224                         /* Cleanup. */
    7225                         int rc2 = ahciScatterGatherListDestroy(pAhciPort, pAhciPortTaskState);
    7226                         if (RT_FAILURE(rc2))
    7227                             AssertMsgFailed(("Destroying task list failed rc=%Rrc\n", rc));
    7228 
    7229                         if (RT_LIKELY(!pAhciPort->fPortReset))
    7230                         {
    7231                             pAhciPortTaskState->cmdHdr.u32PRDBC = pAhciPortTaskState->cbTransfer - cbTransfer;
    7232                             if (RT_FAILURE(rc))
    7233                             {
    7234                                 if (!ahciIsRedoSetWarning(pAhciPort, rc))
    7235                                 {
    7236                                     pAhciPortTaskState->uATARegError = ID_ERR;
    7237                                     pAhciPortTaskState->uATARegStatus = ATA_STAT_READY | ATA_STAT_ERR;
    7238                                 }
    7239                                 else
    7240                                 {
    7241                                     /* Add the task to the mask again. */
    7242                                     ASMAtomicOrU32(&pAhciPort->u32TasksNew, (1 << pAhciPortTaskState->uTag));
    7243                                 }
    7244                             }
    7245                             else
    7246                             {
    7247                                 pAhciPortTaskState->uATARegError = 0;
    7248                                 pAhciPortTaskState->uATARegStatus = ATA_STAT_READY | ATA_STAT_SEEK;
    7249                             }
    7250 
    7251                             if (!pAhciPort->fRedo)
    7252                             {
    7253                                 /* Write updated command header into memory of the guest. */
    7254                                 PDMDevHlpPhysWrite(pAhciPort->CTX_SUFF(pDevIns), pAhciPortTaskState->GCPhysCmdHdrAddr,
    7255                                                    &pAhciPortTaskState->cmdHdr, sizeof(CmdHdr));
    7256 
    7257                                 if (pAhciPortTaskState->fQueued)
    7258                                     ASMAtomicOrU32(&pAhciPort->u32QueuedTasksFinished, (1 << pAhciPortTaskState->uTag));
    7259                                 else
    7260                                 {
    7261                                     /* Task is not queued send D2H FIS */
    7262                                     ahciSendD2HFis(pAhciPort, pAhciPortTaskState, &pAhciPortTaskState->cmdFis[0], true);
    7263                                 }
    7264 
    7265                                 uIORequestsProcessed++;
    7266                             }
    7267                         }
    72686438                    }
    72696439                }
    7270                 else
    7271                 {
    7272                     /* Nothing left to do. Notify the guest. */
    7273                     ahciSendD2HFis(pAhciPort, pAhciPortTaskState, &pAhciPortTaskState->cmdFis[0], true);
    7274                 }
    7275 
     6440
     6441                ahciTransferComplete(pAhciPort, pAhciReq, rc, false /* fFreeReq */);
     6442                uIORequestsProcessed++;
    72766443                STAM_PROFILE_STOP(&pAhciPort->StatProfileProcessTime, a);
    72776444            }
     
    72816448#ifdef DEBUG
    72826449                /* Be paranoid. */
    7283                 memset(&pAhciPortTaskState->cmdHdr, 0, sizeof(CmdHdr));
    7284                 memset(&pAhciPortTaskState->cmdFis, 0, AHCI_CMDFIS_TYPE_H2D_SIZE);
    7285                 pAhciPortTaskState->GCPhysCmdHdrAddr = 0;
    7286                 pAhciPortTaskState->uOffset = 0;
    7287                 pAhciPortTaskState->cbTransfer = 0;
     6450                memset(&pAhciReq->cmdHdr, 0, sizeof(CmdHdr));
     6451                memset(&pAhciReq->cmdFis, 0, AHCI_CMDFIS_TYPE_H2D_SIZE);
     6452                pAhciReq->GCPhysCmdHdrAddr = 0;
     6453                pAhciReq->uOffset = 0;
     6454                pAhciReq->cbTransfer = 0;
    72886455#endif
    7289 
    7290                 /* If we encountered an error notify the guest and continue with the next task. */
    7291                 if (RT_FAILURE(rc))
    7292                 {
    7293                     if (   ASMAtomicReadU32(&pAhciPort->u32QueuedTasksFinished) != 0
    7294                         && RT_LIKELY(!pAhciPort->fPortReset))
    7295                         ahciSendSDBFis(pAhciPort, 0, true);
    7296                 }
    72976456            }
    72986457            fTasksToProcess &= ~(1 << idx);
    72996458            idx = ASMBitFirstSetU32(fTasksToProcess);
    73006459        } /* while tasks to process */
    7301 
    7302         if (   ASMAtomicReadU32(&pAhciPort->u32QueuedTasksFinished) != 0
    7303             && RT_LIKELY(!pAhciPort->fPortReset)
    7304             && RT_LIKELY(!pAhciPort->fRedo))
    7305             ahciSendSDBFis(pAhciPort, 0, true);
    73066460
    73076461        u64StopTime = RTTimeMilliTS();
     
    73226476        PDMDevHlpAsyncNotificationCompleted(pAhciPort->pDevInsR3);
    73236477
    7324     /* Free task state memory */
    7325     if (pAhciPortTaskState->pSGListHead)
    7326         RTMemFree(pAhciPortTaskState->pSGListHead);
    7327     if (pAhciPortTaskState->paSGEntries)
    7328         RTMemFree(pAhciPortTaskState->paSGEntries);
    7329     if (pAhciPortTaskState->pvBufferUnaligned)
    7330         RTMemPageFree(pAhciPortTaskState->pvBufferUnaligned, pAhciPortTaskState->cbBufferUnaligned);
    7331     RTMemFree(pAhciPortTaskState);
     6478    RTMemFree(pAhciReq);
     6479    memset(pAhciPort->aCachedTasks, 0, sizeof(pAhciPort->aCachedTasks));
    73326480
    73336481    ahciLog(("%s: Port %d async IO thread exiting\n", __FUNCTION__, pAhciPort->iLUN));
     
    78527000            {
    78537001                if (pAhciPort->aCachedTasks[i])
    7854                 {
    7855                     if (pAhciPort->aCachedTasks[i]->pSGListHead)
    7856                         RTMemFree(pAhciPort->aCachedTasks[i]->pSGListHead);
    7857                     if (pAhciPort->aCachedTasks[i]->paSGEntries)
    7858                         RTMemFree(pAhciPort->aCachedTasks[i]->paSGEntries);
    7859 
    78607002                    RTMemFree(pAhciPort->aCachedTasks[i]);
    7861                 }
    78627003            }
    78637004        }
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette