IOATAPIHDCommand.cpp [plain text]
#include <IOKit/assert.h>
#include <IOKit/storage/ata/IOATAPIHDDrive.h>
#define super IOATAHDDrive
bool
IOATAPIHDDrive::selectCommandProtocol(bool isDMA)
{
super::selectCommandProtocol(isDMA);
if (isDMA)
_atapiProtocol = kATAProtocolATAPIDMA;
else
_atapiProtocol = kATAProtocolATAPIPIO;
return true;
}
void
IOATAPIHDDrive::setupPacketTaskFile(ATATaskfile * taskfile,
ATAProtocol protocol,
UInt16 byteCount)
{
bzero( taskfile, sizeof(ATATaskfile) );
taskfile->protocol = protocol;
taskfile->regmask = ATARegtoMask(kATARegATAPIDeviceSelect)
| ATARegtoMask(kATARegATAPICommand)
| ATARegtoMask(kATARegATAPIByteCountLow)
| ATARegtoMask(kATARegATAPIByteCountHigh)
| ATARegtoMask(kATARegATAPIFeatures);
taskfile->resultmask = ATARegtoMask(kATARegATAPIError);
taskfile->ataRegs[kATARegATAPIDeviceSelect] = kATAModeLBA | (_unit << 4);
taskfile->ataRegs[kATARegATAPICommand] = kATACommandATAPIPacket;
taskfile->ataRegs[kATARegATAPIByteCountLow] = byteCount & 0xff;
taskfile->ataRegs[kATARegATAPIByteCountHigh] = (byteCount >> 8) & 0xff;
taskfile->ataRegs[kATARegATAPIFeatures] = (protocol ==
kATAProtocolATAPIPIO) ?
0 : kIOATAPIFeaturesDMA;
}
IOATACommand *
IOATAPIHDDrive::atapiCommand(ATACDBInfo * packetCommand,
IOMemoryDescriptor * transferBuffer = 0)
{
ATATaskfile taskfile;
bool isWrite;
UInt32 transferLength;
IOATACommand * cmd = allocateCommand();
if (!cmd) return 0;
setupPacketTaskFile(&taskfile, _atapiProtocol, kIOATAPIMaxTransfer);
IOATAClientData * clientData = ATA_CLIENT_DATA(cmd);
assert(clientData);
clientData->buffer = transferBuffer;
cmd->setTaskfile(&taskfile);
cmd->setCDB(packetCommand);
if (transferBuffer) {
isWrite = (transferBuffer->getDirection() == kIODirectionOut);
transferLength = transferBuffer->getLength();
}
else {
isWrite = false;
transferLength = 0;
}
cmd->setPointers(transferBuffer, transferLength, isWrite);
return cmd;
}
IOATACommand *
IOATAPIHDDrive::atapiCommandReadWrite(IOMemoryDescriptor * buffer,
UInt32 block,
UInt32 nblks)
{
ATACDBInfo atapiCmd;
assert(buffer);
#ifdef DEBUG_LOG
IOLog("%s: atapiCommandReadWrite %08x (%d) %s %d %d\n",
getName(),
buffer,
buffer->getLength(),
(buffer->getDirection() == kIODirectionOut) ? "WR" :
"RD",
block,
nblks);
#endif
bzero(&atapiCmd, sizeof(atapiCmd));
atapiCmd.cdbLength = 12;
atapiCmd.cdb[0] = (buffer->getDirection() == kIODirectionOut) ?
kIOATAPICommandWrite : kIOATAPICommandRead;
atapiCmd.cdb[2] = (UInt8)(block >> 24);
atapiCmd.cdb[3] = (UInt8)(block >> 16);
atapiCmd.cdb[4] = (UInt8)(block >> 8);
atapiCmd.cdb[5] = (UInt8)(block);
atapiCmd.cdb[6] = (UInt8)(nblks >> 24);
atapiCmd.cdb[7] = (UInt8)(nblks >> 16);
atapiCmd.cdb[8] = (UInt8)(nblks >> 8);
atapiCmd.cdb[9] = (UInt8)(nblks);
return atapiCommand(&atapiCmd, buffer);
}
IOATACommand *
IOATAPIHDDrive::atapiCommandStartStopUnit(bool doStart,
bool doLoadEject,
bool immediate)
{
ATACDBInfo atapiCmd;
#ifdef DEBUG_LOG
IOLog("%s: atapiCommandStartStopUnit: %s\n", getName(),
doStart ? "start" : "stop");
#endif
bzero(&atapiCmd, sizeof(atapiCmd));
atapiCmd.cdbLength = 12;
atapiCmd.cdb[0] = kIOATAPICommandStartStopUnit;
atapiCmd.cdb[1] = immediate ? 0x01 : 0x00;
atapiCmd.cdb[4] = (doStart ? 0x01 : 0) |
(doLoadEject ? 0x02 : 0);
return atapiCommand(&atapiCmd);
}
IOATACommand *
IOATAPIHDDrive::atapiCommandFormatUnit(UInt16 interleave,
UInt8 flagBits,
UInt8 vendorBits,
IOMemoryDescriptor * formatData)
{
ATACDBInfo atapiCmd;
bzero(&atapiCmd, sizeof(atapiCmd));
atapiCmd.cdbLength = 12;
atapiCmd.cdb[0] = kIOATAPICommandFormatUnit;
atapiCmd.cdb[1] = flagBits;
atapiCmd.cdb[3] = (UInt8)(interleave >> 8);
atapiCmd.cdb[4] = (UInt8)(interleave);
atapiCmd.cdb[5] = vendorBits;
if (formatData)
atapiCmd.cdb[1] |= 0x10;
return atapiCommand(&atapiCmd, formatData);
}
IOATACommand *
IOATAPIHDDrive::atapiCommandSynchronizeCache()
{
ATACDBInfo atapiCmd;
bzero(&atapiCmd, sizeof(atapiCmd));
atapiCmd.cdbLength = 12;
atapiCmd.cdb[0] = kIOATAPICommandSynchronizeCache;
return atapiCommand(&atapiCmd);
}
IOATACommand *
IOATAPIHDDrive::atapiCommandPreventAllowRemoval(bool doLock)
{
ATACDBInfo atapiCmd;
bzero(&atapiCmd, sizeof(atapiCmd));
atapiCmd.cdbLength = 12;
atapiCmd.cdb[0] = kIOATAPICommandPreventAllow;
atapiCmd.cdb[4] = doLock ? 0x01 : 0;
return atapiCommand(&atapiCmd);
}
IOATACommand *
IOATAPIHDDrive::atapiCommandTestUnitReady()
{
ATACDBInfo atapiCmd;
#ifdef DEBUG_LOG
IOLog("%s: atapiCommandTestUnitReady\n", getName());
#endif
bzero(&atapiCmd, sizeof(atapiCmd));
atapiCmd.cdbLength = 12;
atapiCmd.cdb[0] = kIOATAPICommandTestUnitReady;
return atapiCommand(&atapiCmd);
}
IOATACommand *
IOATAPIHDDrive::atapiCommandModeSense(IOMemoryDescriptor * buffer,
UInt8 pageCode,
UInt8 pageControl)
{
ATACDBInfo atapiCmd;
assert(buffer);
bzero(&atapiCmd, sizeof(atapiCmd));
atapiCmd.cdbLength = 12;
atapiCmd.cdb[0] = kIOATAPICommandModeSense;
atapiCmd.cdb[2] = (pageCode & 0x3f) | ((pageControl & 0x3) << 6);
atapiCmd.cdb[7] = (buffer->getLength() >> 8) & 0xff;
atapiCmd.cdb[8] = buffer->getLength() & 0xff;
return atapiCommand(&atapiCmd, buffer);
}
IOATACommand *
IOATAPIHDDrive::atapiCommandModeSelect(IOMemoryDescriptor * buffer)
{
ATACDBInfo atapiCmd;
assert(buffer);
bzero(&atapiCmd, sizeof(atapiCmd));
atapiCmd.cdbLength = 12;
atapiCmd.cdb[0] = kIOATAPICommandModeSelect;
atapiCmd.cdb[1] = 0x10;
atapiCmd.cdb[7] = (buffer->getLength() >> 8) & 0xff;
atapiCmd.cdb[8] = buffer->getLength() & 0xff;
return atapiCommand(&atapiCmd, buffer);
}