1 /*- 2 * Copyright (c) 2000 Michael Smith 3 * Copyright (c) 2000 BSDi 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 * 27 * $FreeBSD$ 28 */ 29 30 #include "opt_acpi.h" 31 #include <sys/param.h> 32 #include <sys/kernel.h> 33 #include <sys/bus.h> 34 35 #include "acpi.h" 36 37 #include <dev/acpica/acpivar.h> 38 39 /* 40 * Hooks for the ACPI CA debugging infrastructure 41 */ 42 #define _COMPONENT THERMAL_CONTROL 43 MODULE_NAME("THERMAL") 44 45 #define TZ_KELVTOC(x) (((x) - 2732) / 10), (((x) - 2732) % 10) 46 47 struct acpi_tz_softc { 48 device_t tz_dev; 49 ACPI_HANDLE tz_handle; 50 }; 51 52 static int acpi_tz_probe(device_t dev); 53 static int acpi_tz_attach(device_t dev); 54 static void acpi_tz_check_tripping_point(void *context); 55 static device_method_t acpi_tz_methods[] = { 56 /* Device interface */ 57 DEVMETHOD(device_probe, acpi_tz_probe), 58 DEVMETHOD(device_attach, acpi_tz_attach), 59 60 {0, 0} 61 }; 62 63 static driver_t acpi_tz_driver = { 64 "acpi_tz", 65 acpi_tz_methods, 66 sizeof(struct acpi_tz_softc), 67 }; 68 69 devclass_t acpi_tz_devclass; 70 DRIVER_MODULE(acpi_tz, acpi, acpi_tz_driver, acpi_tz_devclass, 0, 0); 71 72 static int 73 acpi_tz_probe(device_t dev) 74 { 75 76 FUNCTION_TRACE(__FUNCTION__); 77 78 if ((acpi_get_type(dev) == ACPI_TYPE_THERMAL) && 79 !acpi_disabled("thermal")) { 80 device_set_desc(dev, "thermal zone"); 81 return_VALUE(0); 82 } 83 return_VALUE(ENXIO); 84 } 85 static void acpi_tz_check_tripping_point(void *context) 86 { 87 device_t dev = context; 88 struct acpi_tz_softc *sc; 89 UINT32 param[4]; 90 ACPI_BUFFER b; 91 sc = device_get_softc(dev); 92 b.Pointer = ¶m[0]; 93 b.Length = sizeof(param); 94 if((AcpiEvaluateObject(sc->tz_handle,"_TMP",NULL,&b)) != AE_OK){ 95 device_printf(dev,"CANNOT FOUND _TMP\n"); 96 return; 97 } 98 99 device_printf(dev,"%d.%d K\n",param[1]/10,param[1]%10); 100 return; 101 } 102 #define ACPI_TZ_STATUS_CHANGE 0x80 103 #define ACPI_TZ_TRIPPOINT_CHANGE 0x81 104 static void acpi_tz_notify_handler( ACPI_HANDLE h,UINT32 notify, void *context) 105 { 106 device_t dev = context; 107 108 switch(notify){ 109 case ACPI_TZ_STATUS_CHANGE: 110 case ACPI_TZ_TRIPPOINT_CHANGE: 111 /*Check trip point*/ 112 AcpiOsQueueForExecution(OSD_PRIORITY_LO, 113 acpi_tz_check_tripping_point,context); 114 break; 115 } 116 } 117 static int 118 acpi_tz_attach(device_t dev) 119 { 120 struct acpi_tz_softc *sc; 121 UINT32 param[4]; 122 ACPI_BUFFER buf; 123 ACPI_STATUS status; 124 125 FUNCTION_TRACE(__FUNCTION__); 126 127 sc = device_get_softc(dev); 128 sc->tz_dev = dev; 129 sc->tz_handle = acpi_get_handle(dev); 130 131 buf.Pointer = ¶m[0]; 132 buf.Length = sizeof(param); 133 if ((status = AcpiEvaluateObject(sc->tz_handle, "_TMP", NULL, &buf)) != AE_OK) { 134 device_printf(sc->tz_dev, "can't fetch temperature - %s\n", acpi_strerror(status)); 135 return_VALUE(ENXIO); 136 } 137 if (param[0] != ACPI_TYPE_NUMBER) { 138 device_printf(sc->tz_dev, "%s._TMP does not evaluate to ACPI_TYPE_NUMBER\n", 139 acpi_name(sc->tz_handle)); 140 return_VALUE(ENXIO); 141 } 142 device_printf(sc->tz_dev, "current temperature %d.%dC\n", TZ_KELVTOC(param[1])); 143 144 AcpiInstallNotifyHandler(sc->tz_handle,ACPI_DEVICE_NOTIFY, 145 acpi_tz_notify_handler,dev); 146 return_VALUE(0); 147 } 148 149 150 151 152 153 154 155