Changeset 24760 in vbox for trunk/src/VBox
- Timestamp:
- Nov 18, 2009 4:05:27 PM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Storage/DevAHCI.cpp
r24750 r24760 2269 2269 #ifdef IN_RING3 2270 2270 2271 static DECLCALLBACK(int) ahci MMIOMap(PPCIDEVICE pPciDev, /*unsigned*/ int iRegion, RTGCPHYS GCPhysAddress, uint32_t cb, PCIADDRESSSPACE enmType)2271 static DECLCALLBACK(int) ahciR3MMIOMap(PPCIDEVICE pPciDev, /*unsigned*/ int iRegion, RTGCPHYS GCPhysAddress, uint32_t cb, PCIADDRESSSPACE enmType) 2272 2272 { 2273 2273 PAHCI pThis = PCIDEV_2_PAHCI(pPciDev); … … 2309 2309 * Map the legacy I/O port ranges to make Solaris work with the controller. 2310 2310 */ 2311 static DECLCALLBACK(int) ahci LegacyFakeIORangeMap(PPCIDEVICE pPciDev, /*unsigned*/ int iRegion, RTGCPHYS GCPhysAddress, uint32_t cb, PCIADDRESSSPACE enmType)2311 static DECLCALLBACK(int) ahciR3LegacyFakeIORangeMap(PPCIDEVICE pPciDev, /*unsigned*/ int iRegion, RTGCPHYS GCPhysAddress, uint32_t cb, PCIADDRESSSPACE enmType) 2312 2312 { 2313 2313 PAHCI pThis = PCIDEV_2_PAHCI(pPciDev); … … 2354 2354 * @param ppLed Where to store the LED pointer. 2355 2355 */ 2356 static DECLCALLBACK(int) ahci Status_QueryStatusLed(PPDMILEDPORTS pInterface, unsigned iLUN, PPDMLED *ppLed)2356 static DECLCALLBACK(int) ahciR3Status_QueryStatusLed(PPDMILEDPORTS pInterface, unsigned iLUN, PPDMLED *ppLed) 2357 2357 { 2358 2358 PAHCI pAhci = PDMILEDPORTS_2_PAHCI(pInterface); … … 2374 2374 * @param enmInterface The requested interface identification. 2375 2375 */ 2376 static DECLCALLBACK(void *) ahci Status_QueryInterface(PPDMIBASE pInterface, PDMINTERFACE enmInterface)2376 static DECLCALLBACK(void *) ahciR3Status_QueryInterface(PPDMIBASE pInterface, PDMINTERFACE enmInterface) 2377 2377 { 2378 2378 PAHCI pAhci = PDMIBASE_2_PAHCI(pInterface); … … 2391 2391 * Query interface method for the AHCI port. 2392 2392 */ 2393 static DECLCALLBACK(void *) ahci PortQueryInterface(PPDMIBASE pInterface, PDMINTERFACE enmInterface)2393 static DECLCALLBACK(void *) ahciR3PortQueryInterface(PPDMIBASE pInterface, PDMINTERFACE enmInterface) 2394 2394 { 2395 2395 PAHCIPort pAhciPort = PDMIBASE_2_PAHCIPORT(pInterface); … … 2407 2407 return NULL; 2408 2408 } 2409 }2410 2411 static DECLCALLBACK(void) ahciRelocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta)2412 {2413 uint32_t i;2414 PAHCI pAhci = PDMINS_2_DATA(pDevIns, PAHCI);2415 2416 pAhci->pDevInsRC += offDelta;2417 pAhci->pHbaCccTimerRC = TMTimerRCPtr(pAhci->pHbaCccTimerR3);2418 pAhci->pNotifierQueueRC = PDMQueueRCPtr(pAhci->pNotifierQueueR3);2419 2420 /* Relocate every port. */2421 for (i = 0; i < RT_ELEMENTS(pAhci->ahciPort); i++)2422 {2423 PAHCIPort pAhciPort = &pAhci->ahciPort[i];2424 pAhciPort->pAhciRC += offDelta;2425 pAhciPort->pDevInsRC += offDelta;2426 }2427 2428 /* Relocate emulated ATA controllers. */2429 for (i = 0; i < RT_ELEMENTS(pAhci->aCts); i++)2430 ataControllerRelocate(&pAhci->aCts[i], offDelta);2431 2409 } 2432 2410 … … 5722 5700 } 5723 5701 5724 /** 5725 * Destroy a driver instance. 5702 /* -=-=-=-=- Helper -=-=-=-=- */ 5703 5704 /** 5705 * Checks if all asynchronous I/O is finished. 5726 5706 * 5727 * Most VM resources are freed by the VM. This callback is provided so that any non-VM 5728 * resources can be freed correctly. 5729 * 5730 * @param pDevIns The device instance data. 5731 */ 5732 static DECLCALLBACK(int) ahciDestruct(PPDMDEVINS pDevIns) 5733 { 5734 PAHCI pAhci = PDMINS_2_DATA(pDevIns, PAHCI); 5735 int rc = VINF_SUCCESS; 5736 unsigned iActPort = 0; 5737 5738 /* 5739 * At this point the async I/O thread is suspended and will not enter 5740 * this module again. So, no coordination is needed here and PDM 5741 * will take care of terminating and cleaning up the thread. 5742 */ 5743 if (PDMCritSectIsInitialized(&pAhci->lock)) 5744 { 5745 TMR3TimerDestroy(pAhci->CTX_SUFF(pHbaCccTimer)); 5746 5747 Log(("%s: Destruct every port\n", __FUNCTION__)); 5748 for (iActPort = 0; iActPort < pAhci->cPortsImpl; iActPort++) 5749 { 5750 PAHCIPort pAhciPort = &pAhci->ahciPort[iActPort]; 5751 5752 if (pAhciPort->pAsyncIOThread) 5753 { 5754 /* Destroy the event semaphore. */ 5755 rc = RTSemEventDestroy(pAhciPort->AsyncIORequestSem); 5756 if (RT_FAILURE(rc)) 5757 { 5758 Log(("%s: Destroying event semaphore for port %d failed rc=%Rrc\n", __FUNCTION__, iActPort, rc)); 5759 } 5760 } 5761 5762 /* Free all cached tasks. */ 5763 for (uint32_t i = 0; i < AHCI_NR_COMMAND_SLOTS; i++) 5764 { 5765 if (pAhciPort->aCachedTasks[i]) 5766 { 5767 if (pAhciPort->aCachedTasks[i]->pSGListHead) 5768 RTMemFree(pAhciPort->aCachedTasks[i]->pSGListHead); 5769 if (pAhciPort->aCachedTasks[i]->paSGEntries) 5770 RTMemFree(pAhciPort->aCachedTasks[i]->paSGEntries); 5771 5772 RTMemFree(pAhciPort->aCachedTasks[i]); 5773 } 5774 } 5775 } 5776 5777 /* Destroy emulated ATA controllers. */ 5778 for (unsigned i = 0; i < RT_ELEMENTS(pAhci->aCts); i++) 5779 ataControllerDestroy(&pAhci->aCts[i]); 5780 5781 PDMR3CritSectDelete(&pAhci->lock); 5782 } 5783 5784 return rc; 5785 } 5786 5787 /** 5788 * Configure the attached device for a port. 5789 * 5790 * @returns VBox status code 5791 * @param pDevIns The device instance data. 5792 * @param pAhciPort The port for which the device is to be configured. 5793 */ 5794 static int ahciConfigureLUN(PPDMDEVINS pDevIns, PAHCIPort pAhciPort) 5795 { 5796 int rc = VINF_SUCCESS; 5797 PDMBLOCKTYPE enmType; 5798 5799 /* 5800 * Query the block and blockbios interfaces. 5801 */ 5802 pAhciPort->pDrvBlock = (PDMIBLOCK *)pAhciPort->pDrvBase->pfnQueryInterface(pAhciPort->pDrvBase, PDMINTERFACE_BLOCK); 5803 if (!pAhciPort->pDrvBlock) 5804 { 5805 AssertMsgFailed(("Configuration error: LUN#%d hasn't a block interface!\n", pAhciPort->iLUN)); 5806 return VERR_PDM_MISSING_INTERFACE; 5807 } 5808 pAhciPort->pDrvBlockBios = (PDMIBLOCKBIOS *)pAhciPort->pDrvBase->pfnQueryInterface(pAhciPort->pDrvBase, PDMINTERFACE_BLOCK_BIOS); 5809 if (!pAhciPort->pDrvBlockBios) 5810 { 5811 AssertMsgFailed(("Configuration error: LUN#%d hasn't a block BIOS interface!\n", pAhciPort->iLUN)); 5812 return VERR_PDM_MISSING_INTERFACE; 5813 } 5814 5815 pAhciPort->pDrvMount = (PDMIMOUNT *)pAhciPort->pDrvBase->pfnQueryInterface(pAhciPort->pDrvBase, PDMINTERFACE_MOUNT); 5816 5817 /* Try to get the optional async block interface. */ 5818 pAhciPort->pDrvBlockAsync = (PDMIBLOCKASYNC *)pAhciPort->pDrvBase->pfnQueryInterface(pAhciPort->pDrvBase, PDMINTERFACE_BLOCK_ASYNC); 5819 5820 /* 5821 * Validate type. 5822 */ 5823 enmType = pAhciPort->pDrvBlock->pfnGetType(pAhciPort->pDrvBlock); 5824 5825 if ( enmType != PDMBLOCKTYPE_HARD_DISK 5826 && enmType != PDMBLOCKTYPE_CDROM 5827 && enmType != PDMBLOCKTYPE_DVD) 5828 { 5829 AssertMsgFailed(("Configuration error: LUN#%d isn't a disk or cd/dvd. enmType=%d\n", pAhciPort->iLUN, enmType)); 5830 return VERR_PDM_UNSUPPORTED_BLOCK_TYPE; 5831 } 5832 5833 if ( (enmType == PDMBLOCKTYPE_CDROM || enmType == PDMBLOCKTYPE_DVD) 5834 && !pAhciPort->pDrvMount) 5835 { 5836 AssertMsgFailed(("Internal error: CD/DVD-ROM without a mountable interface\n")); 5837 return VERR_INTERNAL_ERROR; 5838 } 5839 pAhciPort->fATAPI = (enmType == PDMBLOCKTYPE_CDROM || enmType == PDMBLOCKTYPE_DVD); 5840 5841 if (pAhciPort->fATAPI) 5842 { 5843 pAhciPort->cTotalSectors = pAhciPort->pDrvBlock->pfnGetSize(pAhciPort->pDrvBlock) / 2048; 5844 pAhciPort->PCHSGeometry.cCylinders = 0; 5845 pAhciPort->PCHSGeometry.cHeads = 0; 5846 pAhciPort->PCHSGeometry.cSectors = 0; 5847 LogRel(("AHCI LUN#%d: CD/DVD, total number of sectors %Ld\n", pAhciPort->iLUN, pAhciPort->cTotalSectors)); 5848 } 5849 else 5850 { 5851 pAhciPort->cTotalSectors = pAhciPort->pDrvBlock->pfnGetSize(pAhciPort->pDrvBlock) / 512; 5852 rc = pAhciPort->pDrvBlockBios->pfnGetPCHSGeometry(pAhciPort->pDrvBlockBios, 5853 &pAhciPort->PCHSGeometry); 5854 if (rc == VERR_PDM_MEDIA_NOT_MOUNTED) 5855 { 5856 pAhciPort->PCHSGeometry.cCylinders = 0; 5857 pAhciPort->PCHSGeometry.cHeads = 16; /*??*/ 5858 pAhciPort->PCHSGeometry.cSectors = 63; /*??*/ 5859 } 5860 else if (rc == VERR_PDM_GEOMETRY_NOT_SET) 5861 { 5862 pAhciPort->PCHSGeometry.cCylinders = 0; /* autodetect marker */ 5863 rc = VINF_SUCCESS; 5864 } 5865 AssertRC(rc); 5866 5867 if ( pAhciPort->PCHSGeometry.cCylinders == 0 5868 || pAhciPort->PCHSGeometry.cHeads == 0 5869 || pAhciPort->PCHSGeometry.cSectors == 0) 5870 { 5871 uint64_t cCylinders = pAhciPort->cTotalSectors / (16 * 63); 5872 pAhciPort->PCHSGeometry.cCylinders = RT_MAX(RT_MIN(cCylinders, 16383), 1); 5873 pAhciPort->PCHSGeometry.cHeads = 16; 5874 pAhciPort->PCHSGeometry.cSectors = 63; 5875 /* Set the disk geometry information. Ignore errors. */ 5876 pAhciPort->pDrvBlockBios->pfnSetPCHSGeometry(pAhciPort->pDrvBlockBios, 5877 &pAhciPort->PCHSGeometry); 5878 rc = VINF_SUCCESS; 5879 } 5880 LogRel(("AHCI: LUN#%d: disk, PCHS=%u/%u/%u, total number of sectors %Ld\n", 5881 pAhciPort->iLUN, pAhciPort->PCHSGeometry.cCylinders, 5882 pAhciPort->PCHSGeometry.cHeads, pAhciPort->PCHSGeometry.cSectors, 5883 pAhciPort->cTotalSectors)); 5884 } 5885 return rc; 5886 } 5887 5888 /** 5889 * Checks if all asynchronous I/O is finished. 5707 * Used by ahciR3Reset, ahciR3Suspend and ahciR3PowerOff. ahciR3SavePrep makes 5708 * use of it in strict builds (which is why it's up here). 5890 5709 * 5891 5710 * @returns true if quiesced, false if busy. … … 5913 5732 } 5914 5733 5915 static DECLCALLBACK(int) ahciSavePrep(PPDMDEVINS pDevIns, PSSMHANDLE pSSM) 5734 /* -=-=-=-=- Saved State -=-=-=-=- */ 5735 5736 /** 5737 * @copydoc FNDEVSSMSAVEPREP 5738 */ 5739 static DECLCALLBACK(int) ahciR3SavePrep(PPDMDEVINS pDevIns, PSSMHANDLE pSSM) 5916 5740 { 5917 5741 PAHCI pAhci = PDMINS_2_DATA(pDevIns, PAHCI); … … 5931 5755 } 5932 5756 5933 static DECLCALLBACK(int) ahciLoadPrep(PPDMDEVINS pDevIns, PSSMHANDLE pSSM) 5757 /** 5758 * @copydoc FNDEVSSMLOADPREP 5759 */ 5760 static DECLCALLBACK(int) ahciR3LoadPrep(PPDMDEVINS pDevIns, PSSMHANDLE pSSM) 5934 5761 { 5935 5762 PAHCI pAhci = PDMINS_2_DATA(pDevIns, PAHCI); … … 5948 5775 5949 5776 /** 5950 * Callback employed by ahciSuspend and ahciPowerOff..5951 *5952 * @returns true if we've quiesced, false if we're still working.5953 * @param pDevIns The device instance.5954 */5955 static DECLCALLBACK(bool) ahciR3IsAsyncSuspendOrPowerOffDone(PPDMDEVINS pDevIns)5956 {5957 if (!ahciR3AllAsyncIOIsFinished(pDevIns))5958 return false;5959 5960 PAHCI pThis = PDMINS_2_DATA(pDevIns, PAHCI);5961 ASMAtomicWriteBool(&pThis->fSignalIdle, false);5962 return true;5963 }5964 5965 /**5966 * Common worker for ahciSuspend and ahciPowerOff.5967 */5968 static void ahciR3SuspendOrPowerOff(PPDMDEVINS pDevIns)5969 {5970 PAHCI pThis = PDMINS_2_DATA(pDevIns, PAHCI);5971 5972 ASMAtomicWriteBool(&pThis->fSignalIdle, true);5973 if (!ahciR3AllAsyncIOIsFinished(pDevIns))5974 PDMDevHlpSetAsyncNotification(pDevIns, ahciR3IsAsyncSuspendOrPowerOffDone);5975 else5976 ASMAtomicWriteBool(&pThis->fSignalIdle, false);5977 }5978 5979 /**5980 * Suspend notification.5981 *5982 * @returns VBox status.5983 * @param pDevIns The device instance data.5984 */5985 static DECLCALLBACK(void) ahciSuspend(PPDMDEVINS pDevIns)5986 {5987 PAHCI pAhci = PDMINS_2_DATA(pDevIns, PAHCI);5988 Log(("%s:\n", __FUNCTION__));5989 5990 ahciR3SuspendOrPowerOff(pDevIns);5991 5992 for (uint32_t i = 0; i < RT_ELEMENTS(pAhci->aCts); i++)5993 ataControllerSuspend(&pAhci->aCts[i]);5994 }5995 5996 /**5997 * Resume notification.5998 *5999 * @param pDevIns The device instance data.6000 */6001 static DECLCALLBACK(void) ahciResume(PPDMDEVINS pDevIns)6002 {6003 PAHCI pAhci = PDMINS_2_DATA(pDevIns, PAHCI);6004 6005 Log(("%s:\n", __FUNCTION__));6006 for (uint32_t i = 0; i < RT_ELEMENTS(pAhci->aCts); i++)6007 ataControllerResume(&pAhci->aCts[i]);6008 return;6009 }6010 6011 /**6012 5777 * @copydoc FNDEVSSMLIVEEXEC 6013 5778 */ 6014 static DECLCALLBACK(int) ahci LiveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uPass)5779 static DECLCALLBACK(int) ahciR3LiveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uPass) 6015 5780 { 6016 5781 PAHCI pThis = PDMINS_2_DATA(pDevIns, PAHCI); … … 6041 5806 * @copydoc FNDEVSSMSAVEEXEC 6042 5807 */ 6043 static DECLCALLBACK(int) ahci SaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)5808 static DECLCALLBACK(int) ahciR3SaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM) 6044 5809 { 6045 5810 PAHCI pThis = PDMINS_2_DATA(pDevIns, PAHCI); … … 6050 5815 6051 5816 /* The config */ 6052 rc = ahci LiveExec(pDevIns, pSSM, SSM_PASS_FINAL);5817 rc = ahciR3LiveExec(pDevIns, pSSM, SSM_PASS_FINAL); 6053 5818 AssertRCReturn(rc, rc); 6054 5819 … … 6128 5893 * @param uPass The data pass. 6129 5894 */ 6130 static DECLCALLBACK(int) ahci LoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)5895 static DECLCALLBACK(int) ahciR3LoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass) 6131 5896 { 6132 5897 PAHCI pThis = PDMINS_2_DATA(pDevIns, PAHCI); … … 6280 6045 } 6281 6046 6047 /* -=-=-=-=- device PDM interface -=-=-=-=- */ 6048 6049 static DECLCALLBACK(void) ahciR3Relocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta) 6050 { 6051 uint32_t i; 6052 PAHCI pAhci = PDMINS_2_DATA(pDevIns, PAHCI); 6053 6054 pAhci->pDevInsRC += offDelta; 6055 pAhci->pHbaCccTimerRC = TMTimerRCPtr(pAhci->pHbaCccTimerR3); 6056 pAhci->pNotifierQueueRC = PDMQueueRCPtr(pAhci->pNotifierQueueR3); 6057 6058 /* Relocate every port. */ 6059 for (i = 0; i < RT_ELEMENTS(pAhci->ahciPort); i++) 6060 { 6061 PAHCIPort pAhciPort = &pAhci->ahciPort[i]; 6062 pAhciPort->pAhciRC += offDelta; 6063 pAhciPort->pDevInsRC += offDelta; 6064 } 6065 6066 /* Relocate emulated ATA controllers. */ 6067 for (i = 0; i < RT_ELEMENTS(pAhci->aCts); i++) 6068 ataControllerRelocate(&pAhci->aCts[i], offDelta); 6069 } 6070 6071 /** 6072 * Destroy a driver instance. 6073 * 6074 * Most VM resources are freed by the VM. This callback is provided so that any non-VM 6075 * resources can be freed correctly. 6076 * 6077 * @param pDevIns The device instance data. 6078 */ 6079 static DECLCALLBACK(int) ahciR3Destruct(PPDMDEVINS pDevIns) 6080 { 6081 PAHCI pAhci = PDMINS_2_DATA(pDevIns, PAHCI); 6082 int rc = VINF_SUCCESS; 6083 unsigned iActPort = 0; 6084 6085 /* 6086 * At this point the async I/O thread is suspended and will not enter 6087 * this module again. So, no coordination is needed here and PDM 6088 * will take care of terminating and cleaning up the thread. 6089 */ 6090 if (PDMCritSectIsInitialized(&pAhci->lock)) 6091 { 6092 TMR3TimerDestroy(pAhci->CTX_SUFF(pHbaCccTimer)); 6093 6094 Log(("%s: Destruct every port\n", __FUNCTION__)); 6095 for (iActPort = 0; iActPort < pAhci->cPortsImpl; iActPort++) 6096 { 6097 PAHCIPort pAhciPort = &pAhci->ahciPort[iActPort]; 6098 6099 if (pAhciPort->pAsyncIOThread) 6100 { 6101 /* Destroy the event semaphore. */ 6102 rc = RTSemEventDestroy(pAhciPort->AsyncIORequestSem); 6103 if (RT_FAILURE(rc)) 6104 { 6105 Log(("%s: Destroying event semaphore for port %d failed rc=%Rrc\n", __FUNCTION__, iActPort, rc)); 6106 } 6107 } 6108 6109 /* Free all cached tasks. */ 6110 for (uint32_t i = 0; i < AHCI_NR_COMMAND_SLOTS; i++) 6111 { 6112 if (pAhciPort->aCachedTasks[i]) 6113 { 6114 if (pAhciPort->aCachedTasks[i]->pSGListHead) 6115 RTMemFree(pAhciPort->aCachedTasks[i]->pSGListHead); 6116 if (pAhciPort->aCachedTasks[i]->paSGEntries) 6117 RTMemFree(pAhciPort->aCachedTasks[i]->paSGEntries); 6118 6119 RTMemFree(pAhciPort->aCachedTasks[i]); 6120 } 6121 } 6122 } 6123 6124 /* Destroy emulated ATA controllers. */ 6125 for (unsigned i = 0; i < RT_ELEMENTS(pAhci->aCts); i++) 6126 ataControllerDestroy(&pAhci->aCts[i]); 6127 6128 PDMR3CritSectDelete(&pAhci->lock); 6129 } 6130 6131 return rc; 6132 } 6133 6134 /** 6135 * Configure the attached device for a port. 6136 * 6137 * Used by ahciR3Construct and ahciR3Attach. 6138 * 6139 * @returns VBox status code 6140 * @param pDevIns The device instance data. 6141 * @param pAhciPort The port for which the device is to be configured. 6142 */ 6143 static int ahciR3ConfigureLUN(PPDMDEVINS pDevIns, PAHCIPort pAhciPort) 6144 { 6145 int rc = VINF_SUCCESS; 6146 PDMBLOCKTYPE enmType; 6147 6148 /* 6149 * Query the block and blockbios interfaces. 6150 */ 6151 pAhciPort->pDrvBlock = (PDMIBLOCK *)pAhciPort->pDrvBase->pfnQueryInterface(pAhciPort->pDrvBase, PDMINTERFACE_BLOCK); 6152 if (!pAhciPort->pDrvBlock) 6153 { 6154 AssertMsgFailed(("Configuration error: LUN#%d hasn't a block interface!\n", pAhciPort->iLUN)); 6155 return VERR_PDM_MISSING_INTERFACE; 6156 } 6157 pAhciPort->pDrvBlockBios = (PDMIBLOCKBIOS *)pAhciPort->pDrvBase->pfnQueryInterface(pAhciPort->pDrvBase, PDMINTERFACE_BLOCK_BIOS); 6158 if (!pAhciPort->pDrvBlockBios) 6159 { 6160 AssertMsgFailed(("Configuration error: LUN#%d hasn't a block BIOS interface!\n", pAhciPort->iLUN)); 6161 return VERR_PDM_MISSING_INTERFACE; 6162 } 6163 6164 pAhciPort->pDrvMount = (PDMIMOUNT *)pAhciPort->pDrvBase->pfnQueryInterface(pAhciPort->pDrvBase, PDMINTERFACE_MOUNT); 6165 6166 /* Try to get the optional async block interface. */ 6167 pAhciPort->pDrvBlockAsync = (PDMIBLOCKASYNC *)pAhciPort->pDrvBase->pfnQueryInterface(pAhciPort->pDrvBase, PDMINTERFACE_BLOCK_ASYNC); 6168 6169 /* 6170 * Validate type. 6171 */ 6172 enmType = pAhciPort->pDrvBlock->pfnGetType(pAhciPort->pDrvBlock); 6173 6174 if ( enmType != PDMBLOCKTYPE_HARD_DISK 6175 && enmType != PDMBLOCKTYPE_CDROM 6176 && enmType != PDMBLOCKTYPE_DVD) 6177 { 6178 AssertMsgFailed(("Configuration error: LUN#%d isn't a disk or cd/dvd. enmType=%d\n", pAhciPort->iLUN, enmType)); 6179 return VERR_PDM_UNSUPPORTED_BLOCK_TYPE; 6180 } 6181 6182 if ( (enmType == PDMBLOCKTYPE_CDROM || enmType == PDMBLOCKTYPE_DVD) 6183 && !pAhciPort->pDrvMount) 6184 { 6185 AssertMsgFailed(("Internal error: CD/DVD-ROM without a mountable interface\n")); 6186 return VERR_INTERNAL_ERROR; 6187 } 6188 pAhciPort->fATAPI = (enmType == PDMBLOCKTYPE_CDROM || enmType == PDMBLOCKTYPE_DVD); 6189 6190 if (pAhciPort->fATAPI) 6191 { 6192 pAhciPort->cTotalSectors = pAhciPort->pDrvBlock->pfnGetSize(pAhciPort->pDrvBlock) / 2048; 6193 pAhciPort->PCHSGeometry.cCylinders = 0; 6194 pAhciPort->PCHSGeometry.cHeads = 0; 6195 pAhciPort->PCHSGeometry.cSectors = 0; 6196 LogRel(("AHCI LUN#%d: CD/DVD, total number of sectors %Ld\n", pAhciPort->iLUN, pAhciPort->cTotalSectors)); 6197 } 6198 else 6199 { 6200 pAhciPort->cTotalSectors = pAhciPort->pDrvBlock->pfnGetSize(pAhciPort->pDrvBlock) / 512; 6201 rc = pAhciPort->pDrvBlockBios->pfnGetPCHSGeometry(pAhciPort->pDrvBlockBios, 6202 &pAhciPort->PCHSGeometry); 6203 if (rc == VERR_PDM_MEDIA_NOT_MOUNTED) 6204 { 6205 pAhciPort->PCHSGeometry.cCylinders = 0; 6206 pAhciPort->PCHSGeometry.cHeads = 16; /*??*/ 6207 pAhciPort->PCHSGeometry.cSectors = 63; /*??*/ 6208 } 6209 else if (rc == VERR_PDM_GEOMETRY_NOT_SET) 6210 { 6211 pAhciPort->PCHSGeometry.cCylinders = 0; /* autodetect marker */ 6212 rc = VINF_SUCCESS; 6213 } 6214 AssertRC(rc); 6215 6216 if ( pAhciPort->PCHSGeometry.cCylinders == 0 6217 || pAhciPort->PCHSGeometry.cHeads == 0 6218 || pAhciPort->PCHSGeometry.cSectors == 0) 6219 { 6220 uint64_t cCylinders = pAhciPort->cTotalSectors / (16 * 63); 6221 pAhciPort->PCHSGeometry.cCylinders = RT_MAX(RT_MIN(cCylinders, 16383), 1); 6222 pAhciPort->PCHSGeometry.cHeads = 16; 6223 pAhciPort->PCHSGeometry.cSectors = 63; 6224 /* Set the disk geometry information. Ignore errors. */ 6225 pAhciPort->pDrvBlockBios->pfnSetPCHSGeometry(pAhciPort->pDrvBlockBios, 6226 &pAhciPort->PCHSGeometry); 6227 rc = VINF_SUCCESS; 6228 } 6229 LogRel(("AHCI: LUN#%d: disk, PCHS=%u/%u/%u, total number of sectors %Ld\n", 6230 pAhciPort->iLUN, pAhciPort->PCHSGeometry.cCylinders, 6231 pAhciPort->PCHSGeometry.cHeads, pAhciPort->PCHSGeometry.cSectors, 6232 pAhciPort->cTotalSectors)); 6233 } 6234 return rc; 6235 } 6236 6237 /** 6238 * Callback employed by ahciR3Suspend and ahciR3PowerOff.. 6239 * 6240 * @returns true if we've quiesced, false if we're still working. 6241 * @param pDevIns The device instance. 6242 */ 6243 static DECLCALLBACK(bool) ahciR3IsAsyncSuspendOrPowerOffDone(PPDMDEVINS pDevIns) 6244 { 6245 if (!ahciR3AllAsyncIOIsFinished(pDevIns)) 6246 return false; 6247 6248 PAHCI pThis = PDMINS_2_DATA(pDevIns, PAHCI); 6249 ASMAtomicWriteBool(&pThis->fSignalIdle, false); 6250 return true; 6251 } 6252 6253 /** 6254 * Common worker for ahciR3Suspend and ahciR3PowerOff. 6255 */ 6256 static void ahciR3SuspendOrPowerOff(PPDMDEVINS pDevIns) 6257 { 6258 PAHCI pThis = PDMINS_2_DATA(pDevIns, PAHCI); 6259 6260 ASMAtomicWriteBool(&pThis->fSignalIdle, true); 6261 if (!ahciR3AllAsyncIOIsFinished(pDevIns)) 6262 PDMDevHlpSetAsyncNotification(pDevIns, ahciR3IsAsyncSuspendOrPowerOffDone); 6263 else 6264 ASMAtomicWriteBool(&pThis->fSignalIdle, false); 6265 } 6266 6267 /** 6268 * Suspend notification. 6269 * 6270 * @returns VBox status. 6271 * @param pDevIns The device instance data. 6272 */ 6273 static DECLCALLBACK(void) ahciR3Suspend(PPDMDEVINS pDevIns) 6274 { 6275 PAHCI pAhci = PDMINS_2_DATA(pDevIns, PAHCI); 6276 Log(("%s:\n", __FUNCTION__)); 6277 6278 ahciR3SuspendOrPowerOff(pDevIns); 6279 6280 for (uint32_t i = 0; i < RT_ELEMENTS(pAhci->aCts); i++) 6281 ataControllerSuspend(&pAhci->aCts[i]); 6282 } 6283 6284 /** 6285 * Resume notification. 6286 * 6287 * @param pDevIns The device instance data. 6288 */ 6289 static DECLCALLBACK(void) ahciR3Resume(PPDMDEVINS pDevIns) 6290 { 6291 PAHCI pAhci = PDMINS_2_DATA(pDevIns, PAHCI); 6292 6293 Log(("%s:\n", __FUNCTION__)); 6294 for (uint32_t i = 0; i < RT_ELEMENTS(pAhci->aCts); i++) 6295 ataControllerResume(&pAhci->aCts[i]); 6296 return; 6297 } 6298 6282 6299 /** 6283 6300 * Detach notification. … … 6290 6307 * @param fFlags Flags, combination of the PDMDEVATT_FLAGS_* \#defines. 6291 6308 */ 6292 static DECLCALLBACK(void) ahci Detach(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t fFlags)6309 static DECLCALLBACK(void) ahciR3Detach(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t fFlags) 6293 6310 { 6294 6311 PAHCI pAhci = PDMINS_2_DATA(pDevIns, PAHCI); … … 6333 6350 * @param fFlags Flags, combination of the PDMDEVATT_FLAGS_* \#defines. 6334 6351 */ 6335 static DECLCALLBACK(int) ahci Attach(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t fFlags)6352 static DECLCALLBACK(int) ahciR3Attach(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t fFlags) 6336 6353 { 6337 6354 PAHCI pAhci = PDMINS_2_DATA(pDevIns, PAHCI); … … 6354 6371 rc = PDMDevHlpDriverAttach(pDevIns, pAhciPort->iLUN, &pAhciPort->IBase, &pAhciPort->pDrvBase, NULL); 6355 6372 if (RT_SUCCESS(rc)) 6356 rc = ahci ConfigureLUN(pDevIns, pAhciPort);6373 rc = ahciR3ConfigureLUN(pDevIns, pAhciPort); 6357 6374 else 6358 6375 AssertMsgFailed(("Failed to attach LUN#%d. rc=%Rrc\n", pAhciPort->iLUN, rc)); … … 6419 6436 6420 6437 /** 6421 * Callback employed by ahciR eset.6438 * Callback employed by ahciR3Reset. 6422 6439 * 6423 6440 * @returns true if we've quiesced, false if we're still working. … … 6441 6458 * @param pDevIns The device instance data. 6442 6459 */ 6443 static DECLCALLBACK(void) ahciR eset(PPDMDEVINS pDevIns)6460 static DECLCALLBACK(void) ahciR3Reset(PPDMDEVINS pDevIns) 6444 6461 { 6445 6462 PAHCI pThis = PDMINS_2_DATA(pDevIns, PAHCI); … … 6461 6478 * @param pDevIns Pointer to the device instance 6462 6479 */ 6463 static DECLCALLBACK(void) ahci PowerOff(PPDMDEVINS pDevIns)6480 static DECLCALLBACK(void) ahciR3PowerOff(PPDMDEVINS pDevIns) 6464 6481 { 6465 6482 PAHCI pAhci = PDMINS_2_DATA(pDevIns, PAHCI); … … 6484 6501 * iInstance it's expected to be used a bit in this function. 6485 6502 */ 6486 static DECLCALLBACK(int) ahci Construct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfgHandle)6503 static DECLCALLBACK(int) ahciR3Construct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfgHandle) 6487 6504 { 6488 6505 PAHCI pThis = PDMINS_2_DATA(pDevIns, PAHCI); … … 6598 6615 * to switch to it which also changes device Id and other things in the PCI configuration space). 6599 6616 */ 6600 rc = PDMDevHlpPCIIORegionRegister(pDevIns, 0, 8, PCI_ADDRESS_SPACE_IO, ahci LegacyFakeIORangeMap);6617 rc = PDMDevHlpPCIIORegionRegister(pDevIns, 0, 8, PCI_ADDRESS_SPACE_IO, ahciR3LegacyFakeIORangeMap); 6601 6618 if (RT_FAILURE(rc)) 6602 6619 return PDMDEV_SET_ERROR(pDevIns, rc, 6603 6620 N_("AHCI cannot register PCI I/O region")); 6604 6621 6605 rc = PDMDevHlpPCIIORegionRegister(pDevIns, 1, 1, PCI_ADDRESS_SPACE_IO, ahci LegacyFakeIORangeMap);6622 rc = PDMDevHlpPCIIORegionRegister(pDevIns, 1, 1, PCI_ADDRESS_SPACE_IO, ahciR3LegacyFakeIORangeMap); 6606 6623 if (RT_FAILURE(rc)) 6607 6624 return PDMDEV_SET_ERROR(pDevIns, rc, 6608 6625 N_("AHCI cannot register PCI I/O region")); 6609 6626 6610 rc = PDMDevHlpPCIIORegionRegister(pDevIns, 2, 8, PCI_ADDRESS_SPACE_IO, ahci LegacyFakeIORangeMap);6627 rc = PDMDevHlpPCIIORegionRegister(pDevIns, 2, 8, PCI_ADDRESS_SPACE_IO, ahciR3LegacyFakeIORangeMap); 6611 6628 if (RT_FAILURE(rc)) 6612 6629 return PDMDEV_SET_ERROR(pDevIns, rc, 6613 6630 N_("AHCI cannot register PCI I/O region")); 6614 6631 6615 rc = PDMDevHlpPCIIORegionRegister(pDevIns, 3, 1, PCI_ADDRESS_SPACE_IO, ahci LegacyFakeIORangeMap);6632 rc = PDMDevHlpPCIIORegionRegister(pDevIns, 3, 1, PCI_ADDRESS_SPACE_IO, ahciR3LegacyFakeIORangeMap); 6616 6633 if (RT_FAILURE(rc)) 6617 6634 return PDMDEV_SET_ERROR(pDevIns, rc, 6618 6635 N_("AHCI cannot register PCI I/O region")); 6619 6636 6620 rc = PDMDevHlpPCIIORegionRegister(pDevIns, 4, 0x10, PCI_ADDRESS_SPACE_IO, ahci LegacyFakeIORangeMap);6637 rc = PDMDevHlpPCIIORegionRegister(pDevIns, 4, 0x10, PCI_ADDRESS_SPACE_IO, ahciR3LegacyFakeIORangeMap); 6621 6638 if (RT_FAILURE(rc)) 6622 6639 return PDMDEV_SET_ERROR(pDevIns, rc, 6623 6640 N_("AHCI cannot register PCI I/O region for BMDMA")); 6624 6641 6625 rc = PDMDevHlpPCIIORegionRegister(pDevIns, 5, 4352, PCI_ADDRESS_SPACE_MEM, ahci MMIOMap);6642 rc = PDMDevHlpPCIIORegionRegister(pDevIns, 5, 4352, PCI_ADDRESS_SPACE_MEM, ahciR3MMIOMap); 6626 6643 if (RT_FAILURE(rc)) 6627 6644 return PDMDEV_SET_ERROR(pDevIns, rc, … … 6647 6664 6648 6665 /* Status LUN. */ 6649 pThis->IBase.pfnQueryInterface = ahci Status_QueryInterface;6650 pThis->ILeds.pfnQueryStatusLed = ahci Status_QueryStatusLed;6666 pThis->IBase.pfnQueryInterface = ahciR3Status_QueryInterface; 6667 pThis->ILeds.pfnQueryStatusLed = ahciR3Status_QueryStatusLed; 6651 6668 6652 6669 /* … … 6710 6727 * Init interfaces. 6711 6728 */ 6712 pAhciPort->IBase.pfnQueryInterface = ahci PortQueryInterface;6729 pAhciPort->IBase.pfnQueryInterface = ahciR3PortQueryInterface; 6713 6730 pAhciPort->IPortAsync.pfnTransferCompleteNotify = ahciTransferCompleteNotify; 6714 6731 pAhciPort->IMountNotify.pfnMountNotify = ahciMountNotify; … … 6722 6739 if (RT_SUCCESS(rc)) 6723 6740 { 6724 rc = ahci ConfigureLUN(pDevIns, pAhciPort);6741 rc = ahciR3ConfigureLUN(pDevIns, pAhciPort); 6725 6742 if (RT_FAILURE(rc)) 6726 6743 { … … 6972 6989 6973 6990 rc = PDMDevHlpSSMRegisterEx(pDevIns, AHCI_SAVED_STATE_VERSION, sizeof(*pThis)+cbTotalBufferSize, NULL, 6974 NULL, ahciLiveExec, NULL,6975 ahci SavePrep, ahciSaveExec, NULL,6976 ahci LoadPrep, ahciLoadExec, NULL);6991 NULL, ahciR3LiveExec, NULL, 6992 ahciR3SavePrep, ahciR3SaveExec, NULL, 6993 ahciR3LoadPrep, ahciR3LoadExec, NULL); 6977 6994 if (RT_FAILURE(rc)) 6978 6995 return rc; … … 7006 7023 sizeof(AHCI), 7007 7024 /* pfnConstruct */ 7008 ahci Construct,7025 ahciR3Construct, 7009 7026 /* pfnDestruct */ 7010 ahci Destruct,7027 ahciR3Destruct, 7011 7028 /* pfnRelocate */ 7012 ahciR elocate,7029 ahciR3Relocate, 7013 7030 /* pfnIOCtl */ 7014 7031 NULL, … … 7016 7033 NULL, 7017 7034 /* pfnReset */ 7018 ahciR eset,7035 ahciR3Reset, 7019 7036 /* pfnSuspend */ 7020 ahci Suspend,7037 ahciR3Suspend, 7021 7038 /* pfnResume */ 7022 ahciR esume,7039 ahciR3Resume, 7023 7040 /* pfnAttach */ 7024 ahci Attach,7041 ahciR3Attach, 7025 7042 /* pfnDetach */ 7026 ahci Detach,7043 ahciR3Detach, 7027 7044 /* pfnQueryInterface. */ 7028 7045 NULL, … … 7030 7047 NULL, 7031 7048 /* pfnPowerOff */ 7032 ahci PowerOff,7049 ahciR3PowerOff, 7033 7050 /* pfnSoftReset */ 7034 7051 NULL,
Note:
See TracChangeset
for help on using the changeset viewer.