Changeset 77579 in vbox for trunk/src/VBox
- Timestamp:
- Mar 6, 2019 10:21:16 AM (6 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Storage/DevATA.cpp
r77392 r77579 36 36 #define ATA_SAVED_STATE_VERSION_WITHOUT_EVENT_STATUS 17 37 37 /** @} */ 38 39 /** Values read from an empty (with no devices attached) ATA bus. */ 40 #define ATA_EMPTY_BUS_DATA 0x7F 41 #define ATA_EMPTY_BUS_DATA_32 0x7F7F7F7F 38 42 39 43 … … 4474 4478 4475 4479 /* Check if the guest is reading from a non-existent device. */ 4476 if ( !s->pDrvMedia)4480 if (RT_UNLIKELY(!s->pDrvMedia)) 4477 4481 { 4478 4482 if (pCtl->iSelectedIf) /* Device 1 selected, Device 0 responding for it. */ 4479 4483 { 4480 if (!pCtl->aIfs[0].pDrvMedia) /** @todo this case should never get here! */ 4481 { 4482 Log2(("%s: addr=%#x: no device on channel\n", __FUNCTION__, addr)); 4483 return VERR_IOM_IOPORT_UNUSED; 4484 } 4484 Assert(pCtl->aIfs[0].pDrvMedia); 4485 4486 /* When an ATAPI device 0 responds for non-present device 1, it generally 4487 * returns zeros on reads. The Error register is an exception. See clause 7.1, 4488 * table 16 in ATA-6 specification. 4489 */ 4485 4490 if (((addr & 7) != 1) && pCtl->aIfs[0].fATAPI) { 4486 4491 Log2(("%s: addr=%#x, val=0: LUN#%d not attached/LUN#%d ATAPI\n", __FUNCTION__, addr, … … 4493 4498 else /* Device 0 selected (but not present). */ 4494 4499 { 4495 /* ATA-3 and later specifies that the host must have a pull-down resistor on DD7; ATA-5 explains 4496 * that this causes the BSY bit to always be read as clear when there is no device on a given 4497 * channel. Software then does not need to wait a long time for non-existent drives; note that 4498 * EFI (TianoCore) relies on this behavior. 4500 /* Because device 1 has no way to tell if there is device 0, the behavior is the same 4501 * as for an empty bus; see comments in ataIOPortReadEmptyBus(). Note that EFI (TianoCore) 4502 * relies on this behavior when detecting devices. 4499 4503 */ 4500 *pu32 = 0x7F;4504 *pu32 = ATA_EMPTY_BUS_DATA; 4501 4505 Log2(("%s: addr=%#x: LUN#%d not attached, val=%#02x\n", __FUNCTION__, addr, s->iLUN, *pu32)); 4502 4506 return VINF_SUCCESS; … … 4642 4646 4643 4647 4648 /* 4649 * Read the Alternate status register. Does not affect interrupts. 4650 */ 4644 4651 static uint32_t ataStatusRead(PATACONTROLLER pCtl, uint32_t addr) 4645 4652 { … … 4648 4655 RT_NOREF1(addr); 4649 4656 4650 /// @todo The handler should not be even registered if there 4651 // is no device on an IDE channel. 4652 if (!pCtl->aIfs[0].pDrvMedia && !pCtl->aIfs[1].pDrvMedia) 4653 val = 0xff; 4654 else if (pCtl->iSelectedIf == 1 && !s->pDrvMedia) 4657 Assert(pCtl->aIfs[0].pDrvMedia || pCtl->aIfs[1].pDrvMedia); /* Channel must not be empty. */ 4658 if (pCtl->iSelectedIf == 1 && !s->pDrvMedia) 4655 4659 val = 0; /* Device 1 selected, Device 0 responding for it. */ 4656 4660 else 4657 4661 val = s->uATARegStatus; 4658 Log2(("%s: addr=%#x val=%#04x\n", __FUNCTION__, addr, val));4662 Log2(("%s: LUN#%d read addr=%#x val=%#04x\n", __FUNCTION__, pCtl->aIfs[pCtl->iSelectedIf].iLUN, addr, val)); 4659 4663 return val; 4660 4664 } … … 4668 4672 #endif /* !IN_RING3 */ 4669 4673 4670 Log2(("%s: addr=%#x val=%#04x\n", __FUNCTION__, addr, val));4674 Log2(("%s: LUN#%d write addr=%#x val=%#04x\n", __FUNCTION__, pCtl->aIfs[pCtl->iSelectedIf].iLUN, addr, val)); 4671 4675 /* RESET is common for both drives attached to a controller. */ 4672 4676 if ( !(pCtl->aIfs[0].uATARegDevCtl & ATA_DEVCTL_RESET) … … 4849 4853 * the case for write operations or generally for not yet finished 4850 4854 * transfers (some data might need to be read). */ 4855 ataSetStatus(s, ATA_STAT_BUSY); 4851 4856 ataUnsetStatus(s, ATA_STAT_READY | ATA_STAT_DRQ); 4852 ataSetStatus(s, ATA_STAT_BUSY);4853 4857 4854 4858 Log2(("%s: Ctl#%d: message to async I/O thread, continuing PIO transfer\n", __FUNCTION__, ATACONTROLLER_IDX(pCtl))); … … 6301 6305 6302 6306 /** 6307 * Port I/O Handler for OUT operations on unpopulated IDE channels. 6308 * @see FNIOMIOPORTOUT for details. 6309 */ 6310 PDMBOTHCBDECL(int) ataIOPortWriteEmptyBus(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb) 6311 { 6312 uint32_t i = (uint32_t)(uintptr_t)pvUser; 6313 PCIATAState *pThis = PDMINS_2_DATA(pDevIns, PCIATAState *); 6314 PATACONTROLLER pCtl = &pThis->aCts[i]; 6315 #ifndef VBOX_LOG_ENABLED 6316 RT_NOREF(Port); RT_NOREF(cb); RT_NOREF(u32); RT_NOREF(pCtl); 6317 #endif 6318 6319 Assert(i < 2); 6320 Assert(!pCtl->aIfs[0].pDrvMedia && !pCtl->aIfs[1].pDrvMedia); 6321 6322 /* This is simply a black hole, writes on unpopulated IDE channels elicit no response. */ 6323 LogFunc(("Empty bus: Ignoring write to port %x val=%x size=%d\n", Port, u32, cb)); 6324 return VINF_SUCCESS; 6325 } 6326 6327 6328 /** 6329 * Port I/O Handler for IN operations on unpopulated IDE channels. 6330 * @see FNIOMIOPORTIN for details. 6331 */ 6332 PDMBOTHCBDECL(int) ataIOPortReadEmptyBus(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb) 6333 { 6334 uint32_t i = (uint32_t)(uintptr_t)pvUser; 6335 PCIATAState *pThis = PDMINS_2_DATA(pDevIns, PCIATAState *); 6336 PATACONTROLLER pCtl = &pThis->aCts[i]; 6337 #ifndef VBOX_LOG_ENABLED 6338 RT_NOREF(Port); RT_NOREF(pCtl); 6339 #endif 6340 6341 Assert(i < 2); 6342 Assert(cb <= 4); 6343 Assert(!pCtl->aIfs[0].pDrvMedia && !pCtl->aIfs[1].pDrvMedia); 6344 6345 /* 6346 * Reads on unpopulated IDE channels behave in a unique way. Newer ATA specifications 6347 * mandate that the host must have a pull-down resistor on signal DD7. As a consequence, 6348 * bit 7 is always read as zero. This greatly aids in ATA device detection because 6349 * the empty bus does not look to the host like a permanently busy drive, and no long 6350 * timeouts (on the order of 30 seconds) are needed. 6351 * 6352 * The response is entirely static and does not require any locking or other fancy 6353 * stuff. Breaking it out simplifies the I/O handling for non-empty IDE channels which 6354 * is quite complicated enough already. 6355 */ 6356 *pu32 = ATA_EMPTY_BUS_DATA_32 >> ((4 - cb) * 8); 6357 LogFunc(("Empty bus: port %x val=%x size=%d\n", Port, *pu32, cb)); 6358 return VINF_SUCCESS; 6359 } 6360 6361 6362 /** 6303 6363 * Port I/O Handler for primary port range OUT operations. 6304 6364 * @see FNIOMIOPORTOUT for details. … … 6392 6452 } 6393 6453 else 6454 { 6455 Log(("ataIOPortWrite2: ignoring write to port %x size=%d!\n", Port, cb)); 6394 6456 rc = VINF_SUCCESS; 6457 } 6395 6458 return rc; 6396 6459 } … … 6420 6483 } 6421 6484 else 6485 { 6486 Log(("ataIOPortRead2: ignoring read from port %x size=%d!\n", Port, cb)); 6422 6487 rc = VERR_IOM_IOPORT_UNUSED; 6488 } 6423 6489 return rc; 6424 6490 } … … 7622 7688 7623 7689 /* 7624 * Register the I/O ports. 7625 * The ports are all hardcoded and enforced by the PIIX3 host bridge controller. 7690 * Register stats, create critical sections. 7626 7691 */ 7627 7692 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aCts); i++) 7628 7693 { 7629 rc = PDMDevHlpIOPortRegister(pDevIns, pThis->aCts[i].IOPortBase1, 1, (RTHCPTR)(uintptr_t)i,7630 ataIOPortWrite1Data, ataIOPortRead1Data,7631 ataIOPortWriteStr1Data, ataIOPortReadStr1Data, "ATA I/O Base 1 - Data");7632 AssertLogRelRCReturn(rc, rc);7633 rc = PDMDevHlpIOPortRegister(pDevIns, pThis->aCts[i].IOPortBase1 + 1, 7, (RTHCPTR)(uintptr_t)i,7634 ataIOPortWrite1Other, ataIOPortRead1Other, NULL, NULL, "ATA I/O Base 1 - Other");7635 7636 AssertLogRelRCReturn(rc, rc);7637 if (fRCEnabled)7638 {7639 rc = PDMDevHlpIOPortRegisterRC(pDevIns, pThis->aCts[i].IOPortBase1, 1, (RTGCPTR)i,7640 "ataIOPortWrite1Data", "ataIOPortRead1Data",7641 "ataIOPortWriteStr1Data", "ataIOPortReadStr1Data", "ATA I/O Base 1 - Data");7642 AssertLogRelRCReturn(rc, rc);7643 rc = PDMDevHlpIOPortRegisterRC(pDevIns, pThis->aCts[i].IOPortBase1 + 1, 7, (RTGCPTR)i,7644 "ataIOPortWrite1Other", "ataIOPortRead1Other", NULL, NULL, "ATA I/O Base 1 - Other");7645 AssertLogRelRCReturn(rc, rc);7646 }7647 7648 if (fR0Enabled)7649 {7650 #if 07651 rc = PDMDevHlpIOPortRegisterR0(pDevIns, pThis->aCts[i].IOPortBase1, 1, (RTR0PTR)i,7652 "ataIOPortWrite1Data", "ataIOPortRead1Data", NULL, NULL, "ATA I/O Base 1 - Data");7653 #else7654 rc = PDMDevHlpIOPortRegisterR0(pDevIns, pThis->aCts[i].IOPortBase1, 1, (RTR0PTR)i,7655 "ataIOPortWrite1Data", "ataIOPortRead1Data",7656 "ataIOPortWriteStr1Data", "ataIOPortReadStr1Data", "ATA I/O Base 1 - Data");7657 #endif7658 AssertLogRelRCReturn(rc, rc);7659 rc = PDMDevHlpIOPortRegisterR0(pDevIns, pThis->aCts[i].IOPortBase1 + 1, 7, (RTR0PTR)i,7660 "ataIOPortWrite1Other", "ataIOPortRead1Other", NULL, NULL, "ATA I/O Base 1 - Other");7661 AssertLogRelRCReturn(rc, rc);7662 }7663 7664 rc = PDMDevHlpIOPortRegister(pDevIns, pThis->aCts[i].IOPortBase2, 1, (RTHCPTR)(uintptr_t)i,7665 ataIOPortWrite2, ataIOPortRead2, NULL, NULL, "ATA I/O Base 2");7666 if (RT_FAILURE(rc))7667 return PDMDEV_SET_ERROR(pDevIns, rc, N_("PIIX3 cannot register base2 I/O handlers"));7668 7669 if (fRCEnabled)7670 {7671 rc = PDMDevHlpIOPortRegisterRC(pDevIns, pThis->aCts[i].IOPortBase2, 1, (RTGCPTR)i,7672 "ataIOPortWrite2", "ataIOPortRead2", NULL, NULL, "ATA I/O Base 2");7673 if (RT_FAILURE(rc))7674 return PDMDEV_SET_ERROR(pDevIns, rc, N_("PIIX3 cannot register base2 I/O handlers (GC)"));7675 }7676 if (fR0Enabled)7677 {7678 rc = PDMDevHlpIOPortRegisterR0(pDevIns, pThis->aCts[i].IOPortBase2, 1, (RTR0PTR)i,7679 "ataIOPortWrite2", "ataIOPortRead2", NULL, NULL, "ATA I/O Base 2");7680 if (RT_FAILURE(rc))7681 return PDMDEV_SET_ERROR(pDevIns, rc, N_("PIIX3 cannot register base2 I/O handlers (R0)"));7682 }7683 7684 7694 for (uint32_t j = 0; j < RT_ELEMENTS(pThis->aCts[i].aIfs); j++) 7685 7695 { … … 7932 7942 } 7933 7943 cbTotalBuffer += pIf->cbIOBuffer; 7944 } 7945 } 7946 7947 /* 7948 * Register the I/O ports. 7949 * The ports are all hardcoded and enforced by the PIIX3 host bridge controller. 7950 */ 7951 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aCts); i++) 7952 { 7953 if (!pThis->aCts[i].aIfs[0].pDrvMedia && !pThis->aCts[i].aIfs[1].pDrvMedia) 7954 { 7955 /* No device present on this ATA bus; requires special handling. */ 7956 rc = PDMDevHlpIOPortRegister(pDevIns, pThis->aCts[i].IOPortBase1, 8, (RTHCPTR)(uintptr_t)i, 7957 ataIOPortWriteEmptyBus, ataIOPortReadEmptyBus, NULL, NULL, "ATA I/O Base 1 - Empty Bus"); 7958 7959 AssertLogRelRCReturn(rc, rc); 7960 rc = PDMDevHlpIOPortRegister(pDevIns, pThis->aCts[i].IOPortBase2, 1, (RTHCPTR)(uintptr_t)i, 7961 ataIOPortWriteEmptyBus, ataIOPortReadEmptyBus, NULL, NULL, "ATA I/O Base 2 - Empty Bus"); 7962 AssertLogRelRCReturn(rc, rc); 7963 7964 if (fRCEnabled) 7965 { 7966 rc = PDMDevHlpIOPortRegisterRC(pDevIns, pThis->aCts[i].IOPortBase1, 8, (RTGCPTR)i, 7967 "ataIOPortWriteEmptyBus", "ataIOPortReadEmptyBus", NULL, NULL, "ATA I/O Base 1 - Empty Bus"); 7968 AssertLogRelRCReturn(rc, rc); 7969 rc = PDMDevHlpIOPortRegisterRC(pDevIns, pThis->aCts[i].IOPortBase2, 1, (RTGCPTR)i, 7970 "ataIOPortWriteEmptyBus", "ataIOPortReadEmptyBus", NULL, NULL, "ATA I/O Base 2 - Empty Bus"); 7971 AssertLogRelRCReturn(rc, rc); 7972 } 7973 7974 if (fR0Enabled) 7975 { 7976 rc = PDMDevHlpIOPortRegisterR0(pDevIns, pThis->aCts[i].IOPortBase1, 8, (RTR0PTR)i, 7977 "ataIOPortWriteEmptyBus", "ataIOPortReadEmptyBus", NULL, NULL, "ATA I/O Base 1 - Empty Bus"); 7978 AssertLogRelRCReturn(rc, rc); 7979 rc = PDMDevHlpIOPortRegisterR0(pDevIns, pThis->aCts[i].IOPortBase2, 1, (RTR0PTR)i, 7980 "ataIOPortWriteEmptyBus", "ataIOPortReadEmptyBus", NULL, NULL, "ATA I/O Base 2 - Empty Bus"); 7981 AssertLogRelRCReturn(rc, rc); 7982 } 7983 } 7984 else 7985 { 7986 /* At least one device present, register regular handlers. */ 7987 rc = PDMDevHlpIOPortRegister(pDevIns, pThis->aCts[i].IOPortBase1, 1, (RTHCPTR)(uintptr_t)i, 7988 ataIOPortWrite1Data, ataIOPortRead1Data, 7989 ataIOPortWriteStr1Data, ataIOPortReadStr1Data, "ATA I/O Base 1 - Data"); 7990 AssertLogRelRCReturn(rc, rc); 7991 rc = PDMDevHlpIOPortRegister(pDevIns, pThis->aCts[i].IOPortBase1 + 1, 7, (RTHCPTR)(uintptr_t)i, 7992 ataIOPortWrite1Other, ataIOPortRead1Other, NULL, NULL, "ATA I/O Base 1 - Other"); 7993 7994 AssertLogRelRCReturn(rc, rc); 7995 if (fRCEnabled) 7996 { 7997 rc = PDMDevHlpIOPortRegisterRC(pDevIns, pThis->aCts[i].IOPortBase1, 1, (RTGCPTR)i, 7998 "ataIOPortWrite1Data", "ataIOPortRead1Data", 7999 "ataIOPortWriteStr1Data", "ataIOPortReadStr1Data", "ATA I/O Base 1 - Data"); 8000 AssertLogRelRCReturn(rc, rc); 8001 rc = PDMDevHlpIOPortRegisterRC(pDevIns, pThis->aCts[i].IOPortBase1 + 1, 7, (RTGCPTR)i, 8002 "ataIOPortWrite1Other", "ataIOPortRead1Other", NULL, NULL, "ATA I/O Base 1 - Other"); 8003 AssertLogRelRCReturn(rc, rc); 8004 } 8005 8006 if (fR0Enabled) 8007 { 8008 #if 0 8009 rc = PDMDevHlpIOPortRegisterR0(pDevIns, pThis->aCts[i].IOPortBase1, 1, (RTR0PTR)i, 8010 "ataIOPortWrite1Data", "ataIOPortRead1Data", NULL, NULL, "ATA I/O Base 1 - Data"); 8011 #else 8012 rc = PDMDevHlpIOPortRegisterR0(pDevIns, pThis->aCts[i].IOPortBase1, 1, (RTR0PTR)i, 8013 "ataIOPortWrite1Data", "ataIOPortRead1Data", 8014 "ataIOPortWriteStr1Data", "ataIOPortReadStr1Data", "ATA I/O Base 1 - Data"); 8015 #endif 8016 AssertLogRelRCReturn(rc, rc); 8017 rc = PDMDevHlpIOPortRegisterR0(pDevIns, pThis->aCts[i].IOPortBase1 + 1, 7, (RTR0PTR)i, 8018 "ataIOPortWrite1Other", "ataIOPortRead1Other", NULL, NULL, "ATA I/O Base 1 - Other"); 8019 AssertLogRelRCReturn(rc, rc); 8020 } 8021 8022 rc = PDMDevHlpIOPortRegister(pDevIns, pThis->aCts[i].IOPortBase2, 1, (RTHCPTR)(uintptr_t)i, 8023 ataIOPortWrite2, ataIOPortRead2, NULL, NULL, "ATA I/O Base 2"); 8024 if (RT_FAILURE(rc)) 8025 return PDMDEV_SET_ERROR(pDevIns, rc, N_("PIIX3 cannot register base2 I/O handlers")); 8026 8027 if (fRCEnabled) 8028 { 8029 rc = PDMDevHlpIOPortRegisterRC(pDevIns, pThis->aCts[i].IOPortBase2, 1, (RTGCPTR)i, 8030 "ataIOPortWrite2", "ataIOPortRead2", NULL, NULL, "ATA I/O Base 2"); 8031 if (RT_FAILURE(rc)) 8032 return PDMDEV_SET_ERROR(pDevIns, rc, N_("PIIX3 cannot register base2 I/O handlers (GC)")); 8033 } 8034 if (fR0Enabled) 8035 { 8036 rc = PDMDevHlpIOPortRegisterR0(pDevIns, pThis->aCts[i].IOPortBase2, 1, (RTR0PTR)i, 8037 "ataIOPortWrite2", "ataIOPortRead2", NULL, NULL, "ATA I/O Base 2"); 8038 if (RT_FAILURE(rc)) 8039 return PDMDEV_SET_ERROR(pDevIns, rc, N_("PIIX3 cannot register base2 I/O handlers (R0)")); 8040 } 7934 8041 } 7935 8042 }
Note:
See TracChangeset
for help on using the changeset viewer.