/* Accept a new piece of media, doing whatever's necessary to make it
 * show up properly to the system.
 */
IOReturn
IODVDBlockStorageDriver::acceptNewMedia(void)
{
    IOReturn result;

    if (getMediaType() < kDVDMediaTypeMin || getMediaType() > kDVDMediaTypeMax) {
        return super::acceptNewMedia();
    }

    /* Obtain disc status: */

    switch (getMediaType()) {
        case kDVDMediaTypeR:
        case kDVDMediaTypeRW: {
            bool checkIsWritable = false;
            DVDDiscInfo discInfo;
            DVDRZoneInfo rzoneInfo;

            result = reportDiscInfo(&discInfo);
            if (result != kIOReturnSuccess) {
                break;
            }

            switch (discInfo.discStatus) {
                case 0x01: /* is disc incomplete? */
                    checkIsWritable = true;
                    break;
                case 0x02: /* is disc complete? */
                    checkIsWritable = discInfo.erasable ? true : false;
                    break;
            }

            /* Obtain rzone status: */

            if (checkIsWritable) {
                UInt16 rzoneLast = (discInfo.lastRZoneNumberInLastBorderMSB << 8) |
                                    discInfo.lastRZoneNumberInLastBorderLSB;

                result = reportRZoneInfo(rzoneLast,&rzoneInfo);
                if (result != kIOReturnSuccess) {
                    break;
                }

                if (discInfo.discStatus == 0x01) { /* is disc incomplete? */
                    _maxBlockNumber = max( _maxBlockNumber,
                                           max( OSSwapBigToHostInt32(rzoneInfo.rzoneStartAddress) +
                                                OSSwapBigToHostInt32(rzoneInfo.rzoneSize), 1 ) - 1 );
                }

                if (rzoneInfo.incremental) { /* is rzone incremental? */
                    _writeProtected = false;
                    break;
                }

                if (discInfo.discStatus == 0x01) { /* is disc incomplete? */
                    if (rzoneInfo.blank) { /* is rzone invisible? */
                        UInt16 rzoneFirst = (discInfo.firstRZoneNumberInLastBorderMSB << 8) |
                                             discInfo.firstRZoneNumberInLastBorderLSB;

                        if (rzoneFirst < rzoneLast) {
                            result = reportRZoneInfo(rzoneLast - 1,&rzoneInfo);
                            if (result != kIOReturnSuccess) {
                                break;
                            }

                            if (rzoneInfo.incremental) { /* is rzone incremental? */
                                _writeProtected = false;
                                break;
                            }
                        }
                    }
                }
            }

            break;
        }
        case kDVDMediaTypePlusR:
        case kDVDMediaTypeHDR: {
            DVDDiscInfo discInfo;
            DVDRZoneInfo rzoneInfo;
            IOReturn result;

            result = reportDiscInfo(&discInfo);
            if (result != kIOReturnSuccess) {
                break;
            }

            /* Obtain rzone status: */

            if (discInfo.discStatus == 0x01) { /* is disc incomplete? */
                UInt16 rzoneLast = (discInfo.lastRZoneNumberInLastBorderMSB << 8) |
                                    discInfo.lastRZoneNumberInLastBorderLSB;

                _writeProtected = false;

                result = reportRZoneInfo(rzoneLast,&rzoneInfo);
                if (result != kIOReturnSuccess) {
                    break;
                }

                _maxBlockNumber = max( _maxBlockNumber,
                                       max( OSSwapBigToHostInt32(rzoneInfo.rzoneStartAddress) +
                                            OSSwapBigToHostInt32(rzoneInfo.rzoneSize), 1 ) - 1 );
            }

            break;
        }
    }

    return IOBlockStorageDriver::acceptNewMedia();
}
예제 #2
0
/* Accept a new piece of media, doing whatever's necessary to make it
 * show up properly to the system. The arbitration lock is assumed to
 * be held during the call.
 */
IOReturn
IOCDBlockStorageDriver::acceptNewMedia(void)
{
    IOReturn result;
    int i;
    int nentries;
    int nAudioTracks;

    /* First, we cache information about the tracks on the disc: */

    result = cacheTocInfo();
    if (result != kIOReturnSuccess) {
        assert(_toc == NULL);
    }

    /* Scan thru the track list, counting up the number of Data and Audio tracks. */

    nAudioTracks = 0;

    _minBlockNumberAudio = 0xFFFFFFFF;
    _maxBlockNumberAudio = 0xFFFFFFFF;

    if (_toc) {
        nentries = CDTOCGetDescriptorCount(_toc);

        for (i = 0; i < nentries; i++) {
            UInt32 lba = CDConvertMSFToClippedLBA(_toc->descriptors[i].p);
            /* tracks 1-99, not leadout or skip intervals */
            if (_toc->descriptors[i].point <= 99 && _toc->descriptors[i].adr == 1) {
                if ((_toc->descriptors[i].control & 0x04)) {
                    /* it's a data track */
                    _maxBlockNumberAudio = min(_maxBlockNumberAudio, lba ? (lba - 1) : 0);
                } else {
                    nAudioTracks++;
                    _minBlockNumberAudio = min(_minBlockNumberAudio, lba);
                }
                /* leadout */
            } else if (_toc->descriptors[i].point == 0xA2 && _toc->descriptors[i].adr == 1) {
                _maxBlockNumber = max(_maxBlockNumber, lba ? (lba - 1) : 0);
                _maxBlockNumberAudio = min(_maxBlockNumberAudio, lba ? (lba - 1) : 0);
            }
        }

        if (_maxBlockNumberAudio < _minBlockNumberAudio) {
            _maxBlockNumberAudio = 0xFFFFFFFF;

            /* find first data track or leadout after the audio tracks */
            for (i = 0; i < nentries; i++) {
                UInt32 lba = CDConvertMSFToClippedLBA(_toc->descriptors[i].p);
                /* tracks 1-99, not leadout or skip intervals */
                if (_toc->descriptors[i].point <= 99 && _toc->descriptors[i].adr == 1) {
                    if ((_toc->descriptors[i].control & 0x04)) {
                        /* it's a data track */
                        if (lba > _minBlockNumberAudio) {
                            _maxBlockNumberAudio = min(_maxBlockNumberAudio, lba - 1);
                        }
                    }
                    /* leadout */
                } else if (_toc->descriptors[i].point == 0xA2 && _toc->descriptors[i].adr == 1) {
                    if (lba > _minBlockNumberAudio) {
                        _maxBlockNumberAudio = min(_maxBlockNumberAudio, lba - 1);
                    }
                }
            }
        }
    }

    /* Obtain disc status: */

    switch (getMediaType()) {
    case kCDMediaTypeR:
    case kCDMediaTypeRW: {
        bool checkIsWritable = false;
        CDDiscInfo discInfo;
        CDTrackInfo trackInfo;

        result = reportDiscInfo(&discInfo);
        if (result != kIOReturnSuccess) {
            break;
        }

        switch (discInfo.discStatus) {
        case 0x01: /* is disc incomplete? */
            checkIsWritable = true;
            break;
        case 0x02: /* is disc complete? */
            checkIsWritable = discInfo.erasable ? true : false;
            break;
        }

        /* Obtain track status: */

        if (checkIsWritable) {
            UInt16 trackLast = discInfo.lastTrackNumberInLastSessionLSB;

            result = reportTrackInfo(trackLast,&trackInfo);
            if (result != kIOReturnSuccess) {
                break;
            }

            if (discInfo.discStatus == 0x01) { /* is disc incomplete? */
                _maxBlockNumber = CDConvertMSFToClippedLBA(discInfo.lastPossibleStartTimeOfLeadOut);
            }

            if (trackInfo.packet) { /* is track incremental? */
                _writeProtected = false;
                break;
            }

            if (discInfo.discStatus == 0x01) { /* is disc incomplete? */
                if (trackInfo.blank) { /* is track invisible? */
                    UInt16 trackFirst = discInfo.firstTrackNumberInLastSessionLSB;

                    if (trackFirst < trackLast) {
                        result = reportTrackInfo(trackLast - 1,&trackInfo);
                        if (result != kIOReturnSuccess) {
                            break;
                        }

                        if (trackInfo.packet) { /* is track incremental? */
                            _writeProtected = false;
                            break;
                        }
                    }
                }
            }
        }

        break;
    }
    }

    /* Instantiate a media object and attach it to ourselves. */

    result = super::acceptNewMedia();
    if (result != kIOReturnSuccess) {
        return(result);			/* give up now */
    }

    return(result);
}