/** * Attach command. * * This is called to let the device attach to a driver for a * specified LUN. * * This is like plugging in the mouse after turning on the * system. * * @returns VBox status code. * @param pThis The PS/2 auxiliary device instance data. * @param pDevIns The device instance. * @param iLUN The logical unit which is being detached. * @param fFlags Flags, combination of the PDMDEVATT_FLAGS_* \#defines. */ int PS2MAttach(PPS2M pThis, PPDMDEVINS pDevIns, unsigned iLUN, uint32_t fFlags) { int rc; /* The LUN must be 1, i.e. mouse. */ Assert(iLUN == 1); AssertMsgReturn(fFlags & PDM_TACH_FLAGS_NOT_HOT_PLUG, ("PS/2 mouse does not support hotplugging\n"), VERR_INVALID_PARAMETER); LogFlowFunc(("iLUN=%d\n", iLUN)); rc = PDMDevHlpDriverAttach(pDevIns, iLUN, &pThis->Mouse.IBase, &pThis->Mouse.pDrvBase, "Mouse Port"); if (RT_SUCCESS(rc)) { pThis->Mouse.pDrv = PDMIBASE_QUERY_INTERFACE(pThis->Mouse.pDrvBase, PDMIMOUSECONNECTOR); if (!pThis->Mouse.pDrv) { AssertLogRelMsgFailed(("LUN #1 doesn't have a mouse interface! rc=%Rrc\n", rc)); rc = VERR_PDM_MISSING_INTERFACE; } } else if (rc == VERR_PDM_NO_ATTACHED_DRIVER) { Log(("%s/%d: warning: no driver attached to LUN #1!\n", pDevIns->pReg->szName, pDevIns->iInstance)); rc = VINF_SUCCESS; } else AssertLogRelMsgFailed(("Failed to attach LUN #1! rc=%Rrc\n", rc)); return rc; }
/** * @interface_method_impl{PDMDEVREG,pfnConstruct} */ static DECLCALLBACK(int) gimdevR3Construct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg) { PDMDEV_CHECK_VERSIONS_RETURN(pDevIns); RT_NOREF2(iInstance, pCfg); Assert(iInstance == 0); PGIMDEV pThis = PDMINS_2_DATA(pDevIns, PGIMDEV); /* * Initialize relevant state bits. */ pThis->pDevInsR3 = pDevIns; pThis->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns); pThis->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns); /* * Get debug setup requirements from GIM. */ PVM pVM = PDMDevHlpGetVM(pDevIns); int rc = GIMR3GetDebugSetup(pVM, &pThis->DbgSetup); if ( RT_SUCCESS(rc) && pThis->DbgSetup.cbDbgRecvBuf > 0) { /* * Attach the stream driver for the debug connection. */ PPDMISTREAM pDbgDrvStream = NULL; pThis->IDbgBase.pfnQueryInterface = gimdevR3QueryInterface; rc = PDMDevHlpDriverAttach(pDevIns, GIMDEV_DEBUG_LUN, &pThis->IDbgBase, &pThis->pDbgDrvBase, "GIM Debug Port"); if (RT_SUCCESS(rc)) { pDbgDrvStream = PDMIBASE_QUERY_INTERFACE(pThis->pDbgDrvBase, PDMISTREAM); if (pDbgDrvStream) LogRel(("GIMDev: LUN#%u: Debug port configured\n", GIMDEV_DEBUG_LUN)); else { LogRel(("GIMDev: LUN#%u: No unit\n", GIMDEV_DEBUG_LUN)); rc = VERR_INTERNAL_ERROR_2; } } else { pThis->pDbgDrvBase = NULL; LogRel(("GIMDev: LUN#%u: No debug port configured! rc=%Rrc\n", GIMDEV_DEBUG_LUN, rc)); } if (!pDbgDrvStream) { Assert(rc != VINF_SUCCESS); return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS, N_("Debug port configuration expected when GIM configured with debugging support")); } void *pvDbgRecvBuf = RTMemAllocZ(pThis->DbgSetup.cbDbgRecvBuf); if (RT_UNLIKELY(!pvDbgRecvBuf)) { LogRel(("GIMDev: Failed to alloc %u bytes for debug receive buffer\n", pThis->DbgSetup.cbDbgRecvBuf)); return VERR_NO_MEMORY; } /* * Update the shared debug struct. */ pThis->Dbg.pDbgDrvStream = pDbgDrvStream; pThis->Dbg.pvDbgRecvBuf = pvDbgRecvBuf; pThis->Dbg.cbDbgRecvBufRead = 0; pThis->Dbg.fDbgRecvBufRead = false; /* * Create the sempahore and the debug receive thread itself. */ rc = RTSemEventMultiCreate(&pThis->Dbg.hDbgRecvThreadSem); if (RT_SUCCESS(rc)) { rc = RTThreadCreate(&pThis->hDbgRecvThread, gimDevR3DbgRecvThread, pDevIns, 0 /*cbStack*/, RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "GIMDebugRecv"); if (RT_FAILURE(rc)) { RTSemEventMultiDestroy(pThis->Dbg.hDbgRecvThreadSem); pThis->Dbg.hDbgRecvThreadSem = NIL_RTSEMEVENTMULTI; RTMemFree(pThis->Dbg.pvDbgRecvBuf); pThis->Dbg.pvDbgRecvBuf = NULL; return rc; } } else return rc; } /* * Register this device with the GIM component. */ GIMR3GimDeviceRegister(pVM, pDevIns, pThis->DbgSetup.cbDbgRecvBuf ? &pThis->Dbg : NULL); /* * Get the MMIO2 regions from the GIM provider. */ uint32_t cRegions = 0; PGIMMMIO2REGION pRegionsR3 = GIMR3GetMmio2Regions(pVM, &cRegions); if ( cRegions && pRegionsR3) { /* * Register the MMIO2 regions. */ PGIMMMIO2REGION pCur = pRegionsR3; for (uint32_t i = 0; i < cRegions; i++, pCur++) { Assert(!pCur->fRegistered); rc = PDMDevHlpMMIO2Register(pDevIns, NULL, pCur->iRegion, pCur->cbRegion, 0 /* fFlags */, &pCur->pvPageR3, pCur->szDescription); if (RT_FAILURE(rc)) return rc; pCur->fRegistered = true; #if defined(VBOX_WITH_2X_4GB_ADDR_SPACE) RTR0PTR pR0Mapping = 0; rc = PDMDevHlpMMIO2MapKernel(pDevIns, NULL, pCur->iRegion, 0 /* off */, pCur->cbRegion, pCur->szDescription, &pR0Mapping); AssertLogRelMsgRCReturn(rc, ("PDMDevHlpMapMMIO2IntoR0(%#x,) -> %Rrc\n", pCur->cbRegion, rc), rc); pCur->pvPageR0 = pR0Mapping; #else pCur->pvPageR0 = (RTR0PTR)pCur->pvPageR3; #endif /* * Map into RC if required. */ if (pCur->fRCMapping) { RTRCPTR pRCMapping = 0; rc = PDMDevHlpMMHyperMapMMIO2(pDevIns, NULL, pCur->iRegion, 0 /* off */, pCur->cbRegion, pCur->szDescription, &pRCMapping); AssertLogRelMsgRCReturn(rc, ("PDMDevHlpMMHyperMapMMIO2(%#x,) -> %Rrc\n", pCur->cbRegion, rc), rc); pCur->pvPageRC = pRCMapping; } else pCur->pvPageRC = NIL_RTRCPTR; LogRel(("GIMDev: Registered %s\n", pCur->szDescription)); } } /** @todo Register SSM: PDMDevHlpSSMRegister(). */ /** @todo Register statistics: STAM_REG(). */ /** @todo Register DBGFInfo: PDMDevHlpDBGFInfoRegister(). */ return VINF_SUCCESS; }