Changeset 36878 in vbox
- Timestamp:
- Apr 28, 2011 7:48:01 PM (14 years ago)
- svn:sync-xref-src-repo-rev:
- 71456
- Location:
- trunk/src/VBox/Devices
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Storage/DevAHCI.cpp
r36800 r36878 580 580 /** Base address of the MMIO region. */ 581 581 RTGCPHYS MMIOBase; 582 /** Base address of the I/O port region for Idx/Data. */ 583 RTIOPORT IOPortBase; 582 584 583 585 /** Global Host Control register of the HBA */ … … 597 599 /** Command completion coalescing ports */ 598 600 uint32_t regHbaCccPorts; 601 602 /** Index register for BIOS access. */ 603 uint32_t regIdx; 599 604 600 605 #if HC_ARCH_BITS == 64 … … 2037 2042 2038 2043 /** 2044 * Reads from a AHCI controller register. 2045 * 2046 * @returns VBox status code. 2047 * 2048 * @param pAhci The AHCI instance. 2049 * @param uReg The register to write. 2050 * @param pv Where to store the result. 2051 * @param cb Number of bytes read. 2052 */ 2053 static int ahciRegisterRead(PAHCI pAhci, uint32_t uReg, void *pv, unsigned cb) 2054 { 2055 int rc = VINF_SUCCESS; 2056 uint32_t iReg; 2057 2058 /* 2059 * If the access offset is smaller than AHCI_HBA_GLOBAL_SIZE the guest accesses the global registers. 2060 * Otherwise it accesses the registers of a port. 2061 */ 2062 if (uReg < AHCI_HBA_GLOBAL_SIZE) 2063 { 2064 iReg = uReg >> 2; 2065 Log3(("%s: Trying to read from global register %u\n", __FUNCTION__, iReg)); 2066 if (iReg < RT_ELEMENTS(g_aOpRegs)) 2067 { 2068 const AHCIOPREG *pReg = &g_aOpRegs[iReg]; 2069 rc = pReg->pfnRead(pAhci, iReg, (uint32_t *)pv); 2070 } 2071 else 2072 { 2073 Log3(("%s: Trying to read global register %u/%u!!!\n", __FUNCTION__, iReg, RT_ELEMENTS(g_aOpRegs))); 2074 *(uint32_t *)pv = 0; 2075 } 2076 } 2077 else 2078 { 2079 uint32_t iRegOffset; 2080 uint32_t iPort; 2081 2082 /* Calculate accessed port. */ 2083 uReg -= AHCI_HBA_GLOBAL_SIZE; 2084 iPort = uReg / AHCI_PORT_REGISTER_SIZE; 2085 iRegOffset = (uReg % AHCI_PORT_REGISTER_SIZE); 2086 iReg = iRegOffset >> 2; 2087 2088 Log3(("%s: Trying to read from port %u and register %u\n", __FUNCTION__, iPort, iReg)); 2089 2090 if (RT_LIKELY( iPort < pAhci->cPortsImpl 2091 && iReg < RT_ELEMENTS(g_aPortOpRegs))) 2092 { 2093 const AHCIPORTOPREG *pPortReg = &g_aPortOpRegs[iReg]; 2094 rc = pPortReg->pfnRead(pAhci, &pAhci->ahciPort[iPort], iReg, (uint32_t *)pv); 2095 } 2096 else 2097 { 2098 Log3(("%s: Trying to read port %u register %u/%u!!!\n", __FUNCTION__, iPort, iReg, RT_ELEMENTS(g_aPortOpRegs))); 2099 rc = VINF_IOM_MMIO_UNUSED_00; 2100 } 2101 2102 /* 2103 * Windows Vista tries to read one byte from some registers instead of four. 2104 * Correct the value according to the read size. 2105 */ 2106 if (RT_SUCCESS(rc) && cb != sizeof(uint32_t)) 2107 { 2108 switch (cb) 2109 { 2110 case 1: 2111 { 2112 uint8_t uNewValue; 2113 uint8_t *p = (uint8_t *)pv; 2114 2115 iRegOffset &= 3; 2116 Log3(("%s: iRegOffset=%u\n", __FUNCTION__, iRegOffset)); 2117 uNewValue = p[iRegOffset]; 2118 /* Clear old value */ 2119 *(uint32_t *)pv = 0; 2120 *(uint8_t *)pv = uNewValue; 2121 break; 2122 } 2123 default: 2124 AssertMsgFailed(("%s: unsupported access width cb=%d iPort=%x iRegOffset=%x iReg=%x!!!\n", 2125 __FUNCTION__, cb, iPort, iRegOffset, iReg)); 2126 } 2127 } 2128 } 2129 2130 return rc; 2131 } 2132 2133 /** 2134 * Writes a value to one of the AHCI controller registers. 2135 * 2136 * @returns VBox status code. 2137 * 2138 * @param pAhci The AHCI instance. 2139 * @param uReg The register to write. 2140 * @param pv Where to fetch the result. 2141 * @param cb Number of bytes to write. 2142 */ 2143 static int ahciRegisterWrite(PAHCI pAhci, uint32_t uReg, void *pv, unsigned cb) 2144 { 2145 int rc = VINF_SUCCESS; 2146 uint32_t iReg; 2147 2148 if (uReg < AHCI_HBA_GLOBAL_SIZE) 2149 { 2150 Log3(("Write global HBA register\n")); 2151 iReg = uReg >> 2; 2152 if (iReg < RT_ELEMENTS(g_aOpRegs)) 2153 { 2154 const AHCIOPREG *pReg = &g_aOpRegs[iReg]; 2155 rc = pReg->pfnWrite(pAhci, iReg, *(uint32_t *)pv); 2156 } 2157 else 2158 { 2159 Log3(("%s: Trying to write global register %u/%u!!!\n", __FUNCTION__, iReg, RT_ELEMENTS(g_aOpRegs))); 2160 rc = VINF_SUCCESS; 2161 } 2162 } 2163 else 2164 { 2165 uint32_t iPort; 2166 Log3(("Write Port register\n")); 2167 /* Calculate accessed port. */ 2168 uReg -= AHCI_HBA_GLOBAL_SIZE; 2169 iPort = uReg / AHCI_PORT_REGISTER_SIZE; 2170 iReg = (uReg % AHCI_PORT_REGISTER_SIZE) >> 2; 2171 Log3(("%s: Trying to write to port %u and register %u\n", __FUNCTION__, iPort, iReg)); 2172 if (RT_LIKELY( iPort < pAhci->cPortsImpl 2173 && iReg < RT_ELEMENTS(g_aPortOpRegs))) 2174 { 2175 const AHCIPORTOPREG *pPortReg = &g_aPortOpRegs[iReg]; 2176 rc = pPortReg->pfnWrite(pAhci, &pAhci->ahciPort[iPort], iReg, *(uint32_t *)pv); 2177 } 2178 else 2179 { 2180 Log3(("%s: Trying to write port %u register %u/%u!!!\n", __FUNCTION__, iPort, iReg, RT_ELEMENTS(g_aPortOpRegs))); 2181 rc = VINF_SUCCESS; 2182 } 2183 } 2184 2185 return rc; 2186 } 2187 2188 /** 2039 2189 * Memory mapped I/O Handler for read operations. 2040 2190 * … … 2065 2215 pDevIns->iInstance, pv, cb, pv, cb, GCPhysAddr, rc)); 2066 2216 2067 /*2068 * If the access offset is smaller than AHCI_HBA_GLOBAL_SIZE the guest accesses the global registers.2069 * Otherwise it accesses the registers of a port.2070 */2071 2217 uint32_t uOffset = (GCPhysAddr - pAhci->MMIOBase); 2072 uint32_t iReg; 2073 2074 if (uOffset < AHCI_HBA_GLOBAL_SIZE) 2075 { 2076 iReg = uOffset >> 2; 2077 Log3(("%s: Trying to read from global register %u\n", __FUNCTION__, iReg)); 2078 if (iReg < RT_ELEMENTS(g_aOpRegs)) 2079 { 2080 const AHCIOPREG *pReg = &g_aOpRegs[iReg]; 2081 rc = pReg->pfnRead(pAhci, iReg, (uint32_t *)pv); 2082 } 2083 else 2084 { 2085 Log3(("%s: Trying to read global register %u/%u!!!\n", __FUNCTION__, iReg, RT_ELEMENTS(g_aOpRegs))); 2086 *(uint32_t *)pv = 0; 2087 } 2088 } 2089 else 2090 { 2091 uint32_t iRegOffset; 2092 uint32_t iPort; 2093 2094 /* Calculate accessed port. */ 2095 uOffset -= AHCI_HBA_GLOBAL_SIZE; 2096 iPort = uOffset / AHCI_PORT_REGISTER_SIZE; 2097 iRegOffset = (uOffset % AHCI_PORT_REGISTER_SIZE); 2098 iReg = iRegOffset >> 2; 2099 2100 Log3(("%s: Trying to read from port %u and register %u\n", __FUNCTION__, iPort, iReg)); 2101 2102 if (RT_LIKELY( iPort < pAhci->cPortsImpl 2103 && iReg < RT_ELEMENTS(g_aPortOpRegs))) 2104 { 2105 const AHCIPORTOPREG *pPortReg = &g_aPortOpRegs[iReg]; 2106 rc = pPortReg->pfnRead(pAhci, &pAhci->ahciPort[iPort], iReg, (uint32_t *)pv); 2107 } 2108 else 2109 { 2110 Log3(("%s: Trying to read port %u register %u/%u!!!\n", __FUNCTION__, iPort, iReg, RT_ELEMENTS(g_aPortOpRegs))); 2111 rc = VINF_IOM_MMIO_UNUSED_00; 2112 } 2113 2114 /* 2115 * Windows Vista tries to read one byte from some registers instead of four. 2116 * Correct the value according to the read size. 2117 */ 2118 if (RT_SUCCESS(rc) && cb != sizeof(uint32_t)) 2119 { 2120 switch (cb) 2121 { 2122 case 1: 2123 { 2124 uint8_t uNewValue; 2125 uint8_t *p = (uint8_t *)pv; 2126 2127 iRegOffset &= 3; 2128 Log3(("%s: iRegOffset=%u\n", __FUNCTION__, iRegOffset)); 2129 uNewValue = p[iRegOffset]; 2130 /* Clear old value */ 2131 *(uint32_t *)pv = 0; 2132 *(uint8_t *)pv = uNewValue; 2133 break; 2134 } 2135 default: 2136 AssertMsgFailed(("%s: unsupported access width cb=%d uOffset=%x iPort=%x iRegOffset=%x iReg=%x!!!\n", __FUNCTION__, cb, uOffset, iPort, iRegOffset, iReg)); 2137 } 2138 } 2139 } 2218 rc = ahciRegisterRead(pAhci, uOffset, pv, cb); 2140 2219 2141 2220 Log2(("#%d ahciMMIORead: return pvUser=%p:{%.*Rhxs} cb=%d GCPhysAddr=%RGp rc=%Rrc\n", … … 2211 2290 */ 2212 2291 uint32_t uOffset = (GCPhysAddr - pAhci->MMIOBase); 2213 uint32_t iReg; 2214 if (uOffset < AHCI_HBA_GLOBAL_SIZE) 2215 { 2216 Log3(("Write global HBA register\n")); 2217 iReg = uOffset >> 2; 2218 if (iReg < RT_ELEMENTS(g_aOpRegs)) 2219 { 2220 const AHCIOPREG *pReg = &g_aOpRegs[iReg]; 2221 rc = pReg->pfnWrite(pAhci, iReg, *(uint32_t *)pv); 2222 } 2223 else 2224 { 2225 Log3(("%s: Trying to write global register %u/%u!!!\n", __FUNCTION__, iReg, RT_ELEMENTS(g_aOpRegs))); 2226 rc = VINF_SUCCESS; 2227 } 2228 } 2229 else 2230 { 2231 uint32_t iPort; 2232 Log3(("Write Port register\n")); 2233 /* Calculate accessed port. */ 2234 uOffset -= AHCI_HBA_GLOBAL_SIZE; 2235 iPort = uOffset / AHCI_PORT_REGISTER_SIZE; 2236 iReg = (uOffset % AHCI_PORT_REGISTER_SIZE) >> 2; 2237 Log3(("%s: Trying to write to port %u and register %u\n", __FUNCTION__, iPort, iReg)); 2238 if (RT_LIKELY( iPort < pAhci->cPortsImpl 2239 && iReg < RT_ELEMENTS(g_aPortOpRegs))) 2240 { 2241 const AHCIPORTOPREG *pPortReg = &g_aPortOpRegs[iReg]; 2242 rc = pPortReg->pfnWrite(pAhci, &pAhci->ahciPort[iPort], iReg, *(uint32_t *)pv); 2243 } 2244 else 2245 { 2246 Log3(("%s: Trying to write port %u register %u/%u!!!\n", __FUNCTION__, iPort, iReg, RT_ELEMENTS(g_aPortOpRegs))); 2247 rc = VINF_SUCCESS; 2248 } 2249 } 2292 rc = ahciRegisterWrite(pAhci, uOffset, pv, cb); 2250 2293 2251 2294 return rc; … … 2306 2349 AssertMsgFailed(("Should not happen\n")); 2307 2350 return VINF_SUCCESS; 2351 } 2352 2353 /** 2354 * I/O port handler for writes to the index/data register pair. 2355 * 2356 * @returns VBox status code. 2357 * 2358 * @param pDevIns The device instance. 2359 * @param pvUser User argument. 2360 * @param Port Port address where the write starts. 2361 * @param pv Where to fetch the result. 2362 * @param cb Number of bytes to write. 2363 */ 2364 PDMBOTHCBDECL(int) ahciIdxDataWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb) 2365 { 2366 PAHCI pAhci = PDMINS_2_DATA(pDevIns, PAHCI); 2367 int rc = VINF_SUCCESS; 2368 2369 if (Port - pAhci->IOPortBase >= 8) 2370 { 2371 unsigned iReg = (Port - pAhci->IOPortBase - 8) / 4; 2372 2373 Assert(cb == 4); 2374 2375 if (iReg == 0) 2376 { 2377 /* Write the index register. */ 2378 pAhci->regIdx = u32; 2379 } 2380 else 2381 { 2382 Assert(iReg == 1); 2383 rc = ahciRegisterWrite(pAhci, pAhci->regIdx, &u32, cb); 2384 } 2385 } 2386 /* else: ignore */ 2387 2388 Log2(("#%d ahciIdxDataWrite: pu32=%p:{%.*Rhxs} cb=%d Port=%#x rc=%Rrc\n", 2389 pDevIns->iInstance, &u32, cb, &u32, cb, Port, rc)); 2390 return rc; 2391 } 2392 2393 /** 2394 * I/O port handler for reads from the index/data register pair. 2395 * 2396 * @returns VBox status code. 2397 * 2398 * @param pDevIns The device instance. 2399 * @param pvUser User argument. 2400 * @param Port Port address where the read starts. 2401 * @param pv Where to fetch the result. 2402 * @param cb Number of bytes to write. 2403 */ 2404 PDMBOTHCBDECL(int) ahciIdxDataRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb) 2405 { 2406 PAHCI pAhci = PDMINS_2_DATA(pDevIns, PAHCI); 2407 int rc = VINF_SUCCESS; 2408 2409 if (Port - pAhci->IOPortBase >= 8) 2410 { 2411 unsigned iReg = (Port - pAhci->IOPortBase - 8) / 4; 2412 2413 Assert(cb == 4); 2414 2415 if (iReg == 0) 2416 { 2417 /* Read the index register. */ 2418 *pu32 = pAhci->regIdx; 2419 } 2420 else 2421 { 2422 Assert(iReg == 1); 2423 rc = ahciRegisterRead(pAhci, pAhci->regIdx, pu32, cb); 2424 } 2425 } 2426 else 2427 *pu32 = UINT32_C(0xffffffff); 2428 2429 Log2(("#%d ahciIdxDataRead: pu32=%p:{%.*Rhxs} cb=%d Port=%#x rc=%Rrc\n", 2430 pDevIns->iInstance, pu32, cb, pu32, cb, Port, rc)); 2431 return rc; 2308 2432 } 2309 2433 … … 2415 2539 } 2416 2540 2541 return rc; 2542 } 2543 2544 /** 2545 * Map the BMDMA I/O port range (used for the Index/Data pair register access) 2546 */ 2547 static DECLCALLBACK(int) ahciR3IdxDataIORangeMap(PPCIDEVICE pPciDev, /*unsigned*/ int iRegion, RTGCPHYS GCPhysAddress, uint32_t cb, PCIADDRESSSPACE enmType) 2548 { 2549 PAHCI pThis = PCIDEV_2_PAHCI(pPciDev); 2550 PPDMDEVINS pDevIns = pPciDev->pDevIns; 2551 int rc = VINF_SUCCESS; 2552 2553 Log2(("%s: registering fake I/O area at GCPhysAddr=%RGp cb=%u\n", __FUNCTION__, GCPhysAddress, cb)); 2554 2555 Assert(enmType == PCI_ADDRESS_SPACE_IO); 2556 2557 /* We use the assigned size here, because we currently only support page aligned MMIO ranges. */ 2558 rc = PDMDevHlpIOPortRegister(pDevIns, (RTIOPORT)GCPhysAddress, cb, NULL, 2559 ahciIdxDataWrite, ahciIdxDataRead, NULL, NULL, "AHCI IDX/DATA"); 2560 if (RT_FAILURE(rc)) 2561 return rc; 2562 2563 if (pThis->fR0Enabled) 2564 { 2565 rc = PDMDevHlpIOPortRegisterR0(pDevIns, (RTIOPORT)GCPhysAddress, cb, 0, 2566 "ahciIdxDataWrite", "ahciIdxDataRead", NULL, NULL, "AHCI IDX/DATA"); 2567 if (RT_FAILURE(rc)) 2568 return rc; 2569 } 2570 2571 if (pThis->fGCEnabled) 2572 { 2573 rc = PDMDevHlpIOPortRegisterRC(pDevIns, (RTIOPORT)GCPhysAddress, cb, 0, 2574 "ahciIdxDataWrite", "ahciIdxDataRead", NULL, NULL, "AHCI IDX/DATA"); 2575 if (RT_FAILURE(rc)) 2576 return rc; 2577 } 2578 2579 pThis->IOPortBase = (RTIOPORT)GCPhysAddress; 2417 2580 return rc; 2418 2581 } … … 8047 8210 8048 8211 pThis->dev.config[0x70] = VBOX_PCI_CAP_ID_PM; /* Capability ID: PCI Power Management Interface */ 8049 pThis->dev.config[0x71] = 0x 00; /* next */8212 pThis->dev.config[0x71] = 0xa8; /* next */ 8050 8213 pThis->dev.config[0x72] = 0x03; /* version ? */ 8051 8214 … … 8055 8218 pThis->dev.config[0x95] = 0x01; 8056 8219 pThis->dev.config[0x97] = 0x78; 8220 8221 pThis->dev.config[0xa8] = 0x12; /* SATACR capability */ 8222 pThis->dev.config[0xa9] = 0x00; /* next */ 8223 PCIDevSetWord(&pThis->dev, 0xaa, 0x0010); /* Revision */ 8224 PCIDevSetDWord(&pThis->dev, 0xac, 0x00000028); /* SATA Capability Register 1 */ 8057 8225 8058 8226 /* … … 8108 8276 N_("AHCI cannot register PCI I/O region")); 8109 8277 8110 rc = PDMDevHlpPCIIORegionRegister(pDevIns, 4, 0x10, PCI_ADDRESS_SPACE_IO, ahciR3 LegacyFakeIORangeMap);8278 rc = PDMDevHlpPCIIORegionRegister(pDevIns, 4, 0x10, PCI_ADDRESS_SPACE_IO, ahciR3IdxDataIORangeMap); 8111 8279 if (RT_FAILURE(rc)) 8112 8280 return PDMDEV_SET_ERROR(pDevIns, rc, -
trunk/src/VBox/Devices/testcase/tstDeviceStructSizeRC.cpp
r36870 r36878 1210 1210 GEN_CHECK_OFF(AHCIPort, fAsyncInterface); 1211 1211 GEN_CHECK_OFF(AHCIPort, fResetDevice); 1212 GEN_CHECK_OFF(AHCIPort, fAsyncIOThreadIdle); 1213 GEN_CHECK_OFF(AHCIPort, fRedo); 1212 1214 GEN_CHECK_OFF(AHCIPort, cTotalSectors); 1213 1215 GEN_CHECK_OFF(AHCIPort, cMultSectors); … … 1279 1281 GEN_CHECK_OFF(AHCI, regHbaCccCtl); 1280 1282 GEN_CHECK_OFF(AHCI, regHbaCccPorts); 1283 GEN_CHECK_OFF(AHCI, regIdx); 1281 1284 GEN_CHECK_OFF(AHCI, pHbaCccTimerR3); 1282 1285 GEN_CHECK_OFF(AHCI, pHbaCccTimerR0);
Note:
See TracChangeset
for help on using the changeset viewer.