void FakeSMCPlugin::stop(IOService* provider) { HWSensorsDebugLog("[stop] removing handler"); if (kIOReturnSuccess != storageProvider->callPlatformFunction(kFakeSMCRemoveKeyHandler, true, this, NULL, NULL, NULL)) HWSensorsFatalLog("failed to remove handler from storage provider"); HWSensorsDebugLog("[stop] releasing tachometers"); // Release all tachometers if (OSCollectionIterator *iterator = OSCollectionIterator::withCollection(sensors)) { while (OSString *key = OSDynamicCast(OSString, iterator->getNextObject())) { if (FakeSMCSensor *sensor = getSensor(key->getCStringNoCopy())) { if (sensor->getGroup() == kFakeSMCTachometerSensor) { UInt8 index = index_of_hex_char(sensor->getKey()[1]); HWSensorsInfoLog("releasing Fan%X", index); if (!releaseFanIndex(index)) HWSensorsErrorLog("failed to release Fan index: %d", index); } } } OSSafeRelease(iterator); } HWSensorsDebugLog("[stop] releasing sensors collection"); sensors->flushCollection(); super::stop(provider); }
bool SuperIODevice::start(IOService *provider) { if (!super::start(provider)) return false; // Gigabyte mobos usualy use ITE if (OSDictionary *matching = serviceMatching(kFakeSMCService)) { if (IOService *headingProvider = waitForMatchingService(matching, kFakeSMCDefaultWaitTimeout)) { if (OSString *manufacturer = OSDynamicCast(OSString, headingProvider->getProperty(kOEMInfoManufacturer))) { if (manufacturer->isEqualTo("Gigabyte")) { if (!detectITEFamilyChip()) { UInt16 ite_id = id; if (!detectWinbondFamilyChip()) { HWSensorsFatalLog("found unsupported chip! ITE sequence ID=0x%x, Winbond sequence ID=0x%x", ite_id, id); return false; } } } } } OSSafeRelease(matching); } // Other vendors usualy use Winbond family chipsets if (model == 0) { if (!detectWinbondFamilyChip()) { UInt16 wnbnd_id = id; if (!detectITEFamilyChip()) { HWSensorsFatalLog("found unsupported chip! ITE sequence ID=0x%x, Winbond sequence ID=0x%x", id, wnbnd_id); return false; } } } HWSensorsInfoLog("found %s %s on port=0x%x address=0x%x", vendor, superio_get_model_name(model), port, address); char string[128]; snprintf(string, sizeof(string), "%s,%s", vendor, superio_get_model_name(model)); setName(string); //setProperty("name", &string, (UInt32)strlen(string) + 1); setProperty(kSuperIOHWMAddress, address, 16); setProperty(kSuperIOControlPort, port, 8); setProperty(kSuperIOModelValue, model, 16); setProperty(kSuperIOModelName, superio_get_model_name(model)); setProperty(kSuperIOVendorName, vendor); setProperty(kSuperIODeviceID, OSData::withBytes(&id, sizeof(id))); registerService(); return true; }
FakeSMCKey *FakeSMCKeyStore::addKeyWithHandler(const char *name, const char *type, unsigned char size, FakeSMCKeyHandler *handler) { if (FakeSMCKey *key = getKey(name)) { FakeSMCKeyHandler *existedHandler = key->getHandler(); if (handler->getProbeScore() < existedHandler->getProbeScore()) { HWSensorsErrorLog("key %s already handled with prioritized handler %s", name, existedHandler ? existedHandler->getName() : "*Unreferenced*"); return 0; } else { HWSensorsInfoLog("key %s handler %s has been replaced with new prioritized handler %s", name, existedHandler ? existedHandler->getName() : "*Unreferenced*", handler ? handler->getName() : "*Unreferenced*"); } key->setType(type); key->setSize(size); key->setHandler(handler); return key; } HWSensorsDebugLog("adding key %s with handler, type: %s, size: %d", name, type, size); if (FakeSMCKey *key = FakeSMCKey::withHandler(name, type, size, handler)) { //KEYSLOCK; keys->setObject(key); //KEYSUNLOCK; updateKeyCounterKey(); return key; } HWSensorsErrorLog("failed to create key %s", name); return 0; }
UInt32 FakeSMCDevice::loadKeysFromNVRAM() { UInt32 count = 0; // Find driver and load keys from NVRAM if (OSDictionary *matching = serviceMatching("IODTNVRAM")) { if (IODTNVRAM *nvram = OSDynamicCast(IODTNVRAM, waitForMatchingService(matching, 1000000000ULL * 15))) { useNVRAM = true; if ((genericNVRAM = (0 == strncmp(nvram->getName(), "AppleNVRAM", sizeof("AppleNVRAM"))))) HWSensorsInfoLog("fallback to generic NVRAM methods"); OSSerialize *s = OSSerialize::withCapacity(0); // Workaround for IODTNVRAM->getPropertyTable returns IOKitPersonalities instead of NVRAM properties dictionary if (nvram->serializeProperties(s)) { if (OSDictionary *props = OSDynamicCast(OSDictionary, OSUnserializeXML(s->text()))) { if (OSCollectionIterator *iterator = OSCollectionIterator::withCollection(props)) { size_t prefix_length = strlen(kFakeSMCKeyPropertyPrefix); char name[5]; name[4] = 0; char type[5]; type[4] = 0; while (OSString *property = OSDynamicCast(OSString, iterator->getNextObject())) { const char *buffer = static_cast<const char *>(property->getCStringNoCopy()); if (property->getLength() >= prefix_length + 1 + 4 + 1 + 0 && 0 == strncmp(buffer, kFakeSMCKeyPropertyPrefix, prefix_length)) { if (OSData *data = OSDynamicCast(OSData, props->getObject(property))) { strncpy(name, buffer + prefix_length + 1, 4); // fakesmc-key-???? -> strncpy(type, buffer + prefix_length + 1 + 4 + 1, 4); // fakesmc-key-xxxx-???? -> if (addKeyWithValue(name, type, data->getLength(), data->getBytesNoCopy())) { HWSensorsDebugLog("key %s of type %s loaded from NVRAM", name, type); count++; } } } } OSSafeRelease(iterator); } OSSafeRelease(props); } } OSSafeRelease(s); OSSafeRelease(nvram); } else { HWSensorsWarningLog("NVRAM is unavailable"); } OSSafeRelease(matching); } return count; }
bool FakeSMC::start(IOService *provider) { if (!super::start(provider)) return false; int arg_value = 1; // Check if we have SMC already if (OSDictionary *matching = serviceMatching("IOACPIPlatformDevice")) { if (OSIterator *iterator = getMatchingServices(matching)) { OSString *smcNameProperty = OSString::withCString("APP0001"); while (IOService *service = (IOService*)iterator->getNextObject()) { OSObject *serviceNameProperty = service->getProperty("name"); if (serviceNameProperty && serviceNameProperty->isEqualTo(smcNameProperty)) { HWSensorsFatalLog("SMC device detected, will not create another one"); return false; } } OSSafeRelease(iterator); } OSSafeRelease(matching); } if (!smcDevice->initAndStart(provider, this)) { HWSensorsInfoLog("failed to initialize SMC device"); return false; } registerService(); // Load keys from NVRAM if (PE_parse_boot_argn("-fakesmc-use-nvram", &arg_value, sizeof(arg_value))) { if (UInt32 count = smcDevice->loadKeysFromNVRAM()) HWSensorsInfoLog("%d key%s loaded from NVRAM", count, count == 1 ? "" : "s"); else HWSensorsInfoLog("NVRAM will be used to store system written keys..."); } return true; }
bool GmaSensors::managedStart(IOService *provider) { IOPhysicalAddress bar = (IOPhysicalAddress)((pciDevice->configRead32(kMCHBAR)) & ~0xf); HWSensorsDebugLog("Fx3100: register space=%08lx", (long unsigned int)bar); if(IOMemoryDescriptor * theDescriptor = IOMemoryDescriptor::withPhysicalAddress (bar, 0x2000, kIODirectionOutIn)) { if ((mmio = theDescriptor->map())) { mmio_base = (volatile UInt8 *)mmio->getVirtualAddress(); /*HWSensorsDebugLog("MCHBAR mapped"); for (int i = 0; i < 0x2f; i += 16) { HWSensorsDebugLog("%04lx: ", (long unsigned int)i+0x1000); for (int j=0; j<16; j += 1) { HWSensorsDebugLog("%02lx ", (long unsigned int)INVID8(i+j+0x1000)); } HWSensorsDebugLog(""); }*/ } else { HWSensorsInfoLog("MCHBAR failed to map"); return false; } } enableExclusiveAccessMode(); //Find card number gpuIndex = takeVacantGPUIndex(); if (gpuIndex < 0) { HWSensorsFatalLog("failed to obtain vacant GPU index"); return false; } char key[5]; snprintf(key, 5, KEY_FORMAT_GPU_PROXIMITY_TEMPERATURE, gpuIndex); if (!addSensor(key, TYPE_SP78, 2, kFakeSMCTemperatureSensor, 0)) { HWSensorsFatalLog("failed to register temperature sensor"); releaseGPUIndex(gpuIndex); gpuIndex = -1; return false; } disableExclusiveAccessMode(); registerService(); return true; }
bool TZSensors::start(IOService * provider) { if (!super::start(provider)) return false; acpiDevice = (IOACPIPlatformDevice *)provider; if (!acpiDevice) { HWSensorsFatalLog("ACPI device not ready"); return false; } if (OSDictionary *configuration = getConfigurationNode()) { OSBoolean* disable = OSDynamicCast(OSBoolean, configuration->getObject("DisableDevice")); if (disable && disable->isTrue()) return false; } // On some computers (eg. RehabMan's ProBook 4530s), the system will hang on startup // if kernel cache is used, because of the early call to updateTemperatures and/or // updateTachometers. At least that is the case with an SSD and a valid pre-linked // kernel, along with kernel cache enabled. This 1000ms sleep seems to fix the problem, // enabling a clean boot with TZSensors enabled. // // On the ProBook this is the case with both TZSensors and PTIDSensors, although // PTIDSensors can be avoided by using DropSSDT=Yes (because PTID device is in an SSDT) // // And in the case of TZSensors it even happens (intermittently) without kernel cache. IOSleep(1000); OSObject *object = NULL; if(kIOReturnSuccess == acpiDevice->evaluateObject("_TMP", &object) && object) { for (UInt8 i = 0; i < 0xf; i++) { char key[5]; snprintf(key, 5, KEY_FORMAT_THERMALZONE_TEMPERATURE, i); if (!isKeyHandled(key)) { if (addSensor(key, TYPE_SP78, TYPE_SPXX_SIZE, kFakeSMCTemperatureSensor, 0)) { break; } } } } registerService(); HWSensorsInfoLog("started on %s", acpiDevice->getName()); return true; }
bool FakeSMCKeyStore::start(IOService *provider) { if (!super::start(provider)) return false; // Try to obtain OEM info from Clover EFI if (IORegistryEntry* platformNode = fromPath("/efi/platform", gIODTPlane)) { if (OSData *data = OSDynamicCast(OSData, platformNode->getProperty("OEMVendor"))) { if (OSString *vendor = OSString::withCString((char*)data->getBytesNoCopy())) { if (OSString *manufacturer = getManufacturerNameFromOEMName(vendor)) { this->setProperty(kOEMInfoManufacturer, manufacturer); OSSafeReleaseNULL(manufacturer); } //OSSafeReleaseNULL(vendor); } //OSSafeReleaseNULL(data); } if (OSData *data = OSDynamicCast(OSData, platformNode->getProperty("OEMBoard"))) { if (OSString *product = OSString::withCString((char*)data->getBytesNoCopy())) { this->setProperty(kOEMInfoProduct, product); //OSSafeReleaseNULL(product); } //OSSafeReleaseNULL(data); } } if ((!getProperty(kOEMInfoProduct) || !getProperty(kOEMInfoManufacturer)) && !setOemProperties(this)) { HWSensorsErrorLog("failed to get OEM info from Chameleon/Chimera or Clover EFI, platform profiles will be unavailable"); } if (OSString *manufacturer = OSDynamicCast(OSString, getProperty(kOEMInfoManufacturer)) ) { this->addKeyWithValue("HWS0", TYPE_CH8, manufacturer->getLength(), manufacturer->getCStringNoCopy()); } if (OSString *product = OSDynamicCast(OSString, getProperty(kOEMInfoProduct)) ) { this->addKeyWithValue("HWS1", TYPE_CH8, product->getLength(), product->getCStringNoCopy()); } IOService::publishResource(kFakeSMCKeyStoreService, this); registerService(); HWSensorsInfoLog("started"); return true; }
bool FakeSMCKey::setHandler(FakeSMCKeyHandler *newHandler) { if (handler && newHandler) { if (newHandler->getProbeScore() < handler->getProbeScore()) { HWSensorsErrorLog("key %s already handled with prioritized handler %s", key, handler->getName()); return false; } else { handler = newHandler; HWSensorsInfoLog("key %s handler %s has been replaced with new prioritized handler %s", key, handler->getName(), newHandler->getName()); } } return false; }
bool FakeSMC::start(IOService *provider) { if (!super::start(provider)) return false; if (!smcDevice->init(provider, OSDynamicCast(OSDictionary, getProperty("Configuration")))) { HWSensorsInfoLog("failed to initialize SMC device"); return false; } smcDevice->registerService(); registerService(); return true; }
bool FakeSMC::init(OSDictionary *dictionary) { if (!super::init(dictionary)) return false; IOLog("HWSensors Project Copyright %d netkas, slice, usr-sse2, kozlek, navi, THe KiNG. All rights reserved.\n",HWSENSORS_LASTYEAR); //HWSensorsInfoLog("Opensource SMC device emulator. Copyright 2009 netkas. All rights reserved."); if (!(smcDevice = new FakeSMCDevice)) { HWSensorsInfoLog("failed to create SMC device"); return false; } if (!setOemProperties(this)) HWSensorsWarningLog("failed to read OEM data, specific OEM configuration will be unavailable"); return true; }
IOReturn GPUSensors::probeEvent() { HWSensorsDebugLog("Probe event..."); if (acceleratorLoadedCheck()) { releaseTimerEventSource; onAcceleratorFound(pciDevice); } else if (probeCounter++ == (1000.0f / (float)kGPUSensorsAcceleratorWaitCycle) * 45) { releaseTimerEventSource; onTimeoutExceeded(pciDevice); } else { if (probeCounter > 0 && !(probeCounter % ((int)(1000.0f / (float)kGPUSensorsAcceleratorWaitCycle) * 15))) HWSensorsInfoLog("still waiting for accelerator to start..."); timerEventSource->setTimeoutMS(kGPUSensorsAcceleratorWaitCycle); } return kIOReturnSuccess; }
IOReturn GPUSensors::probeEvent() { HWSensorsDebugLog("Probe event..."); bool acceleratorFound = false; if (OSDictionary *matching = serviceMatching("IOAccelerator")) { if (OSIterator *iterator = getMatchingServices(matching)) { while (IOService *service = (IOService*)iterator->getNextObject()) { if (pciDevice == service->getParentEntry(gIOServicePlane)) { acceleratorFound = true; break; } } OSSafeRelease(iterator); } OSSafeRelease(matching); } if (acceleratorFound) { releaseTimerEventSource; onAcceleratorFound(pciDevice); } else if (probeCounter++ == 45) { releaseTimerEventSource; onTimeoutExceeded(pciDevice); } else { if (probeCounter > 0 && !(probeCounter % 15)) HWSensorsInfoLog("still waiting for IOAccelerator to start..."); timerEventSource->setTimeoutMS(1000); } return kIOReturnSuccess; }
FakeSMCKey *FakeSMCDevice::addKeyWithHandler(const char *name, const char *type, unsigned char size, IOService *handler) { KEYSLOCK; FakeSMCKey *key; if ((key = getKey(name))) { IOService *existedHandler = key->getHandler(); if (getHandlingPriority(handler) < getHandlingPriority(existedHandler)) { HWSensorsErrorLog("key %s already handled with prioritized handler %s", name, existedHandler ? existedHandler->getName() : "*Unreferenced*"); key = 0; } else { HWSensorsInfoLog("key %s handler %s has been replaced with new prioritized handler %s", name, existedHandler ? existedHandler->getName() : "*Unreferenced*", handler ? handler->getName() : "*Unreferenced*"); key->setType(type); key->setSize(size); key->setHandler(handler); } } else { FakeSMCDebugLog("adding key %s with handler, type: %s, size: %d", name, type, size); if ((key = FakeSMCKey::withHandler(name, type, size, handler))) { keys->setObject(key); updateKeyCounterKey(); } else { HWSensorsErrorLog("failed to create key %s", name); } } KEYSUNLOCK; return key; }
IOReturn GPUSensors::probeEvent() { HWSensorsDebugLog("Probe event..."); if (probIsAcceleratorAlreadyLoaded()) { releaseTimerEventSource(timerEventSource); if (!(timerEventSource = IOTimerEventSource::timerEventSource( this, OSMemberFunctionCast(IOTimerEventSource::Action, this, &GPUSensors::delayedStartEvent)))) { HWSensorsFatalLog("failed to initialize delayed startup timer event source"); return false; } if (kIOReturnSuccess != workloop->addEventSource(timerEventSource)) { HWSensorsFatalLog("failed to add delayed startup timer event source into workloop"); timerEventSource->release(); return false; } // Wait a little before start timerEventSource->setTimeoutMS(kGPUSensorsAcceleratorDelayTime); } else if (probeCounter++ == (1000.0f / (kGPUSensorsAcceleratorWaitCycle * 45.0f))) { releaseTimerEventSource(timerEventSource); HWSensorsInfoLog("still waiting for IOAccelerator to start..."); onTimeoutExceeded(pciDevice); } else { // if (probeCounter > 0 && !(probeCounter % ((int)(1000.0f / (float)kGPUSensorsAcceleratorWaitCycle) * 15))) // HWSensorsInfoLog("still waiting for accelerator to start..."); timerEventSource->setTimeoutMS(kGPUSensorsAcceleratorWaitCycle); } return kIOReturnSuccess; }
IOService* X3100monitor::probe(IOService *provider, SInt32 *score) { if (super::probe(provider, score) != this) return 0; if (!(VCard = (IOPCIDevice*)provider)) return 0; IOPhysicalAddress bar = (IOPhysicalAddress)((VCard->configRead32(kMCHBAR)) & ~0xf); HWSensorsDebugLog("Fx3100: register space=%08lx", (long unsigned int)bar); if(IOMemoryDescriptor * theDescriptor = IOMemoryDescriptor::withPhysicalAddress (bar, 0x2000, kIODirectionOutIn)) { if ((mmio = theDescriptor->map())) { mmio_base = (volatile UInt8 *)mmio->getVirtualAddress(); /*HWSensorsDebugLog("MCHBAR mapped"); for (int i = 0; i < 0x2f; i += 16) { HWSensorsDebugLog("%04lx: ", (long unsigned int)i+0x1000); for (int j=0; j<16; j += 1) { HWSensorsDebugLog("%02lx ", (long unsigned int)INVID8(i+j+0x1000)); } HWSensorsDebugLog(""); }*/ } else { HWSensorsInfoLog("MCHBAR failed to map"); return 0; } } return this; }
bool PTIDSensors::start(IOService * provider) { if (!super::start(provider)) return false; acpiDevice = (IOACPIPlatformDevice *)provider; if (!acpiDevice) { HWSensorsFatalLog("ACPI device not ready"); return false; } // Update timers temperaturesLastUpdated = ptimer_read() - NSEC_PER_SEC; tachometersLastUpdated = temperaturesLastUpdated; acpiDevice->evaluateInteger("IVER", &version); if (version == 0) { OSString *name = OSDynamicCast(OSString, provider->getProperty("name")); if (name && name->isEqualTo("INT3F0D")) version = 0x30000; else return false; } setProperty("version", version, 64); // Parse sensors switch (version) { case 0x30000: { OSObject *object = NULL; // Temperatures if(kIOReturnSuccess == acpiDevice->evaluateObject("TSDL", &object) && object) { OSArray *description = OSDynamicCast(OSArray, object); HWSensorsDebugLog("Parsing temperatures..."); for (UInt32 index = 1; index < description->getCount(); index += 2) { parseTemperatureName(OSDynamicCast(OSString, description->getObject(index)), (index - 1) / 2); } } else HWSensorsErrorLog("failed to evaluate TSDL table"); // Tachometers if(kIOReturnSuccess == acpiDevice->evaluateObject("OSDL", &object) && object) { OSArray *description = OSDynamicCast(OSArray, object); HWSensorsDebugLog("Parsing tachometers..."); for (UInt32 index = 2; index < description->getCount(); index += 3) { parseTachometerName(OSDynamicCast(OSString, description->getObject(index)), OSDynamicCast(OSString, description->getObject(index - 1)), (index - 2) / 3); } } else HWSensorsErrorLog("failed to evaluate OSDL table"); break; } case 0x20001: { OSObject *object = NULL; // Temperatures if(kIOReturnSuccess == acpiDevice->evaluateObject("TMPV", &object) && object) { OSArray *description = OSDynamicCast(OSArray, object); for (UInt32 index = 1; index < description->getCount(); index += 3) { parseTemperatureName(OSDynamicCast(OSString, description->getObject(index)), index + 1); } } else HWSensorsErrorLog("failed to evaluate TMPV table"); // Tachometers if(kIOReturnSuccess == acpiDevice->evaluateObject("OSDV", &object) && object) { OSArray *description = OSDynamicCast(OSArray, object); for (UInt32 index = 2; index < description->getCount(); index += 4) { parseTachometerName(OSDynamicCast(OSString, description->getObject(index)), OSDynamicCast(OSString, description->getObject(index - 1)), index + 1); } } else HWSensorsErrorLog("failed to evaluate OSDV table"); break; } default: HWSensorsFatalLog("usupported interface version: 0x%x", (unsigned int)version); return false; } registerService(); HWSensorsInfoLog("started"); return true; }
FakeSMCKey *FakeSMCDevice::addKeyWithValue(const char *name, const char *type, unsigned char size, const void *value) { IORecursiveLockLock(device_lock); FakeSMCKey* key; if ((key = getKey(name))) { if (value) { key->setType(type); key->setSize(size); key->setValueFromBuffer(value, size); } if (debug) { if (strncmp("NATJ", key->getKey(), 5) == 0) { UInt8 val = *(UInt8*)key->getValue(); switch (val) { case 0: HWSensorsInfoLog("Ninja Action Timer Job: do nothing"); break; case 1: HWSensorsInfoLog("Ninja Action Timer Job: force shutdown to S5"); break; case 2: HWSensorsInfoLog("Ninja Action Timer Job: force restart"); break; case 3: HWSensorsInfoLog("Ninja Action Timer Job: force startup"); break; default: break; } } else if (strncmp("NATi", key->getKey(), 5) == 0) { UInt16 val = *(UInt16*)key->getValue(); HWSensorsInfoLog("Ninja Action Timer is set to %d", val); } else if (strncmp("MSDW", key->getKey(), 5) == 0) { UInt8 val = *(UInt8*)key->getValue(); switch (val) { case 0: HWSensorsInfoLog("display is now asleep"); break; case 1: HWSensorsInfoLog("display is now awake"); break; default: break; } } } FakeSMCDebugLog("updating value for key %s, type: %s, size: %d", name, type, size); } else { FakeSMCDebugLog("adding key %s with value, type: %s, size: %d", name, type, size); if ((key = FakeSMCKey::withValue(name, type, size, value))) { keys->setObject(key); updateKeyCounterKey(); } } IORecursiveLockUnlock(device_lock); if (!key) HWSensorsErrorLog("failed to create key %s", name); return key; }
bool SuperIODevice::start(IOService *provider) { if (!super::start(provider)) return false; /*for (int i = 0; i < 2; i++) { i386_ioport_t port = kSuperIOPorts[i]; winbond_family_enter(port); UInt16 id = superio_listen_port_word(port, kSuperIOChipIDRegister); UInt16 model = 0; UInt8 ldn = 0; const char* vendor = ""; switch (id) { // Fintek case F71858: model = id; ldn = kF71858HardwareMonitorLDN; vendor = "Fintek"; break; case F71862: case F71868A: case F71869: case F71869A: case F71882: case F71889AD: case F71889ED: case F71889F: case F71808E: model = id; ldn = kFintekITEHardwareMonitorLDN; vendor = "Fintek"; break; default: switch (id >> 8) { // Winbond case 0x52: switch (id & 0xff) { case 0x17: case 0x3A: case 0x41: model = W83627HF; ldn = kWinbondHardwareMonitorLDN; vendor = "Winbond"; break; } break; case 0x82: switch (id & 0xf0) { case 0x80: model = W83627THF; ldn = kWinbondHardwareMonitorLDN; vendor = "Winbond"; break; } break; case 0x85: switch (id & 0xff) { case 0x41: model = W83687THF; ldn = kWinbondHardwareMonitorLDN; vendor = "Winbond"; break; } break; case 0x88: switch (id & 0xf0) { case 0x50: case 0x60: model = W83627EHF; ldn = kWinbondHardwareMonitorLDN; vendor = "Winbond"; break; } break; case 0xA0: switch (id & 0xf0) { case 0x20: model = W83627DHG; ldn = kWinbondHardwareMonitorLDN; vendor = "Winbond"; break; } break; case 0xA5: switch (id & 0xf0) { case 0x10: model = W83667HG; ldn = kWinbondHardwareMonitorLDN; vendor = "Winbond"; break; } break; case 0xB0: switch (id & 0xf0) { case 0x70: model = W83627DHGP; ldn = kWinbondHardwareMonitorLDN; vendor = "Winbond"; break; } break; case 0xB3: switch (id & 0xf0) { case 0x50: model = W83667HGB; ldn = kWinbondHardwareMonitorLDN; vendor = "Winbond"; break; } break; // Nuvoton case 0xB4: switch (id & 0xf0) { case 0x70: model = NCT6771F; ldn = kWinbondHardwareMonitorLDN; vendor = "Nuvoton"; break; } break; case 0xC3: switch (id & 0xf0) { case 0x30: model = NCT6776F; ldn = kWinbondHardwareMonitorLDN; vendor = "Nuvoton"; break; } break; case 0xC5: switch (id & 0xf0) { case 0x60: model = NCT6779D; ldn = kWinbondHardwareMonitorLDN; vendor = "Nuvoton"; break; } break; } break; } UInt16 address = 0; UInt16 verify = 0; if (model != 0 && ldn != 0) { superio_select_logical_device(port, ldn); address = superio_listen_port_word(port, kSuperIOBaseAddressRegister); IOSleep(50); verify = superio_listen_port_word(port, kSuperIOBaseAddressRegister); winbond_family_exit(port); if (address != verify) continue; // some Fintek chips have address register offset 0x05 added already if ((address & 0x07) == 0x05) address &= 0xFFF8; if (address < 0x100 || (address & 0xF007) != 0) continue; } else { winbond_family_exit(port); IOSleep(50); // IT87XX can enter only on port 0x2E if (port == 0x2E) { ite_family_enter(port); id = superio_listen_port_word(port, kSuperIOChipIDRegister); ldn = 0; vendor = ""; switch (id) { case IT8512F: case IT8712F: case IT8716F: case IT8718F: case IT8720F: case IT8721F: case IT8726F: case IT8728F: case IT8752F: case IT8771E: case IT8772E: model = id; ldn = kFintekITEHardwareMonitorLDN; vendor = "ITE"; break; } if (model != 0 && ldn != 0) { superio_select_logical_device(port, ldn); address = superio_listen_port_word(port, kSuperIOBaseAddressRegister); IOSleep(50); verify = superio_listen_port_word(port, kSuperIOBaseAddressRegister); ite_family_exit(port); if (address != verify || address < 0x100 || (address & 0xF007) != 0) continue; } else { ite_family_exit(port); continue; } } }*/ // Gigabyte mobos usualy use ITE if (IOService *headingProvider = waitForService(serviceMatching(kFakeSMCService))) { if (OSString *manufacturer = OSDynamicCast(OSString, headingProvider->getProperty(kOEMInfoManufacturer))) { if (manufacturer->isEqualTo("Gigabyte")) { if (!detectITEFamilyChip()) { UInt16 ite_id = id; if (!detectWinbondFamilyChip()) { HWSensorsFatalLog("found unsupported ship ITE sequence ID=0x%x, Winbond sequence ID=0x%x", ite_id, id); return false; } } } } } // Other vendors usualy use Winbond family chipsets if (model == 0) { if (!detectWinbondFamilyChip()) { UInt16 wnbnd_id = id; if (!detectITEFamilyChip()) { HWSensorsFatalLog("found unsupported ship ITE sequence ID=0x%x, Winbond sequence ID=0x%x", id, wnbnd_id); return false; } } } HWSensorsInfoLog("found %s %s on port=0x%x address=0x%x", vendor, superio_get_model_name(model), port, address); char string[128]; snprintf(string, sizeof(string), "%s,%s", vendor, superio_get_model_name(model)); setName(string); //setProperty("name", &string, (UInt32)strlen(string) + 1); setProperty(kSuperIOHWMAddress, address, 16); setProperty(kSuperIOControlPort, port, 8); setProperty(kSuperIOModelValue, model, 16); setProperty(kSuperIOModelName, superio_get_model_name(model)); setProperty(kSuperIOVendorName, vendor); setProperty(kSuperIODeviceID, OSData::withBytes(&id, sizeof(id))); registerService(); return true; }
bool FakeSMCDevice::initAndStart(IOService *platform, IOService *provider) { if (!provider || !super::init(platform, 0, 0)) return false; OSDictionary *properties = OSDynamicCast(OSDictionary, provider->getProperty("Configuration")); if (!properties) return false; status = (ApleSMCStatus *) IOMalloc(sizeof(struct AppleSMCStatus)); bzero((void*)status, sizeof(struct AppleSMCStatus)); interrupt_handler = 0; keys = OSArray::withCapacity(1); types = OSDictionary::withCapacity(0); exposedValues = OSDictionary::withCapacity(0); // Add fist key - counter key keyCounterKey = FakeSMCKey::withValue(KEY_COUNTER, TYPE_UI32, TYPE_UI32_SIZE, "\0\0\0\1"); keys->setObject(keyCounterKey); fanCounterKey = FakeSMCKey::withValue(KEY_FAN_NUMBER, TYPE_UI8, TYPE_UI8_SIZE, "\0"); keys->setObject(fanCounterKey); if (!gKeysLock) gKeysLock = IORecursiveLockAlloc(); // Load preconfigured keys FakeSMCDebugLog("loading keys..."); if (OSDictionary *dictionary = OSDynamicCast(OSDictionary, properties->getObject("Keys"))) { if (OSIterator *iterator = OSCollectionIterator::withCollection(dictionary)) { while (const OSSymbol *key = (const OSSymbol *)iterator->getNextObject()) { if (OSArray *array = OSDynamicCast(OSArray, dictionary->getObject(key))) { if (OSIterator *aiterator = OSCollectionIterator::withCollection(array)) { OSString *type = OSDynamicCast(OSString, aiterator->getNextObject()); OSData *value = OSDynamicCast(OSData, aiterator->getNextObject()); if (type && value) addKeyWithValue(key->getCStringNoCopy(), type->getCStringNoCopy(), value->getLength(), value->getBytesNoCopy()); OSSafeRelease(aiterator); } } key = 0; } OSSafeRelease(iterator); } HWSensorsInfoLog("%d preconfigured key%s added", keys->getCount(), keys->getCount() == 1 ? "" : "s"); } else { HWSensorsWarningLog("no preconfigured keys found"); } // Load wellknown type names FakeSMCDebugLog("loading types..."); if (OSDictionary *dictionary = OSDynamicCast(OSDictionary, properties->getObject("Types"))) { if (OSIterator *iterator = OSCollectionIterator::withCollection(dictionary)) { while (OSString *key = OSDynamicCast(OSString, iterator->getNextObject())) { if (OSString *value = OSDynamicCast(OSString, dictionary->getObject(key))) { types->setObject(key, value); } } OSSafeRelease(iterator); } } // Set Clover platform keys if (OSDictionary *dictionary = OSDynamicCast(OSDictionary, properties->getObject("Clover"))) { UInt32 count = 0; if (IORegistryEntry* cloverPlatformNode = fromPath("/efi/platform", gIODTPlane)) { if (OSIterator *iterator = OSCollectionIterator::withCollection(dictionary)) { while (OSString *name = OSDynamicCast(OSString, iterator->getNextObject())) { if (OSData *data = OSDynamicCast(OSData, cloverPlatformNode->getProperty(name))) { if (OSArray *items = OSDynamicCast(OSArray, dictionary->getObject(name))) { OSString *key = OSDynamicCast(OSString, items->getObject(0)); OSString *type = OSDynamicCast(OSString, items->getObject(1)); if (addKeyWithValue(key->getCStringNoCopy(), type->getCStringNoCopy(), data->getLength(), data->getBytesNoCopy())) count++; } } } OSSafeRelease(iterator); } } if (count) HWSensorsInfoLog("%d key%s exported by Clover EFI", count, count == 1 ? "" : "s"); } // Start SMC device if (!super::start(platform)) return false; this->setName("SMC"); FakeSMCSetProperty("name", "APP0001"); if (OSString *compatibleKey = OSDynamicCast(OSString, properties->getObject("smc-compatible"))) FakeSMCSetProperty("compatible", (const char *)compatibleKey->getCStringNoCopy()); else FakeSMCSetProperty("compatible", "smc-napa"); if (!this->setProperty("_STA", (unsigned long long)0x0000000b, 32)) { HWSensorsErrorLog("failed to set '_STA' property"); return false; } if (OSBoolean *debugKey = OSDynamicCast(OSBoolean, properties->getObject("debug"))) debug = debugKey->getValue(); else debug = false; if (OSBoolean *traceKey = OSDynamicCast(OSBoolean, properties->getObject("trace"))) trace = traceKey->getValue(); else trace = false; IODeviceMemory::InitElement rangeList[1]; rangeList[0].start = 0x300; rangeList[0].length = 0x20; // rangeList[1].start = 0xfef00000; // rangeList[1].length = 0x10000; if(OSArray *array = IODeviceMemory::arrayFromList(rangeList, 1)) { this->setDeviceMemory(array); OSSafeRelease(array); } else { HWSensorsFatalLog("failed to create Device memory array"); return false; } OSArray *controllers = OSArray::withCapacity(1); if(!controllers) { HWSensorsFatalLog("failed to create controllers array"); return false; } controllers->setObject((OSSymbol *)OSSymbol::withCStringNoCopy("io-apic-0")); OSArray *specifiers = OSArray::withCapacity(1); if(!specifiers) { HWSensorsFatalLog("failed to create specifiers array"); return false; } UInt64 line = 0x06; OSData *tmpData = OSData::withBytes(&line, sizeof(line)); if (!tmpData) { HWSensorsFatalLog("failed to create specifiers data"); return false; } specifiers->setObject(tmpData); this->setProperty(gIOInterruptControllersKey, controllers) && this->setProperty(gIOInterruptSpecifiersKey, specifiers); this->attachToParent(platform, gIOServicePlane); registerService(); HWSensorsInfoLog("successfully initialized"); return true; }
FakeSMCKey *FakeSMCDevice::addKeyWithValue(const char *name, const char *type, unsigned char size, const void *value) { if (FakeSMCKey *key = getKey(name)) { if (type && strncmp(type, key->getType(), 4) == 0) { key->setType(type); } if (value) { key->setSize(size); key->setValueFromBuffer(value, size); } if (debug) { if (strncmp("NATJ", key->getKey(), 5) == 0) { UInt8 val = *(UInt8*)key->getValue(); switch (val) { case 0: HWSensorsInfoLog("Ninja Action Timer Job: do nothing"); break; case 1: HWSensorsInfoLog("Ninja Action Timer Job: force shutdown to S5"); break; case 2: HWSensorsInfoLog("Ninja Action Timer Job: force restart"); break; case 3: HWSensorsInfoLog("Ninja Action Timer Job: force startup"); break; default: break; } } else if (strncmp("NATi", key->getKey(), 5) == 0) { UInt16 val = *(UInt16*)key->getValue(); HWSensorsInfoLog("Ninja Action Timer is set to %d", val); } else if (strncmp("MSDW", key->getKey(), 5) == 0) { UInt8 val = *(UInt8*)key->getValue(); switch (val) { case 0: HWSensorsInfoLog("display is now asleep"); break; case 1: HWSensorsInfoLog("display is now awake"); break; default: break; } } } FakeSMCDebugLog("value updated for key %s, type: %s, size: %d", name, type, size); return key; } FakeSMCDebugLog("adding key %s with value, type: %s, size: %d", name, type, size); OSString *wellKnownType = 0; if (!type) wellKnownType = OSDynamicCast(OSString, types->getObject(name)); if (FakeSMCKey *key = FakeSMCKey::withValue(name, type ? type : wellKnownType ? wellKnownType->getCStringNoCopy() : 0, size, value)) { KEYSLOCK; keys->setObject(key); KEYSUNLOCK; updateKeyCounterKey(); return key; } HWSensorsErrorLog("failed to create key %s", name); return 0; }
bool PTIDSensors::start(IOService * provider) { if (!super::start(provider)) return false; acpiDevice = (IOACPIPlatformDevice *)provider; if (!acpiDevice) { HWSensorsFatalLog("ACPI device not ready"); return false; } // On some computers (eg. RehabMan's ProBook 4530s), the system will hang on startup // if kernel cache is used, because of the early call to updateTemperatures and/or // updateTachometers. At least that is the case with an SSD and a valid pre-linked // kernel, along with kernel cache enabled. This 1000ms sleep seems to fix the problem, // enabling a clean boot with PTIDSensors enabled. IOSleep(1000); // Update timers temperaturesLastUpdated = ptimer_read() - NSEC_PER_SEC; tachometersLastUpdated = temperaturesLastUpdated; acpiDevice->evaluateInteger("IVER", &version); if (version == 0) { OSString *name = OSDynamicCast(OSString, provider->getProperty("name")); if (name && name->isEqualTo("INT3F0D")) version = 0x30000; else return false; } setProperty("version", version, 64); // Parse sensors switch (version) { case 0x30000: { OSObject *object = NULL; // Temperatures if(kIOReturnSuccess == acpiDevice->evaluateObject("TSDL", &object) && object) { if (OSArray *description = OSDynamicCast(OSArray, object)) { HWSensorsDebugLog("Parsing temperatures..."); int count = description->getCount(); for (int i = 1; i < count; i += 2) { parseTemperatureName(OSDynamicCast(OSString, description->getObject(i)), i/2); } } } else HWSensorsErrorLog("failed to evaluate TSDL table"); // Tachometers if(kIOReturnSuccess == acpiDevice->evaluateObject("OSDL", &object) && object) { if (OSArray *description = OSDynamicCast(OSArray, object)) { HWSensorsDebugLog("Parsing tachometers..."); int count = description->getCount(); for (int i = 2; i < count; i += 3) { parseTachometerName(OSDynamicCast(OSString, description->getObject(i)), OSDynamicCast(OSString, description->getObject(i-1)), i/3); } } } else HWSensorsErrorLog("failed to evaluate OSDL table"); break; } case 0x20001: { OSObject *object = NULL; // Temperatures if (kIOReturnSuccess == acpiDevice->evaluateObject("TMPV", &object) && object) { if (OSArray *description = OSDynamicCast(OSArray, object)) { HWSensorsDebugLog("Parsing temperatures..."); int count = description->getCount(); for (int i = 1; i < count; i += 3) { parseTemperatureName(OSDynamicCast(OSString, description->getObject(i)), i+1); } } } else HWSensorsErrorLog("failed to evaluate TMPV table"); // Tachometers if (kIOReturnSuccess == acpiDevice->evaluateObject("OSDV", &object) && object) { if (OSArray *description = OSDynamicCast(OSArray, object)) { HWSensorsDebugLog("Parsing tachometers..."); int count = description->getCount(); for (int i = 2; i < count; i += 4) { parseTachometerName(OSDynamicCast(OSString, description->getObject(i)), OSDynamicCast(OSString, description->getObject(i-1)), i+1); } } } else HWSensorsErrorLog("failed to evaluate OSDV table"); break; } default: HWSensorsFatalLog("usupported interface version: 0x%x", (UInt32)version); return false; } registerService(); HWSensorsInfoLog("started"); return true; }
bool SuperIOMonitor::start(IOService *provider) { if (!super::start(provider)) return false; OSNumber *number = OSDynamicCast(OSNumber, provider->getProperty(kSuperIOHWMAddress)); if (!number || !(address = number->unsigned16BitValue())) { HWSensorsWarningLog("wrong address provided"); return false; } number = OSDynamicCast(OSNumber, provider->getProperty(kSuperIOControlPort)); if (!number || !(port = number->unsigned8BitValue())) { HWSensorsWarningLog("wrong port provided"); return false; } number = OSDynamicCast(OSNumber, provider->getProperty(kSuperIOModelValue)); if (!number || !(model = number->unsigned16BitValue())) { HWSensorsWarningLog("wrong model provided"); return false; } OSString *string = OSDynamicCast(OSString, provider->getProperty(kSuperIOModelName)); if (!string || !(modelName = string->getCStringNoCopy())) { HWSensorsWarningLog("wrong model name provided"); return false; } string = OSDynamicCast(OSString, provider->getProperty(kSuperIOVendorName)); if (!string || !(vendorName = string->getCStringNoCopy())) { HWSensorsWarningLog("wrong vendor name provided"); return false; } if (!initialize()) return false; OSString *manufacturerName = OSDynamicCast(OSString, provider->getProperty("mb-manufacturer")); OSString *productName = OSDynamicCast(OSString, provider->getProperty("mb-product")); OSDictionary *configuration = NULL; if (OSDictionary *list = OSDynamicCast(OSDictionary, getProperty("Sensors Configuration"))) { if (OSDictionary *manufacturer = OSDynamicCast(OSDictionary, list->getObject(manufacturerName))) if (!(configuration = lookupConfiguration(manufacturer, productName))) if (!(configuration = lookupConfiguration(manufacturer, modelName))) configuration = lookupConfiguration(manufacturer, "Default"); if (!configuration && !(configuration = lookupConfiguration(list, modelName))) configuration = lookupConfiguration(list, "Default"); } if (configuration) { addTemperatureSensors(configuration); addVoltageSensors(configuration); addTachometerSensors(configuration); registerService(); } else HWSensorsWarningLog("no sensors configuration provided"); HWSensorsInfoLog("started"); return true; }
bool LPCSensors::start(IOService *provider) { if (!super::start(provider)) return false; OSNumber *number = OSDynamicCast(OSNumber, provider->getProperty(kSuperIOHWMAddress)); if (!number || !(address = number->unsigned16BitValue())) { HWSensorsFatalLog("wrong address provided"); return false; } number = OSDynamicCast(OSNumber, provider->getProperty(kSuperIOControlPort)); if (!number || !(port = number->unsigned8BitValue())) { HWSensorsFatalLog("wrong port provided"); return false; } number = OSDynamicCast(OSNumber, provider->getProperty(kSuperIOModelValue)); if (!number || !(model = number->unsigned16BitValue())) { HWSensorsFatalLog("wrong model provided"); return false; } OSString *string = OSDynamicCast(OSString, provider->getProperty(kSuperIOModelName)); if (!string || !(modelName = string->getCStringNoCopy())) { HWSensorsFatalLog("wrong model name provided"); return false; } string = OSDynamicCast(OSString, provider->getProperty(kSuperIOVendorName)); if (!string || !(vendorName = string->getCStringNoCopy())) { HWSensorsFatalLog("wrong vendor name provided"); return false; } if (!initialize()) return false; OSString *modelString = OSString::withCString(modelName); if (OSDictionary *configuration = getConfigurationNode(modelString)) { addTemperatureSensors(configuration); addVoltageSensors(configuration); addTachometerSensors(configuration); } else HWSensorsWarningLog("no platform profile provided"); OSSafeReleaseNULL(modelString); // woorkloop if (!(workloop = getWorkLoop())) { HWSensorsFatalLog("Failed to obtain workloop"); return false; } if (!(timerEventSource = IOTimerEventSource::timerEventSource(this, OSMemberFunctionCast(IOTimerEventSource::Action, this, &LPCSensors::woorkloopTimerEvent)))) { HWSensorsFatalLog("failed to initialize timer event source"); return false; } if (kIOReturnSuccess != workloop->addEventSource(timerEventSource)) { HWSensorsFatalLog("failed to add timer event source into workloop"); return false; } // two power states - off and on static const IOPMPowerState powerStates[2] = { { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 1, IOPMDeviceUsable, IOPMPowerOn, IOPMPowerOn, 0, 0, 0, 0, 0, 0, 0, 0 } }; // register interest in power state changes PMinit(); provider->joinPMtree(this); registerPowerDriver(this, (IOPMPowerState *)powerStates, 2); registerService(); HWSensorsInfoLog("started"); return true; }
bool FakeSMC::start(IOService *provider) { if (!super::start(provider)) return false; if (!(keyStore = OSDynamicCast(FakeSMCKeyStore, waitForMatchingService(serviceMatching(kFakeSMCKeyStoreService), kFakeSMCDefaultWaitTimeout)))) { HWSensorsInfoLog("still waiting for FakeSMCKeyStore..."); return false; // HWSensorsDebugLog("creating FakeSMCKeyStore"); // // if (!(keyStore = new FakeSMCKeyStore)) { // HWSensorsInfoLog("failed to create FakeSMCKeyStore"); // return false; // } // // HWSensorsDebugLog("initializing FakeSMCKeyStore"); // // if (keyStore->initAndStart(this, configuration)) { // keyStore->setProperty("IOUserClientClass", "FakeSMCKeyStoreUserClient"); // } // else { // keyStore->release(); // HWSensorsFatalLog("failed to initialize FakeSMCKeyStore device"); // return false; // } } // if (IOService *resources = waitForMatchingService(serviceMatching("IOResources"), 0)) // this->attach(resources); OSDictionary *configuration = OSDynamicCast(OSDictionary, getProperty("Configuration")); // Load preconfigured keys HWSensorsDebugLog("loading keys..."); if (!configuration) { HWSensorsFatalLog("no configuration node found!"); return false; } if (UInt32 count = keyStore->addKeysFromDictionary(OSDynamicCast(OSDictionary, configuration->getObject("Keys")))) { HWSensorsInfoLog("%d preconfigured key%s added", count, count == 1 ? "" : "s"); } else { HWSensorsWarningLog("no preconfigured keys found"); } // Load wellknown type names HWSensorsDebugLog("loading types..."); keyStore->addWellKnownTypesFromDictionary(OSDynamicCast(OSDictionary, configuration->getObject("Types"))); // Set Clover platform keys if (OSDictionary *dictionary = OSDynamicCast(OSDictionary, configuration->getObject("Clover"))) { UInt32 count = 0; if (IORegistryEntry* cloverPlatformNode = fromPath("/efi/platform", gIODTPlane)) { if (OSIterator *iterator = OSCollectionIterator::withCollection(dictionary)) { while (OSString *name = OSDynamicCast(OSString, iterator->getNextObject())) { if (OSData *data = OSDynamicCast(OSData, cloverPlatformNode->getProperty(name))) { if (OSArray *items = OSDynamicCast(OSArray, dictionary->getObject(name))) { OSString *key = OSDynamicCast(OSString, items->getObject(0)); OSString *type = OSDynamicCast(OSString, items->getObject(1)); if (keyStore->addKeyWithValue(key->getCStringNoCopy(), type->getCStringNoCopy(), data->getLength(), data->getBytesNoCopy())) count++; } } } OSSafeRelease(iterator); } } if (count) HWSensorsInfoLog("%d key%s exported by Clover EFI", count, count == 1 ? "" : "s"); } // Check if we have SMC already bool smcDeviceFound = false; if (OSDictionary *matching = serviceMatching("IOACPIPlatformDevice")) { if (OSIterator *iterator = getMatchingServices(matching)) { OSString *smcNameProperty = OSString::withCString("APP0001"); while (IOService *service = (IOService*)iterator->getNextObject()) { OSObject *serviceNameProperty = service->getProperty("name"); if (serviceNameProperty && serviceNameProperty->isEqualTo(smcNameProperty)) { smcDeviceFound = true; } } OSSafeRelease(iterator); } OSSafeRelease(matching); } if (!smcDeviceFound) { if (!(smcDevice = new FakeSMCDevice)) { HWSensorsInfoLog("failed to create SMC device"); return false; } IOService *platformExpert = waitForMatchingService(serviceMatching("IOACPIPlatformExpert"), kFakeSMCDefaultWaitTimeout); if (!smcDevice->initAndStart(platformExpert, this)) { HWSensorsFatalLog("failed to initialize SMC device"); return false; } } else { HWSensorsInfoLog("found physical SMC device, will not create virtual one. Providing only basic plugins functionality"); } int arg_value = 1; // Load keys from NVRAM if (PE_parse_boot_argn("-fakesmc-use-nvram", &arg_value, sizeof(arg_value))) { if (UInt32 count = keyStore->loadKeysFromNVRAM()) HWSensorsInfoLog("%d key%s loaded from NVRAM", count, count == 1 ? "" : "s"); else HWSensorsInfoLog("NVRAM will be used to store system written keys..."); } registerService(); return true; }
bool RadeonMonitor::start(IOService * provider) { HWSensorsDebugLog("Starting..."); if (!super::start(provider)) return false; if (!(card.pdev = (IOPCIDevice*)provider)) return false; if (OSData *data = OSDynamicCast(OSData, provider->getProperty("device-id"))) { card.chip_id = *(UInt32*)data->getBytesNoCopy(); } else { HWSensorsFatalLog("device-id property not found"); return false; } card.pdev->setMemoryEnable(true); for (UInt32 i = 0; (card.mmio = card.pdev->mapDeviceMemoryWithIndex(i)); i++) { long unsigned int mmio_base_phys = card.mmio->getPhysicalAddress(); // Make sure we select MMIO registers if (((card.mmio->getLength()) <= 0x00020000) && (mmio_base_phys != 0)) break; } if (!card.mmio) { HWSensorsInfoLog("failed to map device memory"); return false; } card.family = CHIP_FAMILY_UNKNOW; card.int_thermal_type = THERMAL_TYPE_NONE; card.card_index = takeVacantGPUIndex(); if (card.card_index < 0) { radeon_fatal(&card, "failed to obtain vacant GPU index\n"); return false; } RADEONCardInfo *devices = RADEONCards; while (devices->device_id != NULL) { if ((devices->device_id & 0xffff) == (card.chip_id & 0xffff)) { card.family = devices->ChipFamily; card.info.device_id = devices->device_id; card.info.ChipFamily = devices->ChipFamily; card.info.igp = devices->igp; card.info.is_mobility = devices->is_mobility; radeon_info(&card, "found ATI Radeon 0x%04x\n", card.chip_id & 0xffff); break; } devices++; } if (card.family == CHIP_FAMILY_UNKNOW) { radeon_fatal(&card, "unknown card 0x%04x\n", card.chip_id & 0xffff); //return false; } //try to load bios from ATY,bin_image property of GPU registry node if (OSData *vbios = OSDynamicCast(OSData, provider->getProperty("ATY,bin_image"))) { card.bios_size = vbios->getLength(); card.bios = (UInt8*)IOMalloc(vbios->getLength()); memcpy(card.bios, vbios->getBytesNoCopy(), card.bios_size); if (card.bios[0] == 0x55 && card.bios[1] == 0xaa) { radeon_device *rdev = &card; UInt16 tmp = RBIOS16(0x18); if (RBIOS8(tmp + 0x14) == 0x0) { if ((card.bios_header_start = RBIOS16(0x48))) { tmp = card.bios_header_start + 4; if (!memcmp(card.bios + tmp, "ATOM", 4) || !memcmp(card.bios + tmp, "MOTA", 4)) { card.is_atom_bios = true; } else { card.is_atom_bios = false; } radeon_info(&card, "%sBIOS detected\n", card.is_atom_bios ? "ATOM" : "COM"); } } else radeon_error(&card, "not an x86 BIOS ROM, not using\n"); } else radeon_error(&card, "BIOS signature incorrect %x %x\n", card.bios[0], card.bios[1]); } else radeon_error(&card, "unable to locate ATY,bin_image\n"); if (!card.bios_header_start) { // Free memory for bios image if it was allocated if (card.bios && card.bios_size) { IOFree(card.bios, card.bios_size); card.bios = 0; card.bios_size = 0; } } else if (atom_parse(&card)) { radeon_atombios_get_power_modes(&card); } // Use temperature sensor type based on BIOS name if (card.int_thermal_type == THERMAL_TYPE_NONE && card.bios && card.bios_size) { if (!strncasecmp("R600", card.bios_name, 64) || !strncasecmp("RV610", card.bios_name, 64) || !strncasecmp("RV630", card.bios_name, 64) || !strncasecmp("RV620", card.bios_name, 64) || !strncasecmp("RV635", card.bios_name, 64) || !strncasecmp("RV670", card.bios_name, 64) || !strncasecmp("RS780", card.bios_name, 64) || !strncasecmp("RS880", card.bios_name, 64)) { card.int_thermal_type = THERMAL_TYPE_RV6XX; } else if (!strncasecmp("RV770", card.bios_name, 64) || !strncasecmp("RV730", card.bios_name, 64) || !strncasecmp("RV710", card.bios_name, 64) || !strncasecmp("RV740", card.bios_name, 64)) { card.int_thermal_type = THERMAL_TYPE_RV770; } else if (!strncasecmp("CEDAR", card.bios_name, 64) || !strncasecmp("REDWOOD", card.bios_name, 64) || !strncasecmp("JUNIPER", card.bios_name, 64) || !strncasecmp("CYPRESS", card.bios_name, 64) || !strncasecmp("PALM", card.bios_name, 64) || !strncasecmp("Wrestler", card.bios_name, 64)) { card.int_thermal_type = THERMAL_TYPE_EVERGREEN; } else if (!strncasecmp("SUMO", card.bios_name, 64) || !strncasecmp("SUMO2", card.bios_name, 64)) { card.int_thermal_type = THERMAL_TYPE_SUMO; } else if (!strncasecmp("ARUBA", card.bios_name, 64) || !strncasecmp("BARTS", card.bios_name, 64) || !strncasecmp("TURKS", card.bios_name, 64) || !strncasecmp("CAICOS", card.bios_name, 64) || !strncasecmp("CAYMAN", card.bios_name, 64)) { card.int_thermal_type = THERMAL_TYPE_NI; } else if (!strncasecmp("CAPE VERDE", card.bios_name, 64) || !strncasecmp("PITCAIRN", card.bios_name, 64) || !strncasecmp("TAHITI", card.bios_name, 64)) { card.int_thermal_type = THERMAL_TYPE_SI; } } // Use driver's configuration to resolve temperature sensor type if (card.int_thermal_type == THERMAL_TYPE_NONE) { radeon_info(&card, "using device-id to resolve temperature sensor type\n"); // Enable temperature monitoring switch (card.family) { case CHIP_FAMILY_R600: /* r600 */ case CHIP_FAMILY_RV610: case CHIP_FAMILY_RV630: case CHIP_FAMILY_RV670: case CHIP_FAMILY_RV620: case CHIP_FAMILY_RV635: case CHIP_FAMILY_RS780: case CHIP_FAMILY_RS880: card.int_thermal_type = THERMAL_TYPE_RV6XX; break; case CHIP_FAMILY_RV770: /* r700 */ case CHIP_FAMILY_RV730: case CHIP_FAMILY_RV710: case CHIP_FAMILY_RV740: card.int_thermal_type = THERMAL_TYPE_RV770; break; case CHIP_FAMILY_CEDAR: /* evergreen */ case CHIP_FAMILY_REDWOOD: case CHIP_FAMILY_JUNIPER: case CHIP_FAMILY_CYPRESS: case CHIP_FAMILY_HEMLOCK: case CHIP_FAMILY_PALM: card.int_thermal_type = THERMAL_TYPE_EVERGREEN; break; case CHIP_FAMILY_BARTS: case CHIP_FAMILY_TURKS: case CHIP_FAMILY_CAICOS: case CHIP_FAMILY_CAYMAN: case CHIP_FAMILY_ARUBA: card.int_thermal_type = THERMAL_TYPE_NI; break; case CHIP_FAMILY_SUMO: case CHIP_FAMILY_SUMO2: card.int_thermal_type = THERMAL_TYPE_SUMO; break; case CHIP_FAMILY_TAHITI: case CHIP_FAMILY_PITCAIRN: case CHIP_FAMILY_VERDE: card.int_thermal_type = THERMAL_TYPE_SI; break; // default: // radeon_fatal(&card, "card 0x%04x is unsupported\n", card.chip_id & 0xffff); // return false; } } // Setup temperature sensor if (card.int_thermal_type != THERMAL_TYPE_NONE ) { switch (card.int_thermal_type) { case THERMAL_TYPE_RV6XX: card.get_core_temp = rv6xx_get_temp; radeon_info(&card, "adding rv6xx thermal sensor\n"); break; case THERMAL_TYPE_RV770: card.get_core_temp = rv770_get_temp; radeon_info(&card, "adding rv770 thermal sensor\n"); break; case THERMAL_TYPE_EVERGREEN: case THERMAL_TYPE_NI: card.get_core_temp = evergreen_get_temp; radeon_info(&card, "adding EverGreen thermal sensor\n"); break; case THERMAL_TYPE_SUMO: card.get_core_temp = sumo_get_temp; radeon_info(&card, "adding Sumo thermal sensor\n"); break; case THERMAL_TYPE_SI: card.get_core_temp = si_get_temp; radeon_info(&card, "adding Southern Islands thermal sensor\n"); break; default: radeon_fatal(&card, "card 0x%04x is unsupported\n", card.chip_id & 0xffff); releaseGPUIndex(card.card_index); card.card_index = -1; return false; } } if (card.get_core_temp) { char key[5]; snprintf(key, 5, KEY_FORMAT_GPU_DIODE_TEMPERATURE, card.card_index); if (!addSensor(key, TYPE_SP78, 2, kFakeSMCTemperatureSensor, 0)) { //radeon_error(&card, "failed to register temperature sensor for key %s\n", key); radeon_fatal(&card, "failed to register temperature sensor for key %s\n", key); releaseGPUIndex(card.card_index); card.card_index = -1; return false; } } registerService(); return true; }
bool FakeSMC::init(OSDictionary *dictionary) { if (!super::init(dictionary)) return false; IOLog("HWSensors v%s Copyright %d netkas, slice, usr-sse2, kozlek, navi, THe KiNG, RehabMan. All rights reserved.\n", HWSENSORS_VERSION_STRING, HWSENSORS_LASTYEAR); //HWSensorsInfoLog("Opensource SMC device emulator. Copyright 2009 netkas. All rights reserved."); if (!(smcDevice = new FakeSMCDevice)) { HWSensorsInfoLog("failed to create SMC device"); return false; } if (!setOemProperties(this)) { // Another try after 200 ms spin IOSleep(200); setOemProperties(this); } if (!getProperty(kOEMInfoProduct) || !getProperty(kOEMInfoManufacturer)) { HWSensorsErrorLog("failed to obtain OEM vendor & product information from DMI"); // Try to obtain OEM info from Clover EFI if (IORegistryEntry* platformNode = fromPath("/efi/platform", gIODTPlane)) { if (OSData *data = OSDynamicCast(OSData, platformNode->getProperty("OEMVendor"))) { if (OSString *vendor = OSString::withCString((char*)data->getBytesNoCopy())) { if (OSString *manufacturer = getManufacturerNameFromOEMName(vendor)) { this->setProperty(kOEMInfoManufacturer, manufacturer); //OSSafeReleaseNULL(manufacturer); } //OSSafeReleaseNULL(vendor); } //OSSafeReleaseNULL(data); } if (OSData *data = OSDynamicCast(OSData, platformNode->getProperty("OEMBoard"))) { if (OSString *product = OSString::withCString((char*)data->getBytesNoCopy())) { this->setProperty(kOEMInfoProduct, product); //OSSafeReleaseNULL(product); } //OSSafeReleaseNULL(data); } } else { HWSensorsErrorLog("failed to get OEM info from Clover EFI, specific platform profiles will be unavailable"); } } if (IORegistryEntry *efi = IORegistryEntry::fromPath("/efi", gIODTPlane)) { if (OSData *vendor = OSDynamicCast(OSData, efi->getProperty("firmware-vendor"))) { // firmware-vendor is in EFI node OSData *buffer = OSData::withCapacity(128); const unsigned char* data = static_cast<const unsigned char*>(vendor->getBytesNoCopy()); for (unsigned int index = 0; index < vendor->getLength(); index += 2) { buffer->appendByte(data[index], 1); } OSString *name = OSString::withCString(static_cast<const char *>(buffer->getBytesNoCopy())); setProperty(kFakeSMCFirmwareVendor, name); //OSSafeRelease(vendor); //OSSafeRelease(name); OSSafeRelease(buffer); } OSSafeRelease(efi); } return true; }
bool PTIDSensors::start(IOService * provider) { if (!super::start(provider)) return false; acpiDevice = (IOACPIPlatformDevice *)provider; if (!acpiDevice) { HWSensorsFatalLog("ACPI device not ready"); return false; } // Update timers clock_get_system_nanotime((clock_sec_t*)&temperatureNextUpdate.tv_sec, (clock_nsec_t*)&temperatureNextUpdate.tv_nsec); acpiDevice->evaluateInteger("IVER", &version); if (version == 0) { OSString *name = OSDynamicCast(OSString, getProperty("IONameMatched")); if (name && name->isEqualTo("INT3F0D")) version = 0x30000; else return false; } setProperty("version", version, 64); // Parse sensors switch (version) { case 0x30000: { OSObject *object = NULL; // Temperatures if(kIOReturnSuccess == acpiDevice->evaluateObject("TSDL", &object) && object) { OSArray *description = OSDynamicCast(OSArray, object); if (OSIterator *iterator = OSCollectionIterator::withCollection(description)) { HWSensorsDebugLog("Parsing temperatures..."); UInt32 count = 0; while (OSObject *item = iterator->getNextObject()) { parseTemperatureName(OSDynamicCast(OSString, item), count / 2); count += 2; } } } else HWSensorsErrorLog("failed to evaluate TSDL table"); // Tachometers if(kIOReturnSuccess == acpiDevice->evaluateObject("OSDL", &object) && object) { OSArray *description = OSDynamicCast(OSArray, object); if (OSIterator *iterator = OSCollectionIterator::withCollection(description)) { HWSensorsDebugLog("Parsing tachometers..."); UInt32 count = 0; while (OSObject *item = iterator->getNextObject()) { parseTachometerName(OSDynamicCast(OSString, item), count / 3); count += 3; } } } else HWSensorsErrorLog("failed to evaluate OSDL table"); break; } case 0x20001: { OSObject *object = NULL; // Temperatures if(kIOReturnSuccess == acpiDevice->evaluateObject("TMPV", &object) && object) { OSArray *description = OSDynamicCast(OSArray, object); if (OSIterator *iterator = OSCollectionIterator::withCollection(description)) { HWSensorsDebugLog("Parsing temperatures..."); UInt32 count = 0; while (OSObject *item = iterator->getNextObject()) { parseTemperatureName(OSDynamicCast(OSString, item), count + 1); count += 3; } } } else HWSensorsErrorLog("failed to evaluate TMPV table"); // Tachometers if(kIOReturnSuccess == acpiDevice->evaluateObject("OSDV", &object) && object) { OSArray *description = OSDynamicCast(OSArray, object); if (OSIterator *iterator = OSCollectionIterator::withCollection(description)) { HWSensorsDebugLog("Parsing tachometers..."); UInt32 count = 0; while (OSObject *item = iterator->getNextObject()) { parseTachometerName(OSDynamicCast(OSString, item), count + 2); count++; } } } else HWSensorsErrorLog("failed to evaluate OSDV table"); break; } default: HWSensorsFatalLog("usupported interface version: 0x%x", (UInt32)version); return false; } registerService(); HWSensorsInfoLog("started"); return true; }
bool ACPISensors::start(IOService * provider) { if (!super::start(provider)) return false; acpiDevice = (IOACPIPlatformDevice *)provider; if (!acpiDevice) { HWSensorsFatalLog("ACPI device not ready"); return false; } if (OSDictionary *configuration = getConfigurationNode()) { // Temperatures if (OSDictionary *temps = OSDynamicCast(OSDictionary, configuration->getObject("Temperatures"))) { temperatures = OSDictionary::withCapacity(0); OSCollectionIterator *iterator = OSCollectionIterator::withCollection(temps); UInt16 count = 0; while (OSString *key = OSDynamicCast(OSString, iterator->getNextObject())) { OSString *method = OSDynamicCast(OSString, temps->getObject(key)); if (method && kIOReturnSuccess == acpiDevice->validateObject(method->getCStringNoCopy())) { for (int i = 0; i < FakeSMCTemperatureCount; i++) { if (addSensorToList(temperatures, key, method, FakeSMCTemperature[i].name, FakeSMCTemperature[i].key, FakeSMCTemperature[i].type, FakeSMCTemperature[i].size, kFakeSMCTemperatureSensor, count)) { count++; break; } else HWSensorsErrorLog("Failed to register temperature sensor \"%s\" for method \"%s\"", key->getCStringNoCopy(), method->getCStringNoCopy()); } } }; if (count) HWSensorsInfoLog("%d temperature sensor%s added", count, count > 1 ? "s" : ""); } else return false; // Voltages if (OSDictionary *volts = OSDynamicCast(OSDictionary, configuration->getObject("Voltages"))) { voltages = OSDictionary::withCapacity(0); OSCollectionIterator *iterator = OSCollectionIterator::withCollection(volts); UInt16 count = 0; while (OSString *key = OSDynamicCast(OSString, iterator->getNextObject())) { OSString *method = OSDynamicCast(OSString, volts->getObject(key)); if (method && kIOReturnSuccess == acpiDevice->validateObject(method->getCStringNoCopy())) { for (int i = 0; i < FakeSMCVolatgeCount; i++) { if (addSensorToList(voltages, key, method, FakeSMCVolatge[i].name, FakeSMCVolatge[i].key, FakeSMCVolatge[i].type, FakeSMCVolatge[i].size, kFakeSMCVoltageSensor, count)) { count++; break; } else HWSensorsErrorLog("Failed to register voltage sensor \"%s\" for method \"%s\"", key->getCStringNoCopy(), method->getCStringNoCopy()); } } }; if (count) HWSensorsInfoLog("%d voltage sensor%s added", count, count > 1 ? "s" : ""); } else return false; // Tachometers if (OSDictionary *fans = OSDynamicCast(OSDictionary, configuration->getObject("Tachometers"))) { tachometers = OSDictionary::withCapacity(0); OSCollectionIterator *iterator = OSCollectionIterator::withCollection(fans); UInt16 count = 0; OSDictionary* fanNames = OSDynamicCast(OSDictionary, configuration->getObject("Fan Names")); while (OSString *key = OSDynamicCast(OSString, iterator->getNextObject())) { OSString *method = OSDynamicCast(OSString, fans->getObject(key)); if (method && kIOReturnSuccess == acpiDevice->validateObject(method->getCStringNoCopy())) { OSString* name = NULL; if (fanNames) name = OSDynamicCast(OSString, fanNames->getObject(key)); if (FakeSMCSensor *sensor = addTachometer(count, name ? name->getCStringNoCopy() : 0)) { tachometers->setObject(sensor->getKey(), method); count++; } else HWSensorsErrorLog("Failed to register tachometer sensor for method \"%s\"", method->getCStringNoCopy()); } }; if (count) HWSensorsInfoLog("%d tachometer sensor%s added", count, count > 1 ? "s" : ""); } else return false; } else HWSensorsErrorLog("no valid configuration provided"); registerService(); HWSensorsInfoLog("started"); return true; }
bool SuperIOPlugin::start(IOService *provider) { if (!super::start(provider)) return false; OSNumber *number = OSDynamicCast(OSNumber, provider->getProperty(kSuperIOHWMAddress)); if (!number || !(address = number->unsigned16BitValue())) { HWSensorsFatalLog("wrong address provided"); return false; } number = OSDynamicCast(OSNumber, provider->getProperty(kSuperIOControlPort)); if (!number || !(port = number->unsigned8BitValue())) { HWSensorsFatalLog("wrong port provided"); return false; } number = OSDynamicCast(OSNumber, provider->getProperty(kSuperIOModelValue)); if (!number || !(model = number->unsigned16BitValue())) { HWSensorsFatalLog("wrong model provided"); return false; } OSString *string = OSDynamicCast(OSString, provider->getProperty(kSuperIOModelName)); if (!string || !(modelName = string->getCStringNoCopy())) { HWSensorsFatalLog("wrong model name provided"); return false; } string = OSDynamicCast(OSString, provider->getProperty(kSuperIOVendorName)); if (!string || !(vendorName = string->getCStringNoCopy())) { HWSensorsFatalLog("wrong vendor name provided"); return false; } if (!initialize()) return false; OSString *modelString = OSString::withCString(modelName); if (OSDictionary *configuration = getConfigurationNode(modelString)) { addTemperatureSensors(configuration); addVoltageSensors(configuration); addTachometerSensors(configuration); } else HWSensorsWarningLog("no platform profile provided"); OSSafeReleaseNULL(modelString); registerService(); HWSensorsInfoLog("started"); return true; }