Ciao a tutti, volevo portarvi a conoscenza di un utilissimo tool per la gestione della velocità della ventola di raffreddamento della ps3. Questo tool è stato ideato da Estwald (Hermes, il creatore di IRIS MANAGER) ed è installabile su qualsiasi CFW CEX.
Il programma dispone di 4 funzioni:
1) Ventola alla massima velocità
2) Ventola con velocità controllata dalla SYSCON (è l'impostazione di default di ogni ps3)
3) Ventola con velocità manuale
4) Ventola con velocità gestita dal PAYLOAD

Il punto 4 è un nuovo modo di gestire la velocità della ventola, che non si basa più sulla rilevazione istantanea della temperatura, ma su un insieme di temperature rilevate nel corso della sessione di gioco (velocità delle rilevazioni pari a un intervallo da 7ms a 20ms). Con questo nuovo payload, risulta essere più efficiente il sistema di raffreddamento ed una minore possibilità di surriscaldamento.

Qui trovate le info in lingua originale (spagnolo):
 
Antes de nada, abro éste hilo aquí por tratarse de una modificación de firmware muy concreta (que trabaja sobre CFW CEX 3.41, 3.55, 4.21, 4.30, 4.31 y 4.40), destinada principalmente a trabajar bajo el entorno de los juegos. No se trata de un simple ajuste de la velocidad del ventilador, si no de un payload que cumple su cometido regulando la velocidad del ventilador en función de las temperaturas del sistema, para tratar de evitar un sobrecalentamiento excesivo en lo posible. Por esa razón lo abro aquí y no en Scene, donde también podría tener cabida..

El hilo tendrá dos cometidos: por un lado, el exponer el desarrollo, investigación y los aportes propios o que hagáis vosotros y por otro lado, la parte práctica para quienes solo quieren usar la utilidad.

Empecemos pues por la parte del desarrollo (si a alguien no le interesa, que salte a "La Aaplicación Control Fan")

El Desarrollo: Investigación y Descripción

Cómo ya comenté en otro hilo, existe una syscall llamada sys_sm_set_fan_policy() que permite controlar el ventilado. En concreto, descubrí que tiene al menos, 3 modos de operación que se resumen en:

sys_sm_set_fan_policy(0, 0, 0); // ventilador a toda potencia (velocidad 0xff)

sys_sm_set_fan_policy(0, 1, x) ; // ventilador controlado por el SYSCON (la x no parece usarse de forma directa o es ignorada por que se autoajuste, pero puede que influya cuando se reinicia/apaga el sistema)

sys_sm_set_fan_policy(0, 2, x) ; // ventilador controlado de forma manual.

Este último modo, el 2, es el que nos interesa a nosotros: la x se mueve en el rango de 0x33 (un valor menor se puede escribir, pero se corrige automáticamente en el SYSCON) a 0xFF, que sería la máxima potencia. Este modo tiene sus peligros, si no se maneja debidamente, ya que por ejemplo, si ajustamos 0x33, la velocidad es insuficiente y la temperatura alcanzará temperaturas muy peligrosas. Así que ojo con esto.

Según parece, cuando se reinicia el sistema, el SYSCON cambia a Modo 1 pero al apagarse la consola (piloto rojo) el Modo sigue siendo 2 pero el SYSCON fija el valor a 0x4D, cómo medida de seguridad, seguramente, pues con este valor la consola mantiene niveles aceptables de refrigeración.

De hecho el SYSCON utiliza valores mucho más bajos, usualmente. Que yo haya visto, empieza con el mínimo 0x33, luego sube a 0x40, 0x44, 0x48 y rara vez sube de ahí, por que al SYSCON manejarse en el rango de 70º a 75º en las FAT (al menos en la mía), le parece aceptable y prefiere menos ruido y mayor temperatura, cuando a nosotros nos puede interesar lo contrario.

Todo esto se puede ver mediante la syscall sys_sm_get_fan_policy() que cuenta con cinco parámetros que yo los he llamado así:

int sys_sm_get_fan_policy(u8 id, u8 *st, u8 *mode, u8 *speed, u8 *unknown)



- id es 0

- st y mode: reflejan el modo actual

- speed: como su nombre indica, refleja el valor x de velocidad que ajustamos nosotros o el SYSCON, dependiendo del modo.

- unknown: que yo haya visto (y vosotros mediante la presente aplicación) siempre es 0: ignoro si tiene un uso concreto.

Esta syscall la utilizo únicamente con fines informativos en la utilidad, pero el payload no hace uso de ella.

Una vez que podemos regular la velocidad del ventilador, lo siguiente, pero no menos importante, es conocer la temperatura que queremos regular.

Para ello, tenemos la syscall sys_game_get_temperature() que recibe como primer parámetro 0 si queremos medir la temperatura de la CPU y 1, para el RSX, mientras que el segundo parámetro es una variable que almacenará el valor de temperatura.

Por último, aunque de forma decorativa, hacemos uso de la syscall sys_set_leds() la cual nos permite poner los leds en el estado que queramos.

El problema de éstas syscalls es que requieren un tipo de permiso que nuestras aplicaciones y sobre todo los juegos, no suelen tener: algunas requieren flags PM cómo las relacionadas con el ventilador y otras permisos ROOT. Así que no queda más remedio que desactivar esos chequeos mediante "pokes" como éste:

// enables sys_game_get_temperature
lv2poke32(0x800000000000C694ULL, 0x38600000);



y esa es la razón por la que la utilidad está limitada a esos CFW: faltan los parches necesarios para los otros XD.

Bien, con todo lo dicho hasta ahora, se puede montar una aplicación que ajuste los modos a nuestro antojo, lo cual puede estar bien si solo se pretende ajustar el ventilador a una velocidad fija y ya está (al estilo de los que hacéis el mod del potenciómetro), pero si se pretende algo más "regulable" entonces la cosa se complica, por que requiere que nuestro código esté funcionando a nivel de sistema y eso requiere, por la vía elegida, hacer un payload y pinchar algunas syscalls.

El Payload

¿Y que debe de hacer el payload?. Pues en principio, debe tomar muestras de temperatura, ajustar la velocidad del ventilador, si procede y luego avisarnos de alguna manera (mediante LEDS) si la temperatura está dentro de unos parámetros y tal.

Así dicho suena muy fácil, pero ¿como hacemos todo esto y cómo averiguamos que syscalls pinchar?

Inicialmente, yo opté por pinchar la syscall usleep() pero esa opción no resultó ser buena al final y tuve que recurrir a otra, que es la que voy a describir a continuación (y prestadle atención, que es importante XD)

Antes de nada, conviene saber varias cosas o al menos, es lo que yo se (si alguien sabe otras cosas, que nos lo cuente)

- Las aplicaciones corren en modo usuario y cuando llamas a la syscalls, entras en modo supervisor, kernel, LV2 o llámalo como más te guste.

- Las aplicaciones usan memoria virtual, por lo que no podemos estar seguro si un determinado bloque de memoria está mapeado o lo que es peor, que permita escrituras.

- Cualquier intento de pasar memoria de LV2 cómo variable, retornará con error o simplemente... no retornará

- Dentro de LV2, sólo conocemos esto cuando una determinada syscall, utiliza variables entre sus parámetros. Lo cual tiene sus problemas, si las que necesitamos utilizar sólo reciben valores, pero ninguna dirección de memoria aprovechable. Por lo que necesitamos adquirir dicha información de forma indirecta y eso es un embrollo XD .

- Obviamente, si obtenemos un área de memoria que podamos "modificar" tenemos que asegurarnos que la modificación no afecta, o que de cara a la aplicación, lo datos no se hayan modificados (es decir: preservar los valores)

- Pues bien, nuestra syscall de medir la temperatura, requiere una puta variable XD y eso plantea éstas dificultades.

- Por otro lado, dentro de LV2 es posible llamar a ciertas syscalls o mas concretamente, a las funciones que manejan dichas syscalls, pero hay otras que no se puede (por ejemplo, las de acceso a fichero bloquean el sistema, si por ejemplo, haces un open y luego un read, sin salir a modo usuario)

Con todos estos problemas, encima necesitamos una syscall que se llame con regularidad para poder hacer nuestras lecturas/ajustes y tuve que descartar usleep().

La "salvación" vino en forma de eventos: los eventos del sistema nos permiten, cómo su nombre indica, recibir sucesos dentro del sistema, recibiendo una serie de datos.

La syscall sysEventQueueReceive() es la encargada de recibirlos y además, nos proporciona una variable que podemos utilizar para la medida de temperatura. La syscall en su último parámetro especifica el tiempo en microsegundos durante el cual esperará un evento (0 indica infinito).

Una cosa a tener en cuenta es que ésta syscall recibe TODOS los eventos que se producen vía aplicaciones y es bien posible que mientras estemos procesando uno, se reciba OTRO evento, si nos demoramos en nuestras tareas, por lo que conviene proteger contra ellos.

De hecho, la toma de temperatura requiere entre 7ms y 20ms y volví a encontrarme con problemas, debido a que se sobrepasaba la velocidad de respuesta. en un determinado momento, produciéndose un bloqueo.

Así que cambié de estrategia e intenté averiguar donde se generaban los eventos para que si se debía producir demora, fuese allí y no en el receptor. A todo esto, tengo que decir que ni siquiera conozco de primera mano QUIEN, DONDE Y PORQUE genera los eventos: simplemente, se que algo genera eventos en cadencia suficiente para permitirme hacer mis lecturas y que la naturaleza de esos eventos se producen en el XMB, en los juegos, en el emulador de PSX y en el de PSP. En PS2, al menos en la retrocompatibilidad por hardware de mi PS2 se que no, por que el LV2 que conocemos desaparece y con ello, mi payload

Existen varias formas de producir eventos, pero la más accesible, son los EventPort.

Pinchándolo pude ver que efectivamente, es el origen de las llamadas. La syscall sysEventPortSend() envía en los registros la siguiente información

sysEventPortSend(sys_event_port_t portId,u64 data0,u64 data1,u64 data2)



Cómo vemos, ninguna variable, solo datos, con lo cual, seguimos necesitando el concurso de sysEventQueueReceive() para recibir una variable que podamos modificar.

El problema es que la modificación la debemos hacer en el llamante y no en el llamado, que es el que recibe la variable del programa. Es decir, que necesitamos la gallina para poner el huevo, pero no hay gallina hasta que nazca del huevo [sonrisa]

Para saltar ese obstáculo, recurrí al PID: si conocemos el process ID, podemos comparar, si el envío y la recepción están en el mismo proceso y podemos por tanto, pasar la gallina al huevo, desde la propia gallina [+risas] . O para no liar el asunto, pasar la variable de sysEventQueueReceive() para que la usen nuestros procedimientos en sysEventPortSend() (tambien es necesario por que en principio, no sabemos si el EventPort tendía cómo destinatario ESE QueueReceive, debido a que se relaciona de forma indirecta con el evento!)

Perfecto, hecho eso, mediante unas comprobaciones de seguridad de los respectivos PIDs, podemos asegurar que "mem_app" (en el payload) contiene una dirección de memoria para escritura que podemos usar.

Una vez que cerramos el circuito y vemos que funciona, nos interesa intentar discriminar para encontrar los eventos que nos resultan útiles y descartas otros que no lo son y solo pueden acarrear problemas. Haciendo varias pruebas, resulta que se que la recepción del evento no es bloqueable (o sea, que tiene un tiempo límite) y que el evento que se genera y recibe, útil, tiene todos los datos a 0 (por lo general, un evento contiene una serie de datos con información útil y necesaria para los programas. Por ejemplo, los eventos relacionados con los dispositivos, reciben el tipo de dispositivo en data2).

Ahora necesitamos hacer dos cosas: si nuestros eventos tienen una caducidad y una capacidad de respuesta corta, por un lado, necesitamos una base de tiempo para saber cada cuanto tiempo leer la temperatura, etc, sin lastrar al sistema y también necesitamos dividir las tareas a realizar para que cumplan su cometido sin lastrar al sistema.

Después de éxitos y penurias, al final, de base de tiempo utilizo un registro del procesador (nota: suponía que tenía que haber uno con ese cometido, pero ni idea de como se usaba en CELL [+risas] ) que cuenta los ticks desde el arranque del sistema (con eso podemos conocer cuanto tiempo lleva la consola encendida XD. De hecho, en la utilidad muestro esa información como "PS3 Start Time")

La base de tiempo que utiliza, ni idea [+risas] . Lo que hice al final, es hacer un par de bucles combinados con el reloj de tiempo real para primero sincronizar y luego tomar una lectura durante 60 segundos, con la cual obtener los ticks por segundo que se generan. La cifra: 0x4c1a6bd o 79799997 como gustéis. Tampoco se necesita una precisión del copón, solo algo que que cuente el tiempo de forma razonable [+risas]

Si alguien tiene curiosidad en saber como se obtiene los ticks, ésta es la función:

Código: Seleccionar todo
static inline u64 get_ticks(void)
{
u64 ticks;
asm volatile("mftb %0" : "=r" (ticks));
return ticks;
}



Se supone que en un punto puede dar cero y que habría que entrar en bucle hasta obtener una lectura válida. De hecho, en el payload se hace así:

get_ticks:
mftb %r4 // get tick counter 1s = 79799997 ticks aprox
cmpldi %r4, 0
beq get_ticks
srdi %r4, %r4, 12 // ticks/4096 0 => 1s 0x4C1A ticks aprox



En este caso, utilizo un desplazamiento de 12 bits desde la derecha para obtener un número de ticks con el que comparar de forma "razonable" desde ensamblador

Al final, la rutina trabaja así:

- Se dividen las tareas a realizar de forma que primero, se hace una lectura de temperatura que se va alternando entre CPU y RSX. Esta tarea requiere mucho tiempo en términos de eventos por lo que es importante dividirla

- Cómo segunda tarea está mirar si se necesita corregir la temperatura y ajustar los leds (cosa que la mayor parte del tiempo, no se necesita)

- El temporizador se ajusta para que responda cada 1,5 segundos. Es decir, el proceso de medir la temperatura de la CPU y hacer ajustes, lleva 3 segundo y otros tantos para el RSX, por lo que el total, se de 6 segundos, que es una buena cifra.

- Esta temporización puede ser saltada si el tiempo expiró pero no se pudo producir lectura de temperatura por que no coinciden los PIDS o mem_app está a cero.

- Los PIDs se suelen ajustar a cero en ciertos momentos después de su uso para prevenir problemas (recordad que hablamos de syscalls que se usan por TODO el sistema y tenemos casos donde huevo da lugar a gallina y gallina da lugar a huevo y a veces, la gallina muere y el huevo cuando nace, se equivoca de madre y la lía [+risas] )

- Un detalle MUY importante que no he mencionado, es que para evitar una serie de problemas, me veo obligado a mandar ANTES el evento (o sea, dejar pasar la syscall) que las acciones que estoy realizando por lo que no puedo estar seguro si el sistema, que recordemos que soporta dos hilos por hardware y tal, pueda estar recepcionando el evento mientras uno se piensa que hasta que no salga de la syscall no ocurre nada. Este tipo de pensamientos "monotarea" en el que solemos incurrir, puede hacer que nos roben la cartera y ni siquiera nos hayamos enterado. Por ello, intento cubrirme con el flag "in_use" tambien de forma que se ignoren las llamadas que puedan ser problemáticas (de hecho, ya ignoramos muchas por el uso del contador de ticks)

A grandes líneas, este es el funcionamiento, los problemas que uno se encuentra y como resolverlos sobre la marcha: no tiene por qué ser el enfoque más correcto o incorrecto, si no que simplemente, es cómo yo he resuelto el problema y curiosamente, no en base a lo que sabía, si no en base a lo que no se y voy descubriendo por mi cuenta.

Uso Del Payload

Una característica del payload es que permite ser ubicado en cualquier parte del sistema: se ha elegido la dirección 0xF70 de LV2 (recordad que hay que añadir un 0x80....000 para formar la dirección de 64 bits) pero podría alojarse en cualquier otra parte (usando el método write_htab() que se incluye en los fuente Iris Manager, podemos habilitar la ejecución de las partes prohibidas de LV2) y es compatible con cualquier CFW teóricamente.

Como ya he comentado antes, los parches para habilitar las syscalls que requieren permisos, son la razón por la que la que esto se presenta para CFW 4.31 y 4.40 .

De hecho, solo he testeado en 4.40 por lo que espero no haber metido la pata con los partes para 4.31 XD

En la aplicación, la función load_ps3_controlfan_payload() carga el payload uniendo las diferentes syscalls (el loop y los sleeps son para "garantizar" que el payload se carga bien)

El inicio del payload contiene la ID 'PFAN' (0x5046414E) en los primeros 4 bytes. Los 4 bytes siguientes, contienen en el offset dentro del payload (bajo este punto de vista, el payload comienza en 0) donde encontrar los datos fan_control.

Todos los datos que menciono a continuación son de 32 bits:

En fan_control - 8 bytes podemos cambiar el comparador actual de velocidad (esto solo es útil si deshabilitas el payload y lo quieres volver a habilitar, provocando que se actualice).

En fan_control - 4 podemos deshabilitar o habilitar el payload: 0- >deshabilita, 1- habilita sin leds y 2 - con leds

En fan_control + 0 podemos ajustar la velocidad que se fijará si se llama a la syscall sys_sm_shutdown() para algo que no sea un Reset o Apagado normal (por ejemplo, cuando se activa el emulador de PS2 en la consolas retrocompatibles, al menos). Se supone que con 0x5F la velocidad es suficiente (de hecho, alta) para evitar problemas, pero claro, todo dependerá de la temperatura ambiente y de lo que se caliente vuestra PS3 [+risas]

Dicha syscall es intervenida para que en caso contrario, fije el Modo 1, con la idea de dotaros de algo de protección adicional si no se vuelve a activar la aplicación (si en ese caso, está en Modo 2, carecerá de regulación y dependerá de lo suficiente que sea la velocidad 0x4D)

A partir de fan_control + 4 (inclusive) está la tabla de velocidades que se relacionan con las temperaturas de temp_control0 a temp_control4

Las temperaturas (todas en ºC) temp_control0 a temp_control1 conforman un abanico en el que se tiene en cuenta si la temperatura partía por debajo de temp_control0 y va subiendo o se está bajando desde temp_control1 (si se está calentando, la velocidad es menor que si está viendo la necesidad de enfriar)

temp_control2 supone un cambio de marcha, mientras que temp_control3 supone el punto de inflexión. En el caso por defecto de 70º el led parpadeará en amarillo/verde si la temperatura es mayor o igual de 70º

temp_control4 representa la temperatura de la alarma: en ese caso, el led parpadeará en modo "discoteca" (amarillo, rojo y verde) y la velocidad se ha ajustado en 0xA0, que es ruidos y enfría bastante [+risas]

Un detalle importante cada 11-12 segundos o así, el led se ilumina en verde durante 1,5 segundos (excepto si estamos en temperatura de emergencia). Es la forma que tiene el payload de deciros que está trabajando (sobre todo se nota si está el LED en amarillo fijo)

Y creo que no me olvido de nada importante en este apartado XD (el fuente del payload ya tiene bastantes comentarios)

La Aplicación Control Fan

La aplicación es bastante sencilla (si alguien la quiere compilar, puede usar éste entorno de compilación hilo_psdk3v2-windows-ps3-sdk-con-psl1ght-v2-tiny3d-y-ps3-soundilb_1867760) y muestra en forma de texto toda la información.

Nada más arrancar se fija el modo "#Payload" que es de lo que hemos estado hablando.

La información en pantalla es la siguiente:

Temperatura de la CPU/ temperatura de RSX y Tiempo transcurrido desde el encendido de PS3

Las temperaturas parpedearán en amarillo cuando alcancen los 70 grados y en rojo cuando alcancen los 75 grados

sys_sm_get_fan_policy aquí indica el modo y la velocidad que tiene fijado el SYSCON

Current Mode Indica el modo actual y la velocidad del ventilador fijada (modo 2 y payload)

Los modos vienen resumidos abajo. En el Modo 2, con UP/ARRIBA subimos la velocidad y con DOWN/ABAJO la bajamos. Recordad que el modo 2 es un modo con velocidad fija y no varía en función de la temperatura. El Modo 1 es el normal del sistema.

Para cambiar de Modo se usa SQUARE/CUADRADO e irá cambiando en sentido ascendente (eso permite por ejemplo, fijar una velocidad muy baja en Modo 2 para que la consola se caliente y luego activar el Modo Payload para ver como responde XD)

Con el botón TRIANGULO se sale de la aplicación. Recomiendo usar éste botón para salir y no desde PS

Protecciones de la aplicación

- Desde el Modo Payload, protección anti-shutdown, para que ajuste el modo de protección

- Si se apaga la consola en Modo 2, se conservará al encenderlo, ojo a esto, aunque en principio, el SYSCON fija una velocidad supuestamente apropiada.

- El SYSCON corrige los valores fijados por debajo de 0x33. Aún así, se ha limitado el Modo 2 a 0x30 cómo mínimo y cuando la velocidad baja de 0x4D Current Mode parpadeará en azul

- Si se sale de la aplicación en Modo 2, la velocidad mínima se ajustará a 0x5f, independientemente de la que hubiera sido fijada (a modo de seguridad y por que el Modo 2, no debiera ser fijado, a menos que lo que se pretenda es que el ventilador trabaje a velocidad alta y en ese caso, ese mínimo es correcto :p )

- Independientemente del modo, si la temperatura es mayor o igual a 80 grados, se activará el Modo 0 hasta que la temperatura baje por debajo de los 60 grados (momento en que conectará el Modo Payload) o vosotros mismos cambiéis de modo cuando la temperatura baje de ese límite.

Cómo veis la aplicación tiene sistema de seguridad para evitar que dejéis frita la consola, independientemente de las protecciones que pueda tener el sistema. Ya me contaréis que os parece el tema (seguramente acabe integrándolo en Iris Manager, pero por el momento, estamos en fase de pruebas)

Qui invece in inglese (tradotto con google):
 

First of all, I open this thread here because it is a very specific firmware modification (CEX working on CFW 3.41, 3.55, 4.21, 4.30, 4.31 and 4.40), intended primarily to work under the environment of the games. It is not a simple adjustment of the fan speed, if not a payload that does the job regulating the fan speed depending on the temperature of the system, to try to avoid excessive overheating possible. For that reason I open it here and not in Scene, which also could be accommodated ..

The thread will have two purposes: first, to expose the development, research and the contributions themselves or you do you and on the other hand, the practice for those who just want to use the utility.

Let us begin by the development (if someone is not interested, jump to "The Aaplicación Fan Control")

Development: Research and Description

How I said in another thread, there is a call sys_sm_set_fan_policy syscall () that lets you control the ventilation. Specifically, I found that has at least 3 modes of operation are summarized in:

sys_sm_set_fan_policy (0, 0, 0) / / fan on full (speed 0xff)

sys_sm_set_fan_policy (0, 1, x) / / fan controlled by the SYSCON (the x does not seem to be used directly or is ignored by that autotune, but may also be factors when restarting / shutting down the system)

sys_sm_set_fan_policy (0, 2, x) / / manually controlled fan.

This latter mode, the 2, which interests us: the x is moved in the range of 0x33 (lower values ​​can be written, but is automatically corrected in the SYSCON) to 0xFF, it would be full power. This mode has its dangers, if not handled properly, since for example, if we adjust 0x33, speed is insufficient and the temperature will reach dangerous temperatures. So careful with this.

It appears that when you restart the system, the SYSCON changes to Mode 1 but the console off (red light) Mode 2 but still sets the value SYSCON 0x4D, how security measure, surely, because with this value Console cooling maintains acceptable levels.

In fact the SYSCON uses much lower values, usually. That I have seen, starting with the least 0x33, then up to 0x40, 0x44, 0x48 and rarely goes there, that the SYSCON operated in the range of 70 ° to 75 ° in the FAT (at least in mine), you seems acceptable and prefer less noise and higher temperatures, when we may want us otherwise.

All this can be seen by sys_sm_get_fan_policy syscall () which has five parameters that I have called like this:

sys_sm_get_fan_policy int (u8 id, u8 * st, u8 * mode, u8 * speed, u8 * unknown)
- Id is 0

- St and mode: reflect the current mode

- Speed: as the name suggests, reflects the value x of speed that we or the SYSCON adjusted, depending on mode.

- Unknown: I've seen (and you through this application) is always 0: I do not know if you have a specific use.

This syscall use it solely for informational purposes in the utility, but the payload does not use it.

Once we can control the fan speed, the following, but not least, we want to know the temperature regularly.

To do this, we sys_game_get_temperature syscall () that receives as first parameter 0 if we want to measure the temperature of the CPU and 1 for the RSX, while the second parameter is a variable that will store the value of temperature.

Finally, while decoratively, we use the sys_set_leds syscall () which allows us to put the LEDs in the state we want.

The problem with these is that they require syscalls type of permit applications and especially our games do not usually have: some require flags PM how related fan and other ROOT permissions. So no choice but to disable these checks by "pokes" like this:

/ / Enables sys_game_get_temperature
lv2poke32 (0x800000000000C694ULL, 0x38600000);
and that is the reason that the utility is limited to those CFW: missing required patches for the other .

Well, with everything said so far, you can mount an adjustment application modes at will, which can be fine if you only adapts the fan at a fixed speed and you're (in the style of those who do the mod potentiometer), but if we want something more "adjustable" then it gets tricky, because it requires that our code is running at system level and that required by the chosen route, make a payload and click some syscalls.

The Payload

And you should do the payload?. Well, in principle, be sampled for temperature, fan speed adjustment, if applicable, and then somehow notify us (via LED) if the temperature is within the parameters and such.

So that sounds easy, but how do we do this and how we find out that syscalls click?

Initially, I opted for the syscall click usleep () but that option was not being good at the end and I had to resort to another, which is what I will describe below (and prestadle attention, which is important )

First of all, you should know several things or at least, is what I was (if anyone knows other things that we tell)

- Applications run in user mode and when you call the syscalls, enter supervisor mode, kernel, LV2 or call it what you like.

- Applications use virtual memory, so we can not be sure if a particular memory block is mapped or worse, to allow scripts.

- Any attempt to pass LV2 memory of how variable will return with an error or simply ... not return

- Within LV2, just know that when a given syscall, use variables between their parameters. Which has its problems, if we need to use only receive values, but no usable memory address. So we need to acquire such information indirectly and that is a mess .

- Obviously, if we get a memory area that can "change" we need to ensure that the modification does not affect, or facing the application, data has not been modified (ie preserving the values)

- Well, our syscall to measure temperature, requires a whore Variable and that raises these difficulties.

- On the other hand, within LV2 can call certain syscalls or more specifically, the functions that handle these syscalls, but others can not (for example, block access to file system if, for example, do an open and then a read, without leaving to user mode)

With all these problems, we need a syscall above is called regularly in order to make our readings / settings and I had to discard usleep ().

The "salvation" came in the form of events: system events allow us, how its name suggests, receive events within the system, receiving a data series.

The sysEventQueueReceive syscall () is in charge of receiving and also provides a variable that can be used for temperature measurement. The syscall in its last parameter specifies the time in microseconds during which an event wait (0 means infinite).

One thing to keep in mind is that this syscall get ALL events that occur via applications and it is quite possible that while we are processing one event is received ANOTHER, if we delay in our work, so should be protected against them.

In fact, the required temperature takes between 7ms and 20ms and I ran into problems, because it exceeded the speed of response. at one point, causing a blockage.

So I changed my strategy and tried to figure out where the events were generated to whether to produce delay, was there and not in the receiver. To all this, I have to say I do not even know firsthand WHO, WHERE AND WHY generates events: simply, is that something generates events in cadence enough to allow me to do my reading and that the nature of these events occur in the XMB , in games, in the PSX emulator and the PSP. In PS2, at least in the hardware backwards my PS2 not, because the LV2 we know disappears and with it, my payload

There are several ways of producing events, but the most accessible, are the EventPort.

Prodding could see that indeed, is the origin of the calls. The sysEventPortSend syscall () sends in the records the following information

sysEventPortSend (sys_event_port_t portid, data0 U64, U64 data1, data2 U64)
How we see, no variables, only data, which we still need the help of sysEventQueueReceive () for a variable that can be modified.

The problem is that changing the caller should do in and not in the call, which is the variable that receives the program. That is, we need the hen to lay an egg, but no goose egg until birth

To jump that hurdle, I resorted to PID: if we know the process ID, we can compare, if sending and reception are in the same process and can therefore spend the goose egg from the chicken itself . Or for not rolling the matter, pass sysEventQueueReceive variable () for use by our procedures sysEventPortSend () (it is also necessary that in principle, we do not know if the recipient ESE EventPort how QueueReceive tended, because it relates to indirectly with the event!)

Perfect, done that, through safety checks of the respective PIDs, we can ensure that "mem_app" (in the payload) contains a script memory address we can use.

Once we close the circuit and see that it works, we are interested in discriminating try to find events that we find useful and discard others that are not and can only lead to problems. Doing several tests, it turns out that the reception is not lockable event (ie, it has a time limit) and that the event is generated and received, useful, has all the data to 0 (typically, an event data contains a number of useful and necessary information for programs. For example, device-related events, receive the kind of device in data2).

Now we need to do two things: if our events have a shelf life and short response capacity on the one hand, we need a time base to know how often read the temperature, etc., without ballast system and we also need to divide tasks perform to fulfill their duties without ballasting the system.

After successes and hardships, in the end, Timebase use a processor register (note: supposed to be one with that role, but no idea as used in CELL ) That counts the ticks since system boot (with that we can know how long it takes the console powered . In fact, the utility show that information as "PS3 Start Time")

The time base used, no idea . What I did in the end, is to make a couple of loops combined with real time clock sync first and then take a reading for 60 seconds with which to get the ticks per second are generated. The figure: 79,799,997 0x4c1a6bd or as you please. Nor need ciborium accuracy, just something that has a reasonable time

If anyone is curious to know how you get the ticks, this is the function:

[Code]
{
u64 ticks;
asm volatile("mftb %0" : "=r" (ticks));
return ticks;
} [/code[


It is assumed that at one point may give zero and should be entering loop until a valid reading. In fact, in the payload is done:

get_ticks:
MFTB% r4 / / get tick tick counter 1s = approx 79,799,997
cmpldi% r4, 0
beq get_ticks
SRDI% r4,% r4, 12 / / ticks/4096 0 => approx 1s ticks 0x4C1A

In this case, I use a 12-bit offset from the right to obtain a number of ticks with which to compare in a "reasonable" from assembler

In the end, the routine works like this:

- Divide the tasks so that first one gives a temperature reading that alternates between CPU and RSX. This task is time consuming in terms of events which is important divide

- How second task is to look if you need to correct the temperature and adjust the LEDs (which most of the time, you do not need)

- The timer is set to answer every 1.5 seconds. That is, the process of measuring the temperature of the CPU and make adjustments, it takes three seconds and as many for the RSX, so the total is 6 seconds, which is a good number.

- This timer can be skipped if time expired but could not produce a temperature reading that do not match or mem_app PIDS is zero.

- The PIDs are set to zero at certain times after use to prevent problems (remember we talked about syscalls that are used by the system and we ALL cases where results in chicken egg and goose egg results and sometimes, the chicken and egg dies at birth, mother was wrong and bundles )

- A very important detail that I have not mentioned is that to avoid a number of problems, I am forced to send BEFORE the event (ie pass the syscall) the actions I'm doing so I can not be sure whether the system, remember that supports two hardware threads and such, can be recepcionando the event as one thinks that until the syscall exit nothing happens. These thoughts "single-tasking" which usually incur, can make us steal the wallet and did not even have noticed. So, I try to cover my flag "IN_USE" so also are ignored calls that may be problematic (in fact, many ignore and the use of counter ticks)

In the main, this is the operation, one encounters problems and how to solve them on the fly: does not have to be the right or wrong approach, but simply, is how I have solved the problem and interestingly, not based on what he knew, if not based on what is not and I discover on my own.

Use the Payload

A feature of the payload is allowed to be located in any part of the system has been chosen for LV2 0xF70 address (remember that we must add a 0x80 .... 000 to form the 64-bit address) but could stay in any other part (using the method write_htab () included in Iris Manager source, we enable execution of prohibited parties LV2) and is compatible with any CFW theoretically.

As I said before, the patches to enable the syscalls that require permits, are the reason that this occurs for CFW 4.31 and 4.40.

In fact, I've only tested on 4.40 so hope I have not messed with the parties to 4.31

In the application, load_ps3_controlfan_payload function () loads the payload uniting the different syscalls (the loop and sleeps are to "ensure" that the payload is loaded fine)

The beginning of the ID payload contains 'PFAN' (0x5046414E) in the first 4 bytes. The following 4 bytes contain the offset into the payload (under this point of view, the payload starts at 0) where to find the data fan_control.

All data mentioned below are 32 bits:

In fan_control - 8 bytes can change the speed current comparator (this is only useful if you disable the payload, and you want to re-enable, causing it to update).

In fan_control - 4 can disable or enable the payload: 0 -> disabled, 1 - enabled without leds and 2 - with leds

In fan_control + 0 we can adjust the speed to be set if you call the sys_sm_shutdown syscall () to something other than a Reset or Normal shutdown (for example, when you turn the PS2 emulator on the console backward compatible, at least). 0x5F is assumed that the velocity is sufficient (in fact, high) to avoid problems, but of course, everything depends on the ambient temperature and what warms your PS3

This syscall is operated for otherwise, set the Mode 1, with the idea of ​​dotaros of some extra protection if not re-activate the application (if in that case, is in Mode 2, lack of regulation and depend on enough that the speed 0x4D)

From fan_control + 4 (inclusive) is the speed table that relate to temperatures temp_control4 temp_control0

Temperatures (all in ° C) temp_control0 to temp_control1 make a range in which you consider if temperatures started below temp_control0 and going up or going down from temp_control1 (if is getting warmer, the speed is less than if seeing the need to cool)

temp_control2 is a gear change while temp_control3 represents the turning point. In the default case of 70 ° the LED will blink yellow / green if the temperature is greater than or equal to 70 °

temp_control4 represents temperature alarm: in this case, the LED will flash in "disco" (yellow, red and green) and the speed is set to 0xA0, which is pretty cool noises and

An important detail every 11-12 seconds or so, the green LED illuminates for 1.5 seconds (unless you are in emergency room). It is the form that has the payload must say that is working (especially if it shows solid yellow LED)

And I do not think I miss anything important in this section (The source has enough payload comments)
Fan Control Application

The application is quite simple (if anyone wants to compile, you can use this build environment hilo_psdk3v2-windows-ps3-sdk-with-psl1ght-v2-tiny3d-and-ps3-soundilb_1867760 ) And displayed as the information text.

Just start mode is set to "# Payload" which is what we've been talking.

The information displayed is as follows:

CPU temperature / RSX temperature and elapsed time since the PS3 on

Parpedearán Temperatures in yellow when they reach 70 degrees and red when reaching 75 degrees

sys_sm_get_fan_policy here indicates the mode and speed that has set the SYSCON

Current Mode Indicates the current mode and set fan speed (mode 2 and payload)

Modes are summarized below. In Mode 2, with UP / UP speed climb and DOWN / DOWN bring it down. Remember that mode 2 is a mode with fixed speed and does not vary with temperature. Mode 1 is the normal system.

To switch modes using SQUARE / SQUARE and will change upstream (that allows for example, set a very low speed in Mode 2 for the hot console and then activate the Payload mode to see how it responds )

With the TRIANGLE button exits the application. Highly recommend using this button to exit and not from PS

Application Protection

- From the Payload mode, anti-shutdown protection, to set the protection mode

- If you turn off the console in Mode 2, is retained when you turn it on, look at this, even in principle, set a speed SYSCON supposedly taken.

- The SYSCON corrects the values ​​set below 0x33. Still, it has limited 0x30 Mode 2 to a minimum and how low speed when 0x4D flash blue Current Mode

- If you leave the application in Mode 2, the minimum speed is set to 0x5F, regardless of which had been fixed (by way of security and the Mode 2, it should not be fixed, unless it is intended the fan is working at high speed and in that case, the correct minimum is )

- Regardless of the mode, if the temperature is greater than or equal to 80 degrees, 0 mode is activated until the temperature falls below 60 degrees (when linking Payload Mode) or cambiéis yourself so when the temperature lower that limit.

How you see the application has a security system to prevent fried let the console, regardless of the protections you can have the system. Let me know what you think the issue (probably finished integrating it into Iris Manager, but for now, we're in beta)


Per chi vuole provarlo, troverà i download in basso. Ricordo che nè io, nè extreme generation è responsabile di eventuali danni alle console

Fan control utility v1.00
Fan control Utility v1.06
Fan control Utility v1.07