Changeset 63999 in vbox for trunk/src/VBox/Devices
- Timestamp:
- Sep 26, 2016 11:33:48 AM (8 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Storage/DevAHCI.cpp
r63909 r63999 29 29 * the hard disk and for guests which don't have an AHCI SATA driver. 30 30 * 31 * The data is transfer red in an asynchronous way using one thread per implemented32 * port or using the new async completion interface which is still under33 * development. [not quite up to date]31 * The data is transfered using the extended media interface, asynchronously if 32 * it is supported by the driver below otherwise it weill be done synchronous. 33 * Either way a thread is used to process new requests from the guest. 34 34 */ 35 35 … … 245 245 246 246 /** 247 * Transfer type.248 */249 typedef enum AHCITXDIR250 {251 /** Invalid */252 AHCITXDIR_INVALID = 0,253 /** None */254 AHCITXDIR_NONE,255 /** Read */256 AHCITXDIR_READ,257 /** Write */258 AHCITXDIR_WRITE,259 /** Flush */260 AHCITXDIR_FLUSH,261 /** Trim */262 AHCITXDIR_TRIM263 } AHCITXDIR;264 265 /**266 247 * Task state. 267 248 */ … … 298 279 typedef struct AHCIREQ 299 280 { 300 /** List node for the free list if the request is not in use. */301 RTLISTNODE NodeList;281 /** The I/O request handle from the driver below associated with this request. */ 282 PDMMEDIAEXIOREQ hIoReq; 302 283 /** Task state. */ 303 284 volatile AHCITXSTATE enmTxState; … … 306 287 /** Tag of the task. */ 307 288 uint32_t uTag; 308 /** The command header for this task. */309 CmdHdr cmdHdr;310 289 /** The command Fis for this task. */ 311 290 uint8_t cmdFis[AHCI_CMDFIS_TYPE_H2D_SIZE]; … … 321 300 unsigned cPrdtlEntries; 322 301 /** Data direction. */ 323 AHCITXDIR enmTxDir;302 PDMMEDIAEXIOREQTYPE enmType; 324 303 /** Start offset. */ 325 304 uint64_t uOffset; … … 450 429 /** Flag whether this port is in a reset state. */ 451 430 volatile bool fPortReset; 452 /** If we use the new async interface. */453 bool f AsyncInterface;431 /** Flag whether TRIM is supported. */ 432 bool fTrimEnabled; 454 433 /** Flag if we are in a device reset. */ 455 434 bool fResetDevice; … … 507 486 /** Pointer to the attached driver's block interface. */ 508 487 R3PTRTYPE(PPDMIMEDIA) pDrvMedia; 509 /** Pointer to the attached driver's async blockinterface. */510 R3PTRTYPE(PPDMIMEDIA ASYNC) pDrvMediaAsync;488 /** Pointer to the attached driver's extended interface. */ 489 R3PTRTYPE(PPDMIMEDIAEX) pDrvMediaEx; 511 490 /** Pointer to the attached driver's mount interface. */ 512 491 R3PTRTYPE(PPDMIMOUNT) pDrvMount; … … 515 494 /** The block port interface. */ 516 495 PDMIMEDIAPORT IPort; 517 /** The optional block asyncport interface. */518 PDMIMEDIA ASYNCPORT IPortAsync;496 /** The extended media port interface. */ 497 PDMIMEDIAEXPORT IMediaExPort; 519 498 /** The mount notify interface. */ 520 499 PDMIMOUNTNOTIFY IMountNotify; … … 530 509 /** Async IO Thread. */ 531 510 R3PTRTYPE(PPDMTHREAD) pAsyncIOThread; 532 /** Array of active tasks indexed by the tag. */533 R3PTRTYPE(volatile PAHCIREQ) aActiveTasks[AHCI_NR_COMMAND_SLOTS];534 511 /** First task throwing an error. */ 535 512 R3PTRTYPE(volatile PAHCIREQ) pTaskErr; … … 572 549 uint32_t u32Alignment5; 573 550 574 /** Critical section protecting the global free list. */575 RTCRITSECT CritSectReqsFree;576 /** Head of the global free request list. */577 R3PTRTYPE(PRTLISTANCHOR) pListReqsFree;578 579 551 /** Align to a multiple of 8. */ 580 552 #if HC_ARCH_BITS == 32 … … 706 678 /** R0 enabled. */ 707 679 bool fR0Enabled; 708 /** If the new async interface is used if available. */709 bool fUseAsyncInterfaceIfAvailable;710 680 /** Indicates that PDMDevHlpAsyncNotificationCompleted should be called when 711 681 * a port is entering the idle state. */ … … 960 930 static uint32_t ahciCopyToPrdtl(PPDMDEVINS pDevIns, PAHCIREQ pAhciReq, const void *pvBuf, size_t cbBuf); 961 931 static size_t ahciCopyFromPrdtl(PPDMDEVINS pDevIns, PAHCIREQ pAhciReq, void *pvBuf, size_t cbBuf); 962 static bool ahciCancelActiveTasks(PAHCIPort pAhciPort , PAHCIREQ pAhciReqExcept);932 static bool ahciCancelActiveTasks(PAHCIPort pAhciPort); 963 933 static void ahciReqMemFree(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, bool fForceFree); 964 static void ahciR3PortCachedReqsFree(PAHCIPort pAhciPort);965 934 #endif 966 935 RT_C_DECLS_END … … 1090 1059 { 1091 1060 /* Cancel all tasks first. */ 1092 bool fAllTasksCanceled = ahciCancelActiveTasks(pAhciPort , NULL);1061 bool fAllTasksCanceled = ahciCancelActiveTasks(pAhciPort); 1093 1062 Assert(fAllTasksCanceled); NOREF(fAllTasksCanceled); 1094 1063 … … 2062 2031 2063 2032 /* Cancel all tasks first. */ 2064 fAllTasksCanceled = ahciCancelActiveTasks(pAhciPort , NULL);2033 fAllTasksCanceled = ahciCancelActiveTasks(pAhciPort); 2065 2034 Assert(fAllTasksCanceled); 2066 2035 … … 2717 2686 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pAhciPort->IBase); 2718 2687 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAPORT, &pAhciPort->IPort); 2719 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIA ASYNCPORT, &pAhciPort->IPortAsync);2688 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAEXPORT, &pAhciPort->IMediaExPort); 2720 2689 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMOUNTNOTIFY, &pAhciPort->IMountNotify); 2721 2690 return NULL; … … 3026 2995 pAhciReq->uATARegStatus = ATA_STAT_READY | ATA_STAT_SEEK; 3027 2996 pAhciReq->cmdFis[AHCI_CMDFIS_SECTN] = (pAhciReq->cmdFis[AHCI_CMDFIS_SECTN] & ~7) 3028 | ((pAhciReq->enmT xDir != AHCITXDIR_WRITE) ? ATAPI_INT_REASON_IO : 0)2997 | ((pAhciReq->enmType != PDMMEDIAEXIOREQTYPE_WRITE) ? ATAPI_INT_REASON_IO : 0) 3029 2998 | (!pAhciReq->cbTransfer ? ATAPI_INT_REASON_CD : 0); 3030 2999 memset(pAhciPort->abATAPISense, '\0', sizeof(pAhciPort->abATAPISense)); … … 3142 3111 p[67] = RT_H2LE_U16(120); /* minimum PIO cycle time without flow control */ 3143 3112 p[68] = RT_H2LE_U16(120); /* minimum PIO cycle time with IORDY flow control */ 3144 if ( pAhciPort->pDrvMedia->pfnDiscard 3145 || ( pAhciPort->fAsyncInterface 3146 && pAhciPort->pDrvMediaAsync->pfnStartDiscard) 3113 if ( pAhciPort->fTrimEnabled 3147 3114 || pAhciPort->cbSector != 512 3148 3115 || pAhciPort->fNonRotational) … … 3185 3152 p[217] = RT_H2LE_U16(1); /* Non-rotational medium */ 3186 3153 3187 if ( pAhciPort->pDrvMedia->pfnDiscard 3188 || ( pAhciPort->fAsyncInterface 3189 && pAhciPort->pDrvMediaAsync->pfnStartDiscard)) /** @todo Set bit 14 in word 69 too? (Deterministic read after TRIM). */ 3154 if (pAhciPort->fTrimEnabled) /** @todo Set bit 14 in word 69 too? (Deterministic read after TRIM). */ 3190 3155 p[169] = RT_H2LE_U16(1); /* DATA SET MANAGEMENT command supported. */ 3191 3156 … … 3573 3538 uint8_t abBuf[8]; 3574 3539 3575 Assert(pAhciReq->enmT xDir == AHCITXDIR_READ);3540 Assert(pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_READ); 3576 3541 Assert(pAhciReq->cbTransfer <= 8); 3577 3542 … … 3985 3950 return VERR_NO_MEMORY; 3986 3951 3987 if (pAhciReq->enmT xDir == AHCITXDIR_WRITE)3952 if (pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_WRITE) 3988 3953 { 3989 3954 ahciCopyFromPrdtl(pAhciPort->pDevInsR3, pAhciReq, pvBuf, cbTransfer); … … 3997 3962 if (cbTransfer >= 2048) 3998 3963 { 3999 if (pAhciReq->enmT xDir != AHCITXDIR_WRITE)3964 if (pAhciReq->enmType != PDMMEDIAEXIOREQTYPE_WRITE) 4000 3965 pAhciPort->Led.Asserted.s.fReading = pAhciPort->Led.Actual.s.fReading = 1; 4001 3966 else … … 4074 4039 rc = pAhciPort->pDrvMedia->pfnSendCmd(pAhciPort->pDrvMedia, 4075 4040 aATAPICmd, 4076 pAhciReq->enmT xDir == AHCITXDIR_READ4041 pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_READ 4077 4042 ? PDMMEDIATXDIR_FROM_DEVICE 4078 4043 : PDMMEDIATXDIR_TO_DEVICE, … … 4092 4057 PDMMEDIATXDIR enmBlockTxDir = PDMMEDIATXDIR_NONE; 4093 4058 4094 if (pAhciReq->enmT xDir == AHCITXDIR_READ)4059 if (pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_READ) 4095 4060 enmBlockTxDir = PDMMEDIATXDIR_FROM_DEVICE; 4096 else if (pAhciReq->enmT xDir == AHCITXDIR_WRITE)4061 else if (pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_WRITE) 4097 4062 enmBlockTxDir = PDMMEDIATXDIR_TO_DEVICE; 4098 else if (pAhciReq->enmT xDir == AHCITXDIR_NONE)4063 else if (pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_INVALID) 4099 4064 enmBlockTxDir = PDMMEDIATXDIR_NONE; 4100 4065 else 4101 AssertMsgFailed(("Invalid transfer direction %d\n", pAhciReq->enmT xDir));4066 AssertMsgFailed(("Invalid transfer direction %d\n", pAhciReq->enmType)); 4102 4067 4103 4068 rc = pAhciPort->pDrvMedia->pfnSendCmd(pAhciPort->pDrvMedia, … … 4114 4079 if (cbTransfer >= 2048) 4115 4080 { 4116 if (pAhciReq->enmT xDir != AHCITXDIR_WRITE)4081 if (pAhciReq->enmType != PDMMEDIAEXIOREQTYPE_WRITE) 4117 4082 { 4118 4083 pAhciPort->Led.Actual.s.fReading = 0; … … 4154 4119 } 4155 4120 4156 if (pAhciReq->enmT xDir == AHCITXDIR_READ)4121 if (pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_READ) 4157 4122 { 4158 4123 Assert(cbTransfer <= pAhciReq->cbTransfer); … … 4378 4343 int rcSourceSink = g_apfnAtapiFuncs[iSourceSink](pAhciReq, pAhciPort, cbMax, &cbTransfered); 4379 4344 4380 pAhciReq->cmdHdr.u32PRDBC = (uint32_t)cbTransfered;4381 4345 pAhciReq->cbTransfer = (uint32_t)cbTransfered; 4382 4346 Assert(pAhciReq->cbTransfer == cbTransfered); … … 4385 4349 4386 4350 /* Write updated command header into memory of the guest. */ 4387 PDMDevHlpPCIPhysWrite(pAhciPort->CTX_SUFF(pDevIns), pAhciReq->GCPhysCmdHdrAddr, &pAhciReq->cmdHdr, sizeof(CmdHdr)); 4351 uint32_t u32PRDBC = (uint32_t)cbTransfered; 4352 PDMDevHlpPCIPhysWrite(pAhciPort->CTX_SUFF(pDevIns), pAhciReq->GCPhysCmdHdrAddr + RT_OFFSETOF(CmdHdr, u32PRDBC), 4353 &u32PRDBC, sizeof(u32PRDBC)); 4388 4354 4389 4355 return rcSourceSink; … … 4456 4422 } 4457 4423 4458 static AHCITXDIRatapiParseCmdVirtualATAPI(PAHCIPort pAhciPort, PAHCIREQ pAhciReq)4459 { 4460 AHCITXDIR enmTxDir = AHCITXDIR_NONE;4424 static PDMMEDIAEXIOREQTYPE atapiParseCmdVirtualATAPI(PAHCIPort pAhciPort, PAHCIREQ pAhciReq) 4425 { 4426 PDMMEDIAEXIOREQTYPE enmType = PDMMEDIAEXIOREQTYPE_INVALID; 4461 4427 const uint8_t *pbPacket; 4462 4428 uint32_t cbMax; … … 4576 4542 } 4577 4543 atapiReadSectors(pAhciPort, pAhciReq, iATAPILBA, cSectors, 2048); 4578 enmT xDir = AHCITXDIR_READ;4544 enmType = PDMMEDIAEXIOREQTYPE_READ; 4579 4545 break; 4580 4546 } … … 4625 4591 /* normal read */ 4626 4592 atapiReadSectors(pAhciPort, pAhciReq, iATAPILBA, cSectors, 2048); 4627 enmT xDir = AHCITXDIR_READ;4593 enmType = PDMMEDIAEXIOREQTYPE_READ; 4628 4594 break; 4629 4595 case 0xf8: 4630 4596 /* read all data */ 4631 4597 atapiReadSectors(pAhciPort, pAhciReq, iATAPILBA, cSectors, 2352); 4632 enmT xDir = AHCITXDIR_READ;4598 enmType = PDMMEDIAEXIOREQTYPE_READ; 4633 4599 break; 4634 4600 default: … … 4686 4652 PAHCI pAhci = pAhciPort->CTX_SUFF(pAhci); 4687 4653 PPDMDEVINS pDevIns = pAhci->CTX_SUFF(pDevIns); 4688 4689 /*4690 * Free the I/O memory of all cached tasks of this port4691 * because the driver providing I/O memory allocation interface4692 * is about to be destroyed.4693 */4694 ahciR3PortCachedReqsFree(pAhciPort);4695 4654 4696 4655 /* … … 4828 4787 } 4829 4788 4830 return enmT xDir;4789 return enmType; 4831 4790 } 4832 4791 … … 4834 4793 * Parse ATAPI commands, passing them directly to the CD/DVD drive. 4835 4794 */ 4836 static AHCITXDIRatapiParseCmdPassthrough(PAHCIPort pAhciPort, PAHCIREQ pAhciReq)4795 static PDMMEDIAEXIOREQTYPE atapiParseCmdPassthrough(PAHCIPort pAhciPort, PAHCIREQ pAhciReq) 4837 4796 { 4838 4797 const uint8_t *pbPacket; 4839 4798 uint32_t cSectors, iATAPILBA; 4840 4799 uint32_t cbTransfer = 0; 4841 AHCITXDIR enmTxDir = AHCITXDIR_NONE;4800 PDMMEDIAEXIOREQTYPE enmType = PDMMEDIAEXIOREQTYPE_INVALID; 4842 4801 bool fSendCmd = false; 4843 4802 … … 4855 4814 cbTransfer = ataBE2H_U16(pbPacket + 7); 4856 4815 Log2(("ATAPI PT: lba %d\n", iATAPILBA)); 4857 enmT xDir = AHCITXDIR_WRITE;4816 enmType = PDMMEDIAEXIOREQTYPE_WRITE; 4858 4817 fSendCmd = true; 4859 4818 break; 4860 4819 case SCSI_FORMAT_UNIT: 4861 4820 cbTransfer = pAhciReq->cmdFis[AHCI_CMDFIS_CYLL] | (pAhciReq->cmdFis[AHCI_CMDFIS_CYLH] << 8); /* use ATAPI transfer length */ 4862 enmT xDir = AHCITXDIR_WRITE;4821 enmType = PDMMEDIAEXIOREQTYPE_WRITE; 4863 4822 fSendCmd = true; 4864 4823 break; 4865 4824 case SCSI_GET_CONFIGURATION: 4866 4825 cbTransfer = ataBE2H_U16(pbPacket + 7); 4867 enmT xDir = AHCITXDIR_READ;4826 enmType = PDMMEDIAEXIOREQTYPE_READ; 4868 4827 fSendCmd = true; 4869 4828 break; … … 4876 4835 break; 4877 4836 } 4878 enmT xDir = AHCITXDIR_READ;4837 enmType = PDMMEDIAEXIOREQTYPE_READ; 4879 4838 fSendCmd = true; 4880 4839 break; 4881 4840 case SCSI_GET_PERFORMANCE: 4882 4841 cbTransfer = pAhciReq->cmdFis[AHCI_CMDFIS_CYLL] | (pAhciReq->cmdFis[AHCI_CMDFIS_CYLH] << 8); /* use ATAPI transfer length */ 4883 enmT xDir = AHCITXDIR_READ;4842 enmType = PDMMEDIAEXIOREQTYPE_READ; 4884 4843 fSendCmd = true; 4885 4844 break; 4886 4845 case SCSI_INQUIRY: 4887 4846 cbTransfer = ataBE2H_U16(pbPacket + 3); 4888 enmT xDir = AHCITXDIR_READ;4847 enmType = PDMMEDIAEXIOREQTYPE_READ; 4889 4848 fSendCmd = true; 4890 4849 break; … … 4894 4853 case SCSI_MECHANISM_STATUS: 4895 4854 cbTransfer = ataBE2H_U16(pbPacket + 8); 4896 enmT xDir = AHCITXDIR_READ;4855 enmType = PDMMEDIAEXIOREQTYPE_READ; 4897 4856 fSendCmd = true; 4898 4857 break; 4899 4858 case SCSI_MODE_SELECT_10: 4900 4859 cbTransfer = ataBE2H_U16(pbPacket + 7); 4901 enmT xDir = AHCITXDIR_WRITE;4860 enmType = PDMMEDIAEXIOREQTYPE_WRITE; 4902 4861 fSendCmd = true; 4903 4862 break; 4904 4863 case SCSI_MODE_SENSE_10: 4905 4864 cbTransfer = ataBE2H_U16(pbPacket + 7); 4906 enmT xDir = AHCITXDIR_READ;4865 enmType = PDMMEDIAEXIOREQTYPE_READ; 4907 4866 fSendCmd = true; 4908 4867 break; … … 4929 4888 pAhciReq->cbATAPISector = 2048; /**< @todo this size is not always correct */ 4930 4889 cbTransfer = cSectors * pAhciReq->cbATAPISector; 4931 enmT xDir = AHCITXDIR_READ;4890 enmType = PDMMEDIAEXIOREQTYPE_READ; 4932 4891 fSendCmd = true; 4933 4892 break; … … 4938 4897 pAhciReq->cbATAPISector = 2048; /**< @todo this size is not always correct */ 4939 4898 cbTransfer = cSectors * pAhciReq->cbATAPISector; 4940 enmT xDir = AHCITXDIR_READ;4899 enmType = PDMMEDIAEXIOREQTYPE_READ; 4941 4900 fSendCmd = true; 4942 4901 break; 4943 4902 case SCSI_READ_BUFFER: 4944 4903 cbTransfer = ataBE2H_U24(pbPacket + 6); 4945 enmT xDir = AHCITXDIR_READ;4904 enmType = PDMMEDIAEXIOREQTYPE_READ; 4946 4905 fSendCmd = true; 4947 4906 break; 4948 4907 case SCSI_READ_BUFFER_CAPACITY: 4949 4908 cbTransfer = ataBE2H_U16(pbPacket + 7); 4950 enmT xDir = AHCITXDIR_READ;4909 enmType = PDMMEDIAEXIOREQTYPE_READ; 4951 4910 fSendCmd = true; 4952 4911 break; 4953 4912 case SCSI_READ_CAPACITY: 4954 4913 cbTransfer = 8; 4955 enmT xDir = AHCITXDIR_READ;4914 enmType = PDMMEDIAEXIOREQTYPE_READ; 4956 4915 fSendCmd = true; 4957 4916 break; … … 5006 4965 cbTransfer = cSectors * pAhciReq->cbATAPISector; 5007 4966 } 5008 enmT xDir = AHCITXDIR_READ;4967 enmType = PDMMEDIAEXIOREQTYPE_READ; 5009 4968 fSendCmd = true; 5010 4969 break; … … 5012 4971 case SCSI_READ_DISC_INFORMATION: 5013 4972 cbTransfer = ataBE2H_U16(pbPacket + 7); 5014 enmT xDir = AHCITXDIR_READ;4973 enmType = PDMMEDIAEXIOREQTYPE_READ; 5015 4974 fSendCmd = true; 5016 4975 break; 5017 4976 case SCSI_READ_DVD_STRUCTURE: 5018 4977 cbTransfer = ataBE2H_U16(pbPacket + 8); 5019 enmT xDir = AHCITXDIR_READ;4978 enmType = PDMMEDIAEXIOREQTYPE_READ; 5020 4979 fSendCmd = true; 5021 4980 break; 5022 4981 case SCSI_READ_FORMAT_CAPACITIES: 5023 4982 cbTransfer = ataBE2H_U16(pbPacket + 7); 5024 enmT xDir = AHCITXDIR_READ;4983 enmType = PDMMEDIAEXIOREQTYPE_READ; 5025 4984 fSendCmd = true; 5026 4985 break; 5027 4986 case SCSI_READ_SUBCHANNEL: 5028 4987 cbTransfer = ataBE2H_U16(pbPacket + 7); 5029 enmT xDir = AHCITXDIR_READ;4988 enmType = PDMMEDIAEXIOREQTYPE_READ; 5030 4989 fSendCmd = true; 5031 4990 break; 5032 4991 case SCSI_READ_TOC_PMA_ATIP: 5033 4992 cbTransfer = ataBE2H_U16(pbPacket + 7); 5034 enmT xDir = AHCITXDIR_READ;4993 enmType = PDMMEDIAEXIOREQTYPE_READ; 5035 4994 fSendCmd = true; 5036 4995 break; 5037 4996 case SCSI_READ_TRACK_INFORMATION: 5038 4997 cbTransfer = ataBE2H_U16(pbPacket + 7); 5039 enmT xDir = AHCITXDIR_READ;4998 enmType = PDMMEDIAEXIOREQTYPE_READ; 5040 4999 fSendCmd = true; 5041 5000 break; … … 5045 5004 case SCSI_REPORT_KEY: 5046 5005 cbTransfer = ataBE2H_U16(pbPacket + 8); 5047 enmT xDir = AHCITXDIR_READ;5006 enmType = PDMMEDIAEXIOREQTYPE_READ; 5048 5007 fSendCmd = true; 5049 5008 break; … … 5053 5012 { 5054 5013 pAhciReq->cbTransfer = cbTransfer; 5055 pAhciReq->enmT xDir = AHCITXDIR_READ;5014 pAhciReq->enmType = PDMMEDIAEXIOREQTYPE_READ; 5056 5015 atapiDoTransfer(pAhciPort, pAhciReq, cbTransfer, ATAFN_SS_ATAPI_REQUEST_SENSE); 5057 5016 break; 5058 5017 } 5059 enmT xDir = AHCITXDIR_READ;5018 enmType = PDMMEDIAEXIOREQTYPE_READ; 5060 5019 fSendCmd = true; 5061 5020 break; … … 5071 5030 case SCSI_SEND_CUE_SHEET: 5072 5031 cbTransfer = ataBE2H_U24(pbPacket + 6); 5073 enmT xDir = AHCITXDIR_WRITE;5032 enmType = PDMMEDIAEXIOREQTYPE_WRITE; 5074 5033 fSendCmd = true; 5075 5034 break; 5076 5035 case SCSI_SEND_DVD_STRUCTURE: 5077 5036 cbTransfer = ataBE2H_U16(pbPacket + 8); 5078 enmT xDir = AHCITXDIR_WRITE;5037 enmType = PDMMEDIAEXIOREQTYPE_WRITE; 5079 5038 fSendCmd = true; 5080 5039 break; 5081 5040 case SCSI_SEND_EVENT: 5082 5041 cbTransfer = ataBE2H_U16(pbPacket + 8); 5083 enmT xDir = AHCITXDIR_WRITE;5042 enmType = PDMMEDIAEXIOREQTYPE_WRITE; 5084 5043 fSendCmd = true; 5085 5044 break; 5086 5045 case SCSI_SEND_KEY: 5087 5046 cbTransfer = ataBE2H_U16(pbPacket + 8); 5088 enmT xDir = AHCITXDIR_WRITE;5047 enmType = PDMMEDIAEXIOREQTYPE_WRITE; 5089 5048 fSendCmd = true; 5090 5049 break; 5091 5050 case SCSI_SEND_OPC_INFORMATION: 5092 5051 cbTransfer = ataBE2H_U16(pbPacket + 7); 5093 enmT xDir = AHCITXDIR_WRITE;5052 enmType = PDMMEDIAEXIOREQTYPE_WRITE; 5094 5053 fSendCmd = true; 5095 5054 break; … … 5102 5061 case SCSI_SET_STREAMING: 5103 5062 cbTransfer = ataBE2H_U16(pbPacket + 9); 5104 enmT xDir = AHCITXDIR_WRITE;5063 enmType = PDMMEDIAEXIOREQTYPE_WRITE; 5105 5064 fSendCmd = true; 5106 5065 break; … … 5130 5089 pAhciReq->cbATAPISector = 2048; 5131 5090 cbTransfer = cSectors * pAhciReq->cbATAPISector; 5132 enmT xDir = AHCITXDIR_WRITE;5091 enmType = PDMMEDIAEXIOREQTYPE_WRITE; 5133 5092 fSendCmd = true; 5134 5093 break; … … 5142 5101 pAhciReq->cbATAPISector = 2048; 5143 5102 cbTransfer = cSectors * pAhciReq->cbATAPISector; 5144 enmT xDir = AHCITXDIR_WRITE;5103 enmType = PDMMEDIAEXIOREQTYPE_WRITE; 5145 5104 fSendCmd = true; 5146 5105 break; … … 5159 5118 default: 5160 5119 cbTransfer = ataBE2H_U16(pbPacket + 6); 5161 enmT xDir = AHCITXDIR_WRITE;5120 enmType = PDMMEDIAEXIOREQTYPE_WRITE; 5162 5121 fSendCmd = true; 5163 5122 break; … … 5166 5125 case SCSI_REPORT_LUNS: /* Not part of MMC-3, but used by Windows. */ 5167 5126 cbTransfer = ataBE2H_U32(pbPacket + 6); 5168 enmT xDir = AHCITXDIR_READ;5127 enmType = PDMMEDIAEXIOREQTYPE_READ; 5169 5128 fSendCmd = true; 5170 5129 break; … … 5188 5147 Log2(("ATAPI PT: max size %d\n", cbTransfer)); 5189 5148 if (cbTransfer == 0) 5190 enmT xDir = AHCITXDIR_NONE;5191 pAhciReq->enmT xDir = enmTxDir;5149 enmType = PDMMEDIAEXIOREQTYPE_INVALID; 5150 pAhciReq->enmType = enmType; 5192 5151 pAhciReq->cbTransfer = cbTransfer; 5193 5152 atapiDoTransfer(pAhciPort, pAhciReq, cbTransfer, ATAFN_SS_ATAPI_PASSTHROUGH); 5194 5153 } 5195 5154 5196 return AHCITXDIR_NONE;5197 } 5198 5199 static AHCITXDIRatapiParseCmd(PAHCIPort pAhciPort, PAHCIREQ pAhciReq)5200 { 5201 AHCITXDIR enmTxDir = AHCITXDIR_NONE;5155 return PDMMEDIAEXIOREQTYPE_INVALID; 5156 } 5157 5158 static PDMMEDIAEXIOREQTYPE atapiParseCmd(PAHCIPort pAhciPort, PAHCIREQ pAhciReq) 5159 { 5160 PDMMEDIAEXIOREQTYPE enmType = PDMMEDIAEXIOREQTYPE_INVALID; 5202 5161 const uint8_t *pbPacket; 5203 5162 … … 5207 5166 5208 5167 if (pAhciPort->fATAPIPassthrough) 5209 enmT xDir= atapiParseCmdPassthrough(pAhciPort, pAhciReq);5168 enmType = atapiParseCmdPassthrough(pAhciPort, pAhciReq); 5210 5169 else 5211 enmT xDir= atapiParseCmdVirtualATAPI(pAhciPort, pAhciReq);5212 5213 return enmT xDir;5170 enmType = atapiParseCmdVirtualATAPI(pAhciPort, pAhciReq); 5171 5172 return enmType; 5214 5173 } 5215 5174 … … 5289 5248 abPioSetupFis[AHCI_CMDFIS_TYPE] = AHCI_CMDFIS_TYPE_PIOSETUP; 5290 5249 abPioSetupFis[AHCI_CMDFIS_BITS] = (fInterrupt ? AHCI_CMDFIS_I : 0); 5291 if (pAhciReq->enmT xDir == AHCITXDIR_READ)5250 if (pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_READ) 5292 5251 abPioSetupFis[AHCI_CMDFIS_BITS] |= AHCI_CMDFIS_D; 5293 5252 abPioSetupFis[AHCI_CMDFIS_STS] = pAhciReq->uATARegStatus; … … 5538 5497 } 5539 5498 5540 #if 0 /* unused */5541 DECLINLINE(uint8_t) ahciGetTagQueued(uint8_t *pCmdFis)5542 {5543 return pCmdFis[AHCI_CMDFIS_SECTC] >> 3;5544 }5545 #endif /* unused */5546 5547 5499 /** 5548 5500 * Allocates memory for the given request using already allocated memory if possible. … … 5715 5667 static int ahciIoBufAllocate(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, size_t cbTransfer) 5716 5668 { 5717 AssertMsg( pAhciReq->enmT xDir == AHCITXDIR_READ5718 || pAhciReq->enmT xDir == AHCITXDIR_WRITE,5669 AssertMsg( pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_READ 5670 || pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_WRITE, 5719 5671 ("Allocating I/O memory for a non I/O request is not allowed\n")); 5720 5672 … … 5724 5676 5725 5677 pAhciReq->u.Io.DataSeg.cbSeg = cbTransfer; 5726 if (pAhciReq->enmT xDir == AHCITXDIR_WRITE)5678 if (pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_WRITE) 5727 5679 { 5728 5680 ahciCopyFromPrdtl(pAhciPort->pDevInsR3, pAhciReq, … … 5745 5697 bool fCopyToGuest) 5746 5698 { 5747 AssertMsg( pAhciReq->enmT xDir == AHCITXDIR_READ5748 || pAhciReq->enmT xDir == AHCITXDIR_WRITE,5699 AssertMsg( pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_READ 5700 || pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_WRITE, 5749 5701 ("Freeing I/O memory for a non I/O request is not allowed\n")); 5750 5702 5751 if ( pAhciReq->enmT xDir == AHCITXDIR_READ5703 if ( pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_READ 5752 5704 && fCopyToGuest) 5753 5705 { … … 5773 5725 } 5774 5726 5775 5776 /**5777 * Free all cached tasks on the given port.5778 *5779 * @returns nothing.5780 * @param pAhciPort The AHCI port.5781 */5782 static void ahciR3PortCachedReqsFree(PAHCIPort pAhciPort)5783 {5784 if (pAhciPort->pListReqsFree)5785 {5786 PAHCIREQ pReq = NULL;5787 PAHCIREQ pReqNext = NULL;5788 5789 RTCritSectEnter(&pAhciPort->CritSectReqsFree);5790 RTListForEachSafe(pAhciPort->pListReqsFree, pReq, pReqNext, AHCIREQ, NodeList)5791 {5792 RTListNodeRemove(&pReq->NodeList);5793 ahciReqMemFree(pAhciPort, pReq, true /* fForceFree */);5794 RTMemFree(pReq);5795 }5796 RTCritSectLeave(&pAhciPort->CritSectReqsFree);5797 }5798 }5799 5727 5800 5728 /** … … 5806 5734 * (used for error page reading). 5807 5735 */ 5808 static bool ahciCancelActiveTasks(PAHCIPort pAhciPort, PAHCIREQ pAhciReqExcept) 5809 { 5810 for (unsigned i = 0; i < RT_ELEMENTS(pAhciPort->aActiveTasks); i++) 5811 { 5812 PAHCIREQ pAhciReq = ASMAtomicReadPtrT(&pAhciPort->aActiveTasks[i], PAHCIREQ); 5813 if (pAhciReq != pAhciReqExcept) 5814 { 5815 pAhciReq = (PAHCIREQ)ASMAtomicXchgPtr((void * volatile *)&pAhciPort->aActiveTasks[i], NULL); 5816 5817 if (VALID_PTR(pAhciReq)) 5818 { 5819 bool fXchg = ASMAtomicCmpXchgU32((volatile uint32_t *)&pAhciReq->enmTxState, AHCITXSTATE_CANCELED, AHCITXSTATE_ACTIVE); 5820 if (fXchg) 5821 { 5822 /* Task is active and was canceled. */ 5823 AssertReleaseMsg(ASMAtomicReadU32(&pAhciPort->cTasksActive) > 0, 5824 ("Task was canceled but none is active\n")); 5825 ASMAtomicDecU32(&pAhciPort->cTasksActive); 5826 5827 /* 5828 * Clear the pointer in the cached array. The controller will allocate a 5829 * a new task structure for this tag. 5830 */ 5831 ASMAtomicWriteNullPtr(&pAhciPort->aActiveTasks[i]); 5832 LogRel(("AHCI#%uP%u: Cancelled task %u\n", pAhciPort->CTX_SUFF(pDevIns)->iInstance, 5833 pAhciPort->iLUN, pAhciReq->uTag)); 5834 } 5835 else 5836 AssertMsg(pAhciReq->enmTxState == AHCITXSTATE_FREE, 5837 ("Invalid task state, must be free!\n")); 5838 } 5839 } 5840 } 5841 5736 static bool ahciCancelActiveTasks(PAHCIPort pAhciPort) 5737 { 5738 if (pAhciPort->pDrvMediaEx) 5739 { 5740 int rc = pAhciPort->pDrvMediaEx->pfnIoReqCancelAll(pAhciPort->pDrvMediaEx); 5741 AssertRC(rc); 5742 } 5842 5743 return true; /* always true for now because tasks don't use guest memory as the buffer which makes canceling a task impossible. */ 5843 5744 } … … 5927 5828 LogFlowFunc(("pAhciPort=%#p pAhciReq=%#p\n", pAhciPort, pAhciReq)); 5928 5829 5929 AssertMsgReturn(pAhciReq->enmT xDir == AHCITXDIR_TRIM, ("This is not a trim request\n"), VERR_INVALID_PARAMETER);5830 AssertMsgReturn(pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_DISCARD, ("This is not a trim request\n"), VERR_INVALID_PARAMETER); 5930 5831 5931 5832 /* The data buffer contains LBA range entries. Each range is 8 bytes big. */ … … 6039 5940 static void ahciTrimRangesDestroy(PAHCIREQ pAhciReq) 6040 5941 { 6041 AssertReturnVoid(pAhciReq->enmT xDir == AHCITXDIR_TRIM);5942 AssertReturnVoid(pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_DISCARD); 6042 5943 RTMemFree(pAhciReq->u.Trim.paRanges); 6043 5944 } … … 6048 5949 * @returns A new AHCI request structure or NULL if out of memory. 6049 5950 * @param pAhciPort The AHCI port. 6050 */ 6051 static PAHCIREQ ahciR3ReqAlloc(PAHCIPort pAhciPort) 5951 * @param uTag The tag to assign. 5952 */ 5953 static PAHCIREQ ahciR3ReqAlloc(PAHCIPort pAhciPort, uint32_t uTag) 6052 5954 { 6053 5955 PAHCIREQ pAhciReq = NULL; 6054 6055 /* Check the global free list first. */ 6056 RTCritSectEnter(&pAhciPort->CritSectReqsFree); 6057 pAhciReq = RTListGetFirst(pAhciPort->pListReqsFree, AHCIREQ, NodeList); 6058 if (pAhciReq) 6059 { 6060 AssertMsg(pAhciReq->enmTxState == AHCITXSTATE_FREE, ("Should be free!\n")); 6061 RTListNodeRemove(&pAhciReq->NodeList); 6062 } 6063 RTCritSectLeave(&pAhciPort->CritSectReqsFree); 6064 6065 if (!pAhciReq) 6066 pAhciReq = (PAHCIREQ)RTMemAllocZ(sizeof(AHCIREQ)); 6067 6068 pAhciReq->enmTxState = AHCITXSTATE_ACTIVE; 5956 PDMMEDIAEXIOREQ hIoReq = NULL; 5957 5958 int rc = pAhciPort->pDrvMediaEx->pfnIoReqAlloc(pAhciPort->pDrvMediaEx, &hIoReq, (void **)&pAhciReq, 5959 uTag, 0 /* fFlags */); 5960 if (RT_SUCCESS(rc)) 5961 { 5962 pAhciReq->hIoReq = hIoReq; 5963 pAhciReq->enmTxState = AHCITXSTATE_ACTIVE; 5964 } 5965 else 5966 pAhciReq = NULL; 6069 5967 return pAhciReq; 6070 5968 } … … 6081 5979 pAhciReq->enmTxState = AHCITXSTATE_FREE; 6082 5980 6083 RTCritSectEnter(&pAhciPort->CritSectReqsFree); 6084 RTListAppend(pAhciPort->pListReqsFree, &pAhciReq->NodeList); 6085 RTCritSectLeave(&pAhciPort->CritSectReqsFree); 5981 int rc = pAhciPort->pDrvMediaEx->pfnIoReqFree(pAhciPort->pDrvMediaEx, pAhciReq->hIoReq); 5982 AssertRC(rc); 6086 5983 } 6087 5984 … … 6117 6014 */ 6118 6015 bool fPortReset = ASMAtomicReadBool(&pAhciPort->fPortReset); 6119 bool fXchg = ASMAtomicCmpXchgPtr(&pAhciPort->aActiveTasks[pAhciReq->uTag], NULL, pAhciReq);6120 6016 bool fReqErrSaved = false; 6121 6017 … … 6128 6024 const char *pcszReq = NULL; 6129 6025 6130 switch (pAhciReq->enmT xDir)6131 { 6132 case AHCITXDIR_READ:6026 switch (pAhciReq->enmType) 6027 { 6028 case PDMMEDIAEXIOREQTYPE_READ: 6133 6029 pcszReq = "Read"; 6134 6030 break; 6135 case AHCITXDIR_WRITE:6031 case PDMMEDIAEXIOREQTYPE_WRITE: 6136 6032 pcszReq = "Write"; 6137 6033 break; 6138 case AHCITXDIR_FLUSH:6034 case PDMMEDIAEXIOREQTYPE_FLUSH: 6139 6035 pcszReq = "Flush"; 6140 6036 break; 6141 case AHCITXDIR_TRIM:6037 case PDMMEDIAEXIOREQTYPE_DISCARD: 6142 6038 pcszReq = "Trim"; 6143 6039 break; … … 6150 6046 } 6151 6047 6152 if ( fXchg && !fPortReset)6153 { 6154 if (pAhciReq->enmT xDir == AHCITXDIR_READ)6048 if (rcReq != VERR_PDM_MEDIAEX_IOREQ_CANCELED) 6049 { 6050 if (pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_READ) 6155 6051 { 6156 6052 ahciIoBufFree(pAhciPort, pAhciReq, true /* fCopyToGuest */); … … 6158 6054 pAhciPort->Led.Actual.s.fReading = 0; 6159 6055 } 6160 else if (pAhciReq->enmT xDir == AHCITXDIR_WRITE)6056 else if (pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_WRITE) 6161 6057 { 6162 6058 ahciIoBufFree(pAhciPort, pAhciReq, false /* fCopyToGuest */); … … 6164 6060 pAhciPort->Led.Actual.s.fWriting = 0; 6165 6061 } 6166 else if (pAhciReq->enmT xDir == AHCITXDIR_TRIM)6062 else if (pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_DISCARD) 6167 6063 { 6168 6064 ahciTrimRangesDestroy(pAhciReq); … … 6175 6071 if (pAhciPort->cErrors++ < MAX_LOG_REL_ERRORS) 6176 6072 { 6177 if (pAhciReq->enmT xDir == AHCITXDIR_FLUSH)6073 if (pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_FLUSH) 6178 6074 LogRel(("AHCI#%uP%u: Flush returned rc=%Rrc\n", 6179 6075 pAhciPort->CTX_SUFF(pDevIns)->iInstance, pAhciPort->iLUN, rcReq)); 6180 else if (pAhciReq->enmT xDir == AHCITXDIR_TRIM)6076 else if (pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_DISCARD) 6181 6077 LogRel(("AHCI#%uP%u: Trim returned rc=%Rrc\n", 6182 6078 pAhciPort->CTX_SUFF(pDevIns)->iInstance, pAhciPort->iLUN, rcReq)); … … 6184 6080 LogRel(("AHCI#%uP%u: %s at offset %llu (%u bytes left) returned rc=%Rrc\n", 6185 6081 pAhciPort->CTX_SUFF(pDevIns)->iInstance, pAhciPort->iLUN, 6186 pAhciReq->enmT xDir == AHCITXDIR_READ6082 pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_READ 6187 6083 ? "Read" 6188 6084 : "Write", … … 6194 6090 if (!fRedo) 6195 6091 { 6196 pAhciReq->cmdHdr.u32PRDBC = 0;6197 6092 pAhciReq->uATARegError = ID_ERR; 6198 6093 pAhciReq->uATARegStatus = ATA_STAT_READY | ATA_STAT_ERR; … … 6204 6099 else 6205 6100 { 6206 pAhciReq->cmdHdr.u32PRDBC = pAhciReq->cbTransfer;6207 6208 6101 /* Status will be set already for non I/O requests. */ 6209 if (pAhciReq->enmT xDir != AHCITXDIR_NONE)6102 if (pAhciReq->enmType != PDMMEDIAEXIOREQTYPE_INVALID) 6210 6103 { 6211 6104 pAhciReq->uATARegError = 0; … … 6214 6107 6215 6108 /* Write updated command header into memory of the guest. */ 6216 PDMDevHlpPCIPhysWrite(pAhciPort->CTX_SUFF(pDevIns), pAhciReq->GCPhysCmdHdrAddr, &pAhciReq->cmdHdr, sizeof(CmdHdr)); 6109 uint32_t u32PRDBC = pAhciReq->cbTransfer; 6110 PDMDevHlpPCIPhysWrite(pAhciPort->CTX_SUFF(pDevIns), pAhciReq->GCPhysCmdHdrAddr + RT_OFFSETOF(CmdHdr, u32PRDBC), 6111 &u32PRDBC, sizeof(u32PRDBC)); 6217 6112 6218 6113 if (pAhciReq->fFlags & AHCI_REQ_OVERFLOW) … … 6266 6161 fCanceled = true; 6267 6162 6268 if (pAhciReq->enmT xDir == AHCITXDIR_TRIM)6163 if (pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_DISCARD) 6269 6164 ahciTrimRangesDestroy(pAhciReq); 6270 else if (pAhciReq->enmT xDir != AHCITXDIR_FLUSH)6165 else if (pAhciReq->enmType != PDMMEDIAEXIOREQTYPE_FLUSH) 6271 6166 ahciIoBufFree(pAhciPort, pAhciReq, false /* fCopyToGuest */); 6272 6167 … … 6274 6169 if (pAhciPort->cErrors++ < MAX_LOG_REL_ERRORS) 6275 6170 { 6276 if (pAhciReq->enmT xDir == AHCITXDIR_FLUSH)6171 if (pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_FLUSH) 6277 6172 LogRel(("AHCI#%uP%u: Canceled flush returned rc=%Rrc\n", 6278 6173 pAhciPort->CTX_SUFF(pDevIns)->iInstance, pAhciPort->iLUN, rcReq)); 6279 else if (pAhciReq->enmT xDir == AHCITXDIR_TRIM)6174 else if (pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_DISCARD) 6280 6175 LogRel(("AHCI#%uP%u: Canceled trim returned rc=%Rrc\n", 6281 6176 pAhciPort->CTX_SUFF(pDevIns)->iInstance,pAhciPort->iLUN, rcReq)); … … 6283 6178 LogRel(("AHCI#%uP%u: Canceled %s at offset %llu (%u bytes left) returned rc=%Rrc\n", 6284 6179 pAhciPort->CTX_SUFF(pDevIns)->iInstance, pAhciPort->iLUN, 6285 pAhciReq->enmT xDir == AHCITXDIR_READ6180 pAhciReq->enmType == PDMMEDIAEXIOREQTYPE_READ 6286 6181 ? "read" 6287 6182 : "write", … … 6299 6194 * on this thread. 6300 6195 */ 6301 if (fXchg) 6302 { 6303 AssertReleaseMsg(ASMAtomicReadU32(&pAhciPort->cTasksActive) > 0, 6304 ("Inconsistent request counter\n")); 6305 ASMAtomicDecU32(&pAhciPort->cTasksActive); 6306 } 6196 ASMAtomicDecU32(&pAhciPort->cTasksActive); 6307 6197 6308 6198 if (pAhciPort->cTasksActive == 0 && pAhciPort->pAhciR3->fSignalIdle) … … 6318 6208 6319 6209 /** 6320 * Notification callback for a completed transfer. 6321 * 6322 * @returns VBox status code. 6323 * @param pInterface Pointer to the interface. 6324 * @param pvUser User data. 6325 * @param rcReq IPRT Status code of the completed request. 6326 */ 6327 static DECLCALLBACK(int) ahciR3TransferCompleteNotify(PPDMIMEDIAASYNCPORT pInterface, void *pvUser, int rcReq) 6328 { 6329 PAHCIPort pAhciPort = PDMIMEDIAASYNCPORT_2_PAHCIPORT(pInterface); 6330 PAHCIREQ pAhciReq = (PAHCIREQ)pvUser; 6331 6332 ahciLog(("%s: pInterface=%p pvUser=%p uTag=%u\n", 6333 __FUNCTION__, pInterface, pvUser, pAhciReq->uTag)); 6334 6335 ahciTransferComplete(pAhciPort, pAhciReq, rcReq); 6210 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqCopyFromBuf} 6211 */ 6212 static DECLCALLBACK(int) ahciR3IoReqCopyFromBuf(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq, 6213 void *pvIoReqAlloc, uint32_t offDst, PRTSGBUF pSgBuf, 6214 size_t cbCopy) 6215 { 6216 RT_NOREF2(pInterface, hIoReq); 6217 int rc = VINF_SUCCESS; 6218 PAHCIREQ pIoReq = (PAHCIREQ)pvIoReqAlloc; 6219 6220 if (offDst + cbCopy <= pIoReq->u.Io.DataSeg.cbSeg) 6221 { 6222 void *pvBuf = (uint8_t *)pIoReq->u.Io.DataSeg.pvSeg + offDst; 6223 RTSgBufCopyToBuf(pSgBuf, pvBuf, cbCopy); 6224 } 6225 else 6226 rc = VERR_PDM_MEDIAEX_IOBUF_OVERFLOW; 6227 6228 return rc; 6229 } 6230 6231 /** 6232 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqCopyToBuf} 6233 */ 6234 static DECLCALLBACK(int) ahciR3IoReqCopyToBuf(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq, 6235 void *pvIoReqAlloc, uint32_t offSrc, PRTSGBUF pSgBuf, 6236 size_t cbCopy) 6237 { 6238 RT_NOREF2(pInterface, hIoReq); 6239 int rc = VINF_SUCCESS; 6240 PAHCIREQ pIoReq = (PAHCIREQ)pvIoReqAlloc; 6241 6242 if (offSrc + cbCopy <= pIoReq->u.Io.DataSeg.cbSeg) 6243 { 6244 void *pvBuf = (uint8_t *)pIoReq->u.Io.DataSeg.pvSeg + offSrc; 6245 RTSgBufCopyFromBuf(pSgBuf, pvBuf, cbCopy); 6246 } 6247 else 6248 rc = VERR_PDM_MEDIAEX_IOBUF_UNDERRUN; 6249 6250 return rc; 6251 } 6252 6253 /** 6254 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqQueryDiscardRanges} 6255 */ 6256 static DECLCALLBACK(int) ahciR3IoReqQueryDiscardRanges(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq, 6257 void *pvIoReqAlloc, uint32_t idxRangeStart, 6258 uint32_t cRanges, PRTRANGE paRanges, 6259 uint32_t *pcRanges) 6260 { 6261 RT_NOREF2(pInterface, hIoReq); 6262 PAHCIREQ pIoReq = (PAHCIREQ)pvIoReqAlloc; 6263 uint32_t cRangesCopy = RT_MIN(pIoReq->u.Trim.cRanges - idxRangeStart, cRanges); 6264 Assert( idxRangeStart < pIoReq->u.Trim.cRanges 6265 && (idxRangeStart + cRanges) <= pIoReq->u.Trim.cRanges); 6266 6267 memcpy(paRanges, &pIoReq->u.Trim.paRanges[idxRangeStart], cRangesCopy * sizeof(RTRANGE)); 6268 *pcRanges = cRangesCopy; 6336 6269 6337 6270 return VINF_SUCCESS; 6338 6271 } 6272 6273 /** 6274 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqCompleteNotify} 6275 */ 6276 static DECLCALLBACK(int) ahciR3IoReqCompleteNotify(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq, 6277 void *pvIoReqAlloc, int rcReq) 6278 { 6279 RT_NOREF(hIoReq); 6280 PAHCIPort pAhciPort = RT_FROM_MEMBER(pInterface, AHCIPort, IMediaExPort); 6281 ahciTransferComplete(pAhciPort, (PAHCIREQ)pvIoReqAlloc, rcReq); 6282 return VINF_SUCCESS; 6283 } 6284 6285 /** 6286 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqStateChanged} 6287 */ 6288 static DECLCALLBACK(void) ahciR3IoReqStateChanged(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq, 6289 void *pvIoReqAlloc, PDMMEDIAEXIOREQSTATE enmState) 6290 { 6291 RT_NOREF(hIoReq); 6292 PAHCIPort pAhciPort = RT_FROM_MEMBER(pInterface, AHCIPort, IMediaExPort); 6293 PAHCIREQ pIoReq = (PAHCIREQ)pvIoReqAlloc; 6294 6295 RT_NOREF3(pAhciPort, pIoReq, enmState); 6296 AssertLogRelMsgFailed(("This should not be hit because I/O requests should not be suspended\n")); 6297 } 6298 6339 6299 6340 6300 /** … … 6344 6304 * @param pCmdHdr Pointer to the command header. 6345 6305 */ 6346 static AHCITXDIRahciProcessCmd(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, uint8_t *pCmdFis)6347 { 6348 AHCITXDIR enmTxDir = AHCITXDIR_NONE;6306 static PDMMEDIAEXIOREQTYPE ahciProcessCmd(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, uint8_t *pCmdFis) 6307 { 6308 PDMMEDIAEXIOREQTYPE enmType = PDMMEDIAEXIOREQTYPE_INVALID; 6349 6309 bool fLBA48 = false; 6350 6310 … … 6393 6353 break; 6394 6354 case 0x82: /* write cache disable */ 6395 enmT xDir = AHCITXDIR_FLUSH;6355 enmType = PDMMEDIAEXIOREQTYPE_FLUSH; 6396 6356 break; 6397 6357 case 0x03: … … 6435 6395 case ATA_FLUSH_CACHE_EXT: 6436 6396 case ATA_FLUSH_CACHE: 6437 enmT xDir = AHCITXDIR_FLUSH;6397 enmType = PDMMEDIAEXIOREQTYPE_FLUSH; 6438 6398 break; 6439 6399 case ATA_PACKET: … … 6444 6404 } 6445 6405 else 6446 enmT xDir= atapiParseCmd(pAhciPort, pAhciReq);6406 enmType = atapiParseCmd(pAhciPort, pAhciReq); 6447 6407 break; 6448 6408 case ATA_IDENTIFY_PACKET_DEVICE: … … 6499 6459 pAhciReq->cbTransfer = ahciGetNSectors(pCmdFis, fLBA48) * pAhciPort->cbSector; 6500 6460 pAhciReq->uOffset = ahciGetSector(pAhciPort, pCmdFis, fLBA48) * pAhciPort->cbSector; 6501 enmT xDir = AHCITXDIR_READ;6461 enmType = PDMMEDIAEXIOREQTYPE_READ; 6502 6462 break; 6503 6463 } … … 6508 6468 pAhciReq->cbTransfer = ahciGetNSectors(pCmdFis, fLBA48) * pAhciPort->cbSector; 6509 6469 pAhciReq->uOffset = ahciGetSector(pAhciPort, pCmdFis, fLBA48) * pAhciPort->cbSector; 6510 enmT xDir = AHCITXDIR_WRITE;6470 enmType = PDMMEDIAEXIOREQTYPE_WRITE; 6511 6471 break; 6512 6472 } … … 6516 6476 pAhciReq->uOffset = ahciGetSectorQueued(pCmdFis) * pAhciPort->cbSector; 6517 6477 pAhciReq->fFlags |= AHCI_REQ_IS_QUEUED; 6518 enmT xDir = AHCITXDIR_READ;6478 enmType = PDMMEDIAEXIOREQTYPE_READ; 6519 6479 break; 6520 6480 } … … 6524 6484 pAhciReq->uOffset = ahciGetSectorQueued(pCmdFis) * pAhciPort->cbSector; 6525 6485 pAhciReq->fFlags |= AHCI_REQ_IS_QUEUED; 6526 enmT xDir = AHCITXDIR_WRITE;6486 enmType = PDMMEDIAEXIOREQTYPE_WRITE; 6527 6487 break; 6528 6488 } … … 6569 6529 aBuf[511] = (uint8_t)-(int8_t)uChkSum; 6570 6530 6571 if (pTaskErr->enmTxDir == AHCITXDIR_TRIM)6572 ahciTrimRangesDestroy(pTaskErr);6573 else if (pTaskErr->enmTxDir != AHCITXDIR_FLUSH)6574 ahciReqMemFree(pAhciPort, pTaskErr, true /* fForceFree */);6575 6576 6531 /* Finally free the error task state structure because it is completely unused now. */ 6577 6532 RTMemFree(pTaskErr); … … 6584 6539 * See SATA2 1.2 spec chapter 4.2.3.4 6585 6540 */ 6586 bool fAbortedAll = ahciCancelActiveTasks(pAhciPort , pAhciReq);6541 bool fAbortedAll = ahciCancelActiveTasks(pAhciPort); 6587 6542 Assert(fAbortedAll); NOREF(fAbortedAll); 6588 6543 ahciSendSDBFis(pAhciPort, 0xffffffff, true); … … 6603 6558 case ATA_DATA_SET_MANAGEMENT: 6604 6559 { 6605 if ( ( !pAhciPort->fAsyncInterface 6606 && pAhciPort->pDrvMedia->pfnDiscard) 6607 || ( pAhciPort->fAsyncInterface 6608 && pAhciPort->pDrvMediaAsync->pfnStartDiscard)) 6560 if (pAhciPort->fTrimEnabled) 6609 6561 { 6610 6562 /* Check that the trim bit is set and all other bits are 0. */ … … 6616 6568 } 6617 6569 else 6618 enmT xDir = AHCITXDIR_TRIM;6570 enmType = PDMMEDIAEXIOREQTYPE_DISCARD; 6619 6571 break; 6620 6572 } … … 6636 6588 } 6637 6589 6638 return enmT xDir;6590 return enmType; 6639 6591 } 6640 6592 … … 6647 6599 static bool ahciPortTaskGetCommandFis(PAHCIPort pAhciPort, PAHCIREQ pAhciReq) 6648 6600 { 6649 RTGCPHYS GCPhysAddrCmdTbl;6650 6651 6601 AssertMsgReturn(pAhciPort->GCPhysAddrClb && pAhciPort->GCPhysAddrFb, 6652 6602 ("%s: GCPhysAddrClb and/or GCPhysAddrFb are 0\n", __FUNCTION__), … … 6658 6608 * We can process the Command FIS afterwards. 6659 6609 */ 6610 CmdHdr cmdHdr; 6660 6611 pAhciReq->GCPhysCmdHdrAddr = pAhciPort->GCPhysAddrClb + pAhciReq->uTag * sizeof(CmdHdr); 6661 6612 LogFlow(("%s: PDMDevHlpPhysRead GCPhysAddrCmdLst=%RGp cbCmdHdr=%u\n", __FUNCTION__, 6662 6613 pAhciReq->GCPhysCmdHdrAddr, sizeof(CmdHdr))); 6663 PDMDevHlpPhysRead(pAhciPort->CTX_SUFF(pDevIns), pAhciReq->GCPhysCmdHdrAddr, & pAhciReq->cmdHdr, sizeof(CmdHdr));6614 PDMDevHlpPhysRead(pAhciPort->CTX_SUFF(pDevIns), pAhciReq->GCPhysCmdHdrAddr, &cmdHdr, sizeof(CmdHdr)); 6664 6615 6665 6616 #ifdef LOG_ENABLED 6666 6617 /* Print some infos about the command header. */ 6667 ahciDumpCmdHdrInfo(pAhciPort, & pAhciReq->cmdHdr);6618 ahciDumpCmdHdrInfo(pAhciPort, &cmdHdr); 6668 6619 #endif 6669 6620 6670 GCPhysAddrCmdTbl = AHCI_RTGCPHYS_FROM_U32(pAhciReq->cmdHdr.u32CmdTblAddrUp, pAhciReq->cmdHdr.u32CmdTblAddr);6671 6672 AssertMsgReturn(( pAhciReq->cmdHdr.u32DescInf & AHCI_CMDHDR_CFL_MASK) * sizeof(uint32_t) == AHCI_CMDFIS_TYPE_H2D_SIZE,6621 RTGCPHYS GCPhysAddrCmdTbl = AHCI_RTGCPHYS_FROM_U32(cmdHdr.u32CmdTblAddrUp, cmdHdr.u32CmdTblAddr); 6622 6623 AssertMsgReturn((cmdHdr.u32DescInf & AHCI_CMDHDR_CFL_MASK) * sizeof(uint32_t) == AHCI_CMDFIS_TYPE_H2D_SIZE, 6673 6624 ("This is not a command FIS!!\n"), 6674 6625 false); … … 6683 6634 6684 6635 /* Set transfer direction. */ 6685 pAhciReq->enmT xDir = (pAhciReq->cmdHdr.u32DescInf & AHCI_CMDHDR_W) ? AHCITXDIR_WRITE : AHCITXDIR_READ;6636 pAhciReq->enmType = (cmdHdr.u32DescInf & AHCI_CMDHDR_W) ? PDMMEDIAEXIOREQTYPE_WRITE : PDMMEDIAEXIOREQTYPE_READ; 6686 6637 6687 6638 /* If this is an ATAPI command read the atapi command. */ 6688 if ( pAhciReq->cmdHdr.u32DescInf & AHCI_CMDHDR_A)6639 if (cmdHdr.u32DescInf & AHCI_CMDHDR_A) 6689 6640 { 6690 6641 GCPhysAddrCmdTbl += AHCI_CMDHDR_ACMD_OFFSET; … … 6693 6644 6694 6645 /* We "received" the FIS. Clear the BSY bit in regTFD. */ 6695 if (( pAhciReq->cmdHdr.u32DescInf & AHCI_CMDHDR_C) && (pAhciReq->fFlags & AHCI_REQ_CLEAR_SACT))6646 if ((cmdHdr.u32DescInf & AHCI_CMDHDR_C) && (pAhciReq->fFlags & AHCI_REQ_CLEAR_SACT)) 6696 6647 { 6697 6648 /* … … 6703 6654 } 6704 6655 6705 pAhciReq->GCPhysPrdtl = AHCI_RTGCPHYS_FROM_U32( pAhciReq->cmdHdr.u32CmdTblAddrUp, pAhciReq->cmdHdr.u32CmdTblAddr) + AHCI_CMDHDR_PRDT_OFFSET;6706 pAhciReq->cPrdtlEntries = AHCI_CMDHDR_PRDTL_ENTRIES( pAhciReq->cmdHdr.u32DescInf);6656 pAhciReq->GCPhysPrdtl = AHCI_RTGCPHYS_FROM_U32(cmdHdr.u32CmdTblAddrUp, cmdHdr.u32CmdTblAddr) + AHCI_CMDHDR_PRDT_OFFSET; 6657 pAhciReq->cPrdtlEntries = AHCI_CMDHDR_PRDTL_ENTRIES(cmdHdr.u32DescInf); 6707 6658 6708 6659 #ifdef LOG_ENABLED … … 6737 6688 * @param pAhciPort The port the request is for. 6738 6689 * @param pAhciReq The request to submit. 6739 * @param enmT xDirThe request type.6740 */ 6741 static bool ahciR3ReqSubmit(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, AHCITXDIR enmTxDir)6690 * @param enmType The request type. 6691 */ 6692 static bool ahciR3ReqSubmit(PAHCIPort pAhciPort, PAHCIREQ pAhciReq, PDMMEDIAEXIOREQTYPE enmType) 6742 6693 { 6743 6694 int rc = VINF_SUCCESS; 6744 6695 bool fReqCanceled = false; 6745 6696 6746 if (pAhciPort->fAsyncInterface) 6747 { 6748 VBOXDD_AHCI_REQ_SUBMIT(pAhciReq, pAhciReq->enmTxDir, pAhciReq->uOffset, pAhciReq->cbTransfer); 6749 VBOXDD_AHCI_REQ_SUBMIT_TIMESTAMP(pAhciReq, pAhciReq->tsStart); 6750 if (enmTxDir == AHCITXDIR_FLUSH) 6751 { 6752 rc = pAhciPort->pDrvMediaAsync->pfnStartFlush(pAhciPort->pDrvMediaAsync, 6753 pAhciReq); 6754 } 6755 else if (enmTxDir == AHCITXDIR_TRIM) 6756 { 6757 rc = ahciTrimRangesCreate(pAhciPort, pAhciReq); 6758 if (RT_SUCCESS(rc)) 6759 { 6760 pAhciPort->Led.Asserted.s.fWriting = pAhciPort->Led.Actual.s.fWriting = 1; 6761 rc = pAhciPort->pDrvMediaAsync->pfnStartDiscard(pAhciPort->pDrvMediaAsync, pAhciReq->u.Trim.paRanges, 6762 pAhciReq->u.Trim.cRanges, pAhciReq); 6763 } 6764 } 6765 else if (enmTxDir == AHCITXDIR_READ) 6766 { 6767 pAhciPort->Led.Asserted.s.fReading = pAhciPort->Led.Actual.s.fReading = 1; 6768 rc = pAhciPort->pDrvMediaAsync->pfnStartRead(pAhciPort->pDrvMediaAsync, pAhciReq->uOffset, 6769 &pAhciReq->u.Io.DataSeg, 1, 6770 pAhciReq->cbTransfer, 6771 pAhciReq); 6772 } 6773 else 6697 VBOXDD_AHCI_REQ_SUBMIT(pAhciReq, pAhciReq->enmType, pAhciReq->uOffset, pAhciReq->cbTransfer); 6698 VBOXDD_AHCI_REQ_SUBMIT_TIMESTAMP(pAhciReq, pAhciReq->tsStart); 6699 6700 if (enmType == PDMMEDIAEXIOREQTYPE_FLUSH) 6701 rc = pAhciPort->pDrvMediaEx->pfnIoReqFlush(pAhciPort->pDrvMediaEx, pAhciReq->hIoReq); 6702 else if (enmType == PDMMEDIAEXIOREQTYPE_DISCARD) 6703 { 6704 rc = ahciTrimRangesCreate(pAhciPort, pAhciReq); 6705 if (RT_SUCCESS(rc)) 6774 6706 { 6775 6707 pAhciPort->Led.Asserted.s.fWriting = pAhciPort->Led.Actual.s.fWriting = 1; 6776 rc = pAhciPort->pDrvMedia Async->pfnStartWrite(pAhciPort->pDrvMediaAsync, pAhciReq->uOffset,6777 &pAhciReq->u.Io.DataSeg, 1,6778 pAhciReq->cbTransfer,6779 pAhciReq);6780 }6781 if (rc == VINF_VD_ASYNC_IO_FINISHED)6782 fReqCanceled = ahciTransferComplete(pAhciPort, pAhciReq, VINF_SUCCESS);6783 else if (RT_FAILURE(rc) && rc != VERR_VD_ASYNC_IO_IN_PROGRESS)6784 fReqCanceled = ahciTransferComplete(pAhciPort, pAhciReq, rc);6708 rc = pAhciPort->pDrvMediaEx->pfnIoReqDiscard(pAhciPort->pDrvMediaEx, pAhciReq->hIoReq, 6709 pAhciReq->u.Trim.cRanges); 6710 } 6711 } 6712 else if (enmType == PDMMEDIAEXIOREQTYPE_READ) 6713 { 6714 pAhciPort->Led.Asserted.s.fReading = pAhciPort->Led.Actual.s.fReading = 1; 6715 rc = pAhciPort->pDrvMediaEx->pfnIoReqRead(pAhciPort->pDrvMediaEx, pAhciReq->hIoReq, 6716 pAhciReq->uOffset, pAhciReq->cbTransfer); 6785 6717 } 6786 6718 else 6787 6719 { 6788 if (enmTxDir == AHCITXDIR_FLUSH) 6789 rc = pAhciPort->pDrvMedia->pfnFlush(pAhciPort->pDrvMedia); 6790 else if (enmTxDir == AHCITXDIR_TRIM) 6791 { 6792 rc = ahciTrimRangesCreate(pAhciPort, pAhciReq); 6793 if (RT_SUCCESS(rc)) 6794 { 6795 pAhciPort->Led.Asserted.s.fWriting = pAhciPort->Led.Actual.s.fWriting = 1; 6796 rc = pAhciPort->pDrvMedia->pfnDiscard(pAhciPort->pDrvMedia, pAhciReq->u.Trim.paRanges, 6797 pAhciReq->u.Trim.cRanges); 6798 pAhciPort->Led.Asserted.s.fWriting = pAhciPort->Led.Actual.s.fWriting = 0; 6799 } 6800 } 6801 else if (enmTxDir == AHCITXDIR_READ) 6802 { 6803 pAhciPort->Led.Asserted.s.fReading = pAhciPort->Led.Actual.s.fReading = 1; 6804 rc = pAhciPort->pDrvMedia->pfnRead(pAhciPort->pDrvMedia, pAhciReq->uOffset, 6805 pAhciReq->u.Io.DataSeg.pvSeg, 6806 pAhciReq->cbTransfer); 6807 pAhciPort->Led.Asserted.s.fReading = pAhciPort->Led.Actual.s.fReading = 0; 6808 } 6809 else 6810 { 6811 pAhciPort->Led.Asserted.s.fWriting = pAhciPort->Led.Actual.s.fWriting = 1; 6812 rc = pAhciPort->pDrvMedia->pfnWrite(pAhciPort->pDrvMedia, pAhciReq->uOffset, 6813 pAhciReq->u.Io.DataSeg.pvSeg, 6814 pAhciReq->cbTransfer); 6815 pAhciPort->Led.Asserted.s.fWriting = pAhciPort->Led.Actual.s.fWriting = 0; 6816 } 6720 pAhciPort->Led.Asserted.s.fWriting = pAhciPort->Led.Actual.s.fWriting = 1; 6721 rc = pAhciPort->pDrvMediaEx->pfnIoReqWrite(pAhciPort->pDrvMediaEx, pAhciReq->hIoReq, 6722 pAhciReq->uOffset, pAhciReq->cbTransfer); 6723 } 6724 6725 if (rc == VINF_SUCCESS) 6726 fReqCanceled = ahciTransferComplete(pAhciPort, pAhciReq, VINF_SUCCESS); 6727 else if (rc != VINF_PDM_MEDIAEX_IOREQ_IN_PROGRESS) 6817 6728 fReqCanceled = ahciTransferComplete(pAhciPort, pAhciReq, rc); 6818 }6819 6729 6820 6730 return fReqCanceled; … … 6838 6748 /* Set current command slot */ 6839 6749 ASMAtomicWriteU32(&pAhciPort->u32CurrentCommandSlot, pAhciReq->uTag); 6840 ASMAtomicWritePtr(&pAhciPort->aActiveTasks[pAhciReq->uTag], pAhciReq);6841 6750 6842 6751 bool fContinue = ahciPortTaskGetCommandFis(pAhciPort, pAhciReq); … … 6984 6893 { 6985 6894 bool fReqCanceled = false; 6986 AHCITXDIR enmTxDir;6987 PAHCIREQ pAhciReq;6988 6895 6989 6896 /* Decrement to get the slot number. */ … … 6991 6898 ahciLog(("%s: Processing command at slot %d\n", __FUNCTION__, idx)); 6992 6899 6993 /* Check whether the request is already active and ignore. */ 6994 if (ASMAtomicReadPtr((void * volatile *)&pAhciPort->aActiveTasks[idx])) 6995 { 6996 ahciLog(("%s: Ignoring command at slot %d because it is already active\n", __FUNCTION__, idx)); 6997 continue; 6998 } 6999 7000 pAhciReq = ahciR3ReqAlloc(pAhciPort); 6900 PAHCIREQ pAhciReq = ahciR3ReqAlloc(pAhciPort, idx); 7001 6901 if (RT_LIKELY(pAhciReq)) 7002 6902 { … … 7007 6907 if (fContinue) 7008 6908 { 7009 enmTxDir= ahciProcessCmd(pAhciPort, pAhciReq, pAhciReq->cmdFis);7010 pAhciReq->enmT xDir = enmTxDir;7011 7012 if (enmT xDir != AHCITXDIR_NONE)6909 PDMMEDIAEXIOREQTYPE enmType = ahciProcessCmd(pAhciPort, pAhciReq, pAhciReq->cmdFis); 6910 pAhciReq->enmType = enmType; 6911 6912 if (enmType != PDMMEDIAEXIOREQTYPE_INVALID) 7013 6913 { 7014 if ( enmT xDir != AHCITXDIR_FLUSH7015 && enmT xDir != AHCITXDIR_TRIM)6914 if ( enmType != PDMMEDIAEXIOREQTYPE_FLUSH 6915 && enmType != PDMMEDIAEXIOREQTYPE_DISCARD) 7016 6916 { 7017 6917 STAM_REL_COUNTER_INC(&pAhciPort->StatDMA); … … 7027 6927 7028 6928 if (!(pAhciReq->fFlags & AHCI_REQ_OVERFLOW)) 7029 fReqCanceled = ahciR3ReqSubmit(pAhciPort, pAhciReq, enmT xDir);6929 fReqCanceled = ahciR3ReqSubmit(pAhciPort, pAhciReq, enmType); 7030 6930 else /* Overflow is handled in completion routine. */ 7031 6931 fReqCanceled = ahciTransferComplete(pAhciPort, pAhciReq, VINF_SUCCESS); … … 7035 6935 } /* Command */ 7036 6936 else 7037 {7038 ASMAtomicWriteNullPtr(&pAhciPort->aActiveTasks[pAhciReq->uTag]);7039 6937 ahciR3ReqFree(pAhciPort, pAhciReq); 7040 }7041 6938 } 7042 6939 else /* !Request allocated, use on stack variant to signal the error. */ … … 7144 7041 PAHCIPort pThisPort = &pThis->ahciPort[i]; 7145 7042 7146 pHlp->pfnPrintf(pHlp, "Port %d: async=%RTbooldevice-attached=%RTbool\n",7147 pThisPort->iLUN, pThisPort-> fAsyncInterface, pThisPort->pDrvBase != NULL);7043 pHlp->pfnPrintf(pHlp, "Port %d: device-attached=%RTbool\n", 7044 pThisPort->iLUN, pThisPort->pDrvBase != NULL); 7148 7045 pHlp->pfnPrintf(pHlp, "PortClb=%#x\n", pThisPort->regCLB); 7149 7046 pHlp->pfnPrintf(pHlp, "PortClbU=%#x\n", pThisPort->regCLBU); … … 7707 7604 Log(("%s:\n", __FUNCTION__)); 7708 7605 7709 /* Free all cached I/O tasks. */7710 ahciR3PortCachedReqsFree(pAhciPort);7711 7712 7606 pAhciPort->cTotalSectors = 0; 7713 7607 … … 7739 7633 static int ahciR3ConfigureLUN(PPDMDEVINS pDevIns, PAHCIPort pAhciPort) 7740 7634 { 7741 int rc = VINF_SUCCESS; 7742 PDMMEDIATYPE enmType; 7743 7744 /* 7745 * Query the block and blockbios interfaces. 7746 */ 7635 /* Query the media interface. */ 7747 7636 pAhciPort->pDrvMedia = PDMIBASE_QUERY_INTERFACE(pAhciPort->pDrvBase, PDMIMEDIA); 7748 if (!pAhciPort->pDrvMedia) 7749 { 7750 AssertMsgFailed(("Configuration error: LUN#%d hasn't a block interface!\n", pAhciPort->iLUN)); 7751 return VERR_PDM_MISSING_INTERFACE; 7752 } 7637 AssertMsgReturn(VALID_PTR(pAhciPort->pDrvMedia), 7638 ("AHCI configuration error: LUN#%d misses the basic media interface!\n", pAhciPort->iLUN), 7639 VERR_PDM_MISSING_INTERFACE); 7640 7641 /* Get the extended media interface. */ 7642 pAhciPort->pDrvMediaEx = PDMIBASE_QUERY_INTERFACE(pAhciPort->pDrvBase, PDMIMEDIAEX); 7643 AssertMsgReturn(VALID_PTR(pAhciPort->pDrvMediaEx), 7644 ("AHCI configuration error: LUN#%d misses the extended media interface!\n", pAhciPort->iLUN), 7645 VERR_PDM_MISSING_INTERFACE); 7753 7646 7754 7647 pAhciPort->pDrvMount = PDMIBASE_QUERY_INTERFACE(pAhciPort->pDrvBase, PDMIMOUNT); 7755 7756 /* Try to get the optional async block interface. */7757 pAhciPort->pDrvMediaAsync = PDMIBASE_QUERY_INTERFACE(pAhciPort->pDrvBase, PDMIMEDIAASYNC);7758 7648 7759 7649 /* 7760 7650 * Validate type. 7761 7651 */ 7762 enmType = pAhciPort->pDrvMedia->pfnGetType(pAhciPort->pDrvMedia); 7763 7764 if ( enmType != PDMMEDIATYPE_HARD_DISK 7765 && enmType != PDMMEDIATYPE_CDROM 7766 && enmType != PDMMEDIATYPE_DVD) 7767 { 7768 AssertMsgFailed(("Configuration error: LUN#%d isn't a disk or cd/dvd. enmType=%d\n", pAhciPort->iLUN, enmType)); 7769 return VERR_PDM_UNSUPPORTED_BLOCK_TYPE; 7770 } 7771 7772 if ( (enmType == PDMMEDIATYPE_CDROM || enmType == PDMMEDIATYPE_DVD) 7773 && !pAhciPort->pDrvMount) 7774 { 7775 AssertMsgFailed(("Internal error: CD/DVD-ROM without a mountable interface\n")); 7776 return VERR_INTERNAL_ERROR; 7777 } 7778 pAhciPort->fATAPI = (enmType == PDMMEDIATYPE_CDROM || enmType == PDMMEDIATYPE_DVD); 7779 pAhciPort->fATAPIPassthrough = pAhciPort->fATAPI ? (pAhciPort->pDrvMedia->pfnSendCmd != NULL) : false; 7780 7781 rc = RTCritSectInit(&pAhciPort->CritSectReqsFree); 7652 PDMMEDIATYPE enmType = pAhciPort->pDrvMedia->pfnGetType(pAhciPort->pDrvMedia); 7653 AssertMsgReturn(enmType == PDMMEDIATYPE_HARD_DISK || enmType == PDMMEDIATYPE_CDROM || enmType == PDMMEDIATYPE_DVD, 7654 ("AHCI configuration error: LUN#%d isn't a disk or cd/dvd. enmType=%u\n", pAhciPort->iLUN, enmType), 7655 VERR_PDM_UNSUPPORTED_BLOCK_TYPE); 7656 AssertMsgReturn(enmType == PDMMEDIATYPE_HARD_DISK || pAhciPort->pDrvMount, 7657 ("AHCI configuration error: LUN#%d is CD/DVD-ROM without a mountable interface\n", pAhciPort->iLUN), 7658 VERR_INTERNAL_ERROR); 7659 7660 int rc = pAhciPort->pDrvMediaEx->pfnIoReqAllocSizeSet(pAhciPort->pDrvMediaEx, sizeof(AHCIREQ)); 7782 7661 if (RT_FAILURE(rc)) 7783 7662 return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS, 7784 N_("AHCI initialisation error: Failed to create critical section for free request list")); 7785 7786 pAhciPort->pListReqsFree = (PRTLISTANCHOR)PDMDevHlpMMHeapAllocZ(pDevIns, sizeof(RTLISTANCHOR)); 7787 if (!pAhciPort->pListReqsFree) 7788 return PDMDevHlpVMSetError(pDevIns, VERR_NO_MEMORY, RT_SRC_POS, 7789 N_("AHCI initialisation error: Failed to allocate memory for free request list")); 7790 7791 RTListInit(pAhciPort->pListReqsFree); 7792 7663 N_("AHCI configuration error: LUN#%u: Failed to set I/O request size!"), 7664 pAhciPort->iLUN); 7665 7666 uint32_t fFeatures = 0; 7667 rc = pAhciPort->pDrvMediaEx->pfnQueryFeatures(pAhciPort->pDrvMediaEx, &fFeatures); 7668 if (RT_FAILURE(rc)) 7669 return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS, 7670 N_("AHCI configuration error: LUN#%u: Failed to query features of device"), 7671 pAhciPort->iLUN); 7672 7673 if (fFeatures & PDMIMEDIAEX_FEATURE_F_DISCARD) 7674 pAhciPort->fTrimEnabled = true; 7675 7676 pAhciPort->fATAPI = (enmType == PDMMEDIATYPE_CDROM || enmType == PDMMEDIATYPE_DVD); 7677 pAhciPort->fATAPIPassthrough = pAhciPort->fATAPI ? !!(fFeatures & PDMIMEDIAEX_FEATURE_F_RAWSCSICMD) : false; 7793 7678 if (pAhciPort->fATAPI) 7794 7679 { … … 7834 7719 pAhciPort->PCHSGeometry.cHeads, pAhciPort->PCHSGeometry.cSectors, 7835 7720 pAhciPort->cTotalSectors)); 7836 if (pAhciPort-> pDrvMedia->pfnDiscard)7721 if (pAhciPort->fTrimEnabled) 7837 7722 LogRel(("AHCI: LUN#%d: Enabled TRIM support\n", pAhciPort->iLUN)); 7838 7723 } … … 7853 7738 PAHCI pThis = PDMINS_2_DATA(pDevIns, PAHCI); 7854 7739 ASMAtomicWriteBool(&pThis->fSignalIdle, false); 7855 /*7856 * Free all cached tasks here, not possible on destruct because the driver7857 * is destroyed before us.7858 */7859 for (unsigned iPort = 0; iPort < pThis->cPortsImpl; iPort++)7860 ahciR3PortCachedReqsFree(&pThis->ahciPort[iPort]);7861 7740 return true; 7862 7741 } … … 7873 7752 PDMDevHlpSetAsyncNotification(pDevIns, ahciR3IsAsyncSuspendOrPowerOffDone); 7874 7753 else 7875 {7876 /*7877 * Free all cached tasks here, not possible on destruct because the driver7878 * is destroyed before us.7879 */7880 for (unsigned iPort = 0; iPort < pThis->cPortsImpl; iPort++)7881 ahciR3PortCachedReqsFree(&pThis->ahciPort[iPort]);7882 7883 7754 ASMAtomicWriteBool(&pThis->fSignalIdle, false); 7884 }7885 7755 } 7886 7756 … … 8089 7959 if (pAhciPort->fATAPI) 8090 7960 ahciMediumRemoved(pAhciPort); 8091 8092 /* Free all cached I/O tasks. */8093 ahciR3PortCachedReqsFree(pAhciPort);8094 8095 if (RTCritSectIsInitialized(&pAhciPort->CritSectReqsFree))8096 RTCritSectDelete(&pAhciPort->CritSectReqsFree);8097 8098 if (pAhciPort->pListReqsFree)8099 MMR3HeapFree(pAhciPort->pListReqsFree);8100 8101 pAhciPort->pListReqsFree = NULL;8102 7961 8103 7962 if (!(fFlags & PDM_TACH_FLAGS_NOT_HOT_PLUG)) … … 8126 7985 pAhciPort->pDrvBase = NULL; 8127 7986 pAhciPort->pDrvMedia = NULL; 8128 pAhciPort->pDrvMedia Async= NULL;7987 pAhciPort->pDrvMediaEx = NULL; 8129 7988 } 8130 7989 … … 8152 8011 AssertRelease(!pAhciPort->pDrvBase); 8153 8012 AssertRelease(!pAhciPort->pDrvMedia); 8154 AssertRelease(!pAhciPort->pDrvMedia Async);8013 AssertRelease(!pAhciPort->pDrvMediaEx); 8155 8014 Assert(pAhciPort->iLUN == iLUN); 8156 8015 … … 8187 8046 char szName[24]; 8188 8047 RTStrPrintf(szName, sizeof(szName), "Port%d", iLUN); 8189 8190 if ( pAhciPort->pDrvMediaAsync8191 && !pAhciPort->fATAPI)8192 pAhciPort->fAsyncInterface = true;8193 else8194 pAhciPort->fAsyncInterface = false;8195 8048 8196 8049 rc = SUPSemEventCreate(pThis->pSupDrvSession, &pAhciPort->hEvtProcess); … … 8345 8198 pAhciPort->hEvtProcess = NIL_SUPSEMEVENT; 8346 8199 } 8347 8348 if (RTCritSectIsInitialized(&pAhciPort->CritSectReqsFree))8349 RTCritSectDelete(&pAhciPort->CritSectReqsFree);8350 8351 #ifdef VBOX_STRICT8352 for (uint32_t i = 0; i < AHCI_NR_COMMAND_SLOTS; i++)8353 Assert(!pAhciPort->aActiveTasks[i]);8354 #endif8355 8200 } 8356 8201 … … 8387 8232 "SecondarySlave\0" 8388 8233 "PortCount\0" 8389 "UseAsyncInterfaceIfAvailable\0"8390 8234 "Bootable\0" 8391 8235 "CmdSlotsAvail\0")) … … 8418 8262 N_("AHCI configuration error: PortCount=%u should be at least 1"), 8419 8263 pThis->cPortsImpl); 8420 8421 rc = CFGMR3QueryBoolDef(pCfg, "UseAsyncInterfaceIfAvailable", &pThis->fUseAsyncInterfaceIfAvailable, true);8422 if (RT_FAILURE(rc))8423 return PDMDEV_SET_ERROR(pDevIns, rc,8424 N_("AHCI configuration error: failed to read UseAsyncInterfaceIfAvailable as boolean"));8425 8264 8426 8265 rc = CFGMR3QueryBoolDef(pCfg, "Bootable", &pThis->fBootable, true); … … 8641 8480 * Init interfaces. 8642 8481 */ 8643 pAhciPort->IBase.pfnQueryInterface = ahciR3PortQueryInterface; 8644 pAhciPort->IPortAsync.pfnTransferCompleteNotify = ahciR3TransferCompleteNotify; 8645 pAhciPort->IPort.pfnQueryDeviceLocation = ahciR3PortQueryDeviceLocation; 8646 pAhciPort->IMountNotify.pfnMountNotify = ahciR3MountNotify; 8647 pAhciPort->IMountNotify.pfnUnmountNotify = ahciR3UnmountNotify; 8648 pAhciPort->fWrkThreadSleeping = true; 8482 pAhciPort->IBase.pfnQueryInterface = ahciR3PortQueryInterface; 8483 pAhciPort->IMediaExPort.pfnIoReqCompleteNotify = ahciR3IoReqCompleteNotify; 8484 pAhciPort->IMediaExPort.pfnIoReqCopyFromBuf = ahciR3IoReqCopyFromBuf; 8485 pAhciPort->IMediaExPort.pfnIoReqCopyToBuf = ahciR3IoReqCopyToBuf; 8486 pAhciPort->IMediaExPort.pfnIoReqQueryDiscardRanges = ahciR3IoReqQueryDiscardRanges; 8487 pAhciPort->IMediaExPort.pfnIoReqStateChanged = ahciR3IoReqStateChanged; 8488 pAhciPort->IPort.pfnQueryDeviceLocation = ahciR3PortQueryDeviceLocation; 8489 pAhciPort->IMountNotify.pfnMountNotify = ahciR3MountNotify; 8490 pAhciPort->IMountNotify.pfnUnmountNotify = ahciR3UnmountNotify; 8491 pAhciPort->fWrkThreadSleeping = true; 8649 8492 8650 8493 /* Query per port configuration options if available. */ … … 8681 8524 if (RT_FAILURE(rc)) 8682 8525 return rc; 8683 8684 /*8685 * If the new async interface is available we use a PDMQueue to transmit8686 * the requests into R3.8687 * Otherwise we use a event semaphore and a async I/O thread which processes them.8688 */8689 if (pAhciPort->pDrvMediaAsync && pThis->fUseAsyncInterfaceIfAvailable)8690 {8691 LogRel(("AHCI: LUN#%d: using async I/O\n", pAhciPort->iLUN));8692 pAhciPort->fAsyncInterface = true;8693 }8694 else8695 {8696 LogRel(("AHCI: LUN#%d: using normal I/O\n", pAhciPort->iLUN));8697 pAhciPort->fAsyncInterface = false;8698 }8699 8526 8700 8527 rc = SUPSemEventCreate(pThis->pSupDrvSession, &pAhciPort->hEvtProcess);
Note:
See TracChangeset
for help on using the changeset viewer.