/*====================================================================== The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language governing rights and limitations under the License. The initial developer of the original code is David A. Hinds . Portions created by David A. Hinds are Copyright (C) 1999 David A. Hinds. All Rights Reserved. Contributor: Apple Computer, Inc. Portions © 2003 Apple Computer, Inc. All rights reserved. Alternatively, the contents of this file may be used under the terms of the GNU Public License version 2 (the "GPL"), in which case the provisions of the GPL are applicable instead of the above. If you wish to allow the use of your version of this file only under the terms of the GPL and not to allow others to use your version of this file under the MPL, indicate your decision by deleting the provisions above and replace them with the notice and other provisions required by the GPL. If you do not delete the provisions above, a recipient may use your version of this file under either the MPL or the GPL. Portions of this code are derived from: cb_enabler.c 1.31 2000/06/12 21:29:36 ======================================================================*/ #include #include #include #include #ifdef PCMCIA_DEBUG extern int ds_debug; MODULE_PARM(ds_debug, "i"); #define DEBUG(n, args...) if (ds_debug>(n)) printk(KERN_DEBUG args) #else #define DEBUG(n, args...) #endif #define CardServices cardServices #define cs_error(handle, func, ret) \ { \ error_info_t err = { func, ret }; \ CardServices(ReportError, handle, &err); \ } #undef super #define super IOPCIDevice OSDefineMetaClassAndStructors(IOCardBusDevice, IOPCIDevice); OSMetaClassDefineReservedUnused(IOCardBusDevice, 0); OSMetaClassDefineReservedUnused(IOCardBusDevice, 1); OSMetaClassDefineReservedUnused(IOCardBusDevice, 2); OSMetaClassDefineReservedUnused(IOCardBusDevice, 3); OSMetaClassDefineReservedUnused(IOCardBusDevice, 4); OSMetaClassDefineReservedUnused(IOCardBusDevice, 5); OSMetaClassDefineReservedUnused(IOCardBusDevice, 6); OSMetaClassDefineReservedUnused(IOCardBusDevice, 7); OSMetaClassDefineReservedUnused(IOCardBusDevice, 8); OSMetaClassDefineReservedUnused(IOCardBusDevice, 9); OSMetaClassDefineReservedUnused(IOCardBusDevice, 10); OSMetaClassDefineReservedUnused(IOCardBusDevice, 11); OSMetaClassDefineReservedUnused(IOCardBusDevice, 12); OSMetaClassDefineReservedUnused(IOCardBusDevice, 13); OSMetaClassDefineReservedUnused(IOCardBusDevice, 14); OSMetaClassDefineReservedUnused(IOCardBusDevice, 15); OSMetaClassDefineReservedUnused(IOCardBusDevice, 16); OSMetaClassDefineReservedUnused(IOCardBusDevice, 17); OSMetaClassDefineReservedUnused(IOCardBusDevice, 18); OSMetaClassDefineReservedUnused(IOCardBusDevice, 19); OSMetaClassDefineReservedUnused(IOCardBusDevice, 20); OSMetaClassDefineReservedUnused(IOCardBusDevice, 21); OSMetaClassDefineReservedUnused(IOCardBusDevice, 22); OSMetaClassDefineReservedUnused(IOCardBusDevice, 23); OSMetaClassDefineReservedUnused(IOCardBusDevice, 24); OSMetaClassDefineReservedUnused(IOCardBusDevice, 25); OSMetaClassDefineReservedUnused(IOCardBusDevice, 26); OSMetaClassDefineReservedUnused(IOCardBusDevice, 27); OSMetaClassDefineReservedUnused(IOCardBusDevice, 28); OSMetaClassDefineReservedUnused(IOCardBusDevice, 29); OSMetaClassDefineReservedUnused(IOCardBusDevice, 30); OSMetaClassDefineReservedUnused(IOCardBusDevice, 31); IOReturn IOCardBusDevice::setPowerState(unsigned long powerState, IOService * whatDevice) { DEBUG(1, "IOCardBusDevice:setPowerState state=%d\n", powerState); if ((powerState == kIOPCIDeviceOnState) || (powerState == 1)) { if (!(state & DEV_SUSPEND)) return IOPMAckImplied; state &= ~DEV_SUSPEND; // restore basic pci config regs parent->setDevicePowerState(this, 1); } else if (powerState == kIOPCIDeviceOffState) { if (state & DEV_SUSPEND) return IOPMAckImplied; state |= DEV_SUSPEND; // save basic pci config regs parent->setDevicePowerState(this, 0); } return IOPMAckImplied; } IOReturn IOCardBusDevice::setProperties(OSObject * properties) { OSDictionary * dict; int rc; dict = OSDynamicCast(OSDictionary, properties); if (dict) { if (IOUserClient::clientHasPrivilege(current_task(), kIOClientPrivilegeLocalUser)) { IOLog("IOCardBusDevice::setProperties: failed, the user has insufficient privileges"); return kIOReturnNotPrivileged; } if (dict->getObject("eject request")) { rc = IOPCCardBridge::requestCardEjection(parent->getProvider()); if (rc) { IOLog("IOCardBusDevice::setProperties(eject request) failed with error = %d\n", rc); return kIOReturnError; } return kIOReturnSuccess; } } return kIOReturnBadArgument; } u_int IOCardBusDevice::getState(void) { return state; } client_handle_t IOCardBusDevice::getCardServicesHandle(void) { return handle; } int IOCardBusDevice::cardServices(int func, void * arg1 /* = 0 */, void * arg2 /* = 0 */, void * arg3 /* = 0*/) { if (func < 0) return CS_UNSUPPORTED_FUNCTION; return gIOPCCardWorkLoop->runAction((IOWorkLoop::Action)gCardServicesGate, NULL, (void *)func, arg1, arg2, arg3); } int IOCardBusDevice::eventHandler(cs_event_t event, int priority, event_callback_args_t *args) { DEBUG(1, "IOCardBusDevice::eventHandler(0x%06x, %d, 0x%p)\n", event, priority, args->client_handle); IOCardBusDevice *nub = OSDynamicCast(IOCardBusDevice, (OSObject *)args->client_data); if (!nub) { IOLog("IOCardBusDevice::eventHandler: bogus event?\n"); return 0; } IOReturn ret = nub->messageClients(kIOPCCardCSEventMessage, (void *)event); if (ret && ret != kIOReturnUnsupported) { IOLog("IOCardBusDevice::eventHandler: messageClients returned %d\n", ret); return ret; } else { return 0; } } //MACOSXXX including bsd/sys/systm.h causes too much pain __BEGIN_DECLS int snprintf __P((char *, size_t, const char *, ...)); __END_DECLS bool IOCardBusDevice::bindCardServices(void) { int ret; IOLog("IOCardBusDevice: binding socket %d function %d to card services.\n", socket, function); snprintf(bindName, sizeof(bindName), "Cardbus Expert"); state = DEV_PRESENT | DEV_CONFIG_PENDING; bind_req_t bind_req; bind_req.Socket = socket; bind_req.Function = function; bind_req.dev_info = &bindName; ret = CardServices(BindDevice, &bind_req); if (ret) return false; client_reg_t client_reg; client_reg.dev_info = &bindName; client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; client_reg.event_handler = &IOCardBusDevice::eventHandler; client_reg.EventMask = CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | CS_EVENT_RESET_REQUEST | CS_EVENT_EJECTION_REQUEST; client_reg.Version = 0x0210; client_reg.event_callback_args.client_data = (void *)this; ret = CardServices(RegisterClient, &handle, &client_reg); if (ret) return false; state |= DEV_CONFIG; if (function == 0) { /* Special hook: this configures all functions on the card */ ret = CardServices(RequestIO, handle, NULL); if (ret) return false; memset(&configuration, 0, sizeof(struct config_req_t)); configuration.Vcc = 33; configuration.IntType = INT_CARDBUS; ret = ((IOPCCardBridge *)parent)->configureSocket((IOService *)this, &configuration); if (ret) return false; } state &= ~DEV_CONFIG_PENDING; return true; } bool IOCardBusDevice::unbindCardServices(void) { int ret; IOLog("IOCardBusDevice: releasing socket %d function %d from card services.\n", socket, function); if (state & DEV_CONFIG) { if (function == 0) { ret = ((IOPCCardBridge *)parent)->unconfigureSocket((IOService *)this); if (ret) return false; ret = CardServices(ReleaseIO, handle, NULL); if (ret) return false; } ret = CardServices(DeregisterClient, handle); if (ret) return false; } state &= ~DEV_CONFIG; snprintf(bindName, sizeof(bindName), "not bound"); return true; } bool IOCardBusDevice::finalize(IOOptionBits options) { unbindCardServices(); return super::finalize(options); } static UInt64 getDebugFlags(OSDictionary * props) { OSNumber *debugProp = OSDynamicCast(OSNumber, props->getObject(gIOKitDebugKey)); if (debugProp) { return debugProp->unsigned64BitValue(); } return 0; } static bool compareVersionOneInfo(OSDictionary *catalog, OSDictionary *cis, bool debug) { OSArray *version1 = OSDynamicCast(OSArray, catalog->getObject(kIOPCCardVersionOneMatchKey)); OSArray *myversion1 = OSDynamicCast(OSArray, cis->getObject(kIOPCCardVersionOneMatchKey)); if (!version1) { if (debug) IOLog("IOPCCardDevice: the VersionOneInfo match array is not of type OSArray?\n"); return false; } if (!myversion1) { if (debug) IOLog("IOPCCardDevice: there is no VersionOneInfo CIS tuple to match against?\n"); return false; } const OSString *wild = OSString::withCString("*"); int max = version1->getCount(); for (int i = 0; i < max; i++) { OSString *str = OSDynamicCast(OSString, version1->getObject(i)); if (!str) { IOLog("IOPCCardDevice: the VersionOneInfo[%d] in match array is not of type OSString?\n", i); wild->release(); return false; } if (str->isEqualTo(wild)) continue; OSString *mystr = OSDynamicCast(OSString, myversion1->getObject(i)); if (mystr && !mystr->isEqualTo(str)) { if (debug && mystr) { IOLog("IOPCCardDevice: VersionOneInfo[%d], \"%s\"(match string) != \"%s\"(CIS string).\n", i, str->getCStringNoCopy(), mystr->getCStringNoCopy()); } wild->release(); return false; } } wild->release(); if (debug) IOLog("IOPCCardDevice: VersionOneInfo matched.\n"); return true; } static bool compareFunceTuples(OSDictionary *catalog, OSDictionary *cis, bool debug) { OSNumber *funcid = OSDynamicCast(OSNumber, cis->getObject(kIOPCCardFunctionIDMatchKey)); OSArray *funceArray = OSDynamicCast(OSArray, cis->getObject(kIOPCCardFunctionExtensionMatchKey)); OSArray *matchArray = OSDynamicCast(OSArray, catalog->getObject(kIOPCCardFunctionExtensionMatchKey)); if (!funcid && !funceArray) { if (debug) IOLog("IOPCCardDevice: card doesn't appear to have any FUNCE tuples.\n"); return false; } int funceArraySize = funceArray->getCount(); if (!funceArraySize) return false; if (!matchArray) { IOLog("IOPCCardDevice: FunctionExtensionMatch is not an array?\n"); return false; } int matchArraySize = matchArray->getCount(); if (!matchArraySize || matchArraySize & 1) { IOLog("IOPCCardDevice: FunctionExtensionMatch in match array is empty or has a odd count?\n"); return false; } bool matched = false; bool matchAll = false; for (int i = 0; i < matchArraySize; i += 2) { OSData *pattern = OSDynamicCast(OSData, matchArray->getObject(i)); OSData *mask = OSDynamicCast(OSData, matchArray->getObject(i+1)); if (!pattern || !mask) { IOLog("IOPCCardDevice: FunctionExtensionMatch[%d-%d] pair is bogus?\n", i, i+1); continue; } int matchSize = pattern->getLength(); if (matchSize != (int)mask->getLength()) { IOLog("IOPCCardDevice: FunctionExtensionMatch[%d-%d] pair have different sizes?\n", i, i+1); continue; } // the function extension match property from the driver // contains the function id as the first byte of the pattern, // we need both id and extension data to make a match, the // function id must always match // the first first byte of the mask data in the match pair is // used to control if that pair must match. if it is nonzero // then that pair must match. matchSize--; for (int j=0; j < funceArraySize; j++) { OSData *funce = OSDynamicCast(OSData, funceArray->getObject(j)); int funceSize = funce->getLength(); if (funceSize < matchSize) continue; UInt8 *f = (UInt8 *)funce->getBytesNoCopy(); UInt8 *p = (UInt8 *)pattern->getBytesNoCopy(); UInt8 *m = (UInt8 *)mask->getBytesNoCopy(); // compare function id, ignore the mask if (funcid->unsigned8BitValue() != *p) break; // get type of matching from first match mask matchAll = *m != 0; // skip over function id p++; m++; matched = true; for (int k=0; k < matchSize; k++) { if ((p[k] | m[k]) != m[k]) { if (!j) IOLog("IOPCCardDevice: FunctionExtensionMatch[%d-%d] pair will never match?\n", i, i+1); matched = false; break; } if ((f[k] & m[k]) != p[k]) { matched = false; break; } } // stop looking, this pair has matched one of the function extension tuples if (matched) break; } if (matchAll && !matched) break; if (!matchAll && matched) { if (debug) IOLog("IOPCCardDevice: FunctionExtensionMatch[%d-%d] pair matched.\n", i, i+1); return true; } } if (matched) { if (debug) IOLog("IOPCCardDevice: all FunctionExtensionMatch pairs matched against function extention tuples.\n"); return true; } if (debug) IOLog("IOPCCardDevice: FUNCE tuples failed to match.\n"); return false; } bool IOCardBusDevice::matchPropertyTable(OSDictionary *table, SInt32 *score) { // only look for properties that we care about // and only return false if they don't match // in all other cases return true bool matched = true; bool debug = getDebugFlags(table) & kIOLogStart != 0; if (debug) IOLog("IOCardBusDevice::matchPropertyTable entered.\n"); if (table->getObject(kIOPCCardVersionOneMatchKey)) { matched = compareVersionOneInfo(table, getPropertyTable(), debug); return matched; } //MACOSXXX still need to do specific cis tuple matching/patching return super::matchPropertyTable(table, score); } IOService * IOCardBusDevice::matchLocation(IOService * client) { return this; } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #undef super #define super IOService OSDefineMetaClassAndStructors(IOPCCard16Device, IOService); OSMetaClassDefineReservedUnused(IOPCCard16Device, 0); OSMetaClassDefineReservedUnused(IOPCCard16Device, 1); OSMetaClassDefineReservedUnused(IOPCCard16Device, 2); OSMetaClassDefineReservedUnused(IOPCCard16Device, 3); OSMetaClassDefineReservedUnused(IOPCCard16Device, 4); OSMetaClassDefineReservedUnused(IOPCCard16Device, 5); OSMetaClassDefineReservedUnused(IOPCCard16Device, 6); OSMetaClassDefineReservedUnused(IOPCCard16Device, 7); OSMetaClassDefineReservedUnused(IOPCCard16Device, 8); OSMetaClassDefineReservedUnused(IOPCCard16Device, 9); OSMetaClassDefineReservedUnused(IOPCCard16Device, 10); OSMetaClassDefineReservedUnused(IOPCCard16Device, 11); OSMetaClassDefineReservedUnused(IOPCCard16Device, 12); OSMetaClassDefineReservedUnused(IOPCCard16Device, 13); OSMetaClassDefineReservedUnused(IOPCCard16Device, 14); OSMetaClassDefineReservedUnused(IOPCCard16Device, 15); OSMetaClassDefineReservedUnused(IOPCCard16Device, 16); OSMetaClassDefineReservedUnused(IOPCCard16Device, 17); OSMetaClassDefineReservedUnused(IOPCCard16Device, 18); OSMetaClassDefineReservedUnused(IOPCCard16Device, 19); OSMetaClassDefineReservedUnused(IOPCCard16Device, 20); OSMetaClassDefineReservedUnused(IOPCCard16Device, 21); OSMetaClassDefineReservedUnused(IOPCCard16Device, 22); OSMetaClassDefineReservedUnused(IOPCCard16Device, 23); OSMetaClassDefineReservedUnused(IOPCCard16Device, 24); OSMetaClassDefineReservedUnused(IOPCCard16Device, 25); OSMetaClassDefineReservedUnused(IOPCCard16Device, 26); OSMetaClassDefineReservedUnused(IOPCCard16Device, 27); OSMetaClassDefineReservedUnused(IOPCCard16Device, 28); OSMetaClassDefineReservedUnused(IOPCCard16Device, 29); OSMetaClassDefineReservedUnused(IOPCCard16Device, 30); OSMetaClassDefineReservedUnused(IOPCCard16Device, 31); bool IOPCCard16Device::attach(IOService * provider) { static IOPMPowerState powerStates[kIOPCCard16DevicePowerStateCount] = { { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 1, 0, IOPMSoftSleep, IOPMSoftSleep, 0, 0, 0, 0, 0, 0, 0, 0 }, { 1, 0, IOPMPowerOn, IOPMPowerOn, 0, 0, 0, 0, 0, 0, 0, 0 } }; bridge = OSDynamicCast(IOPCCardBridge, provider); if (!bridge) return false; // initialize superclass variables PMinit(); // register as controlling driver registerPowerDriver(this, (IOPMPowerState *) powerStates, kIOPCCard16DevicePowerStateCount); // join the tree provider->joinPMtree(this); if (!super::attach(provider)) { PMstop(); return false; } return true; } void IOPCCard16Device::detach(IOService * provider) { PMstop(); return super::detach(provider); } IOReturn IOPCCard16Device::setPowerState(unsigned long powerState, IOService * whatDevice) { DEBUG(1, "IOPCCard16Device:setPowerState state=%d\n", powerState); return enabler ? enabler->setPowerState(powerState, whatDevice) : IOPMAckImplied; } IOReturn IOPCCard16Device::setProperties(OSObject * properties) { OSDictionary * dict; int rc; dict = OSDynamicCast(OSDictionary, properties); if (dict) { if (dict->getObject("eject request")) { if (IOUserClient::clientHasPrivilege(current_task(), kIOClientPrivilegeLocalUser)) { IOLog("IOCardBusDevice::setProperties: failed, the user has insufficient privileges"); return kIOReturnNotPrivileged; } rc = IOPCCardBridge::requestCardEjection(bridge->getProvider()); if (rc) { IOLog("IOPCCard16Device::setProperties(eject request) failed with error = %d\n", rc); return kIOReturnError; } return kIOReturnSuccess; } } return kIOReturnBadArgument; } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ u_int IOPCCard16Device::getState(void) { return enabler ? enabler->getState() : 0; } client_handle_t IOPCCard16Device::getCardServicesHandle(void) { return handle; } int IOPCCard16Device::cardServices(int func, void * arg1 /* = 0 */, void * arg2 /* = 0 */, void * arg3 /* = 0 */) { if (func < 0) return CS_UNSUPPORTED_FUNCTION; return gIOPCCardWorkLoop->runAction((IOWorkLoop::Action)gCardServicesGate, NULL, (void *)func, arg1, arg2, arg3); } int IOPCCard16Device::eventHandler(cs_event_t event, int priority, event_callback_args_t *args) { IOReturn ret; DEBUG(1, "IOPCCard16Device::eventHandler(0x%06x, %d, 0x%p, 0x%p)\n", event, priority, args->client_handle, args->client_data); IOPCCard16Device *nub = OSDynamicCast(IOPCCard16Device, (OSObject *)args->client_data); if (!nub) { IOLog("IOPCCard16Device::eventHandler: bogus event?\n"); return 0; } // let the enabler take a first crack at looking at this event if (nub->enabler) { ret = nub->enabler->eventHandler(event, priority, args); if (ret) return 0; } ret = nub->messageClients(kIOPCCardCSEventMessage, (void *)event); if (ret && ret != kIOReturnUnsupported) { IOLog("IOPCCard16Device::eventHandler: messageClients returned %d\n", ret); return ret; } return 0; } // this is to keep bind names unique static int bindNameIndex = 0; bool IOPCCard16Device::bindCardServices(void) { int ret; IOLog("IOPCCard16Device: binding socket %d function %d to card services.\n", socket, function); snprintf(bindName, sizeof(bindName), "PCCardExpert%d", bindNameIndex++); bind_req_t bind_req; bind_req.Socket = socket; bind_req.Function = function; bind_req.dev_info = &bindName; ret = CardServices(BindDevice, &bind_req); if (ret) return false; client_reg_t client_reg; client_reg.dev_info = &bindName; client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; client_reg.event_handler = &IOPCCard16Device::eventHandler; client_reg.EventMask = CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | CS_EVENT_RESET_REQUEST | CS_EVENT_EJECTION_REQUEST; client_reg.Version = 0x0210; client_reg.event_callback_args.client_data = (void *)this; ret = CardServices(RegisterClient, &handle, &client_reg); if (ret) return false; return true; } bool IOPCCard16Device::unbindCardServices(void) { int ret; if (enabler) { enabler->detach(this); enabler->release(); enabler = 0; } IOLog("IOPCCard16Device: releasing socket %d function %d from card services.\n", socket, function); ret = CardServices(DeregisterClient, handle); if (ret) return false; snprintf(bindName, sizeof(bindName), "not bound"); return true; } bool IOPCCard16Device::finalize(IOOptionBits options) { unbindCardServices(); return super::finalize(options); } bool IOPCCard16Device::matchPropertyTable(OSDictionary *table, SInt32 *score) { // only look for properties that we care about and only return // false if they don't match, in all other cases return true bool matched = false; bool debug = getDebugFlags(table) & kIOLogStart != 0; if (debug) IOLog("IOPCCard16Device::matchPropertyTable entered.\n"); if (table->getObject(kIOPCCardVersionOneMatchKey)) { matched = compareVersionOneInfo(table, getPropertyTable(), debug); if (!matched) return false; } if (table->getObject(kIOPCCardFunctionExtensionMatchKey)) { matched = compareFunceTuples(table, getPropertyTable(), debug); if (!matched) return false; } if (table->getObject(kIOPCCardMemoryDeviceNameMatchKey)) { matched = compareProperty(table, kIOPCCardMemoryDeviceNameMatchKey); if (debug) IOLog("MemoryDeviceName %s.\n", matched ? "matched" : "didn't match"); if (!matched) return false; } if (table->getObject(kIOPCCardFunctionNameMatchKey)) { matched = compareProperty(table, kIOPCCardFunctionNameMatchKey); if (debug) IOLog("FunctionName %s.\n", matched ? "matched" : "didn't match"); if (!matched) return false; } if (table->getObject(kIOPCCardFunctionIDMatchKey)) { matched = compareProperty(table, kIOPCCardFunctionIDMatchKey); if (debug) IOLog("FunctionID %s.\n", matched ? "matched" : "didn't match"); if (!matched) return false; } //MACOSXXX still need to do specific cis tuple matching/patching if (debug) IOLog("IOPCCard16Device::matchPropertyTable %s a match.\n", matched ? "found" : "didn't find"); return true; } IOService * IOPCCard16Device::matchLocation(IOService * client) { return this; } //***************************************************************************** bool IOPCCard16Device::installEnabler(IOPCCard16Enabler *customEnabler /* = 0 */) { if (enabler) { if (!enabler->detach(this)) return false; enabler->release(); enabler = 0; } if (customEnabler) { // use the specified custom enabler enabler = OSDynamicCast(IOPCCard16Enabler, customEnabler); if (!enabler) return false; enabler->retain(); } else { // create a default enabler enabler = IOPCCard16Enabler::withDevice(this); if (!enabler) return false; } return enabler->attach(this); } bool IOPCCard16Device::configure(UInt32 index /* = 0 */) { if (!enabler) { if (!installEnabler()) return false; } return enabler->configure(index); } bool IOPCCard16Device::unconfigure(void) { bool success = true; if (enabler) { success = enabler->detach(this); enabler->release(); enabler = 0; } return success; } bool IOPCCard16Device::getConfigurationInfo(config_info_t *config) { return enabler ? enabler->getConfigurationInfo(config) : false; } UInt32 IOPCCard16Device::getWindowCount(void) { return enabler ? enabler->getWindowCount() : 0; } UInt32 IOPCCard16Device::getWindowType(UInt32 index) { return enabler ? enabler->getWindowType(index) : 0; } UInt32 IOPCCard16Device::getWindowSize(UInt32 index) { return enabler ? enabler->getWindowSize(index) : 0; } bool IOPCCard16Device::getWindowAttributes(UInt32 index, UInt32 *attributes) { return enabler ? enabler->getWindowAttributes(index, attributes) : false; } bool IOPCCard16Device::getWindowHandle(UInt32 index, window_handle_t *handle) { return enabler ? enabler->getWindowHandle(index, handle) : false; } bool IOPCCard16Device::getWindowOffset(UInt32 index, UInt32 *offset) { return enabler ? enabler->getWindowOffset(index, offset) : false; } bool IOPCCard16Device::setWindowOffset(UInt32 index, UInt32 newOffset) { return enabler ? enabler->setWindowOffset(index, newOffset) : false; } //***************************************************************************** IODeviceMemory * IOPCCard16Device::ioDeviceMemory(void) { return bridge->ioDeviceMemory(); } #ifdef __ppc__ UInt32 IOPCCard16Device::ioRead32( UInt16 offset, IOMemoryMap * map /* = 0 */) { UInt32 value; if( 0 == map) { map = ioMap; if( 0 == map) return( 0 ); } value = OSReadSwapInt32( (volatile void *)map->getVirtualAddress(), offset); eieio(); return( value ); } UInt16 IOPCCard16Device::ioRead16( UInt16 offset, IOMemoryMap * map /* = 0 */) { UInt16 value; if( 0 == map) { map = ioMap; if( 0 == map) return( 0 ); } value = OSReadSwapInt16( (volatile void *)map->getVirtualAddress(), offset); eieio(); return( value ); } UInt8 IOPCCard16Device::ioRead8( UInt16 offset, IOMemoryMap * map /* = 0 */ ) { UInt32 value; if( 0 == map) { map = ioMap; if( 0 == map) return( 0 ); } value = ((volatile UInt8 *) map->getVirtualAddress())[ offset ]; eieio(); return( value ); } void IOPCCard16Device::ioWrite32( UInt16 offset, UInt32 value, IOMemoryMap * map /* = 0 */ ) { if( 0 == map) { map = ioMap; if( 0 == map) return; } OSWriteSwapInt32( (volatile void *)map->getVirtualAddress(), offset, value); eieio(); } void IOPCCard16Device::ioWrite16( UInt16 offset, UInt16 value, IOMemoryMap * map /* = 0 */ ) { if( 0 == map) { map = ioMap; if( 0 == map) return; } OSWriteSwapInt16( (volatile void *)map->getVirtualAddress(), offset, value); eieio(); } void IOPCCard16Device::ioWrite8( UInt16 offset, UInt8 value, IOMemoryMap * map /* = 0 */ ) { if( 0 == map) { map = ioMap; if( 0 == map) return; } ((volatile UInt8 *) map->getVirtualAddress())[ offset ] = value; eieio(); } #endif //***************************************************************************** #ifdef __i386__ // MACOSXXX this file was pulled from xnu, when it gets properly // exported from the kernel framework it should be pulled from // this project. #include "pio.h" UInt32 IOPCCard16Device::ioRead32( UInt16 offset, IOMemoryMap * map /* = 0 */ ) { UInt32 value; if( 0 == map) map = ioMap; value = inl( map->getPhysicalAddress() + offset ); return( value ); } UInt16 IOPCCard16Device::ioRead16( UInt16 offset, IOMemoryMap * map /* = 0 */) { UInt16 value; if( 0 == map) map = ioMap; value = inw( map->getPhysicalAddress() + offset ); return( value ); } UInt8 IOPCCard16Device::ioRead8( UInt16 offset, IOMemoryMap * map /* = 0 */ ) { UInt32 value; if( 0 == map) map = ioMap; value = inb( map->getPhysicalAddress() + offset ); return( value ); } void IOPCCard16Device::ioWrite32( UInt16 offset, UInt32 value, IOMemoryMap * map /* = 0 */ ) { if( 0 == map) map = ioMap; outl( map->getPhysicalAddress() + offset, value ); } void IOPCCard16Device::ioWrite16( UInt16 offset, UInt16 value, IOMemoryMap * map /* = 0 */ ) { if( 0 == map) map = ioMap; outw( map->getPhysicalAddress() + offset, value ); } void IOPCCard16Device::ioWrite8( UInt16 offset, UInt8 value, IOMemoryMap * map /* = 0 */ ) { if( 0 == map) map = ioMap; outb( map->getPhysicalAddress() + offset, value ); } #endif