Changeset 81891 in vbox for trunk/src/VBox/Devices/Serial
- Timestamp:
- Nov 16, 2019 1:43:54 AM (5 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Serial/DevOxPcie958.cpp
r81591 r81891 107 107 /** Pointer to the device instance - RC ptr. */ 108 108 PPDMDEVINSRC pDevInsRC; 109 /** Flag whether R0 is enabled. */ 110 bool fR0Enabled; 111 /** Flag whether RC is enabled. */ 112 bool fRCEnabled; 113 /** Alignment. */ 114 bool afAlignment[2]; 109 uint32_t u32Alignment; 115 110 /** UART global IRQ status. */ 116 111 volatile uint32_t u32RegIrqStsGlob; … … 123 118 /** MMIO Base address. */ 124 119 RTGCPHYS GCPhysMMIO; 120 /** Handle to the MMIO region (PCI region \#0). */ 121 IOMMMIOHANDLE hMmio; 125 122 /** The UARTs. */ 126 123 OX958UART aUarts[OX958_UARTS_MAX]; 127 128 124 } DEVOX958; 129 125 /** Pointer to an OXPCIe958 device instance. */ … … 138 134 * 139 135 * @returns nothing. 136 * @param pDevIns The device instance. 140 137 * @param pThis The OXPCIe958 device instance. 141 138 */ 142 static void ox958IrqUpdate(P DEVOX958 pThis)139 static void ox958IrqUpdate(PPDMDEVINS pDevIns, PDEVOX958 pThis) 143 140 { 144 141 uint32_t u32IrqSts = ASMAtomicReadU32(&pThis->u32RegIrqStsGlob); … … 146 143 147 144 if (u32IrqSts & u32IrqEn) 148 PDMDevHlpPCISetIrq(p This->CTX_SUFF(pDevIns), 0, PDM_IRQ_LEVEL_HIGH);145 PDMDevHlpPCISetIrq(pDevIns, 0, PDM_IRQ_LEVEL_HIGH); 149 146 else 150 PDMDevHlpPCISetIrq(p This->CTX_SUFF(pDevIns), 0, PDM_IRQ_LEVEL_LOW);147 PDMDevHlpPCISetIrq(pDevIns, 0, PDM_IRQ_LEVEL_LOW); 151 148 } 152 149 … … 155 152 * Performs a register read from the given UART. 156 153 * 157 * @returns nothing.154 * @returns Strict VBox status code. 158 155 * @param pThis The OXPCIe958 device instance. 159 156 * @param pUart The UART accessed. … … 162 159 * @param cb Number of bytes to read. 163 160 */ 164 static intox958UartRegRead(PDEVOX958 pThis, POX958UART pUart, uint32_t offUartReg, void *pv, unsigned cb)165 { 166 int rc = VINF_SUCCESS;161 static VBOXSTRICTRC ox958UartRegRead(PDEVOX958 pThis, POX958UART pUart, uint32_t offUartReg, void *pv, unsigned cb) 162 { 163 VBOXSTRICTRC rc; 167 164 RT_NOREF(pThis); 168 165 … … 170 167 { 171 168 /* Access to the DMA registers. */ 169 rc = VINF_SUCCESS; 172 170 } 173 171 else /* Access UART registers. */ … … 181 179 * Performs a register write to the given UART. 182 180 * 183 * @returns nothing.181 * @returns Strict VBox status code. 184 182 * @param pThis The OXPCIe958 device instance. 185 183 * @param pUart The UART accessed. … … 188 186 * @param cb Number of bytes to write. 189 187 */ 190 static intox958UartRegWrite(PDEVOX958 pThis, POX958UART pUart, uint32_t offUartReg, const void *pv, unsigned cb)191 { 192 int rc = VINF_SUCCESS;188 static VBOXSTRICTRC ox958UartRegWrite(PDEVOX958 pThis, POX958UART pUart, uint32_t offUartReg, const void *pv, unsigned cb) 189 { 190 VBOXSTRICTRC rc; 193 191 RT_NOREF(pThis); 194 192 … … 196 194 { 197 195 /* Access to the DMA registers. */ 196 rc = VINF_SUCCESS; 198 197 } 199 198 else /* Access UART registers. */ … … 222 221 else 223 222 ASMAtomicAndU32(&pThis->u32RegIrqStsGlob, ~RT_BIT_32(iLUN)); 224 ox958IrqUpdate(pThis); 225 } 226 227 228 /** 229 * Read a MMIO register. 230 * 231 * @returns VBox status code suitable for scheduling. 232 * @param pDevIns The device instance. 233 * @param pvUser A user argument (ignored). 234 * @param GCPhysAddr The physical address being written to. (This is within our MMIO memory range.) 235 * @param pv Where to put the data we read. 236 * @param cb The size of the read. 237 */ 238 PDMBOTHCBDECL(int) ox958MmioRead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb) 239 { 240 PDEVOX958 pThis = PDMDEVINS_2_DATA(pDevIns, PDEVOX958); 241 uint32_t offReg = (GCPhysAddr - pThis->GCPhysMMIO); 242 int rc = VINF_SUCCESS; 243 RT_NOREF(pThis, pvUser); 244 245 if (offReg < OX958_REG_UART_REGION_OFFSET) 223 ox958IrqUpdate(pDevIns, pThis); 224 } 225 226 227 /** 228 * @callback_method_impl{FNIOMMMIONEWREAD} 229 */ 230 static DECLCALLBACK(VBOXSTRICTRC) ox958MmioRead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS off, void *pv, unsigned cb) 231 { 232 PDEVOX958 pThis = PDMDEVINS_2_DATA(pDevIns, PDEVOX958); 233 VBOXSTRICTRC rc = VINF_SUCCESS; 234 RT_NOREF(pvUser); 235 236 if (off < OX958_REG_UART_REGION_OFFSET) 246 237 { 247 238 uint32_t *pu32 = (uint32_t *)pv; 248 239 Assert(cb == 4); 249 240 250 switch ( offReg)241 switch ((uint32_t)off) 251 242 { 252 243 case OX958_REG_CC_REV_ID: … … 278 269 { 279 270 /* Figure out the UART accessed from the offset. */ 280 off Reg-= OX958_REG_UART_REGION_OFFSET;281 uint32_t iUart = offReg/ OX958_REG_UART_REGION_SIZE;282 uint32_t offUartReg = offReg% OX958_REG_UART_REGION_SIZE;283 if (iUart < pThis->cUarts)271 off -= OX958_REG_UART_REGION_OFFSET; 272 uint32_t iUart = (uint32_t)off / OX958_REG_UART_REGION_SIZE; 273 uint32_t offUartReg = (uint32_t)off % OX958_REG_UART_REGION_SIZE; 274 if (iUart < RT_MIN(pThis->cUarts, RT_ELEMENTS(pThis->aUarts))) 284 275 { 285 276 POX958UART pUart = &pThis->aUarts[iUart]; … … 297 288 298 289 /** 299 * Write to a MMIO register. 300 * 301 * @returns VBox status code suitable for scheduling. 302 * @param pDevIns The device instance. 303 * @param pvUser A user argument (ignored). 304 * @param GCPhysAddr The physical address being written to. (This is within our MMIO memory range.) 305 * @param pv Pointer to the data being written. 306 * @param cb The size of the data being written. 307 */ 308 PDMBOTHCBDECL(int) ox958MmioWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void const *pv, unsigned cb) 309 { 310 PDEVOX958 pThis = PDMDEVINS_2_DATA(pDevIns, PDEVOX958); 311 uint32_t offReg = (GCPhysAddr - pThis->GCPhysMMIO); 312 int rc = VINF_SUCCESS; 290 * @callback_method_impl{FNIOMMMIONEWWRITE} 291 */ 292 static DECLCALLBACK(VBOXSTRICTRC) ox958MmioWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS off, void const *pv, unsigned cb) 293 { 294 PDEVOX958 pThis = PDMDEVINS_2_DATA(pDevIns, PDEVOX958); 295 VBOXSTRICTRC rc = VINF_SUCCESS; 313 296 RT_NOREF1(pvUser); 314 297 315 if (off Reg< OX958_REG_UART_REGION_OFFSET)298 if (off < OX958_REG_UART_REGION_OFFSET) 316 299 { 317 300 const uint32_t u32 = *(const uint32_t *)pv; 318 301 Assert(cb == 4); 319 302 320 switch ( offReg)303 switch ((uint32_t)off) 321 304 { 322 305 case OX958_REG_UART_IRQ_ENABLE: 323 306 ASMAtomicOrU32(&pThis->u32RegIrqEnGlob, u32); 324 ox958IrqUpdate(p This);307 ox958IrqUpdate(pDevIns, pThis); 325 308 break; 326 309 case OX958_REG_UART_IRQ_DISABLE: 327 310 ASMAtomicAndU32(&pThis->u32RegIrqEnGlob, ~u32); 328 ox958IrqUpdate(p This);311 ox958IrqUpdate(pDevIns, pThis); 329 312 break; 330 313 case OX958_REG_UART_WAKE_IRQ_ENABLE: … … 338 321 case OX958_REG_UART_CNT: /* Readonly */ 339 322 default: 340 rc = VINF_SUCCESS;323 break; 341 324 } 342 325 } … … 344 327 { 345 328 /* Figure out the UART accessed from the offset. */ 346 off Reg-= OX958_REG_UART_REGION_OFFSET;347 uint32_t iUart = offReg/ OX958_REG_UART_REGION_SIZE;348 uint32_t offUartReg = offReg% OX958_REG_UART_REGION_SIZE;349 if (iUart < pThis->cUarts)329 off -= OX958_REG_UART_REGION_OFFSET; 330 uint32_t iUart = (uint32_t)off / OX958_REG_UART_REGION_SIZE; 331 uint32_t offUartReg = (uint32_t)off % OX958_REG_UART_REGION_SIZE; 332 if (iUart < RT_MIN(pThis->cUarts, RT_ELEMENTS(pThis->aUarts))) 350 333 { 351 334 POX958UART pUart = &pThis->aUarts[iUart]; … … 361 344 362 345 #ifdef IN_RING3 363 /**364 * @callback_method_impl{FNPCIIOREGIONMAP}365 */366 static DECLCALLBACK(int) ox958R3Map(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t iRegion,367 RTGCPHYS GCPhysAddress, RTGCPHYS cb, PCIADDRESSSPACE enmType)368 {369 PDEVOX958 pThis = PDMDEVINS_2_DATA(pDevIns, PDEVOX958);370 int rc = VINF_SUCCESS;371 RT_NOREF(pPciDev, enmType);372 Assert(pPciDev == pDevIns->apPciDevs[0]);373 374 if (iRegion == 0)375 {376 Assert(enmType == PCI_ADDRESS_SPACE_MEM);377 378 rc = PDMDevHlpMMIORegister(pDevIns, GCPhysAddress, cb, NULL /*pvUser*/,379 IOMMMIO_FLAGS_READ_PASSTHRU | IOMMMIO_FLAGS_WRITE_PASSTHRU,380 ox958MmioWrite, ox958MmioRead, "OxPCIe958");381 if (RT_FAILURE(rc))382 return rc;383 384 /* Enable (or not) RC/R0 support. */385 if (pThis->fRCEnabled)386 {387 rc = PDMDevHlpMMIORegisterRC(pDevIns, GCPhysAddress, cb, NIL_RTRCPTR /*pvUser*/,388 "ox958MmioWrite", "ox958MmioRead");389 if (RT_FAILURE(rc))390 return rc;391 }392 393 if (pThis->fR0Enabled)394 {395 rc = PDMDevHlpMMIORegisterR0(pDevIns, GCPhysAddress, cb, NIL_RTR0PTR /*pvUser*/,396 "ox958MmioWrite", "ox958MmioRead");397 if (RT_FAILURE(rc))398 return rc;399 }400 401 pThis->GCPhysMMIO = GCPhysAddress;402 }403 404 return VINF_SUCCESS;405 }406 407 346 408 347 /** @interface_method_impl{PDMDEVREG,pfnDetach} */ … … 425 364 RT_NOREF(fFlags); 426 365 427 if (iLUN >= pThis->cUarts)366 if (iLUN >= RT_MIN(pThis->cUarts, RT_ELEMENTS(pThis->aUarts))) 428 367 return VERR_PDM_LUN_NOT_FOUND; 429 368 … … 441 380 pThis->u32RegIrqEnWake = 0x00; 442 381 443 for (uint32_t i = 0; i < pThis->cUarts; i++) 382 uint32_t const cUarts = RT_MIN(pThis->cUarts, RT_ELEMENTS(pThis->aUarts)); 383 for (uint32_t i = 0; i < cUarts; i++) 444 384 uartR3Reset(&pThis->aUarts[i].UartCore); 445 385 } … … 453 393 454 394 pThis->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns); 455 for (uint32_t i = 0; i < pThis->cUarts; i++) 395 uint32_t const cUarts = RT_MIN(pThis->cUarts, RT_ELEMENTS(pThis->aUarts)); 396 for (uint32_t i = 0; i < cUarts; i++) 456 397 uartR3Relocate(&pThis->aUarts[i].UartCore, offDelta); 457 398 } … … 461 402 static DECLCALLBACK(int) ox958R3Destruct(PPDMDEVINS pDevIns) 462 403 { 404 PDMDEV_CHECK_VERSIONS_RETURN_QUIET(pDevIns); 463 405 PDEVOX958 pThis = PDMDEVINS_2_DATA(pDevIns, PDEVOX958); 464 PDMDEV_CHECK_VERSIONS_RETURN_QUIET(pDevIns); 465 466 for (uint32_t i = 0; i < pThis->cUarts; i++)406 407 uint32_t const cUarts = RT_MIN(pThis->cUarts, RT_ELEMENTS(pThis->aUarts)); 408 for (uint32_t i = 0; i < cUarts; i++) 467 409 uartR3Destruct(&pThis->aUarts[i].UartCore); 468 410 … … 474 416 static DECLCALLBACK(int) ox958R3Construct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg) 475 417 { 418 PDMDEV_CHECK_VERSIONS_RETURN(pDevIns); 476 419 RT_NOREF(iInstance); 477 PDEVOX958 pThis = PDMDEVINS_2_DATA(pDevIns, PDEVOX958); 478 bool fRCEnabled = true; 479 bool fR0Enabled = true; 480 bool fMsiXSupported = false; 481 int rc; 482 483 PDMDEV_CHECK_VERSIONS_RETURN(pDevIns); 420 PDEVOX958 pThis = PDMDEVINS_2_DATA(pDevIns, PDEVOX958); 421 PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3; 422 bool fMsiXSupported = false; 423 int rc; 424 425 /* 426 * Init instance data. 427 */ 428 pThis->pDevInsR3 = pDevIns; 429 pThis->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns); 430 pThis->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns); 431 432 rc = PDMDevHlpSetDeviceCritSect(pDevIns, PDMDevHlpCritSectGetNop(pDevIns)); 433 AssertRCReturn(rc, rc); 484 434 485 435 /* 486 436 * Validate and read configuration. 487 437 */ 488 if (!CFGMR3AreValuesValid(pCfg, "RCEnabled\0" 489 "R0Enabled\0" 490 "MsiXSupported\0" 491 "UartCount\0")) 492 return PDMDEV_SET_ERROR(pDevIns, VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES, 493 N_("OXPCIe958 configuration error: Unknown option specified")); 494 495 rc = CFGMR3QueryBoolDef(pCfg, "RCEnabled", &fRCEnabled, true); 438 PDMDEV_VALIDATE_CONFIG_RETURN(pDevIns, "MsiXSupported|UartCount", ""); 439 440 rc = pHlp->pfnCFGMQueryBoolDef(pCfg, "MsiXSupported", &fMsiXSupported, true); 496 441 if (RT_FAILURE(rc)) 497 return PDMDEV_SET_ERROR(pDevIns, rc, 498 N_("OXPCIe958 configuration error: Failed to read \"RCEnabled\" as boolean")); 499 500 rc = CFGMR3QueryBoolDef(pCfg, "R0Enabled", &fR0Enabled, true); 442 return PDMDEV_SET_ERROR(pDevIns, rc, N_("OXPCIe958 configuration error: failed to read \"MsiXSupported\" as boolean")); 443 444 rc = pHlp->pfnCFGMQueryU32Def(pCfg, "UartCount", &pThis->cUarts, OX958_UARTS_MAX); 501 445 if (RT_FAILURE(rc)) 502 return PDMDEV_SET_ERROR(pDevIns, rc, 503 N_("OXPCIe958 configuration error: failed to read \"R0Enabled\" as boolean")); 504 505 rc = CFGMR3QueryBoolDef(pCfg, "MsiXSupported", &fMsiXSupported, true); 506 if (RT_FAILURE(rc)) 507 return PDMDEV_SET_ERROR(pDevIns, rc, 508 N_("OXPCIe958 configuration error: failed to read \"MsiXSupported\" as boolean")); 509 510 rc = CFGMR3QueryU32Def(pCfg, "UartCount", &pThis->cUarts, OX958_UARTS_MAX); 511 if (RT_FAILURE(rc)) 512 return PDMDEV_SET_ERROR(pDevIns, rc, 513 N_("OXPCIe958 configuration error: failed to read \"UartCount\" as unsigned 32bit integer")); 446 return PDMDEV_SET_ERROR(pDevIns, rc, N_("OXPCIe958 configuration error: failed to read \"UartCount\" as unsigned 32bit integer")); 514 447 515 448 if (!pThis->cUarts || pThis->cUarts > OX958_UARTS_MAX) … … 519 452 520 453 /* 521 * Init instance data.454 * Fill PCI config space. 522 455 */ 523 pThis->fR0Enabled = fR0Enabled;524 pThis->fRCEnabled = fRCEnabled;525 pThis->pDevInsR3 = pDevIns;526 pThis->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);527 pThis->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);528 529 /* Fill PCI config space. */530 456 PPDMPCIDEV pPciDev = pDevIns->apPciDevs[0]; 531 457 PDMPCIDEV_ASSERT_VALID(pDevIns, pPciDev); … … 534 460 PDMPciDevSetDeviceId(pPciDev, OX958_PCI_DEVICE_ID); 535 461 PDMPciDevSetCommand(pPciDev, 0x0000); 536 # ifdef VBOX_WITH_MSI_DEVICES462 # ifdef VBOX_WITH_MSI_DEVICES 537 463 PDMPciDevSetStatus(pPciDev, VBOX_PCI_STATUS_CAP_LIST); 538 464 PDMPciDevSetCapabilityList(pPciDev, OX958_PCI_MSI_CAP_OFS); 539 # else465 # else 540 466 PDMPciDevSetCapabilityList(pPciDev, 0x70); 541 # endif467 # endif 542 468 PDMPciDevSetRevisionId(pPciDev, 0x00); 543 469 PDMPciDevSetClassBase(pPciDev, 0x07); /* Communication controller. */ … … 552 478 PDMPciDevSetInterruptPin(pPciDev, 0x01); 553 479 /** @todo More Capabilities. */ 554 555 rc = PDMDevHlpSetDeviceCritSect(pDevIns, PDMDevHlpCritSectGetNop(pDevIns));556 if (RT_FAILURE(rc))557 return rc;558 480 559 481 /* … … 564 486 return rc; 565 487 566 # ifdef VBOX_WITH_MSI_DEVICES488 # ifdef VBOX_WITH_MSI_DEVICES 567 489 PDMMSIREG MsiReg; 568 490 RT_ZERO(MsiReg); … … 584 506 /* That's OK, we can work without MSI */ 585 507 } 586 #endif 587 588 rc = PDMDevHlpPCIIORegionRegister(pDevIns, 0, _16K, PCI_ADDRESS_SPACE_MEM, ox958R3Map); 589 if (RT_FAILURE(rc)) 590 return rc; 508 # endif 509 510 rc = PDMDevHlpPCIIORegionCreateMmio(pDevIns, 0 /*iPciRegion*/, _16K, PCI_ADDRESS_SPACE_MEM, 511 ox958MmioWrite, ox958MmioRead, NULL /*pvUser*/, 512 IOMMMIO_FLAGS_READ_PASSTHRU | IOMMMIO_FLAGS_WRITE_PASSTHRU, 513 "OxPCIe958", &pThis->hMmio); 514 AssertRCReturn(rc, rc); 591 515 592 516 /** @todo This dynamic symbol resolving will be reworked later! */ … … 595 519 RTRCPTR pfnSerialIrqReqRC = NIL_RTRCPTR; 596 520 597 # ifdef VBOX_WITH_RAW_MODE_KEEP598 if ( fRCEnabled521 # ifdef VBOX_WITH_RAW_MODE_KEEP 522 if ( pDevIns->fRCEnabled 599 523 && VM_IS_RAW_MODE_ENABLED(pVM)) 600 524 { … … 603 527 return rc; 604 528 } 605 # endif606 607 if ( fR0Enabled)529 # endif 530 531 if (pDevIns->fR0Enabled) 608 532 { 609 533 rc = PDMR3LdrGetSymbolR0(pVM, pDevIns->pReg->pszR0Mod, "ox958IrqReq", &pfnSerialIrqReqR0); … … 625 549 } 626 550 627 #endif /* IN_RING3 */ 551 #else /* !IN_RING3 */ 552 553 /** 554 * @callback_method_impl{PDMDEVREGR0,pfnConstruct} 555 */ 556 static DECLCALLBACK(int) ox958RZConstruct(PPDMDEVINS pDevIns) 557 { 558 PDMDEV_CHECK_VERSIONS_RETURN(pDevIns); 559 PDEVOX958 pThis = PDMDEVINS_2_DATA(pDevIns, PDEVOX958); 560 561 int rc = PDMDevHlpSetDeviceCritSect(pDevIns, PDMDevHlpCritSectGetNop(pDevIns)); 562 AssertRCReturn(rc, rc); 563 564 rc = PDMDevHlpMmioSetUpContext(pDevIns, pThis->hMmio, ox958MmioWrite, ox958MmioRead, NULL /*pvUser*/); 565 AssertRCReturn(rc, rc); 566 567 return VINF_SUCCESS; 568 } 569 570 #endif /* !IN_RING3 */ 628 571 629 572 … … 670 613 #elif defined(IN_RING0) 671 614 /* .pfnEarlyConstruct = */ NULL, 672 /* .pfnConstruct = */ NULL,615 /* .pfnConstruct = */ ox958RZConstruct, 673 616 /* .pfnDestruct = */ NULL, 674 617 /* .pfnFinalDestruct = */ NULL, … … 683 626 /* .pfnReserved7 = */ NULL, 684 627 #elif defined(IN_RC) 685 /* .pfnConstruct = */ NULL,628 /* .pfnConstruct = */ ox958RZConstruct, 686 629 /* .pfnReserved0 = */ NULL, 687 630 /* .pfnReserved1 = */ NULL,
Note:
See TracChangeset
for help on using the changeset viewer.