Changeset 39655 in vbox for trunk/src/VBox/Devices
- Timestamp:
- Dec 19, 2011 5:50:12 PM (13 years ago)
- svn:sync-xref-src-repo-rev:
- 75469
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Storage/DevAHCI.cpp
r39584 r39655 61 61 #define AHCI_MAX_NR_PORTS_IMPL 30 62 62 #define AHCI_NR_COMMAND_SLOTS 32 63 #define AHCI_NR_OF_ALLOWED_BIGGER_LISTS 10064 63 65 64 /** The current saved state version. */ … … 117 116 #define ATAPI_SENSE_SIZE 64 118 117 119 /* Command Header. */ 118 /** 119 * Command Header. 120 */ 121 #pragma pack(1) 120 122 typedef struct 121 123 { … … 131 133 uint32_t u32Reserved[4]; 132 134 } CmdHdr; 135 #pragma pack() 133 136 AssertCompileSize(CmdHdr, 32); 134 137 … … 191 194 #define AHCI_CMDFIS_ERR 3 192 195 193 /**194 * Scatter gather list entry data.195 */196 typedef struct AHCIPORTTASKSTATESGENTRY197 {198 /** Flag whether the buffer in the list is from the guest or an199 * allocated temporary buffer because the segments in the guest200 * are not sector aligned.201 */202 bool fGuestMemory;203 /** Flag dependent data. */204 union205 {206 /** Data to handle direct mappings of guest buffers. */207 struct208 {209 /** The page lock. */210 PGMPAGEMAPLOCK PageLock;211 } direct;212 /** Data to handle temporary buffers. */213 struct214 {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;227 196 /** Pointer to a task state. */ 228 typedef struct AHCI PORTTASKSTATE *PAHCIPORTTASKSTATE;197 typedef struct AHCIREQ *PAHCIREQ; 229 198 230 199 /** … … 232 201 * 233 202 * @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 */ 208 typedef DECLCALLBACK(int) FNAHCIPOSTPROCESS(PAHCIREQ pAhciReq, void **ppvProc, size_t *pcbProc); 237 209 /** Pointer to a FNAHCIPOSTPROCESS() function. */ 238 210 typedef FNAHCIPOSTPROCESS *PFNAHCIPOSTPROCESS; … … 274 246 } AHCITXSTATE, *PAHCITXSTATE; 275 247 248 /** Task encountered a buffer overflow. */ 249 #define AHCI_REQ_OVERFLOW RT_BIT_32(0) 250 276 251 /** 277 252 * A task state. 278 253 */ 279 typedef struct AHCI PORTTASKSTATE254 typedef struct AHCIREQ 280 255 { 281 256 /** Task state. */ … … 295 270 /** Physical address of the command header. - GC */ 296 271 RTGCPHYS GCPhysCmdHdrAddr; 272 /** Physical address if the PRDT */ 273 RTGCPHYS GCPhysPrdtl; 274 /** Number of entries in the PRDTL. */ 275 unsigned cPrdtlEntries; 297 276 /** Data direction. */ 298 277 AHCITXDIR enmTxDir; … … 305 284 /** ATA status register */ 306 285 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; 335 311 336 312 /** … … 508 484 * Only used with the async interface. 509 485 */ 510 R3PTRTYPE(PAHCI PORTTASKSTATE)aCachedTasks[AHCI_NR_COMMAND_SLOTS];486 R3PTRTYPE(PAHCIREQ) aCachedTasks[AHCI_NR_COMMAND_SLOTS]; 511 487 /** First task throwing an error. */ 512 R3PTRTYPE(volatile PAHCI PORTTASKSTATE)pTaskErr;488 R3PTRTYPE(volatile PAHCIREQ) pTaskErr; 513 489 514 490 #if HC_ARCH_BITS == 32 … … 915 891 static int ahciPostFisIntoMemory(PAHCIPort pAhciPort, unsigned uFisType, uint8_t *cmdFis); 916 892 static 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); 893 static size_t ahciCopyToPrdtl(PPDMDEVINS pDevIns, PAHCIREQ pAhciReq, 894 void *pvBuf, size_t cbBuf); 895 static size_t ahciCopyFromPrdtl(PPDMDEVINS pDevIns, PAHCIREQ pAhciReq, 896 void *pvBuf, size_t cbBuf); 926 897 static bool ahciCancelActiveTasks(PAHCIPort pAhciPort); 927 898 #endif … … 936 907 #define PDMILEDPORTS_2_PAHCI(pInterface) ( (PAHCI)((uintptr_t)(pInterface) - RT_OFFSETOF(AHCI, ILeds)) ) 937 908 938 #if 1939 909 #define AHCI_RTGCPHYS_FROM_U32(Hi, Lo) ( (RTGCPHYS)RT_MAKE_U64(Lo, Hi) ) 940 #else941 #define AHCI_RTGCPHYS_FROM_U32(Hi, Lo) ( (RTGCPHYS)(Lo) )942 #endif943 910 944 911 #ifdef IN_RING3 … … 2653 2620 } 2654 2621 2622 /** 2623 * @interface_method_impl{PDMIBLOCKPORT,pfnQueryDeviceLocation} 2624 */ 2655 2625 static DECLCALLBACK(int) ahciR3PortQueryDeviceLocation(PPDMIBLOCKPORT pInterface, const char **ppcszController, 2656 2626 uint32_t *piInstance, uint32_t *piLUN) … … 2686 2656 { 2687 2657 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__)); 2719 2682 break; 2683 } 2720 2684 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)); 2725 2688 break; 2689 } 2726 2690 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)); 2731 2694 break; 2695 } 2732 2696 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)); 2737 2700 break; 2701 } 2738 2702 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)); 2743 2706 break; 2707 } 2744 2708 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)); 2749 2712 break; 2713 } 2750 2714 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__)); 2754 2717 break; 2718 } 2755 2719 default: 2756 2720 ahciLog(("%s: ERROR Unknown command FIS type\n", __FUNCTION__)); … … 2859 2823 { 2860 2824 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; 2865 2828 break; 2829 } 2866 2830 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; 2871 2834 break; 2835 } 2872 2836 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; 2877 2840 break; 2841 } 2878 2842 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; 2883 2846 break; 2847 } 2884 2848 default: 2885 2849 /* … … 2954 2918 } 2955 2919 2956 static void atapiCmdOK(PAHCIPort pAhciPort, PAHCI PORTTASKSTATE pAhciPortTaskState)2957 { 2958 pAhci PortTaskState->uATARegError = 0;2959 pAhci PortTaskState->uATARegStatus = ATA_STAT_READY | ATA_STAT_SEEK;2960 pAhci PortTaskState->cmdFis[AHCI_CMDFIS_SECTN] = (pAhciPortTaskState->cmdFis[AHCI_CMDFIS_SECTN] & ~7)2961 | ((pAhci PortTaskState->enmTxDir != AHCITXDIR_WRITE) ? ATAPI_INT_REASON_IO : 0)2962 | (!pAhci PortTaskState->cbTransfer ? ATAPI_INT_REASON_CD : 0);2920 static 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); 2963 2927 memset(pAhciPort->abATAPISense, '\0', sizeof(pAhciPort->abATAPISense)); 2964 2928 pAhciPort->abATAPISense[0] = 0x70; … … 2966 2930 } 2967 2931 2968 static void atapiCmdError(PAHCIPort pAhciPort, PAHCI PORTTASKSTATE pAhciPortTaskState, const uint8_t *pabATAPISense, size_t cbATAPISense)2932 static void atapiCmdError(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, const uint8_t *pabATAPISense, size_t cbATAPISense) 2969 2933 { 2970 2934 Log(("%s: sense=%#x (%s) asc=%#x ascq=%#x (%s)\n", __FUNCTION__, pabATAPISense[2] & 0x0f, SCSISenseText(pabATAPISense[2] & 0x0f), 2971 2935 pabATAPISense[12], pabATAPISense[13], SCSISenseExtText(pabATAPISense[12], pabATAPISense[13]))); 2972 pAhci PortTaskState->uATARegError = pabATAPISense[2] << 4;2973 pAhci PortTaskState->uATARegStatus = ATA_STAT_READY | ATA_STAT_ERR;2974 pAhci PortTaskState->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) | 2975 2939 ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD; 2976 2940 memset(pAhciPort->abATAPISense, '\0', sizeof(pAhciPort->abATAPISense)); … … 2980 2944 /** @todo deprecated function - doesn't provide enough info. Replace by direct 2981 2945 * calls to atapiCmdError() with full data. */ 2982 static void atapiCmdErrorSimple(PAHCIPort pAhciPort, PAHCI PORTTASKSTATE pAhciPortTaskState, uint8_t uATAPISenseKey, uint8_t uATAPIASC)2946 static void atapiCmdErrorSimple(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, uint8_t uATAPISenseKey, uint8_t uATAPIASC) 2983 2947 { 2984 2948 uint8_t abATAPISense[ATAPI_SENSE_SIZE]; … … 2988 2952 abATAPISense[7] = 10; 2989 2953 abATAPISense[12] = uATAPIASC; 2990 atapiCmdError(pAhciPort, pAhci PortTaskState, abATAPISense, sizeof(abATAPISense));2954 atapiCmdError(pAhciPort, pAhciReq, abATAPISense, sizeof(abATAPISense)); 2991 2955 } 2992 2956 … … 3120 3084 } 3121 3085 3122 typedef int (*PAtapiFunc)(PAHCI PORTTASKSTATE, PAHCIPort, int *);3123 3124 static int atapiGetConfigurationSS(PAHCI PORTTASKSTATE, PAHCIPort, int *);3125 static int atapiGetEventStatusNotificationSS(PAHCI PORTTASKSTATE, PAHCIPort, int *);3126 static int atapiIdentifySS(PAHCI PORTTASKSTATE, PAHCIPort, int *);3127 static int atapiInquirySS(PAHCI PORTTASKSTATE, PAHCIPort, int *);3128 static int atapiMechanismStatusSS(PAHCI PORTTASKSTATE, PAHCIPort, int *);3129 static int atapiModeSenseErrorRecoverySS(PAHCI PORTTASKSTATE, PAHCIPort, int *);3130 static int atapiModeSenseCDStatusSS(PAHCI PORTTASKSTATE, PAHCIPort, int *);3131 static int atapiReadCapacitySS(PAHCI PORTTASKSTATE, PAHCIPort, int *);3132 static int atapiReadDiscInformationSS(PAHCI PORTTASKSTATE, PAHCIPort, int *);3133 static int atapiReadTOCNormalSS(PAHCI PORTTASKSTATE, PAHCIPort, int *);3134 static int atapiReadTOCMultiSS(PAHCI PORTTASKSTATE, PAHCIPort, int *);3135 static int atapiReadTOCRawSS(PAHCI PORTTASKSTATE, PAHCIPort, int *);3136 static int atapiReadTrackInformationSS(PAHCI PORTTASKSTATE, PAHCIPort, int *);3137 static int atapiRequestSenseSS(PAHCI PORTTASKSTATE, PAHCIPort, int *);3138 static int atapiPassthroughSS(PAHCI PORTTASKSTATE, PAHCIPort, int *);3086 typedef int (*PAtapiFunc)(PAHCIREQ, PAHCIPort, size_t, size_t *); 3087 3088 static int atapiGetConfigurationSS(PAHCIREQ, PAHCIPort, size_t, size_t *); 3089 static int atapiGetEventStatusNotificationSS(PAHCIREQ, PAHCIPort, size_t, size_t *); 3090 static int atapiIdentifySS(PAHCIREQ, PAHCIPort, size_t, size_t *); 3091 static int atapiInquirySS(PAHCIREQ, PAHCIPort, size_t, size_t *); 3092 static int atapiMechanismStatusSS(PAHCIREQ, PAHCIPort, size_t, size_t *); 3093 static int atapiModeSenseErrorRecoverySS(PAHCIREQ, PAHCIPort, size_t, size_t *); 3094 static int atapiModeSenseCDStatusSS(PAHCIREQ, PAHCIPort, size_t, size_t *); 3095 static int atapiReadCapacitySS(PAHCIREQ, PAHCIPort, size_t, size_t *); 3096 static int atapiReadDiscInformationSS(PAHCIREQ, PAHCIPort, size_t, size_t *); 3097 static int atapiReadTOCNormalSS(PAHCIREQ, PAHCIPort, size_t, size_t *); 3098 static int atapiReadTOCMultiSS(PAHCIREQ, PAHCIPort, size_t, size_t *); 3099 static int atapiReadTOCRawSS(PAHCIREQ, PAHCIPort, size_t, size_t *); 3100 static int atapiReadTrackInformationSS(PAHCIREQ, PAHCIPort, size_t, size_t *); 3101 static int atapiRequestSenseSS(PAHCIREQ, PAHCIPort, size_t, size_t *); 3102 static int atapiPassthroughSS(PAHCIREQ, PAHCIPort, size_t, size_t *); 3139 3103 3140 3104 /** … … 3186 3150 }; 3187 3151 3188 static int atapiIdentifySS(PAHCI PORTTASKSTATE pAhciPortTaskState, PAHCIPort pAhciPort, int *pcbData)3152 static int atapiIdentifySS(PAHCIREQ pAhciReq, PAHCIPort pAhciPort, size_t cbData, size_t *pcbData) 3189 3153 { 3190 3154 uint16_t p[256]; … … 3227 3191 3228 3192 /* 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); 3232 3197 return VINF_SUCCESS; 3233 3198 } 3234 3199 3235 static int atapiReadCapacitySS(PAHCI PORTTASKSTATE pAhciPortTaskState, PAHCIPort pAhciPort, int *pcbData)3200 static int atapiReadCapacitySS(PAHCIREQ pAhciReq, PAHCIPort pAhciPort, size_t cbData, size_t *pcbData) 3236 3201 { 3237 3202 uint8_t aBuf[8]; … … 3241 3206 3242 3207 /* 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); 3246 3212 return VINF_SUCCESS; 3247 3213 } 3248 3214 3249 3215 3250 static int atapiReadDiscInformationSS(PAHCI PORTTASKSTATE pAhciPortTaskState, PAHCIPort pAhciPort, int *pcbData)3216 static int atapiReadDiscInformationSS(PAHCIREQ pAhciReq, PAHCIPort pAhciPort, size_t cbData, size_t *pcbData) 3251 3217 { 3252 3218 uint8_t aBuf[34]; … … 3268 3234 3269 3235 /* 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); 3273 3240 return VINF_SUCCESS; 3274 3241 } 3275 3242 3276 3243 3277 static int atapiReadTrackInformationSS(PAHCI PORTTASKSTATE pAhciPortTaskState, PAHCIPort pAhciPort, int *pcbData)3244 static int atapiReadTrackInformationSS(PAHCIREQ pAhciReq, PAHCIPort pAhciPort, size_t cbData, size_t *pcbData) 3278 3245 { 3279 3246 uint8_t aBuf[36]; 3280 3247 3281 3248 /* Accept address/number type of 1 only, and only track 1 exists. */ 3282 if ((pAhci PortTaskState->aATAPICmd[1] & 0x03) != 1 || ataBE2H_U32(&pAhciPortTaskState->aATAPICmd[2]) != 1)3283 { 3284 atapiCmdErrorSimple(pAhciPort, pAhci PortTaskState, 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); 3285 3252 return VINF_SUCCESS; 3286 3253 } … … 3298 3265 3299 3266 /* 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); 3303 3271 return VINF_SUCCESS; 3304 3272 } … … 3421 3389 } 3422 3390 3423 static int atapiGetConfigurationSS(PAHCI PORTTASKSTATE pAhciPortTaskState, PAHCIPort pAhciPort, int *pcbData)3391 static int atapiGetConfigurationSS(PAHCIREQ pAhciReq, PAHCIPort pAhciPort, size_t cbData, size_t *pcbData) 3424 3392 { 3425 3393 uint8_t aBuf[80]; … … 3429 3397 3430 3398 /* Accept valid request types only, and only starting feature 0. */ 3431 if ((pAhci PortTaskState->aATAPICmd[1] & 0x03) == 3 || ataBE2H_U16(&pAhciPortTaskState->aATAPICmd[2]) != 0)3432 { 3433 atapiCmdErrorSimple(pAhciPort, pAhci PortTaskState, 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); 3434 3402 return VINF_SUCCESS; 3435 3403 } … … 3479 3447 3480 3448 /* 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); 3484 3453 return VINF_SUCCESS; 3485 3454 } 3486 3455 3487 3456 3488 static int atapiGetEventStatusNotificationSS(PAHCI PORTTASKSTATE pAhciPortTaskState, PAHCIPort pAhciPort, int *pcbData)3457 static int atapiGetEventStatusNotificationSS(PAHCIREQ pAhciReq, PAHCIPort pAhciPort, size_t cbData, size_t *pcbData) 3489 3458 { 3490 3459 uint8_t abBuf[8]; 3491 3460 3492 Assert(pAhci PortTaskState->enmTxDir == AHCITXDIR_READ);3493 Assert(pAhci PortTaskState->cbTransfer <= 8);3494 3495 if (!(pAhci PortTaskState->aATAPICmd[1] & 1))3461 Assert(pAhciReq->enmTxDir == AHCITXDIR_READ); 3462 Assert(pAhciReq->cbTransfer <= 8); 3463 3464 if (!(pAhciReq->aATAPICmd[1] & 1)) 3496 3465 { 3497 3466 /* no asynchronous operation supported */ 3498 atapiCmdErrorSimple(pAhciPort, pAhci PortTaskState, 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); 3499 3468 return VINF_SUCCESS; 3500 3469 } … … 3555 3524 } while (!ASMAtomicCmpXchgU32(&pAhciPort->MediaEventStatus, NewStatus, OldStatus)); 3556 3525 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); 3560 3530 return VINF_SUCCESS; 3561 3531 } 3562 3532 3563 3533 3564 static int atapiInquirySS(PAHCI PORTTASKSTATE pAhciPortTaskState, PAHCIPort pAhciPort, int *pcbData)3534 static int atapiInquirySS(PAHCIREQ pAhciReq, PAHCIPort pAhciPort, size_t cbData, size_t *pcbData) 3565 3535 { 3566 3536 uint8_t aBuf[36]; … … 3579 3549 3580 3550 /* 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); 3584 3555 return VINF_SUCCESS; 3585 3556 } 3586 3557 3587 3558 3588 static int atapiModeSenseErrorRecoverySS(PAHCI PORTTASKSTATE pAhciPortTaskState, PAHCIPort pAhciPort, int *pcbData)3559 static int atapiModeSenseErrorRecoverySS(PAHCIREQ pAhciReq, PAHCIPort pAhciPort, size_t cbData, size_t *pcbData) 3589 3560 { 3590 3561 uint8_t aBuf[16]; … … 3608 3579 3609 3580 /* 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); 3613 3585 return VINF_SUCCESS; 3614 3586 } 3615 3587 3616 3588 3617 static int atapiModeSenseCDStatusSS(PAHCI PORTTASKSTATE pAhciPortTaskState, PAHCIPort pAhciPort, int *pcbData)3589 static int atapiModeSenseCDStatusSS(PAHCIREQ pAhciReq, PAHCIPort pAhciPort, size_t cbData, size_t *pcbData) 3618 3590 { 3619 3591 uint8_t aBuf[40]; … … 3658 3630 3659 3631 /* 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); 3663 3636 return VINF_SUCCESS; 3664 3637 } 3665 3638 3666 3639 3667 static int atapiRequestSenseSS(PAHCI PORTTASKSTATE pAhciPortTaskState, PAHCIPort pAhciPort, int *pcbData)3640 static int atapiRequestSenseSS(PAHCIREQ pAhciReq, PAHCIPort pAhciPort, size_t cbData, size_t *pcbData) 3668 3641 { 3669 3642 /* 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); 3673 3647 return VINF_SUCCESS; 3674 3648 } 3675 3649 3676 3650 3677 static int atapiMechanismStatusSS(PAHCI PORTTASKSTATE pAhciPortTaskState, PAHCIPort pAhciPort, int *pcbData)3651 static int atapiMechanismStatusSS(PAHCIREQ pAhciReq, PAHCIPort pAhciPort, size_t cbData, size_t *pcbData) 3678 3652 { 3679 3653 uint8_t aBuf[8]; … … 3688 3662 3689 3663 /* 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); 3693 3668 return VINF_SUCCESS; 3694 3669 } 3695 3670 3696 3671 3697 static int atapiReadTOCNormalSS(PAHCI PORTTASKSTATE pAhciPortTaskState, PAHCIPort pAhciPort, int *pcbData)3672 static int atapiReadTOCNormalSS(PAHCIREQ pAhciReq, PAHCIPort pAhciPort, size_t cbData, size_t *pcbData) 3698 3673 { 3699 3674 uint8_t aBuf[20], *q, iStartTrack; … … 3701 3676 uint32_t cbSize; 3702 3677 3703 fMSF = (pAhci PortTaskState->aATAPICmd[1] >> 1) & 1;3704 iStartTrack = pAhci PortTaskState->aATAPICmd[6];3678 fMSF = (pAhciReq->aATAPICmd[1] >> 1) & 1; 3679 iStartTrack = pAhciReq->aATAPICmd[6]; 3705 3680 if (iStartTrack > 1 && iStartTrack != 0xaa) 3706 3681 { 3707 atapiCmdErrorSimple(pAhciPort, pAhci PortTaskState, 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); 3708 3683 return VINF_SUCCESS; 3709 3684 } … … 3750 3725 3751 3726 /* 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); 3755 3731 return VINF_SUCCESS; 3756 3732 } 3757 3733 3758 3734 3759 static int atapiReadTOCMultiSS(PAHCI PORTTASKSTATE pAhciPortTaskState, PAHCIPort pAhciPort, int *pcbData)3735 static int atapiReadTOCMultiSS(PAHCIREQ pAhciReq, PAHCIPort pAhciPort, size_t cbData, size_t *pcbData) 3760 3736 { 3761 3737 uint8_t aBuf[12]; 3762 3738 bool fMSF; 3763 3739 3764 fMSF = (pAhci PortTaskState->aATAPICmd[1] >> 1) & 1;3740 fMSF = (pAhciReq->aATAPICmd[1] >> 1) & 1; 3765 3741 /* multi session: only a single session defined */ 3766 3742 /** @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. */ … … 3783 3759 3784 3760 /* 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); 3788 3765 return VINF_SUCCESS; 3789 3766 } 3790 3767 3791 3768 3792 static int atapiReadTOCRawSS(PAHCI PORTTASKSTATE pAhciPortTaskState, PAHCIPort pAhciPort, int *pcbData)3769 static int atapiReadTOCRawSS(PAHCIREQ pAhciReq, PAHCIPort pAhciPort, size_t cbData, size_t *pcbData) 3793 3770 { 3794 3771 uint8_t aBuf[50]; /* Counted a maximum of 45 bytes but better be on the safe side. */ … … 3797 3774 uint32_t cbSize; 3798 3775 3799 fMSF = (pAhci PortTaskState->aATAPICmd[1] >> 1) & 1;3800 iStartTrack = pAhci PortTaskState->aATAPICmd[6];3776 fMSF = (pAhciReq->aATAPICmd[1] >> 1) & 1; 3777 iStartTrack = pAhciReq->aATAPICmd[6]; 3801 3778 3802 3779 q = aBuf + 2; … … 3871 3848 3872 3849 /* 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); 3876 3854 return VINF_SUCCESS; 3877 3855 } … … 3885 3863 } 3886 3864 3887 static int atapiPassthroughSS(PAHCI PORTTASKSTATE pAhciPortTaskState, PAHCIPort pAhciPort, int *pcbData)3865 static int atapiPassthroughSS(PAHCIREQ pAhciReq, PAHCIPort pAhciPort, size_t cbData, size_t *pcbData) 3888 3866 { 3889 3867 int rc = VINF_SUCCESS; 3890 3868 uint8_t abATAPISense[ATAPI_SENSE_SIZE]; 3891 3869 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 } 3894 3887 3895 3888 /* Simple heuristics: if there is at least one sector of data … … 3897 3890 if (cbTransfer >= 2048) 3898 3891 { 3899 if (pAhci PortTaskState->enmTxDir != AHCITXDIR_WRITE)3892 if (pAhciReq->enmTxDir != AHCITXDIR_WRITE) 3900 3893 pAhciPort->Led.Asserted.s.fReading = pAhciPort->Led.Actual.s.fReading = 1; 3901 3894 else … … 3910 3903 uint8_t aATAPICmd[ATAPI_PACKET_SIZE]; 3911 3904 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]) 3917 3908 { 3918 3909 case SCSI_READ_10: 3919 3910 case SCSI_WRITE_10: 3920 3911 case SCSI_WRITE_AND_VERIFY_10: 3921 iATAPILBA = ataBE2H_U32(pAhci PortTaskState->aATAPICmd + 2);3922 cSectors = ataBE2H_U16(pAhci PortTaskState->aATAPICmd + 7);3912 iATAPILBA = ataBE2H_U32(pAhciReq->aATAPICmd + 2); 3913 cSectors = ataBE2H_U16(pAhciReq->aATAPICmd + 7); 3923 3914 break; 3924 3915 case SCSI_READ_12: 3925 3916 case SCSI_WRITE_12: 3926 iATAPILBA = ataBE2H_U32(pAhci PortTaskState->aATAPICmd + 2);3927 cSectors = ataBE2H_U32(pAhci PortTaskState->aATAPICmd + 6);3917 iATAPILBA = ataBE2H_U32(pAhciReq->aATAPICmd + 2); 3918 cSectors = ataBE2H_U32(pAhciReq->aATAPICmd + 6); 3928 3919 break; 3929 3920 case SCSI_READ_CD: 3930 iATAPILBA = ataBE2H_U32(pAhci PortTaskState->aATAPICmd + 2);3931 cSectors = ataBE2H_U24(pAhci PortTaskState->aATAPICmd + 6);3921 iATAPILBA = ataBE2H_U32(pAhciReq->aATAPICmd + 2); 3922 cSectors = ataBE2H_U24(pAhciReq->aATAPICmd + 6); 3932 3923 break; 3933 3924 case SCSI_READ_CD_MSF: 3934 iATAPILBA = ataMSF2LBA(pAhci PortTaskState->aATAPICmd + 3);3935 cSectors = ataMSF2LBA(pAhci PortTaskState->aATAPICmd + 6) - iATAPILBA;3925 iATAPILBA = ataMSF2LBA(pAhciReq->aATAPICmd + 3); 3926 cSectors = ataMSF2LBA(pAhciReq->aATAPICmd + 6) - iATAPILBA; 3936 3927 break; 3937 3928 default: 3938 AssertMsgFailed(("Don't know how to split command %#04x\n", pAhci PortTaskState->aATAPICmd[0]));3929 AssertMsgFailed(("Don't know how to split command %#04x\n", pAhciReq->aATAPICmd[0])); 3939 3930 if (pAhciPort->cErrors++ < MAX_LOG_REL_ERRORS) 3940 3931 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); 3945 3937 cReqSectors = 0; 3946 3938 for (uint32_t i = cSectors; i > 0; i -= cReqSectors) 3947 3939 { 3948 if (i * pAhci PortTaskState->cbATAPISector > SCSI_MAX_BUFFER_SIZE)3949 cReqSectors = SCSI_MAX_BUFFER_SIZE / pAhci PortTaskState->cbATAPISector;3940 if (i * pAhciReq->cbATAPISector > SCSI_MAX_BUFFER_SIZE) 3941 cReqSectors = SCSI_MAX_BUFFER_SIZE / pAhciReq->cbATAPISector; 3950 3942 else 3951 3943 cReqSectors = i; 3952 cbCurrTX = pAhci PortTaskState->cbATAPISector * cReqSectors;3953 switch (pAhci PortTaskState->aATAPICmd[0])3944 cbCurrTX = pAhciReq->cbATAPISector * cReqSectors; 3945 switch (pAhciReq->aATAPICmd[0]) 3954 3946 { 3955 3947 case SCSI_READ_10: … … 3975 3967 rc = pAhciPort->pDrvBlock->pfnSendCmd(pAhciPort->pDrvBlock, 3976 3968 aATAPICmd, 3977 pAhci PortTaskState->enmTxDir == AHCITXDIR_READ3969 pAhciReq->enmTxDir == AHCITXDIR_READ 3978 3970 ? PDMBLOCKTXDIR_FROM_DEVICE 3979 3971 : PDMBLOCKTXDIR_TO_DEVICE, … … 3986 3978 break; 3987 3979 iATAPILBA += cReqSectors; 3988 pbBuf += pAhci PortTaskState->cbATAPISector * cReqSectors;3980 pbBuf += pAhciReq->cbATAPISector * cReqSectors; 3989 3981 } 3990 3982 } … … 3993 3985 PDMBLOCKTXDIR enmBlockTxDir = PDMBLOCKTXDIR_NONE; 3994 3986 3995 if (pAhci PortTaskState->enmTxDir == AHCITXDIR_READ)3987 if (pAhciReq->enmTxDir == AHCITXDIR_READ) 3996 3988 enmBlockTxDir = PDMBLOCKTXDIR_FROM_DEVICE; 3997 else if (pAhci PortTaskState->enmTxDir == AHCITXDIR_WRITE)3989 else if (pAhciReq->enmTxDir == AHCITXDIR_WRITE) 3998 3990 enmBlockTxDir = PDMBLOCKTXDIR_TO_DEVICE; 3999 else if (pAhci PortTaskState->enmTxDir == AHCITXDIR_NONE)3991 else if (pAhciReq->enmTxDir == AHCITXDIR_NONE) 4000 3992 enmBlockTxDir = PDMBLOCKTXDIR_NONE; 4001 3993 else 4002 AssertMsgFailed(("Invalid transfer direction %d\n", pAhci PortTaskState->enmTxDir));3994 AssertMsgFailed(("Invalid transfer direction %d\n", pAhciReq->enmTxDir)); 4003 3995 4004 3996 rc = pAhciPort->pDrvBlock->pfnSendCmd(pAhciPort->pDrvBlock, 4005 pAhci PortTaskState->aATAPICmd,3997 pAhciReq->aATAPICmd, 4006 3998 enmBlockTxDir, 4007 p AhciPortTaskState->pSGListHead[0].pvSeg,3999 pvBuf, 4008 4000 &cbTransfer, 4009 4001 abATAPISense, … … 4015 4007 if (cbTransfer >= 2048) 4016 4008 { 4017 if (pAhci PortTaskState->enmTxDir != AHCITXDIR_WRITE)4009 if (pAhciReq->enmTxDir != AHCITXDIR_WRITE) 4018 4010 { 4019 4011 pAhciPort->Led.Actual.s.fReading = 0; … … 4029 4021 if (RT_SUCCESS(rc)) 4030 4022 { 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) 4038 4028 { 4039 4029 /* Make sure that the real drive cannot be identified. 4040 4030 * Motivation: changing the VM configuration should be as 4041 4031 * 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); 4045 4038 } 4046 else if (pAhci PortTaskState->aATAPICmd[0] == SCSI_READ_TOC_PMA_ATIP)4039 else if (pAhciReq->aATAPICmd[0] == SCSI_READ_TOC_PMA_ATIP) 4047 4040 { 4048 4041 /* Set the media type if we can detect it. */ 4049 uint8_t *pbBuf = (uint8_t *)p AhciPortTaskState->pSGListHead[0].pvSeg;4042 uint8_t *pbBuf = (uint8_t *)pvBuf; 4050 4043 4051 4044 /** @todo: Implemented only for formatted TOC now. */ 4052 if ( (pAhci PortTaskState->aATAPICmd[1] & 0xf) == 04045 if ( (pAhciReq->aATAPICmd[1] & 0xf) == 0 4053 4046 && cbTransfer >= 6) 4054 4047 { … … 4073 4066 ataMediumTypeSet(pAhciPort, ATA_MEDIA_TYPE_UNKNOWN); 4074 4067 } 4068 4075 4069 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); 4079 4083 } 4080 4084 else … … 4082 4086 if (pAhciPort->cErrors < MAX_LOG_REL_ERRORS) 4083 4087 { 4084 uint8_t u8Cmd = pAhci PortTaskState->aATAPICmd[0];4088 uint8_t u8Cmd = pAhciReq->aATAPICmd[0]; 4085 4089 do 4086 4090 { … … 4097 4101 } while (0); 4098 4102 } 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 4112 static int atapiDoTransfer(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, size_t cbMax, ATAPIFN iSourceSink) 4113 { 4114 size_t cbTransfered = 0; 4107 4115 int rc, rcSourceSink; 4108 4116 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; 4124 4122 4125 4123 LogFlow(("cbTransfered=%d\n", cbTransfered)); 4126 4124 4127 if (pAhciPortTaskState->cbSGBuffers)4128 {4129 rc = ahciScatterGatherListDestroy(pAhciPort, pAhciPortTaskState);4130 AssertRC(rc);4131 }4132 4133 4125 /* 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)); 4135 4128 4136 4129 return rcSourceSink; 4137 4130 } 4138 4131 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; 4132 static 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; 4145 4145 4146 4146 for (uint32_t i = iATAPILBA; i < iATAPILBA + cSectors; i++) … … 4163 4163 } 4164 4164 4165 *ppvProc = pbBuf; 4166 *pcbProc = pAhciReq->cbTransfer; 4167 4165 4168 return VINF_SUCCESS; 4166 4169 } 4167 4170 4168 static int atapiReadSectors(PAHCIPort pAhciPort, PAHCI PORTTASKSTATE pAhciPortTaskState, uint32_t iATAPILBA, uint32_t cSectors, uint32_t cbSector)4171 static int atapiReadSectors(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, uint32_t iATAPILBA, uint32_t cSectors, uint32_t cbSector) 4169 4172 { 4170 4173 Log(("%s: %d sectors at LBA %d\n", __FUNCTION__, cSectors, iATAPILBA)); … … 4173 4176 { 4174 4177 case 2048: 4175 pAhci PortTaskState->uOffset = (uint64_t)iATAPILBA * cbSector;4176 pAhci PortTaskState->cbTransfer = cSectors * cbSector;4178 pAhciReq->uOffset = (uint64_t)iATAPILBA * cbSector; 4179 pAhciReq->cbTransfer = cSectors * cbSector; 4177 4180 break; 4178 4181 case 2352: 4179 4182 { 4180 pAhci PortTaskState->pfnPostProcess = atapiReadSectors2352PostProcess;4181 pAhci PortTaskState->uOffset = (uint64_t)iATAPILBA * 2048;4182 pAhci PortTaskState->cbTransfer = cSectors * 2048;4183 pAhciReq->u.Io.pfnPostProcess = atapiReadSectors2352PostProcess; 4184 pAhciReq->uOffset = (uint64_t)iATAPILBA * 2048; 4185 pAhciReq->cbTransfer = cSectors * 2048; 4183 4186 break; 4184 4187 } … … 4191 4194 } 4192 4195 4193 static AHCITXDIR atapiParseCmdVirtualATAPI(PAHCIPort pAhciPort, PAHCI PORTTASKSTATE pAhciPortTaskState)4196 static AHCITXDIR atapiParseCmdVirtualATAPI(PAHCIPort pAhciPort, PAHCIREQ pAhciReq) 4194 4197 { 4195 4198 AHCITXDIR rc = AHCITXDIR_NONE; … … 4197 4200 uint32_t cbMax; 4198 4201 4199 pbPacket = pAhci PortTaskState->aATAPICmd;4202 pbPacket = pAhciReq->aATAPICmd; 4200 4203 4201 4204 ahciLog(("%s: ATAPI CMD=%#04x \"%s\"\n", __FUNCTION__, pbPacket[0], SCSICmdText(pbPacket[0]))); … … 4207 4210 { 4208 4211 if (pAhciPort->cNotifiedMediaChange-- > 2) 4209 atapiCmdErrorSimple(pAhciPort, pAhci PortTaskState, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);4212 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT); 4210 4213 else 4211 atapiCmdErrorSimple(pAhciPort, pAhci PortTaskState, 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 */ 4212 4215 } 4213 4216 else if (pAhciPort->pDrvMount->pfnIsMounted(pAhciPort->pDrvMount)) 4214 atapiCmdOK(pAhciPort, pAhci PortTaskState);4217 atapiCmdOK(pAhciPort, pAhciReq); 4215 4218 else 4216 atapiCmdErrorSimple(pAhciPort, pAhci PortTaskState, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);4219 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT); 4217 4220 break; 4218 4221 case SCSI_GET_EVENT_STATUS_NOTIFICATION: 4219 4222 cbMax = ataBE2H_U16(pbPacket + 7); 4220 atapiDoTransfer(pAhciPort, pAhci PortTaskState, ATAFN_SS_ATAPI_GET_EVENT_STATUS_NOTIFICATION);4223 atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_GET_EVENT_STATUS_NOTIFICATION); 4221 4224 break; 4222 4225 case SCSI_MODE_SENSE_10: … … 4232 4235 { 4233 4236 case SCSI_MODEPAGE_ERROR_RECOVERY: 4234 atapiDoTransfer(pAhciPort, pAhci PortTaskState, ATAFN_SS_ATAPI_MODE_SENSE_ERROR_RECOVERY);4237 atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_MODE_SENSE_ERROR_RECOVERY); 4235 4238 break; 4236 4239 case SCSI_MODEPAGE_CD_STATUS: 4237 atapiDoTransfer(pAhciPort, pAhci PortTaskState, ATAFN_SS_ATAPI_MODE_SENSE_CD_STATUS);4240 atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_MODE_SENSE_CD_STATUS); 4238 4241 break; 4239 4242 default: … … 4247 4250 default: 4248 4251 case SCSI_PAGECONTROL_SAVED: 4249 atapiCmdErrorSimple(pAhciPort, pAhci PortTaskState, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_SAVING_PARAMETERS_NOT_SUPPORTED);4252 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_SAVING_PARAMETERS_NOT_SUPPORTED); 4250 4253 break; 4251 4254 } … … 4254 4257 case SCSI_REQUEST_SENSE: 4255 4258 cbMax = pbPacket[4]; 4256 atapiDoTransfer(pAhciPort, pAhci PortTaskState, ATAFN_SS_ATAPI_REQUEST_SENSE);4259 atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_REQUEST_SENSE); 4257 4260 break; 4258 4261 case SCSI_PREVENT_ALLOW_MEDIUM_REMOVAL: … … 4263 4266 else 4264 4267 pAhciPort->pDrvMount->pfnUnlock(pAhciPort->pDrvMount); 4265 atapiCmdOK(pAhciPort, pAhci PortTaskState);4268 atapiCmdOK(pAhciPort, pAhciReq); 4266 4269 } 4267 4270 else 4268 atapiCmdErrorSimple(pAhciPort, pAhci PortTaskState, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);4271 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT); 4269 4272 break; 4270 4273 case SCSI_READ_10: … … 4276 4279 { 4277 4280 pAhciPort->cNotifiedMediaChange-- ; 4278 atapiCmdErrorSimple(pAhciPort, pAhci PortTaskState, 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 */ 4279 4282 break; 4280 4283 } 4281 4284 else if (!pAhciPort->pDrvMount->pfnIsMounted(pAhciPort->pDrvMount)) 4282 4285 { 4283 atapiCmdErrorSimple(pAhciPort, pAhci PortTaskState, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);4286 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT); 4284 4287 break; 4285 4288 } … … 4291 4294 if (cSectors == 0) 4292 4295 { 4293 atapiCmdOK(pAhciPort, pAhci PortTaskState);4296 atapiCmdOK(pAhciPort, pAhciReq); 4294 4297 break; 4295 4298 } … … 4306 4309 uLastLogTS = RTTimeMilliTS(); 4307 4310 } 4308 atapiCmdErrorSimple(pAhciPort, pAhci PortTaskState, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR);4311 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR); 4309 4312 break; 4310 4313 } 4311 atapiReadSectors(pAhciPort, pAhci PortTaskState, iATAPILBA, cSectors, 2048);4314 atapiReadSectors(pAhciPort, pAhciReq, iATAPILBA, cSectors, 2048); 4312 4315 rc = AHCITXDIR_READ; 4313 4316 } … … 4320 4323 { 4321 4324 pAhciPort->cNotifiedMediaChange-- ; 4322 atapiCmdErrorSimple(pAhciPort, pAhci PortTaskState, 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 */ 4323 4326 break; 4324 4327 } 4325 4328 else if (!pAhciPort->pDrvMount->pfnIsMounted(pAhciPort->pDrvMount)) 4326 4329 { 4327 atapiCmdErrorSimple(pAhciPort, pAhci PortTaskState, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);4330 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT); 4328 4331 break; 4329 4332 } … … 4332 4335 if (cSectors == 0) 4333 4336 { 4334 atapiCmdOK(pAhciPort, pAhci PortTaskState);4337 atapiCmdOK(pAhciPort, pAhciReq); 4335 4338 break; 4336 4339 } … … 4347 4350 uLastLogTS = RTTimeMilliTS(); 4348 4351 } 4349 atapiCmdErrorSimple(pAhciPort, pAhci PortTaskState, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR);4352 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR); 4350 4353 break; 4351 4354 } … … 4354 4357 case 0x00: 4355 4358 /* nothing */ 4356 atapiCmdOK(pAhciPort, pAhci PortTaskState);4359 atapiCmdOK(pAhciPort, pAhciReq); 4357 4360 break; 4358 4361 case 0x10: 4359 4362 /* normal read */ 4360 atapiReadSectors(pAhciPort, pAhci PortTaskState, iATAPILBA, cSectors, 2048);4363 atapiReadSectors(pAhciPort, pAhciReq, iATAPILBA, cSectors, 2048); 4361 4364 rc = AHCITXDIR_READ; 4362 4365 break; 4363 4366 case 0xf8: 4364 4367 /* read all data */ 4365 atapiReadSectors(pAhciPort, pAhci PortTaskState, iATAPILBA, cSectors, 2352);4368 atapiReadSectors(pAhciPort, pAhciReq, iATAPILBA, cSectors, 2352); 4366 4369 rc = AHCITXDIR_READ; 4367 4370 break; 4368 4371 default: 4369 4372 LogRel(("AHCI ATAPI: LUN#%d: CD-ROM sector format not supported\n", pAhciPort->iLUN)); 4370 atapiCmdErrorSimple(pAhciPort, pAhci PortTaskState, 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); 4371 4374 break; 4372 4375 } … … 4379 4382 { 4380 4383 pAhciPort->cNotifiedMediaChange-- ; 4381 atapiCmdErrorSimple(pAhciPort, pAhci PortTaskState, 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 */ 4382 4385 break; 4383 4386 } 4384 4387 else if (!pAhciPort->pDrvMount->pfnIsMounted(pAhciPort->pDrvMount)) 4385 4388 { 4386 atapiCmdErrorSimple(pAhciPort, pAhci PortTaskState, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);4389 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT); 4387 4390 break; 4388 4391 } … … 4400 4403 uLastLogTS = RTTimeMilliTS(); 4401 4404 } 4402 atapiCmdErrorSimple(pAhciPort, pAhci PortTaskState, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR);4405 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_LOGICAL_BLOCK_OOR); 4403 4406 break; 4404 4407 } 4405 atapiCmdOK(pAhciPort, pAhci PortTaskState);4406 pAhci PortTaskState->uATARegStatus |= ATA_STAT_SEEK; /* Linux expects this. */4408 atapiCmdOK(pAhciPort, pAhciReq); 4409 pAhciReq->uATARegStatus |= ATA_STAT_SEEK; /* Linux expects this. */ 4407 4410 } 4408 4411 break; … … 4439 4442 } 4440 4443 if (RT_SUCCESS(rc2)) 4441 atapiCmdOK(pAhciPort, pAhci PortTaskState);4444 atapiCmdOK(pAhciPort, pAhciReq); 4442 4445 else 4443 atapiCmdErrorSimple(pAhciPort, pAhci PortTaskState, 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); 4444 4447 } 4445 4448 break; … … 4447 4450 { 4448 4451 cbMax = ataBE2H_U16(pbPacket + 8); 4449 atapiDoTransfer(pAhciPort, pAhci PortTaskState, ATAFN_SS_ATAPI_MECHANISM_STATUS);4452 atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_MECHANISM_STATUS); 4450 4453 } 4451 4454 break; … … 4457 4460 { 4458 4461 pAhciPort->cNotifiedMediaChange-- ; 4459 atapiCmdErrorSimple(pAhciPort, pAhci PortTaskState, 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 */ 4460 4463 break; 4461 4464 } 4462 4465 else if (!pAhciPort->pDrvMount->pfnIsMounted(pAhciPort->pDrvMount)) 4463 4466 { 4464 atapiCmdErrorSimple(pAhciPort, pAhci PortTaskState, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);4467 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT); 4465 4468 break; 4466 4469 } … … 4473 4476 { 4474 4477 case 0: 4475 atapiDoTransfer(pAhciPort, pAhci PortTaskState, ATAFN_SS_ATAPI_READ_TOC_NORMAL);4478 atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_READ_TOC_NORMAL); 4476 4479 break; 4477 4480 case 1: 4478 atapiDoTransfer(pAhciPort, pAhci PortTaskState, ATAFN_SS_ATAPI_READ_TOC_MULTI);4481 atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_READ_TOC_MULTI); 4479 4482 break; 4480 4483 case 2: 4481 atapiDoTransfer(pAhciPort, pAhci PortTaskState, ATAFN_SS_ATAPI_READ_TOC_RAW);4484 atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_READ_TOC_RAW); 4482 4485 break; 4483 4486 default: 4484 4487 error_cmd: 4485 atapiCmdErrorSimple(pAhciPort, pAhci PortTaskState, 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); 4486 4489 break; 4487 4490 } … … 4492 4495 { 4493 4496 pAhciPort->cNotifiedMediaChange-- ; 4494 atapiCmdErrorSimple(pAhciPort, pAhci PortTaskState, 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 */ 4495 4498 break; 4496 4499 } 4497 4500 else if (!pAhciPort->pDrvMount->pfnIsMounted(pAhciPort->pDrvMount)) 4498 4501 { 4499 atapiCmdErrorSimple(pAhciPort, pAhci PortTaskState, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);4502 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT); 4500 4503 break; 4501 4504 } 4502 atapiDoTransfer(pAhciPort, pAhci PortTaskState, ATAFN_SS_ATAPI_READ_CAPACITY);4505 atapiDoTransfer(pAhciPort, pAhciReq, 8 /* cbMax */, ATAFN_SS_ATAPI_READ_CAPACITY); 4503 4506 break; 4504 4507 case SCSI_READ_DISC_INFORMATION: … … 4506 4509 { 4507 4510 pAhciPort->cNotifiedMediaChange-- ; 4508 atapiCmdErrorSimple(pAhciPort, pAhci PortTaskState, 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 */ 4509 4512 break; 4510 4513 } 4511 4514 else if (!pAhciPort->pDrvMount->pfnIsMounted(pAhciPort->pDrvMount)) 4512 4515 { 4513 atapiCmdErrorSimple(pAhciPort, pAhci PortTaskState, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);4516 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT); 4514 4517 break; 4515 4518 } 4516 4519 cbMax = ataBE2H_U16(pbPacket + 7); 4517 atapiDoTransfer(pAhciPort, pAhci PortTaskState, ATAFN_SS_ATAPI_READ_DISC_INFORMATION);4520 atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_READ_DISC_INFORMATION); 4518 4521 break; 4519 4522 case SCSI_READ_TRACK_INFORMATION: … … 4521 4524 { 4522 4525 pAhciPort->cNotifiedMediaChange-- ; 4523 atapiCmdErrorSimple(pAhciPort, pAhci PortTaskState, 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 */ 4524 4527 break; 4525 4528 } 4526 4529 else if (!pAhciPort->pDrvMount->pfnIsMounted(pAhciPort->pDrvMount)) 4527 4530 { 4528 atapiCmdErrorSimple(pAhciPort, pAhci PortTaskState, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT);4531 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT); 4529 4532 break; 4530 4533 } 4531 4534 cbMax = ataBE2H_U16(pbPacket + 7); 4532 atapiDoTransfer(pAhciPort, pAhci PortTaskState, ATAFN_SS_ATAPI_READ_TRACK_INFORMATION);4535 atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_READ_TRACK_INFORMATION); 4533 4536 break; 4534 4537 case SCSI_GET_CONFIGURATION: 4535 4538 /* No media change stuff here, it can confuse Linux guests. */ 4536 4539 cbMax = ataBE2H_U16(pbPacket + 7); 4537 atapiDoTransfer(pAhciPort, pAhci PortTaskState, ATAFN_SS_ATAPI_GET_CONFIGURATION);4540 atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_GET_CONFIGURATION); 4538 4541 break; 4539 4542 case SCSI_INQUIRY: 4540 4543 cbMax = pbPacket[4]; 4541 atapiDoTransfer(pAhciPort, pAhci PortTaskState, ATAFN_SS_ATAPI_INQUIRY);4544 atapiDoTransfer(pAhciPort, pAhciReq, cbMax, ATAFN_SS_ATAPI_INQUIRY); 4542 4545 break; 4543 4546 default: 4544 atapiCmdErrorSimple(pAhciPort, pAhci PortTaskState, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_ILLEGAL_OPCODE);4547 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_ILLEGAL_OPCODE); 4545 4548 break; 4546 4549 } … … 4552 4555 * Parse ATAPI commands, passing them directly to the CD/DVD drive. 4553 4556 */ 4554 static AHCITXDIR atapiParseCmdPassthrough(PAHCIPort pAhciPort, PAHCI PORTTASKSTATE pAhciPortTaskState)4557 static AHCITXDIR atapiParseCmdPassthrough(PAHCIPort pAhciPort, PAHCIREQ pAhciReq) 4555 4558 { 4556 4559 const uint8_t *pbPacket; … … 4559 4562 AHCITXDIR enmTxDir = AHCITXDIR_NONE; 4560 4563 4561 pbPacket = pAhci PortTaskState->aATAPICmd;4564 pbPacket = pAhciReq->aATAPICmd; 4562 4565 switch (pbPacket[0]) 4563 4566 { … … 4573 4576 goto sendcmd; 4574 4577 case SCSI_FORMAT_UNIT: 4575 cbTransfer = pAhci PortTaskState->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 */ 4576 4579 enmTxDir = AHCITXDIR_WRITE; 4577 4580 goto sendcmd; … … 4584 4587 if (ASMAtomicReadU32(&pAhciPort->MediaEventStatus) != ATA_EVENT_STATUS_UNCHANGED) 4585 4588 { 4586 pAhci PortTaskState->cbTransfer = RT_MIN(cbTransfer, 8);4587 atapiDoTransfer(pAhciPort, pAhci PortTaskState, 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); 4588 4591 break; 4589 4592 } … … 4591 4594 goto sendcmd; 4592 4595 case SCSI_GET_PERFORMANCE: 4593 cbTransfer = pAhci PortTaskState->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 */ 4594 4597 enmTxDir = AHCITXDIR_READ; 4595 4598 goto sendcmd; … … 4627 4630 cSectors = ataBE2H_U16(pbPacket + 7); 4628 4631 Log2(("ATAPI PT: lba %d sectors %d\n", iATAPILBA, cSectors)); 4629 pAhci PortTaskState->cbATAPISector = 2048; /**< @todo this size is not always correct */4630 cbTransfer = cSectors * pAhci PortTaskState->cbATAPISector;4632 pAhciReq->cbATAPISector = 2048; /**< @todo this size is not always correct */ 4633 cbTransfer = cSectors * pAhciReq->cbATAPISector; 4631 4634 enmTxDir = AHCITXDIR_READ; 4632 4635 goto sendcmd; … … 4635 4638 cSectors = ataBE2H_U32(pbPacket + 6); 4636 4639 Log2(("ATAPI PT: lba %d sectors %d\n", iATAPILBA, cSectors)); 4637 pAhci PortTaskState->cbATAPISector = 2048; /**< @todo this size is not always correct */4638 cbTransfer = cSectors * pAhci PortTaskState->cbATAPISector;4640 pAhciReq->cbATAPISector = 2048; /**< @todo this size is not always correct */ 4641 cbTransfer = cSectors * pAhciReq->cbATAPISector; 4639 4642 enmTxDir = AHCITXDIR_READ; 4640 4643 goto sendcmd; … … 4658 4661 case 0x0: /* All types. */ 4659 4662 if (ASMAtomicReadU32(&pAhciPort->MediaTrackType) == ATA_MEDIA_TYPE_CDDA) 4660 pAhci PortTaskState->cbATAPISector = 2352;4663 pAhciReq->cbATAPISector = 2352; 4661 4664 else 4662 pAhci PortTaskState->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. */ 4663 4666 break; 4664 4667 case 0x1: /* CD-DA */ 4665 pAhci PortTaskState->cbATAPISector = 2352;4668 pAhciReq->cbATAPISector = 2352; 4666 4669 break; 4667 4670 case 0x2: /* Mode 1 */ 4668 pAhci PortTaskState->cbATAPISector = 2048;4671 pAhciReq->cbATAPISector = 2048; 4669 4672 break; 4670 4673 case 0x3: /* Mode 2 formless */ 4671 pAhci PortTaskState->cbATAPISector = 2336;4674 pAhciReq->cbATAPISector = 2336; 4672 4675 break; 4673 4676 case 0x4: /* Mode 2 form 1 */ 4674 pAhci PortTaskState->cbATAPISector = 2048;4677 pAhciReq->cbATAPISector = 2048; 4675 4678 break; 4676 4679 case 0x5: /* Mode 2 form 2 */ 4677 pAhci PortTaskState->cbATAPISector = 2324;4680 pAhciReq->cbATAPISector = 2324; 4678 4681 break; 4679 4682 default: /* Reserved */ 4680 4683 AssertMsgFailed(("Unknown sector type\n")); 4681 pAhci PortTaskState->cbATAPISector = 0; /** @todo we should probably fail the command here already. */4684 pAhciReq->cbATAPISector = 0; /** @todo we should probably fail the command here already. */ 4682 4685 } 4683 4686 4684 cbTransfer = ataBE2H_U24(pbPacket + 6) * pAhci PortTaskState->cbATAPISector;4687 cbTransfer = ataBE2H_U24(pbPacket + 6) * pAhciReq->cbATAPISector; 4685 4688 enmTxDir = AHCITXDIR_READ; 4686 4689 goto sendcmd; … … 4690 4693 if (cSectors > 32) 4691 4694 cSectors = 32; /* Limit transfer size to 64~74K. Safety first. In any case this can only harm software doing CDDA extraction. */ 4692 pAhci PortTaskState->cbATAPISector = 2048; /**< @todo this size is not always correct */4693 cbTransfer = cSectors * pAhci PortTaskState->cbATAPISector;4695 pAhciReq->cbATAPISector = 2048; /**< @todo this size is not always correct */ 4696 cbTransfer = cSectors * pAhciReq->cbATAPISector; 4694 4697 enmTxDir = AHCITXDIR_READ; 4695 4698 goto sendcmd; … … 4728 4731 if ((pAhciPort->abATAPISense[2] & 0x0f) != SCSI_SENSE_NONE) 4729 4732 { 4730 pAhci PortTaskState->cbTransfer = cbTransfer;4731 pAhci PortTaskState->enmTxDir = AHCITXDIR_READ;4732 atapiDoTransfer(pAhciPort, pAhci PortTaskState, ATAFN_SS_ATAPI_REQUEST_SENSE);4733 pAhciReq->cbTransfer = cbTransfer; 4734 pAhciReq->enmTxDir = AHCITXDIR_READ; 4735 atapiDoTransfer(pAhciPort, pAhciReq, cbTransfer, ATAFN_SS_ATAPI_REQUEST_SENSE); 4733 4736 break; 4734 4737 } … … 4783 4786 cSectors = ataBE2H_U16(pbPacket + 7); 4784 4787 Log2(("ATAPI PT: lba %d sectors %d\n", iATAPILBA, cSectors)); 4785 pAhci PortTaskState->cbATAPISector = 2048; /**< @todo this size is not always correct */4786 cbTransfer = cSectors * pAhci PortTaskState->cbATAPISector;4788 pAhciReq->cbATAPISector = 2048; /**< @todo this size is not always correct */ 4789 cbTransfer = cSectors * pAhciReq->cbATAPISector; 4787 4790 enmTxDir = AHCITXDIR_WRITE; 4788 4791 goto sendcmd; … … 4791 4794 cSectors = ataBE2H_U32(pbPacket + 6); 4792 4795 Log2(("ATAPI PT: lba %d sectors %d\n", iATAPILBA, cSectors)); 4793 pAhci PortTaskState->cbATAPISector = 2048; /**< @todo this size is not always correct */4794 cbTransfer = cSectors * pAhci PortTaskState->cbATAPISector;4796 pAhciReq->cbATAPISector = 2048; /**< @todo this size is not always correct */ 4797 cbTransfer = cSectors * pAhciReq->cbATAPISector; 4795 4798 enmTxDir = AHCITXDIR_WRITE; 4796 4799 goto sendcmd; … … 4800 4803 Log2(("ATAPI PT: lba %d sectors %d\n", iATAPILBA, cSectors)); 4801 4804 /* The sector size is determined by the async I/O thread. */ 4802 pAhci PortTaskState->cbATAPISector = 0;4805 pAhciReq->cbATAPISector = 0; 4803 4806 /* Preliminary, will be corrected once the sector size is known. */ 4804 4807 cbTransfer = cSectors; … … 4815 4818 case 0x0f: /* activate deferred microcode */ 4816 4819 LogRel(("PIIX3 ATA: LUN#%d: CD-ROM passthrough command attempted to update firmware, blocked\n", pAhciPort->iLUN)); 4817 atapiCmdErrorSimple(pAhciPort, pAhci PortTaskState, 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); 4818 4821 break; 4819 4822 default: … … 4833 4836 * opcode 0x01" in syslog) and replies with a sense code of 0, 4834 4837 * which sends cdrecord to an endless loop. */ 4835 atapiCmdErrorSimple(pAhciPort, pAhci PortTaskState, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_ILLEGAL_OPCODE);4838 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_ILLEGAL_OPCODE); 4836 4839 break; 4837 4840 default: 4838 4841 LogRel(("AHCI: LUN#%d: passthrough unimplemented for command %#x\n", pAhciPort->iLUN, pbPacket[0])); 4839 atapiCmdErrorSimple(pAhciPort, pAhci PortTaskState, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_ILLEGAL_OPCODE);4842 atapiCmdErrorSimple(pAhciPort, pAhciReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_ILLEGAL_OPCODE); 4840 4843 break; 4841 4844 sendcmd: … … 4844 4847 if (cbTransfer == 0) 4845 4848 enmTxDir = AHCITXDIR_NONE; 4846 pAhci PortTaskState->enmTxDir = enmTxDir;4847 pAhci PortTaskState->cbTransfer = cbTransfer;4848 atapiDoTransfer(pAhciPort, pAhci PortTaskState, ATAFN_SS_ATAPI_PASSTHROUGH);4849 pAhciReq->enmTxDir = enmTxDir; 4850 pAhciReq->cbTransfer = cbTransfer; 4851 atapiDoTransfer(pAhciPort, pAhciReq, cbTransfer, ATAFN_SS_ATAPI_PASSTHROUGH); 4849 4852 } 4850 4853 … … 4852 4855 } 4853 4856 4854 static AHCITXDIR atapiParseCmd(PAHCIPort pAhciPort, PAHCI PORTTASKSTATE pAhciPortTaskState)4857 static AHCITXDIR atapiParseCmd(PAHCIPort pAhciPort, PAHCIREQ pAhciReq) 4855 4858 { 4856 4859 AHCITXDIR enmTxDir = AHCITXDIR_NONE; 4857 4860 const uint8_t *pbPacket; 4858 4861 4859 pbPacket = pAhci PortTaskState->aATAPICmd;4862 pbPacket = pAhciReq->aATAPICmd; 4860 4863 #ifdef DEBUG 4861 4864 Log(("%s: LUN#%d CMD=%#04x \"%s\"\n", __FUNCTION__, pAhciPort->iLUN, pbPacket[0], SCSICmdText(pbPacket[0]))); … … 4863 4866 Log(("%s: LUN#%d CMD=%#04x\n", __FUNCTION__, pAhciPort->iLUN, pbPacket[0])); 4864 4867 #endif /* !DEBUG */ 4865 Log2(("%s: limit=%#x packet: %.*Rhxs\n", __FUNCTION__, pAhci PortTaskState->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)); 4866 4869 4867 4870 if (pAhciPort->fATAPIPassthrough) 4868 enmTxDir = atapiParseCmdPassthrough(pAhciPort, pAhci PortTaskState);4871 enmTxDir = atapiParseCmdPassthrough(pAhciPort, pAhciReq); 4869 4872 else 4870 enmTxDir = atapiParseCmdVirtualATAPI(pAhciPort, pAhci PortTaskState);4873 enmTxDir = atapiParseCmdVirtualATAPI(pAhciPort, pAhciReq); 4871 4874 4872 4875 return enmTxDir; … … 4878 4881 * @returns nothing 4879 4882 * @param pAhciPort The port the device is attached to. 4880 * @param pAhci PortTaskStateThe state to get the tag number from.4881 */ 4882 static void ahciFinishStorageDeviceReset(PAHCIPort pAhciPort, PAHCI PORTTASKSTATE pAhciPortTaskState)4883 * @param pAhciReq The state to get the tag number from. 4884 */ 4885 static void ahciFinishStorageDeviceReset(PAHCIPort pAhciPort, PAHCIREQ pAhciReq) 4883 4886 { 4884 4887 int rc; … … 4895 4898 else 4896 4899 pAhciPort->regSIG = AHCI_PORT_SIG_DISK; 4897 ASMAtomicOrU32(&pAhciPort->u32TasksFinished, (1 << pAhci PortTaskState->uTag));4900 ASMAtomicOrU32(&pAhciPort->u32TasksFinished, (1 << pAhciReq->uTag)); 4898 4901 4899 4902 rc = ahciHbaSetInterrupt(pAhciPort->CTX_SUFF(pAhci), pAhciPort->iLUN, VERR_IGNORED); … … 4906 4909 * @returns nothing. 4907 4910 * @param pAhciPort The device to reset. 4908 * @param pAhci PortTaskStateThe task state.4909 */ 4910 static void ahciDeviceReset(PAHCIPort pAhciPort, PAHCI PORTTASKSTATE pAhciPortTaskState)4911 * @param pAhciReq The task state. 4912 */ 4913 static void ahciDeviceReset(PAHCIPort pAhciPort, PAHCIREQ pAhciReq) 4911 4914 { 4912 4915 ASMAtomicWriteBool(&pAhciPort->fResetDevice, true); … … 4918 4921 */ 4919 4922 Assert(ASMAtomicReadU32(&pAhciPort->cTasksActive) == 0); 4920 ahciFinishStorageDeviceReset(pAhciPort, pAhci PortTaskState);4923 ahciFinishStorageDeviceReset(pAhciPort, pAhciReq); 4921 4924 } 4922 4925 … … 4926 4929 * @returns Nothing 4927 4930 * @param pAhciPort The port of the SATA controller. 4928 * @param pAhci PortTaskStateThe state of the task.4931 * @param pAhciReq The state of the task. 4929 4932 * @param pCmdFis Pointer to the command FIS from the guest. 4930 4933 * @param fInterrupt If an interrupt should be send to the guest. 4931 4934 */ 4932 static void ahciSendD2HFis(PAHCIPort pAhciPort, PAHCI PORTTASKSTATE pAhciPortTaskState, uint8_t *pCmdFis, bool fInterrupt)4935 static void ahciSendD2HFis(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, uint8_t *pCmdFis, bool fInterrupt) 4933 4936 { 4934 4937 uint8_t d2hFis[20]; … … 4943 4946 d2hFis[AHCI_CMDFIS_TYPE] = AHCI_CMDFIS_TYPE_D2H; 4944 4947 d2hFis[AHCI_CMDFIS_BITS] = (fInterrupt ? AHCI_CMDFIS_I : 0); 4945 d2hFis[AHCI_CMDFIS_STS] = pAhci PortTaskState->uATARegStatus;4946 d2hFis[AHCI_CMDFIS_ERR] = pAhci PortTaskState->uATARegError;4948 d2hFis[AHCI_CMDFIS_STS] = pAhciReq->uATARegStatus; 4949 d2hFis[AHCI_CMDFIS_ERR] = pAhciReq->uATARegError; 4947 4950 d2hFis[AHCI_CMDFIS_SECTN] = pCmdFis[AHCI_CMDFIS_SECTN]; 4948 4951 d2hFis[AHCI_CMDFIS_CYLL] = pCmdFis[AHCI_CMDFIS_CYLL]; … … 4956 4959 4957 4960 /* Update registers. */ 4958 pAhciPort->regTFD = (pAhci PortTaskState->uATARegError << 8) | pAhciPortTaskState->uATARegStatus;4961 pAhciPort->regTFD = (pAhciReq->uATARegError << 8) | pAhciReq->uATARegStatus; 4959 4962 4960 4963 ahciPostFisIntoMemory(pAhciPort, AHCI_CMDFIS_TYPE_D2H, d2hFis); 4961 4964 4962 if (pAhci PortTaskState->uATARegStatus & ATA_STAT_ERR)4965 if (pAhciReq->uATARegStatus & ATA_STAT_ERR) 4963 4966 { 4964 4967 /* Error bit is set. */ … … 4979 4982 4980 4983 /* Mark command as completed. */ 4981 ASMAtomicOrU32(&pAhciPort->u32TasksFinished, (1 << pAhci PortTaskState->uTag));4984 ASMAtomicOrU32(&pAhciPort->u32TasksFinished, (1 << pAhciReq->uTag)); 4982 4985 } 4983 4986 … … 5003 5006 bool fAssertIntr = false; 5004 5007 PAHCI pAhci = pAhciPort->CTX_SUFF(pAhci); 5005 PAHCI PORTTASKSTATE pTaskErr = ASMAtomicReadPtrT(&pAhciPort->pTaskErr, PAHCIPORTTASKSTATE);5008 PAHCIREQ pTaskErr = ASMAtomicReadPtrT(&pAhciPort->pTaskErr, PAHCIREQ); 5006 5009 5007 5010 ahciLog(("%s: Building SDB FIS\n", __FUNCTION__)); … … 5136 5139 } 5137 5140 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. 5257 5143 * 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 */ 5150 static 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 */ 5203 static 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. 5370 5249 * 5371 5250 * @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 */ 5254 static 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 5274 static 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)) 5477 5291 { 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 5993 5307 5994 5308 /** … … 6002 5316 for (unsigned i = 0; i < RT_ELEMENTS(pAhciPort->aCachedTasks); i++) 6003 5317 { 6004 PAHCI PORTTASKSTATE pAhciPortTaskState= pAhciPort->aCachedTasks[i];6005 6006 if (VALID_PTR(pAhci PortTaskState))5318 PAHCIREQ pAhciReq = pAhciPort->aCachedTasks[i]; 5319 5320 if (VALID_PTR(pAhciReq)) 6007 5321 { 6008 5322 bool fXchg = false; 6009 ASMAtomicCmpXchgSize(&pAhci PortTaskState->enmTxState, AHCITXSTATE_CANCELED, AHCITXSTATE_ACTIVE, fXchg);5323 ASMAtomicCmpXchgSize(&pAhciReq->enmTxState, AHCITXSTATE_CANCELED, AHCITXSTATE_ACTIVE, fXchg); 6010 5324 6011 5325 if (fXchg) … … 6021 5335 ASMAtomicWriteNullPtr(&pAhciPort->aCachedTasks[i]); 6022 5336 LogRel(("AHCI#%dP%d: Cancelled task %u\n", pAhciPort->CTX_SUFF(pDevIns)->iInstance, 6023 pAhciPort->iLUN, pAhci PortTaskState->uTag));5337 pAhciPort->iLUN, pAhciReq->uTag)); 6024 5338 } 6025 5339 else 6026 AssertMsg(pAhci PortTaskState->enmTxState == AHCITXSTATE_FREE,5340 AssertMsg(pAhciReq->enmTxState == AHCITXSTATE_FREE, 6027 5341 ("Invalid task state, must be free!\n")); 6028 5342 } … … 6093 5407 * 6094 5408 * @returns VBox status code. 6095 * @param pAhciPort 6096 * @param pAhci portTaskState The task statehandling the TRIM request.6097 */ 6098 static int ahciTrimRangesCreate(PAHCIPort pAhciPort, PAHCI PORTTASKSTATE pAhciPortTaskState)6099 { 6100 RTSGBUF SgBuf;5409 * @param pAhciPort AHCI port state. 5410 * @param pAhciReq The request handling the TRIM request. 5411 */ 5412 static int ahciTrimRangesCreate(PAHCIPort pAhciPort, PAHCIREQ pAhciReq) 5413 { 5414 SGLEntry aPrdtlEntries[32]; 6101 5415 uint64_t aRanges[64]; 6102 5416 unsigned cRangesMax; 6103 5417 unsigned cRanges = 0; 5418 uint32_t cPrdtlEntries = pAhciReq->cPrdtlEntries; 5419 RTGCPHYS GCPhysPrdtl = pAhciReq->GCPhysPrdtl; 5420 PPDMDEVINS pDevIns = pAhciPort->CTX_SUFF(pDevIns); 6104 5421 int rc = VINF_SUCCESS; 6105 5422 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); 6110 5426 6111 5427 /* 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 } 6115 5438 6116 5439 do 6117 5440 { 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++) 6154 5458 { 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++; 6162 5462 else 6163 5463 break; 6164 5464 } 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; 6165 5520 } while (idxRange < cRanges); 6166 5521 } 6167 5522 else 5523 rc = VERR_NO_MEMORY; 5524 5525 LogFlowFunc(("returns rc=%Rrc\n", rc)); 6168 5526 return rc; 6169 5527 } … … 6173 5531 * 6174 5532 * @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 */ 5535 static void ahciTrimRangesDestroy(PAHCIREQ pAhciReq) 5536 { 5537 AssertReturnVoid(pAhciReq->enmTxDir == AHCITXDIR_TRIM); 5538 RTMemFree(pAhciReq->u.Trim.paRanges); 6180 5539 } 6181 5540 … … 6186 5545 * @returns VBox status code 6187 5546 * 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 */ 5552 static int ahciTransferComplete(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, int rcReq, bool fFreeReq) 6193 5553 { 6194 5554 bool fXchg = false; 6195 5555 bool fRedo = false; 6196 5556 6197 ASMAtomicCmpXchgSize(&pAhci PortTaskState->enmTxState, AHCITXSTATE_FREE, AHCITXSTATE_ACTIVE, fXchg);5557 ASMAtomicCmpXchgSize(&pAhciReq->enmTxState, AHCITXSTATE_FREE, AHCITXSTATE_ACTIVE, fXchg); 6198 5558 6199 5559 if (fXchg) 6200 5560 { 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); 6208 5565 pAhciPort->Led.Actual.s.fReading = 0; 6209 5566 } 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); 6213 5571 pAhciPort->Led.Actual.s.fWriting = 0; 6214 5572 } 6215 else if (pAhci PortTaskState->enmTxDir == AHCITXDIR_TRIM)6216 { 6217 ahciTrimRangesDestroy(pAhci PortTaskState);5573 else if (pAhciReq->enmTxDir == AHCITXDIR_TRIM) 5574 { 5575 ahciTrimRangesDestroy(pAhciReq); 6218 5576 pAhciPort->Led.Actual.s.fWriting = 0; 6219 5577 } … … 6224 5582 if (pAhciPort->cErrors++ < MAX_LOG_REL_ERRORS) 6225 5583 { 6226 if (pAhci PortTaskState->enmTxDir == AHCITXDIR_FLUSH)5584 if (pAhciReq->enmTxDir == AHCITXDIR_FLUSH) 6227 5585 LogRel(("AHCI#%u: Flush returned rc=%Rrc\n", 6228 5586 pAhciPort->iLUN, rcReq)); 6229 else if (pAhci PortTaskState->enmTxDir == AHCITXDIR_TRIM)5587 else if (pAhciReq->enmTxDir == AHCITXDIR_TRIM) 6230 5588 LogRel(("AHCI#%u: Trim returned rc=%Rrc\n", 6231 5589 pAhciPort->iLUN, rcReq)); … … 6233 5591 LogRel(("AHCI#%u: %s at offset %llu (%u bytes left) returned rc=%Rrc\n", 6234 5592 pAhciPort->iLUN, 6235 pAhci PortTaskState->enmTxDir == AHCITXDIR_READ5593 pAhciReq->enmTxDir == AHCITXDIR_READ 6236 5594 ? "Read" 6237 5595 : "Write", 6238 pAhci PortTaskState->uOffset,6239 pAhci PortTaskState->cbTransfer, rcReq));5596 pAhciReq->uOffset, 5597 pAhciReq->cbTransfer, rcReq)); 6240 5598 } 6241 5599 … … 6243 5601 if (!fRedo) 6244 5602 { 6245 pAhci PortTaskState->cmdHdr.u32PRDBC = 0;6246 pAhci PortTaskState->uATARegError= ID_ERR;6247 pAhci PortTaskState->uATARegStatus= ATA_STAT_READY | ATA_STAT_ERR;6248 ASMAtomicCmpXchgPtr(&pAhciPort->pTaskErr, pAhci PortTaskState, 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); 6249 5607 } 6250 5608 else 6251 ASMAtomicOrU32(&pAhciPort->u32TasksNew, (1 << pAhciPortTaskState->uTag));5609 ASMAtomicOrU32(&pAhciPort->u32TasksNew, RT_BIT_32(pAhciReq->uTag)); 6252 5610 } 6253 5611 else 6254 5612 { 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 } 6259 5621 6260 5622 /* 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 } 6263 5637 } 6264 5638 6265 5639 /* Add the task to the cache. */ 6266 ASMAtomicWritePtr(&pAhciPort->aCachedTasks[pAhci PortTaskState->uTag], pAhciPortTaskState);5640 ASMAtomicWritePtr(&pAhciPort->aCachedTasks[pAhciReq->uTag], pAhciReq); 6267 5641 ASMAtomicDecU32(&pAhciPort->cTasksActive); 6268 5642 6269 5643 if (!fRedo) 6270 5644 { 6271 if (pAhci PortTaskState->fQueued)5645 if (pAhciReq->fQueued) 6272 5646 { 6273 if (RT_SUCCESS(rcReq) && !ASMAtomicReadPtrT(&pAhciPort->pTaskErr, PAHCI PORTTASKSTATE))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)); 6275 5649 6276 5650 /* … … 6282 5656 } 6283 5657 else 6284 ahciSendD2HFis(pAhciPort, pAhci PortTaskState, pAhciPortTaskState->cmdFis, true);5658 ahciSendD2HFis(pAhciPort, pAhciReq, pAhciReq->cmdFis, true); 6285 5659 } 6286 5660 } … … 6291 5665 * The guest might use it for other things now because it doesn't know about that task anymore. 6292 5666 */ 6293 AssertMsg(pAhci PortTaskState->enmTxState == AHCITXSTATE_CANCELED,5667 AssertMsg(pAhciReq->enmTxState == AHCITXSTATE_CANCELED, 6294 5668 ("Task is not active but wasn't canceled!\n")); 6295 5669 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 */); 6297 5674 6298 5675 /* Leave a log message about the canceled request. */ 6299 5676 if (pAhciPort->cErrors++ < MAX_LOG_REL_ERRORS) 6300 5677 { 6301 if (pAhci PortTaskState->enmTxDir == AHCITXDIR_FLUSH)5678 if (pAhciReq->enmTxDir == AHCITXDIR_FLUSH) 6302 5679 LogRel(("AHCI#%u: Canceled flush returned rc=%Rrc\n", 6303 5680 pAhciPort->iLUN, rcReq)); … … 6305 5682 LogRel(("AHCI#%u: Canceled %s at offset %llu (%u bytes left) returned rc=%Rrc\n", 6306 5683 pAhciPort->iLUN, 6307 pAhci PortTaskState->enmTxDir == AHCITXDIR_READ5684 pAhciReq->enmTxDir == AHCITXDIR_READ 6308 5685 ? "read" 6309 5686 : "write", 6310 pAhci PortTaskState->uOffset,6311 pAhci PortTaskState->cbTransfer, rcReq));5687 pAhciReq->uOffset, 5688 pAhciReq->cbTransfer, rcReq)); 6312 5689 } 6313 5690 6314 5691 /* Finally free the task state structure because it is completely unused now. */ 6315 RTMemFree(pAhciPortTaskState); 5692 if (fFreeReq) 5693 RTMemFree(pAhciReq); 6316 5694 } 6317 5695 … … 6330 5708 { 6331 5709 PAHCIPort pAhciPort = PDMIBLOCKASYNCPORT_2_PAHCIPORT(pInterface); 6332 PAHCI PORTTASKSTATE pAhciPortTaskState = (PAHCIPORTTASKSTATE)pvUser;5710 PAHCIREQ pAhciReq = (PAHCIREQ)pvUser; 6333 5711 6334 5712 ahciLog(("%s: pInterface=%p pvUser=%p uTag=%u\n", 6335 __FUNCTION__, pInterface, pvUser, pAhci PortTaskState->uTag));6336 6337 int rc = ahciTransferComplete(pAhciPort, pAhci PortTaskState, rcReq);5713 __FUNCTION__, pInterface, pvUser, pAhciReq->uTag)); 5714 5715 int rc = ahciTransferComplete(pAhciPort, pAhciReq, rcReq, true); 6338 5716 6339 5717 if (pAhciPort->cTasksActive == 0 && pAhciPort->pAhciR3->fSignalIdle) … … 6348 5726 * @param pCmdHdr Pointer to the command header. 6349 5727 */ 6350 static AHCITXDIR ahciProcessCmd(PAHCIPort pAhciPort, PAHCI PORTTASKSTATE pAhciPortTaskState, uint8_t *pCmdFis)5728 static AHCITXDIR ahciProcessCmd(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, uint8_t *pCmdFis) 6351 5729 { 6352 5730 AHCITXDIR rc = AHCITXDIR_NONE; 6353 5731 bool fLBA48 = false; 6354 CmdHdr *pCmdHdr = &pAhci PortTaskState->cmdHdr;5732 CmdHdr *pCmdHdr = &pAhciReq->cmdHdr; 6355 5733 6356 5734 AssertMsg(pCmdFis[AHCI_CMDFIS_TYPE] == AHCI_CMDFIS_TYPE_H2D, ("FIS is not a host to device Fis!!\n")); 6357 5735 6358 pAhci PortTaskState->cbTransfer = 0;5736 pAhciReq->cbTransfer = 0; 6359 5737 6360 5738 switch (pCmdFis[AHCI_CMDFIS_CMD]) 6361 5739 { 6362 5740 case ATA_IDENTIFY_DEVICE: 5741 { 5742 if (pAhciPort->pDrvBlock && !pAhciPort->fATAPI) 6363 5743 { 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; 6397 5756 } 5757 else 5758 { 5759 pAhciReq->uATARegError = ABRT_ERR; 5760 pAhciReq->uATARegStatus = ATA_STAT_READY | ATA_STAT_SEEK | ATA_STAT_ERR; 5761 } 5762 break; 5763 } 6398 5764 case ATA_READ_NATIVE_MAX_ADDRESS_EXT: 6399 5765 case ATA_READ_NATIVE_MAX_ADDRESS: … … 6408 5774 case 0xcc: /* reverting to power-on defaults enable */ 6409 5775 case 0x66: /* reverting to power-on defaults disable */ 6410 pAhci PortTaskState->uATARegError = 0;6411 pAhci PortTaskState->uATARegStatus = ATA_STAT_READY | ATA_STAT_SEEK;5776 pAhciReq->uATARegError = 0; 5777 pAhciReq->uATARegStatus = ATA_STAT_READY | ATA_STAT_SEEK; 6412 5778 break; 6413 5779 case 0x82: /* write cache disable */ … … 6432 5798 } 6433 5799 default: 6434 pAhci PortTaskState->uATARegError = ABRT_ERR;6435 pAhci PortTaskState->uATARegStatus = ATA_STAT_READY | ATA_STAT_ERR;5800 pAhciReq->uATARegError = ABRT_ERR; 5801 pAhciReq->uATARegStatus = ATA_STAT_READY | ATA_STAT_ERR; 6436 5802 } 6437 5803 break; … … 6441 5807 if (!pAhciPort->fATAPI) 6442 5808 { 6443 pAhci PortTaskState->uATARegError = ABRT_ERR;6444 pAhci PortTaskState->uATARegStatus = ATA_STAT_READY | ATA_STAT_ERR;5809 pAhciReq->uATARegError = ABRT_ERR; 5810 pAhciReq->uATARegStatus = ATA_STAT_READY | ATA_STAT_ERR; 6445 5811 } 6446 5812 else 6447 5813 { 6448 5814 /* Reset the device. */ 6449 ahciDeviceReset(pAhciPort, pAhci PortTaskState);5815 ahciDeviceReset(pAhciPort, pAhciReq); 6450 5816 } 6451 5817 break; … … 6458 5824 if (!pAhciPort->fATAPI) 6459 5825 { 6460 pAhci PortTaskState->uATARegError = ABRT_ERR;6461 pAhci PortTaskState->uATARegStatus = ATA_STAT_READY | ATA_STAT_ERR;5826 pAhciReq->uATARegError = ABRT_ERR; 5827 pAhciReq->uATARegStatus = ATA_STAT_READY | ATA_STAT_ERR; 6462 5828 } 6463 5829 else 6464 rc = atapiParseCmd(pAhciPort, pAhci PortTaskState);5830 rc = atapiParseCmd(pAhciPort, pAhciReq); 6465 5831 break; 6466 5832 case ATA_IDENTIFY_PACKET_DEVICE: 6467 5833 if (!pAhciPort->fATAPI) 6468 5834 { 6469 pAhci PortTaskState->uATARegError = ABRT_ERR;6470 pAhci PortTaskState->uATARegStatus = ATA_STAT_READY | ATA_STAT_ERR;5835 pAhciReq->uATARegError = ABRT_ERR; 5836 pAhciReq->uATARegStatus = ATA_STAT_READY | ATA_STAT_ERR; 6471 5837 } 6472 5838 else 6473 5839 { 6474 atapiDoTransfer(pAhciPort, pAhci PortTaskState, ATAFN_SS_ATAPI_IDENTIFY);6475 6476 pAhci PortTaskState->uATARegError = 0;6477 pAhci PortTaskState->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; 6478 5844 } 6479 5845 break; … … 6483 5849 || (pCmdFis[AHCI_CMDFIS_SECTC] & (pCmdFis[AHCI_CMDFIS_SECTC] - 1)) != 0)) 6484 5850 { 6485 pAhci PortTaskState->uATARegError = ABRT_ERR;6486 pAhci PortTaskState->uATARegStatus = ATA_STAT_READY | ATA_STAT_ERR;5851 pAhciReq->uATARegError = ABRT_ERR; 5852 pAhciReq->uATARegStatus = ATA_STAT_READY | ATA_STAT_ERR; 6487 5853 } 6488 5854 else … … 6490 5856 Log2(("%s: set multi sector count to %d\n", __FUNCTION__, pCmdFis[AHCI_CMDFIS_SECTC])); 6491 5857 pAhciPort->cMultSectors = pCmdFis[AHCI_CMDFIS_SECTC]; 6492 pAhci PortTaskState->uATARegError = 0;6493 pAhci PortTaskState->uATARegStatus = ATA_STAT_READY | ATA_STAT_SEEK;5858 pAhciReq->uATARegError = 0; 5859 pAhciReq->uATARegStatus = ATA_STAT_READY | ATA_STAT_SEEK; 6494 5860 } 6495 5861 break; … … 6497 5863 break; /* Do nothing. */ 6498 5864 case ATA_CHECK_POWER_MODE: 6499 pAhci PortTaskState->cmdFis[AHCI_CMDFIS_SECTC] = 0xff; /* drive active or idle */5865 pAhciReq->cmdFis[AHCI_CMDFIS_SECTC] = 0xff; /* drive active or idle */ 6500 5866 /* fall through */ 6501 5867 case ATA_INITIALIZE_DEVICE_PARAMETERS: … … 6507 5873 case ATA_READ_VERIFY_SECTORS_WITHOUT_RETRIES: 6508 5874 case ATA_SLEEP: 6509 pAhci PortTaskState->uATARegError = 0;6510 pAhci PortTaskState->uATARegStatus = ATA_STAT_READY | ATA_STAT_SEEK;5875 pAhciReq->uATARegError = 0; 5876 pAhciReq->uATARegStatus = ATA_STAT_READY | ATA_STAT_SEEK; 6511 5877 break; 6512 5878 case ATA_READ_DMA_EXT: … … 6514 5880 case ATA_READ_DMA: 6515 5881 { 6516 pAhci PortTaskState->cbTransfer = ahciGetNSectors(pCmdFis, fLBA48) * 512;6517 pAhci PortTaskState->uOffset = ahciGetSector(pAhciPort, pCmdFis, fLBA48) * 512;5882 pAhciReq->cbTransfer = ahciGetNSectors(pCmdFis, fLBA48) * 512; 5883 pAhciReq->uOffset = ahciGetSector(pAhciPort, pCmdFis, fLBA48) * 512; 6518 5884 rc = AHCITXDIR_READ; 6519 5885 break; … … 6523 5889 case ATA_WRITE_DMA: 6524 5890 { 6525 pAhci PortTaskState->cbTransfer = ahciGetNSectors(pCmdFis, fLBA48) * 512;6526 pAhci PortTaskState->uOffset = ahciGetSector(pAhciPort, pCmdFis, fLBA48) * 512;5891 pAhciReq->cbTransfer = ahciGetNSectors(pCmdFis, fLBA48) * 512; 5892 pAhciReq->uOffset = ahciGetSector(pAhciPort, pCmdFis, fLBA48) * 512; 6527 5893 rc = AHCITXDIR_WRITE; 6528 5894 break; … … 6530 5896 case ATA_READ_FPDMA_QUEUED: 6531 5897 { 6532 pAhci PortTaskState->cbTransfer = ahciGetNSectorsQueued(pCmdFis) * 512;6533 pAhci PortTaskState->uOffset = ahciGetSectorQueued(pCmdFis) * 512;5898 pAhciReq->cbTransfer = ahciGetNSectorsQueued(pCmdFis) * 512; 5899 pAhciReq->uOffset = ahciGetSectorQueued(pCmdFis) * 512; 6534 5900 rc = AHCITXDIR_READ; 6535 5901 break; … … 6537 5903 case ATA_WRITE_FPDMA_QUEUED: 6538 5904 { 6539 pAhci PortTaskState->cbTransfer = ahciGetNSectorsQueued(pCmdFis) * 512;6540 pAhci PortTaskState->uOffset = ahciGetSectorQueued(pCmdFis) * 512;5905 pAhciReq->cbTransfer = ahciGetNSectorsQueued(pCmdFis) * 512; 5906 pAhciReq->uOffset = ahciGetSectorQueued(pCmdFis) * 512; 6541 5907 rc = AHCITXDIR_WRITE; 6542 5908 break; … … 6547 5913 unsigned offLogRead = ((pCmdFis[AHCI_CMDFIS_CYLLEXP] << 8) | pCmdFis[AHCI_CMDFIS_CYLL]) * 512; 6548 5914 unsigned iPage = pCmdFis[AHCI_CMDFIS_SECTN]; 5915 size_t cbCopied; 6549 5916 6550 5917 LogFlow(("Trying to read %zu bytes starting at offset %u from page %u\n", cbLogRead, offLogRead, iPage)); … … 6561 5928 { 6562 5929 LogFlow(("Reading error page\n")); 6563 PAHCI PORTTASKSTATE pTaskErr = ASMAtomicXchgPtrT(&pAhciPort->pTaskErr, NULL, PAHCIPORTTASKSTATE);5930 PAHCIREQ pTaskErr = ASMAtomicXchgPtrT(&pAhciPort->pTaskErr, NULL, PAHCIREQ); 6564 5931 if (pTaskErr) 6565 5932 { … … 6594 5961 } 6595 5962 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 6601 5963 /* 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; 6614 5968 } 6615 5969 … … 6618 5972 case ATA_DATA_SET_MANAGEMENT: 6619 5973 { 6620 if ( pAhciPort->pDrvBlock->pfnDiscard 5974 if ( ( !pAhciPort->fAsyncInterface 5975 && pAhciPort->pDrvBlock->pfnDiscard) 6621 5976 || ( pAhciPort->fAsyncInterface 6622 5977 && pAhciPort->pDrvBlockAsync->pfnStartDiscard)) 6623 5978 { 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; 6625 5988 break; 6626 5989 } … … 6632 5995 case ATA_NV_CACHE: 6633 5996 case ATA_IDLE: 6634 pAhci PortTaskState->uATARegError = ABRT_ERR;6635 pAhci PortTaskState->uATARegStatus = ATA_STAT_READY | ATA_STAT_ERR;5997 pAhciReq->uATARegError = ABRT_ERR; 5998 pAhciReq->uATARegStatus = ATA_STAT_READY | ATA_STAT_ERR; 6636 5999 break; 6637 6000 default: /* For debugging purposes. */ 6638 6001 AssertMsgFailed(("Unknown command issued\n")); 6639 pAhci PortTaskState->uATARegError = ABRT_ERR;6640 pAhci PortTaskState->uATARegStatus = ATA_STAT_READY | ATA_STAT_ERR;6002 pAhciReq->uATARegError = ABRT_ERR; 6003 pAhciReq->uATARegStatus = ATA_STAT_READY | ATA_STAT_ERR; 6641 6004 } 6642 6005 … … 6648 6011 * 6649 6012 * @returns nothing 6650 * @param pAhci PortTaskStateThe state of the actual task.6651 */ 6652 static void ahciPortTaskGetCommandFis(PAHCIPort pAhciPort, PAHCI PORTTASKSTATE pAhciPortTaskState)6013 * @param pAhciReq The state of the actual task. 6014 */ 6015 static void ahciPortTaskGetCommandFis(PAHCIPort pAhciPort, PAHCIREQ pAhciReq) 6653 6016 { 6654 6017 RTGCPHYS GCPhysAddrCmdTbl; … … 6661 6024 * We can process the Command FIS afterwards. 6662 6025 */ 6663 pAhci PortTaskState->GCPhysCmdHdrAddr = pAhciPort->GCPhysAddrClb + pAhciPortTaskState->uTag * sizeof(CmdHdr);6026 pAhciReq->GCPhysCmdHdrAddr = pAhciPort->GCPhysAddrClb + pAhciReq->uTag * sizeof(CmdHdr); 6664 6027 LogFlow(("%s: PDMDevHlpPhysRead GCPhysAddrCmdLst=%RGp cbCmdHdr=%u\n", __FUNCTION__, 6665 pAhci PortTaskState->GCPhysCmdHdrAddr, sizeof(CmdHdr)));6666 PDMDevHlpPhysRead(pAhciPort->CTX_SUFF(pDevIns), pAhci PortTaskState->GCPhysCmdHdrAddr, &pAhciPortTaskState->cmdHdr, sizeof(CmdHdr));6028 pAhciReq->GCPhysCmdHdrAddr, sizeof(CmdHdr))); 6029 PDMDevHlpPhysRead(pAhciPort->CTX_SUFF(pDevIns), pAhciReq->GCPhysCmdHdrAddr, &pAhciReq->cmdHdr, sizeof(CmdHdr)); 6667 6030 6668 6031 #ifdef DEBUG 6669 6032 /* Print some infos about the command header. */ 6670 ahciDumpCmdHdrInfo(pAhciPort, &pAhci PortTaskState->cmdHdr);6033 ahciDumpCmdHdrInfo(pAhciPort, &pAhciReq->cmdHdr); 6671 6034 #endif 6672 6035 6673 GCPhysAddrCmdTbl = AHCI_RTGCPHYS_FROM_U32(pAhci PortTaskState->cmdHdr.u32CmdTblAddrUp, pAhciPortTaskState->cmdHdr.u32CmdTblAddr);6674 6675 AssertMsg((pAhci PortTaskState->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, 6676 6039 ("This is not a command FIS!!\n")); 6677 6040 6678 6041 /* Read the command Fis. */ 6679 6042 LogFlow(("%s: PDMDevHlpPhysRead GCPhysAddrCmdTbl=%RGp cbCmdFis=%u\n", __FUNCTION__, GCPhysAddrCmdTbl, AHCI_CMDFIS_TYPE_H2D_SIZE)); 6680 PDMDevHlpPhysRead(pAhciPort->CTX_SUFF(pDevIns), GCPhysAddrCmdTbl, &pAhci PortTaskState->cmdFis[0], AHCI_CMDFIS_TYPE_H2D_SIZE);6043 PDMDevHlpPhysRead(pAhciPort->CTX_SUFF(pDevIns), GCPhysAddrCmdTbl, &pAhciReq->cmdFis[0], AHCI_CMDFIS_TYPE_H2D_SIZE); 6681 6044 6682 6045 /* Set transfer direction. */ 6683 pAhci PortTaskState->enmTxDir = (pAhciPortTaskState->cmdHdr.u32DescInf & AHCI_CMDHDR_W) ? AHCITXDIR_WRITE : AHCITXDIR_READ;6046 pAhciReq->enmTxDir = (pAhciReq->cmdHdr.u32DescInf & AHCI_CMDHDR_W) ? AHCITXDIR_WRITE : AHCITXDIR_READ; 6684 6047 6685 6048 /* If this is an ATAPI command read the atapi command. */ 6686 if (pAhci PortTaskState->cmdHdr.u32DescInf & AHCI_CMDHDR_A)6049 if (pAhciReq->cmdHdr.u32DescInf & AHCI_CMDHDR_A) 6687 6050 { 6688 6051 GCPhysAddrCmdTbl += AHCI_CMDHDR_ACMD_OFFSET; 6689 PDMDevHlpPhysRead(pAhciPort->CTX_SUFF(pDevIns), GCPhysAddrCmdTbl, &pAhci PortTaskState->aATAPICmd[0], ATAPI_PACKET_SIZE);6052 PDMDevHlpPhysRead(pAhciPort->CTX_SUFF(pDevIns), GCPhysAddrCmdTbl, &pAhciReq->aATAPICmd[0], ATAPI_PACKET_SIZE); 6690 6053 } 6691 6054 6692 6055 /* We "received" the FIS. Clear the BSY bit in regTFD. */ 6693 if ((pAhci PortTaskState->cmdHdr.u32DescInf & AHCI_CMDHDR_C) && (pAhciPortTaskState->fQueued))6056 if ((pAhciReq->cmdHdr.u32DescInf & AHCI_CMDHDR_C) && (pAhciReq->fQueued)) 6694 6057 { 6695 6058 /* … … 6697 6060 * but this FIS does not assert an interrupt 6698 6061 */ 6699 ahciSendD2HFis(pAhciPort, pAhci PortTaskState, pAhciPortTaskState->cmdFis, false);6062 ahciSendD2HFis(pAhciPort, pAhciReq, pAhciReq->cmdFis, false); 6700 6063 pAhciPort->regTFD &= ~AHCI_PORT_TFD_BSY; 6701 6064 } 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); 6702 6068 6703 6069 #ifdef DEBUG 6704 6070 /* Print some infos about the FIS. */ 6705 ahciDumpFisInfo(pAhciPort, &pAhci PortTaskState->cmdFis[0]);6071 ahciDumpFisInfo(pAhciPort, &pAhciReq->cmdFis[0]); 6706 6072 6707 6073 /* 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++) 6713 6078 { 6714 6079 SGLEntry SGEntry; 6715 6080 6716 ahciLog(("Entry %u at address %RGp\n", i, GCPhys AddrPRDTLEntryStart));6717 PDMDevHlpPhysRead(pAhciPort->CTX_SUFF(pDevIns), GCPhys AddrPRDTLEntryStart, &SGEntry, sizeof(SGLEntry));6081 ahciLog(("Entry %u at address %RGp\n", i, GCPhysPrdtl)); 6082 PDMDevHlpPhysRead(pAhciPort->CTX_SUFF(pDevIns), GCPhysPrdtl, &SGEntry, sizeof(SGLEntry)); 6718 6083 6719 6084 RTGCPHYS GCPhysDataAddr = AHCI_RTGCPHYS_FROM_U32(SGEntry.u32DBAUp, SGEntry.u32DBA); 6720 6085 ahciLog(("GCPhysAddr=%RGp Size=%u\n", GCPhysDataAddr, SGEntry.u32DescInf & SGLENTRY_DESCINF_DBC)); 6721 6086 6722 GCPhys AddrPRDTLEntryStart+= sizeof(SGLEntry);6087 GCPhysPrdtl += sizeof(SGLEntry); 6723 6088 } 6724 6089 #endif … … 6756 6121 while (idx) 6757 6122 { 6758 AHCITXDIR 6759 PAHCI PORTTASKSTATE pAhciPortTaskState;6123 AHCITXDIR enmTxDir; 6124 PAHCIREQ pAhciReq; 6760 6125 6761 6126 /* Decrement to get the slot number. */ … … 6769 6134 if (!pAhciPort->aCachedTasks[idx]) 6770 6135 { 6771 pAhci PortTaskState = (PAHCIPORTTASKSTATE)RTMemAllocZ(sizeof(AHCIPORTTASKSTATE));6772 AssertMsg(pAhci PortTaskState, ("%s: Cannot allocate task state memory!\n"));6773 pAhci PortTaskState->enmTxState = AHCITXSTATE_FREE;6136 pAhciReq = (PAHCIREQ)RTMemAllocZ(sizeof(AHCIREQ)); 6137 AssertMsg(pAhciReq, ("%s: Cannot allocate task state memory!\n")); 6138 pAhciReq->enmTxState = AHCITXSTATE_FREE; 6774 6139 } 6775 6140 else 6776 pAhci PortTaskState= pAhciPort->aCachedTasks[idx];6141 pAhciReq = pAhciPort->aCachedTasks[idx]; 6777 6142 6778 6143 bool fXchg; 6779 ASMAtomicCmpXchgSize(&pAhci PortTaskState->enmTxState, AHCITXSTATE_ACTIVE, AHCITXSTATE_FREE, fXchg);6144 ASMAtomicCmpXchgSize(&pAhciReq->enmTxState, AHCITXSTATE_ACTIVE, AHCITXSTATE_FREE, fXchg); 6780 6145 AssertMsg(fXchg, ("Task is already active\n")); 6781 6146 6782 pAhciPortTaskState->uATARegStatus = 0; 6783 pAhciPortTaskState->uATARegError = 0; 6147 pAhciReq->uATARegStatus = 0; 6148 pAhciReq->uATARegError = 0; 6149 pAhciReq->fFlags = 0; 6784 6150 6785 6151 /* Set current command slot */ 6786 pAhci PortTaskState->uTag = idx;6787 ASMAtomicWriteU32(&pAhciPort->u32CurrentCommandSlot, pAhci PortTaskState->uTag);6788 6789 ahciPortTaskGetCommandFis(pAhciPort, pAhci PortTaskState);6152 pAhciReq->uTag = idx; 6153 ASMAtomicWriteU32(&pAhciPort->u32CurrentCommandSlot, pAhciReq->uTag); 6154 6155 ahciPortTaskGetCommandFis(pAhciPort, pAhciReq); 6790 6156 6791 6157 /* 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. */ 6792 6158 if (pAhciPort->regSACT & (1 << idx)) 6793 6159 { 6794 pAhci PortTaskState->fQueued = true;6795 ASMAtomicOrU32(&pAhciPort->u32TasksFinished, (1 << pAhci PortTaskState->uTag));6160 pAhciReq->fQueued = true; 6161 ASMAtomicOrU32(&pAhciPort->u32TasksFinished, (1 << pAhciReq->uTag)); 6796 6162 } 6797 6163 else 6798 pAhci PortTaskState->fQueued = false;6799 6800 if (!(pAhci PortTaskState->cmdFis[AHCI_CMDFIS_BITS] & AHCI_CMDFIS_C))6164 pAhciReq->fQueued = false; 6165 6166 if (!(pAhciReq->cmdFis[AHCI_CMDFIS_BITS] & AHCI_CMDFIS_C)) 6801 6167 { 6802 6168 /* If the reset bit is set put the device into reset state. */ 6803 if (pAhci PortTaskState->cmdFis[AHCI_CMDFIS_CTL] & AHCI_CMDFIS_CTL_SRST)6169 if (pAhciReq->cmdFis[AHCI_CMDFIS_CTL] & AHCI_CMDFIS_CTL_SRST) 6804 6170 { 6805 6171 ahciLog(("%s: Setting device into reset state\n", __FUNCTION__)); 6806 6172 pAhciPort->fResetDevice = true; 6807 ahciSendD2HFis(pAhciPort, pAhci PortTaskState, pAhciPortTaskState->cmdFis, true);6808 pAhciPort->aCachedTasks[idx] = pAhci PortTaskState;6809 6810 ASMAtomicCmpXchgSize(&pAhci PortTaskState->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); 6811 6177 AssertMsg(fXchg, ("Task is not active\n")); 6812 6178 return true; … … 6814 6180 else if (pAhciPort->fResetDevice) /* The bit is not set and we are in a reset state. */ 6815 6181 { 6816 ahciFinishStorageDeviceReset(pAhciPort, pAhci PortTaskState);6817 pAhciPort->aCachedTasks[idx] = pAhci PortTaskState;6818 6819 ASMAtomicCmpXchgSize(&pAhci PortTaskState->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); 6820 6186 AssertMsg(fXchg, ("Task is not active\n")); 6821 6187 return true; … … 6826 6192 else 6827 6193 { 6828 enmTxDir = ahciProcessCmd(pAhciPort, pAhciPortTaskState, pAhciPortTaskState->cmdFis); 6194 ASMAtomicIncU32(&pAhciPort->cTasksActive); 6195 6196 enmTxDir = ahciProcessCmd(pAhciPort, pAhciReq, pAhciReq->cmdFis); 6197 pAhciReq->enmTxDir = enmTxDir; 6829 6198 6830 6199 if (enmTxDir != AHCITXDIR_NONE) 6831 6200 { 6832 pAhciPortTaskState->enmTxDir = enmTxDir; 6833 6834 ASMAtomicIncU32(&pAhciPort->cTasksActive); 6835 6836 if (enmTxDir != AHCITXDIR_FLUSH) 6201 if ( enmTxDir != AHCITXDIR_FLUSH 6202 && enmTxDir != AHCITXDIR_TRIM) 6837 6203 { 6838 bool fReadonly = true;6839 6204 STAM_REL_COUNTER_INC(&pAhciPort->StatDMA); 6840 6205 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); 6846 6207 if (RT_FAILURE(rc)) 6847 6208 AssertMsgFailed(("%s: Failed to process command %Rrc\n", __FUNCTION__, rc)); 6848 6209 } 6849 6210 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)) 6868 6212 { 6869 6213 if (enmTxDir == AHCITXDIR_FLUSH) 6870 6214 { 6871 6215 rc = pAhciPort->pDrvBlockAsync->pfnStartFlush(pAhciPort->pDrvBlockAsync, 6872 pAhci PortTaskState);6216 pAhciReq); 6873 6217 } 6874 6218 else if (enmTxDir == AHCITXDIR_TRIM) 6875 6219 { 6876 rc = ahciTrimRangesCreate(pAhciPort, pAhci PortTaskState);6220 rc = ahciTrimRangesCreate(pAhciPort, pAhciReq); 6877 6221 if (RT_SUCCESS(rc)) 6878 6222 { 6879 6223 pAhciPort->Led.Asserted.s.fWriting = pAhciPort->Led.Actual.s.fWriting = 1; 6880 rc = pAhciPort->pDrvBlockAsync->pfnStartDiscard(pAhciPort->pDrvBlockAsync, pAhci PortTaskState->paRanges,6881 pAhci PortTaskState->cRanges, pAhciPortTaskState);6224 rc = pAhciPort->pDrvBlockAsync->pfnStartDiscard(pAhciPort->pDrvBlockAsync, pAhciReq->u.Trim.paRanges, 6225 pAhciReq->u.Trim.cRanges, pAhciReq); 6882 6226 } 6883 6227 } … … 6885 6229 { 6886 6230 pAhciPort->Led.Asserted.s.fReading = pAhciPort->Led.Actual.s.fReading = 1; 6887 rc = pAhciPort->pDrvBlockAsync->pfnStartRead(pAhciPort->pDrvBlockAsync, pAhci PortTaskState->uOffset,6888 pAhciPortTaskState->pSGListHead, pAhciPortTaskState->cSGListUsed,6889 pAhci PortTaskState->cbTransfer,6890 pAhci PortTaskState);6231 rc = pAhciPort->pDrvBlockAsync->pfnStartRead(pAhciPort->pDrvBlockAsync, pAhciReq->uOffset, 6232 &pAhciReq->u.Io.DataSeg, 1, 6233 pAhciReq->cbTransfer, 6234 pAhciReq); 6891 6235 } 6892 6236 else 6893 6237 { 6894 6238 pAhciPort->Led.Asserted.s.fWriting = pAhciPort->Led.Actual.s.fWriting = 1; 6895 rc = pAhciPort->pDrvBlockAsync->pfnStartWrite(pAhciPort->pDrvBlockAsync, pAhci PortTaskState->uOffset,6896 pAhciPortTaskState->pSGListHead, pAhciPortTaskState->cSGListUsed,6897 pAhci PortTaskState->cbTransfer,6898 pAhci PortTaskState);6239 rc = pAhciPort->pDrvBlockAsync->pfnStartWrite(pAhciPort->pDrvBlockAsync, pAhciReq->uOffset, 6240 &pAhciReq->u.Io.DataSeg, 1, 6241 pAhciReq->cbTransfer, 6242 pAhciReq); 6899 6243 } 6900 6244 if (rc == VINF_VD_ASYNC_IO_FINISHED) 6901 rc = ahciTransferComplete(pAhciPort, pAhci PortTaskState, VINF_SUCCESS);6245 rc = ahciTransferComplete(pAhciPort, pAhciReq, VINF_SUCCESS, true); 6902 6246 else if (RT_FAILURE(rc) && rc != VERR_VD_ASYNC_IO_IN_PROGRESS) 6903 rc = ahciTransferComplete(pAhciPort, pAhci PortTaskState, rc);6247 rc = ahciTransferComplete(pAhciPort, pAhciReq, rc, true); 6904 6248 } 6905 6249 } 6906 6250 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); 6916 6252 } /* Command */ 6917 6253 6918 u32Tasks &= ~ (1 <<idx); /* Clear task bit. */6254 u32Tasks &= ~RT_BIT_32(idx); /* Clear task bit. */ 6919 6255 idx = ASMBitFirstSetU32(u32Tasks); 6920 6256 } /* while tasks available */ … … 6929 6265 PAHCIPort pAhciPort = (PAHCIPort)pThread->pvUser; 6930 6266 PAHCI pAhci = pAhciPort->CTX_SUFF(pAhci); 6931 PAHCI PORTTASKSTATE pAhciPortTaskState;6267 PAHCIREQ pAhciReq; 6932 6268 int rc = VINF_SUCCESS; 6933 6269 uint64_t u64StartTime = 0; … … 6944 6280 6945 6281 /* We use only one task structure. */ 6946 pAhci PortTaskState = (PAHCIPORTTASKSTATE)RTMemAllocZ(sizeof(AHCIPORTTASKSTATE));6947 if (!pAhci PortTaskState)6282 pAhciReq = (PAHCIREQ)RTMemAllocZ(sizeof(AHCIREQ)); 6283 if (!pAhciReq) 6948 6284 { 6949 6285 AssertMsgFailed(("Failed to allocate task state memory\n")); 6950 6286 return VERR_NO_MEMORY; 6951 6287 } 6288 6289 pAhciReq->enmTxState = AHCITXSTATE_FREE; 6952 6290 6953 6291 while (pThread->enmState == PDMTHREADSTATE_RUNNING) … … 6992 6330 STAM_PROFILE_START(&pAhciPort->StatProfileProcessTime, a); 6993 6331 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")); 6998 6341 6999 6342 /* Set current command slot */ 7000 ASMAtomicWriteU32(&pAhciPort->u32CurrentCommandSlot, pAhci PortTaskState->uTag);6343 ASMAtomicWriteU32(&pAhciPort->u32CurrentCommandSlot, pAhciReq->uTag); 7001 6344 7002 6345 /* 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. */ 7003 6346 if (pAhciPort->regSACT & (1 << idx)) 7004 6347 { 7005 pAhci PortTaskState->fQueued = true;7006 ASMAtomicOrU32(&pAhciPort->u32TasksFinished, (1 << pAhci PortTaskState->uTag));6348 pAhciReq->fQueued = true; 6349 ASMAtomicOrU32(&pAhciPort->u32TasksFinished, (1 << pAhciReq->uTag)); 7007 6350 } 7008 6351 else 7009 pAhci PortTaskState->fQueued = false;7010 7011 ahciPortTaskGetCommandFis(pAhciPort, pAhci PortTaskState);7012 7013 ahciLog(("%s: Got command at slot %d\n", __FUNCTION__, pAhci PortTaskState->uTag));7014 7015 if (!(pAhci PortTaskState->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)) 7016 6359 { 7017 6360 /* If the reset bit is set put the device into reset state. */ 7018 if (pAhci PortTaskState->cmdFis[AHCI_CMDFIS_CTL] & AHCI_CMDFIS_CTL_SRST)6361 if (pAhciReq->cmdFis[AHCI_CMDFIS_CTL] & AHCI_CMDFIS_CTL_SRST) 7019 6362 { 7020 6363 ahciLog(("%s: Setting device into reset state\n", __FUNCTION__)); 7021 6364 pAhciPort->fResetDevice = true; 7022 ahciSendD2HFis(pAhciPort, pAhci PortTaskState, &pAhciPortTaskState->cmdFis[0], true);6365 ahciSendD2HFis(pAhciPort, pAhciReq, &pAhciReq->cmdFis[0], true); 7023 6366 } 7024 6367 else if (pAhciPort->fResetDevice) /* The bit is not set and we are in a reset state. */ 7025 6368 { 7026 ahciFinishStorageDeviceReset(pAhciPort, pAhci PortTaskState);6369 ahciFinishStorageDeviceReset(pAhciPort, pAhciReq); 7027 6370 } 7028 6371 /* 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")); 7029 6375 } 7030 6376 else 7031 6377 { 7032 enmTxDir = ahciProcessCmd(pAhciPort, pAhciPortTaskState, &pAhciPortTaskState->cmdFis[0]); 6378 ASMAtomicIncU32(&pAhciPort->cTasksActive); 6379 enmTxDir = ahciProcessCmd(pAhciPort, pAhciReq, &pAhciReq->cmdFis[0]); 6380 pAhciReq->enmTxDir = enmTxDir; 7033 6381 7034 6382 if (enmTxDir == AHCITXDIR_FLUSH) 7035 {7036 6383 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 else7054 {7055 /* Add the task to the mask again. */7056 ASMAtomicOrU32(&pAhciPort->u32TasksNew, (1 << pAhciPortTaskState->uTag));7057 }7058 }7059 else7060 {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 else7070 {7071 /* Task is not queued send D2H FIS */7072 ahciSendD2HFis(pAhciPort, pAhciPortTaskState, &pAhciPortTaskState->cmdFis[0], true);7073 }7074 }7075 }7076 6384 else if (enmTxDir == AHCITXDIR_TRIM) 7077 6385 { 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); 7083 6387 if (RT_SUCCESS(rc)) 7084 6388 { 7085 6389 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); 7087 6393 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 else7113 {7114 /* Add the task to the mask again. */7115 ASMAtomicOrU32(&pAhciPort->u32TasksNew, (1 << pAhciPortTaskState->uTag));7116 }7117 }7118 else7119 {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 else7129 {7130 /* Task is not queued send D2H FIS */7131 ahciSendD2HFis(pAhciPort, pAhciPortTaskState, &pAhciPortTaskState->cmdFis[0], true);7132 }7133 6394 } 7134 6395 } … … 7137 6398 uint64_t uOffset = 0; 7138 6399 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); 7143 6402 if (RT_FAILURE(rc)) 7144 6403 AssertMsgFailed(("%s: Failed to get number of list elments %Rrc\n", __FUNCTION__, rc)); 7145 6404 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)) 7161 6406 { 7162 6407 STAM_REL_COUNTER_INC(&pAhciPort->StatDMA); 7163 6408 7164 6409 /* 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; 7169 6412 7170 6413 STAM_PROFILE_START(&pAhciPort->StatProfileReadWrite, b); 7171 6414 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) 7173 6419 { 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); 7208 6426 } 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 } 7209 6436 7210 6437 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_READ7219 ? "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 else7240 {7241 /* Add the task to the mask again. */7242 ASMAtomicOrU32(&pAhciPort->u32TasksNew, (1 << pAhciPortTaskState->uTag));7243 }7244 }7245 else7246 {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 else7260 {7261 /* Task is not queued send D2H FIS */7262 ahciSendD2HFis(pAhciPort, pAhciPortTaskState, &pAhciPortTaskState->cmdFis[0], true);7263 }7264 7265 uIORequestsProcessed++;7266 }7267 }7268 6438 } 7269 6439 } 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++; 7276 6443 STAM_PROFILE_STOP(&pAhciPort->StatProfileProcessTime, a); 7277 6444 } … … 7281 6448 #ifdef DEBUG 7282 6449 /* Be paranoid. */ 7283 memset(&pAhci PortTaskState->cmdHdr, 0, sizeof(CmdHdr));7284 memset(&pAhci PortTaskState->cmdFis, 0, AHCI_CMDFIS_TYPE_H2D_SIZE);7285 pAhci PortTaskState->GCPhysCmdHdrAddr = 0;7286 pAhci PortTaskState->uOffset = 0;7287 pAhci PortTaskState->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; 7288 6455 #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) != 07294 && RT_LIKELY(!pAhciPort->fPortReset))7295 ahciSendSDBFis(pAhciPort, 0, true);7296 }7297 6456 } 7298 6457 fTasksToProcess &= ~(1 << idx); 7299 6458 idx = ASMBitFirstSetU32(fTasksToProcess); 7300 6459 } /* while tasks to process */ 7301 7302 if ( ASMAtomicReadU32(&pAhciPort->u32QueuedTasksFinished) != 07303 && RT_LIKELY(!pAhciPort->fPortReset)7304 && RT_LIKELY(!pAhciPort->fRedo))7305 ahciSendSDBFis(pAhciPort, 0, true);7306 6460 7307 6461 u64StopTime = RTTimeMilliTS(); … … 7322 6476 PDMDevHlpAsyncNotificationCompleted(pAhciPort->pDevInsR3); 7323 6477 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)); 7332 6480 7333 6481 ahciLog(("%s: Port %d async IO thread exiting\n", __FUNCTION__, pAhciPort->iLUN)); … … 7852 7000 { 7853 7001 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 7860 7002 RTMemFree(pAhciPort->aCachedTasks[i]); 7861 }7862 7003 } 7863 7004 }
Note:
See TracChangeset
for help on using the changeset viewer.