Index: /trunk/src/VBox/Devices/Storage/ATAPIPassthrough.cpp
===================================================================
--- /trunk/src/VBox/Devices/Storage/ATAPIPassthrough.cpp	(revision 43571)
+++ /trunk/src/VBox/Devices/Storage/ATAPIPassthrough.cpp	(revision 43572)
@@ -33,4 +33,7 @@
 /** The track is the lead out track of the medium. */
 #define TRACK_FLAGS_LEAD_OUT     RT_BIT_32(2)
+
+/** Don't clear already detected tracks on the medium. */
+#define ATAPI_TRACK_LIST_REALLOCATE_FLAGS_DONT_CLEAR RT_BIT_32(0)
 
 /**
@@ -136,10 +139,12 @@
  * @param   pTrackList    The track list to reallocate.
  * @param   cTracks       Number of tracks the list must be able to hold.
- */
-static int atapiTrackListReallocate(PTRACKLIST pTrackList, unsigned cTracks)
+ * @param   fFlags        Flags for the reallocation.
+ */
+static int atapiTrackListReallocate(PTRACKLIST pTrackList, unsigned cTracks, uint32_t fFlags)
 {
     int rc = VINF_SUCCESS;
 
-    ATAPIPassthroughTrackListClear(pTrackList);
+    if (!(fFlags & ATAPI_TRACK_LIST_REALLOCATE_FLAGS_DONT_CLEAR))
+        ATAPIPassthroughTrackListClear(pTrackList);
 
     if (pTrackList->cTracksMax < cTracks)
@@ -172,5 +177,5 @@
  * @param   pbCueSheetEntry    CUE sheet entry to use.
  */
-static void atapiTrackListEntryCreateFromCueSheetEntry(PTRACK pTrack, uint8_t *pbCueSheetEntry)
+static void atapiTrackListEntryCreateFromCueSheetEntry(PTRACK pTrack, const uint8_t *pbCueSheetEntry)
 {
     TRACKDATAFORM enmTrackDataForm = TRACKDATAFORM_INVALID;
@@ -264,5 +269,5 @@
  * @param   pvBuf         The CUE sheet.
  */
-static int atapiTrackListUpdateFromSendCueSheet(PTRACKLIST pTrackList, uint8_t *pbCDB, void *pvBuf)
+static int atapiTrackListUpdateFromSendCueSheet(PTRACKLIST pTrackList, const uint8_t *pbCDB, const void *pvBuf)
 {
     int rc = VINF_SUCCESS;
@@ -272,8 +277,8 @@
     AssertReturn(cbCueSheet % 8 == 0 && cTracks, VERR_INVALID_PARAMETER);
 
-    rc = atapiTrackListReallocate(pTrackList, cTracks);
+    rc = atapiTrackListReallocate(pTrackList, cTracks, 0);
     if (RT_SUCCESS(rc))
     {
-        uint8_t *pbCueSheet = (uint8_t *)pvBuf;
+        const uint8_t *pbCueSheet = (uint8_t *)pvBuf;
         PTRACK pTrack = pTrackList->paTracks;
 
@@ -291,25 +296,109 @@
 }
 
-static int atapiTrackListUpdateFromSendDvdStructure(PTRACKLIST pTrackList, uint8_t *pbCDB, void *pvBuf)
+static int atapiTrackListUpdateFromSendDvdStructure(PTRACKLIST pTrackList, const uint8_t *pbCDB, const void *pvBuf)
 {
     return VERR_NOT_IMPLEMENTED;
 }
 
-static int atapiTrackListUpdateFromReadTocPmaAtip(PTRACKLIST pTrackList, uint8_t *pbCDB, void *pvBuf)
+/**
+ * Update track list from formatted TOC data.
+ *
+ * @returns VBox status code.
+ * @param   pTrackList    The track list to update.
+ * @param   fMSF          Flag whether block addresses are in MSF or LBA format.
+ * @param   pbBuf         Buffer holding the formatted TOC.
+ * @param   cbBuffer      Size of the buffer.
+ */
+static int atapiTrackListUpdateFromFormattedToc(PTRACKLIST pTrackList, uint8_t iTrack,
+                                                bool fMSF, const uint8_t *pbBuf, size_t cbBuffer)
+{
+    int rc = VINF_SUCCESS;
+    size_t cbToc = atapiBE2H_U16(pbBuf);
+    uint8_t iTrackFirst = pbBuf[2];
+    unsigned cTracks;
+
+    cbToc -= 2;
+    pbBuf += 4;
+    AssertReturn(cbToc % 8 == 0, VERR_INVALID_PARAMETER);
+
+    cTracks = cbToc / 8 + iTrackFirst;
+
+    rc = atapiTrackListReallocate(pTrackList, cTracks, ATAPI_TRACK_LIST_REALLOCATE_FLAGS_DONT_CLEAR);
+    if (RT_SUCCESS(rc))
+    {
+        PTRACK pTrack = &pTrackList->paTracks[iTrackFirst];
+
+        for (unsigned i = iTrackFirst; i < cTracks; i++)
+        {
+            if (pbBuf[1] & 0x4)
+                pTrack->enmMainDataForm = TRACKDATAFORM_MODE1_2048;
+            else
+                pTrack->enmMainDataForm = TRACKDATAFORM_CDDA;
+
+            pTrack->enmSubChnDataForm = SUBCHNDATAFORM_0;
+            if (fMSF)
+                pTrack->iLbaStart = atapiMSF2LBA(&pbBuf[4]);
+            else
+                pTrack->iLbaStart = atapiBE2H_U32(&pbBuf[4]);
+
+            if (pbBuf[2] != 0xaa)
+            {
+                /* Calculate number of sectors from the next entry. */
+                int64_t iLbaNext;
+
+                if (fMSF)
+                    iLbaNext = atapiMSF2LBA(&pbBuf[4+8]);
+                else
+                    iLbaNext = atapiBE2H_U32(&pbBuf[4+8]);
+
+                pTrack->cSectors = iLbaNext - pTrack->iLbaStart;
+            }
+            else
+                pTrack->cSectors = 0;
+
+            pTrack->fFlags &= ~TRACK_FLAGS_UNDETECTED;
+            pbBuf += 8;
+        }
+    }
+
+    return rc;
+}
+
+static int atapiTrackListUpdateFromReadTocPmaAtip(PTRACKLIST pTrackList, const uint8_t *pbCDB, const void *pvBuf)
+{
+    int rc = VINF_SUCCESS;
+    size_t cbBuffer = atapiBE2H_U16(&pbCDB[7]);
+    bool fMSF = (pbCDB[1] & 0x2) != 0;
+    uint8_t uFmt = pbCDB[2] & 0xf;
+    uint8_t iTrack = pbCDB[6];
+
+    switch (uFmt)
+    {
+        case 0x00:
+            rc = atapiTrackListUpdateFromFormattedToc(pTrackList, iTrack, fMSF, (uint8_t *)pvBuf, cbBuffer);
+            break;
+        case 0x01:
+        case 0x02:
+        case 0x03:
+        case 0x04:
+        case 0x05:
+        default:
+            rc = VERR_INVALID_PARAMETER;
+    }
+
+    return rc;
+}
+
+static int atapiTrackListUpdateFromReadTrackInformation(PTRACKLIST pTrackList, const uint8_t *pbCDB, const void *pvBuf)
 {
     return VERR_NOT_IMPLEMENTED;
 }
 
-static int atapiTrackListUpdateFromReadTrackInformation(PTRACKLIST pTrackList, uint8_t *pbCDB, void *pvBuf)
+static int atapiTrackListUpdateFromReadDvdStructure(PTRACKLIST pTrackList, const uint8_t *pbCDB, const void *pvBuf)
 {
     return VERR_NOT_IMPLEMENTED;
 }
 
-static int atapiTrackListUpdateFromReadDvdStructure(PTRACKLIST pTrackList, uint8_t *pbCDB, void *pvBuf)
-{
-    return VERR_NOT_IMPLEMENTED;
-}
-
-static int atapiTrackListUpdateFromReadDiscInformation(PTRACKLIST pTrackList, uint8_t *pbCDB, void *pvBuf)
+static int atapiTrackListUpdateFromReadDiscInformation(PTRACKLIST pTrackList, const uint8_t *pbCDB, const void *pvBuf)
 {
     return VERR_NOT_IMPLEMENTED;
@@ -426,5 +515,5 @@
 }
 
-DECLHIDDEN(int) ATAPIPassthroughTrackListUpdate(PTRACKLIST pTrackList, uint8_t *pbCDB, void *pvBuf)
+DECLHIDDEN(int) ATAPIPassthroughTrackListUpdate(PTRACKLIST pTrackList, const uint8_t *pbCDB, const void *pvBuf)
 {
     int rc = VINF_SUCCESS;
@@ -455,5 +544,7 @@
     }
 
+#ifdef LOG_ENABLED
     atapiTrackListDump(pTrackList);
+#endif
 
     return rc;
Index: /trunk/src/VBox/Devices/Storage/DevATA.cpp
===================================================================
--- /trunk/src/VBox/Devices/Storage/DevATA.cpp	(revision 43571)
+++ /trunk/src/VBox/Devices/Storage/DevATA.cpp	(revision 43572)
@@ -102,6 +102,4 @@
 /* Media track type */
 #define ATA_MEDIA_TYPE_UNKNOWN                  0    /**< unknown CD type */
-#define ATA_MEDIA_TYPE_DATA                     1    /**< Data CD */
-#define ATA_MEDIA_TYPE_CDDA                     2    /**< CD-DA  (audio) CD type */
 #define ATA_MEDIA_NO_DISC                    0x70    /**< Door closed, no medium */
 
@@ -2128,4 +2126,5 @@
         {
             case SCSI_SEND_CUE_SHEET:
+            case SCSI_READ_TOC_PMA_ATIP:
             {
                 if (!s->pTrackList)
@@ -2137,6 +2136,6 @@
                 if (   RT_FAILURE(rc)
                     && s->cErrors++ < MAX_LOG_REL_ERRORS)
-                    LogRel(("ATA: Error (%Rrc) while updating the tracklist during SEND CUE SHEET, burning the disc might fail\n",
-                            rc));
+                    LogRel(("ATA: Error (%Rrc) while updating the tracklist during %s, burning the disc might fail\n",
+                            rc, s->aATAPICmd[0] == SCSI_SEND_CUE_SHEET ? "SEND CUE SHEET" : "READ TOC/PMA/ATIP"));
                 break;
             }
@@ -2169,35 +2168,5 @@
                 ataSCSIPadStr(s->CTX_SUFF(pbIOBuffer) + 32, "1.0", 4);
             }
-            else if (   s->aATAPICmd[0] == SCSI_READ_TOC_PMA_ATIP
-                     && (s->aATAPICmd[2] & 0xf) != 0x05
-                     && s->aATAPICmd[6] != 0xaa)
-            {
-                /* Set the media type if we can detect it. */
-                uint8_t *pbBuf = s->CTX_SUFF(pbIOBuffer);
-
-                /** @todo: Implemented only for formatted TOC now. */
-                if (   (s->aATAPICmd[2] & 0xf) == 0
-                    && cbTransfer >= 6)
-                {
-                    uint32_t NewMediaType;
-                    uint32_t OldMediaType;
-
-                    if (pbBuf[5] & 0x4)
-                        NewMediaType = ATA_MEDIA_TYPE_DATA;
-                    else
-                        NewMediaType = ATA_MEDIA_TYPE_CDDA;
-
-                    OldMediaType = ataMediumTypeSet(s, NewMediaType);
-
-                    if (OldMediaType != NewMediaType)
-                        LogRel(("PIIX3 ATA: LUN#%d: CD-ROM passthrough, detected %s CD\n",
-                                s->iLUN,
-                                NewMediaType == ATA_MEDIA_TYPE_DATA
-                                ? "data"
-                                : "audio"));
-                }
-                else /* Play safe and set to unknown. */
-                    ataMediumTypeSet(s, ATA_MEDIA_TYPE_UNKNOWN);
-            }
+
             if (cbTransfer)
                 Log3(("ATAPI PT data read (%d): %.*Rhxs\n", cbTransfer, cbTransfer, s->CTX_SUFF(pbIOBuffer)));
@@ -3524,9 +3493,18 @@
             {
                 case 0x0: /* All types. */
-                    if (ASMAtomicReadU32(&s->MediaTrackType) == ATA_MEDIA_TYPE_CDDA)
-                        s->cbATAPISector = 2352;
+                {
+                    uint32_t iLbaStart;
+
+                    if (pbPacket[0] == SCSI_READ_CD)
+                        iLbaStart = ataBE2H_U32(&pbPacket[2]);
+                    else
+                        iLbaStart = ataMSF2LBA(&pbPacket[3]);
+
+                    if (s->pTrackList)
+                        s->cbATAPISector = ATAPIPassthroughTrackListGetSectorSizeFromLba(s->pTrackList, iLbaStart);
                     else
                         s->cbATAPISector = 2048; /* Might be incorrect if we couldn't determine the type. */
                     break;
+                }
                 case 0x1: /* CD-DA */
                     s->cbATAPISector = 2352;
