ApplePCCardSample.cpp [plain text]
#include <IOKit/IOService.h>
#include <IOKit/IOLib.h>
#include <IOKit/IOInterruptEventSource.h>
#include <IOKit/IOWorkLoop.h>
#include <IOKit/pccard/IOPCCard.h>
class ApplePCCardSampleEnabler : public IOPCCard16Enabler
{
OSDeclareDefaultStructors(ApplePCCardSampleEnabler);
public:
static ApplePCCardSampleEnabler * withDevice(IOPCCard16Device *provider);
virtual bool sortConfigurations(void);
};
#undef super
#define super IOPCCard16Enabler
OSDefineMetaClassAndStructors(ApplePCCardSampleEnabler, IOPCCard16Enabler);
ApplePCCardSampleEnabler *
ApplePCCardSampleEnabler::withDevice(IOPCCard16Device *provider)
{
ApplePCCardSampleEnabler *me = new ApplePCCardSampleEnabler;
if (me && !me->init(provider)) {
me->free();
return 0;
}
return me;
}
bool
ApplePCCardSampleEnabler::sortConfigurations(void)
{
IOLog("ApplePCCardSampleEnabler::sortConfigurations entered\n");
return super::sortConfigurations();
}
class ApplePCCardSample : public IOService
{
OSDeclareDefaultStructors(ApplePCCardSample)
IOPCCard16Device * nub;
IOInterruptEventSource * interruptSource;
IOWorkLoop * workLoop;
public:
virtual IOService * probe(IOService *provider, SInt32 *score);
virtual bool start(IOService * provider);
virtual void stop(IOService * provider);
virtual IOReturn message(UInt32 type, IOService * provider, void * argument = 0);
void interruptOccurred(IOInterruptEventSource * src, int i);
};
#define CardServices nub->cardServices
#undef super
#define super IOService
OSDefineMetaClassAndStructors(ApplePCCardSample, IOService);
IOService*
ApplePCCardSample::probe(IOService * provider, SInt32 * score)
{
IOLog("ApplePCCardSample::probe(provider=%p, score=0x%x) starting\n", provider, (int)*score);
nub = OSDynamicCast(IOPCCard16Device, provider);
if (!nub) return NULL;
if (!super::probe(provider, score)) return NULL;
return this;
}
bool
ApplePCCardSample::start(IOService * provider)
{
IOLog("ApplePCCardSample::start(provider=%p, this=%p) starting\n", provider, this);
nub = OSDynamicCast(IOPCCard16Device, provider);
if (!nub) {
IOLog("%s: provider is not of class IOPCCard16Device?\n", getName());
return false;
}
workLoop = getWorkLoop();
if (!workLoop) {
IOLog("%s: could not get the workLoop.\n", getName());
return false;
}
interruptSource = IOInterruptEventSource::interruptEventSource(this,
(IOInterruptEventAction)&ApplePCCardSample::interruptOccurred,
provider,
0);
if (!interruptSource) {
IOLog("%s: Failed to create interrupt event source.\n", getName());
return false;
}
if (workLoop->addEventSource(interruptSource) != kIOReturnSuccess) {
IOLog("%s: Failed to add interrupt event to workLoop.\n", getName());
interruptSource->release();
interruptSource = NULL;
workLoop->release();
workLoop = NULL;
return false;
}
workLoop->enableAllInterrupts();
cisinfo_t cisinfo;
int ret = CardServices(ValidateCIS, nub->getCardServicesHandle(), &cisinfo);
if (ret != CS_SUCCESS) {
IOLog("ApplePCCardSample: ValidateCIS failed %d.\n", ret);
stop(provider);
return false;
}
IOLog("ApplePCCardSample: ValidateCIS Chains=%d.\n", cisinfo.Chains);
#if 1
ApplePCCardSampleEnabler *customEnabler = ApplePCCardSampleEnabler::withDevice(nub);
if (!customEnabler) IOLog("%s: ApplePCCardSampleEnabler::withDevice(nub) failed\n", getName());
bool success = nub->installEnabler(customEnabler);
if (!success) IOLog("%s: nub->installEnabler(customEnabler) failed\n", getName());
customEnabler->release();
#endif
if (!nub->configure()) {
stop(provider);
return false;
}
config_info_t config;
if (!nub->getConfigurationInfo(&config)) IOLog("%s: getConfigurationInfo failed\n", getName());
IOLog("%s: the client is %svalid, ConfigBase=0x%x, BasePort1=0x%x(0x%x), BasePort2=0x%x(0x%x)\n",
getName(), (config.Attributes & CONF_VALID_CLIENT) ? "" : "not ", config.ConfigBase,
config.BasePort1, config.NumPorts1, config.BasePort2, config.NumPorts2);
unsigned windowCount = nub->getWindowCount();
for (unsigned i=0; i < windowCount; i++) {
UInt32 attributes;
if (!nub->getWindowAttributes(i, &attributes)) IOLog("%s: getWindowAttributes failed\n", getName());
IOLog("%s: mapping window index %d, size = 0x%x, attributes = 0x%x\n", getName(), i, (int)nub->getWindowSize(i), (int)attributes);
IOMemoryMap * map = nub->mapDeviceMemoryWithIndex(i);
if (!map) {
IOLog("%s: Failed to map device memory index %d.\n", getName(), i);
stop(provider);
return false;
}
if (nub->getWindowType(i) == IOPCCARD16_MEMORY_WINDOW) {
UInt32 offset;
if (!nub->getWindowOffset(i, &offset)) IOLog("%s: getWindowOffset failed\n", getName());
IOLog("%s: window %d physical 0x%x virtual 0x%x offset 0x%x length 0x%x (memory)\n",
getName(), i, (int)map->getPhysicalAddress(), map->getVirtualAddress(), (int)offset, (int)map->getLength());
IOLog("%x %x %x %x %x %x %x %x\n",
(int)OSReadSwapInt32((void *)map->getVirtualAddress(), 0), (int)OSReadSwapInt32((void *)map->getVirtualAddress(), 4),
(int)OSReadSwapInt32((void *)map->getVirtualAddress(), 8), (int)OSReadSwapInt32((void *)map->getVirtualAddress(), 12),
(int)OSReadSwapInt32((void *)map->getVirtualAddress(), 16), (int)OSReadSwapInt32((void *)map->getVirtualAddress(), 20),
(int)OSReadSwapInt32((void *)map->getVirtualAddress(), 24), (int)OSReadSwapInt32((void *)map->getVirtualAddress(), 28));
#if 1
if (!nub->setWindowOffset(i, 0x1000)) IOLog("%s: setWindowOffset failed\n", getName());
if (!nub->getWindowOffset(i, &offset)) IOLog("%s: getWindowOffset failed (case 2)\n", getName());
IOLog("%s: window %d physical 0x%x virtual 0x%x offset 0x%x length 0x%x (memory)\n",
getName(), i, (int)map->getPhysicalAddress(), map->getVirtualAddress(), (int)offset, (int)map->getLength());
IOLog("%x %x %x %x %x %x %x %x\n",
(int)OSReadSwapInt32((void *)map->getVirtualAddress(), 0), (int)OSReadSwapInt32((void *)map->getVirtualAddress(), 4),
(int)OSReadSwapInt32((void *)map->getVirtualAddress(), 8), (int)OSReadSwapInt32((void *)map->getVirtualAddress(), 12),
(int)OSReadSwapInt32((void *)map->getVirtualAddress(), 16), (int)OSReadSwapInt32((void *)map->getVirtualAddress(), 20),
(int)OSReadSwapInt32((void *)map->getVirtualAddress(), 24), (int)OSReadSwapInt32((void *)map->getVirtualAddress(), 28));
#endif
} else {
IOLog("%s: window %d physical 0x%x virtual 0x%x length 0x%x (io)\n",
getName(), i, (int)map->getPhysicalAddress(), map->getVirtualAddress(), (int)map->getLength());
if (attributes & IO_DATA_PATH_WIDTH == IO_DATA_PATH_WIDTH_16) {
int l = map->getLength(); l = l > 0x10 ? 0x10 : l;
for (int j=0; j < l; j++,j++) {
IOLog("%x ", nub->ioRead16(j, map));
}
} else {
int l = map->getLength(); l = l > 0x10 ? 0x10 : l;
for (int j=0; j < l; j++) {
IOLog("%x ", nub->ioRead8(j, map));
}
}
IOLog("\n");
}
map->release();
}
IOLog("ApplePCCardSample::start(provider=%p, this=%p) ending\n", provider, this);
return true;
}
void
ApplePCCardSample::stop(IOService * provider)
{
IOLog("ApplePCCardSample::stop(provider=%p, this=%p) stopping\n", provider, this);
if (nub != provider) {
IOLog("%s: nub != provider\n", getName());
return;
}
nub->unconfigure();
if (workLoop && interruptSource) {
workLoop->removeEventSource(interruptSource);
interruptSource->release();
interruptSource = NULL;
workLoop = NULL;
}
super::stop(provider);
}
IOReturn
ApplePCCardSample::message(UInt32 type, IOService * provider, void * argument)
{
if (type == kIOPCCardCSEventMessage) {
IOLog("ApplePCCardSample::message, nub=%p, CS event received type=0x%x.\n", nub, (unsigned int)argument);
}
return 0;
}
void
ApplePCCardSample::interruptOccurred(IOInterruptEventSource * src, int i)
{
IOLog("ApplePCCardSample::interruptOccurred, nub=%p, src=%p, i=0x%x.\n", nub, src, i);
}