|
|
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: /* ! 23: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. ! 24: * ! 25: * IOATAPIHDCommand.cpp - Performs ATAPI command processing. ! 26: * ! 27: * HISTORY ! 28: * Sep 2, 1999 jliu - Ported from AppleATAPIDrive. ! 29: */ ! 30: ! 31: #include <IOKit/assert.h> ! 32: #include <IOKit/storage/ata/IOATAPIHDDrive.h> ! 33: ! 34: #define super IOATAHDDrive ! 35: ! 36: // Enable this define to generate debugging messages. ! 37: // #define DEBUG_LOG 1 ! 38: ! 39: // -------------------------------------------------------------------------- ! 40: // Returns the Command protocol to use (e.g. ataProtocolPIO, ataProtocolDMA). ! 41: ! 42: void ! 43: IOATAPIHDDrive::selectCommandProtocol(bool useDMA) ! 44: { ! 45: super::selectCommandProtocol(useDMA); ! 46: ! 47: if (useDMA) ! 48: _atapiProtocol = atapiProtocolDMA; ! 49: else ! 50: _atapiProtocol = atapiProtocolPIO; ! 51: } ! 52: ! 53: // -------------------------------------------------------------------------- ! 54: // Setup a ATATaskFile for an ATAPI packet command from the parameters given. ! 55: ! 56: void ! 57: IOATAPIHDDrive::setupPacketTaskFile(ATATaskfile * taskfile, ! 58: ATAProtocol protocol, ! 59: UInt16 byteCount) ! 60: { ! 61: taskfile->protocol = protocol; ! 62: ! 63: taskfile->regmask = ATARegtoMask(atapiRegDeviceSelect) ! 64: | ATARegtoMask(atapiRegCommand) ! 65: | ATARegtoMask(atapiRegByteCountLow) ! 66: | ATARegtoMask(atapiRegByteCountHigh) ! 67: | ATARegtoMask(atapiRegFeatures); ! 68: ! 69: taskfile->resultmask = ATARegtoMask(atapiRegError); ! 70: ! 71: taskfile->ataRegs[atapiRegDeviceSelect] = ataModeLBA | (_unit << 4); ! 72: taskfile->ataRegs[atapiRegCommand] = atapiCommandPacket; ! 73: taskfile->ataRegs[atapiRegByteCountLow] = byteCount & 0xff; ! 74: taskfile->ataRegs[atapiRegByteCountHigh] = (byteCount >> 8) & 0xff; ! 75: taskfile->ataRegs[atapiRegFeatures] = (protocol == atapiProtocolPIO) ? ! 76: 0 : kIOATAPIFeaturesDMA; ! 77: } ! 78: ! 79: // -------------------------------------------------------------------------- ! 80: // Create a generic ATAPI command object. ! 81: ! 82: IOATACommand * ! 83: IOATAPIHDDrive::atapiCommand(ATAPICmd * packetCommand, ! 84: IOMemoryDescriptor * transferBuffer = 0, ! 85: IOMemoryDescriptor * senseData = 0) ! 86: { ! 87: ATATaskfile taskfile; ! 88: bool isWrite; ! 89: UInt32 transferLength; ! 90: ! 91: IOATACommand * cmd = allocateCommand(); ! 92: if (!cmd) return 0; // error, command allocation failed. ! 93: ! 94: // Create ATA packet command. ! 95: // ! 96: setupPacketTaskFile(&taskfile, _atapiProtocol, kIOATAPIMaxTransfer); ! 97: ! 98: // Get a pointer to the client data buffer, and record parameters ! 99: // which shall be later used by the completion routine. ! 100: // ! 101: IOATAClientData * clientData = ATA_CLIENT_DATA(cmd); ! 102: assert(clientData); ! 103: ! 104: clientData->buffer = transferBuffer; ! 105: ! 106: cmd->setTaskfile(&taskfile); ! 107: cmd->setATAPICmd(packetCommand, senseData, ! 108: senseData ? senseData->getLength() : 0); ! 109: ! 110: if (transferBuffer) { ! 111: isWrite = (transferBuffer->getDirection() == kIODirectionOut); ! 112: transferLength = transferBuffer->getLength(); ! 113: } ! 114: else { ! 115: isWrite = false; ! 116: transferLength = 0; ! 117: } ! 118: cmd->setPointers(transferBuffer, transferLength, isWrite); ! 119: ! 120: return cmd; ! 121: } ! 122: ! 123: // -------------------------------------------------------------------------- ! 124: // Allocates and return an IOATACommand to perform a read/write operation. ! 125: ! 126: IOATACommand * ! 127: IOATAPIHDDrive::atapiCommandReadWrite(IOMemoryDescriptor * buffer, ! 128: UInt32 block, ! 129: UInt32 nblks) ! 130: { ! 131: ATAPICmd atapiCmd; ! 132: ! 133: assert(buffer); ! 134: ! 135: #ifdef DEBUG_LOG ! 136: IOLog("%s: atapiCommandReadWrite %08x (%d) %s %d %d\n", ! 137: getName(), ! 138: buffer, ! 139: buffer->getLength(), ! 140: (buffer->getDirection() == kIODirectionOut) ? "WR" : ! 141: "RD", ! 142: block, ! 143: nblks); ! 144: #endif ! 145: ! 146: // Create the ATAPI packet (bytes 1, 10, 11 are reserved). ! 147: // ! 148: bzero(&atapiCmd, sizeof(atapiCmd)); ! 149: ! 150: atapiCmd.cdbLength = 12; ! 151: atapiCmd.cdb[0] = (buffer->getDirection() == kIODirectionOut) ? ! 152: kIOATAPICommandWrite : kIOATAPICommandRead; ! 153: atapiCmd.cdb[2] = (block >> 24) & 0xff; ! 154: atapiCmd.cdb[3] = (block >> 16) & 0xff; ! 155: atapiCmd.cdb[4] = (block >> 8) & 0xff; ! 156: atapiCmd.cdb[5] = (block & 0xff); ! 157: atapiCmd.cdb[6] = (nblks >> 24) & 0xff; ! 158: atapiCmd.cdb[7] = (nblks >> 16) & 0xff; ! 159: atapiCmd.cdb[8] = (nblks >> 8) & 0xff; ! 160: atapiCmd.cdb[9] = (nblks & 0xff); ! 161: ! 162: return atapiCommand(&atapiCmd, buffer); ! 163: } ! 164: ! 165: // -------------------------------------------------------------------------- ! 166: // ATAPI Start/Stop Unit command (1B). ! 167: ! 168: IOATACommand * ! 169: IOATAPIHDDrive::atapiCommandStartStopUnit(IOMemoryDescriptor * senseData, ! 170: bool doStart, ! 171: bool doLoadEject, ! 172: bool immediate) ! 173: { ! 174: ATAPICmd atapiCmd; ! 175: ! 176: #ifdef DEBUG_LOG ! 177: IOLog("%s: atapiCommandStartStopUnit: %s\n", getName(), ! 178: doStart ? "start" : "stop"); ! 179: #endif ! 180: ! 181: // Create the ATAPI packet. ! 182: // ! 183: bzero(&atapiCmd, sizeof(atapiCmd)); ! 184: ! 185: atapiCmd.cdbLength = 12; ! 186: atapiCmd.cdb[0] = kIOATAPICommandStartStopUnit; ! 187: atapiCmd.cdb[1] = immediate ? 0x01 : 0x00; ! 188: atapiCmd.cdb[4] = (doStart ? 0x01 : 0) | ! 189: (doLoadEject ? 0x02 : 0); ! 190: ! 191: return atapiCommand(&atapiCmd, 0, senseData); ! 192: } ! 193: ! 194: // -------------------------------------------------------------------------- ! 195: // ATAPI Prevent/Allow medium removal command (1E). ! 196: ! 197: IOATACommand * ! 198: IOATAPIHDDrive::atapiCommandPreventAllowRemoval(bool doLock) ! 199: { ! 200: ATAPICmd atapiCmd; ! 201: ! 202: // Create the ATAPI packet. ! 203: // ! 204: bzero(&atapiCmd, sizeof(atapiCmd)); ! 205: ! 206: atapiCmd.cdbLength = 12; ! 207: atapiCmd.cdb[0] = kIOATAPICommandPreventAllow; ! 208: atapiCmd.cdb[4] = doLock ? 0x01 : 0; ! 209: ! 210: return atapiCommand(&atapiCmd); ! 211: } ! 212: ! 213: // -------------------------------------------------------------------------- ! 214: // ATAPI Test Unit Ready command (00). ! 215: ! 216: IOATACommand * ! 217: IOATAPIHDDrive::atapiCommandTestUnitReady(IOMemoryDescriptor * senseData) ! 218: { ! 219: ATAPICmd atapiCmd; ! 220: ! 221: #ifdef DEBUG_LOG ! 222: IOLog("%s: atapiCommandTestUnitReady\n", getName()); ! 223: #endif ! 224: ! 225: // Create the ATAPI packet. ! 226: // ! 227: bzero(&atapiCmd, sizeof(atapiCmd)); ! 228: ! 229: atapiCmd.cdbLength = 12; ! 230: atapiCmd.cdb[0] = kIOATAPICommandTestUnitReady; ! 231: ! 232: return atapiCommand(&atapiCmd, 0, senseData); ! 233: } ! 234: ! 235: // -------------------------------------------------------------------------- ! 236: // ATAPI Read TOC command (43). ! 237: ! 238: IOATACommand * ! 239: IOATAPIHDDrive::atapiCommandReadTOC(IOMemoryDescriptor * buffer, ! 240: tocFormat format, ! 241: UInt8 startTrackSession) ! 242: { ! 243: ATAPICmd atapiCmd; ! 244: ! 245: assert(buffer); ! 246: ! 247: // Create the ATAPI packet. ! 248: // ! 249: bzero(&atapiCmd, sizeof(atapiCmd)); ! 250: ! 251: atapiCmd.cdbLength = 12; ! 252: atapiCmd.cdb[0] = kIOATAPICommandReadTOC; ! 253: atapiCmd.cdb[1] = (format == ktocSCSI2MSF) ? 0x02 : 0x00; ! 254: atapiCmd.cdb[6] = startTrackSession; ! 255: atapiCmd.cdb[7] = (buffer->getLength() >> 8) & 0xff; ! 256: atapiCmd.cdb[8] = buffer->getLength() & 0xff; ! 257: ! 258: switch (format) { ! 259: case ktocSCSI2MSF: ! 260: case ktocSCSI2LBA: ! 261: atapiCmd.cdb[9] = 0x00; ! 262: break; ! 263: ! 264: case ktocSessionInfo: ! 265: atapiCmd.cdb[9] = 0x40; ! 266: break; ! 267: ! 268: case ktocQLeadin: ! 269: atapiCmd.cdb[9] = 0x80; ! 270: break; ! 271: } ! 272: ! 273: return atapiCommand(&atapiCmd, buffer); ! 274: } ! 275: ! 276: IOATACommand * ! 277: IOATAPIHDDrive::atapiCommandPlayAudioMSF(UInt32 starting_msf, ! 278: UInt32 ending_msf) ! 279: { ! 280: ATAPICmd atapiCmd; ! 281: ! 282: // IOLog("IOATAPIHDDrive::atapiCommandPlayAudioMSF %x %x\n",starting_msf,ending_msf); ! 283: ! 284: bzero(&atapiCmd, sizeof(atapiCmd)); ! 285: atapiCmd.cdbLength = 12; ! 286: ! 287: atapiCmd.cdb[0] = kIOATAPICommandPlayAudioMSF; ! 288: ! 289: // starting MSF address ! 290: atapiCmd.cdb[3] = (starting_msf >> 16) & 0xff; ! 291: atapiCmd.cdb[4] = (starting_msf >> 8) & 0xff; ! 292: atapiCmd.cdb[5] = (starting_msf & 0xff); ! 293: ! 294: // ending MSF address ! 295: atapiCmd.cdb[6] = (ending_msf >> 16) & 0xff; ! 296: atapiCmd.cdb[7] = (ending_msf >> 8) & 0xff; ! 297: atapiCmd.cdb[8] = (ending_msf & 0xff); ! 298: ! 299: return atapiCommand(&atapiCmd); ! 300: } ! 301: ! 302: IOATACommand * ! 303: IOATAPIHDDrive::atapiCommandPlayAudio(UInt32 starting_lba, ! 304: UInt32 length_lba) ! 305: { ! 306: ATAPICmd atapiCmd; ! 307: ! 308: // IOLog("IOATAPIHDDrive::atapiCommandPlayAudio\n"); ! 309: ! 310: bzero(&atapiCmd, sizeof(atapiCmd)); ! 311: atapiCmd.cdbLength = 12; ! 312: ! 313: atapiCmd.cdb[0] = kIOATAPICommandPlayAudio; ! 314: ! 315: // starting LBA address ! 316: atapiCmd.cdb[2] = (starting_lba >> 24) & 0xff; ! 317: atapiCmd.cdb[3] = (starting_lba >> 16) & 0xff; ! 318: atapiCmd.cdb[4] = (starting_lba >> 8) & 0xff; ! 319: atapiCmd.cdb[5] = (starting_lba & 0xff); ! 320: ! 321: // length in blocks ! 322: atapiCmd.cdb[7] = (length_lba >> 8) & 0xff; ! 323: atapiCmd.cdb[8] = (length_lba & 0xff); ! 324: ! 325: return atapiCommand(&atapiCmd); ! 326: } ! 327: ! 328: IOATACommand * ! 329: IOATAPIHDDrive::atapiCommandPauseResume(bool resume) ! 330: { ! 331: ATAPICmd atapiCmd; ! 332: ! 333: // IOLog("IOATAPIHDDrive::atapiCommandPauseResume\n"); ! 334: ! 335: bzero(&atapiCmd, sizeof(atapiCmd)); ! 336: atapiCmd.cdbLength = 12; ! 337: ! 338: atapiCmd.cdb[0] = kIOATAPICommandPauseResume; ! 339: ! 340: // set resume bit ! 341: if (resume) atapiCmd.cdb[8] = 0x01; ! 342: ! 343: return atapiCommand(&atapiCmd); ! 344: } ! 345: ! 346: IOATACommand * ! 347: IOATAPIHDDrive::atapiCommandModeSense(IOMemoryDescriptor * buffer, ! 348: UInt8 pageCode) ! 349: { ! 350: ATAPICmd atapiCmd; ! 351: ! 352: assert(buffer); ! 353: ! 354: bzero(&atapiCmd, sizeof(atapiCmd)); ! 355: ! 356: atapiCmd.cdbLength = 12; ! 357: atapiCmd.cdb[0] = kIOATAPICommandModeSense; ! 358: atapiCmd.cdb[2] = pageCode; ! 359: atapiCmd.cdb[7] = (buffer->getLength() >> 8) & 0xff; ! 360: atapiCmd.cdb[8] = buffer->getLength() & 0xff; ! 361: ! 362: return atapiCommand(&atapiCmd, buffer); ! 363: } ! 364: ! 365: IOATACommand * ! 366: IOATAPIHDDrive::atapiCommandModeSelect(IOMemoryDescriptor * buffer, ! 367: UInt8 pageCode) ! 368: { ! 369: ATAPICmd atapiCmd; ! 370: ! 371: assert(buffer); ! 372: ! 373: bzero(&atapiCmd, sizeof(atapiCmd)); ! 374: ! 375: atapiCmd.cdbLength = 12; ! 376: atapiCmd.cdb[0] = kIOATAPICommandModeSelect; ! 377: atapiCmd.cdb[1] = 0x10; ! 378: atapiCmd.cdb[2] = pageCode; ! 379: atapiCmd.cdb[7] = (buffer->getLength() >> 8) & 0xff; ! 380: atapiCmd.cdb[8] = buffer->getLength() & 0xff; ! 381: ! 382: return atapiCommand(&atapiCmd, buffer); ! 383: } ! 384: ! 385: IOATACommand * ! 386: IOATAPIHDDrive::atapiCommandReadSubChannel(IOMemoryDescriptor * buffer, ! 387: UInt8 dataFormat, ! 388: UInt8 trackNumber, ! 389: bool subQ) ! 390: { ! 391: ATAPICmd atapiCmd; ! 392: ! 393: assert(buffer); ! 394: ! 395: bzero(&atapiCmd, sizeof(atapiCmd)); ! 396: ! 397: atapiCmd.cdbLength = 12; ! 398: atapiCmd.cdb[0] = kIOATAPICommandReadSubChannel; ! 399: atapiCmd.cdb[1] = 0x02; ! 400: if (subQ) atapiCmd.cdb[2] = 0x40; ! 401: atapiCmd.cdb[3] = dataFormat; ! 402: atapiCmd.cdb[6] = trackNumber; ! 403: atapiCmd.cdb[7] = (buffer->getLength() >> 8) & 0xff; ! 404: atapiCmd.cdb[8] = buffer->getLength() & 0xff; ! 405: ! 406: return atapiCommand(&atapiCmd, buffer); ! 407: } ! 408: ! 409: IOATACommand * ! 410: IOATAPIHDDrive::atapiCommandReadHeader(IOMemoryDescriptor * buffer, ! 411: UInt32 address) ! 412: { ! 413: ATAPICmd atapiCmd; ! 414: ! 415: assert(buffer); ! 416: ! 417: bzero(&atapiCmd, sizeof(atapiCmd)); ! 418: ! 419: atapiCmd.cdbLength = 12; ! 420: atapiCmd.cdb[0] = kIOATAPICommandReadHeader; ! 421: atapiCmd.cdb[1] = 0x02; // MSF ! 422: ! 423: // starting LBA address ! 424: atapiCmd.cdb[2] = (address >> 24) & 0xff; ! 425: atapiCmd.cdb[3] = (address >> 16) & 0xff; ! 426: atapiCmd.cdb[4] = (address >> 8) & 0xff; ! 427: atapiCmd.cdb[5] = (address & 0xff); ! 428: ! 429: atapiCmd.cdb[7] = (buffer->getLength() >> 8) & 0xff; ! 430: atapiCmd.cdb[8] = buffer->getLength() & 0xff; ! 431: ! 432: return atapiCommand(&atapiCmd, buffer); ! 433: } ! 434: ! 435: IOATACommand * ! 436: IOATAPIHDDrive::atapiCommandReadCD(IOMemoryDescriptor * buffer, ! 437: UInt32 address, ! 438: UInt32 length, ! 439: UInt8 sector, ! 440: UInt8 header, ! 441: UInt8 error, ! 442: UInt8 data) ! 443: { ! 444: ! 445: ATAPICmd atapiCmd; ! 446: ! 447: assert(buffer); ! 448: ! 449: bzero(&atapiCmd, sizeof(atapiCmd)); ! 450: ! 451: atapiCmd.cdbLength = 12; ! 452: atapiCmd.cdb[0] = kIOATAPICommandReadCD; ! 453: ! 454: // expected sector type ! 455: atapiCmd.cdb[1] = (sector << 2) & 0xff; ! 456: ! 457: // starting LBA address ! 458: atapiCmd.cdb[2] = (address >> 24) & 0xff; ! 459: atapiCmd.cdb[3] = (address >> 16) & 0xff; ! 460: atapiCmd.cdb[4] = (address >> 8) & 0xff; ! 461: atapiCmd.cdb[5] = (address & 0xff); ! 462: ! 463: // transfer length ! 464: atapiCmd.cdb[6] = (buffer->getLength() >> 16) & 0xff; ! 465: atapiCmd.cdb[7] = (buffer->getLength() >> 8) & 0xff; ! 466: atapiCmd.cdb[8] = buffer->getLength() & 0xff; ! 467: ! 468: // flag bits ! 469: atapiCmd.cdb[9] = ((header << 5) | (error << 1)) & 0xff; ! 470: ! 471: // sub-channel data selection ! 472: atapiCmd.cdb[10] = (data) & 0xff; ! 473: ! 474: return atapiCommand(&atapiCmd, buffer); ! 475: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.