Changeset 66198 in vbox
- Timestamp:
- Mar 22, 2017 2:23:57 PM (8 years ago)
- svn:sync-xref-src-repo-rev:
- 114113
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Storage/DevATA.cpp
r66057 r66198 1840 1840 int rc = VINF_SUCCESS; 1841 1841 uint32_t cbTransfer, cSectors; 1842 uint64_t cbBlockRegion = 0; 1842 1843 1843 1844 Assert(s->uTxDir == PDMMEDIATXDIR_FROM_DEVICE); … … 1849 1850 ataR3LockLeave(pCtl); 1850 1851 1851 STAM_PROFILE_ADV_START(&s->StatReads, r); 1852 s->Led.Asserted.s.fReading = s->Led.Actual.s.fReading = 1; 1853 switch (s->cbATAPISector) 1854 { 1855 case 2048: 1856 rc = s->pDrvMedia->pfnRead(s->pDrvMedia, (uint64_t)s->iATAPILBA * s->cbATAPISector, s->CTX_SUFF(pbIOBuffer), s->cbATAPISector * cSectors); 1857 break; 1858 case 2352: 1859 { 1860 uint8_t *pbBuf = s->CTX_SUFF(pbIOBuffer); 1861 1862 for (uint32_t i = s->iATAPILBA; i < s->iATAPILBA + cSectors; i++) 1852 rc = s->pDrvMedia->pfnQueryRegionPropertiesForLba(s->pDrvMedia, s->iATAPILBA, NULL, NULL, 1853 &cbBlockRegion, NULL); 1854 if (RT_SUCCESS(rc)) 1855 { 1856 STAM_PROFILE_ADV_START(&s->StatReads, r); 1857 s->Led.Asserted.s.fReading = s->Led.Actual.s.fReading = 1; 1858 1859 /* If the region block size and requested sector matches we can just pass the request through. */ 1860 if (cbBlockRegion == s->cbATAPISector) 1861 rc = s->pDrvMedia->pfnRead(s->pDrvMedia, (uint64_t)s->iATAPILBA * s->cbATAPISector, 1862 s->CTX_SUFF(pbIOBuffer), s->cbATAPISector * cSectors); 1863 else 1864 { 1865 if (cbBlockRegion == 2048 && s->cbATAPISector == 2352) 1863 1866 { 1864 /* Sync bytes, see 4.2.3.8 CD Main Channel Block Formats */ 1865 *pbBuf++ = 0x00; 1866 memset(pbBuf, 0xff, 10); 1867 pbBuf += 10; 1868 *pbBuf++ = 0x00; 1869 /* MSF */ 1870 scsiLBA2MSF(pbBuf, i); 1871 pbBuf += 3; 1872 *pbBuf++ = 0x01; /* mode 1 data */ 1873 /* data */ 1874 rc = s->pDrvMedia->pfnRead(s->pDrvMedia, (uint64_t)i * 2048, pbBuf, 2048); 1875 if (RT_FAILURE(rc)) 1876 break; 1877 pbBuf += 2048; 1878 /** 1879 * @todo: maybe compute ECC and parity, layout is: 1880 * 2072 4 EDC 1881 * 2076 172 P parity symbols 1882 * 2248 104 Q parity symbols 1883 */ 1884 memset(pbBuf, 0, 280); 1885 pbBuf += 280; 1867 /* Generate the sync bytes. */ 1868 uint8_t *pbBuf = s->CTX_SUFF(pbIOBuffer); 1869 1870 for (uint32_t i = s->iATAPILBA; i < s->iATAPILBA + cSectors; i++) 1871 { 1872 /* Sync bytes, see 4.2.3.8 CD Main Channel Block Formats */ 1873 *pbBuf++ = 0x00; 1874 memset(pbBuf, 0xff, 10); 1875 pbBuf += 10; 1876 *pbBuf++ = 0x00; 1877 /* MSF */ 1878 scsiLBA2MSF(pbBuf, i); 1879 pbBuf += 3; 1880 *pbBuf++ = 0x01; /* mode 1 data */ 1881 /* data */ 1882 rc = s->pDrvMedia->pfnRead(s->pDrvMedia, (uint64_t)i * 2048, pbBuf, 2048); 1883 if (RT_FAILURE(rc)) 1884 break; 1885 pbBuf += 2048; 1886 /** 1887 * @todo: maybe compute ECC and parity, layout is: 1888 * 2072 4 EDC 1889 * 2076 172 P parity symbols 1890 * 2248 104 Q parity symbols 1891 */ 1892 memset(pbBuf, 0, 280); 1893 pbBuf += 280; 1894 } 1886 1895 } 1887 break; 1888 } 1889 default: 1890 break; 1891 } 1892 s->Led.Actual.s.fReading = 0; 1893 STAM_PROFILE_ADV_STOP(&s->StatReads, r); 1896 else if (cbBlockRegion == 2352 && s->cbATAPISector == 2048) 1897 { 1898 /* Read only the user data portion. */ 1899 uint8_t *pbBuf = s->CTX_SUFF(pbIOBuffer); 1900 1901 for (uint32_t i = s->iATAPILBA; i < s->iATAPILBA + cSectors; i++) 1902 { 1903 uint8_t abTmp[2352]; 1904 rc = s->pDrvMedia->pfnRead(s->pDrvMedia, (uint64_t)i * 2352, &abTmp[0], 2352); 1905 if (RT_FAILURE(rc)) 1906 break; 1907 1908 memcpy(pbBuf, &abTmp[16], 2048); 1909 pbBuf += 2048; 1910 } 1911 } 1912 } 1913 s->Led.Actual.s.fReading = 0; 1914 STAM_PROFILE_ADV_STOP(&s->StatReads, r); 1915 } 1894 1916 1895 1917 ataR3LockEnter(pCtl); … … 2181 2203 2182 2204 if (cbTransfer) 2183 Log3(("ATAPI PT data read (%d): %.*Rhxs\n", cbTransfer, cbTransfer, s->CTX_SUFF(pbIOBuffer)));2205 Log3(("ATAPI PT data read (%d):\n%.*Rhxd\n", cbTransfer, cbTransfer, s->CTX_SUFF(pbIOBuffer))); 2184 2206 } 2185 2207 … … 2415 2437 pbBuf[4] = 1; /* number of sessions (LSB) */ 2416 2438 pbBuf[5] = 1; /* first track number in last session (LSB) */ 2417 pbBuf[6] = 1; /* last track number in last session (LSB) */2439 pbBuf[6] = (uint8_t)s->pDrvMedia->pfnGetRegionCount(s->pDrvMedia); /* last track number in last session (LSB) */ 2418 2440 pbBuf[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 */ 2419 2441 pbBuf[8] = 0; /* disc type = CD-ROM */ … … 2421 2443 pbBuf[10] = 0; /* number of sessions (MSB) */ 2422 2444 pbBuf[11] = 0; /* number of sessions (MSB) */ 2423 scsiH2BE_U32(pbBuf + 16, 0x 00ffffff); /* last session lead-in start time is not available */2424 scsiH2BE_U32(pbBuf + 20, 0x 00ffffff); /* last possible start time for lead-out is not available */2445 scsiH2BE_U32(pbBuf + 16, 0xffffffff); /* last session lead-in start time is not available */ 2446 scsiH2BE_U32(pbBuf + 20, 0xffffffff); /* last possible start time for lead-out is not available */ 2425 2447 s->iSourceSink = ATAFN_SS_NULL; 2426 2448 atapiR3CmdOK(s); … … 2432 2454 { 2433 2455 uint8_t *pbBuf = s->CTX_SUFF(pbIOBuffer); 2456 uint32_t u32LogAddr = scsiBE2H_U32(&s->aATAPICmd[2]); 2457 uint8_t u8LogAddrType = s->aATAPICmd[1] & 0x03; 2458 2459 int rc = VINF_SUCCESS; 2460 uint64_t u64LbaStart = 0; 2461 uint32_t uRegion = 0; 2462 uint64_t cBlocks = 0; 2463 uint64_t cbBlock = 0; 2464 uint8_t u8DataMode = 0xf; /* Unknown data mode. */ 2465 uint8_t u8TrackMode = 0; 2466 VDREGIONDATAFORM enmDataForm = VDREGIONDATAFORM_INVALID; 2434 2467 2435 2468 Assert(s->uTxDir == PDMMEDIATXDIR_FROM_DEVICE); 2436 2469 Assert(s->cbElementaryTransfer <= 36); 2437 /* Accept address/number type of 1 only, and only track 1 exists. */ 2438 if ((s->aATAPICmd[1] & 0x03) != 1 || scsiBE2H_U32(&s->aATAPICmd[2]) != 1) 2470 2471 switch (u8LogAddrType) 2472 { 2473 case 0x00: 2474 rc = s->pDrvMedia->pfnQueryRegionPropertiesForLba(s->pDrvMedia, u32LogAddr, &uRegion, 2475 NULL, NULL, NULL); 2476 if (RT_SUCCESS(rc)) 2477 rc = s->pDrvMedia->pfnQueryRegionProperties(s->pDrvMedia, uRegion, &u64LbaStart, 2478 &cBlocks, &cbBlock, &enmDataForm); 2479 break; 2480 case 0x01: 2481 { 2482 if (u32LogAddr >= 1) 2483 { 2484 uRegion = u32LogAddr - 1; 2485 rc = s->pDrvMedia->pfnQueryRegionProperties(s->pDrvMedia, uRegion, &u64LbaStart, 2486 &cBlocks, &cbBlock, &enmDataForm); 2487 } 2488 else 2489 rc = VERR_NOT_FOUND; /** @todo: Return lead-in information. */ 2490 break; 2491 } 2492 case 0x02: 2493 default: 2494 atapiR3CmdErrorSimple(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET); 2495 return false; 2496 } 2497 2498 if (RT_FAILURE(rc)) 2439 2499 { 2440 2500 atapiR3CmdErrorSimple(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET); 2441 2501 return false; 2442 2502 } 2503 2504 switch (enmDataForm) 2505 { 2506 case VDREGIONDATAFORM_MODE1_2048: 2507 case VDREGIONDATAFORM_MODE1_2352: 2508 case VDREGIONDATAFORM_MODE1_0: 2509 u8DataMode = 1; 2510 break; 2511 case VDREGIONDATAFORM_XA_2336: 2512 case VDREGIONDATAFORM_XA_2352: 2513 case VDREGIONDATAFORM_XA_0: 2514 case VDREGIONDATAFORM_MODE2_2336: 2515 case VDREGIONDATAFORM_MODE2_2352: 2516 case VDREGIONDATAFORM_MODE2_0: 2517 u8DataMode = 2; 2518 break; 2519 default: 2520 u8DataMode = 0xf; 2521 } 2522 2523 if (enmDataForm == VDREGIONDATAFORM_CDDA) 2524 u8TrackMode = 0x0; 2525 else 2526 u8TrackMode = 0x4; 2527 2443 2528 memset(pbBuf, '\0', 36); 2444 2529 scsiH2BE_U16(pbBuf, 34); 2445 pbBuf[2] = 1;/* track number (LSB) */2446 pbBuf[3] = 1; /* session number (LSB) */2447 pbBuf[5] = (0 << 5) | (0 << 4) | (4 << 0);/* not damaged, primary copy, data track */2448 pbBuf[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*/2449 pbBuf[7] = (0 << 1) | (0 << 0); /* last recorded address not valid, next recordable address not valid */2450 scsiH2BE_U32(pbBuf + 8, 0);/* track start address is 0 */2451 scsiH2BE_U32(pbBuf + 24, s->cTotalSectors);/* track size */2452 pbBuf[32] = 0; /* track number (MSB) */2453 pbBuf[33] = 0; /* session number (MSB) */2530 pbBuf[2] = uRegion + 1; /* track number (LSB) */ 2531 pbBuf[3] = 1; /* session number (LSB) */ 2532 pbBuf[5] = (0 << 5) | (0 << 4) | u8TrackMode; /* not damaged, primary copy, data track */ 2533 pbBuf[6] = (0 << 7) | (0 << 6) | (0 << 5) | (0 << 6) | u8DataMode; /* not reserved track, not blank, not packet writing, not fixed packet */ 2534 pbBuf[7] = (0 << 1) | (0 << 0); /* last recorded address not valid, next recordable address not valid */ 2535 scsiH2BE_U32(pbBuf + 8, (uint32_t)u64LbaStart); /* track start address is 0 */ 2536 scsiH2BE_U32(pbBuf + 24, (uint32_t)cBlocks); /* track size */ 2537 pbBuf[32] = 0; /* track number (MSB) */ 2538 pbBuf[33] = 0; /* session number (MSB) */ 2454 2539 s->iSourceSink = ATAFN_SS_NULL; 2455 2540 atapiR3CmdOK(s); … … 2476 2561 } 2477 2562 2478 static uint32_tatapiR3GetConfigurationFillFeatureCore(ATADevState *s, uint8_t *pbBuf, size_t cbBuf)2563 static DECLCALLBACK(uint32_t) atapiR3GetConfigurationFillFeatureCore(ATADevState *s, uint8_t *pbBuf, size_t cbBuf) 2479 2564 { 2480 2565 RT_NOREF1(s); … … 2492 2577 } 2493 2578 2494 static uint32_tatapiR3GetConfigurationFillFeatureMorphing(ATADevState *s, uint8_t *pbBuf, size_t cbBuf)2579 static DECLCALLBACK(uint32_t) atapiR3GetConfigurationFillFeatureMorphing(ATADevState *s, uint8_t *pbBuf, size_t cbBuf) 2495 2580 { 2496 2581 RT_NOREF1(s); … … 2507 2592 } 2508 2593 2509 static uint32_tatapiR3GetConfigurationFillFeatureRemovableMedium(ATADevState *s, uint8_t *pbBuf, size_t cbBuf)2594 static DECLCALLBACK(uint32_t) atapiR3GetConfigurationFillFeatureRemovableMedium(ATADevState *s, uint8_t *pbBuf, size_t cbBuf) 2510 2595 { 2511 2596 RT_NOREF1(s); … … 2523 2608 } 2524 2609 2525 static uint32_tatapiR3GetConfigurationFillFeatureRandomReadable (ATADevState *s, uint8_t *pbBuf, size_t cbBuf)2610 static DECLCALLBACK(uint32_t) atapiR3GetConfigurationFillFeatureRandomReadable (ATADevState *s, uint8_t *pbBuf, size_t cbBuf) 2526 2611 { 2527 2612 RT_NOREF1(s); … … 2540 2625 } 2541 2626 2542 static uint32_tatapiR3GetConfigurationFillFeatureCDRead(ATADevState *s, uint8_t *pbBuf, size_t cbBuf)2627 static DECLCALLBACK(uint32_t) atapiR3GetConfigurationFillFeatureCDRead(ATADevState *s, uint8_t *pbBuf, size_t cbBuf) 2543 2628 { 2544 2629 RT_NOREF1(s); … … 2555 2640 } 2556 2641 2557 static uint32_tatapiR3GetConfigurationFillFeaturePowerManagement(ATADevState *s, uint8_t *pbBuf, size_t cbBuf)2642 static DECLCALLBACK(uint32_t) atapiR3GetConfigurationFillFeaturePowerManagement(ATADevState *s, uint8_t *pbBuf, size_t cbBuf) 2558 2643 { 2559 2644 RT_NOREF1(s); … … 2568 2653 } 2569 2654 2570 static uint32_tatapiR3GetConfigurationFillFeatureTimeout(ATADevState *s, uint8_t *pbBuf, size_t cbBuf)2655 static DECLCALLBACK(uint32_t) atapiR3GetConfigurationFillFeatureTimeout(ATADevState *s, uint8_t *pbBuf, size_t cbBuf) 2571 2656 { 2572 2657 RT_NOREF1(s); … … 2582 2667 } 2583 2668 2669 /** 2670 * Callback to fill in the correct data for a feature. 2671 * 2672 * @returns Number of bytes written into the buffer. 2673 * @param s The ATA device state. 2674 * @param pbBuf The buffer to fill the data with. 2675 * @param cbBuf Size of the buffer. 2676 */ 2677 typedef DECLCALLBACK(uint32_t) FNATAPIR3FEATUREFILL(ATADevState *s, uint8_t *pbBuf, size_t cbBuf); 2678 /** Pointer to a feature fill callback. */ 2679 typedef FNATAPIR3FEATUREFILL *PFNATAPIR3FEATUREFILL; 2680 2681 /** 2682 * ATAPI feature descriptor. 2683 */ 2684 typedef struct ATAPIR3FEATDESC 2685 { 2686 /** The feature number. */ 2687 uint16_t u16Feat; 2688 /** The callback to fill in the correct data. */ 2689 PFNATAPIR3FEATUREFILL pfnFeatureFill; 2690 } ATAPIR3FEATDESC; 2691 2692 /** 2693 * Array of known ATAPI feature descriptors. 2694 */ 2695 static const ATAPIR3FEATDESC s_aAtapiR3Features[] = 2696 { 2697 { 0x0000, atapiR3GetConfigurationFillFeatureListProfiles}, 2698 { 0x0001, atapiR3GetConfigurationFillFeatureCore}, 2699 { 0x0002, atapiR3GetConfigurationFillFeatureMorphing}, 2700 { 0x0003, atapiR3GetConfigurationFillFeatureRemovableMedium}, 2701 { 0x0010, atapiR3GetConfigurationFillFeatureRandomReadable}, 2702 { 0x001e, atapiR3GetConfigurationFillFeatureCDRead}, 2703 { 0x0100, atapiR3GetConfigurationFillFeaturePowerManagement}, 2704 { 0x0105, atapiR3GetConfigurationFillFeatureTimeout} 2705 }; 2706 2584 2707 static bool atapiR3GetConfigurationSS(ATADevState *s) 2585 2708 { … … 2588 2711 uint32_t cbCopied = 0; 2589 2712 uint16_t u16Sfn = scsiBE2H_U16(&s->aATAPICmd[2]); 2713 uint8_t u8Rt = s->aATAPICmd[1] & 0x03; 2590 2714 2591 2715 Assert(s->uTxDir == PDMMEDIATXDIR_FROM_DEVICE); 2592 2716 Assert(s->cbElementaryTransfer <= 80); 2593 /* Accept valid request types only , and only starting feature 0. */2594 if ( (s->aATAPICmd[1] & 0x03) == 3 || u16Sfn != 0)2717 /* Accept valid request types only. */ 2718 if (u8Rt == 3) 2595 2719 { 2596 2720 atapiR3CmdErrorSimple(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET); … … 2607 2731 pbBuf += 8; 2608 2732 2609 cbCopied = atapiR3GetConfigurationFillFeatureListProfiles(s, pbBuf, cbBuf); 2610 cbBuf -= cbCopied; 2611 pbBuf += cbCopied; 2612 2613 cbCopied = atapiR3GetConfigurationFillFeatureCore(s, pbBuf, cbBuf); 2614 cbBuf -= cbCopied; 2615 pbBuf += cbCopied; 2616 2617 cbCopied = atapiR3GetConfigurationFillFeatureMorphing(s, pbBuf, cbBuf); 2618 cbBuf -= cbCopied; 2619 pbBuf += cbCopied; 2620 2621 cbCopied = atapiR3GetConfigurationFillFeatureRemovableMedium(s, pbBuf, cbBuf); 2622 cbBuf -= cbCopied; 2623 pbBuf += cbCopied; 2624 2625 cbCopied = atapiR3GetConfigurationFillFeatureRandomReadable (s, pbBuf, cbBuf); 2626 cbBuf -= cbCopied; 2627 pbBuf += cbCopied; 2628 2629 cbCopied = atapiR3GetConfigurationFillFeatureCDRead(s, pbBuf, cbBuf); 2630 cbBuf -= cbCopied; 2631 pbBuf += cbCopied; 2632 2633 cbCopied = atapiR3GetConfigurationFillFeaturePowerManagement(s, pbBuf, cbBuf); 2634 cbBuf -= cbCopied; 2635 pbBuf += cbCopied; 2636 2637 cbCopied = atapiR3GetConfigurationFillFeatureTimeout(s, pbBuf, cbBuf); 2638 cbBuf -= cbCopied; 2639 pbBuf += cbCopied; 2733 if (u8Rt == 0x2) 2734 { 2735 for (uint32_t i = 0; i < RT_ELEMENTS(s_aAtapiR3Features); i++) 2736 { 2737 if (s_aAtapiR3Features[i].u16Feat == u16Sfn) 2738 { 2739 cbCopied = s_aAtapiR3Features[i].pfnFeatureFill(s, pbBuf, cbBuf); 2740 cbBuf -= cbCopied; 2741 pbBuf += cbCopied; 2742 break; 2743 } 2744 } 2745 } 2746 else 2747 { 2748 for (uint32_t i = 0; i < RT_ELEMENTS(s_aAtapiR3Features); i++) 2749 { 2750 if (s_aAtapiR3Features[i].u16Feat > u16Sfn) 2751 { 2752 cbCopied = s_aAtapiR3Features[i].pfnFeatureFill(s, pbBuf, cbBuf); 2753 cbBuf -= cbCopied; 2754 pbBuf += cbCopied; 2755 } 2756 } 2757 } 2640 2758 2641 2759 /* Set data length now - the field is not included in the final length. */ … … 2865 2983 bool fMSF; 2866 2984 uint32_t cbSize; 2985 uint32_t cTracks = s->pDrvMedia->pfnGetRegionCount(s->pDrvMedia); 2867 2986 2868 2987 Assert(s->uTxDir == PDMMEDIATXDIR_FROM_DEVICE); 2869 2988 fMSF = (s->aATAPICmd[1] >> 1) & 1; 2870 2989 iStartTrack = s->aATAPICmd[6]; 2871 if (iStartTrack > 1 && iStartTrack != 0xaa) 2990 if (iStartTrack == 0) 2991 iStartTrack = 1; 2992 2993 if (iStartTrack > cTracks && iStartTrack != 0xaa) 2872 2994 { 2873 2995 atapiR3CmdErrorSimple(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET); … … 2875 2997 } 2876 2998 q = pbBuf + 2; 2877 *q++ = 1; /* first session */ 2878 *q++ = 1; /* last session */ 2879 if (iStartTrack <= 1) 2880 { 2881 *q++ = 0; /* reserved */ 2882 *q++ = 0x14; /* ADR, control */ 2883 *q++ = 1; /* track number */ 2884 *q++ = 0; /* reserved */ 2999 *q++ = iStartTrack; /* first track number */ 3000 *q++ = cTracks; /* last track number */ 3001 for (uint32_t iTrack = iStartTrack; iTrack <= cTracks; iTrack++) 3002 { 3003 uint64_t uLbaStart = 0; 3004 VDREGIONDATAFORM enmDataForm = VDREGIONDATAFORM_MODE1_2048; 3005 3006 int rc = s->pDrvMedia->pfnQueryRegionProperties(s->pDrvMedia, iTrack - 1, &uLbaStart, 3007 NULL, NULL, &enmDataForm); 3008 AssertRC(rc); 3009 3010 *q++ = 0; /* reserved */ 3011 3012 if (enmDataForm == VDREGIONDATAFORM_CDDA) 3013 *q++ = 0x10; /* ADR, control */ 3014 else 3015 *q++ = 0x14; /* ADR, control */ 3016 3017 *q++ = (uint8_t)iTrack; /* track number */ 3018 *q++ = 0; /* reserved */ 2885 3019 if (fMSF) 2886 3020 { 2887 3021 *q++ = 0; /* reserved */ 2888 scsiLBA2MSF(q, 0);3022 scsiLBA2MSF(q, (uint32_t)uLbaStart); 2889 3023 q += 3; 2890 3024 } … … 2892 3026 { 2893 3027 /* sector 0 */ 2894 scsiH2BE_U32(q, 0);3028 scsiH2BE_U32(q, (uint32_t)uLbaStart); 2895 3029 q += 4; 2896 3030 } … … 2901 3035 *q++ = 0xaa; /* track number */ 2902 3036 *q++ = 0; /* reserved */ 3037 3038 /* Query start and length of last track to get the start of the lead out track. */ 3039 uint64_t uLbaStart = 0; 3040 uint64_t cBlocks = 0; 3041 3042 int rc = s->pDrvMedia->pfnQueryRegionProperties(s->pDrvMedia, cTracks - 1, &uLbaStart, 3043 &cBlocks, NULL, NULL); 3044 AssertRC(rc); 3045 3046 uLbaStart += cBlocks; 2903 3047 if (fMSF) 2904 3048 { 2905 3049 *q++ = 0; /* reserved */ 2906 scsiLBA2MSF(q, s->cTotalSectors);3050 scsiLBA2MSF(q, (uint32_t)uLbaStart); 2907 3051 q += 3; 2908 3052 } 2909 3053 else 2910 3054 { 2911 scsiH2BE_U32(q, s->cTotalSectors);3055 scsiH2BE_U32(q, (uint32_t)uLbaStart); 2912 3056 q += 4; 2913 3057 } … … 2938 3082 pbBuf[2] = 0x01; 2939 3083 pbBuf[3] = 0x01; 2940 pbBuf[5] = 0x14; /* ADR, control */ 3084 3085 VDREGIONDATAFORM enmDataForm = VDREGIONDATAFORM_MODE1_2048; 3086 int rc = s->pDrvMedia->pfnQueryRegionProperties(s->pDrvMedia, 0, NULL, 3087 NULL, NULL, &enmDataForm); 3088 AssertRC(rc); 3089 3090 if (enmDataForm == VDREGIONDATAFORM_CDDA) 3091 pbBuf[5] = 0x10; /* ADR, control */ 3092 else 3093 pbBuf[5] = 0x14; /* ADR, control */ 3094 2941 3095 pbBuf[6] = 1; /* first track in last complete session */ 2942 3096 if (fMSF) … … 3139 3293 cSectors = scsiBE2H_U32(pbPacket + 6); 3140 3294 iATAPILBA = scsiBE2H_U32(pbPacket + 2); 3295 3296 /* Check that the sector size is valid. */ 3297 uint64_t cbSector = 2048; 3298 int rc = s->pDrvMedia->pfnQueryRegionPropertiesForLba(s->pDrvMedia, iATAPILBA, 3299 NULL, NULL, &cbSector, NULL); 3300 AssertRC(rc); 3301 if (cbSector != 2048) 3302 { 3303 uint8_t abATAPISense[ATAPI_SENSE_SIZE]; 3304 RT_ZERO(abATAPISense); 3305 3306 abATAPISense[0] = 0x70 | (1 << 7); 3307 abATAPISense[2] = (SCSI_SENSE_ILLEGAL_REQUEST & 0x0f) | SCSI_SENSE_FLAG_ILI; 3308 scsiH2BE_U32(&abATAPISense[3], iATAPILBA); 3309 abATAPISense[7] = 10; 3310 abATAPISense[12] = SCSI_ASC_ILLEGAL_MODE_FOR_THIS_TRACK; 3311 atapiR3CmdError(s, &abATAPISense[0], sizeof(abATAPISense)); 3312 break; 3313 } 3314 3141 3315 if (cSectors == 0) 3142 3316 { … … 3175 3349 { 3176 3350 atapiR3CmdErrorSimple(s, SCSI_SENSE_NOT_READY, SCSI_ASC_MEDIUM_NOT_PRESENT); 3351 break; 3352 } 3353 if ((pbPacket[10] & 0x7) != 0) 3354 { 3355 atapiR3CmdErrorSimple(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET); 3177 3356 break; 3178 3357 } … … 3199 3378 break; 3200 3379 } 3201 switch (pbPacket[9] & 0xf8) 3380 /* 3381 * If the LBA is in an audio track we are required to ignore pretty much all 3382 * of the channel selection values (except 0x00) and map everything to 0x10 3383 * which means read user data with a sector size of 2352 bytes. 3384 * 3385 * (MMC-6 chapter 6.19.2.6) 3386 */ 3387 uint8_t uChnSel = pbPacket[9] & 0xf8; 3388 VDREGIONDATAFORM enmDataForm; 3389 int rc = s->pDrvMedia->pfnQueryRegionPropertiesForLba(s->pDrvMedia, iATAPILBA, 3390 NULL, NULL, NULL, &enmDataForm); 3391 AssertRC(rc); 3392 3393 if (enmDataForm == VDREGIONDATAFORM_CDDA) 3202 3394 { 3203 case 0x00: 3395 if (uChnSel == 0) 3396 { 3204 3397 /* nothing */ 3205 3398 atapiR3CmdOK(s); 3206 break; 3207 case 0x10: 3208 /* normal read */ 3209 atapiR3ReadSectors(s, iATAPILBA, cSectors, 2048); 3210 break; 3211 case 0xf8: 3212 /* read all data */ 3399 } 3400 else 3213 3401 atapiR3ReadSectors(s, iATAPILBA, cSectors, 2352); 3214 break; 3215 default: 3216 LogRel(("PIIX3 ATA: LUN#%d: CD-ROM sector format not supported (%#x)\n", s->iLUN, pbPacket[9] & 0xf8)); 3217 atapiR3CmdErrorSimple(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET); 3218 break; 3402 } 3403 else 3404 { 3405 switch (uChnSel) 3406 { 3407 case 0x00: 3408 /* nothing */ 3409 atapiR3CmdOK(s); 3410 break; 3411 case 0x10: 3412 /* normal read */ 3413 atapiR3ReadSectors(s, iATAPILBA, cSectors, 2048); 3414 break; 3415 case 0xf8: 3416 /* read all data */ 3417 atapiR3ReadSectors(s, iATAPILBA, cSectors, 2352); 3418 break; 3419 default: 3420 LogRel(("PIIX3 ATA: LUN#%d: CD-ROM sector format not supported (%#x)\n", s->iLUN, pbPacket[9] & 0xf8)); 3421 atapiR3CmdErrorSimple(s, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INV_FIELD_IN_CMD_PACKET); 3422 break; 3423 } 3219 3424 } 3220 3425 break; … … 3556 3761 return; 3557 3762 3558 if (pIf->fATAPI) 3559 pIf->cTotalSectors = pIf->pDrvMedia->pfnGetSize(pIf->pDrvMedia) / 2048; 3560 else 3561 pIf->cTotalSectors = pIf->pDrvMedia->pfnGetSize(pIf->pDrvMedia) / pIf->cbSector; 3763 uint32_t cRegions = pIf->pDrvMedia->pfnGetRegionCount(pIf->pDrvMedia); 3764 for (uint32_t i = 0; i < cRegions; i++) 3765 { 3766 uint64_t cBlocks = 0; 3767 int rc = pIf->pDrvMedia->pfnQueryRegionProperties(pIf->pDrvMedia, i, NULL, &cBlocks, 3768 NULL, NULL); 3769 AssertRC(rc); 3770 pIf->cTotalSectors += cBlocks; 3771 } 3562 3772 3563 3773 LogRel(("PIIX3 ATA: LUN#%d: CD/DVD, total number of sectors %Ld, passthrough unchanged\n", pIf->iLUN, pIf->cTotalSectors)); … … 6161 6371 */ 6162 6372 if (pIf->fATAPI) 6163 pIf->cbSector = 2048; 6373 pIf->cbSector = 2048; /* Not required for ATAPI, one medium can have multiple sector sizes. */ 6164 6374 else 6165 6375 pIf->cbSector = pIf->pDrvMedia->pfnGetSectorSize(pIf->pDrvMedia); … … 6195 6405 * Init geometry (only for non-CD/DVD media). 6196 6406 */ 6407 uint32_t cRegions = pIf->pDrvMedia->pfnGetRegionCount(pIf->pDrvMedia); 6408 pIf->cTotalSectors = 0; 6409 for (uint32_t i = 0; i < cRegions; i++) 6410 { 6411 uint64_t cBlocks = 0; 6412 rc = pIf->pDrvMedia->pfnQueryRegionProperties(pIf->pDrvMedia, i, NULL, &cBlocks, 6413 NULL, NULL); 6414 AssertRC(rc); 6415 pIf->cTotalSectors += cBlocks; 6416 } 6417 6197 6418 if (pIf->fATAPI) 6198 6419 { 6199 pIf->cTotalSectors = pIf->pDrvMedia->pfnGetSize(pIf->pDrvMedia) / pIf->cbSector;6200 6420 pIf->PCHSGeometry.cCylinders = 0; /* dummy */ 6201 6421 pIf->PCHSGeometry.cHeads = 0; /* dummy */ … … 6206 6426 else 6207 6427 { 6208 pIf->cTotalSectors = pIf->pDrvMedia->pfnGetSize(pIf->pDrvMedia) / pIf->cbSector;6209 6428 rc = pIf->pDrvMedia->pfnBiosGetPCHSGeometry(pIf->pDrvMedia, &pIf->PCHSGeometry); 6210 6429 if (rc == VERR_PDM_MEDIA_NOT_MOUNTED)
Note:
See TracChangeset
for help on using the changeset viewer.