VirtualBox

source: vbox/trunk/src/VBox/Devices/Storage/ATAPIPassthrough.cpp@ 64671

Last change on this file since 64671 was 64410, checked in by vboxsync, 8 years ago

ATAPIPassthrough: fixed setting the amount of tracks when the request doesn't start from the beginning

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 19.8 KB
Line 
1/* $Id: ATAPIPassthrough.cpp 64410 2016-10-25 11:56:01Z vboxsync $ */
2/** @file
3 * VBox storage devices: ATAPI emulation (common code for DevATA and DevAHCI).
4 */
5
6/*
7 * Copyright (C) 2012-2016 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17#define LOG_GROUP LOG_GROUP_DEV_IDE
18#include <iprt/log.h>
19#include <iprt/assert.h>
20#include <iprt/mem.h>
21
22#include <VBox/log.h>
23#include <VBox/err.h>
24#include <VBox/cdefs.h>
25#include <VBox/scsi.h>
26
27#include "ATAPIPassthrough.h"
28
29/** The track was not detected yet. */
30#define TRACK_FLAGS_UNDETECTED RT_BIT_32(0)
31/** The track is the lead in track of the medium. */
32#define TRACK_FLAGS_LEAD_IN RT_BIT_32(1)
33/** The track is the lead out track of the medium. */
34#define TRACK_FLAGS_LEAD_OUT RT_BIT_32(2)
35
36/** Don't clear already detected tracks on the medium. */
37#define ATAPI_TRACK_LIST_REALLOCATE_FLAGS_DONT_CLEAR RT_BIT_32(0)
38
39/**
40 * Track main data form.
41 */
42typedef enum TRACKDATAFORM
43{
44 /** Invalid data form. */
45 TRACKDATAFORM_INVALID = 0,
46 /** 2352 bytes of data. */
47 TRACKDATAFORM_CDDA,
48 /** CDDA data is pause. */
49 TRACKDATAFORM_CDDA_PAUSE,
50 /** Mode 1 with 2048 bytes sector size. */
51 TRACKDATAFORM_MODE1_2048,
52 /** Mode 1 with 2352 bytes sector size. */
53 TRACKDATAFORM_MODE1_2352,
54 /** Mode 1 with 0 bytes sector size (generated by the drive). */
55 TRACKDATAFORM_MODE1_0,
56 /** XA Mode with 2336 bytes sector size. */
57 TRACKDATAFORM_XA_2336,
58 /** XA Mode with 2352 bytes sector size. */
59 TRACKDATAFORM_XA_2352,
60 /** XA Mode with 0 bytes sector size (generated by the drive). */
61 TRACKDATAFORM_XA_0,
62 /** Mode 2 with 2336 bytes sector size. */
63 TRACKDATAFORM_MODE2_2336,
64 /** Mode 2 with 2352 bytes sector size. */
65 TRACKDATAFORM_MODE2_2352,
66 /** Mode 2 with 0 bytes sector size (generated by the drive). */
67 TRACKDATAFORM_MODE2_0
68} TRACKDATAFORM;
69
70/**
71 * Subchannel data form.
72 */
73typedef enum SUBCHNDATAFORM
74{
75 /** Invalid subchannel data form. */
76 SUBCHNDATAFORM_INVALID = 0,
77 /** 0 bytes for the subchannel (generated by the drive). */
78 SUBCHNDATAFORM_0,
79 /** 96 bytes of data for the subchannel. */
80 SUBCHNDATAFORM_96
81} SUBCHNDATAFORM;
82
83/**
84 * Track entry.
85 */
86typedef struct TRACK
87{
88 /** Start LBA of the track. */
89 int64_t iLbaStart;
90 /** Number of sectors in the track. */
91 uint32_t cSectors;
92 /** Data form of main data. */
93 TRACKDATAFORM enmMainDataForm;
94 /** Data form of sub channel. */
95 SUBCHNDATAFORM enmSubChnDataForm;
96 /** Flags for the track. */
97 uint32_t fFlags;
98} TRACK, *PTRACK;
99
100/**
101 * Media track list.
102 */
103typedef struct TRACKLIST
104{
105 /** Number of detected tracks of the current medium. */
106 unsigned cTracksCurrent;
107 /** Maximum number of tracks the list can contain. */
108 unsigned cTracksMax;
109 /** Variable list of tracks. */
110 PTRACK paTracks;
111} TRACKLIST, *PTRACKLIST;
112
113DECLINLINE(uint16_t) atapiBE2H_U16(const uint8_t *pbBuf)
114{
115 return (pbBuf[0] << 8) | pbBuf[1];
116}
117
118
119DECLINLINE(uint32_t) atapiBE2H_U24(const uint8_t *pbBuf)
120{
121 return (pbBuf[0] << 16) | (pbBuf[1] << 8) | pbBuf[2];
122}
123
124
125DECLINLINE(uint32_t) atapiBE2H_U32(const uint8_t *pbBuf)
126{
127 return (pbBuf[0] << 24) | (pbBuf[1] << 16) | (pbBuf[2] << 8) | pbBuf[3];
128}
129
130DECLINLINE(int64_t) atapiMSF2LBA(const uint8_t *pbBuf)
131{
132 return ((int64_t)(pbBuf[0] * 60 + pbBuf[1]) * 75 + pbBuf[2]) - 150; /* 2 second pregap */
133}
134
135/**
136 * Reallocate the given track list to be able to hold the given number of tracks.
137 *
138 * @returns VBox status code.
139 * @param pTrackList The track list to reallocate.
140 * @param cTracks Number of tracks the list must be able to hold.
141 * @param fFlags Flags for the reallocation.
142 */
143static int atapiTrackListReallocate(PTRACKLIST pTrackList, unsigned cTracks, uint32_t fFlags)
144{
145 int rc = VINF_SUCCESS;
146
147 if (!(fFlags & ATAPI_TRACK_LIST_REALLOCATE_FLAGS_DONT_CLEAR))
148 ATAPIPassthroughTrackListClear(pTrackList);
149
150 if (pTrackList->cTracksMax < cTracks)
151 {
152 PTRACK paTracksNew = (PTRACK)RTMemRealloc(pTrackList->paTracks, cTracks * sizeof(TRACK));
153 if (paTracksNew)
154 {
155 pTrackList->paTracks = paTracksNew;
156
157 /* Mark new tracks as undetected. */
158 for (unsigned i = pTrackList->cTracksMax; i < cTracks; i++)
159 pTrackList->paTracks[i].fFlags |= TRACK_FLAGS_UNDETECTED;
160
161 pTrackList->cTracksMax = cTracks;
162 }
163 else
164 rc = VERR_NO_MEMORY;
165 }
166
167 if (RT_SUCCESS(rc))
168 pTrackList->cTracksCurrent = cTracks;
169
170 return rc;
171}
172
173/**
174 * Initilizes the given track from the given CUE sheet entry.
175 *
176 * @returns nothing.
177 * @param pTrack The track to initialize.
178 * @param pbCueSheetEntry CUE sheet entry to use.
179 */
180static void atapiTrackListEntryCreateFromCueSheetEntry(PTRACK pTrack, const uint8_t *pbCueSheetEntry)
181{
182 TRACKDATAFORM enmTrackDataForm = TRACKDATAFORM_INVALID;
183 SUBCHNDATAFORM enmSubChnDataForm = SUBCHNDATAFORM_INVALID;
184
185 /* Determine size of main data based on the data form field. */
186 switch (pbCueSheetEntry[3] & 0x3f)
187 {
188 case 0x00: /* CD-DA with data. */
189 enmTrackDataForm = TRACKDATAFORM_CDDA;
190 break;
191 case 0x01: /* CD-DA without data (used for pauses between tracks). */
192 enmTrackDataForm = TRACKDATAFORM_CDDA_PAUSE;
193 break;
194 case 0x10: /* CD-ROM mode 1 */
195 case 0x12:
196 enmTrackDataForm = TRACKDATAFORM_MODE1_2048;
197 break;
198 case 0x11:
199 case 0x13:
200 enmTrackDataForm = TRACKDATAFORM_MODE1_2352;
201 break;
202 case 0x14:
203 enmTrackDataForm = TRACKDATAFORM_MODE1_0;
204 break;
205 case 0x20: /* CD-ROM XA, CD-I */
206 case 0x22:
207 enmTrackDataForm = TRACKDATAFORM_XA_2336;
208 break;
209 case 0x21:
210 case 0x23:
211 enmTrackDataForm = TRACKDATAFORM_XA_2352;
212 break;
213 case 0x24:
214 enmTrackDataForm = TRACKDATAFORM_XA_0;
215 break;
216 case 0x31: /* CD-ROM Mode 2 */
217 case 0x33:
218 enmTrackDataForm = TRACKDATAFORM_MODE2_2352;
219 break;
220 case 0x30:
221 case 0x32:
222 enmTrackDataForm = TRACKDATAFORM_MODE2_2336;
223 break;
224 case 0x34:
225 enmTrackDataForm = TRACKDATAFORM_MODE2_0;
226 break;
227 default: /* Reserved, invalid mode. Log and leave default sector size. */
228 LogRel(("ATA: Invalid data form mode %d for current CUE sheet\n",
229 pbCueSheetEntry[3] & 0x3f));
230 }
231
232 /* Determine size of sub channel data based on data form field. */
233 switch ((pbCueSheetEntry[3] & 0xc0) >> 6)
234 {
235 case 0x00: /* Sub channel all zeroes, autogenerated by the drive. */
236 enmSubChnDataForm = SUBCHNDATAFORM_0;
237 break;
238 case 0x01:
239 case 0x03:
240 enmSubChnDataForm = SUBCHNDATAFORM_96;
241 break;
242 default:
243 LogRel(("ATA: Invalid sub-channel data form mode %u for current CUE sheet\n",
244 pbCueSheetEntry[3] & 0xc0));
245 }
246
247 pTrack->enmMainDataForm = enmTrackDataForm;
248 pTrack->enmSubChnDataForm = enmSubChnDataForm;
249 pTrack->iLbaStart = atapiMSF2LBA(&pbCueSheetEntry[5]);
250 if (pbCueSheetEntry[1] != 0xaa)
251 {
252 /* Calculate number of sectors from the next entry. */
253 int64_t iLbaNext = atapiMSF2LBA(&pbCueSheetEntry[5+8]);
254 pTrack->cSectors = iLbaNext - pTrack->iLbaStart;
255 }
256 else
257 {
258 pTrack->fFlags |= TRACK_FLAGS_LEAD_OUT;
259 pTrack->cSectors = 0;
260 }
261 pTrack->fFlags &= ~TRACK_FLAGS_UNDETECTED;
262}
263
264/**
265 * Update the track list from a SEND CUE SHEET request.
266 *
267 * @returns VBox status code.
268 * @param pTrackList Track list to update.
269 * @param pbCDB CDB of the SEND CUE SHEET request.
270 * @param pvBuf The CUE sheet.
271 */
272static int atapiTrackListUpdateFromSendCueSheet(PTRACKLIST pTrackList, const uint8_t *pbCDB, const void *pvBuf)
273{
274 int rc = VINF_SUCCESS;
275 unsigned cbCueSheet = atapiBE2H_U24(pbCDB + 6);
276 unsigned cTracks = cbCueSheet / 8;
277
278 AssertReturn(cbCueSheet % 8 == 0 && cTracks, VERR_INVALID_PARAMETER);
279
280 rc = atapiTrackListReallocate(pTrackList, cTracks, 0);
281 if (RT_SUCCESS(rc))
282 {
283 const uint8_t *pbCueSheet = (uint8_t *)pvBuf;
284 PTRACK pTrack = pTrackList->paTracks;
285
286 for (unsigned i = 0; i < cTracks; i++)
287 {
288 atapiTrackListEntryCreateFromCueSheetEntry(pTrack, pbCueSheet);
289 if (i == 0)
290 pTrack->fFlags |= TRACK_FLAGS_LEAD_IN;
291 pTrack++;
292 pbCueSheet += 8;
293 }
294 }
295
296 return rc;
297}
298
299static int atapiTrackListUpdateFromSendDvdStructure(PTRACKLIST pTrackList, const uint8_t *pbCDB, const void *pvBuf)
300{
301 RT_NOREF(pTrackList, pbCDB, pvBuf);
302 return VERR_NOT_IMPLEMENTED;
303}
304
305/**
306 * Update track list from formatted TOC data.
307 *
308 * @returns VBox status code.
309 * @param pTrackList The track list to update.
310 * @param iTrack The first track the TOC has data for.
311 * @param fMSF Flag whether block addresses are in MSF or LBA format.
312 * @param pbBuf Buffer holding the formatted TOC.
313 * @param cbBuffer Size of the buffer.
314 */
315static int atapiTrackListUpdateFromFormattedToc(PTRACKLIST pTrackList, uint8_t iTrack,
316 bool fMSF, const uint8_t *pbBuf, uint32_t cbBuffer)
317{
318 RT_NOREF(iTrack, cbBuffer); /** @todo unused parameters */
319 int rc = VINF_SUCCESS;
320 unsigned cbToc = atapiBE2H_U16(pbBuf);
321 uint8_t iTrackFirst = pbBuf[2];
322 unsigned cTracks;
323
324 cbToc -= 2;
325 pbBuf += 4;
326 AssertReturn(cbToc % 8 == 0, VERR_INVALID_PARAMETER);
327
328 cTracks = cbToc / 8 + iTrackFirst;
329
330 rc = atapiTrackListReallocate(pTrackList, iTrackFirst + cTracks, ATAPI_TRACK_LIST_REALLOCATE_FLAGS_DONT_CLEAR);
331 if (RT_SUCCESS(rc))
332 {
333 PTRACK pTrack = &pTrackList->paTracks[iTrackFirst];
334
335 for (unsigned i = iTrackFirst; i < cTracks; i++)
336 {
337 if (pbBuf[1] & 0x4)
338 pTrack->enmMainDataForm = TRACKDATAFORM_MODE1_2048;
339 else
340 pTrack->enmMainDataForm = TRACKDATAFORM_CDDA;
341
342 pTrack->enmSubChnDataForm = SUBCHNDATAFORM_0;
343 if (fMSF)
344 pTrack->iLbaStart = atapiMSF2LBA(&pbBuf[4]);
345 else
346 pTrack->iLbaStart = atapiBE2H_U32(&pbBuf[4]);
347
348 if (pbBuf[2] != 0xaa)
349 {
350 /* Calculate number of sectors from the next entry. */
351 int64_t iLbaNext;
352
353 if (fMSF)
354 iLbaNext = atapiMSF2LBA(&pbBuf[4+8]);
355 else
356 iLbaNext = atapiBE2H_U32(&pbBuf[4+8]);
357
358 pTrack->cSectors = iLbaNext - pTrack->iLbaStart;
359 }
360 else
361 pTrack->cSectors = 0;
362
363 pTrack->fFlags &= ~TRACK_FLAGS_UNDETECTED;
364 pbBuf += 8;
365 pTrack++;
366 }
367 }
368
369 return rc;
370}
371
372static int atapiTrackListUpdateFromReadTocPmaAtip(PTRACKLIST pTrackList, const uint8_t *pbCDB, const void *pvBuf)
373{
374 int rc = VINF_SUCCESS;
375 uint16_t cbBuffer = atapiBE2H_U16(&pbCDB[7]);
376 bool fMSF = (pbCDB[1] & 0x2) != 0;
377 uint8_t uFmt = pbCDB[2] & 0xf;
378 uint8_t iTrack = pbCDB[6];
379
380 switch (uFmt)
381 {
382 case 0x00:
383 rc = atapiTrackListUpdateFromFormattedToc(pTrackList, iTrack, fMSF, (uint8_t *)pvBuf, cbBuffer);
384 break;
385 case 0x01:
386 case 0x02:
387 case 0x03:
388 case 0x04:
389 rc = VERR_NOT_IMPLEMENTED;
390 break;
391 case 0x05:
392 rc = VINF_SUCCESS; /* Does not give information about the tracklist. */
393 break;
394 default:
395 rc = VERR_INVALID_PARAMETER;
396 }
397
398 return rc;
399}
400
401static int atapiTrackListUpdateFromReadTrackInformation(PTRACKLIST pTrackList, const uint8_t *pbCDB, const void *pvBuf)
402{
403 RT_NOREF(pTrackList, pbCDB, pvBuf);
404 return VERR_NOT_IMPLEMENTED;
405}
406
407static int atapiTrackListUpdateFromReadDvdStructure(PTRACKLIST pTrackList, const uint8_t *pbCDB, const void *pvBuf)
408{
409 RT_NOREF(pTrackList, pbCDB, pvBuf);
410 return VERR_NOT_IMPLEMENTED;
411}
412
413static int atapiTrackListUpdateFromReadDiscInformation(PTRACKLIST pTrackList, const uint8_t *pbCDB, const void *pvBuf)
414{
415 RT_NOREF(pTrackList, pbCDB, pvBuf);
416 return VERR_NOT_IMPLEMENTED;
417}
418
419#ifdef LOG_ENABLED
420
421/**
422 * Converts the given track data form to a string.
423 *
424 * @returns Track data form as a string.
425 * @param enmTrackDataForm The track main data form.
426 */
427static const char *atapiTrackListMainDataFormToString(TRACKDATAFORM enmTrackDataForm)
428{
429 switch (enmTrackDataForm)
430 {
431 case TRACKDATAFORM_CDDA:
432 return "CD-DA";
433 case TRACKDATAFORM_CDDA_PAUSE:
434 return "CD-DA Pause";
435 case TRACKDATAFORM_MODE1_2048:
436 return "Mode 1 (2048 bytes)";
437 case TRACKDATAFORM_MODE1_2352:
438 return "Mode 1 (2352 bytes)";
439 case TRACKDATAFORM_MODE1_0:
440 return "Mode 1 (0 bytes)";
441 case TRACKDATAFORM_XA_2336:
442 return "XA (2336 bytes)";
443 case TRACKDATAFORM_XA_2352:
444 return "XA (2352 bytes)";
445 case TRACKDATAFORM_XA_0:
446 return "XA (0 bytes)";
447 case TRACKDATAFORM_MODE2_2336:
448 return "Mode 2 (2336 bytes)";
449 case TRACKDATAFORM_MODE2_2352:
450 return "Mode 2 (2352 bytes)";
451 case TRACKDATAFORM_MODE2_0:
452 return "Mode 2 (0 bytes)";
453 case TRACKDATAFORM_INVALID:
454 default:
455 return "Invalid";
456 }
457}
458
459/**
460 * Converts the given subchannel data form to a string.
461 *
462 * @returns Subchannel data form as a string.
463 * @param enmSubChnDataForm The subchannel main data form.
464 */
465static const char *atapiTrackListSubChnDataFormToString(SUBCHNDATAFORM enmSubChnDataForm)
466{
467 switch (enmSubChnDataForm)
468 {
469 case SUBCHNDATAFORM_0:
470 return "0";
471 case SUBCHNDATAFORM_96:
472 return "96";
473 case SUBCHNDATAFORM_INVALID:
474 default:
475 return "Invalid";
476 }
477}
478
479/**
480 * Dump the complete track list to the release log.
481 *
482 * @returns nothing.
483 * @param pTrackList The track list to dump.
484 */
485static void atapiTrackListDump(PTRACKLIST pTrackList)
486{
487 LogRel(("Track List: cTracks=%u\n", pTrackList->cTracksCurrent));
488 for (unsigned i = 0; i < pTrackList->cTracksCurrent; i++)
489 {
490 PTRACK pTrack = &pTrackList->paTracks[i];
491
492 LogRel((" Track %u: LBAStart=%lld cSectors=%u enmMainDataForm=%s enmSubChnDataForm=%s fFlags=[%s%s%s]\n",
493 i, pTrack->iLbaStart, pTrack->cSectors, atapiTrackListMainDataFormToString(pTrack->enmMainDataForm),
494 atapiTrackListSubChnDataFormToString(pTrack->enmSubChnDataForm),
495 pTrack->fFlags & TRACK_FLAGS_UNDETECTED ? "UNDETECTED " : "",
496 pTrack->fFlags & TRACK_FLAGS_LEAD_IN ? "Lead-In " : "",
497 pTrack->fFlags & TRACK_FLAGS_LEAD_OUT ? "Lead-Out" : ""));
498 }
499}
500
501#endif /* LOG_ENABLED */
502
503DECLHIDDEN(int) ATAPIPassthroughTrackListCreateEmpty(PTRACKLIST *ppTrackList)
504{
505 int rc = VERR_NO_MEMORY;
506 PTRACKLIST pTrackList = (PTRACKLIST)RTMemAllocZ(sizeof(TRACKLIST));
507
508 if (pTrackList)
509 {
510 rc = VINF_SUCCESS;
511 *ppTrackList = pTrackList;
512 }
513
514 return rc;
515}
516
517DECLHIDDEN(void) ATAPIPassthroughTrackListDestroy(PTRACKLIST pTrackList)
518{
519 if (pTrackList->paTracks)
520 RTMemFree(pTrackList->paTracks);
521 RTMemFree(pTrackList);
522}
523
524DECLHIDDEN(void) ATAPIPassthroughTrackListClear(PTRACKLIST pTrackList)
525{
526 AssertPtrReturnVoid(pTrackList);
527
528 pTrackList->cTracksCurrent = 0;
529
530 /* Mark all tracks as undetected. */
531 for (unsigned i = 0; i < pTrackList->cTracksMax; i++)
532 pTrackList->paTracks[i].fFlags |= TRACK_FLAGS_UNDETECTED;
533}
534
535DECLHIDDEN(int) ATAPIPassthroughTrackListUpdate(PTRACKLIST pTrackList, const uint8_t *pbCDB, const void *pvBuf)
536{
537 int rc = VINF_SUCCESS;
538
539 switch (pbCDB[0])
540 {
541 case SCSI_SEND_CUE_SHEET:
542 rc = atapiTrackListUpdateFromSendCueSheet(pTrackList, pbCDB, pvBuf);
543 break;
544 case SCSI_SEND_DVD_STRUCTURE:
545 rc = atapiTrackListUpdateFromSendDvdStructure(pTrackList, pbCDB, pvBuf);
546 break;
547 case SCSI_READ_TOC_PMA_ATIP:
548 rc = atapiTrackListUpdateFromReadTocPmaAtip(pTrackList, pbCDB, pvBuf);
549 break;
550 case SCSI_READ_TRACK_INFORMATION:
551 rc = atapiTrackListUpdateFromReadTrackInformation(pTrackList, pbCDB, pvBuf);
552 break;
553 case SCSI_READ_DVD_STRUCTURE:
554 rc = atapiTrackListUpdateFromReadDvdStructure(pTrackList, pbCDB, pvBuf);
555 break;
556 case SCSI_READ_DISC_INFORMATION:
557 rc = atapiTrackListUpdateFromReadDiscInformation(pTrackList, pbCDB, pvBuf);
558 break;
559 default:
560 LogRel(("ATAPI: Invalid opcode %#x while determining media layout\n", pbCDB[0]));
561 rc = VERR_INVALID_PARAMETER;
562 }
563
564#ifdef LOG_ENABLED
565 atapiTrackListDump(pTrackList);
566#endif
567
568 return rc;
569}
570
571DECLHIDDEN(uint32_t) ATAPIPassthroughTrackListGetSectorSizeFromLba(PTRACKLIST pTrackList, uint32_t iAtapiLba)
572{
573 PTRACK pTrack = NULL;
574 uint32_t cbAtapiSector = 2048;
575
576 if (pTrackList->cTracksCurrent)
577 {
578 if ( iAtapiLba > UINT32_C(0xffff4fa1)
579 && (int32_t)iAtapiLba < -150)
580 {
581 /* Lead-In area, this is always the first entry in the cue sheet. */
582 pTrack = pTrackList->paTracks;
583 Assert(pTrack->fFlags & TRACK_FLAGS_LEAD_IN);
584 LogFlowFunc(("Selected Lead-In area\n"));
585 }
586 else
587 {
588 int64_t iAtapiLba64 = (int32_t)iAtapiLba;
589 pTrack = &pTrackList->paTracks[1];
590
591 /* Go through the track list and find the correct entry. */
592 for (unsigned i = 1; i < pTrackList->cTracksCurrent - 1; i++)
593 {
594 if (pTrack->fFlags & TRACK_FLAGS_UNDETECTED)
595 continue;
596
597 if ( pTrack->iLbaStart <= iAtapiLba64
598 && iAtapiLba64 < pTrack->iLbaStart + pTrack->cSectors)
599 break;
600
601 pTrack++;
602 }
603 }
604
605 if (pTrack)
606 {
607 switch (pTrack->enmMainDataForm)
608 {
609 case TRACKDATAFORM_CDDA:
610 case TRACKDATAFORM_MODE1_2352:
611 case TRACKDATAFORM_XA_2352:
612 case TRACKDATAFORM_MODE2_2352:
613 cbAtapiSector = 2352;
614 break;
615 case TRACKDATAFORM_MODE1_2048:
616 cbAtapiSector = 2048;
617 break;
618 case TRACKDATAFORM_CDDA_PAUSE:
619 case TRACKDATAFORM_MODE1_0:
620 case TRACKDATAFORM_XA_0:
621 case TRACKDATAFORM_MODE2_0:
622 cbAtapiSector = 0;
623 break;
624 case TRACKDATAFORM_XA_2336:
625 case TRACKDATAFORM_MODE2_2336:
626 cbAtapiSector = 2336;
627 break;
628 case TRACKDATAFORM_INVALID:
629 default:
630 AssertMsgFailed(("Invalid track data form %d\n", pTrack->enmMainDataForm));
631 }
632
633 switch (pTrack->enmSubChnDataForm)
634 {
635 case SUBCHNDATAFORM_0:
636 break;
637 case SUBCHNDATAFORM_96:
638 cbAtapiSector += 96;
639 break;
640 case SUBCHNDATAFORM_INVALID:
641 default:
642 AssertMsgFailed(("Invalid subchannel data form %d\n", pTrack->enmSubChnDataForm));
643 }
644 }
645 }
646
647 return cbAtapiSector;
648}
649
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette