ApplePMUPCCardEject.cpp [plain text]
#include "ApplePMUPCCardEject.h"
#ifdef PCMCIA_DEBUG
#define DEBUG(args...) IOLog(args)
#else
#define DEBUG(args...)
#endif
#define super IOPCCardEjectController
OSDefineMetaClassAndStructors(ApplePMUPCCardEject, IOPCCardEjectController)
#define kPMUpcmcia 0x04 // pcmcia (buttons and timeout-eject)
bool
ApplePMUPCCardEject::start(IOService * provider)
{
if (!super::start(provider)) return false;
bridge = OSDynamicCast(IOPCIDevice, provider);
if (!bridge) return false;
OSData * socketData = OSDynamicCast(OSData, bridge->getProperty("AAPL,pmu-socket-number"));
if (!socketData) return false;
pmuSocket = *(UInt32 *)socketData->getBytesNoCopy();
if (!pmuSocket) return false;
pmuDriver = waitForService(serviceMatching("ApplePMU"));
if (!pmuDriver) return false;
if (pmuDriver->callPlatformFunction("registerForPMUInterrupts", true, (void*)kPMUpcmcia,
(void*)handleInterrupt, (void*)this, NULL) != kIOReturnSuccess) {
return false;
}
DEBUG("ApplePMUPCCardEject::start for pmu socket %d was successful\n", pmuSocket);
return true;
}
void
ApplePMUPCCardEject::stop(IOService * provider)
{
DEBUG("ApplePMUPCCardEject::stop, pmu socket %d\n", pmuSocket);
if (pmuDriver) {
pmuDriver->callPlatformFunction("deRegisterClient", true, (void*)this, (void*)kPMUpcmcia, NULL, NULL);
}
super::stop(provider);
}
typedef struct SendMiscCommandParameterBlock {
int command;
IOByteCount sLength;
UInt8 * sBuffer;
IOByteCount *rLength;
UInt8 * rBuffer;
} SendMiscCommandParameterBlock;
typedef SendMiscCommandParameterBlock *SendMiscCommandParameterBlockPtr;
IOReturn
ApplePMUPCCardEject::localSendMiscCommand(int command, IOByteCount sLength, UInt8 *sBuffer)
{
if (!pmuDriver) return kIOReturnError;
SendMiscCommandParameterBlock prmBlock = {command, sLength, sBuffer, 0, 0};
return pmuDriver->callPlatformFunction("sendMiscCommand", true, (void*)&prmBlock, NULL, NULL, NULL);
}
#define kPMUDoPCMCIAEject 0x4C // eject PCMCIA card(s)
IOReturn
ApplePMUPCCardEject::ejectCard()
{
DEBUG("ApplePMUPCCardEject::ejectCard sending command\n");
IOReturn rc = localSendMiscCommand(kPMUDoPCMCIAEject, 1, &pmuSocket);
if (rc != kIOReturnSuccess) return rc;
return super::ejectCard();
}
#define kEjectRequestPMgrOp 1
#define kEjectTimeoutPMgrOp 2
#define kEjectInterruptTypeMask (kEjectRequestPMgrOp | kEjectTimeoutPMgrOp)
void
ApplePMUPCCardEject::handleInterrupt(IOService *client, UInt8 interruptMask, UInt32 length, UInt8 *buffer)
{
if (interruptMask != kPMUpcmcia) return;
ApplePMUPCCardEject *myThis = OSDynamicCast(ApplePMUPCCardEject, client);
if (!myThis) return;
if (!buffer || (length < 2)) return;
if (buffer[1] != myThis->pmuSocket) return;
DEBUG("ApplePMUPCCardEject::handleInterrupt mask = 0x%x, pmu socket = %d\n", interruptMask, myThis->pmuSocket);
DEBUG("ApplePMUPCCardEject::handleInterrupt length = %d, buffer = %x %x\n", (int)length, buffer[0], buffer[1]);
switch (buffer[0] & kEjectInterruptTypeMask) {
case kEjectRequestPMgrOp:
DEBUG("ApplePMUPCCardEject::handleInterrupt EJECTION_REQUEST\n");
(void)myThis->requestCardEjection();
break;
case kEjectTimeoutPMgrOp:
DEBUG("ApplePMUPCCardEject::handleInterrupt EJECTION_FAILED\n");
break;
default:
DEBUG("ApplePMUPCCardEject::handleInterrupt command completed cmd = 0x%x\n", buffer[0]);
break;
}
}