Deleted Added
full compact
2c2
< * Copyright (c) 2000 Michael Smith
---
> * Copyright (c) 2000, 2001 Michael Smith
27c27
< * $FreeBSD: head/sys/dev/acpica/acpi_thermal.c 78662 2001-06-23 10:38:25Z iwasaki $
---
> * $FreeBSD: head/sys/dev/acpica/acpi_thermal.c 78915 2001-06-28 06:17:16Z msmith $
33a34
> #include <sys/reboot.h>
47a49,69
> #define TZ_NOTIFY_TEMPERATURE 0x80
> #define TZ_NOTIFY_DEVICES 0x81
> #define TZ_NOTIFY_LEVELS 0x82
>
> #define TZ_POLLRATE (hz * 10) /* every ten seconds */
>
> #define TZ_NUMLEVELS 10 /* defined by ACPI spec */
> struct acpi_tz_state {
> int ac[TZ_NUMLEVELS];
> ACPI_BUFFER al[TZ_NUMLEVELS];
> int crt;
> int hot;
> ACPI_BUFFER psl;
> int psv;
> int tc1;
> int tc2;
> int tsp;
> int tzp;
> };
>
>
49,51c71,81
< device_t tz_dev;
< ACPI_HANDLE tz_handle;
< int tz_tmp;
---
> device_t tz_dev;
> ACPI_HANDLE tz_handle;
> struct callout_handle tz_timeout;
> int tz_current;
> #define TZ_STATE_NONE 0
> #define TZ_STATE_PSV 1
> #define TZ_STATE_AC0 2
> #define TZ_STATE_HOT (TZ_STATE_AC0 + TZ_NUMLEVELS)
> #define TZ_STATE_CRT (TZ_STATE_AC0 + TZ_NUMLEVELS + 1)
>
> struct acpi_tz_state tz_state;
56c86,90
< static void acpi_tz_check_tripping_point(void *context);
---
> static int acpi_tz_establish(struct acpi_tz_softc *sc);
> static void acpi_tz_all_off(struct acpi_tz_softc *sc);
> static void acpi_tz_switch_cooler_off(ACPI_OBJECT *obj, void *arg);
> static void acpi_tz_switch_cooler_on(ACPI_OBJECT *obj, void *arg);
> static void acpi_tz_getparam(struct acpi_tz_softc *sc, char *node, int *data);
57a92
> static void acpi_tz_timeout(void *arg);
75a111,113
> /*
> * Match an ACPI thermal zone.
> */
80c118
< FUNCTION_TRACE(__func__);
---
> /* no FUNCTION_TRACE - too noisy */
85c123
< return_VALUE(0);
---
> return(-10);
87c125
< return_VALUE(ENXIO);
---
> return(ENXIO);
89a128,130
> /*
> * Attach to an ACPI thermal zone.
> */
94c135
< struct acpi_softc *acpi_sc;
---
> int error;
101a143,152
> /*
> * Parse the current state of the thermal zone and build control
> * structures.
> */
> if ((error = acpi_tz_establish(sc)) != 0)
> return_VALUE(error);
>
> /*
> * Register for any Notify events sent to this zone.
> */
105,112d155
< if (device_get_unit(dev) == 0) {
< acpi_sc = acpi_device_get_parent_softc(dev);
< SYSCTL_ADD_UINT(&acpi_sc->acpi_sysctl_ctx,
< SYSCTL_CHILDREN(acpi_sc->acpi_sysctl_tree),
< OID_AUTO, "temperature", CTLFLAG_RD,
< &sc->tz_tmp, 0, "");
< }
<
119a163,236
> /*
> * Parse the current state of this thermal zone and set up to use it.
> *
> * Note that we may have previous state, which will have to be discarded.
> */
> static int
> acpi_tz_establish(struct acpi_tz_softc *sc)
> {
> ACPI_OBJECT *obj;
> int i;
> char nbuf[8];
>
> FUNCTION_TRACE(__func__);
>
> /*
> * Power everything off and erase any existing state.
> */
> acpi_tz_all_off(sc);
> for (i = 0; i < TZ_NUMLEVELS; i++)
> if (sc->tz_state.al[i].Pointer != NULL)
> AcpiOsFree(sc->tz_state.al[i].Pointer);
> if (sc->tz_state.psl.Pointer != NULL)
> AcpiOsFree(sc->tz_state.psl.Pointer);
> bzero(&sc->tz_state, sizeof(sc->tz_state));
>
> /* kill the timeout (harmless if not running */
> untimeout(acpi_tz_timeout, sc, sc->tz_timeout);
>
> /*
> * Evaluate thermal zone parameters.
> */
> for (i = 0; i < TZ_NUMLEVELS; i++) {
> sprintf(nbuf, "_AC%d", i);
> acpi_tz_getparam(sc, nbuf, &sc->tz_state.ac[i]);
> sprintf(nbuf, "_AL%d", i);
> acpi_EvaluateIntoBuffer(sc->tz_handle, nbuf, NULL, &sc->tz_state.al[i]);
> obj = (ACPI_OBJECT *)sc->tz_state.al[i].Pointer;
> if (obj != NULL) {
> /* should be a package containing a list of power objects */
> if (obj->Type != ACPI_TYPE_PACKAGE) {
> device_printf(sc->tz_dev, "%s has unknown object type %d, rejecting\n",
> nbuf, obj->Type);
> return_VALUE(ENXIO);
> }
> }
> }
> acpi_tz_getparam(sc, "_CRT", &sc->tz_state.crt);
> acpi_tz_getparam(sc, "_HOT", &sc->tz_state.hot);
> acpi_EvaluateIntoBuffer(sc->tz_handle, "_PSL", NULL, &sc->tz_state.psl);
> acpi_tz_getparam(sc, "_PSV", &sc->tz_state.psv);
> acpi_tz_getparam(sc, "_TC1", &sc->tz_state.tc1);
> acpi_tz_getparam(sc, "_TC2", &sc->tz_state.tc2);
> acpi_tz_getparam(sc, "_TSP", &sc->tz_state.tsp);
> acpi_tz_getparam(sc, "_TZP", &sc->tz_state.tzp);
>
> /*
> * Power off everything that we've just been given.
> */
> acpi_tz_all_off(sc);
>
> /*
> * Do we need to poll the thermal zone? Ignore the suggested
> * rate.
> */
> if (sc->tz_state.tzp != 0)
> sc->tz_timeout = timeout(acpi_tz_timeout, sc, TZ_POLLRATE);
>
>
> return_VALUE(0);
> }
>
> /*
> * Evaluate the condition of a thermal zone, take appropriate actions.
> */
121c238
< acpi_tz_check_tripping_point(void *context)
---
> acpi_tz_monitor(struct acpi_tz_softc *sc)
123,126c240,241
< struct acpi_tz_softc *sc;
< device_t dev = context;
< ACPI_STATUS status;
< int tp;
---
> int temp, new;
> int i;
130,132c245,250
< sc = device_get_softc(dev);
< if ((status = acpi_EvaluateInteger(sc->tz_handle, "_TMP", &tp)) != AE_OK) {
< device_printf(dev, "can't evaluate _TMP method - %s\n", acpi_strerror(status));
---
> /*
> * Get the current temperature.
> */
> if ((acpi_EvaluateInteger(sc->tz_handle, "_TMP", &temp)) != AE_OK) {
> device_printf(sc->tz_dev, "error fetching current temperature\n");
> /* XXX disable zone? go to max cooling? */
134a253,272
>
> /*
> * Work out what we ought to be doing right now.
> */
> new = TZ_STATE_NONE;
> if ((sc->tz_state.psv != -1) && (temp > sc->tz_state.psv))
> new = TZ_STATE_PSV;
> for (i = 0; i < TZ_NUMLEVELS; i++)
> if ((sc->tz_state.ac[i] != -1) && (temp > sc->tz_state.ac[i]))
> new = TZ_STATE_AC0 + i;
> if ((sc->tz_state.hot != -1) && (temp > sc->tz_state.hot))
> new = TZ_STATE_HOT;
> if ((sc->tz_state.crt != -1) && (temp > sc->tz_state.crt))
> new = TZ_STATE_CRT;
>
> /*
> * If our state has not changed, do nothing.
> */
> if (new == sc->tz_current)
> return_VOID;
136,138c274,278
< sc->tz_tmp = (tp - TZ_ZEROC) / 10;
< if (bootverbose) {
< device_printf(dev, "%dC\n", sc->tz_tmp);
---
> /*
> * XXX if we're in a passive-cooling mode, revert to full-speed operation.
> */
> if (sc->tz_current == TZ_STATE_PSV) {
> /* XXX implement */
139a280,309
>
> /*
> * If we're in an active-cooling mode, turn off the current cooler(s).
> */
> if ((sc->tz_current >= TZ_STATE_AC0) && (sc->tz_current < (TZ_STATE_AC0 + TZ_NUMLEVELS)))
> acpi_ForeachPackageObject((ACPI_OBJECT *)sc->tz_state.al[sc->tz_current - TZ_STATE_AC0].Pointer,
> acpi_tz_switch_cooler_off, sc);
>
> /*
> * XXX If the new mode is passive-cooling, make appropriate adjustments.
> */
>
> /*
> * If the new mode is an active-cooling mode, turn on the new cooler(s).
> */
> if ((new >= TZ_STATE_AC0) && (new < (TZ_STATE_AC0 + TZ_NUMLEVELS)))
> acpi_ForeachPackageObject((ACPI_OBJECT *)sc->tz_state.al[new - TZ_STATE_AC0].Pointer,
> acpi_tz_switch_cooler_on, sc);
>
> /*
> * If we're _HOT or _CRT, shut down now!
> */
> if ((new == TZ_STATE_HOT) || (new == TZ_STATE_CRT)) {
> device_printf(sc->tz_dev, "WARNING - emergency thermal shutdown in progress.\n");
> shutdown_nice(RB_POWEROFF);
> }
>
> /* gone to new state */
> sc->tz_current = new;
>
143,144c313,315
< #define ACPI_TZ_STATUS_CHANGE 0x80
< #define ACPI_TZ_TRIPPOINT_CHANGE 0x81
---
> /*
> * Turn off all the cooling devices.
> */
145a317,428
> acpi_tz_all_off(struct acpi_tz_softc *sc)
> {
> int i;
>
> FUNCTION_TRACE(__func__);
>
> /*
> * Scan all the _AL objects, and turn them all off.
> */
> for (i = 0; i < TZ_NUMLEVELS; i++) {
> if (sc->tz_state.al[i].Pointer == NULL)
> continue;
> acpi_ForeachPackageObject((ACPI_OBJECT *)sc->tz_state.al[i].Pointer,
> acpi_tz_switch_cooler_off, sc);
> }
>
> /*
> * XXX revert any passive-cooling options.
> */
>
> sc->tz_current = TZ_STATE_NONE;
> return_VOID;
> }
>
> /*
> * Given an object, verify that it's a reference to a device of some sort,
> * and try to switch it off.
> */
> static void
> acpi_tz_switch_cooler_off(ACPI_OBJECT *obj, void *arg)
> {
> struct acpi_tz_softc *sc = (struct acpi_tz_softc *)arg;
> ACPI_HANDLE cooler;
>
> FUNCTION_TRACE(__func__);
>
> switch(obj->Type) {
> case ACPI_TYPE_STRING:
> DEBUG_PRINT(TRACE_OBJECTS, ("called to turn %s off\n", obj->String.Pointer));
>
> /*
> * Find the handle for the device and turn it off.
> * The String object here seems to contain a fully-qualified path, so we
> * don't have to search for it in our parents.
> *
> * XXX This may not always be the case.
> */
> if (AcpiGetHandle(obj->String.Pointer, NULL, &cooler) == AE_OK)
> acpi_pwr_switch_consumer(cooler, ACPI_STATE_D3);
> break;
>
> default:
> DEBUG_PRINT(TRACE_OBJECTS, ("called to handle unsupported object type %d\n",
> obj->Type));
> break;
> }
> return_VOID;
> }
>
> /*
> * Given an object, verify that it's a reference to a device of some sort,
> * and try to switch it on.
> *
> * XXX replication of off/on function code is bad, mmmkay?
> */
> static void
> acpi_tz_switch_cooler_on(ACPI_OBJECT *obj, void *arg)
> {
> struct acpi_tz_softc *sc = (struct acpi_tz_softc *)arg;
> ACPI_HANDLE cooler, parent;
>
> FUNCTION_TRACE(__func__);
>
> switch(obj->Type) {
> case ACPI_TYPE_STRING:
> DEBUG_PRINT(TRACE_OBJECTS, ("called to turn %s off\n", obj->String.Pointer));
>
> /* find the handle for the device and turn it off */
> if (acpi_GetHandleInScope(sc->tz_handle, obj->String.Pointer, &cooler) == AE_OK)
> acpi_pwr_switch_consumer(cooler, ACPI_STATE_D0);
> break;
>
> default:
> DEBUG_PRINT(TRACE_OBJECTS, ("called to handle unsupported object type %d\n",
> obj->Type));
> break;
> }
> return_VOID;
> }
>
> /*
> * Read/debug-print a parameter, default it to -1.
> */
> static void
> acpi_tz_getparam(struct acpi_tz_softc *sc, char *node, int *data)
> {
>
> FUNCTION_TRACE(__func__);
>
> if (acpi_EvaluateInteger(sc->tz_handle, node, data) != AE_OK) {
> *data = -1;
> } else {
> DEBUG_PRINT(TRACE_VALUES, ("%s.%s = %d\n", acpi_name(sc->tz_handle),
> node, *data));
> }
> return_VOID;
> }
>
> /*
> * Respond to a Notify event sent to the zone.
> */
> static void
147a431,432
> struct acpi_tz_softc *sc = (struct acpi_tz_softc *)context;
>
150,155c435,445
< switch(notify){
< case ACPI_TZ_STATUS_CHANGE:
< case ACPI_TZ_TRIPPOINT_CHANGE:
< /*Check trip point*/
< AcpiOsQueueForExecution(OSD_PRIORITY_LO, acpi_tz_check_tripping_point, context);
< break;
---
> switch(notify) {
> case TZ_NOTIFY_TEMPERATURE:
> acpi_tz_monitor(sc); /* temperature change occurred */
> break;
> case TZ_NOTIFY_DEVICES:
> case TZ_NOTIFY_LEVELS:
> acpi_tz_establish(sc); /* zone devices/setpoints changed */
> break;
> default:
> device_printf(sc->tz_dev, "unknown Notify event 0x%x\n", notify);
> break;
159a450,465
> /*
> * Poll the thermal zone.
> */
> static void
> acpi_tz_timeout(void *arg)
> {
> struct acpi_tz_softc *sc = (struct acpi_tz_softc *)arg;
>
> /* check temperature, take action */
> acpi_tz_monitor(sc);
>
> /* XXX passive cooling actions? */
>
> /* re-register ourself */
> sc->tz_timeout = timeout(acpi_tz_timeout, sc, TZ_POLLRATE);
> }