Exemplo n.º 1
0
bool GeforceSensors::shadowBios()
{
    struct nouveau_device *device = &card;

    //try to load bios from registry first from "vbios" property created by Chameleon boolloader
    if (OSData *vbios = OSDynamicCast(OSData, pciDevice->getProperty("vbios"))) {
        device->bios.size = vbios->getLength();
        device->bios.data = (u8*)IOMalloc(card.bios.size);
        memcpy(device->bios.data, vbios->getBytesNoCopy(), device->bios.size);
    }

    if (!device->bios.data || !device->bios.size || nouveau_bios_score(device, true) < 1) {
        if (nouveau_bios_shadow(device)) {
            //nv_info(device, "early shadow VBIOS succeeded\n");
        }
        else {
            if (device->bios.data && device->bios.size) {
                IOFree(card.bios.data, card.bios.size);
                device->bios.data = NULL;
                device->bios.size = 0;
            }
            return false;
        }
    }

    return true;
}
Exemplo n.º 2
0
static int
nouveau_bios_ctor(struct nouveau_object *parent,
		  struct nouveau_object *engine,
		  struct nouveau_oclass *oclass, void *data, u32 size,
		  struct nouveau_object **pobject)
{
	struct nouveau_bios *bios;
	struct bit_entry bit_i;
	int ret;

	ret = nouveau_subdev_create(parent, engine, oclass, 0,
				    "VBIOS", "bios", &bios);
	*pobject = nv_object(bios);
	if (ret)
		return ret;

	ret = nouveau_bios_shadow(bios);
	if (ret)
		return ret;

	/* detect type of vbios we're dealing with */
	bios->bmp_offset = nvbios_findstr(bios->data, bios->size,
					  "\xff\x7f""NV\0", 5);
	if (bios->bmp_offset) {
		nv_info(bios, "BMP version %x.%x\n",
			bmp_version(bios) >> 8,
			bmp_version(bios) & 0xff);
	}
bool GeforceSensors::start(IOService *provider)
{
	HWSensorsDebugLog("Starting...");
	
	if (!super::start(provider))
        return false;
        
    struct nouveau_device *device = &card;
    
    // map device memory
    if ((device->pcidev = (IOPCIDevice*)provider)) {
        
        device->pcidev->setMemoryEnable(true);
        
        if ((device->mmio = device->pcidev->mapDeviceMemoryWithIndex(0))) {
            nv_debug(device, "memory mapped successfully\n");
        }
        else {
            HWSensorsFatalLog("failed to map memory");
            return false;
        }
    }
    else {
        HWSensorsFatalLog("failed to assign PCI device");
        return false;
    }
    
    card.card_index = -1;

    if (OSData *multiboard_capable = OSDynamicCast(OSData, provider->getProperty("rm_multiboard_capable"))) {
        if (0x1 == *((UInt32*)multiboard_capable->getBytesNoCopy())) {
            if (OSData *board_number = OSDynamicCast(OSData, provider->getProperty("rm_board_number"))) {
                UInt8 index = *((UInt32*)board_number->getBytesNoCopy());
                card.card_index = takeGPUIndex(index);
            }
        }
    }
    
    if (card.card_index < 0)
        card.card_index = takeVacantGPUIndex();
    
    if (card.card_index < 0) {
        HWSensorsFatalLog("failed to take vacant GPU index");
        return false;
    }
    
    // identify chipset
    if (!nouveau_identify(device)) {
        releaseGPUIndex(card.card_index);
        return false;
    }
    
    // shadow and parse bios
    
    //try to load bios from registry first from "vbios" property created by Chameleon boolloader
    if (OSData *vbios = OSDynamicCast(OSData, provider->getProperty("vbios"))) {
        device->bios.size = vbios->getLength();
        device->bios.data = (u8*)IOMalloc(card.bios.size);
        memcpy(device->bios.data, vbios->getBytesNoCopy(), device->bios.size);
    }
    
    if (!device->bios.data || !device->bios.size || nouveau_bios_score(device, true) < 1)
        if (!nouveau_bios_shadow(device)) {
            if (device->bios.data && device->bios.size) {
                IOFree(card.bios.data, card.bios.size);
                device->bios.data = NULL;
                device->bios.size = 0;
            }
            
            nv_fatal(device, "unable to shadow VBIOS\n");
            
            releaseGPUIndex(card.card_index);
            card.card_index = -1;
            return false;
        }
    
    nouveau_vbios_init(device);
    nouveau_bios_parse(device);
    
    // initialize funcs and variables
    if (!nouveau_init(device)) {
        nv_error(device, "unable to initialize monitoring driver\n");
        releaseGPUIndex(card.card_index);
        card.card_index = -1;
        return false;
    }
    
    nv_info(device, "chipset: %s (NV%02X) bios: %02x.%02x.%02x.%02x\n", device->cname, device->chipset, device->bios.version.major, device->bios.version.chip, device->bios.version.minor, device->bios.version.micro);
    
    if (device->card_type < NV_C0) {
        // init i2c structures
        nouveau_i2c_create(device);
        
        // setup nouveau i2c sensors
        nouveau_i2c_probe(device);
    }
    
    // Register sensors
    char key[5];
    if (card.core_temp_get || card.board_temp_get) {
        nv_debug(device, "registering i2c temperature sensors...\n");
        
        if (card.core_temp_get && card.board_temp_get) {
            snprintf(key, 5, KEY_FORMAT_GPU_DIODE_TEMPERATURE, card.card_index);
            addSensor(key, TYPE_SP78, 2, kFakeSMCTemperatureSensor, nouveau_temp_core);
            
            snprintf(key, 5, KEY_FORMAT_GPU_HEATSINK_TEMPERATURE, card.card_index);
            addSensor(key, TYPE_SP78, 2, kFakeSMCTemperatureSensor, nouveau_temp_board);
        }
        else if (card.core_temp_get) {
            snprintf(key, 5, KEY_FORMAT_GPU_DIODE_TEMPERATURE, card.card_index);
            addSensor(key, TYPE_SP78, 2, kFakeSMCTemperatureSensor, nouveau_temp_core);
        }
        else if (card.board_temp_get) {
            snprintf(key, 5, KEY_FORMAT_GPU_HEATSINK_TEMPERATURE, card.card_index);
            addSensor(key, TYPE_SP78, 2, kFakeSMCTemperatureSensor, nouveau_temp_board);
        }
    }
    else if (card.temp_get)
    {
        nv_debug(device, "registering temperature sensors...\n");
        
        snprintf(key, 5, KEY_FORMAT_GPU_DIODE_TEMPERATURE, card.card_index);
        addSensor(key, TYPE_SP78, 2, kFakeSMCTemperatureSensor, nouveau_temp_diode);
    }
    
    int arg_value = 1;

    if (card.clocks_get && !PE_parse_boot_argn("-gpusensors-no-clocks", &arg_value, sizeof(arg_value))) {
        nv_debug(device, "registering clocks sensors...\n");
        
        if (card.clocks_get(&card, nouveau_clock_core) > 0) {
            snprintf(key, 5, KEY_FAKESMC_FORMAT_GPU_FREQUENCY, card.card_index);
            addSensor(key, TYPE_UI32, TYPE_UI32_SIZE, kFakeSMCFrequencySensor, nouveau_clock_core);
        }
        
//        if (card.clocks_get(&card, nouveau_clock_shader) > 0) {
//            snprintf(key, 5, KEY_FAKESMC_FORMAT_GPU_SHADER_FREQUENCY, card.card_index);
//            addSensor(key, TYPE_UI32, TYPE_UI32_SIZE, kFakeSMCFrequencySensor, nouveau_clock_shader);
//        }
        
        if (card.clocks_get(&card, nouveau_clock_rop) > 0) {
            snprintf(key, 5, KEY_FAKESMC_FORMAT_GPU_ROP_FREQUENCY, card.card_index);
            addSensor(key, TYPE_UI32, TYPE_UI32_SIZE, kFakeSMCFrequencySensor, nouveau_clock_rop);
        }
        
        if (card.clocks_get(&card, nouveau_clock_memory) > 0) {
            snprintf(key, 5, KEY_FAKESMC_FORMAT_GPU_MEMORY_FREQUENCY, card.card_index);
            addSensor(key, TYPE_UI32, TYPE_UI32_SIZE, kFakeSMCFrequencySensor, nouveau_clock_memory);
        }
    }
    
    if (card.fan_pwm_get || card.fan_rpm_get) {
        nv_debug(device, "registering PWM sensors...\n");

        char title[DIAG_FUNCTION_STR_LEN];
        snprintf (title, DIAG_FUNCTION_STR_LEN, "GPU %X", card.card_index + 1);
        
        if (card.fan_rpm_get && card.fan_rpm_get(device) >= 0)
            addTachometer(nouveau_fan_rpm, title, GPU_FAN_RPM, card.card_index);
        
        if (card.fan_pwm_get && card.fan_pwm_get(device) >= 0)
            addTachometer(nouveau_fan_pwm, title, GPU_FAN_PWM_CYCLE, card.card_index);
    }
    
    if (card.voltage_get && card.voltage.supported) {
        nv_debug(device, "registering voltage sensors...\n");
        snprintf(key, 5, KEY_FORMAT_GPU_VOLTAGE, card.card_index);
        addSensor(key, TYPE_FP2E, TYPE_FPXX_SIZE, kFakeSMCVoltageSensor, 0);
    }
    
    registerService();
    
    nv_info(device, "started\n");
    
    return true;
}
bool GeforceSensors::start(IOService * provider)
{
	DebugLog("Starting...");
	
	if (!super::start(provider)) 
    return false;
  
  if (!(fakeSMC = waitForService(serviceMatching(kFakeSMCDeviceService)))) {
		WarningLog("Can't locate fake SMC device, kext will not load");
		return false;
	}  
  
  struct nouveau_device *device = &card;
  
  //Find card number
  card.card_index = getVacantGPUIndex();
  
  if (card.card_index < 0) {
    nv_error(device, "failed to obtain vacant GPU index\n");
    return false;
  }
  
  // map device memory
//  device->pcidev = (IOPCIDevice*)provider;
  if (device->pcidev) {
    
    device->pcidev->setMemoryEnable(true);
    
    if ((device->mmio = device->pcidev->mapDeviceMemoryWithIndex(0))) {
      nv_debug(device, "memory mapped successfully\n");
    }
    else {
      nv_error(device, "failed to map memory\n");
      return false;
    }
  }
  else {
    nv_error(device, "failed to assign PCI device\n");
    return false;
  }
  
  // identify chipset
  if (!nouveau_identify(device))
    return false;
  
  // shadow and parse bios
  
  //try to load bios from registry first from "vbios" property created by Chameleon boolloader
  if (OSData *vbios = OSDynamicCast(OSData, provider->getProperty("vbios"))) {
    device->bios.size = vbios->getLength();
    device->bios.data = (u8*)IOMalloc(card.bios.size);
    memcpy(device->bios.data, vbios->getBytesNoCopy(), device->bios.size);
  }
  
  if (!device->bios.data || !device->bios.size || nouveau_bios_score(device, true) < 1)
    if (!nouveau_bios_shadow(device)) {
      if (device->bios.data && device->bios.size) {
        IOFree(card.bios.data, card.bios.size);
        device->bios.data = NULL;
        device->bios.size = 0;
      }
      
      nv_error(device, "unable to shadow VBIOS\n");
      
      return false;
    }
  
  nouveau_vbios_init(device);
  nouveau_bios_parse(device);
  
  // initialize funcs and variables
  if (!nouveau_init(device)) {
    nv_error(device, "unable to initialize monitoring driver\n");
    return false;
  }
  
  nv_info(device, "chipset: %s (NV%02X) bios: %02x.%02x.%02x.%02x\n", device->cname, (unsigned int)device->chipset, device->bios.version.major, device->bios.version.chip, device->bios.version.minor, device->bios.version.micro);
  
  if (device->card_type < NV_C0) {
    // init i2c structures
    nouveau_i2c_create(device);
    
    // setup nouveau i2c sensors
    nouveau_i2c_probe(device);
  }
  
  // Register sensors
  char key[5];
  
  if (card.core_temp_get || card.board_temp_get) {
    nv_debug(device, "registering i2c temperature sensors...\n");
    
    if (card.core_temp_get && card.board_temp_get) {
      snprintf(key, 5, KEY_FORMAT_GPU_DIODE_TEMPERATURE, card.card_index);
      this->addSensor(key, TYPE_SP78, 2, 0);
      
      snprintf(key, 5, KEY_FORMAT_GPU_HEATSINK_TEMPERATURE, card.card_index);
      addSensor(key, TYPE_SP78, 2, 0);
    }
    else if (card.core_temp_get) {
      snprintf(key, 5, KEY_FORMAT_GPU_PROXIMITY_TEMPERATURE, card.card_index);
      addSensor(key, TYPE_SP78, 2, 0);
    }
    else if (card.board_temp_get) {
      snprintf(key, 5, KEY_FORMAT_GPU_PROXIMITY_TEMPERATURE, card.card_index);
      addSensor(key, TYPE_SP78, 2, 0);
    }
  }
  else if (card.temp_get)
  {
    nv_debug(device, "registering temperature sensors...\n");
    
    snprintf(key, 5, KEY_FORMAT_GPU_PROXIMITY_TEMPERATURE, card.card_index);
    addSensor(key, TYPE_SP78, 2, 0);
  }
  
  if (card.clocks_get) {
    nv_debug(device, "registering clocks sensors...\n");
    
    if (card.clocks_get(&card, nouveau_clock_core) > 0) {
      snprintf(key, 5, KEY_FAKESMC_FORMAT_GPU_FREQUENCY, card.card_index);
      addSensor(key, TYPE_UI32, TYPE_UI32_SIZE, nouveau_clock_core);
    }
    
    if (card.clocks_get(&card, nouveau_clock_shader) > 0) {
      snprintf(key, 5, KEY_FAKESMC_FORMAT_GPU_SHADER_FREQUENCY, card.card_index);
      addSensor(key, TYPE_UI32, TYPE_UI32_SIZE, nouveau_clock_shader);
    }
    
    if (card.clocks_get(&card, nouveau_clock_rop) > 0) {
      snprintf(key, 5, KEY_FAKESMC_FORMAT_GPU_ROP_FREQUENCY, card.card_index);
      addSensor(key, TYPE_UI32, TYPE_UI32_SIZE, nouveau_clock_rop);
    }
    
    if (card.clocks_get(&card, nouveau_clock_memory) > 0) {
      snprintf(key, 5, KEY_FAKESMC_FORMAT_GPU_MEMORY_FREQUENCY, card.card_index);
      addSensor(key, TYPE_UI32, TYPE_UI32_SIZE, nouveau_clock_memory);
    }
  }
  
  if (card.fan_pwm_get || card.fan_rpm_get) {
    nv_debug(device, "registering PWM sensors...\n");
    
    if (card.fan_rpm_get && card.fan_rpm_get(device) > 0) {
      char title[6];
      snprintf (title, 6, "GPU %X", card.card_index + 1);
      
      UInt8 fanIndex = 0;
      
      if (addTachometer( fanIndex)) {
        if (card.fan_pwm_get && card.fan_pwm_get(device) > 0) {
          snprintf(key, 5, KEY_FAKESMC_FORMAT_GPUPWM, fanIndex);
          addSensor(key, TYPE_UI8, TYPE_UI8_SIZE, 0);
        }
      }
    }
  }
  
  if (card.voltage_get && card.voltage.supported) {
    nv_debug(device, "registering voltage sensors...\n");
    snprintf(key, 5, KEY_FORMAT_GPU_VOLTAGE, card.card_index);
    addSensor(key, TYPE_FP2E, TYPE_FPXX_SIZE, 0);
  }
  
  nv_info(device, "started\n");
  
  return true;
}