Changeset 64064 in vbox
- Timestamp:
- Sep 28, 2016 8:51:22 AM (8 years ago)
- svn:sync-xref-src-repo-rev:
- 110992
- Location:
- trunk/src/VBox/Devices/Storage/VSCSI
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Storage/VSCSI/VSCSIInternal.h
r63992 r64064 208 208 DECLR3CALLBACKMEMBER(int, pfnVScsiLunReqProcess, (PVSCSILUNINT pVScsiLun, PVSCSIREQINT pVScsiReq)); 209 209 210 /** 211 * Informs about a medium being inserted - optional. 212 * 213 * @returns VBox status code. 214 * @param pVScsiLun The SCSI LUN instance. 215 */ 216 DECLR3CALLBACKMEMBER(int, pfnVScsiLunMediumInserted, (PVSCSILUNINT pVScsiLun)); 217 218 /** 219 * Informs about a medium being removed - optional. 220 * 221 * @returns VBox status code. 222 * @param pVScsiLun The SCSI LUN instance. 223 */ 224 DECLR3CALLBACKMEMBER(int, pfnVScsiLunMediumRemoved, (PVSCSILUNINT pVScsiLun)); 225 210 226 } VSCSILUNDESC; 211 227 -
trunk/src/VBox/Devices/Storage/VSCSI/VSCSILun.cpp
r63992 r64064 129 129 VBOXDDU_DECL(int) VSCSILunMountNotify(VSCSILUN hVScsiLun) 130 130 { 131 int rc = VINF_SUCCESS; 131 132 PVSCSILUNINT pVScsiLun = (PVSCSILUNINT)hVScsiLun; 132 133 … … 138 139 pVScsiLun->fReady = false; 139 140 pVScsiLun->fMediaPresent = true; 141 if (pVScsiLun->pVScsiLunDesc->pfnVScsiLunMediumInserted) 142 rc = pVScsiLun->pVScsiLunDesc->pfnVScsiLunMediumInserted(pVScsiLun); 140 143 141 return VINF_SUCCESS;144 return rc; 142 145 } 143 146 … … 151 154 VBOXDDU_DECL(int) VSCSILunUnmountNotify(VSCSILUN hVScsiLun) 152 155 { 156 int rc = VINF_SUCCESS; 153 157 PVSCSILUNINT pVScsiLun = (PVSCSILUNINT)hVScsiLun; 154 158 … … 159 163 pVScsiLun->fReady = false; 160 164 pVScsiLun->fMediaPresent = false; 165 if (pVScsiLun->pVScsiLunDesc->pfnVScsiLunMediumRemoved) 166 rc = pVScsiLun->pVScsiLunDesc->pfnVScsiLunMediumRemoved(pVScsiLun); 161 167 162 return VINF_SUCCESS;168 return rc; 163 169 } -
trunk/src/VBox/Devices/Storage/VSCSI/VSCSILunMmc.cpp
r63562 r64064 25 25 #include <VBox/types.h> 26 26 #include <VBox/vscsi.h> 27 #include <iprt/asm.h> 27 28 #include <iprt/assert.h> 28 29 #include <iprt/mem.h> … … 30 31 31 32 #include "VSCSIInternal.h" 33 34 /** 35 * Different event status types. 36 */ 37 typedef enum MMCEVENTSTATUSTYPE 38 { 39 /** Medium event status not changed. */ 40 MMCEVENTSTATUSTYPE_UNCHANGED = 0, 41 /** New medium inserted. */ 42 MMCEVENTSTATUSTYPE_MEDIA_NEW, 43 /** Medium removed. */ 44 MMCEVENTSTATUSTYPE_MEDIA_REMOVED, 45 /** Medium was removed + new medium was inserted. */ 46 MMCEVENTSTATUSTYPE_MEDIA_CHANGED, 47 /** Medium eject requested (eject button pressed). */ 48 MMCEVENTSTATUSTYPE_MEDIA_EJECT_REQUESTED, 49 /** 32bit hack. */ 50 MMCEVENTSTATUSTYPE_32BIT_HACK = 0x7fffffff 51 } MMCEVENTSTATUSTYPE; 52 53 /** @name Media track types. 54 * @{ */ 55 /** Unknown media type. */ 56 #define MMC_MEDIA_TYPE_UNKNOWN 0 57 /** Door closed, no media. */ 58 #define MMC_MEDIA_TYPE_NO_DISC 0x70 59 /** @} */ 60 32 61 33 62 /** … … 37 66 { 38 67 /** Core LUN structure */ 39 VSCSILUNINT Core;68 VSCSILUNINT Core; 40 69 /** Size of the virtual disk. */ 41 uint64_t cSectors;70 uint64_t cSectors; 42 71 /** Sector size. */ 43 uint32_t cbSector;72 uint32_t cbSector; 44 73 /** Medium locked indicator. */ 45 bool fLocked; 74 bool fLocked; 75 /** Media event status. */ 76 volatile MMCEVENTSTATUSTYPE MediaEventStatus; 77 /** Media track type. */ 78 volatile uint32_t u32MediaTrackType; 46 79 } VSCSILUNMMC, *PVSCSILUNMMC; 47 80 … … 158 191 } 159 192 193 /** 194 * Create raw TOC data information. 195 * 196 * @returns SCSI status code. 197 * @param pVScsiLun The LUN instance. 198 * @param pVScsiReq The VSCSI request. 199 * @param cbMaxTransfer The maximum transfer size. 200 * @param fMSF Flag whether to use MSF format to encode sector numbers. 201 */ 202 static int mmcReadTOCRaw(PVSCSILUNINT pVScsiLun, PVSCSIREQINT pVScsiReq, uint16_t cbMaxTransfer, bool fMSF) 203 { 204 PVSCSILUNMMC pVScsiLunMmc = (PVSCSILUNMMC)pVScsiLun; 205 uint8_t aReply[50]; /* Counted a maximum of 45 bytes but better be on the safe side. */ 206 uint32_t cbSize; 207 uint8_t *pbBuf = &aReply[0] + 2; 208 209 *pbBuf++ = 1; /* first session */ 210 *pbBuf++ = 1; /* last session */ 211 212 *pbBuf++ = 1; /* session number */ 213 *pbBuf++ = 0x14; /* data track */ 214 *pbBuf++ = 0; /* track number */ 215 *pbBuf++ = 0xa0; /* first track in program area */ 216 *pbBuf++ = 0; /* min */ 217 *pbBuf++ = 0; /* sec */ 218 *pbBuf++ = 0; /* frame */ 219 *pbBuf++ = 0; 220 *pbBuf++ = 1; /* first track */ 221 *pbBuf++ = 0x00; /* disk type CD-DA or CD data */ 222 *pbBuf++ = 0; 223 224 *pbBuf++ = 1; /* session number */ 225 *pbBuf++ = 0x14; /* data track */ 226 *pbBuf++ = 0; /* track number */ 227 *pbBuf++ = 0xa1; /* last track in program area */ 228 *pbBuf++ = 0; /* min */ 229 *pbBuf++ = 0; /* sec */ 230 *pbBuf++ = 0; /* frame */ 231 *pbBuf++ = 0; 232 *pbBuf++ = 1; /* last track */ 233 *pbBuf++ = 0; 234 *pbBuf++ = 0; 235 236 *pbBuf++ = 1; /* session number */ 237 *pbBuf++ = 0x14; /* data track */ 238 *pbBuf++ = 0; /* track number */ 239 *pbBuf++ = 0xa2; /* lead-out */ 240 *pbBuf++ = 0; /* min */ 241 *pbBuf++ = 0; /* sec */ 242 *pbBuf++ = 0; /* frame */ 243 if (fMSF) 244 { 245 *pbBuf++ = 0; /* reserved */ 246 mmcLBA2MSF(pbBuf, pVScsiLunMmc->cSectors); 247 pbBuf += 3; 248 } 249 else 250 { 251 vscsiH2BEU32(pbBuf, pVScsiLunMmc->cSectors); 252 pbBuf += 4; 253 } 254 255 *pbBuf++ = 1; /* session number */ 256 *pbBuf++ = 0x14; /* ADR, control */ 257 *pbBuf++ = 0; /* track number */ 258 *pbBuf++ = 1; /* point */ 259 *pbBuf++ = 0; /* min */ 260 *pbBuf++ = 0; /* sec */ 261 *pbBuf++ = 0; /* frame */ 262 if (fMSF) 263 { 264 *pbBuf++ = 0; /* reserved */ 265 mmcLBA2MSF(pbBuf, 0); 266 pbBuf += 3; 267 } 268 else 269 { 270 /* sector 0 */ 271 vscsiH2BEU32(pbBuf, 0); 272 pbBuf += 4; 273 } 274 275 cbSize = pbBuf - aReply; 276 vscsiH2BEU16(&aReply[0], cbSize - 2); 277 278 RTSgBufCopyFromBuf(&pVScsiReq->SgBuf, aReply, RT_MIN(cbMaxTransfer, cbSize)); 279 return vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq); 280 } 281 282 static size_t vscsiLunMmcGetConfigurationFillFeatureListProfiles(uint8_t *pbBuf, size_t cbBuf) 283 { 284 if (cbBuf < 3*4) 285 return 0; 286 287 vscsiH2BEU16(pbBuf, 0x0); /* feature 0: list of profiles supported */ 288 pbBuf[2] = (0 << 2) | (1 << 1) | (1 << 0); /* version 0, persistent, current */ 289 pbBuf[3] = 8; /* additional bytes for profiles */ 290 /* The MMC-3 spec says that DVD-ROM read capability should be reported 291 * before CD-ROM read capability. */ 292 vscsiH2BEU16(pbBuf + 4, 0x10); /* profile: read-only DVD */ 293 pbBuf[6] = (0 << 0); /* NOT current profile */ 294 vscsiH2BEU16(pbBuf + 8, 0x08); /* profile: read only CD */ 295 pbBuf[10] = (1 << 0); /* current profile */ 296 297 return 3*4; /* Header + 2 profiles entries */ 298 } 299 300 static size_t vscsiLunMmcGetConfigurationFillFeatureCore(uint8_t *pbBuf, size_t cbBuf) 301 { 302 if (cbBuf < 12) 303 return 0; 304 305 vscsiH2BEU16(pbBuf, 0x1); /* feature 0001h: Core Feature */ 306 pbBuf[2] = (0x2 << 2) | RT_BIT(1) | RT_BIT(0); /* Version | Persistent | Current */ 307 pbBuf[3] = 8; /* Additional length */ 308 vscsiH2BEU16(pbBuf + 4, 0x00000002); /* Physical interface ATAPI. */ 309 pbBuf[8] = RT_BIT(0); /* DBE */ 310 /* Rest is reserved. */ 311 312 return 12; 313 } 314 315 static size_t vscsiLunMmcGetConfigurationFillFeatureMorphing(uint8_t *pbBuf, size_t cbBuf) 316 { 317 if (cbBuf < 8) 318 return 0; 319 320 vscsiH2BEU16(pbBuf, 0x2); /* feature 0002h: Morphing Feature */ 321 pbBuf[2] = (0x1 << 2) | RT_BIT(1) | RT_BIT(0); /* Version | Persistent | Current */ 322 pbBuf[3] = 4; /* Additional length */ 323 pbBuf[4] = RT_BIT(1) | 0x0; /* OCEvent | !ASYNC */ 324 /* Rest is reserved. */ 325 326 return 8; 327 } 328 329 static size_t vscsiLunMmcGetConfigurationFillFeatureRemovableMedium(uint8_t *pbBuf, size_t cbBuf) 330 { 331 if (cbBuf < 8) 332 return 0; 333 334 vscsiH2BEU16(pbBuf, 0x3); /* feature 0003h: Removable Medium Feature */ 335 pbBuf[2] = (0x2 << 2) | RT_BIT(1) | RT_BIT(0); /* Version | Persistent | Current */ 336 pbBuf[3] = 4; /* Additional length */ 337 /* Tray type loading | Load | Eject | !Pvnt Jmpr | !DBML | Lock */ 338 pbBuf[4] = (0x2 << 5) | RT_BIT(4) | RT_BIT(3) | (0x0 << 2) | (0x0 << 1) | RT_BIT(0); 339 /* Rest is reserved. */ 340 341 return 8; 342 } 343 344 static size_t vscsiLunMmcGetConfigurationFillFeatureRandomReadable(uint8_t *pbBuf, size_t cbBuf) 345 { 346 if (cbBuf < 12) 347 return 0; 348 349 vscsiH2BEU16(pbBuf, 0x10); /* feature 0010h: Random Readable Feature */ 350 pbBuf[2] = (0x0 << 2) | RT_BIT(1) | RT_BIT(0); /* Version | Persistent | Current */ 351 pbBuf[3] = 8; /* Additional length */ 352 vscsiH2BEU32(pbBuf + 4, 2048); /* Logical block size. */ 353 vscsiH2BEU16(pbBuf + 8, 0x10); /* Blocking (0x10 for DVD, CD is not defined). */ 354 pbBuf[10] = 0; /* PP not present */ 355 /* Rest is reserved. */ 356 357 return 12; 358 } 359 360 static size_t vscsiLunMmcGetConfigurationFillFeatureCDRead(uint8_t *pbBuf, size_t cbBuf) 361 { 362 if (cbBuf < 8) 363 return 0; 364 365 vscsiH2BEU16(pbBuf, 0x1e); /* feature 001Eh: CD Read Feature */ 366 pbBuf[2] = (0x2 << 2) | RT_BIT(1) | RT_BIT(0); /* Version | Persistent | Current */ 367 pbBuf[3] = 0; /* Additional length */ 368 pbBuf[4] = (0x0 << 7) | (0x0 << 1) | 0x0; /* !DAP | !C2-Flags | !CD-Text. */ 369 /* Rest is reserved. */ 370 371 return 8; 372 } 373 374 static size_t vscsiLunMmcGetConfigurationFillFeaturePowerManagement(uint8_t *pbBuf, size_t cbBuf) 375 { 376 if (cbBuf < 4) 377 return 0; 378 379 vscsiH2BEU16(pbBuf, 0x100); /* feature 0100h: Power Management Feature */ 380 pbBuf[2] = (0x0 << 2) | RT_BIT(1) | RT_BIT(0); /* Version | Persistent | Current */ 381 pbBuf[3] = 0; /* Additional length */ 382 383 return 4; 384 } 385 386 static size_t vscsiLunMmcGetConfigurationFillFeatureTimeout(uint8_t *pbBuf, size_t cbBuf) 387 { 388 if (cbBuf < 8) 389 return 0; 390 391 vscsiH2BEU16(pbBuf, 0x105); /* feature 0105h: Timeout Feature */ 392 pbBuf[2] = (0x0 << 2) | RT_BIT(1) | RT_BIT(0); /* Version | Persistent | Current */ 393 pbBuf[3] = 4; /* Additional length */ 394 pbBuf[4] = 0x0; /* !Group3 */ 395 396 return 8; 397 } 398 399 /** 400 * Processes the GET CONFIGURATION SCSI request. 401 * 402 * @returns SCSI status code. 403 * @param pVScsiLunMmc The MMC LUN instance. 404 * @param pVScsiReq The VSCSI request. 405 * @param cbMaxTransfer The maximum transfer size. 406 */ 407 static int vscsiLunMmcGetConfiguration(PVSCSILUNMMC pVScsiLunMmc, PVSCSIREQINT pVScsiReq, uint16_t cbMaxTransfer) 408 { 409 uint8_t aReply[80]; 410 uint8_t *pbBuf = &aReply[0]; 411 size_t cbBuf = sizeof(aReply); 412 size_t cbCopied = 0; 413 414 /* Accept valid request types only, and only starting feature 0. */ 415 if ((pVScsiReq->pbCDB[1] & 0x03) == 3 || vscsiBE2HU16(&pVScsiReq->pbCDB[2]) != 0) 416 return vscsiLunReqSenseErrorSet(&pVScsiLunMmc->Core, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, 417 SCSI_ASC_INV_FIELD_IN_CMD_PACKET, 0x00); 418 419 /** @todo implement switching between CD-ROM and DVD-ROM profile (the only 420 * way to differentiate them right now is based on the image size). */ 421 if (pVScsiLunMmc->cSectors) 422 vscsiH2BEU16(pbBuf + 6, 0x08); /* current profile: read-only CD */ 423 else 424 vscsiH2BEU16(pbBuf + 6, 0x00); /* current profile: none -> no media */ 425 cbBuf -= 8; 426 pbBuf += 8; 427 428 cbCopied = vscsiLunMmcGetConfigurationFillFeatureListProfiles(pbBuf, cbBuf); 429 cbBuf -= cbCopied; 430 pbBuf += cbCopied; 431 432 cbCopied = vscsiLunMmcGetConfigurationFillFeatureCore(pbBuf, cbBuf); 433 cbBuf -= cbCopied; 434 pbBuf += cbCopied; 435 436 cbCopied = vscsiLunMmcGetConfigurationFillFeatureMorphing(pbBuf, cbBuf); 437 cbBuf -= cbCopied; 438 pbBuf += cbCopied; 439 440 cbCopied = vscsiLunMmcGetConfigurationFillFeatureRemovableMedium(pbBuf, cbBuf); 441 cbBuf -= cbCopied; 442 pbBuf += cbCopied; 443 444 cbCopied = vscsiLunMmcGetConfigurationFillFeatureRandomReadable(pbBuf, cbBuf); 445 cbBuf -= cbCopied; 446 pbBuf += cbCopied; 447 448 cbCopied = vscsiLunMmcGetConfigurationFillFeatureCDRead(pbBuf, cbBuf); 449 cbBuf -= cbCopied; 450 pbBuf += cbCopied; 451 452 cbCopied = vscsiLunMmcGetConfigurationFillFeaturePowerManagement(pbBuf, cbBuf); 453 cbBuf -= cbCopied; 454 pbBuf += cbCopied; 455 456 cbCopied = vscsiLunMmcGetConfigurationFillFeatureTimeout(pbBuf, cbBuf); 457 cbBuf -= cbCopied; 458 pbBuf += cbCopied; 459 460 /* Set data length now. */ 461 vscsiH2BEU32(&aReply[0], (uint32_t)(sizeof(aReply) - cbBuf)); 462 463 RTSgBufCopyFromBuf(&pVScsiReq->SgBuf, aReply, RT_MIN(cbMaxTransfer, sizeof(aReply) - cbBuf)); 464 return vscsiLunReqSenseOkSet(&pVScsiLunMmc->Core, pVScsiReq); 465 } 466 467 /** 468 * Processes the READ DVD STRUCTURE SCSI request. 469 * 470 * @returns SCSI status code. 471 * @param pVScsiLunMmc The MMC LUN instance. 472 * @param pVScsiReq The VSCSI request. 473 * @param cbMaxTransfer The maximum transfer size. 474 */ 475 static int vscsiLunMmcReadDvdStructure(PVSCSILUNMMC pVScsiLunMmc, PVSCSIREQINT pVScsiReq, uint16_t cbMaxTransfer) 476 { 477 uint8_t aReply[25]; /* Counted a maximum of 20 bytes but better be on the safe side. */ 478 479 RT_ZERO(aReply); 480 481 /* Act according to the indicated format. */ 482 switch (pVScsiReq->pbCDB[7]) 483 { 484 case 0x00: 485 case 0x01: 486 case 0x02: 487 case 0x03: 488 case 0x04: 489 case 0x05: 490 case 0x06: 491 case 0x07: 492 case 0x08: 493 case 0x09: 494 case 0x0a: 495 case 0x0b: 496 case 0x0c: 497 case 0x0d: 498 case 0x0e: 499 case 0x0f: 500 case 0x10: 501 case 0x11: 502 case 0x30: 503 case 0x31: 504 case 0xff: 505 if (pVScsiReq->pbCDB[1] == 0) 506 { 507 int uASC = SCSI_ASC_NONE; 508 509 switch (pVScsiReq->pbCDB[7]) 510 { 511 case 0x0: /* Physical format information */ 512 { 513 uint8_t uLayer = pVScsiReq->pbCDB[6]; 514 uint64_t cTotalSectors; 515 516 if (uLayer != 0) 517 { 518 uASC = -SCSI_ASC_INV_FIELD_IN_CMD_PACKET; 519 break; 520 } 521 522 cTotalSectors = pVScsiLunMmc->cSectors; 523 cTotalSectors >>= 2; 524 if (cTotalSectors == 0) 525 { 526 uASC = -SCSI_ASC_MEDIUM_NOT_PRESENT; 527 break; 528 } 529 530 aReply[4] = 1; /* DVD-ROM, part version 1 */ 531 aReply[5] = 0xf; /* 120mm disc, minimum rate unspecified */ 532 aReply[6] = 1; /* one layer, read-only (per MMC-2 spec) */ 533 aReply[7] = 0; /* default densities */ 534 535 /* FIXME: 0x30000 per spec? */ 536 vscsiH2BEU32(&aReply[8], 0); /* start sector */ 537 vscsiH2BEU32(&aReply[12], cTotalSectors - 1); /* end sector */ 538 vscsiH2BEU32(&aReply[16], cTotalSectors - 1); /* l0 end sector */ 539 540 /* Size of buffer, not including 2 byte size field */ 541 vscsiH2BEU32(&aReply[0], 2048 + 2); 542 543 /* 2k data + 4 byte header */ 544 uASC = (2048 + 4); 545 break; 546 } 547 case 0x01: /* DVD copyright information */ 548 aReply[4] = 0; /* no copyright data */ 549 aReply[5] = 0; /* no region restrictions */ 550 551 /* Size of buffer, not including 2 byte size field */ 552 vscsiH2BEU16(&aReply[0], 4 + 2); 553 554 /* 4 byte header + 4 byte data */ 555 uASC = (4 + 4); 556 break; 557 558 case 0x03: /* BCA information - invalid field for no BCA info */ 559 uASC = -SCSI_ASC_INV_FIELD_IN_CMD_PACKET; 560 break; 561 562 case 0x04: /* DVD disc manufacturing information */ 563 /* Size of buffer, not including 2 byte size field */ 564 vscsiH2BEU16(&aReply[0], 2048 + 2); 565 566 /* 2k data + 4 byte header */ 567 uASC = (2048 + 4); 568 break; 569 case 0xff: 570 /* 571 * This lists all the command capabilities above. Add new ones 572 * in order and update the length and buffer return values. 573 */ 574 575 aReply[4] = 0x00; /* Physical format */ 576 aReply[5] = 0x40; /* Not writable, is readable */ 577 vscsiH2BEU16(&aReply[6], 2048 + 4); 578 579 aReply[8] = 0x01; /* Copyright info */ 580 aReply[9] = 0x40; /* Not writable, is readable */ 581 vscsiH2BEU16(&aReply[10], 4 + 4); 582 583 aReply[12] = 0x03; /* BCA info */ 584 aReply[13] = 0x40; /* Not writable, is readable */ 585 vscsiH2BEU16(&aReply[14], 188 + 4); 586 587 aReply[16] = 0x04; /* Manufacturing info */ 588 aReply[17] = 0x40; /* Not writable, is readable */ 589 vscsiH2BEU16(&aReply[18], 2048 + 4); 590 591 /* Size of buffer, not including 2 byte size field */ 592 vscsiH2BEU16(&aReply[0], 16 + 2); 593 594 /* data written + 4 byte header */ 595 uASC = (16 + 4); 596 break; 597 default: /** @todo formats beyond DVD-ROM requires */ 598 uASC = -SCSI_ASC_INV_FIELD_IN_CMD_PACKET; 599 } 600 601 if (uASC < 0) 602 return vscsiLunReqSenseErrorSet(&pVScsiLunMmc->Core, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, 603 -uASC, 0x00); 604 break; 605 } 606 /** @todo BD support, fall through for now */ 607 608 /* Generic disk structures */ 609 case 0x80: /** @todo AACS volume identifier */ 610 case 0x81: /** @todo AACS media serial number */ 611 case 0x82: /** @todo AACS media identifier */ 612 case 0x83: /** @todo AACS media key block */ 613 case 0x90: /** @todo List of recognized format layers */ 614 case 0xc0: /** @todo Write protection status */ 615 default: 616 return vscsiLunReqSenseErrorSet(&pVScsiLunMmc->Core, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, 617 SCSI_ASC_INV_FIELD_IN_CMD_PACKET, 0x00); 618 } 619 620 RTSgBufCopyFromBuf(&pVScsiReq->SgBuf, aReply, RT_MIN(cbMaxTransfer, sizeof(aReply))); 621 return vscsiLunReqSenseOkSet(&pVScsiLunMmc->Core, pVScsiReq); 622 } 623 624 /** 625 * Processes the MODE SENSE 10 SCSI request. 626 * 627 * @returns SCSI status code. 628 * @param pVScsiLunMmc The MMC LUN instance. 629 * @param pVScsiReq The VSCSI request. 630 * @param cbMaxTransfer The maximum transfer size. 631 */ 632 static int vscsiLunMmcModeSense10(PVSCSILUNMMC pVScsiLunMmc, PVSCSIREQINT pVScsiReq, uint16_t cbMaxTransfer) 633 { 634 int rcReq; 635 uint8_t uPageControl = pVScsiReq->pbCDB[2] >> 6; 636 uint8_t uPageCode = pVScsiReq->pbCDB[2] & 0x3f; 637 638 switch (uPageControl) 639 { 640 case SCSI_PAGECONTROL_CURRENT: 641 switch (uPageCode) 642 { 643 case SCSI_MODEPAGE_ERROR_RECOVERY: 644 { 645 uint8_t aReply[16]; 646 647 vscsiH2BEU16(&aReply[0], 16 + 6); 648 aReply[2] = (uint8_t)pVScsiLunMmc->u32MediaTrackType; 649 aReply[3] = 0; 650 aReply[4] = 0; 651 aReply[5] = 0; 652 aReply[6] = 0; 653 aReply[7] = 0; 654 655 aReply[8] = 0x01; 656 aReply[9] = 0x06; 657 aReply[10] = 0x00; 658 aReply[11] = 0x05; 659 aReply[12] = 0x00; 660 aReply[13] = 0x00; 661 aReply[14] = 0x00; 662 aReply[15] = 0x00; 663 RTSgBufCopyFromBuf(&pVScsiReq->SgBuf, aReply, RT_MIN(cbMaxTransfer, sizeof(aReply))); 664 rcReq = vscsiLunReqSenseOkSet(&pVScsiLunMmc->Core, pVScsiReq); 665 break; 666 } 667 case SCSI_MODEPAGE_CD_STATUS: 668 { 669 uint8_t aReply[40]; 670 671 vscsiH2BEU16(&aReply[0], 38); 672 aReply[2] = (uint8_t)pVScsiLunMmc->u32MediaTrackType; 673 aReply[3] = 0; 674 aReply[4] = 0; 675 aReply[5] = 0; 676 aReply[6] = 0; 677 aReply[7] = 0; 678 679 aReply[8] = 0x2a; 680 aReply[9] = 30; /* page length */ 681 aReply[10] = 0x08; /* DVD-ROM read support */ 682 aReply[11] = 0x00; /* no write support */ 683 /* The following claims we support audio play. This is obviously false, 684 * but the Linux generic CDROM support makes many features depend on this 685 * capability. If it's not set, this causes many things to be disabled. */ 686 aReply[12] = 0x71; /* multisession support, mode 2 form 1/2 support, audio play */ 687 aReply[13] = 0x00; /* no subchannel reads supported */ 688 aReply[14] = (1 << 0) | (1 << 3) | (1 << 5); /* lock supported, eject supported, tray type loading mechanism */ 689 if (pVScsiLunMmc->fLocked) 690 aReply[14] |= 1 << 1; /* report lock state */ 691 aReply[15] = 0; /* no subchannel reads supported, no separate audio volume control, no changer etc. */ 692 vscsiH2BEU16(&aReply[16], 5632); /* (obsolete) claim 32x speed support */ 693 vscsiH2BEU16(&aReply[18], 2); /* number of audio volume levels */ 694 vscsiH2BEU16(&aReply[20], 128); /* buffer size supported in Kbyte - We don't have a buffer because we write directly into guest memory. 695 Just write some dummy value. */ 696 vscsiH2BEU16(&aReply[22], 5632); /* (obsolete) current read speed 32x */ 697 aReply[24] = 0; /* reserved */ 698 aReply[25] = 0; /* reserved for digital audio (see idx 15) */ 699 vscsiH2BEU16(&aReply[26], 0); /* (obsolete) maximum write speed */ 700 vscsiH2BEU16(&aReply[28], 0); /* (obsolete) current write speed */ 701 vscsiH2BEU16(&aReply[30], 0); /* copy management revision supported 0=no CSS */ 702 aReply[32] = 0; /* reserved */ 703 aReply[33] = 0; /* reserved */ 704 aReply[34] = 0; /* reserved */ 705 aReply[35] = 1; /* rotation control CAV */ 706 vscsiH2BEU16(&aReply[36], 0); /* current write speed */ 707 vscsiH2BEU16(&aReply[38], 0); /* number of write speed performance descriptors */ 708 RTSgBufCopyFromBuf(&pVScsiReq->SgBuf, aReply, RT_MIN(cbMaxTransfer, sizeof(aReply))); 709 rcReq = vscsiLunReqSenseOkSet(&pVScsiLunMmc->Core, pVScsiReq); 710 break; 711 } 712 default: 713 rcReq = vscsiLunReqSenseErrorSet(&pVScsiLunMmc->Core, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, 714 SCSI_ASC_INV_FIELD_IN_CMD_PACKET, 0x00); 715 break; 716 } 717 break; 718 case SCSI_PAGECONTROL_CHANGEABLE: 719 case SCSI_PAGECONTROL_DEFAULT: 720 rcReq = vscsiLunReqSenseErrorSet(&pVScsiLunMmc->Core, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, 721 SCSI_ASC_INV_FIELD_IN_CMD_PACKET, 0x00); 722 break; 723 default: 724 case SCSI_PAGECONTROL_SAVED: 725 rcReq = vscsiLunReqSenseErrorSet(&pVScsiLunMmc->Core, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, 726 SCSI_ASC_SAVING_PARAMETERS_NOT_SUPPORTED, 0x00); 727 break; 728 } 729 730 return rcReq; 731 } 732 733 /** 734 * Processes the GET EVENT STATUS NOTIFICATION SCSI request. 735 * 736 * @returns SCSI status code. 737 * @param pVScsiLunMmc The MMC LUN instance. 738 * @param pVScsiReq The VSCSI request. 739 * @param cbMaxTransfer The maximum transfer size. 740 */ 741 static int vscsiLunMmcGetEventStatusNotification(PVSCSILUNMMC pVScsiLunMmc, PVSCSIREQINT pVScsiReq, 742 uint16_t cbMaxTransfer) 743 { 744 uint32_t OldStatus; 745 uint32_t NewStatus; 746 uint8_t aReply[8]; 747 RT_ZERO(aReply); 748 749 do 750 { 751 OldStatus = ASMAtomicReadU32((volatile uint32_t *)&pVScsiLunMmc->MediaEventStatus); 752 NewStatus = MMCEVENTSTATUSTYPE_UNCHANGED; 753 754 switch (OldStatus) 755 { 756 case MMCEVENTSTATUSTYPE_MEDIA_NEW: 757 /* mount */ 758 vscsiH2BEU16(&aReply[0], 6); 759 aReply[2] = 0x04; /* media */ 760 aReply[3] = 0x5e; /* supported = busy|media|external|power|operational */ 761 aReply[4] = 0x02; /* new medium */ 762 aReply[5] = 0x02; /* medium present / door closed */ 763 aReply[6] = 0x00; 764 aReply[7] = 0x00; 765 break; 766 767 case MMCEVENTSTATUSTYPE_MEDIA_CHANGED: 768 case MMCEVENTSTATUSTYPE_MEDIA_REMOVED: 769 /* umount */ 770 vscsiH2BEU16(&aReply[0], 6); 771 aReply[2] = 0x04; /* media */ 772 aReply[3] = 0x5e; /* supported = busy|media|external|power|operational */ 773 aReply[4] = 0x03; /* media removal */ 774 aReply[5] = 0x00; /* medium absent / door closed */ 775 aReply[6] = 0x00; 776 aReply[7] = 0x00; 777 if (OldStatus == MMCEVENTSTATUSTYPE_MEDIA_CHANGED) 778 NewStatus = MMCEVENTSTATUSTYPE_MEDIA_NEW; 779 break; 780 781 case MMCEVENTSTATUSTYPE_MEDIA_EJECT_REQUESTED: /* currently unused */ 782 vscsiH2BEU16(&aReply[0], 6); 783 aReply[2] = 0x04; /* media */ 784 aReply[3] = 0x5e; /* supported = busy|media|external|power|operational */ 785 aReply[4] = 0x01; /* eject requested (eject button pressed) */ 786 aReply[5] = 0x02; /* medium present / door closed */ 787 aReply[6] = 0x00; 788 aReply[7] = 0x00; 789 break; 790 791 case MMCEVENTSTATUSTYPE_UNCHANGED: 792 default: 793 vscsiH2BEU16(&aReply[0], 6); 794 aReply[2] = 0x01; /* operational change request / notification */ 795 aReply[3] = 0x5e; /* supported = busy|media|external|power|operational */ 796 aReply[4] = 0x00; 797 aReply[5] = 0x00; 798 aReply[6] = 0x00; 799 aReply[7] = 0x00; 800 break; 801 } 802 } while (!ASMAtomicCmpXchgU32((volatile uint32_t *)&pVScsiLunMmc->MediaEventStatus, NewStatus, OldStatus)); 803 804 RTSgBufCopyFromBuf(&pVScsiReq->SgBuf, aReply, RT_MIN(cbMaxTransfer, sizeof(aReply))); 805 return vscsiLunReqSenseOkSet(&pVScsiLunMmc->Core, pVScsiReq); 806 } 807 160 808 static DECLCALLBACK(int) vscsiLunMmcInit(PVSCSILUNINT pVScsiLun) 161 809 { … … 164 812 int rc = VINF_SUCCESS; 165 813 166 pVScsiLunMmc->cbSector = 2048; /* Default to 2K sectors. */ 814 ASMAtomicWriteU32((volatile uint32_t *)&pVScsiLunMmc->MediaEventStatus, MMCEVENTSTATUSTYPE_UNCHANGED); 815 pVScsiLunMmc->u32MediaTrackType = MMC_MEDIA_TYPE_UNKNOWN; 816 pVScsiLunMmc->cbSector = 2048; /* Default to 2K sectors. */ 167 817 rc = vscsiLunMediumGetSize(pVScsiLun, &cbDisk); 168 818 if (RT_SUCCESS(rc)) … … 215 865 switch (uCmd) 216 866 { 217 case SCSI_TEST_UNIT_READY: 218 Assert(!pVScsiLunMmc->Core.fReady); /* Only should get here if LUN isn't ready. */ 219 rcReq = vscsiLunReqSenseErrorSet(pVScsiLun, pVScsiReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT, 0x00); 220 break; 221 222 case SCSI_INQUIRY: 223 { 224 SCSIINQUIRYDATA ScsiInquiryReply; 225 226 memset(&ScsiInquiryReply, 0, sizeof(ScsiInquiryReply)); 227 228 ScsiInquiryReply.cbAdditional = 31; 229 ScsiInquiryReply.fRMB = 1; /* Removable. */ 230 ScsiInquiryReply.u5PeripheralDeviceType = SCSI_INQUIRY_DATA_PERIPHERAL_DEVICE_TYPE_CD_DVD; 231 ScsiInquiryReply.u3PeripheralQualifier = SCSI_INQUIRY_DATA_PERIPHERAL_QUALIFIER_CONNECTED; 232 ScsiInquiryReply.u3AnsiVersion = 0x05; /* MMC-?? compliant */ 233 ScsiInquiryReply.fCmdQue = 1; /* Command queuing supported. */ 234 ScsiInquiryReply.fWBus16 = 1; 235 vscsiPadStr(ScsiInquiryReply.achVendorId, "VBOX", 8); 236 vscsiPadStr(ScsiInquiryReply.achProductId, "CD-ROM", 16); 237 vscsiPadStr(ScsiInquiryReply.achProductLevel, "1.0", 4); 238 239 RTSgBufCopyFromBuf(&pVScsiReq->SgBuf, (uint8_t *)&ScsiInquiryReply, sizeof(SCSIINQUIRYDATA)); 240 rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq); 241 break; 242 } 243 case SCSI_READ_CAPACITY: 244 { 245 uint8_t aReply[8]; 246 memset(aReply, 0, sizeof(aReply)); 247 248 /* 249 * If sector size exceeds the maximum value that is 250 * able to be stored in 4 bytes return 0xffffffff in this field 251 */ 252 if (pVScsiLunMmc->cSectors > UINT32_C(0xffffffff)) 253 vscsiH2BEU32(aReply, UINT32_C(0xffffffff)); 254 else 255 vscsiH2BEU32(aReply, pVScsiLunMmc->cSectors - 1); 256 vscsiH2BEU32(&aReply[4], pVScsiLunMmc->cbSector); 257 RTSgBufCopyFromBuf(&pVScsiReq->SgBuf, aReply, sizeof(aReply)); 258 rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq); 259 break; 260 } 261 case SCSI_MODE_SENSE_6: 262 { 263 uint8_t uModePage = pVScsiReq->pbCDB[2] & 0x3f; 264 uint8_t aReply[24]; 265 uint8_t *pu8ReplyPos; 266 bool fValid = false; 267 268 memset(aReply, 0, sizeof(aReply)); 269 aReply[0] = 4; /* Reply length 4. */ 270 aReply[1] = 0; /* Default media type. */ 271 aReply[2] = RT_BIT(4); /* Caching supported. */ 272 aReply[3] = 0; /* Block descriptor length. */ 273 274 pu8ReplyPos = aReply + 4; 275 276 if ((uModePage == 0x08) || (uModePage == 0x3f)) 277 { 278 memset(pu8ReplyPos, 0, 20); 279 *pu8ReplyPos++ = 0x08; /* Page code. */ 280 *pu8ReplyPos++ = 0x12; /* Size of the page. */ 281 *pu8ReplyPos++ = 0x4; /* Write cache enabled. */ 282 fValid = true; 283 } else if (uModePage == 0) { 284 fValid = true; 285 } 286 287 /* Querying unknown pages must fail. */ 288 if (fValid) { 867 case SCSI_TEST_UNIT_READY: 868 Assert(!pVScsiLunMmc->Core.fReady); /* Only should get here if LUN isn't ready. */ 869 rcReq = vscsiLunReqSenseErrorSet(pVScsiLun, pVScsiReq, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT, 0x00); 870 break; 871 872 case SCSI_INQUIRY: 873 { 874 SCSIINQUIRYDATA ScsiInquiryReply; 875 876 memset(&ScsiInquiryReply, 0, sizeof(ScsiInquiryReply)); 877 878 ScsiInquiryReply.cbAdditional = 31; 879 ScsiInquiryReply.fRMB = 1; /* Removable. */ 880 ScsiInquiryReply.u5PeripheralDeviceType = SCSI_INQUIRY_DATA_PERIPHERAL_DEVICE_TYPE_CD_DVD; 881 ScsiInquiryReply.u3PeripheralQualifier = SCSI_INQUIRY_DATA_PERIPHERAL_QUALIFIER_CONNECTED; 882 ScsiInquiryReply.u3AnsiVersion = 0x05; /* MMC-?? compliant */ 883 ScsiInquiryReply.fCmdQue = 1; /* Command queuing supported. */ 884 ScsiInquiryReply.fWBus16 = 1; 885 vscsiPadStr(ScsiInquiryReply.achVendorId, "VBOX", 8); 886 vscsiPadStr(ScsiInquiryReply.achProductId, "CD-ROM", 16); 887 vscsiPadStr(ScsiInquiryReply.achProductLevel, "1.0", 4); 888 889 RTSgBufCopyFromBuf(&pVScsiReq->SgBuf, (uint8_t *)&ScsiInquiryReply, sizeof(SCSIINQUIRYDATA)); 890 rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq); 891 break; 892 } 893 case SCSI_READ_CAPACITY: 894 { 895 uint8_t aReply[8]; 896 memset(aReply, 0, sizeof(aReply)); 897 898 /* 899 * If sector size exceeds the maximum value that is 900 * able to be stored in 4 bytes return 0xffffffff in this field 901 */ 902 if (pVScsiLunMmc->cSectors > UINT32_C(0xffffffff)) 903 vscsiH2BEU32(aReply, UINT32_C(0xffffffff)); 904 else 905 vscsiH2BEU32(aReply, pVScsiLunMmc->cSectors - 1); 906 vscsiH2BEU32(&aReply[4], pVScsiLunMmc->cbSector); 289 907 RTSgBufCopyFromBuf(&pVScsiReq->SgBuf, aReply, sizeof(aReply)); 290 908 rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq); 291 } else { 292 rcReq = vscsiLunReqSenseErrorSet(pVScsiLun, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET, 0x00); 293 } 294 break; 295 } 296 case SCSI_MODE_SELECT_6: 297 { 298 /** @todo implement!! */ 299 rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq); 300 break; 301 } 302 case SCSI_READ_6: 303 { 304 enmTxDir = VSCSIIOREQTXDIR_READ; 305 uLbaStart = ((uint64_t) pVScsiReq->pbCDB[3] 306 | (pVScsiReq->pbCDB[2] << 8) 307 | ((pVScsiReq->pbCDB[1] & 0x1f) << 16)); 308 cSectorTransfer = pVScsiReq->pbCDB[4]; 309 break; 310 } 311 case SCSI_READ_10: 312 { 313 enmTxDir = VSCSIIOREQTXDIR_READ; 314 uLbaStart = vscsiBE2HU32(&pVScsiReq->pbCDB[2]); 315 cSectorTransfer = vscsiBE2HU16(&pVScsiReq->pbCDB[7]); 316 break; 317 } 318 case SCSI_READ_12: 319 { 320 enmTxDir = VSCSIIOREQTXDIR_READ; 321 uLbaStart = vscsiBE2HU32(&pVScsiReq->pbCDB[2]); 322 cSectorTransfer = vscsiBE2HU32(&pVScsiReq->pbCDB[6]); 323 break; 324 } 325 case SCSI_READ_16: 326 { 327 enmTxDir = VSCSIIOREQTXDIR_READ; 328 uLbaStart = vscsiBE2HU64(&pVScsiReq->pbCDB[2]); 329 cSectorTransfer = vscsiBE2HU32(&pVScsiReq->pbCDB[10]); 330 break; 331 } 332 case SCSI_READ_BUFFER: 333 { 334 uint8_t uDataMode = pVScsiReq->pbCDB[1] & 0x1f; 335 336 switch (uDataMode) 337 { 338 case 0x00: 339 case 0x01: 340 case 0x02: 341 case 0x03: 342 case 0x0a: 343 break; 344 case 0x0b: 909 break; 910 } 911 case SCSI_MODE_SENSE_6: 912 { 913 uint8_t uModePage = pVScsiReq->pbCDB[2] & 0x3f; 914 uint8_t aReply[24]; 915 uint8_t *pu8ReplyPos; 916 bool fValid = false; 917 918 memset(aReply, 0, sizeof(aReply)); 919 aReply[0] = 4; /* Reply length 4. */ 920 aReply[1] = 0; /* Default media type. */ 921 aReply[2] = RT_BIT(4); /* Caching supported. */ 922 aReply[3] = 0; /* Block descriptor length. */ 923 924 pu8ReplyPos = aReply + 4; 925 926 if ((uModePage == 0x08) || (uModePage == 0x3f)) 345 927 { 346 uint8_t aReply[4]; 347 348 /* We do not implement an echo buffer. */ 349 memset(aReply, 0, sizeof(aReply)); 350 928 memset(pu8ReplyPos, 0, 20); 929 *pu8ReplyPos++ = 0x08; /* Page code. */ 930 *pu8ReplyPos++ = 0x12; /* Size of the page. */ 931 *pu8ReplyPos++ = 0x4; /* Write cache enabled. */ 932 fValid = true; 933 } else if (uModePage == 0) { 934 fValid = true; 935 } 936 937 /* Querying unknown pages must fail. */ 938 if (fValid) { 351 939 RTSgBufCopyFromBuf(&pVScsiReq->SgBuf, aReply, sizeof(aReply)); 352 940 rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq); 353 break; 941 } else { 942 rcReq = vscsiLunReqSenseErrorSet(pVScsiLun, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET, 0x00); 354 943 } 355 case 0x1a: 356 case 0x1c: 357 break; 358 default: 359 AssertMsgFailed(("Invalid data mode\n")); 360 } 361 break; 362 } 363 case SCSI_VERIFY_10: 364 case SCSI_START_STOP_UNIT: 365 { 366 rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq); 367 break; 368 } 369 case SCSI_LOG_SENSE: 370 { 371 uint8_t uPageCode = pVScsiReq->pbCDB[2] & 0x3f; 372 uint8_t uSubPageCode = pVScsiReq->pbCDB[3]; 373 374 switch (uPageCode) 375 { 376 case 0x00: 944 break; 945 } 946 case SCSI_MODE_SENSE_10: 947 { 948 size_t cbMax = vscsiBE2HU32(&pVScsiReq->pbCDB[7]); 949 rcReq = vscsiLunMmcModeSense10(pVScsiLunMmc, pVScsiReq, cbMax); 950 break; 951 } 952 case SCSI_SEEK_10: 953 { 954 uint32_t uLba = vscsiBE2HU32(&pVScsiReq->pbCDB[2]); 955 if (uLba > pVScsiLunMmc->cSectors) 956 rcReq = vscsiLunReqSenseErrorSet(pVScsiLun, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, 957 SCSI_ASC_LOGICAL_BLOCK_OOR, 0x00); 958 else 959 rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq); 960 break; 961 } 962 case SCSI_MODE_SELECT_6: 963 { 964 /** @todo implement!! */ 965 rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq); 966 break; 967 } 968 case SCSI_READ_6: 969 { 970 enmTxDir = VSCSIIOREQTXDIR_READ; 971 uLbaStart = ((uint64_t) pVScsiReq->pbCDB[3] 972 | (pVScsiReq->pbCDB[2] << 8) 973 | ((pVScsiReq->pbCDB[1] & 0x1f) << 16)); 974 cSectorTransfer = pVScsiReq->pbCDB[4]; 975 break; 976 } 977 case SCSI_READ_10: 978 { 979 enmTxDir = VSCSIIOREQTXDIR_READ; 980 uLbaStart = vscsiBE2HU32(&pVScsiReq->pbCDB[2]); 981 cSectorTransfer = vscsiBE2HU16(&pVScsiReq->pbCDB[7]); 982 break; 983 } 984 case SCSI_READ_12: 985 { 986 enmTxDir = VSCSIIOREQTXDIR_READ; 987 uLbaStart = vscsiBE2HU32(&pVScsiReq->pbCDB[2]); 988 cSectorTransfer = vscsiBE2HU32(&pVScsiReq->pbCDB[6]); 989 break; 990 } 991 case SCSI_READ_16: 992 { 993 enmTxDir = VSCSIIOREQTXDIR_READ; 994 uLbaStart = vscsiBE2HU64(&pVScsiReq->pbCDB[2]); 995 cSectorTransfer = vscsiBE2HU32(&pVScsiReq->pbCDB[10]); 996 break; 997 } 998 case SCSI_READ_BUFFER: 999 { 1000 uint8_t uDataMode = pVScsiReq->pbCDB[1] & 0x1f; 1001 1002 switch (uDataMode) 377 1003 { 378 if (uSubPageCode == 0) 1004 case 0x00: 1005 case 0x01: 1006 case 0x02: 1007 case 0x03: 1008 case 0x0a: 1009 break; 1010 case 0x0b: 379 1011 { 380 1012 uint8_t aReply[4]; 381 382 aReply[0] = 0; 383 aReply[1] = 0; 384 aReply[2] = 0; 385 aReply[3] = 0; 1013 RT_ZERO(aReply); 386 1014 387 1015 RTSgBufCopyFromBuf(&pVScsiReq->SgBuf, aReply, sizeof(aReply)); … … 389 1017 break; 390 1018 } 1019 case 0x1a: 1020 case 0x1c: 1021 break; 1022 default: 1023 AssertMsgFailed(("Invalid data mode\n")); 391 1024 } 392 default: 1025 break; 1026 } 1027 case SCSI_VERIFY_10: 1028 case SCSI_START_STOP_UNIT: 1029 { 1030 /** @todo: Improve START STOP UNIT */ 1031 rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq); 1032 break; 1033 } 1034 case SCSI_LOG_SENSE: 1035 { 1036 uint8_t uPageCode = pVScsiReq->pbCDB[2] & 0x3f; 1037 uint8_t uSubPageCode = pVScsiReq->pbCDB[3]; 1038 1039 switch (uPageCode) 1040 { 1041 case 0x00: 1042 { 1043 if (uSubPageCode == 0) 1044 { 1045 uint8_t aReply[4]; 1046 1047 aReply[0] = 0; 1048 aReply[1] = 0; 1049 aReply[2] = 0; 1050 aReply[3] = 0; 1051 1052 RTSgBufCopyFromBuf(&pVScsiReq->SgBuf, aReply, sizeof(aReply)); 1053 rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq); 1054 break; 1055 } 1056 } 1057 default: 1058 rcReq = vscsiLunReqSenseErrorSet(pVScsiLun, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET, 0x00); 1059 } 1060 break; 1061 } 1062 case SCSI_SERVICE_ACTION_IN_16: 1063 { 1064 switch (pVScsiReq->pbCDB[1] & 0x1f) 1065 { 1066 case SCSI_SVC_ACTION_IN_READ_CAPACITY_16: 1067 { 1068 uint8_t aReply[32]; 1069 1070 memset(aReply, 0, sizeof(aReply)); 1071 vscsiH2BEU64(aReply, pVScsiLunMmc->cSectors - 1); 1072 vscsiH2BEU32(&aReply[8], pVScsiLunMmc->cbSector); 1073 /* Leave the rest 0 */ 1074 RTSgBufCopyFromBuf(&pVScsiReq->SgBuf, aReply, sizeof(aReply)); 1075 rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq); 1076 break; 1077 } 1078 default: 1079 rcReq = vscsiLunReqSenseErrorSet(pVScsiLun, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, 1080 SCSI_ASC_INV_FIELD_IN_CMD_PACKET, 0x00); /* Don't know if this is correct */ 1081 } 1082 break; 1083 } 1084 case SCSI_PREVENT_ALLOW_MEDIUM_REMOVAL: 1085 { 1086 pVScsiLunMmc->fLocked = pVScsiReq->pbCDB[4] & 1; 1087 vscsiLunMediumSetLock(pVScsiLun, pVScsiLunMmc->fLocked); 1088 rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq); 1089 break; 1090 } 1091 case SCSI_READ_TOC_PMA_ATIP: 1092 { 1093 uint8_t format; 1094 uint16_t cbMax; 1095 bool fMSF; 1096 1097 format = pVScsiReq->pbCDB[2] & 0x0f; 1098 cbMax = vscsiBE2HU16(&pVScsiReq->pbCDB[7]); 1099 fMSF = (pVScsiReq->pbCDB[1] >> 1) & 1; 1100 switch (format) 1101 { 1102 case 0x00: 1103 rcReq = mmcReadTOCNormal(pVScsiLun, pVScsiReq, cbMax, fMSF); 1104 break; 1105 case 0x01: 1106 rcReq = mmcReadTOCMulti(pVScsiLun, pVScsiReq, cbMax, fMSF); 1107 break; 1108 case 0x02: 1109 rcReq = mmcReadTOCRaw(pVScsiLun, pVScsiReq, cbMax, fMSF); 1110 break; 1111 default: 1112 rcReq = vscsiLunReqSenseErrorSet(pVScsiLun, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET, 0x00); 1113 } 1114 break; 1115 } 1116 case SCSI_GET_EVENT_STATUS_NOTIFICATION: 1117 { 1118 /* Only supporting polled mode at the moment. */ 1119 if (pVScsiReq->pbCDB[1] & 0x1) 1120 { 1121 size_t cbMax = vscsiBE2HU16(&pVScsiReq->pbCDB[7]); 1122 rcReq = vscsiLunMmcGetEventStatusNotification(pVScsiLunMmc, pVScsiReq, cbMax); 1123 } 1124 else 393 1125 rcReq = vscsiLunReqSenseErrorSet(pVScsiLun, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET, 0x00); 394 } 395 break; 396 } 397 case SCSI_SERVICE_ACTION_IN_16: 398 { 399 switch (pVScsiReq->pbCDB[1] & 0x1f) 400 { 401 case SCSI_SVC_ACTION_IN_READ_CAPACITY_16: 1126 break; 1127 } 1128 case SCSI_MECHANISM_STATUS: 1129 { 1130 size_t cbMax = vscsiBE2HU16(&pVScsiReq->pbCDB[8]); 1131 uint8_t aReply[8]; 1132 1133 vscsiH2BEU16(&aReply[0], 0); 1134 /* no current LBA */ 1135 aReply[2] = 0; 1136 aReply[3] = 0; 1137 aReply[4] = 0; 1138 aReply[5] = 1; 1139 vscsiH2BEU16(&aReply[6], 0); 1140 RTSgBufCopyFromBuf(&pVScsiReq->SgBuf, aReply, RT_MIN(sizeof(aReply), cbMax)); 1141 rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq); 1142 break; 1143 } 1144 case SCSI_READ_DISC_INFORMATION: 1145 { 1146 uint8_t aReply[34]; 1147 size_t cbMax = vscsiBE2HU16(&pVScsiReq->pbCDB[7]); 1148 1149 memset(aReply, '\0', sizeof(aReply)); 1150 vscsiH2BEU16(&aReply[0], 32); 1151 aReply[2] = (0 << 4) | (3 << 2) | (2 << 0); /* not erasable, complete session, complete disc */ 1152 aReply[3] = 1; /* number of first track */ 1153 aReply[4] = 1; /* number of sessions (LSB) */ 1154 aReply[5] = 1; /* first track number in last session (LSB) */ 1155 aReply[6] = 1; /* last track number in last session (LSB) */ 1156 aReply[7] = (0 << 7) | (0 << 6) | (1 << 5) | (0 << 2) | (0 << 0); /* disc id not valid, disc bar code not valid, unrestricted use, not dirty, not RW medium */ 1157 aReply[8] = 0; /* disc type = CD-ROM */ 1158 aReply[9] = 0; /* number of sessions (MSB) */ 1159 aReply[10] = 0; /* number of sessions (MSB) */ 1160 aReply[11] = 0; /* number of sessions (MSB) */ 1161 vscsiH2BEU32(&aReply[16], 0x00ffffff); /* last session lead-in start time is not available */ 1162 vscsiH2BEU32(&aReply[20], 0x00ffffff); /* last possible start time for lead-out is not available */ 1163 RTSgBufCopyFromBuf(&pVScsiReq->SgBuf, aReply, RT_MIN(sizeof(aReply), cbMax)); 1164 rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq); 1165 break; 1166 } 1167 case SCSI_READ_TRACK_INFORMATION: 1168 { 1169 /* Accept address/number type of 1 only, and only track 1 exists. */ 1170 if ((pVScsiReq->pbCDB[1] & 0x03) != 1 || vscsiBE2HU32(&pVScsiReq->pbCDB[2]) != 1) 1171 rcReq = vscsiLunReqSenseErrorSet(pVScsiLun, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, 1172 SCSI_ASC_INV_FIELD_IN_CMD_PACKET, 0x00); 1173 else 402 1174 { 403 uint8_t aReply[32]; 404 405 memset(aReply, 0, sizeof(aReply)); 406 vscsiH2BEU64(aReply, pVScsiLunMmc->cSectors - 1); 407 vscsiH2BEU32(&aReply[8], pVScsiLunMmc->cbSector); 408 /* Leave the rest 0 */ 409 RTSgBufCopyFromBuf(&pVScsiReq->SgBuf, aReply, sizeof(aReply)); 1175 size_t cbMax = vscsiBE2HU16(&pVScsiReq->pbCDB[7]); 1176 uint8_t aReply[36]; 1177 RT_ZERO(aReply); 1178 1179 vscsiH2BEU16(&aReply[0], 34); 1180 aReply[2] = 1; /* track number (LSB) */ 1181 aReply[3] = 1; /* session number (LSB) */ 1182 aReply[5] = (0 << 5) | (0 << 4) | (4 << 0); /* not damaged, primary copy, data track */ 1183 aReply[6] = (0 << 7) | (0 << 6) | (0 << 5) | (0 << 6) | (1 << 0); /* not reserved track, not blank, not packet writing, not fixed packet, data mode 1 */ 1184 aReply[7] = (0 << 1) | (0 << 0); /* last recorded address not valid, next recordable address not valid */ 1185 vscsiH2BEU32(&aReply[8], 0); /* track start address is 0 */ 1186 vscsiH2BEU32(&aReply[24], pVScsiLunMmc->cSectors); /* track size */ 1187 aReply[32] = 0; /* track number (MSB) */ 1188 aReply[33] = 0; /* session number (MSB) */ 1189 1190 RTSgBufCopyFromBuf(&pVScsiReq->SgBuf, aReply, RT_MIN(sizeof(aReply), cbMax)); 410 1191 rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq); 411 break;412 1192 } 413 default: 414 rcReq = vscsiLunReqSenseErrorSet(pVScsiLun, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET, 0x00); /* Don't know if this is correct */ 415 } 416 break; 417 } 418 case SCSI_PREVENT_ALLOW_MEDIUM_REMOVAL: 419 { 420 pVScsiLunMmc->fLocked = pVScsiReq->pbCDB[4] & 1; 421 vscsiLunMediumSetLock(pVScsiLun, pVScsiLunMmc->fLocked); 422 rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq); 423 break; 424 } 425 case SCSI_READ_TOC_PMA_ATIP: 426 { 427 uint8_t format; 428 uint16_t cbMax; 429 bool fMSF; 430 431 format = pVScsiReq->pbCDB[2] & 0x0f; 432 cbMax = vscsiBE2HU16(&pVScsiReq->pbCDB[7]); 433 fMSF = (pVScsiReq->pbCDB[1] >> 1) & 1; 434 switch (format) 435 { 436 case 0x00: 437 mmcReadTOCNormal(pVScsiLun, pVScsiReq, cbMax, fMSF); 438 break; 439 case 0x01: 440 mmcReadTOCMulti(pVScsiLun, pVScsiReq, cbMax, fMSF); 441 break; 442 default: 443 rcReq = vscsiLunReqSenseErrorSet(pVScsiLun, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET, 0x00); 444 } 445 break; 446 } 447 448 default: 449 //AssertMsgFailed(("Command %#x [%s] not implemented\n", pVScsiReq->pbCDB[0], SCSICmdText(pVScsiReq->pbCDB[0]))); 450 rcReq = vscsiLunReqSenseErrorSet(pVScsiLun, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_ILLEGAL_OPCODE, 0x00); 1193 break; 1194 } 1195 case SCSI_GET_CONFIGURATION: 1196 { 1197 size_t cbMax = vscsiBE2HU16(&pVScsiReq->pbCDB[7]); 1198 rcReq = vscsiLunMmcGetConfiguration(pVScsiLunMmc, pVScsiReq, cbMax); 1199 break; 1200 } 1201 case SCSI_READ_DVD_STRUCTURE: 1202 { 1203 size_t cbMax = vscsiBE2HU16(&pVScsiReq->pbCDB[8]); 1204 rcReq = vscsiLunMmcReadDvdStructure(pVScsiLunMmc, pVScsiReq, cbMax); 1205 break; 1206 } 1207 default: 1208 //AssertMsgFailed(("Command %#x [%s] not implemented\n", pVScsiReq->pbCDB[0], SCSICmdText(pVScsiReq->pbCDB[0]))); 1209 rcReq = vscsiLunReqSenseErrorSet(pVScsiLun, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_ILLEGAL_OPCODE, 0x00); 451 1210 } 452 1211 } … … 482 1241 } 483 1242 1243 /** @interface_method_impl{VSCSILUNDESC,pfnVScsiLunMediumInserted} */ 1244 static DECLCALLBACK(int) vscsiLunMmcMediumInserted(PVSCSILUNINT pVScsiLun) 1245 { 1246 PVSCSILUNMMC pVScsiLunMmc = (PVSCSILUNMMC)pVScsiLun; 1247 1248 uint32_t OldStatus, NewStatus; 1249 do 1250 { 1251 OldStatus = ASMAtomicReadU32((volatile uint32_t *)&pVScsiLunMmc->MediaEventStatus); 1252 switch (OldStatus) 1253 { 1254 case MMCEVENTSTATUSTYPE_MEDIA_CHANGED: 1255 case MMCEVENTSTATUSTYPE_MEDIA_REMOVED: 1256 /* no change, we will send "medium removed" + "medium inserted" */ 1257 NewStatus = MMCEVENTSTATUSTYPE_MEDIA_CHANGED; 1258 break; 1259 default: 1260 NewStatus = MMCEVENTSTATUSTYPE_MEDIA_NEW; 1261 break; 1262 } 1263 } while (!ASMAtomicCmpXchgU32((volatile uint32_t *)&pVScsiLunMmc->MediaEventStatus, 1264 NewStatus, OldStatus)); 1265 1266 ASMAtomicXchgU32(&pVScsiLunMmc->u32MediaTrackType, MMC_MEDIA_TYPE_UNKNOWN); 1267 return VINF_SUCCESS; 1268 } 1269 1270 /** @interface_method_impl{VSCSILUNDESC,pfnVScsiLunMediumRemoved} */ 1271 static DECLCALLBACK(int) vscsiLunMmcMediumRemoved(PVSCSILUNINT pVScsiLun) 1272 { 1273 PVSCSILUNMMC pVScsiLunMmc = (PVSCSILUNMMC)pVScsiLun; 1274 1275 ASMAtomicWriteU32((volatile uint32_t *)&pVScsiLunMmc->MediaEventStatus, MMCEVENTSTATUSTYPE_MEDIA_REMOVED); 1276 ASMAtomicXchgU32(&pVScsiLunMmc->u32MediaTrackType, MMC_MEDIA_TYPE_NO_DISC); 1277 return VINF_SUCCESS; 1278 } 1279 1280 484 1281 VSCSILUNDESC g_VScsiLunTypeMmc = 485 1282 { … … 495 1292 vscsiLunMmcDestroy, 496 1293 /** pfnVScsiLunReqProcess */ 497 vscsiLunMmcReqProcess 1294 vscsiLunMmcReqProcess, 1295 /** pfnVScsiLunMediumInserted */ 1296 vscsiLunMmcMediumInserted, 1297 /** pfnVScsiLunMediumRemoved */ 1298 vscsiLunMmcMediumRemoved 498 1299 }; -
trunk/src/VBox/Devices/Storage/VSCSI/VSCSILunSbc.cpp
r63562 r64064 593 593 vscsiLunSbcDestroy, 594 594 /** pfnVScsiLunReqProcess */ 595 vscsiLunSbcReqProcess 595 vscsiLunSbcReqProcess, 596 /** pfnVScsiLunMediumInserted */ 597 NULL, 598 /** pfnVScsiLunMediumRemoved */ 599 NULL 596 600 }; 597 601
Note:
See TracChangeset
for help on using the changeset viewer.