|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * The contents of this file constitute Original Code as defined in and ! 7: * are subject to the Apple Public Source License Version 1.1 (the ! 8: * "License"). You may not use this file except in compliance with the ! 9: * License. Please obtain a copy of the License at ! 10: * http://www.apple.com/publicsource and read it before using this file. ! 11: * ! 12: * This Original Code and all software distributed under the License are ! 13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 17: * License for the specific language governing rights and limitations ! 18: * under the License. ! 19: * ! 20: * @APPLE_LICENSE_HEADER_END@ ! 21: */ ! 22: #include <IOKit/IOLib.h> ! 23: #include <IOKit/storage/IOCDDrive.h> ! 24: #include <IOKit/storage/IOCDMedia.h> ! 25: #include "IOCDAudioNub.h" ! 26: #include <IOKit/storage/IOCDDriveNub.h> ! 27: ! 28: #define super IOHDDrive ! 29: OSDefineMetaClassAndStructors(IOCDDrive,IOHDDrive) ! 30: ! 31: /* Accept a new piece of media, doing whatever's necessary to make it ! 32: * show up properly to the system. ! 33: */ ! 34: IOReturn ! 35: IOCDDrive::acceptNewMedia(void) ! 36: { ! 37: IOReturn result; ! 38: bool ok; ! 39: int i; ! 40: UInt32 nblocks; ! 41: UInt64 nbytes; ! 42: int nDataTracks; ! 43: int nAudioTracks; ! 44: char name[128]; ! 45: bool nameSep; ! 46: ! 47: // IOLog("%s[IOCDDrive]::acceptNewMedia\n",getName()); ! 48: ! 49: /* First, we cache information about the tracks on the disc: */ ! 50: ! 51: result = cacheTocInfo(); ! 52: if (result != kIOReturnSuccess) { ! 53: IOLog("%s[IOCDDrive]::acceptNewMedia; err '%s' from cacheTocInfo\n", ! 54: getName(),stringFromReturn(result)); ! 55: return(result); ! 56: } ! 57: ! 58: /* Scan thru the track list, counting up the number of Data and Audio tracks. ! 59: * We also total up the number of blocks (bytes) for all data tracks. ! 60: */ ! 61: ! 62: nDataTracks = 0; ! 63: nAudioTracks = 0; ! 64: nblocks = 0; ! 65: ! 66: for (i = 1; i <= 99; i++) { /* only tracks 1-99, not leadout or points */ ! 67: if (trackExists(i)) { ! 68: if (trackIsData(i)) { ! 69: nDataTracks++; ! 70: nblocks += getTrackBlocks(i); ! 71: } else { ! 72: nAudioTracks++; ! 73: } ! 74: } ! 75: } ! 76: ! 77: nbytes = nblocks * 2048; ! 78: ! 79: /* Instantiate a CD Media nub above ourselves. */ ! 80: ! 81: name[0] = 0; ! 82: nameSep = false; ! 83: if (_provider->getVendorString()) { ! 84: strcat(name, _provider->getVendorString()); ! 85: nameSep = true; ! 86: } ! 87: if (_provider->getProductString()) { ! 88: if (nameSep == true) strcat(name, " "); ! 89: strcat(name, _provider->getProductString()); ! 90: nameSep = true; ! 91: } ! 92: if (nameSep == true) strcat(name, " "); ! 93: strcat(name, "Media"); ! 94: ! 95: result = instantiateMediaObject((IOMedia **)&_mediaNub,0,nbytes,2048,true,name); ! 96: ! 97: if (_mediaNub) { ! 98: ok = _mediaNub->attach(this); ! 99: } else { ! 100: IOLog("%s[IOCDDrive]::acceptNewMedia; can't instantiate CD media nub.\n",getName()); ! 101: return(result); /* give up now */ ! 102: } ! 103: if (!ok) { ! 104: IOLog("%s[IOCDDrive]::acceptNewMedia; can't attach CD media nub.\n",getName()); ! 105: _mediaNub->release(); ! 106: _mediaNub = NULL; ! 107: return(kIOReturnNoMemory); /* give up now */ ! 108: } ! 109: ! 110: /* Instantiate an audio control nub for the audio portion of the media. */ ! 111: ! 112: _acNub = new IOCDAudioNub; ! 113: if (_acNub) { ! 114: _acNub->init(); ! 115: ok = _acNub->attach(this); ! 116: if (!ok) { ! 117: IOLog("%s[IOCDDrive]::acceptNewMedia; can't attach audio control nub.\n",getName()); ! 118: _acNub->release(); ! 119: _acNub = NULL; ! 120: } ! 121: } else { ! 122: IOLog("%s[IOCDDrive]::acceptNewMedia; can't instantiate audio control nub.\n", ! 123: getName()); ! 124: } ! 125: ! 126: IOLog("%s media: %ld blocks, %ld bytes each, %d data tracks, %d audio tracks.\n", ! 127: getName(),nblocks,2048L,nDataTracks,nAudioTracks); ! 128: ! 129: /* Now that the nubs are attached, register them. */ ! 130: ! 131: _mediaNub->setProperty("audio tracks",nAudioTracks,32); ! 132: _mediaNub->setProperty("data tracks",nDataTracks,32); ! 133: _mediaNub->registerService(); ! 134: ! 135: if (_acNub) { ! 136: _acNub->registerService(); ! 137: } ! 138: ! 139: _mediaPresent = true; ! 140: ! 141: return(result); ! 142: } ! 143: ! 144: IOReturn ! 145: IOCDDrive::audioPlay(positioningType addressType,cdAddress address,audioPlayMode mode) ! 146: { ! 147: return(_CDprovider->audioPlay(addressType,address,mode)); ! 148: } ! 149: ! 150: IOReturn ! 151: IOCDDrive::audioPause(bool pause) ! 152: { ! 153: return(_CDprovider->audioPause(pause)); ! 154: } ! 155: ! 156: IOReturn ! 157: IOCDDrive::audioScan(positioningType addressType,cdAddress address,bool reverse) ! 158: { ! 159: return(_CDprovider->audioScan(addressType,address,reverse)); ! 160: } ! 161: ! 162: IOReturn ! 163: IOCDDrive::audioTrackSearch(positioningType addressType,cdAddress address, ! 164: bool startPlay,audioPlayMode mode) ! 165: { ! 166: return(_CDprovider->audioTrackSearch(addressType,address,startPlay,mode)); ! 167: } ! 168: ! 169: IOReturn ! 170: IOCDDrive::cacheTocInfo(void) ! 171: { ! 172: IOReturn result; ! 173: struct rawToc *toc; ! 174: struct tocTrackDescriptor *d; ! 175: struct tocTrackDescriptor *end; ! 176: int length; ! 177: struct trackInfo *t; ! 178: struct trackInfo *priorTrack = 0; /* =0 avoids "uninitialized" warning */ ! 179: int i; ! 180: ! 181: for (i = 0; i < kTrackEntries; i++) { /* max 99 tracks plus leadout */ ! 182: bzero((void *)&_trackInfo[i],sizeof(struct trackInfo)); ! 183: } ! 184: ! 185: toc = IONew(struct rawToc,1); ! 186: if (toc == NULL) { ! 187: return(kIOReturnNoMemory); ! 188: } ! 189: ! 190: /* Read the TOC in Lba format to get most of the info we need: */ ! 191: ! 192: result = _CDprovider->readTOC(toc,sizeof(struct rawToc),ktocSCSI2LBA); ! 193: ! 194: // IOLog("raw toc in LBA format:\n"); ! 195: // dump((char *)toc,sizeof(struct rawToc)); ! 196: ! 197: if (result != kIOReturnSuccess) { ! 198: IODelete(toc,struct rawToc,1); ! 199: return(result); ! 200: } ! 201: ! 202: /* Scan all the tracks in the TOC, setting up our track info.*/ ! 203: ! 204: d = &toc->descriptors[0]; ! 205: length = toc->header.len_hi << 8 | toc->header.len_lo - 2; /* bytes used for descriptors */ ! 206: end = &toc->descriptors[length / sizeof(struct tocTrackDescriptor)]; ! 207: ! 208: while (d < end) { ! 209: t = &_trackInfo[d->track]; ! 210: setTrackInfoEntry(d,t); ! 211: t->lba = d->lba_3 << 24 | d->lba_2 << 16 | d->lba_1 << 8 | d->lba_0; ! 212: ! 213: /* Compute the number of blocks in the prior track, now that we ! 214: * know the starting LBA of this track. ! 215: */ ! 216: if (d->track > 1) { ! 217: priorTrack->nblocks = t->lba - priorTrack->lba; ! 218: } ! 219: priorTrack = t; ! 220: d++; ! 221: } ! 222: ! 223: /* Read the TOC again, this time in MSF format, and grab the MSF info. */ ! 224: ! 225: result = _CDprovider->readTOC(toc,sizeof(struct rawToc),ktocSCSI2MSF); ! 226: if (result != kIOReturnSuccess) { ! 227: IODelete(toc,struct rawToc,1); ! 228: return(result); ! 229: } ! 230: ! 231: d = &toc->descriptors[0]; ! 232: length = toc->header.len_hi << 8 | toc->header.len_lo - 2; /* bytes used for descriptors */ ! 233: end = &toc->descriptors[length / sizeof(struct tocTrackDescriptor)]; ! 234: ! 235: while (d < end) { ! 236: t = &_trackInfo[d->track]; ! 237: // setTrackInfoEntry(d,t); ! 238: t->msf = d->lba_3 << 24 | d->lba_2 << 16 | d->lba_1 << 8 | d->lba_0; ! 239: d++; ! 240: } ! 241: ! 242: IODelete(toc,struct rawToc,1); ! 243: ! 244: _tocInfoCached = true; ! 245: ! 246: IOLog("-CD track ctl isdata lba10 lba16 M:S:F nblks10 nblks16\n"); ! 247: ! 248: #define SHOWTOC ! 249: #ifdef SHOWTOC ! 250: for (i = 1; i < kTrackEntries; i++) { ! 251: if (_trackInfo[i].track != 0) { ! 252: IOLog(" %02x %02x %s %8d %08x %02d:%02d:%02d %8d %08x\n", ! 253: _trackInfo[i].track, ! 254: _trackInfo[i].control, ! 255: _trackInfo[i].isData ? "Y" : "N", ! 256: (int)_trackInfo[i].lba, ! 257: (int)_trackInfo[i].lba, ! 258: (int)_trackInfo[i].msf >> 16 & 0xff, ! 259: (int)_trackInfo[i].msf >> 8 & 0xff, ! 260: (int)_trackInfo[i].msf & 0xff, ! 261: (int)_trackInfo[i].nblocks, ! 262: (int)_trackInfo[i].nblocks); ! 263: } ! 264: } ! 265: #endif ! 266: ! 267: return(result); ! 268: } ! 269: ! 270: /* Decommission all nubs. */ ! 271: IOReturn ! 272: IOCDDrive::decommissionMedia(bool forcible) ! 273: { ! 274: IOReturn result; ! 275: ! 276: result = kIOReturnSuccess; ! 277: ! 278: lockForArbitration(); ! 279: ! 280: if (_mediaNub) { ! 281: result = tearDown(_mediaNub); ! 282: if (forcible || (result == kIOReturnSuccess)) { ! 283: _mediaNub = 0; ! 284: } ! 285: } ! 286: ! 287: /* If it's not a forcible teardown, we only attempt to decommission the ! 288: * audio portion of the CD if all the data tracks decommissioned successfully. ! 289: */ ! 290: ! 291: if (forcible || (result == kIOReturnSuccess)) { ! 292: if (_acNub) { ! 293: result = tearDown(_acNub); ! 294: if (forcible || (result == kIOReturnSuccess)) { ! 295: _acNub = 0; ! 296: } ! 297: } ! 298: } ! 299: ! 300: if (forcible || (result == kIOReturnSuccess)) { ! 301: initMediaStates(); /* deny existence of any media */ ! 302: _tocInfoCached = false; ! 303: } ! 304: ! 305: unlockForArbitration(); ! 306: ! 307: return(result); ! 308: } ! 309: ! 310: /* We should check with other clients using the other nubs before we allow ! 311: * the client of the IOCDMediaNub to eject the media. ! 312: */ ! 313: IOReturn ! 314: IOCDDrive::ejectMedia(void) ! 315: { ! 316: /* For now, we don't check with the other clients. */ ! 317: ! 318: return(super::ejectMedia()); ! 319: } ! 320: ! 321: IOReturn ! 322: IOCDDrive::getAudioStatus(struct audioStatus *status) ! 323: { ! 324: return(_CDprovider->getAudioStatus(status)); ! 325: } ! 326: ! 327: const char * ! 328: IOCDDrive::getDeviceTypeName(void) ! 329: { ! 330: return(kDeviceTypeCDROM); ! 331: } ! 332: ! 333: UInt32 ! 334: IOCDDrive::getTrackBlocks(UInt32 track) ! 335: { ! 336: if (trackExists(track)) { ! 337: return(_trackInfo[track].nblocks); ! 338: } else { ! 339: return(0); ! 340: } ! 341: } ! 342: ! 343: UInt32 ! 344: IOCDDrive::getTrackStartBlock(UInt32 track) ! 345: { ! 346: if (trackExists(track)) { ! 347: return(_trackInfo[track].lba); ! 348: } else { ! 349: return(0); ! 350: } ! 351: } ! 352: ! 353: bool ! 354: IOCDDrive::init(OSDictionary * properties) ! 355: { ! 356: int i; ! 357: ! 358: for (i = 0; i < kTrackEntries; i++) { ! 359: bzero((void *)&_trackInfo[i],sizeof(struct trackInfo)); ! 360: } ! 361: ! 362: _acNub = NULL; ! 363: _mediaNub = NULL; ! 364: ! 365: _tocInfoCached = false; ! 366: ! 367: return(super::init(properties)); ! 368: } ! 369: ! 370: IOMedia * ! 371: IOCDDrive::instantiateDesiredMediaObject(void) ! 372: { ! 373: return(new IOCDMedia); ! 374: } ! 375: ! 376: IOReturn ! 377: IOCDDrive::readAudioData(positioningType addressType,cdAddress address, ! 378: UInt8 blockCount,UInt8 *buffer) ! 379: { ! 380: return(_CDprovider->readAudioData(addressType,address,blockCount,buffer)); ! 381: } ! 382: ! 383: IOReturn ! 384: IOCDDrive::readAudioSubcodes(positioningType addressType,cdAddress address, ! 385: UInt8 blockCount,UInt8 *buffer) ! 386: { ! 387: return(_CDprovider->readAudioSubcodes(addressType,address,blockCount,buffer)); ! 388: } ! 389: ! 390: IOReturn ! 391: IOCDDrive::readAudioVolume(UInt8 *leftVolume,UInt8 *rightVolume) ! 392: { ! 393: return(_CDprovider->readAudioVolume(leftVolume,rightVolume)); ! 394: } ! 395: ! 396: IOReturn ! 397: IOCDDrive::readAudioWithQSubcode(positioningType addressType,cdAddress address, ! 398: UInt8 blockCount,UInt8 *buffer) ! 399: { ! 400: return(_CDprovider->readAudioWithQSubcode(addressType,address,blockCount,buffer)); ! 401: } ! 402: ! 403: IOReturn ! 404: IOCDDrive::readAudioWithAllSubcodes(positioningType addressType,cdAddress address, ! 405: UInt8 blockCount,UInt8 *buffer) ! 406: { ! 407: return(_CDprovider->readAudioWithAllSubcodes(addressType,address,blockCount,buffer)); ! 408: } ! 409: ! 410: IOReturn ! 411: IOCDDrive::readEntireTOC(struct macEntireToc *buffer) ! 412: { ! 413: /* Return our cached TOC info. */ ! 414: ! 415: int i; ! 416: int out; ! 417: ! 418: bzero(buffer,sizeof(struct macEntireToc)); ! 419: ! 420: out = 0; ! 421: ! 422: /* Copy A0, A1, A2: */ ! 423: ! 424: for (i = 0xa0; i <= 0xa2; i++) { ! 425: if (_trackInfo[i].track != 0) { /* then the track exists */ ! 426: buffer->entries[out].trackPoint = _trackInfo[i].track; ! 427: buffer->entries[out].type = (trackType)_trackInfo[i].control; ! 428: buffer->entries[out].pMin = _trackInfo[i].msf >> 16; ! 429: buffer->entries[out].pSec = _trackInfo[i].msf >> 8; ! 430: buffer->entries[out].pFrame = _trackInfo[i].msf & 0xff; ! 431: ! 432: out++; ! 433: } ! 434: } ! 435: ! 436: /* Copy tracks: */ ! 437: ! 438: for (i = 1; i <= 99; i++) { ! 439: if (_trackInfo[i].track != 0) { /* then the track exists */ ! 440: buffer->entries[out].trackPoint = _trackInfo[i].track; ! 441: buffer->entries[out].type = (trackType)_trackInfo[i].control; ! 442: buffer->entries[out].pMin = _trackInfo[i].msf >> 16; ! 443: buffer->entries[out].pSec = _trackInfo[i].msf >> 8; ! 444: buffer->entries[out].pFrame = _trackInfo[i].msf & 0xff; ! 445: ! 446: out++; ! 447: } ! 448: } ! 449: return(kIOReturnSuccess); ! 450: } ! 451: ! 452: IOReturn ! 453: IOCDDrive::readHeader(UInt32 blockAddress,struct headerInfo *buffer) ! 454: { ! 455: return(_CDprovider->readHeader(blockAddress,buffer)); ! 456: } ! 457: ! 458: IOReturn ! 459: IOCDDrive::readISRC(UInt32 track,UInt8 *buffer,bool *found) ! 460: { ! 461: return(_CDprovider->readISRC(track,buffer,found)); ! 462: } ! 463: ! 464: IOReturn ! 465: IOCDDrive::readLeadOutAddress(cdAddress *buffer) ! 466: { ! 467: if (!_tocInfoCached) { ! 468: return(kIOReturnNotReady); ! 469: } ! 470: ! 471: *buffer = (cdAddress)_trackInfo[0xaa].msf; ! 472: return(kIOReturnSuccess); ! 473: } ! 474: ! 475: IOReturn ! 476: IOCDDrive::readMCN(UInt8 *buffer,bool *found) ! 477: { ! 478: return(_CDprovider->readMCN(buffer,found)); ! 479: } ! 480: ! 481: IOReturn ! 482: IOCDDrive::readQSubcodes(struct qSubcodeTocInfo *buffer,UInt32 bufSize) ! 483: { ! 484: return(_CDprovider->readQSubcodes(buffer,bufSize)); ! 485: } ! 486: ! 487: IOReturn ! 488: IOCDDrive::readSessionInfo(struct sessionInfo *info) ! 489: { ! 490: IOReturn result; ! 491: struct rawToc *toc; ! 492: struct tocTrackDescriptor *d; ! 493: ! 494: toc = IONew(struct rawToc,1); ! 495: if (toc == NULL) { ! 496: return(kIOReturnNoMemory); ! 497: } ! 498: ! 499: result = _CDprovider->readTOC(toc,sizeof(struct rawToc),ktocSessionInfo); ! 500: ! 501: if (result == kIOReturnSuccess) { ! 502: info->firstSessionNumber = toc->header.firstTrack; ! 503: info->lastSessionNumber = toc->header.lastTrack; ! 504: d = &toc->descriptors[0]; ! 505: info->trackNumber = d->track; ! 506: info->info.type = (trackType)(d->adrControl); ! 507: info->info.address = (cdAddress)( d->lba_3 << 24 | ! 508: d->lba_2 << 16 | ! 509: d->lba_1 << 8 | ! 510: d->lba_0); ! 511: } ! 512: ! 513: IODelete(toc,struct rawToc,1); ! 514: ! 515: return(result); ! 516: } ! 517: ! 518: IOReturn ! 519: IOCDDrive::readSubcodeBuffer(UInt8 *buffer,bool purge,UInt32 entryCount) ! 520: { ! 521: return(_CDprovider->readSubcodeBuffer(buffer,purge,entryCount)); ! 522: } ! 523: ! 524: IOReturn ! 525: IOCDDrive::readTheQSubcode(struct qSubcode *buffer) ! 526: { ! 527: return(_CDprovider->readTheQSubcode(buffer)); ! 528: } ! 529: ! 530: IOReturn ! 531: IOCDDrive::readTrackInfo(UInt32 startingTrack,struct trackTypeInfo *buf,UInt32 bufSize) ! 532: { ! 533: struct trackTypeInfo *end; ! 534: ! 535: if (!_tocInfoCached) { ! 536: return(kIOReturnNotReady); ! 537: } ! 538: ! 539: end = &buf[bufSize / sizeof(struct trackTypeInfo)]; ! 540: ! 541: /* Copy till we run past track 99 or the buffer runs out. */ ! 542: ! 543: while (startingTrack <= 99) { ! 544: if (buf >= end) { ! 545: return(kIOReturnSuccess); ! 546: } ! 547: if (_trackInfo[startingTrack].track != 0) { /* then the track exists */ ! 548: buf->type = (trackType)_trackInfo[startingTrack].control; ! 549: buf->address = _trackInfo[startingTrack].msf; ! 550: ! 551: buf++; ! 552: } ! 553: ! 554: startingTrack++; ! 555: } ! 556: ! 557: return(kIOReturnSuccess); ! 558: } ! 559: ! 560: IOReturn ! 561: IOCDDrive::readTrackLimits(UInt32 *first,UInt32 *last) ! 562: { ! 563: int i; ! 564: bool gotFirst; ! 565: ! 566: if (!_tocInfoCached) { ! 567: return(kIOReturnNotReady); ! 568: } ! 569: ! 570: gotFirst = false; ! 571: ! 572: for (i = 1; i < 99; i++) { ! 573: if (_trackInfo[i].track == 0) { /* track doesn't exist; skip it */ ! 574: continue; ! 575: } ! 576: ! 577: if (!gotFirst) { ! 578: *first = _trackInfo[i].track; ! 579: gotFirst = true; ! 580: } ! 581: ! 582: /* Last will keep changing till we end the loop and will end up right. */ ! 583: ! 584: *last = _trackInfo[i].track; ! 585: } ! 586: ! 587: return(kIOReturnSuccess); ! 588: } ! 589: ! 590: IOReturn ! 591: IOCDDrive::setAudioStopAddress(positioningType addressType,cdAddress address) ! 592: { ! 593: return(_CDprovider->setAudioStopAddress(addressType,address)); ! 594: } ! 595: ! 596: bool ! 597: IOCDDrive::setProvider(IOService * provider) ! 598: { ! 599: _CDprovider = OSDynamicCast(IOCDDriveNub,provider); ! 600: ! 601: if (_CDprovider == NULL) { ! 602: return(false); ! 603: } else { ! 604: super::setProvider(provider); ! 605: return(true); ! 606: } ! 607: } ! 608: ! 609: void ! 610: IOCDDrive::setTrackInfoEntry(struct tocTrackDescriptor *d,struct trackInfo *t) ! 611: { ! 612: t->track = d->track; ! 613: t->control = d->adrControl & 0xff; ! 614: if ((d->adrControl & 0xf0) == 0x10) { /* then Qsub info is present */ ! 615: t->control = d->adrControl & 0xff; ! 616: if (d->adrControl & tt_data) { /* it's a data track */ ! 617: t->isData = true; ! 618: } else { ! 619: t->isData = false; ! 620: } ! 621: } ! 622: } ! 623: ! 624: IOReturn ! 625: IOCDDrive::setVolume(UInt8 leftVolume,UInt8 rightVolume) ! 626: { ! 627: return(_CDprovider->setVolume(leftVolume,rightVolume)); ! 628: } ! 629: ! 630: bool ! 631: IOCDDrive::showStats(void) ! 632: { ! 633: return(false); ! 634: } ! 635: ! 636: bool ! 637: IOCDDrive::trackExists(UInt32 track) ! 638: { ! 639: if (_trackInfo[track].track != 0) { ! 640: return(true); ! 641: } else { ! 642: return(false); ! 643: } ! 644: } ! 645: ! 646: bool ! 647: IOCDDrive::trackIsAudio(UInt32 track) ! 648: { ! 649: if (trackExists(track)) { ! 650: return(!_trackInfo[track].isData); ! 651: } else { ! 652: return(false); ! 653: } ! 654: } ! 655: ! 656: bool ! 657: IOCDDrive::trackIsData(UInt32 track) ! 658: { ! 659: if (trackExists(track)) { ! 660: return(_trackInfo[track].isData); ! 661: } else { ! 662: return(false); ! 663: } ! 664: } ! 665: ! 666: void ! 667: IOCDDrive::dump(char *buf,int count) ! 668: { ! 669: static char string[17] = "xxxxxxxxxxxxxxxx"; ! 670: ! 671: short i; ! 672: char c; ! 673: char *cp; ! 674: ! 675: if (!count) return; ! 676: ! 677: i = 0; ! 678: cp = buf; ! 679: do { ! 680: c = *cp; ! 681: IOLog("%02x ",(c & 0xff)); ! 682: c &= 0x7f; ! 683: string[i % 16] = /* (isprint(c) || (c == ' ')) ? c : */ '.'; ! 684: if ((i % 16)==15) ! 685: IOLog("%s\n",string); ! 686: cp++; i++; ! 687: } while (--count); ! 688: ! 689: /* pad out for last line */ ! 690: if (i % 16) { /* then a shortie left */ ! 691: string[i % 16] = '\0'; ! 692: while (i % 16) { ! 693: IOLog(" "); ! 694: i++; ! 695: } ! 696: IOLog("%s\n",string); ! 697: } ! 698: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.