[5212] | 1 | /* $Id: DrvHostBase.cpp 99739 2023-05-11 01:01:08Z vboxsync $ */
|
---|
[1] | 2 | /** @file
|
---|
[5212] | 3 | * DrvHostBase - Host base drive access driver.
|
---|
[1] | 4 | */
|
---|
| 5 |
|
---|
| 6 | /*
|
---|
[98103] | 7 | * Copyright (C) 2006-2023 Oracle and/or its affiliates.
|
---|
[1] | 8 | *
|
---|
[96407] | 9 | * This file is part of VirtualBox base platform packages, as
|
---|
| 10 | * available from https://www.virtualbox.org.
|
---|
| 11 | *
|
---|
| 12 | * This program is free software; you can redistribute it and/or
|
---|
| 13 | * modify it under the terms of the GNU General Public License
|
---|
| 14 | * as published by the Free Software Foundation, in version 3 of the
|
---|
| 15 | * License.
|
---|
| 16 | *
|
---|
| 17 | * This program is distributed in the hope that it will be useful, but
|
---|
| 18 | * WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
| 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
---|
| 20 | * General Public License for more details.
|
---|
| 21 | *
|
---|
| 22 | * You should have received a copy of the GNU General Public License
|
---|
| 23 | * along with this program; if not, see <https://www.gnu.org/licenses>.
|
---|
| 24 | *
|
---|
| 25 | * SPDX-License-Identifier: GPL-3.0-only
|
---|
[1] | 26 | */
|
---|
| 27 |
|
---|
| 28 |
|
---|
[57358] | 29 | /*********************************************************************************************************************************
|
---|
| 30 | * Header Files *
|
---|
| 31 | *********************************************************************************************************************************/
|
---|
[1] | 32 | #define LOG_GROUP LOG_GROUP_DRV_HOST_BASE
|
---|
[1965] | 33 |
|
---|
[35346] | 34 | #include <VBox/vmm/pdmdrv.h>
|
---|
[59252] | 35 | #include <VBox/vmm/pdmstorageifs.h>
|
---|
[76404] | 36 | #include <VBox/err.h>
|
---|
[1] | 37 | #include <iprt/assert.h>
|
---|
| 38 | #include <iprt/file.h>
|
---|
[262] | 39 | #include <iprt/path.h>
|
---|
[1] | 40 | #include <iprt/string.h>
|
---|
| 41 | #include <iprt/thread.h>
|
---|
| 42 | #include <iprt/semaphore.h>
|
---|
| 43 | #include <iprt/uuid.h>
|
---|
| 44 | #include <iprt/asm.h>
|
---|
| 45 | #include <iprt/critsect.h>
|
---|
[1965] | 46 | #include <iprt/ctype.h>
|
---|
[52505] | 47 | #include <iprt/mem.h>
|
---|
[1] | 48 |
|
---|
| 49 | #include "DrvHostBase.h"
|
---|
| 50 |
|
---|
| 51 |
|
---|
| 52 |
|
---|
| 53 |
|
---|
| 54 | /* -=-=-=-=- IBlock -=-=-=-=- */
|
---|
| 55 |
|
---|
[64274] | 56 | /** @interface_method_impl{PDMIMEDIA,pfnRead} */
|
---|
[59248] | 57 | static DECLCALLBACK(int) drvHostBaseRead(PPDMIMEDIA pInterface, uint64_t off, void *pvBuf, size_t cbRead)
|
---|
[1] | 58 | {
|
---|
[64316] | 59 | PDRVHOSTBASE pThis = RT_FROM_MEMBER(pInterface, DRVHOSTBASE, IMedia);
|
---|
[1] | 60 | LogFlow(("%s-%d: drvHostBaseRead: off=%#llx pvBuf=%p cbRead=%#x (%s)\n",
|
---|
[26166] | 61 | pThis->pDrvIns->pReg->szName, pThis->pDrvIns->iInstance, off, pvBuf, cbRead, pThis->pszDevice));
|
---|
[1] | 62 | RTCritSectEnter(&pThis->CritSect);
|
---|
| 63 |
|
---|
[64839] | 64 | STAM_REL_COUNTER_INC(&pThis->StatReqsSubmitted);
|
---|
| 65 | STAM_REL_COUNTER_INC(&pThis->StatReqsRead);
|
---|
| 66 |
|
---|
[1] | 67 | /*
|
---|
| 68 | * Check the state.
|
---|
| 69 | */
|
---|
| 70 | int rc;
|
---|
| 71 | if (pThis->fMediaPresent)
|
---|
| 72 | {
|
---|
| 73 | /*
|
---|
| 74 | * Seek and read.
|
---|
| 75 | */
|
---|
[64251] | 76 | rc = drvHostBaseReadOs(pThis, off, pvBuf, cbRead);
|
---|
[11266] | 77 | if (RT_SUCCESS(rc))
|
---|
[1] | 78 | {
|
---|
[64251] | 79 | Log2(("%s-%d: drvHostBaseReadOs: off=%#llx cbRead=%#x\n"
|
---|
[37596] | 80 | "%16.*Rhxd\n",
|
---|
| 81 | pThis->pDrvIns->pReg->szName, pThis->pDrvIns->iInstance, off, cbRead, cbRead, pvBuf));
|
---|
[1] | 82 | }
|
---|
| 83 | else
|
---|
[64320] | 84 | Log(("%s-%d: drvHostBaseRead: drvHostBaseReadOs(%#llx, %p, %#x) -> %Rrc ('%s')\n",
|
---|
[64251] | 85 | pThis->pDrvIns->pReg->szName, pThis->pDrvIns->iInstance,
|
---|
[37596] | 86 | off, pvBuf, cbRead, rc, pThis->pszDevice));
|
---|
[1] | 87 | }
|
---|
| 88 | else
|
---|
| 89 | rc = VERR_MEDIA_NOT_PRESENT;
|
---|
| 90 |
|
---|
[64839] | 91 | if (RT_SUCCESS(rc))
|
---|
| 92 | {
|
---|
| 93 | STAM_REL_COUNTER_INC(&pThis->StatReqsSucceeded);
|
---|
| 94 | STAM_REL_COUNTER_ADD(&pThis->StatBytesRead, cbRead);
|
---|
| 95 | }
|
---|
| 96 | else
|
---|
| 97 | STAM_REL_COUNTER_INC(&pThis->StatReqsFailed);
|
---|
| 98 |
|
---|
[1] | 99 | RTCritSectLeave(&pThis->CritSect);
|
---|
[26166] | 100 | LogFlow(("%s-%d: drvHostBaseRead: returns %Rrc\n", pThis->pDrvIns->pReg->szName, pThis->pDrvIns->iInstance, rc));
|
---|
[1] | 101 | return rc;
|
---|
| 102 | }
|
---|
| 103 |
|
---|
| 104 |
|
---|
[64274] | 105 | /** @interface_method_impl{PDMIMEDIA,pfnWrite} */
|
---|
[59248] | 106 | static DECLCALLBACK(int) drvHostBaseWrite(PPDMIMEDIA pInterface, uint64_t off, const void *pvBuf, size_t cbWrite)
|
---|
[1] | 107 | {
|
---|
[64316] | 108 | PDRVHOSTBASE pThis = RT_FROM_MEMBER(pInterface, DRVHOSTBASE, IMedia);
|
---|
[1] | 109 | LogFlow(("%s-%d: drvHostBaseWrite: off=%#llx pvBuf=%p cbWrite=%#x (%s)\n",
|
---|
[26166] | 110 | pThis->pDrvIns->pReg->szName, pThis->pDrvIns->iInstance, off, pvBuf, cbWrite, pThis->pszDevice));
|
---|
[1] | 111 | Log2(("%s-%d: drvHostBaseWrite: off=%#llx cbWrite=%#x\n"
|
---|
[13840] | 112 | "%16.*Rhxd\n",
|
---|
[26166] | 113 | pThis->pDrvIns->pReg->szName, pThis->pDrvIns->iInstance, off, cbWrite, cbWrite, pvBuf));
|
---|
[1] | 114 | RTCritSectEnter(&pThis->CritSect);
|
---|
| 115 |
|
---|
[64839] | 116 | STAM_REL_COUNTER_INC(&pThis->StatReqsSubmitted);
|
---|
| 117 | STAM_REL_COUNTER_INC(&pThis->StatReqsWrite);
|
---|
| 118 |
|
---|
[1] | 119 | /*
|
---|
| 120 | * Check the state.
|
---|
| 121 | */
|
---|
| 122 | int rc;
|
---|
| 123 | if (!pThis->fReadOnly)
|
---|
| 124 | {
|
---|
| 125 | if (pThis->fMediaPresent)
|
---|
| 126 | {
|
---|
| 127 | /*
|
---|
| 128 | * Seek and write.
|
---|
| 129 | */
|
---|
[64251] | 130 | rc = drvHostBaseWriteOs(pThis, off, pvBuf, cbWrite);
|
---|
[37596] | 131 | if (RT_FAILURE(rc))
|
---|
[64251] | 132 | Log(("%s-%d: drvHostBaseWrite: drvHostBaseWriteOs(%#llx, %p, %#x) -> %Rrc ('%s')\n",
|
---|
| 133 | pThis->pDrvIns->pReg->szName, pThis->pDrvIns->iInstance,
|
---|
[37596] | 134 | off, pvBuf, cbWrite, rc, pThis->pszDevice));
|
---|
[1] | 135 | }
|
---|
| 136 | else
|
---|
| 137 | rc = VERR_MEDIA_NOT_PRESENT;
|
---|
| 138 | }
|
---|
| 139 | else
|
---|
| 140 | rc = VERR_WRITE_PROTECT;
|
---|
| 141 |
|
---|
[64839] | 142 | if (RT_SUCCESS(rc))
|
---|
| 143 | {
|
---|
| 144 | STAM_REL_COUNTER_INC(&pThis->StatReqsSucceeded);
|
---|
| 145 | STAM_REL_COUNTER_ADD(&pThis->StatBytesWritten, cbWrite);
|
---|
| 146 | }
|
---|
| 147 | else
|
---|
| 148 | STAM_REL_COUNTER_INC(&pThis->StatReqsFailed);
|
---|
| 149 |
|
---|
[1] | 150 | RTCritSectLeave(&pThis->CritSect);
|
---|
[26166] | 151 | LogFlow(("%s-%d: drvHostBaseWrite: returns %Rrc\n", pThis->pDrvIns->pReg->szName, pThis->pDrvIns->iInstance, rc));
|
---|
[1] | 152 | return rc;
|
---|
| 153 | }
|
---|
| 154 |
|
---|
| 155 |
|
---|
[64274] | 156 | /** @interface_method_impl{PDMIMEDIA,pfnFlush} */
|
---|
[59248] | 157 | static DECLCALLBACK(int) drvHostBaseFlush(PPDMIMEDIA pInterface)
|
---|
[1] | 158 | {
|
---|
| 159 | int rc;
|
---|
[64316] | 160 | PDRVHOSTBASE pThis = RT_FROM_MEMBER(pInterface, DRVHOSTBASE, IMedia);
|
---|
[1] | 161 | LogFlow(("%s-%d: drvHostBaseFlush: (%s)\n",
|
---|
[26166] | 162 | pThis->pDrvIns->pReg->szName, pThis->pDrvIns->iInstance, pThis->pszDevice));
|
---|
[1] | 163 | RTCritSectEnter(&pThis->CritSect);
|
---|
| 164 |
|
---|
[64839] | 165 | STAM_REL_COUNTER_INC(&pThis->StatReqsSubmitted);
|
---|
| 166 | STAM_REL_COUNTER_INC(&pThis->StatReqsFlush);
|
---|
| 167 |
|
---|
[1] | 168 | if (pThis->fMediaPresent)
|
---|
[64251] | 169 | rc = drvHostBaseFlushOs(pThis);
|
---|
[1] | 170 | else
|
---|
| 171 | rc = VERR_MEDIA_NOT_PRESENT;
|
---|
| 172 |
|
---|
[64839] | 173 | if (RT_SUCCESS(rc))
|
---|
| 174 | STAM_REL_COUNTER_INC(&pThis->StatReqsSucceeded);
|
---|
| 175 | else
|
---|
| 176 | STAM_REL_COUNTER_INC(&pThis->StatReqsFailed);
|
---|
| 177 |
|
---|
[1] | 178 | RTCritSectLeave(&pThis->CritSect);
|
---|
[26166] | 179 | LogFlow(("%s-%d: drvHostBaseFlush: returns %Rrc\n", pThis->pDrvIns->pReg->szName, pThis->pDrvIns->iInstance, rc));
|
---|
[1] | 180 | return rc;
|
---|
| 181 | }
|
---|
| 182 |
|
---|
| 183 |
|
---|
[64274] | 184 | /** @interface_method_impl{PDMIMEDIA,pfnIsReadOnly} */
|
---|
[59248] | 185 | static DECLCALLBACK(bool) drvHostBaseIsReadOnly(PPDMIMEDIA pInterface)
|
---|
[1] | 186 | {
|
---|
[64316] | 187 | PDRVHOSTBASE pThis = RT_FROM_MEMBER(pInterface, DRVHOSTBASE, IMedia);
|
---|
[1] | 188 | return pThis->fReadOnly;
|
---|
| 189 | }
|
---|
| 190 |
|
---|
| 191 |
|
---|
[64093] | 192 | /** @interface_method_impl{PDMIMEDIA,pfnIsNonRotational} */
|
---|
| 193 | static DECLCALLBACK(bool) drvHostBaseIsNonRotational(PPDMIMEDIA pInterface)
|
---|
| 194 | {
|
---|
| 195 | RT_NOREF1(pInterface);
|
---|
| 196 | return false;
|
---|
| 197 | }
|
---|
| 198 |
|
---|
| 199 |
|
---|
[64274] | 200 | /** @interface_method_impl{PDMIMEDIA,pfnGetSize} */
|
---|
[59248] | 201 | static DECLCALLBACK(uint64_t) drvHostBaseGetSize(PPDMIMEDIA pInterface)
|
---|
[1] | 202 | {
|
---|
[64316] | 203 | PDRVHOSTBASE pThis = RT_FROM_MEMBER(pInterface, DRVHOSTBASE, IMedia);
|
---|
[1] | 204 | RTCritSectEnter(&pThis->CritSect);
|
---|
| 205 |
|
---|
| 206 | uint64_t cb = 0;
|
---|
| 207 | if (pThis->fMediaPresent)
|
---|
| 208 | cb = pThis->cbSize;
|
---|
| 209 |
|
---|
| 210 | RTCritSectLeave(&pThis->CritSect);
|
---|
[26166] | 211 | LogFlow(("%s-%d: drvHostBaseGetSize: returns %llu\n", pThis->pDrvIns->pReg->szName, pThis->pDrvIns->iInstance, cb));
|
---|
[1] | 212 | return cb;
|
---|
| 213 | }
|
---|
| 214 |
|
---|
| 215 |
|
---|
[64274] | 216 | /** @interface_method_impl{PDMIMEDIA,pfnGetType} */
|
---|
[59248] | 217 | static DECLCALLBACK(PDMMEDIATYPE) drvHostBaseGetType(PPDMIMEDIA pInterface)
|
---|
[1] | 218 | {
|
---|
[64316] | 219 | PDRVHOSTBASE pThis = RT_FROM_MEMBER(pInterface, DRVHOSTBASE, IMedia);
|
---|
[26166] | 220 | LogFlow(("%s-%d: drvHostBaseGetType: returns %d\n", pThis->pDrvIns->pReg->szName, pThis->pDrvIns->iInstance, pThis->enmType));
|
---|
[1] | 221 | return pThis->enmType;
|
---|
| 222 | }
|
---|
| 223 |
|
---|
| 224 |
|
---|
[64274] | 225 | /** @interface_method_impl{PDMIMEDIA,pfnGetUuid} */
|
---|
[59248] | 226 | static DECLCALLBACK(int) drvHostBaseGetUuid(PPDMIMEDIA pInterface, PRTUUID pUuid)
|
---|
[1] | 227 | {
|
---|
[64316] | 228 | PDRVHOSTBASE pThis = RT_FROM_MEMBER(pInterface, DRVHOSTBASE, IMedia);
|
---|
[1] | 229 |
|
---|
| 230 | *pUuid = pThis->Uuid;
|
---|
| 231 |
|
---|
[26166] | 232 | LogFlow(("%s-%d: drvHostBaseGetUuid: returns VINF_SUCCESS *pUuid=%RTuuid\n", pThis->pDrvIns->pReg->szName, pThis->pDrvIns->iInstance, pUuid));
|
---|
[1] | 233 | return VINF_SUCCESS;
|
---|
| 234 | }
|
---|
| 235 |
|
---|
| 236 |
|
---|
[64274] | 237 | /** @interface_method_impl{PDMIMEDIA,pfnBiosGetPCHSGeometry} */
|
---|
[59248] | 238 | static DECLCALLBACK(int) drvHostBaseGetPCHSGeometry(PPDMIMEDIA pInterface, PPDMMEDIAGEOMETRY pPCHSGeometry)
|
---|
[1] | 239 | {
|
---|
[64316] | 240 | PDRVHOSTBASE pThis = RT_FROM_MEMBER(pInterface, DRVHOSTBASE, IMedia);
|
---|
[1] | 241 | RTCritSectEnter(&pThis->CritSect);
|
---|
| 242 |
|
---|
| 243 | int rc = VINF_SUCCESS;
|
---|
| 244 | if (pThis->fMediaPresent)
|
---|
| 245 | {
|
---|
[6291] | 246 | if ( pThis->PCHSGeometry.cCylinders > 0
|
---|
| 247 | && pThis->PCHSGeometry.cHeads > 0
|
---|
| 248 | && pThis->PCHSGeometry.cSectors > 0)
|
---|
[1] | 249 | {
|
---|
[6291] | 250 | *pPCHSGeometry = pThis->PCHSGeometry;
|
---|
[1] | 251 | }
|
---|
| 252 | else
|
---|
| 253 | rc = VERR_PDM_GEOMETRY_NOT_SET;
|
---|
| 254 | }
|
---|
| 255 | else
|
---|
| 256 | rc = VERR_PDM_MEDIA_NOT_MOUNTED;
|
---|
| 257 |
|
---|
| 258 | RTCritSectLeave(&pThis->CritSect);
|
---|
[11284] | 259 | LogFlow(("%s-%d: %s: returns %Rrc CHS={%d,%d,%d}\n",
|
---|
[64320] | 260 | pThis->pDrvIns->pReg->szName, pThis->pDrvIns->iInstance, __FUNCTION__, rc,
|
---|
| 261 | pThis->PCHSGeometry.cCylinders, pThis->PCHSGeometry.cHeads, pThis->PCHSGeometry.cSectors));
|
---|
[1] | 262 | return rc;
|
---|
| 263 | }
|
---|
| 264 |
|
---|
| 265 |
|
---|
[64274] | 266 | /** @interface_method_impl{PDMIMEDIA,pfnBiosSetPCHSGeometry} */
|
---|
[59248] | 267 | static DECLCALLBACK(int) drvHostBaseSetPCHSGeometry(PPDMIMEDIA pInterface, PCPDMMEDIAGEOMETRY pPCHSGeometry)
|
---|
[1] | 268 | {
|
---|
[64316] | 269 | PDRVHOSTBASE pThis = RT_FROM_MEMBER(pInterface, DRVHOSTBASE, IMedia);
|
---|
[6291] | 270 | LogFlow(("%s-%d: %s: cCylinders=%d cHeads=%d cSectors=%d\n",
|
---|
[64320] | 271 | pThis->pDrvIns->pReg->szName, pThis->pDrvIns->iInstance, __FUNCTION__,
|
---|
| 272 | pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
|
---|
[1] | 273 | RTCritSectEnter(&pThis->CritSect);
|
---|
| 274 |
|
---|
| 275 | int rc = VINF_SUCCESS;
|
---|
| 276 | if (pThis->fMediaPresent)
|
---|
| 277 | {
|
---|
[6291] | 278 | pThis->PCHSGeometry = *pPCHSGeometry;
|
---|
[1] | 279 | }
|
---|
| 280 | else
|
---|
| 281 | {
|
---|
| 282 | AssertMsgFailed(("Invalid state! Not mounted!\n"));
|
---|
| 283 | rc = VERR_PDM_MEDIA_NOT_MOUNTED;
|
---|
| 284 | }
|
---|
| 285 |
|
---|
| 286 | RTCritSectLeave(&pThis->CritSect);
|
---|
| 287 | return rc;
|
---|
| 288 | }
|
---|
| 289 |
|
---|
| 290 |
|
---|
[64274] | 291 | /** @interface_method_impl{PDMIMEDIA,pfnBiosGetLCHSGeometry} */
|
---|
[59248] | 292 | static DECLCALLBACK(int) drvHostBaseGetLCHSGeometry(PPDMIMEDIA pInterface, PPDMMEDIAGEOMETRY pLCHSGeometry)
|
---|
[1] | 293 | {
|
---|
[64316] | 294 | PDRVHOSTBASE pThis = RT_FROM_MEMBER(pInterface, DRVHOSTBASE, IMedia);
|
---|
[1] | 295 | RTCritSectEnter(&pThis->CritSect);
|
---|
| 296 |
|
---|
| 297 | int rc = VINF_SUCCESS;
|
---|
| 298 | if (pThis->fMediaPresent)
|
---|
| 299 | {
|
---|
[6291] | 300 | if ( pThis->LCHSGeometry.cCylinders > 0
|
---|
| 301 | && pThis->LCHSGeometry.cHeads > 0
|
---|
| 302 | && pThis->LCHSGeometry.cSectors > 0)
|
---|
| 303 | {
|
---|
| 304 | *pLCHSGeometry = pThis->LCHSGeometry;
|
---|
| 305 | }
|
---|
[1] | 306 | else
|
---|
[6291] | 307 | rc = VERR_PDM_GEOMETRY_NOT_SET;
|
---|
[1] | 308 | }
|
---|
| 309 | else
|
---|
| 310 | rc = VERR_PDM_MEDIA_NOT_MOUNTED;
|
---|
| 311 |
|
---|
| 312 | RTCritSectLeave(&pThis->CritSect);
|
---|
[11284] | 313 | LogFlow(("%s-%d: %s: returns %Rrc CHS={%d,%d,%d}\n",
|
---|
[64320] | 314 | pThis->pDrvIns->pReg->szName, pThis->pDrvIns->iInstance, __FUNCTION__, rc,
|
---|
| 315 | pThis->LCHSGeometry.cCylinders, pThis->LCHSGeometry.cHeads, pThis->LCHSGeometry.cSectors));
|
---|
[1] | 316 | return rc;
|
---|
| 317 | }
|
---|
| 318 |
|
---|
| 319 |
|
---|
[64274] | 320 | /** @interface_method_impl{PDMIMEDIA,pfnBiosSetLCHSGeometry} */
|
---|
[59248] | 321 | static DECLCALLBACK(int) drvHostBaseSetLCHSGeometry(PPDMIMEDIA pInterface, PCPDMMEDIAGEOMETRY pLCHSGeometry)
|
---|
[1] | 322 | {
|
---|
[64316] | 323 | PDRVHOSTBASE pThis = RT_FROM_MEMBER(pInterface, DRVHOSTBASE, IMedia);
|
---|
[6291] | 324 | LogFlow(("%s-%d: %s: cCylinders=%d cHeads=%d cSectors=%d\n",
|
---|
[64320] | 325 | pThis->pDrvIns->pReg->szName, pThis->pDrvIns->iInstance, __FUNCTION__,
|
---|
| 326 | pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
|
---|
[1] | 327 | RTCritSectEnter(&pThis->CritSect);
|
---|
| 328 |
|
---|
| 329 | int rc = VINF_SUCCESS;
|
---|
| 330 | if (pThis->fMediaPresent)
|
---|
| 331 | {
|
---|
[6291] | 332 | pThis->LCHSGeometry = *pLCHSGeometry;
|
---|
[1] | 333 | }
|
---|
| 334 | else
|
---|
| 335 | {
|
---|
| 336 | AssertMsgFailed(("Invalid state! Not mounted!\n"));
|
---|
| 337 | rc = VERR_PDM_MEDIA_NOT_MOUNTED;
|
---|
| 338 | }
|
---|
| 339 |
|
---|
| 340 | RTCritSectLeave(&pThis->CritSect);
|
---|
| 341 | return rc;
|
---|
| 342 | }
|
---|
| 343 |
|
---|
| 344 |
|
---|
[64274] | 345 | /** @interface_method_impl{PDMIMEDIA,pfnBiosIsVisible} */
|
---|
[59248] | 346 | static DECLCALLBACK(bool) drvHostBaseIsVisible(PPDMIMEDIA pInterface)
|
---|
[1] | 347 | {
|
---|
[64316] | 348 | PDRVHOSTBASE pThis = RT_FROM_MEMBER(pInterface, DRVHOSTBASE, IMedia);
|
---|
[1] | 349 | return pThis->fBiosVisible;
|
---|
| 350 | }
|
---|
| 351 |
|
---|
| 352 |
|
---|
[66165] | 353 | /** @interface_method_impl{PDMIMEDIA,pfnGetRegionCount} */
|
---|
| 354 | static DECLCALLBACK(uint32_t) drvHostBaseGetRegionCount(PPDMIMEDIA pInterface)
|
---|
| 355 | {
|
---|
[67841] | 356 | PDRVHOSTBASE pThis = RT_FROM_MEMBER(pInterface, DRVHOSTBASE, IMedia);
|
---|
[1] | 357 |
|
---|
[66165] | 358 | LogFlowFunc(("\n"));
|
---|
[67841] | 359 | uint32_t cRegions = pThis->fMediaPresent ? 1 : 0;
|
---|
[66165] | 360 |
|
---|
| 361 | /* For now just return one region for all devices. */
|
---|
[69304] | 362 | /** @todo Handle CD/DVD passthrough properly. */
|
---|
[66165] | 363 |
|
---|
| 364 | LogFlowFunc(("returns %u\n", cRegions));
|
---|
| 365 | return cRegions;
|
---|
| 366 | }
|
---|
| 367 |
|
---|
| 368 | /** @interface_method_impl{PDMIMEDIA,pfnQueryRegionProperties} */
|
---|
| 369 | static DECLCALLBACK(int) drvHostBaseQueryRegionProperties(PPDMIMEDIA pInterface, uint32_t uRegion, uint64_t *pu64LbaStart,
|
---|
| 370 | uint64_t *pcBlocks, uint64_t *pcbBlock,
|
---|
[66192] | 371 | PVDREGIONDATAFORM penmDataForm)
|
---|
[66165] | 372 | {
|
---|
| 373 | LogFlowFunc(("\n"));
|
---|
| 374 | int rc = VINF_SUCCESS;
|
---|
| 375 | PDRVHOSTBASE pThis = RT_FROM_MEMBER(pInterface, DRVHOSTBASE, IMedia);
|
---|
| 376 |
|
---|
[67841] | 377 | if (uRegion < 1 && pThis->fMediaPresent)
|
---|
[66165] | 378 | {
|
---|
| 379 | uint64_t cbMedia;
|
---|
| 380 | rc = drvHostBaseGetMediaSizeOs(pThis, &cbMedia);
|
---|
| 381 | if (RT_SUCCESS(rc))
|
---|
| 382 | {
|
---|
| 383 | uint64_t cbBlock = 0;
|
---|
| 384 |
|
---|
| 385 | if (pThis->enmType == PDMMEDIATYPE_DVD)
|
---|
| 386 | cbBlock = 2048;
|
---|
| 387 | else
|
---|
| 388 | cbBlock = 512; /* Floppy. */
|
---|
| 389 |
|
---|
| 390 | if (pu64LbaStart)
|
---|
| 391 | *pu64LbaStart = 0;
|
---|
| 392 | if (pcBlocks)
|
---|
| 393 | *pcBlocks = cbMedia / cbBlock;
|
---|
| 394 | if (pcbBlock)
|
---|
| 395 | *pcbBlock = cbBlock;
|
---|
| 396 | if (penmDataForm)
|
---|
[66192] | 397 | *penmDataForm = VDREGIONDATAFORM_RAW;
|
---|
[66165] | 398 | }
|
---|
| 399 | }
|
---|
| 400 | else
|
---|
| 401 | rc = VERR_NOT_FOUND;
|
---|
| 402 |
|
---|
| 403 | LogFlowFunc(("returns %Rrc\n", rc));
|
---|
| 404 | return rc;
|
---|
| 405 | }
|
---|
| 406 |
|
---|
| 407 | /** @interface_method_impl{PDMIMEDIA,pfnQueryRegionPropertiesForLba} */
|
---|
| 408 | static DECLCALLBACK(int) drvHostBaseQueryRegionPropertiesForLba(PPDMIMEDIA pInterface, uint64_t u64LbaStart,
|
---|
[66193] | 409 | uint32_t *puRegion, uint64_t *pcBlocks,
|
---|
| 410 | uint64_t *pcbBlock, PVDREGIONDATAFORM penmDataForm)
|
---|
[66165] | 411 | {
|
---|
| 412 | LogFlowFunc(("\n"));
|
---|
| 413 | int rc = VINF_SUCCESS;
|
---|
| 414 | PDRVHOSTBASE pThis = RT_FROM_MEMBER(pInterface, DRVHOSTBASE, IMedia);
|
---|
| 415 | uint64_t cbMedia;
|
---|
| 416 | uint64_t cbBlock = 0;
|
---|
| 417 |
|
---|
| 418 | if (pThis->enmType == PDMMEDIATYPE_DVD)
|
---|
| 419 | cbBlock = 2048;
|
---|
| 420 | else
|
---|
| 421 | cbBlock = 512; /* Floppy. */
|
---|
| 422 |
|
---|
| 423 | rc = drvHostBaseGetMediaSizeOs(pThis, &cbMedia);
|
---|
| 424 | if ( RT_SUCCESS(rc)
|
---|
| 425 | && u64LbaStart < cbMedia / cbBlock)
|
---|
| 426 | {
|
---|
[66193] | 427 | if (puRegion)
|
---|
| 428 | *puRegion = 0;
|
---|
[66165] | 429 | if (pcBlocks)
|
---|
| 430 | *pcBlocks = cbMedia / cbBlock;
|
---|
| 431 | if (pcbBlock)
|
---|
| 432 | *pcbBlock = cbBlock;
|
---|
| 433 | if (penmDataForm)
|
---|
[66192] | 434 | *penmDataForm = VDREGIONDATAFORM_RAW;
|
---|
[66165] | 435 | }
|
---|
| 436 | else
|
---|
| 437 | rc = VERR_NOT_FOUND;
|
---|
| 438 |
|
---|
| 439 | LogFlowFunc(("returns %Rrc\n", rc));
|
---|
| 440 | return rc;
|
---|
| 441 | }
|
---|
| 442 |
|
---|
| 443 |
|
---|
| 444 |
|
---|
[64320] | 445 | /* -=-=-=-=- IMediaEx -=-=-=-=- */
|
---|
| 446 |
|
---|
| 447 | DECLHIDDEN(int) drvHostBaseBufferRetain(PDRVHOSTBASE pThis, PDRVHOSTBASEREQ pReq, size_t cbBuf, bool fWrite, void **ppvBuf)
|
---|
| 448 | {
|
---|
| 449 | int rc = VINF_SUCCESS;
|
---|
| 450 |
|
---|
| 451 | if (pThis->cbBuf < cbBuf)
|
---|
| 452 | {
|
---|
| 453 | RTMemFree(pThis->pvBuf);
|
---|
| 454 | pThis->cbBuf = 0;
|
---|
| 455 | pThis->pvBuf = RTMemAlloc(cbBuf);
|
---|
| 456 | if (pThis->pvBuf)
|
---|
| 457 | pThis->cbBuf = cbBuf;
|
---|
| 458 | else
|
---|
| 459 | rc = VERR_NO_MEMORY;
|
---|
| 460 | }
|
---|
| 461 |
|
---|
| 462 | if (RT_SUCCESS(rc) && fWrite)
|
---|
| 463 | {
|
---|
| 464 | RTSGSEG Seg;
|
---|
| 465 | RTSGBUF SgBuf;
|
---|
| 466 |
|
---|
| 467 | Seg.pvSeg = pThis->pvBuf;
|
---|
| 468 | Seg.cbSeg = cbBuf;
|
---|
| 469 | RTSgBufInit(&SgBuf, &Seg, 1);
|
---|
| 470 | rc = pThis->pDrvMediaExPort->pfnIoReqCopyToBuf(pThis->pDrvMediaExPort, (PDMMEDIAEXIOREQ)pReq,
|
---|
| 471 | &pReq->abAlloc[0], 0, &SgBuf, cbBuf);
|
---|
| 472 | }
|
---|
| 473 |
|
---|
| 474 | if (RT_SUCCESS(rc))
|
---|
| 475 | *ppvBuf = pThis->pvBuf;
|
---|
| 476 |
|
---|
| 477 | return rc;
|
---|
| 478 | }
|
---|
| 479 |
|
---|
| 480 | DECLHIDDEN(int) drvHostBaseBufferRelease(PDRVHOSTBASE pThis, PDRVHOSTBASEREQ pReq, size_t cbBuf, bool fWrite, void *pvBuf)
|
---|
| 481 | {
|
---|
| 482 | int rc = VINF_SUCCESS;
|
---|
| 483 |
|
---|
| 484 | if (!fWrite)
|
---|
| 485 | {
|
---|
| 486 | RTSGSEG Seg;
|
---|
| 487 | RTSGBUF SgBuf;
|
---|
| 488 |
|
---|
| 489 | Seg.pvSeg = pvBuf;
|
---|
| 490 | Seg.cbSeg = cbBuf;
|
---|
| 491 | RTSgBufInit(&SgBuf, &Seg, 1);
|
---|
| 492 | rc = pThis->pDrvMediaExPort->pfnIoReqCopyFromBuf(pThis->pDrvMediaExPort, (PDMMEDIAEXIOREQ)pReq,
|
---|
| 493 | &pReq->abAlloc[0], 0, &SgBuf, cbBuf);
|
---|
| 494 | }
|
---|
| 495 |
|
---|
| 496 | return rc;
|
---|
| 497 | }
|
---|
| 498 |
|
---|
| 499 | /** @interface_method_impl{PDMIMEDIAEX,pfnQueryFeatures} */
|
---|
| 500 | static DECLCALLBACK(int) drvHostBaseQueryFeatures(PPDMIMEDIAEX pInterface, uint32_t *pfFeatures)
|
---|
| 501 | {
|
---|
| 502 | PDRVHOSTBASE pThis = RT_FROM_MEMBER(pInterface, DRVHOSTBASE, IMediaEx);
|
---|
| 503 |
|
---|
| 504 | *pfFeatures = pThis->IMediaEx.pfnIoReqSendScsiCmd ? PDMIMEDIAEX_FEATURE_F_RAWSCSICMD : 0;
|
---|
| 505 | return VINF_SUCCESS;
|
---|
| 506 | }
|
---|
| 507 |
|
---|
[71807] | 508 | /** @interface_method_impl{PDMIMEDIAEX,pfnNotifySuspend} */
|
---|
| 509 | static DECLCALLBACK(void) drvHostBaseNotifySuspend(PPDMIMEDIAEX pInterface)
|
---|
| 510 | {
|
---|
| 511 | RT_NOREF(pInterface); /* Nothing to do here. */
|
---|
| 512 | }
|
---|
| 513 |
|
---|
[64320] | 514 | /** @interface_method_impl{PDMIMEDIAEX,pfnIoReqAllocSizeSet} */
|
---|
| 515 | static DECLCALLBACK(int) drvHostBaseIoReqAllocSizeSet(PPDMIMEDIAEX pInterface, size_t cbIoReqAlloc)
|
---|
| 516 | {
|
---|
| 517 | PDRVHOSTBASE pThis = RT_FROM_MEMBER(pInterface, DRVHOSTBASE, IMediaEx);
|
---|
| 518 |
|
---|
[73097] | 519 | pThis->cbIoReqAlloc = RT_UOFFSETOF_DYN(DRVHOSTBASEREQ, abAlloc[cbIoReqAlloc]);
|
---|
[64320] | 520 | return VINF_SUCCESS;
|
---|
| 521 | }
|
---|
| 522 |
|
---|
| 523 | /** @interface_method_impl{PDMIMEDIAEX,pfnIoReqAlloc} */
|
---|
| 524 | static DECLCALLBACK(int) drvHostBaseIoReqAlloc(PPDMIMEDIAEX pInterface, PPDMMEDIAEXIOREQ phIoReq, void **ppvIoReqAlloc,
|
---|
| 525 | PDMMEDIAEXIOREQID uIoReqId, uint32_t fFlags)
|
---|
| 526 | {
|
---|
| 527 | RT_NOREF2(uIoReqId, fFlags);
|
---|
| 528 |
|
---|
| 529 | int rc = VINF_SUCCESS;
|
---|
| 530 | PDRVHOSTBASE pThis = RT_FROM_MEMBER(pInterface, DRVHOSTBASE, IMediaEx);
|
---|
| 531 | PDRVHOSTBASEREQ pReq = (PDRVHOSTBASEREQ)RTMemAllocZ(pThis->cbIoReqAlloc);
|
---|
| 532 | if (RT_LIKELY(pReq))
|
---|
| 533 | {
|
---|
[64407] | 534 | pReq->cbReq = 0;
|
---|
| 535 | pReq->cbResidual = 0;
|
---|
[64320] | 536 | *phIoReq = (PDMMEDIAEXIOREQ)pReq;
|
---|
| 537 | *ppvIoReqAlloc = &pReq->abAlloc[0];
|
---|
| 538 | }
|
---|
| 539 | else
|
---|
| 540 | rc = VERR_NO_MEMORY;
|
---|
| 541 |
|
---|
| 542 | return rc;
|
---|
| 543 | }
|
---|
| 544 |
|
---|
| 545 | /** @interface_method_impl{PDMIMEDIAEX,pfnIoReqFree} */
|
---|
| 546 | static DECLCALLBACK(int) drvHostBaseIoReqFree(PPDMIMEDIAEX pInterface, PDMMEDIAEXIOREQ hIoReq)
|
---|
| 547 | {
|
---|
| 548 | RT_NOREF1(pInterface);
|
---|
| 549 | PDRVHOSTBASEREQ pReq = (PDRVHOSTBASEREQ)hIoReq;
|
---|
| 550 |
|
---|
| 551 | RTMemFree(pReq);
|
---|
| 552 | return VINF_SUCCESS;
|
---|
| 553 | }
|
---|
| 554 |
|
---|
| 555 | /** @interface_method_impl{PDMIMEDIAEX,pfnIoReqQueryResidual} */
|
---|
| 556 | static DECLCALLBACK(int) drvHostBaseIoReqQueryResidual(PPDMIMEDIAEX pInterface, PDMMEDIAEXIOREQ hIoReq, size_t *pcbResidual)
|
---|
| 557 | {
|
---|
[64407] | 558 | RT_NOREF1(pInterface);
|
---|
| 559 | PDRVHOSTBASEREQ pReq = (PDRVHOSTBASEREQ)hIoReq;
|
---|
[64320] | 560 |
|
---|
[64407] | 561 | *pcbResidual = pReq->cbResidual;
|
---|
[64320] | 562 | return VINF_SUCCESS;
|
---|
| 563 | }
|
---|
| 564 |
|
---|
[64407] | 565 | /** @interface_method_impl{PDMIMEDIAEX,pfnIoReqQueryXferSize} */
|
---|
| 566 | static DECLCALLBACK(int) drvHostBaseIoReqQueryXferSize(PPDMIMEDIAEX pInterface, PDMMEDIAEXIOREQ hIoReq, size_t *pcbXfer)
|
---|
| 567 | {
|
---|
| 568 | RT_NOREF1(pInterface);
|
---|
| 569 | PDRVHOSTBASEREQ pReq = (PDRVHOSTBASEREQ)hIoReq;
|
---|
| 570 |
|
---|
| 571 | *pcbXfer = pReq->cbReq;
|
---|
| 572 | return VINF_SUCCESS;
|
---|
| 573 | }
|
---|
| 574 |
|
---|
[64320] | 575 | /** @interface_method_impl{PDMIMEDIAEX,pfnIoReqCancelAll} */
|
---|
| 576 | static DECLCALLBACK(int) drvHostBaseIoReqCancelAll(PPDMIMEDIAEX pInterface)
|
---|
| 577 | {
|
---|
| 578 | RT_NOREF1(pInterface);
|
---|
| 579 | return VINF_SUCCESS;
|
---|
| 580 | }
|
---|
| 581 |
|
---|
| 582 | /** @interface_method_impl{PDMIMEDIAEX,pfnIoReqCancel} */
|
---|
| 583 | static DECLCALLBACK(int) drvHostBaseIoReqCancel(PPDMIMEDIAEX pInterface, PDMMEDIAEXIOREQID uIoReqId)
|
---|
| 584 | {
|
---|
| 585 | RT_NOREF2(pInterface, uIoReqId);
|
---|
| 586 | return VERR_PDM_MEDIAEX_IOREQID_NOT_FOUND;
|
---|
| 587 | }
|
---|
| 588 |
|
---|
| 589 | /** @interface_method_impl{PDMIMEDIAEX,pfnIoReqRead} */
|
---|
| 590 | static DECLCALLBACK(int) drvHostBaseIoReqRead(PPDMIMEDIAEX pInterface, PDMMEDIAEXIOREQ hIoReq, uint64_t off, size_t cbRead)
|
---|
| 591 | {
|
---|
| 592 | PDRVHOSTBASE pThis = RT_FROM_MEMBER(pInterface, DRVHOSTBASE, IMediaEx);
|
---|
| 593 | PDRVHOSTBASEREQ pReq = (PDRVHOSTBASEREQ)hIoReq;
|
---|
| 594 | LogFlow(("%s-%d: drvHostBaseIoReqRead: off=%#llx cbRead=%#x (%s)\n",
|
---|
| 595 | pThis->pDrvIns->pReg->szName, pThis->pDrvIns->iInstance, off, cbRead, pThis->pszDevice));
|
---|
| 596 | RTCritSectEnter(&pThis->CritSect);
|
---|
| 597 |
|
---|
[64407] | 598 | pReq->cbReq = cbRead;
|
---|
| 599 | pReq->cbResidual = cbRead;
|
---|
| 600 |
|
---|
[64839] | 601 | STAM_REL_COUNTER_INC(&pThis->StatReqsSubmitted);
|
---|
| 602 | STAM_REL_COUNTER_INC(&pThis->StatReqsRead);
|
---|
| 603 |
|
---|
[64320] | 604 | /*
|
---|
| 605 | * Check the state.
|
---|
| 606 | */
|
---|
| 607 | int rc;
|
---|
| 608 | if (pThis->fMediaPresent)
|
---|
| 609 | {
|
---|
| 610 | void *pvBuf;
|
---|
| 611 | rc = drvHostBaseBufferRetain(pThis, pReq, cbRead, false, &pvBuf);
|
---|
| 612 | if (RT_SUCCESS(rc))
|
---|
| 613 | {
|
---|
| 614 | /*
|
---|
| 615 | * Seek and read.
|
---|
| 616 | */
|
---|
| 617 | rc = drvHostBaseReadOs(pThis, off, pvBuf, cbRead);
|
---|
| 618 | if (RT_SUCCESS(rc))
|
---|
| 619 | {
|
---|
| 620 | Log2(("%s-%d: drvHostBaseReadOs: off=%#llx cbRead=%#x\n"
|
---|
| 621 | "%16.*Rhxd\n",
|
---|
| 622 | pThis->pDrvIns->pReg->szName, pThis->pDrvIns->iInstance, off, cbRead, cbRead, pvBuf));
|
---|
[64407] | 623 |
|
---|
| 624 | pReq->cbResidual = 0;
|
---|
[64320] | 625 | }
|
---|
| 626 | else
|
---|
| 627 | Log(("%s-%d: drvHostBaseIoReqRead: drvHostBaseReadOs(%#llx, %p, %#x) -> %Rrc ('%s')\n",
|
---|
| 628 | pThis->pDrvIns->pReg->szName, pThis->pDrvIns->iInstance,
|
---|
| 629 | off, pvBuf, cbRead, rc, pThis->pszDevice));
|
---|
| 630 |
|
---|
| 631 | rc = drvHostBaseBufferRelease(pThis, pReq, cbRead, false, pvBuf);
|
---|
| 632 | }
|
---|
| 633 | else
|
---|
| 634 | Log(("%s-%d: drvHostBaseIoReqRead: drvHostBaseBufferRetain(%#llx, %p, %#x) -> %Rrc ('%s')\n",
|
---|
| 635 | pThis->pDrvIns->pReg->szName, pThis->pDrvIns->iInstance,
|
---|
| 636 | off, pvBuf, cbRead, rc, pThis->pszDevice));
|
---|
| 637 | }
|
---|
| 638 | else
|
---|
| 639 | rc = VERR_MEDIA_NOT_PRESENT;
|
---|
| 640 |
|
---|
[64839] | 641 | if (RT_SUCCESS(rc))
|
---|
| 642 | {
|
---|
| 643 | STAM_REL_COUNTER_INC(&pThis->StatReqsSucceeded);
|
---|
| 644 | STAM_REL_COUNTER_INC(&pThis->StatBytesRead);
|
---|
| 645 | }
|
---|
| 646 | else
|
---|
| 647 | STAM_REL_COUNTER_INC(&pThis->StatReqsFailed);
|
---|
| 648 |
|
---|
[64320] | 649 | RTCritSectLeave(&pThis->CritSect);
|
---|
| 650 | LogFlow(("%s-%d: drvHostBaseIoReqRead: returns %Rrc\n", pThis->pDrvIns->pReg->szName, pThis->pDrvIns->iInstance, rc));
|
---|
| 651 | return rc;
|
---|
| 652 | }
|
---|
| 653 |
|
---|
| 654 | /** @interface_method_impl{PDMIMEDIAEX,pfnIoReqWrite} */
|
---|
| 655 | static DECLCALLBACK(int) drvHostBaseIoReqWrite(PPDMIMEDIAEX pInterface, PDMMEDIAEXIOREQ hIoReq, uint64_t off, size_t cbWrite)
|
---|
| 656 | {
|
---|
| 657 | PDRVHOSTBASE pThis = RT_FROM_MEMBER(pInterface, DRVHOSTBASE, IMediaEx);
|
---|
| 658 | PDRVHOSTBASEREQ pReq = (PDRVHOSTBASEREQ)hIoReq;
|
---|
| 659 | LogFlow(("%s-%d: drvHostBaseIoReqWrite: off=%#llx cbWrite=%#x (%s)\n",
|
---|
| 660 | pThis->pDrvIns->pReg->szName, pThis->pDrvIns->iInstance, off, cbWrite, pThis->pszDevice));
|
---|
| 661 | RTCritSectEnter(&pThis->CritSect);
|
---|
| 662 |
|
---|
[64407] | 663 | pReq->cbReq = cbWrite;
|
---|
| 664 | pReq->cbResidual = cbWrite;
|
---|
| 665 |
|
---|
[64839] | 666 | STAM_REL_COUNTER_INC(&pThis->StatReqsSubmitted);
|
---|
| 667 | STAM_REL_COUNTER_INC(&pThis->StatReqsWrite);
|
---|
| 668 |
|
---|
[64320] | 669 | /*
|
---|
| 670 | * Check the state.
|
---|
| 671 | */
|
---|
| 672 | int rc;
|
---|
| 673 | if (!pThis->fReadOnly)
|
---|
| 674 | {
|
---|
| 675 | if (pThis->fMediaPresent)
|
---|
| 676 | {
|
---|
| 677 | void *pvBuf;
|
---|
| 678 | rc = drvHostBaseBufferRetain(pThis, pReq, cbWrite, true, &pvBuf);
|
---|
| 679 | if (RT_SUCCESS(rc))
|
---|
| 680 | {
|
---|
| 681 | Log2(("%s-%d: drvHostBaseIoReqWrite: off=%#llx cbWrite=%#x\n"
|
---|
| 682 | "%16.*Rhxd\n",
|
---|
| 683 | pThis->pDrvIns->pReg->szName, pThis->pDrvIns->iInstance, off, cbWrite, cbWrite, pvBuf));
|
---|
| 684 | /*
|
---|
| 685 | * Seek and write.
|
---|
| 686 | */
|
---|
| 687 | rc = drvHostBaseWriteOs(pThis, off, pvBuf, cbWrite);
|
---|
| 688 | if (RT_FAILURE(rc))
|
---|
| 689 | Log(("%s-%d: drvHostBaseIoReqWrite: drvHostBaseWriteOs(%#llx, %p, %#x) -> %Rrc ('%s')\n",
|
---|
| 690 | pThis->pDrvIns->pReg->szName, pThis->pDrvIns->iInstance,
|
---|
| 691 | off, pvBuf, cbWrite, rc, pThis->pszDevice));
|
---|
[64407] | 692 | else
|
---|
| 693 | pReq->cbResidual = 0;
|
---|
[64320] | 694 |
|
---|
| 695 | rc = drvHostBaseBufferRelease(pThis, pReq, cbWrite, true, pvBuf);
|
---|
| 696 | }
|
---|
| 697 | }
|
---|
| 698 | else
|
---|
| 699 | rc = VERR_MEDIA_NOT_PRESENT;
|
---|
| 700 | }
|
---|
| 701 | else
|
---|
| 702 | rc = VERR_WRITE_PROTECT;
|
---|
| 703 |
|
---|
[64839] | 704 | if (RT_SUCCESS(rc))
|
---|
| 705 | {
|
---|
| 706 | STAM_REL_COUNTER_INC(&pThis->StatReqsSucceeded);
|
---|
| 707 | STAM_REL_COUNTER_INC(&pThis->StatBytesWritten);
|
---|
| 708 | }
|
---|
| 709 | else
|
---|
| 710 | STAM_REL_COUNTER_INC(&pThis->StatReqsFailed);
|
---|
| 711 |
|
---|
[64320] | 712 | RTCritSectLeave(&pThis->CritSect);
|
---|
| 713 | LogFlow(("%s-%d: drvHostBaseIoReqWrite: returns %Rrc\n", pThis->pDrvIns->pReg->szName, pThis->pDrvIns->iInstance, rc));
|
---|
| 714 | return rc;
|
---|
| 715 | }
|
---|
| 716 |
|
---|
| 717 | /** @interface_method_impl{PDMIMEDIAEX,pfnIoReqFlush} */
|
---|
| 718 | static DECLCALLBACK(int) drvHostBaseIoReqFlush(PPDMIMEDIAEX pInterface, PDMMEDIAEXIOREQ hIoReq)
|
---|
| 719 | {
|
---|
| 720 | RT_NOREF1(hIoReq);
|
---|
| 721 |
|
---|
| 722 | int rc;
|
---|
| 723 | PDRVHOSTBASE pThis = RT_FROM_MEMBER(pInterface, DRVHOSTBASE, IMediaEx);
|
---|
| 724 | LogFlow(("%s-%d: drvHostBaseIoReqFlush: (%s)\n",
|
---|
| 725 | pThis->pDrvIns->pReg->szName, pThis->pDrvIns->iInstance, pThis->pszDevice));
|
---|
| 726 | RTCritSectEnter(&pThis->CritSect);
|
---|
| 727 |
|
---|
[64839] | 728 | STAM_REL_COUNTER_INC(&pThis->StatReqsSubmitted);
|
---|
| 729 | STAM_REL_COUNTER_INC(&pThis->StatReqsFlush);
|
---|
| 730 |
|
---|
[64320] | 731 | if (pThis->fMediaPresent)
|
---|
| 732 | rc = drvHostBaseFlushOs(pThis);
|
---|
| 733 | else
|
---|
| 734 | rc = VERR_MEDIA_NOT_PRESENT;
|
---|
| 735 |
|
---|
[64839] | 736 | if (RT_SUCCESS(rc))
|
---|
| 737 | STAM_REL_COUNTER_INC(&pThis->StatReqsSucceeded);
|
---|
| 738 | else
|
---|
| 739 | STAM_REL_COUNTER_INC(&pThis->StatReqsFailed);
|
---|
| 740 |
|
---|
[64320] | 741 | RTCritSectLeave(&pThis->CritSect);
|
---|
| 742 | LogFlow(("%s-%d: drvHostBaseFlush: returns %Rrc\n", pThis->pDrvIns->pReg->szName, pThis->pDrvIns->iInstance, rc));
|
---|
| 743 | return rc;
|
---|
| 744 | }
|
---|
| 745 |
|
---|
| 746 | /** @interface_method_impl{PDMIMEDIAEX,pfnIoReqDiscard} */
|
---|
| 747 | static DECLCALLBACK(int) drvHostBaseIoReqDiscard(PPDMIMEDIAEX pInterface, PDMMEDIAEXIOREQ hIoReq, unsigned cRangesMax)
|
---|
| 748 | {
|
---|
| 749 | RT_NOREF3(pInterface, hIoReq, cRangesMax);
|
---|
| 750 | return VERR_NOT_SUPPORTED;
|
---|
| 751 | }
|
---|
| 752 |
|
---|
| 753 | /** @interface_method_impl{PDMIMEDIAEX,pfnIoReqGetActiveCount} */
|
---|
| 754 | static DECLCALLBACK(uint32_t) drvHostBaseIoReqGetActiveCount(PPDMIMEDIAEX pInterface)
|
---|
| 755 | {
|
---|
| 756 | RT_NOREF1(pInterface);
|
---|
| 757 | return 0;
|
---|
| 758 | }
|
---|
| 759 |
|
---|
| 760 | /** @interface_method_impl{PDMIMEDIAEX,pfnIoReqGetSuspendedCount} */
|
---|
| 761 | static DECLCALLBACK(uint32_t) drvHostBaseIoReqGetSuspendedCount(PPDMIMEDIAEX pInterface)
|
---|
| 762 | {
|
---|
| 763 | RT_NOREF1(pInterface);
|
---|
| 764 | return 0;
|
---|
| 765 | }
|
---|
| 766 |
|
---|
| 767 | /** @interface_method_impl{PDMIMEDIAEX,pfnIoReqQuerySuspendedStart} */
|
---|
| 768 | static DECLCALLBACK(int) drvHostBaseIoReqQuerySuspendedStart(PPDMIMEDIAEX pInterface, PPDMMEDIAEXIOREQ phIoReq, void **ppvIoReqAlloc)
|
---|
| 769 | {
|
---|
| 770 | RT_NOREF3(pInterface, phIoReq, ppvIoReqAlloc);
|
---|
| 771 | return VERR_NOT_IMPLEMENTED;
|
---|
| 772 | }
|
---|
| 773 |
|
---|
| 774 | /** @interface_method_impl{PDMIMEDIAEX,pfnIoReqQuerySuspendedNext} */
|
---|
| 775 | static DECLCALLBACK(int) drvHostBaseIoReqQuerySuspendedNext(PPDMIMEDIAEX pInterface, PDMMEDIAEXIOREQ hIoReq,
|
---|
| 776 | PPDMMEDIAEXIOREQ phIoReqNext, void **ppvIoReqAllocNext)
|
---|
| 777 | {
|
---|
| 778 | RT_NOREF4(pInterface, hIoReq, phIoReqNext, ppvIoReqAllocNext);
|
---|
| 779 | return VERR_NOT_IMPLEMENTED;
|
---|
| 780 | }
|
---|
| 781 |
|
---|
| 782 | /** @interface_method_impl{PDMIMEDIAEX,pfnIoReqSuspendedSave} */
|
---|
| 783 | static DECLCALLBACK(int) drvHostBaseIoReqSuspendedSave(PPDMIMEDIAEX pInterface, PSSMHANDLE pSSM, PDMMEDIAEXIOREQ hIoReq)
|
---|
| 784 | {
|
---|
| 785 | RT_NOREF3(pInterface, pSSM, hIoReq);
|
---|
| 786 | return VERR_NOT_IMPLEMENTED;
|
---|
| 787 | }
|
---|
| 788 |
|
---|
| 789 | /** @interface_method_impl{PDMIMEDIAEX,pfnIoReqSuspendedLoad} */
|
---|
| 790 | static DECLCALLBACK(int) drvHostBaseIoReqSuspendedLoad(PPDMIMEDIAEX pInterface, PSSMHANDLE pSSM, PDMMEDIAEXIOREQ hIoReq)
|
---|
| 791 | {
|
---|
| 792 | RT_NOREF3(pInterface, pSSM, hIoReq);
|
---|
| 793 | return VERR_NOT_IMPLEMENTED;
|
---|
| 794 | }
|
---|
| 795 |
|
---|
| 796 |
|
---|
| 797 |
|
---|
[1] | 798 | /* -=-=-=-=- IMount -=-=-=-=- */
|
---|
| 799 |
|
---|
[62956] | 800 | /** @interface_method_impl{PDMIMOUNT,pfnUnmount} */
|
---|
[35560] | 801 | static DECLCALLBACK(int) drvHostBaseUnmount(PPDMIMOUNT pInterface, bool fForce, bool fEject)
|
---|
[1] | 802 | {
|
---|
[62928] | 803 | RT_NOREF(fEject);
|
---|
[37780] | 804 | /* While we're not mountable (see drvHostBaseMount), we're unmountable. */
|
---|
[64316] | 805 | PDRVHOSTBASE pThis = RT_FROM_MEMBER(pInterface, DRVHOSTBASE, IMount);
|
---|
[37780] | 806 | RTCritSectEnter(&pThis->CritSect);
|
---|
| 807 |
|
---|
| 808 | /*
|
---|
| 809 | * Validate state.
|
---|
| 810 | */
|
---|
| 811 | int rc = VINF_SUCCESS;
|
---|
| 812 | if (!pThis->fLocked || fForce)
|
---|
| 813 | {
|
---|
| 814 | /* Unlock drive if necessary. */
|
---|
| 815 | if (pThis->fLocked)
|
---|
| 816 | {
|
---|
| 817 | if (pThis->pfnDoLock)
|
---|
| 818 | rc = pThis->pfnDoLock(pThis, false);
|
---|
| 819 | if (RT_SUCCESS(rc))
|
---|
| 820 | pThis->fLocked = false;
|
---|
| 821 | }
|
---|
| 822 |
|
---|
[64316] | 823 | if (fEject)
|
---|
| 824 | {
|
---|
| 825 | /*
|
---|
| 826 | * Eject the disc.
|
---|
| 827 | */
|
---|
| 828 | rc = drvHostBaseEjectOs(pThis);
|
---|
| 829 | }
|
---|
| 830 |
|
---|
[37780] | 831 | /*
|
---|
| 832 | * Media is no longer present.
|
---|
| 833 | */
|
---|
| 834 | DRVHostBaseMediaNotPresent(pThis);
|
---|
| 835 | }
|
---|
| 836 | else
|
---|
| 837 | {
|
---|
[64316] | 838 | Log(("drvHostBaseUnmount: Locked\n"));
|
---|
[37780] | 839 | rc = VERR_PDM_MEDIA_LOCKED;
|
---|
| 840 | }
|
---|
| 841 |
|
---|
| 842 | RTCritSectLeave(&pThis->CritSect);
|
---|
| 843 | LogFlow(("drvHostBaseUnmount: returns %Rrc\n", rc));
|
---|
| 844 | return rc;
|
---|
[1] | 845 | }
|
---|
| 846 |
|
---|
| 847 |
|
---|
[62956] | 848 | /** @interface_method_impl{PDMIMOUNT,pfnIsMounted} */
|
---|
[1] | 849 | static DECLCALLBACK(bool) drvHostBaseIsMounted(PPDMIMOUNT pInterface)
|
---|
| 850 | {
|
---|
[64316] | 851 | PDRVHOSTBASE pThis = RT_FROM_MEMBER(pInterface, DRVHOSTBASE, IMount);
|
---|
[1] | 852 | RTCritSectEnter(&pThis->CritSect);
|
---|
| 853 |
|
---|
| 854 | bool fRc = pThis->fMediaPresent;
|
---|
| 855 |
|
---|
| 856 | RTCritSectLeave(&pThis->CritSect);
|
---|
| 857 | return fRc;
|
---|
| 858 | }
|
---|
| 859 |
|
---|
| 860 |
|
---|
[62956] | 861 | /** @interface_method_impl{PDMIMOUNT,pfnIsLocked} */
|
---|
[1] | 862 | static DECLCALLBACK(int) drvHostBaseLock(PPDMIMOUNT pInterface)
|
---|
| 863 | {
|
---|
[64316] | 864 | PDRVHOSTBASE pThis = RT_FROM_MEMBER(pInterface, DRVHOSTBASE, IMount);
|
---|
[1] | 865 | RTCritSectEnter(&pThis->CritSect);
|
---|
| 866 |
|
---|
| 867 | int rc = VINF_SUCCESS;
|
---|
| 868 | if (!pThis->fLocked)
|
---|
| 869 | {
|
---|
| 870 | if (pThis->pfnDoLock)
|
---|
[92226] | 871 | {
|
---|
[1] | 872 | rc = pThis->pfnDoLock(pThis, true);
|
---|
[92226] | 873 | if (RT_SUCCESS(rc))
|
---|
| 874 | pThis->fLocked = true;
|
---|
| 875 | }
|
---|
[1] | 876 | }
|
---|
| 877 | else
|
---|
[26166] | 878 | LogFlow(("%s-%d: drvHostBaseLock: already locked\n", pThis->pDrvIns->pReg->szName, pThis->pDrvIns->iInstance));
|
---|
[1] | 879 |
|
---|
| 880 | RTCritSectLeave(&pThis->CritSect);
|
---|
[26166] | 881 | LogFlow(("%s-%d: drvHostBaseLock: returns %Rrc\n", pThis->pDrvIns->pReg->szName, pThis->pDrvIns->iInstance, rc));
|
---|
[1] | 882 | return rc;
|
---|
| 883 | }
|
---|
| 884 |
|
---|
| 885 |
|
---|
[62956] | 886 | /** @interface_method_impl{PDMIMOUNT,pfnIsLocked} */
|
---|
[1] | 887 | static DECLCALLBACK(int) drvHostBaseUnlock(PPDMIMOUNT pInterface)
|
---|
| 888 | {
|
---|
[64316] | 889 | PDRVHOSTBASE pThis = RT_FROM_MEMBER(pInterface, DRVHOSTBASE, IMount);
|
---|
[1] | 890 | RTCritSectEnter(&pThis->CritSect);
|
---|
| 891 |
|
---|
| 892 | int rc = VINF_SUCCESS;
|
---|
| 893 | if (pThis->fLocked)
|
---|
| 894 | {
|
---|
| 895 | if (pThis->pfnDoLock)
|
---|
| 896 | rc = pThis->pfnDoLock(pThis, false);
|
---|
[11266] | 897 | if (RT_SUCCESS(rc))
|
---|
[1] | 898 | pThis->fLocked = false;
|
---|
| 899 | }
|
---|
| 900 | else
|
---|
[26166] | 901 | LogFlow(("%s-%d: drvHostBaseUnlock: not locked\n", pThis->pDrvIns->pReg->szName, pThis->pDrvIns->iInstance));
|
---|
[1] | 902 |
|
---|
| 903 | RTCritSectLeave(&pThis->CritSect);
|
---|
[26166] | 904 | LogFlow(("%s-%d: drvHostBaseUnlock: returns %Rrc\n", pThis->pDrvIns->pReg->szName, pThis->pDrvIns->iInstance, rc));
|
---|
[1] | 905 | return rc;
|
---|
| 906 | }
|
---|
| 907 |
|
---|
| 908 |
|
---|
[62956] | 909 | /** @interface_method_impl{PDMIMOUNT,pfnIsLocked} */
|
---|
[1] | 910 | static DECLCALLBACK(bool) drvHostBaseIsLocked(PPDMIMOUNT pInterface)
|
---|
| 911 | {
|
---|
[64316] | 912 | PDRVHOSTBASE pThis = RT_FROM_MEMBER(pInterface, DRVHOSTBASE, IMount);
|
---|
[1] | 913 | RTCritSectEnter(&pThis->CritSect);
|
---|
| 914 |
|
---|
| 915 | bool fRc = pThis->fLocked;
|
---|
| 916 |
|
---|
| 917 | RTCritSectLeave(&pThis->CritSect);
|
---|
| 918 | return fRc;
|
---|
| 919 | }
|
---|
| 920 |
|
---|
| 921 |
|
---|
| 922 | /* -=-=-=-=- IBase -=-=-=-=- */
|
---|
| 923 |
|
---|
[25966] | 924 | /**
|
---|
| 925 | * @interface_method_impl{PDMIBASE,pfnQueryInterface}
|
---|
| 926 | */
|
---|
| 927 | static DECLCALLBACK(void *) drvHostBaseQueryInterface(PPDMIBASE pInterface, const char *pszIID)
|
---|
[1] | 928 | {
|
---|
[25966] | 929 | PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
|
---|
| 930 | PDRVHOSTBASE pThis = PDMINS_2_DATA(pDrvIns, PDRVHOSTBASE);
|
---|
| 931 |
|
---|
[25985] | 932 | PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
|
---|
[59248] | 933 | PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIA, &pThis->IMedia);
|
---|
[25974] | 934 | PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMOUNT, &pThis->IMount);
|
---|
[64320] | 935 | PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAEX, pThis->pDrvMediaExPort ? &pThis->IMediaEx : NULL);
|
---|
[25966] | 936 | return NULL;
|
---|
[1] | 937 | }
|
---|
| 938 |
|
---|
| 939 |
|
---|
| 940 | /* -=-=-=-=- poller thread -=-=-=-=- */
|
---|
| 941 |
|
---|
[2084] | 942 |
|
---|
[1] | 943 | /**
|
---|
| 944 | * Media present.
|
---|
| 945 | * Query the size and notify the above driver / device.
|
---|
| 946 | *
|
---|
| 947 | * @param pThis The instance data.
|
---|
| 948 | */
|
---|
[64316] | 949 | DECLHIDDEN(int) DRVHostBaseMediaPresent(PDRVHOSTBASE pThis)
|
---|
[1] | 950 | {
|
---|
| 951 | /*
|
---|
| 952 | * Open the drive.
|
---|
| 953 | */
|
---|
[64316] | 954 | int rc = drvHostBaseMediaRefreshOs(pThis);
|
---|
[11266] | 955 | if (RT_FAILURE(rc))
|
---|
[1] | 956 | return rc;
|
---|
| 957 |
|
---|
| 958 | /*
|
---|
[23739] | 959 | * Determine the size.
|
---|
[1] | 960 | */
|
---|
| 961 | uint64_t cb;
|
---|
[64316] | 962 | rc = drvHostBaseGetMediaSizeOs(pThis, &cb);
|
---|
[11266] | 963 | if (RT_FAILURE(rc))
|
---|
[1] | 964 | {
|
---|
[11284] | 965 | LogFlow(("%s-%d: failed to figure media size of %s, rc=%Rrc\n",
|
---|
[26166] | 966 | pThis->pDrvIns->pReg->szName, pThis->pDrvIns->iInstance, pThis->pszDevice, rc));
|
---|
[1] | 967 | return rc;
|
---|
| 968 | }
|
---|
| 969 |
|
---|
| 970 | /*
|
---|
| 971 | * Update the data and inform the unit.
|
---|
| 972 | */
|
---|
| 973 | pThis->cbSize = cb;
|
---|
| 974 | pThis->fMediaPresent = true;
|
---|
| 975 | if (pThis->pDrvMountNotify)
|
---|
| 976 | pThis->pDrvMountNotify->pfnMountNotify(pThis->pDrvMountNotify);
|
---|
| 977 | LogFlow(("%s-%d: drvHostBaseMediaPresent: cbSize=%lld (%#llx)\n",
|
---|
[26166] | 978 | pThis->pDrvIns->pReg->szName, pThis->pDrvIns->iInstance, pThis->cbSize, pThis->cbSize));
|
---|
[1] | 979 | return VINF_SUCCESS;
|
---|
| 980 | }
|
---|
| 981 |
|
---|
| 982 |
|
---|
| 983 | /**
|
---|
| 984 | * Media no longer present.
|
---|
| 985 | * @param pThis The instance data.
|
---|
| 986 | */
|
---|
[64316] | 987 | DECLHIDDEN(void) DRVHostBaseMediaNotPresent(PDRVHOSTBASE pThis)
|
---|
[1] | 988 | {
|
---|
| 989 | pThis->fMediaPresent = false;
|
---|
| 990 | pThis->fLocked = false;
|
---|
[6291] | 991 | pThis->PCHSGeometry.cCylinders = 0;
|
---|
| 992 | pThis->PCHSGeometry.cHeads = 0;
|
---|
| 993 | pThis->PCHSGeometry.cSectors = 0;
|
---|
| 994 | pThis->LCHSGeometry.cCylinders = 0;
|
---|
| 995 | pThis->LCHSGeometry.cHeads = 0;
|
---|
| 996 | pThis->LCHSGeometry.cSectors = 0;
|
---|
[1] | 997 | if (pThis->pDrvMountNotify)
|
---|
| 998 | pThis->pDrvMountNotify->pfnUnmountNotify(pThis->pDrvMountNotify);
|
---|
| 999 | }
|
---|
| 1000 |
|
---|
| 1001 |
|
---|
[64316] | 1002 | static int drvHostBaseMediaPoll(PDRVHOSTBASE pThis)
|
---|
[1] | 1003 | {
|
---|
[64316] | 1004 | /*
|
---|
| 1005 | * Poll for media change.
|
---|
| 1006 | */
|
---|
| 1007 | bool fMediaPresent = false;
|
---|
| 1008 | bool fMediaChanged = false;
|
---|
| 1009 | drvHostBaseQueryMediaStatusOs(pThis, &fMediaChanged, &fMediaPresent);
|
---|
[1] | 1010 |
|
---|
[64316] | 1011 | RTCritSectEnter(&pThis->CritSect);
|
---|
[1] | 1012 |
|
---|
[64316] | 1013 | int rc = VINF_SUCCESS;
|
---|
| 1014 | if (pThis->fMediaPresent != fMediaPresent)
|
---|
[1] | 1015 | {
|
---|
[64316] | 1016 | LogFlow(("drvHostDvdPoll: %d -> %d\n", pThis->fMediaPresent, fMediaPresent));
|
---|
| 1017 | pThis->fMediaPresent = false;
|
---|
| 1018 | if (fMediaPresent)
|
---|
| 1019 | rc = DRVHostBaseMediaPresent(pThis);
|
---|
| 1020 | else
|
---|
| 1021 | DRVHostBaseMediaNotPresent(pThis);
|
---|
[1] | 1022 | }
|
---|
[64316] | 1023 | else if (fMediaPresent)
|
---|
| 1024 | {
|
---|
| 1025 | /*
|
---|
| 1026 | * Poll for media change.
|
---|
| 1027 | */
|
---|
| 1028 | if (fMediaChanged)
|
---|
| 1029 | {
|
---|
| 1030 | LogFlow(("drvHostDVDMediaThread: Media changed!\n"));
|
---|
| 1031 | DRVHostBaseMediaNotPresent(pThis);
|
---|
| 1032 | rc = DRVHostBaseMediaPresent(pThis);
|
---|
| 1033 | }
|
---|
| 1034 | }
|
---|
| 1035 |
|
---|
| 1036 | RTCritSectLeave(&pThis->CritSect);
|
---|
| 1037 | return rc;
|
---|
[1] | 1038 | }
|
---|
| 1039 |
|
---|
| 1040 |
|
---|
| 1041 | /**
|
---|
| 1042 | * This thread will periodically poll the device for media presence.
|
---|
| 1043 | *
|
---|
| 1044 | * @returns Ignored.
|
---|
| 1045 | * @param ThreadSelf Handle of this thread. Ignored.
|
---|
| 1046 | * @param pvUser Pointer to the driver instance structure.
|
---|
| 1047 | */
|
---|
| 1048 | static DECLCALLBACK(int) drvHostBaseMediaThread(RTTHREAD ThreadSelf, void *pvUser)
|
---|
| 1049 | {
|
---|
| 1050 | PDRVHOSTBASE pThis = (PDRVHOSTBASE)pvUser;
|
---|
| 1051 | LogFlow(("%s-%d: drvHostBaseMediaThread: ThreadSelf=%p pvUser=%p\n",
|
---|
[26166] | 1052 | pThis->pDrvIns->pReg->szName, pThis->pDrvIns->iInstance, ThreadSelf, pvUser));
|
---|
[1] | 1053 | bool fFirst = true;
|
---|
| 1054 | int cRetries = 10;
|
---|
| 1055 | while (!pThis->fShutdownPoller)
|
---|
| 1056 | {
|
---|
| 1057 | /*
|
---|
| 1058 | * Perform the polling (unless we've run out of 50ms retries).
|
---|
| 1059 | */
|
---|
[64316] | 1060 | if (cRetries-- > 0)
|
---|
[1] | 1061 | {
|
---|
| 1062 |
|
---|
[64316] | 1063 | int rc = drvHostBaseMediaPoll(pThis);
|
---|
[11266] | 1064 | if (RT_FAILURE(rc))
|
---|
[1] | 1065 | {
|
---|
| 1066 | RTSemEventWait(pThis->EventPoller, 50);
|
---|
| 1067 | continue;
|
---|
| 1068 | }
|
---|
| 1069 | }
|
---|
| 1070 |
|
---|
| 1071 | /*
|
---|
| 1072 | * Signal EMT after the first go.
|
---|
| 1073 | */
|
---|
| 1074 | if (fFirst)
|
---|
| 1075 | {
|
---|
| 1076 | RTThreadUserSignal(ThreadSelf);
|
---|
| 1077 | fFirst = false;
|
---|
| 1078 | }
|
---|
| 1079 |
|
---|
| 1080 | /*
|
---|
| 1081 | * Sleep.
|
---|
| 1082 | */
|
---|
| 1083 | int rc = RTSemEventWait(pThis->EventPoller, pThis->cMilliesPoller);
|
---|
[11266] | 1084 | if ( RT_FAILURE(rc)
|
---|
[1] | 1085 | && rc != VERR_TIMEOUT)
|
---|
| 1086 | {
|
---|
[11284] | 1087 | AssertMsgFailed(("rc=%Rrc\n", rc));
|
---|
[1] | 1088 | pThis->ThreadPoller = NIL_RTTHREAD;
|
---|
[11284] | 1089 | LogFlow(("drvHostBaseMediaThread: returns %Rrc\n", rc));
|
---|
[1] | 1090 | return rc;
|
---|
| 1091 | }
|
---|
| 1092 | cRetries = 10;
|
---|
| 1093 | }
|
---|
| 1094 |
|
---|
| 1095 | /* (Don't clear the thread handle here, the destructor thread is using it to wait.) */
|
---|
[26166] | 1096 | LogFlow(("%s-%d: drvHostBaseMediaThread: returns VINF_SUCCESS\n", pThis->pDrvIns->pReg->szName, pThis->pDrvIns->iInstance));
|
---|
[1] | 1097 | return VINF_SUCCESS;
|
---|
| 1098 | }
|
---|
| 1099 |
|
---|
[64839] | 1100 | /**
|
---|
| 1101 | * Registers statistics associated with the given media driver.
|
---|
| 1102 | *
|
---|
| 1103 | * @returns VBox status code.
|
---|
| 1104 | * @param pThis The media driver instance.
|
---|
| 1105 | */
|
---|
| 1106 | static int drvHostBaseStatsRegister(PDRVHOSTBASE pThis)
|
---|
| 1107 | {
|
---|
| 1108 | PPDMDRVINS pDrvIns = pThis->pDrvIns;
|
---|
| 1109 | uint32_t iInstance, iLUN;
|
---|
| 1110 | const char *pcszController;
|
---|
| 1111 |
|
---|
| 1112 | int rc = pThis->pDrvMediaPort->pfnQueryDeviceLocation(pThis->pDrvMediaPort, &pcszController,
|
---|
| 1113 | &iInstance, &iLUN);
|
---|
| 1114 | if (RT_SUCCESS(rc))
|
---|
| 1115 | {
|
---|
| 1116 | char *pszCtrlUpper = RTStrDup(pcszController);
|
---|
| 1117 | if (pszCtrlUpper)
|
---|
| 1118 | {
|
---|
| 1119 | RTStrToUpper(pszCtrlUpper);
|
---|
| 1120 |
|
---|
| 1121 | PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->StatBytesRead, STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_BYTES,
|
---|
| 1122 | "Amount of data read.", "/Devices/%s%u/Port%u/ReadBytes", pszCtrlUpper, iInstance, iLUN);
|
---|
| 1123 | PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->StatBytesWritten, STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_BYTES,
|
---|
| 1124 | "Amount of data written.", "/Devices/%s%u/Port%u/WrittenBytes", pszCtrlUpper, iInstance, iLUN);
|
---|
| 1125 |
|
---|
| 1126 | PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->StatReqsSubmitted, STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_COUNT,
|
---|
| 1127 | "Number of I/O requests submitted.", "/Devices/%s%u/Port%u/ReqsSubmitted", pszCtrlUpper, iInstance, iLUN);
|
---|
| 1128 | PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->StatReqsFailed, STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_COUNT,
|
---|
| 1129 | "Number of I/O requests failed.", "/Devices/%s%u/Port%u/ReqsFailed", pszCtrlUpper, iInstance, iLUN);
|
---|
| 1130 | PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->StatReqsSucceeded, STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_COUNT,
|
---|
| 1131 | "Number of I/O requests succeeded.", "/Devices/%s%u/Port%u/ReqsSucceeded", pszCtrlUpper, iInstance, iLUN);
|
---|
| 1132 | PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->StatReqsFlush, STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_COUNT,
|
---|
| 1133 | "Number of flush I/O requests submitted.", "/Devices/%s%u/Port%u/ReqsFlush", pszCtrlUpper, iInstance, iLUN);
|
---|
| 1134 | PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->StatReqsWrite, STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_COUNT,
|
---|
| 1135 | "Number of write I/O requests submitted.", "/Devices/%s%u/Port%u/ReqsWrite", pszCtrlUpper, iInstance, iLUN);
|
---|
| 1136 | PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->StatReqsRead, STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_COUNT,
|
---|
| 1137 | "Number of read I/O requests submitted.", "/Devices/%s%u/Port%u/ReqsRead", pszCtrlUpper, iInstance, iLUN);
|
---|
| 1138 |
|
---|
| 1139 | RTStrFree(pszCtrlUpper);
|
---|
| 1140 | }
|
---|
| 1141 | else
|
---|
| 1142 | rc = VERR_NO_STR_MEMORY;
|
---|
| 1143 | }
|
---|
| 1144 |
|
---|
| 1145 | return rc;
|
---|
| 1146 | }
|
---|
| 1147 |
|
---|
| 1148 | /**
|
---|
| 1149 | * Deregisters statistics associated with the given media driver.
|
---|
| 1150 | *
|
---|
| 1151 | * @param pThis The media driver instance.
|
---|
| 1152 | */
|
---|
| 1153 | static void drvhostBaseStatsDeregister(PDRVHOSTBASE pThis)
|
---|
| 1154 | {
|
---|
| 1155 | PPDMDRVINS pDrvIns = pThis->pDrvIns;
|
---|
| 1156 |
|
---|
| 1157 | PDMDrvHlpSTAMDeregister(pDrvIns, &pThis->StatBytesRead);
|
---|
| 1158 | PDMDrvHlpSTAMDeregister(pDrvIns, &pThis->StatBytesWritten);
|
---|
| 1159 | PDMDrvHlpSTAMDeregister(pDrvIns, &pThis->StatReqsSubmitted);
|
---|
| 1160 | PDMDrvHlpSTAMDeregister(pDrvIns, &pThis->StatReqsFailed);
|
---|
| 1161 | PDMDrvHlpSTAMDeregister(pDrvIns, &pThis->StatReqsSucceeded);
|
---|
| 1162 | PDMDrvHlpSTAMDeregister(pDrvIns, &pThis->StatReqsFlush);
|
---|
| 1163 | PDMDrvHlpSTAMDeregister(pDrvIns, &pThis->StatReqsWrite);
|
---|
| 1164 | PDMDrvHlpSTAMDeregister(pDrvIns, &pThis->StatReqsRead);
|
---|
| 1165 | }
|
---|
| 1166 |
|
---|
[1] | 1167 | /* -=-=-=-=- driver interface -=-=-=-=- */
|
---|
| 1168 |
|
---|
| 1169 |
|
---|
| 1170 | /**
|
---|
| 1171 | * Done state load operation.
|
---|
| 1172 | *
|
---|
| 1173 | * @returns VBox load code.
|
---|
| 1174 | * @param pDrvIns Driver instance of the driver which registered the data unit.
|
---|
| 1175 | * @param pSSM SSM operation handle.
|
---|
| 1176 | */
|
---|
| 1177 | static DECLCALLBACK(int) drvHostBaseLoadDone(PPDMDRVINS pDrvIns, PSSMHANDLE pSSM)
|
---|
| 1178 | {
|
---|
[62928] | 1179 | RT_NOREF(pSSM);
|
---|
[11267] | 1180 | PDRVHOSTBASE pThis = PDMINS_2_DATA(pDrvIns, PDRVHOSTBASE);
|
---|
[26166] | 1181 | LogFlow(("%s-%d: drvHostBaseMediaThread:\n", pThis->pDrvIns->pReg->szName, pThis->pDrvIns->iInstance));
|
---|
[1] | 1182 | RTCritSectEnter(&pThis->CritSect);
|
---|
| 1183 |
|
---|
| 1184 | /*
|
---|
| 1185 | * Tell the device/driver above us that the media status is uncertain.
|
---|
| 1186 | */
|
---|
| 1187 | if (pThis->pDrvMountNotify)
|
---|
| 1188 | {
|
---|
| 1189 | pThis->pDrvMountNotify->pfnUnmountNotify(pThis->pDrvMountNotify);
|
---|
| 1190 | if (pThis->fMediaPresent)
|
---|
| 1191 | pThis->pDrvMountNotify->pfnMountNotify(pThis->pDrvMountNotify);
|
---|
| 1192 | }
|
---|
| 1193 |
|
---|
| 1194 | RTCritSectLeave(&pThis->CritSect);
|
---|
| 1195 | return VINF_SUCCESS;
|
---|
| 1196 | }
|
---|
| 1197 |
|
---|
| 1198 |
|
---|
| 1199 | /** @copydoc FNPDMDRVDESTRUCT */
|
---|
| 1200 | DECLCALLBACK(void) DRVHostBaseDestruct(PPDMDRVINS pDrvIns)
|
---|
| 1201 | {
|
---|
[11267] | 1202 | PDRVHOSTBASE pThis = PDMINS_2_DATA(pDrvIns, PDRVHOSTBASE);
|
---|
[26166] | 1203 | LogFlow(("%s-%d: drvHostBaseDestruct: iInstance=%d\n", pDrvIns->pReg->szName, pDrvIns->iInstance, pDrvIns->iInstance));
|
---|
[1] | 1204 |
|
---|
| 1205 | /*
|
---|
| 1206 | * Terminate the thread.
|
---|
| 1207 | */
|
---|
| 1208 | if (pThis->ThreadPoller != NIL_RTTHREAD)
|
---|
| 1209 | {
|
---|
| 1210 | pThis->fShutdownPoller = true;
|
---|
| 1211 | int rc;
|
---|
| 1212 | int cTimes = 50;
|
---|
| 1213 | do
|
---|
| 1214 | {
|
---|
[64316] | 1215 | RTSemEventSignal(pThis->EventPoller);
|
---|
[1] | 1216 | rc = RTThreadWait(pThis->ThreadPoller, 100, NULL);
|
---|
| 1217 | } while (cTimes-- > 0 && rc == VERR_TIMEOUT);
|
---|
| 1218 |
|
---|
| 1219 | if (!rc)
|
---|
| 1220 | pThis->ThreadPoller = NIL_RTTHREAD;
|
---|
| 1221 | }
|
---|
| 1222 |
|
---|
| 1223 | /*
|
---|
[64316] | 1224 | * Cleanup the other resources.
|
---|
[1] | 1225 | */
|
---|
[64316] | 1226 | drvHostBaseDestructOs(pThis);
|
---|
| 1227 |
|
---|
| 1228 | if (pThis->EventPoller != NULL)
|
---|
[1] | 1229 | {
|
---|
[64316] | 1230 | RTSemEventDestroy(pThis->EventPoller);
|
---|
| 1231 | pThis->EventPoller = NULL;
|
---|
[1] | 1232 | }
|
---|
| 1233 |
|
---|
| 1234 | if (pThis->pszDevice)
|
---|
| 1235 | {
|
---|
[91897] | 1236 | PDMDrvHlpMMHeapFree(pDrvIns, pThis->pszDevice);
|
---|
[1] | 1237 | pThis->pszDevice = NULL;
|
---|
| 1238 | }
|
---|
| 1239 |
|
---|
| 1240 | if (pThis->pszDeviceOpen)
|
---|
| 1241 | {
|
---|
| 1242 | RTStrFree(pThis->pszDeviceOpen);
|
---|
| 1243 | pThis->pszDeviceOpen = NULL;
|
---|
| 1244 | }
|
---|
| 1245 |
|
---|
[64320] | 1246 | if (pThis->pvBuf)
|
---|
| 1247 | {
|
---|
| 1248 | RTMemFree(pThis->pvBuf);
|
---|
| 1249 | pThis->pvBuf = NULL;
|
---|
| 1250 | pThis->cbBuf = 0;
|
---|
| 1251 | }
|
---|
| 1252 |
|
---|
[3113] | 1253 | /* Forget about the notifications. */
|
---|
| 1254 | pThis->pDrvMountNotify = NULL;
|
---|
| 1255 |
|
---|
[64839] | 1256 | drvhostBaseStatsDeregister(pThis);
|
---|
| 1257 |
|
---|
[3113] | 1258 | /* Leave the instance operational if this is just a cleanup of the state
|
---|
[33540] | 1259 | * after an attach error happened. So don't destroy the critsect then. */
|
---|
[3113] | 1260 | if (!pThis->fKeepInstance && RTCritSectIsInitialized(&pThis->CritSect))
|
---|
[1] | 1261 | RTCritSectDelete(&pThis->CritSect);
|
---|
[26166] | 1262 | LogFlow(("%s-%d: drvHostBaseDestruct completed\n", pDrvIns->pReg->szName, pDrvIns->iInstance));
|
---|
[1] | 1263 | }
|
---|
| 1264 |
|
---|
| 1265 |
|
---|
| 1266 | /**
|
---|
[64316] | 1267 | * Initializes the instance data .
|
---|
[1] | 1268 | *
|
---|
| 1269 | * On failure call DRVHostBaseDestruct().
|
---|
| 1270 | *
|
---|
| 1271 | * @returns VBox status code.
|
---|
| 1272 | * @param pDrvIns Driver instance.
|
---|
[64316] | 1273 | * @param pszCfgValid Pointer to a string of valid CFGM options.
|
---|
[26173] | 1274 | * @param pCfg Configuration handle.
|
---|
[1] | 1275 | * @param enmType Device type.
|
---|
| 1276 | */
|
---|
[64316] | 1277 | DECLHIDDEN(int) DRVHostBaseInit(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, const char *pszCfgValid, PDMMEDIATYPE enmType)
|
---|
[1] | 1278 | {
|
---|
[64316] | 1279 | int src = VINF_SUCCESS;
|
---|
[91869] | 1280 | PDRVHOSTBASE pThis = PDMINS_2_DATA(pDrvIns, PDRVHOSTBASE);
|
---|
| 1281 | PCPDMDRVHLPR3 pHlp = pDrvIns->pHlpR3;
|
---|
| 1282 |
|
---|
[64316] | 1283 | LogFlow(("%s-%d: DRVHostBaseInit: iInstance=%d\n", pDrvIns->pReg->szName, pDrvIns->iInstance, pDrvIns->iInstance));
|
---|
[1] | 1284 |
|
---|
| 1285 | /*
|
---|
| 1286 | * Initialize most of the data members.
|
---|
| 1287 | */
|
---|
| 1288 | pThis->pDrvIns = pDrvIns;
|
---|
[3113] | 1289 | pThis->fKeepInstance = false;
|
---|
[1] | 1290 | pThis->ThreadPoller = NIL_RTTHREAD;
|
---|
| 1291 | pThis->enmType = enmType;
|
---|
[45061] | 1292 | pThis->fAttachFailError = true; /* It's an error until we've read the config. */
|
---|
[1] | 1293 |
|
---|
| 1294 | /* IBase. */
|
---|
| 1295 | pDrvIns->IBase.pfnQueryInterface = drvHostBaseQueryInterface;
|
---|
| 1296 |
|
---|
[59248] | 1297 | /* IMedia. */
|
---|
[66165] | 1298 | pThis->IMedia.pfnRead = drvHostBaseRead;
|
---|
| 1299 | pThis->IMedia.pfnWrite = drvHostBaseWrite;
|
---|
| 1300 | pThis->IMedia.pfnFlush = drvHostBaseFlush;
|
---|
| 1301 | pThis->IMedia.pfnIsReadOnly = drvHostBaseIsReadOnly;
|
---|
| 1302 | pThis->IMedia.pfnIsNonRotational = drvHostBaseIsNonRotational;
|
---|
| 1303 | pThis->IMedia.pfnGetSize = drvHostBaseGetSize;
|
---|
| 1304 | pThis->IMedia.pfnGetType = drvHostBaseGetType;
|
---|
| 1305 | pThis->IMedia.pfnGetUuid = drvHostBaseGetUuid;
|
---|
| 1306 | pThis->IMedia.pfnBiosGetPCHSGeometry = drvHostBaseGetPCHSGeometry;
|
---|
| 1307 | pThis->IMedia.pfnBiosSetPCHSGeometry = drvHostBaseSetPCHSGeometry;
|
---|
| 1308 | pThis->IMedia.pfnBiosGetLCHSGeometry = drvHostBaseGetLCHSGeometry;
|
---|
| 1309 | pThis->IMedia.pfnBiosSetLCHSGeometry = drvHostBaseSetLCHSGeometry;
|
---|
| 1310 | pThis->IMedia.pfnBiosIsVisible = drvHostBaseIsVisible;
|
---|
| 1311 | pThis->IMedia.pfnGetRegionCount = drvHostBaseGetRegionCount;
|
---|
| 1312 | pThis->IMedia.pfnQueryRegionProperties = drvHostBaseQueryRegionProperties;
|
---|
| 1313 | pThis->IMedia.pfnQueryRegionPropertiesForLba = drvHostBaseQueryRegionPropertiesForLba;
|
---|
[1] | 1314 |
|
---|
[64320] | 1315 | /* IMediaEx */
|
---|
| 1316 | pThis->IMediaEx.pfnQueryFeatures = drvHostBaseQueryFeatures;
|
---|
[71807] | 1317 | pThis->IMediaEx.pfnNotifySuspend = drvHostBaseNotifySuspend;
|
---|
[64320] | 1318 | pThis->IMediaEx.pfnIoReqAllocSizeSet = drvHostBaseIoReqAllocSizeSet;
|
---|
| 1319 | pThis->IMediaEx.pfnIoReqAlloc = drvHostBaseIoReqAlloc;
|
---|
| 1320 | pThis->IMediaEx.pfnIoReqFree = drvHostBaseIoReqFree;
|
---|
| 1321 | pThis->IMediaEx.pfnIoReqQueryResidual = drvHostBaseIoReqQueryResidual;
|
---|
[64407] | 1322 | pThis->IMediaEx.pfnIoReqQueryXferSize = drvHostBaseIoReqQueryXferSize;
|
---|
[64320] | 1323 | pThis->IMediaEx.pfnIoReqCancelAll = drvHostBaseIoReqCancelAll;
|
---|
| 1324 | pThis->IMediaEx.pfnIoReqCancel = drvHostBaseIoReqCancel;
|
---|
| 1325 | pThis->IMediaEx.pfnIoReqRead = drvHostBaseIoReqRead;
|
---|
| 1326 | pThis->IMediaEx.pfnIoReqWrite = drvHostBaseIoReqWrite;
|
---|
| 1327 | pThis->IMediaEx.pfnIoReqFlush = drvHostBaseIoReqFlush;
|
---|
| 1328 | pThis->IMediaEx.pfnIoReqDiscard = drvHostBaseIoReqDiscard;
|
---|
| 1329 | pThis->IMediaEx.pfnIoReqGetActiveCount = drvHostBaseIoReqGetActiveCount;
|
---|
| 1330 | pThis->IMediaEx.pfnIoReqGetSuspendedCount = drvHostBaseIoReqGetSuspendedCount;
|
---|
| 1331 | pThis->IMediaEx.pfnIoReqQuerySuspendedStart = drvHostBaseIoReqQuerySuspendedStart;
|
---|
| 1332 | pThis->IMediaEx.pfnIoReqQuerySuspendedNext = drvHostBaseIoReqQuerySuspendedNext;
|
---|
| 1333 | pThis->IMediaEx.pfnIoReqSuspendedSave = drvHostBaseIoReqSuspendedSave;
|
---|
| 1334 | pThis->IMediaEx.pfnIoReqSuspendedLoad = drvHostBaseIoReqSuspendedLoad;
|
---|
| 1335 |
|
---|
[1] | 1336 | /* IMount. */
|
---|
| 1337 | pThis->IMount.pfnUnmount = drvHostBaseUnmount;
|
---|
| 1338 | pThis->IMount.pfnIsMounted = drvHostBaseIsMounted;
|
---|
| 1339 | pThis->IMount.pfnLock = drvHostBaseLock;
|
---|
| 1340 | pThis->IMount.pfnUnlock = drvHostBaseUnlock;
|
---|
| 1341 | pThis->IMount.pfnIsLocked = drvHostBaseIsLocked;
|
---|
| 1342 |
|
---|
[64316] | 1343 | drvHostBaseInitOs(pThis);
|
---|
| 1344 |
|
---|
[91869] | 1345 | if (!pHlp->pfnCFGMAreValuesValid(pCfg, pszCfgValid))
|
---|
[64278] | 1346 | {
|
---|
| 1347 | pThis->fAttachFailError = true;
|
---|
| 1348 | return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES;
|
---|
| 1349 | }
|
---|
| 1350 |
|
---|
[1] | 1351 | /*
|
---|
[64320] | 1352 | * Get the IMediaPort & IMountNotify interfaces of the above driver/device.
|
---|
[1] | 1353 | */
|
---|
[59248] | 1354 | pThis->pDrvMediaPort = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMIMEDIAPORT);
|
---|
| 1355 | if (!pThis->pDrvMediaPort)
|
---|
[1] | 1356 | {
|
---|
[59248] | 1357 | AssertMsgFailed(("Configuration error: No media port interface above!\n"));
|
---|
[1] | 1358 | return VERR_PDM_MISSING_INTERFACE_ABOVE;
|
---|
| 1359 | }
|
---|
[64320] | 1360 | pThis->pDrvMediaExPort = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMIMEDIAEXPORT);
|
---|
[25974] | 1361 | pThis->pDrvMountNotify = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMIMOUNTNOTIFY);
|
---|
[1] | 1362 |
|
---|
| 1363 | /*
|
---|
| 1364 | * Query configuration.
|
---|
| 1365 | */
|
---|
| 1366 | /* Device */
|
---|
[91869] | 1367 | int rc = pHlp->pfnCFGMQueryStringAlloc(pCfg, "Path", &pThis->pszDevice);
|
---|
[11266] | 1368 | if (RT_FAILURE(rc))
|
---|
[1] | 1369 | {
|
---|
[11286] | 1370 | AssertMsgFailed(("Configuration error: query for \"Path\" string returned %Rra.\n", rc));
|
---|
[1] | 1371 | return rc;
|
---|
| 1372 | }
|
---|
| 1373 |
|
---|
| 1374 | /* Mountable */
|
---|
| 1375 | uint32_t u32;
|
---|
[91869] | 1376 | rc = pHlp->pfnCFGMQueryU32Def(pCfg, "Interval", &u32, 1000);
|
---|
[11266] | 1377 | if (RT_SUCCESS(rc))
|
---|
[1] | 1378 | pThis->cMilliesPoller = u32;
|
---|
[64316] | 1379 | else
|
---|
[1] | 1380 | {
|
---|
[11284] | 1381 | AssertMsgFailed(("Configuration error: Query \"Mountable\" resulted in %Rrc.\n", rc));
|
---|
[1] | 1382 | return rc;
|
---|
| 1383 | }
|
---|
| 1384 |
|
---|
[64316] | 1385 | /* ReadOnly - passthrough mode requires read/write access in any case. */
|
---|
| 1386 | if ( (pThis->enmType == PDMMEDIATYPE_CDROM || pThis->enmType == PDMMEDIATYPE_DVD)
|
---|
| 1387 | && pThis->IMedia.pfnSendCmd)
|
---|
| 1388 | pThis->fReadOnlyConfig = false;
|
---|
| 1389 | else
|
---|
[1] | 1390 | {
|
---|
[91869] | 1391 | rc = pHlp->pfnCFGMQueryBoolDef(pCfg, "ReadOnly", &pThis->fReadOnlyConfig,
|
---|
| 1392 | enmType == PDMMEDIATYPE_DVD || enmType == PDMMEDIATYPE_CDROM
|
---|
| 1393 | ? true
|
---|
| 1394 | : false);
|
---|
[64316] | 1395 | if (RT_FAILURE(rc))
|
---|
| 1396 | {
|
---|
| 1397 | AssertMsgFailed(("Configuration error: Query \"ReadOnly\" resulted in %Rrc.\n", rc));
|
---|
| 1398 | return rc;
|
---|
| 1399 | }
|
---|
[1] | 1400 | }
|
---|
| 1401 |
|
---|
| 1402 | /* Locked */
|
---|
[91869] | 1403 | rc = pHlp->pfnCFGMQueryBoolDef(pCfg, "Locked", &pThis->fLocked, false);
|
---|
[64316] | 1404 | if (RT_FAILURE(rc))
|
---|
[1] | 1405 | {
|
---|
[11284] | 1406 | AssertMsgFailed(("Configuration error: Query \"Locked\" resulted in %Rrc.\n", rc));
|
---|
[1] | 1407 | return rc;
|
---|
| 1408 | }
|
---|
| 1409 |
|
---|
| 1410 | /* BIOS visible */
|
---|
[91869] | 1411 | rc = pHlp->pfnCFGMQueryBoolDef(pCfg, "BIOSVisible", &pThis->fBiosVisible, true);
|
---|
[64316] | 1412 | if (RT_FAILURE(rc))
|
---|
[1] | 1413 | {
|
---|
[11284] | 1414 | AssertMsgFailed(("Configuration error: Query \"BIOSVisible\" resulted in %Rrc.\n", rc));
|
---|
[1] | 1415 | return rc;
|
---|
| 1416 | }
|
---|
| 1417 |
|
---|
| 1418 | /* Uuid */
|
---|
| 1419 | char *psz;
|
---|
[91869] | 1420 | rc = pHlp->pfnCFGMQueryStringAlloc(pCfg, "Uuid", &psz);
|
---|
[1] | 1421 | if (rc == VERR_CFGM_VALUE_NOT_FOUND)
|
---|
| 1422 | RTUuidClear(&pThis->Uuid);
|
---|
[11266] | 1423 | else if (RT_SUCCESS(rc))
|
---|
[1] | 1424 | {
|
---|
| 1425 | rc = RTUuidFromStr(&pThis->Uuid, psz);
|
---|
[11266] | 1426 | if (RT_FAILURE(rc))
|
---|
[1] | 1427 | {
|
---|
[11284] | 1428 | AssertMsgFailed(("Configuration error: Uuid from string failed on \"%s\", rc=%Rrc.\n", psz, rc));
|
---|
[91897] | 1429 | PDMDrvHlpMMHeapFree(pDrvIns, psz);
|
---|
[1] | 1430 | return rc;
|
---|
| 1431 | }
|
---|
[91897] | 1432 | PDMDrvHlpMMHeapFree(pDrvIns, psz);
|
---|
[1] | 1433 | }
|
---|
| 1434 | else
|
---|
| 1435 | {
|
---|
[11284] | 1436 | AssertMsgFailed(("Configuration error: Failed to obtain the uuid, rc=%Rrc.\n", rc));
|
---|
[1] | 1437 | return rc;
|
---|
| 1438 | }
|
---|
| 1439 |
|
---|
[3113] | 1440 | /* Define whether attach failure is an error (default) or not. */
|
---|
[64316] | 1441 | bool fAttachFailError = true;
|
---|
[91869] | 1442 | rc = pHlp->pfnCFGMQueryBoolDef(pCfg, "AttachFailError", &fAttachFailError, true);
|
---|
[3113] | 1443 | pThis->fAttachFailError = fAttachFailError;
|
---|
| 1444 |
|
---|
[1] | 1445 | /* log config summary */
|
---|
[11287] | 1446 | Log(("%s-%d: pszDevice='%s' (%s) cMilliesPoller=%d fReadOnlyConfig=%d fLocked=%d fBIOSVisible=%d Uuid=%RTuuid\n",
|
---|
[26166] | 1447 | pDrvIns->pReg->szName, pDrvIns->iInstance, pThis->pszDevice, pThis->pszDeviceOpen, pThis->cMilliesPoller,
|
---|
[1] | 1448 | pThis->fReadOnlyConfig, pThis->fLocked, pThis->fBiosVisible, &pThis->Uuid));
|
---|
| 1449 |
|
---|
| 1450 | /*
|
---|
| 1451 | * Check that there are no drivers below us.
|
---|
| 1452 | */
|
---|
[22480] | 1453 | AssertMsgReturn(PDMDrvHlpNoAttach(pDrvIns) == VERR_PDM_NO_ATTACHED_DRIVER,
|
---|
[22277] | 1454 | ("Configuration error: Not possible to attach anything to this driver!\n"),
|
---|
| 1455 | VERR_PDM_DRVINS_NO_ATTACH);
|
---|
[1] | 1456 |
|
---|
| 1457 | /*
|
---|
| 1458 | * Register saved state.
|
---|
| 1459 | */
|
---|
[64316] | 1460 | rc = PDMDrvHlpSSMRegisterLoadDone(pDrvIns, drvHostBaseLoadDone);
|
---|
[11266] | 1461 | if (RT_FAILURE(rc))
|
---|
[1] | 1462 | return rc;
|
---|
| 1463 |
|
---|
| 1464 | /*
|
---|
[64316] | 1465 | * Initialize the critical section used for serializing the access to the media.
|
---|
[1] | 1466 | */
|
---|
[64316] | 1467 | rc = RTCritSectInit(&pThis->CritSect);
|
---|
| 1468 | if (RT_FAILURE(rc))
|
---|
| 1469 | return rc;
|
---|
[1] | 1470 |
|
---|
| 1471 | /*
|
---|
| 1472 | * Open the device.
|
---|
| 1473 | */
|
---|
[64316] | 1474 | rc = drvHostBaseOpenOs(pThis, pThis->fReadOnlyConfig);
|
---|
[11266] | 1475 | if (RT_FAILURE(rc))
|
---|
[1] | 1476 | {
|
---|
[262] | 1477 | char *pszDevice = pThis->pszDevice;
|
---|
[3666] | 1478 | #ifndef RT_OS_DARWIN
|
---|
[1965] | 1479 | char szPathReal[256];
|
---|
[2272] | 1480 | if ( RTPathExists(pszDevice)
|
---|
| 1481 | && RT_SUCCESS(RTPathReal(pszDevice, szPathReal, sizeof(szPathReal))))
|
---|
[1965] | 1482 | pszDevice = szPathReal;
|
---|
| 1483 | #endif
|
---|
[5212] | 1484 |
|
---|
| 1485 | /*
|
---|
| 1486 | * Disable CD/DVD passthrough in case it was enabled. Would cause
|
---|
[3538] | 1487 | * weird failures later when the guest issues commands. These would
|
---|
| 1488 | * all fail because of the invalid file handle. So use the normal
|
---|
| 1489 | * virtual CD/DVD code, which deals more gracefully with unavailable
|
---|
[5212] | 1490 | * "media" - actually a complete drive in this case.
|
---|
| 1491 | */
|
---|
[59248] | 1492 | pThis->IMedia.pfnSendCmd = NULL;
|
---|
[11284] | 1493 | AssertMsgFailed(("Could not open host device %s, rc=%Rrc\n", pszDevice, rc));
|
---|
[262] | 1494 | switch (rc)
|
---|
| 1495 | {
|
---|
| 1496 | case VERR_ACCESS_DENIED:
|
---|
| 1497 | return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS,
|
---|
[3666] | 1498 | #ifdef RT_OS_LINUX
|
---|
[262] | 1499 | N_("Cannot open host device '%s' for %s access. Check the permissions "
|
---|
| 1500 | "of that device ('/bin/ls -l %s'): Most probably you need to be member "
|
---|
| 1501 | "of the device group. Make sure that you logout/login after changing "
|
---|
| 1502 | "the group settings of the current user"),
|
---|
| 1503 | #else
|
---|
| 1504 | N_("Cannot open host device '%s' for %s access. Check the permissions "
|
---|
| 1505 | "of that device"),
|
---|
| 1506 | #endif
|
---|
[1965] | 1507 | pszDevice, pThis->fReadOnlyConfig ? "readonly" : "read/write",
|
---|
| 1508 | pszDevice);
|
---|
[262] | 1509 | default:
|
---|
[3158] | 1510 | {
|
---|
[3113] | 1511 | if (pThis->fAttachFailError)
|
---|
| 1512 | return rc;
|
---|
[18645] | 1513 | int erc = PDMDrvHlpVMSetRuntimeError(pDrvIns, 0 /*fFlags*/,
|
---|
| 1514 | "DrvHost_MOUNTFAIL",
|
---|
[3158] | 1515 | N_("Cannot attach to host device '%s'"), pszDevice);
|
---|
| 1516 | AssertRC(erc);
|
---|
| 1517 | src = rc;
|
---|
| 1518 | }
|
---|
[262] | 1519 | }
|
---|
[1] | 1520 | }
|
---|
| 1521 |
|
---|
| 1522 | /*
|
---|
| 1523 | * Lock the drive if that's required by the configuration.
|
---|
| 1524 | */
|
---|
| 1525 | if (pThis->fLocked)
|
---|
| 1526 | {
|
---|
| 1527 | if (pThis->pfnDoLock)
|
---|
| 1528 | rc = pThis->pfnDoLock(pThis, true);
|
---|
[11266] | 1529 | if (RT_FAILURE(rc))
|
---|
[1] | 1530 | {
|
---|
[11284] | 1531 | AssertMsgFailed(("Failed to lock the dvd drive. rc=%Rrc\n", rc));
|
---|
[1] | 1532 | return rc;
|
---|
| 1533 | }
|
---|
| 1534 | }
|
---|
| 1535 |
|
---|
[64316] | 1536 | if (RT_SUCCESS(src) && drvHostBaseIsMediaPollingRequiredOs(pThis))
|
---|
[3113] | 1537 | {
|
---|
| 1538 | /*
|
---|
| 1539 | * Create the event semaphore which the poller thread will wait on.
|
---|
| 1540 | */
|
---|
| 1541 | rc = RTSemEventCreate(&pThis->EventPoller);
|
---|
[11266] | 1542 | if (RT_FAILURE(rc))
|
---|
[3113] | 1543 | return rc;
|
---|
[1] | 1544 |
|
---|
[3113] | 1545 | /*
|
---|
| 1546 | * Start the thread which will poll for the media.
|
---|
| 1547 | */
|
---|
| 1548 | rc = RTThreadCreate(&pThis->ThreadPoller, drvHostBaseMediaThread, pThis, 0,
|
---|
| 1549 | RTTHREADTYPE_INFREQUENT_POLLER, RTTHREADFLAGS_WAITABLE, "DVDMEDIA");
|
---|
[11266] | 1550 | if (RT_FAILURE(rc))
|
---|
[3113] | 1551 | {
|
---|
[11284] | 1552 | AssertMsgFailed(("Failed to create poller thread. rc=%Rrc\n", rc));
|
---|
[3113] | 1553 | return rc;
|
---|
| 1554 | }
|
---|
[1] | 1555 |
|
---|
[3113] | 1556 | /*
|
---|
| 1557 | * Wait for the thread to start up (!w32:) and do one detection loop.
|
---|
| 1558 | */
|
---|
| 1559 | rc = RTThreadUserWait(pThis->ThreadPoller, 10000);
|
---|
| 1560 | AssertRC(rc);
|
---|
| 1561 | }
|
---|
[1] | 1562 |
|
---|
[64839] | 1563 | if (RT_SUCCESS(rc))
|
---|
| 1564 | drvHostBaseStatsRegister(pThis);
|
---|
| 1565 |
|
---|
[64316] | 1566 | if (RT_FAILURE(rc))
|
---|
| 1567 | {
|
---|
| 1568 | if (!pThis->fAttachFailError)
|
---|
| 1569 | {
|
---|
| 1570 | /* Suppressing the attach failure error must not affect the normal
|
---|
| 1571 | * DRVHostBaseDestruct, so reset this flag below before leaving. */
|
---|
| 1572 | pThis->fKeepInstance = true;
|
---|
| 1573 | rc = VINF_SUCCESS;
|
---|
| 1574 | }
|
---|
| 1575 | DRVHostBaseDestruct(pDrvIns);
|
---|
| 1576 | pThis->fKeepInstance = false;
|
---|
| 1577 | }
|
---|
| 1578 |
|
---|
[11266] | 1579 | if (RT_FAILURE(src))
|
---|
[3113] | 1580 | return src;
|
---|
[64316] | 1581 |
|
---|
[3158] | 1582 | return rc;
|
---|
[1] | 1583 | }
|
---|
| 1584 |
|
---|