Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/acpi_support/acpi_ibm.c
| /*- | /*- | ||||
| * Copyright (c) 2004 Takanori Watanabe | * Copyright (c) 2004 Takanori Watanabe | ||||
| * Copyright (c) 2005 Markus Brueffer <markus@FreeBSD.org> | * Copyright (c) 2005 Markus Brueffer <markus@FreeBSD.org> | ||||
| * Copyright (c) 2018 Michael Gmelin <grembo@FreeBSD.org> | |||||
| * All rights reserved. | * All rights reserved. | ||||
| * | * | ||||
| * Redistribution and use in source and binary forms, with or without | * Redistribution and use in source and binary forms, with or without | ||||
| * modification, are permitted provided that the following conditions | * modification, are permitted provided that the following conditions | ||||
| * are met: | * are met: | ||||
| * 1. Redistributions of source code must retain the above copyright | * 1. Redistributions of source code must retain the above copyright | ||||
| * notice, this list of conditions and the following disclaimer. | * notice, this list of conditions and the following disclaimer. | ||||
| * 2. Redistributions in binary form must reproduce the above copyright | * 2. Redistributions in binary form must reproduce the above copyright | ||||
| ▲ Show 20 Lines • Show All 57 Lines • ▼ Show 20 Lines | |||||
| #define ACPI_IBM_METHOD_THINKLIGHT 7 | #define ACPI_IBM_METHOD_THINKLIGHT 7 | ||||
| #define ACPI_IBM_METHOD_BLUETOOTH 8 | #define ACPI_IBM_METHOD_BLUETOOTH 8 | ||||
| #define ACPI_IBM_METHOD_WLAN 9 | #define ACPI_IBM_METHOD_WLAN 9 | ||||
| #define ACPI_IBM_METHOD_FANSPEED 10 | #define ACPI_IBM_METHOD_FANSPEED 10 | ||||
| #define ACPI_IBM_METHOD_FANLEVEL 11 | #define ACPI_IBM_METHOD_FANLEVEL 11 | ||||
| #define ACPI_IBM_METHOD_FANSTATUS 12 | #define ACPI_IBM_METHOD_FANSTATUS 12 | ||||
| #define ACPI_IBM_METHOD_THERMAL 13 | #define ACPI_IBM_METHOD_THERMAL 13 | ||||
| #define ACPI_IBM_METHOD_HANDLEREVENTS 14 | #define ACPI_IBM_METHOD_HANDLEREVENTS 14 | ||||
| #define ACPI_IBM_METHOD_KBD_BACKLIGHT 15 | |||||
| #define ACPI_IBM_METHOD_KBD_BL_LEDON 16 | |||||
| #define ACPI_IBM_METHOD_KBD_BL_LEDOFF 17 | |||||
| #define ACPI_IBM_METHOD_MICMUTE_LED 18 | |||||
| /* Hotkeys/Buttons */ | /* Hotkeys/Buttons */ | ||||
| #define IBM_RTC_HOTKEY1 0x64 | #define IBM_RTC_HOTKEY1 0x64 | ||||
| #define IBM_RTC_MASK_HOME (1 << 0) | #define IBM_RTC_MASK_HOME (1 << 0) | ||||
| #define IBM_RTC_MASK_SEARCH (1 << 1) | #define IBM_RTC_MASK_SEARCH (1 << 1) | ||||
| #define IBM_RTC_MASK_MAIL (1 << 2) | #define IBM_RTC_MASK_MAIL (1 << 2) | ||||
| #define IBM_RTC_MASK_WLAN (1 << 5) | #define IBM_RTC_MASK_WLAN (1 << 5) | ||||
| #define IBM_RTC_HOTKEY2 0x65 | #define IBM_RTC_HOTKEY2 0x65 | ||||
| Show All 39 Lines | |||||
| #define IBM_NAME_THERMAL_UPDT "UPDT" | #define IBM_NAME_THERMAL_UPDT "UPDT" | ||||
| #define IBM_NAME_EVENTS_STATUS_GET "DHKC" | #define IBM_NAME_EVENTS_STATUS_GET "DHKC" | ||||
| #define IBM_NAME_EVENTS_MASK_GET "DHKN" | #define IBM_NAME_EVENTS_MASK_GET "DHKN" | ||||
| #define IBM_NAME_EVENTS_STATUS_SET "MHKC" | #define IBM_NAME_EVENTS_STATUS_SET "MHKC" | ||||
| #define IBM_NAME_EVENTS_MASK_SET "MHKM" | #define IBM_NAME_EVENTS_MASK_SET "MHKM" | ||||
| #define IBM_NAME_EVENTS_GET "MHKP" | #define IBM_NAME_EVENTS_GET "MHKP" | ||||
| #define IBM_NAME_EVENTS_AVAILMASK "MHKA" | #define IBM_NAME_EVENTS_AVAILMASK "MHKA" | ||||
| #define IBM_NAME_EVENTS_VERSION "MHKV" | |||||
| #define IBM_NAME_KBD_BACKLIGHT_GET "MLCG" | |||||
| #define IBM_NAME_MASK_KBD_BL_SUPPORT (1 << 9) | |||||
| #define IBM_NAME_MASK_KBD_BL_LEVEL 0x3 | |||||
| #define IBM_NAME_KBD_BACKLIGHT_SET "MLCS" | |||||
| #define IBM_NAME_MICMUTE_LED_SET "MMTS" | |||||
| #define IBM_NAME_MICMUTE_LED_OFF 0x0 | |||||
| #define IBM_NAME_MICMUTE_LED_ON 0x2 | |||||
| #define IBM_NAME_MICMUTE_LED_BLINK 0x3 | |||||
| /* Event Code */ | /* Event Code */ | ||||
| #define IBM_EVENT_LCD_BACKLIGHT 0x03 | #define IBM_EVENT_LCD_BACKLIGHT 0x03 | ||||
| #define IBM_EVENT_SUSPEND_TO_RAM 0x04 | #define IBM_EVENT_SUSPEND_TO_RAM 0x04 | ||||
| #define IBM_EVENT_BLUETOOTH 0x05 | #define IBM_EVENT_BLUETOOTH 0x05 | ||||
| #define IBM_EVENT_SCREEN_EXPAND 0x07 | #define IBM_EVENT_SCREEN_EXPAND 0x07 | ||||
| #define IBM_EVENT_SUSPEND_TO_DISK 0x0c | #define IBM_EVENT_SUSPEND_TO_DISK 0x0c | ||||
| #define IBM_EVENT_BRIGHTNESS_UP 0x10 | #define IBM_EVENT_BRIGHTNESS_UP 0x10 | ||||
| #define IBM_EVENT_BRIGHTNESS_DOWN 0x11 | #define IBM_EVENT_BRIGHTNESS_DOWN 0x11 | ||||
| Show All 24 Lines | struct acpi_ibm_softc { | ||||
| /* Keylight commands and states */ | /* Keylight commands and states */ | ||||
| ACPI_HANDLE light_handle; | ACPI_HANDLE light_handle; | ||||
| int light_cmd_on; | int light_cmd_on; | ||||
| int light_cmd_off; | int light_cmd_off; | ||||
| int light_val; | int light_val; | ||||
| int light_get_supported; | int light_get_supported; | ||||
| int light_set_supported; | int light_set_supported; | ||||
| /* led(4) interface */ | /* led(4) interface for thinklight */ | ||||
| struct cdev *led_dev; | struct cdev *led_dev; | ||||
| int led_busy; | int led_busy; | ||||
| int led_state; | int led_state; | ||||
| /* Keyboard backlight support */ | |||||
| int kbd_backlight_supported; | |||||
| int kbd_backlight_val; | |||||
| /* led(4) interface for keyboard backlight */ | |||||
| struct cdev *kbd_backlight_led_dev; | |||||
| int kbd_backlight_led_busy; | |||||
| int kbd_backlight_led_state; | |||||
| int kbd_backlight_ledon; | |||||
| int kbd_backlight_ledoff; | |||||
| /* micmute led */ | |||||
| int micmute_led_supported; | |||||
| int micmute_led_val; | |||||
| /* led(4) interface for micmute led */ | |||||
| struct cdev *micmute_led_dev; | |||||
| int micmute_led_busy; | |||||
| int micmute_led_state; | |||||
| int wlan_bt_flags; | int wlan_bt_flags; | ||||
| int thermal_updt_supported; | int thermal_updt_supported; | ||||
| unsigned int events_availmask; | unsigned int events_availmask; | ||||
| unsigned int events_initialmask; | unsigned int events_initialmask; | ||||
| int events_mask_supported; | int events_mask_supported; | ||||
| int events_enable; | int events_enable; | ||||
| ▲ Show 20 Lines • Show All 67 Lines • ▼ Show 20 Lines | int flag_rdonly; | ||||
| .method = ACPI_IBM_METHOD_FANLEVEL, | .method = ACPI_IBM_METHOD_FANLEVEL, | ||||
| .description = "Fan level", | .description = "Fan level", | ||||
| }, | }, | ||||
| { | { | ||||
| .name = "fan", | .name = "fan", | ||||
| .method = ACPI_IBM_METHOD_FANSTATUS, | .method = ACPI_IBM_METHOD_FANSTATUS, | ||||
| .description = "Fan enable", | .description = "Fan enable", | ||||
| }, | }, | ||||
| { | |||||
| .name = "kbd_backlight", | |||||
| .method = ACPI_IBM_METHOD_KBD_BACKLIGHT, | |||||
| .description = "Keyboard backlight level", | |||||
| }, | |||||
| { | |||||
| .name = "kbd_backlight_ledon", | |||||
| .method = ACPI_IBM_METHOD_KBD_BL_LEDON, | |||||
| .description = "Keyboard backlight LED on level", | |||||
| }, | |||||
| { | |||||
| .name = "kbd_backlight_ledoff", | |||||
| .method = ACPI_IBM_METHOD_KBD_BL_LEDOFF, | |||||
| .description = "Keyboard backlight LED off level", | |||||
| }, | |||||
| { | |||||
| .name = "micmute_led", | |||||
| .method = ACPI_IBM_METHOD_MICMUTE_LED, | |||||
| .description = "Control micmute LED", | |||||
| }, | |||||
| { NULL, 0, NULL, 0 } | { NULL, 0, NULL, 0 } | ||||
| }; | }; | ||||
| /* | /* | ||||
| * Per-model default list of event mask. | * Per-model default list of event mask. | ||||
| */ | */ | ||||
| #define ACPI_IBM_HKEY_RFKILL_MASK (1 << 4) | #define ACPI_IBM_HKEY_RFKILL_MASK (1 << 4) | ||||
| Show All 29 Lines | |||||
| static int acpi_ibm_probe(device_t dev); | static int acpi_ibm_probe(device_t dev); | ||||
| static int acpi_ibm_attach(device_t dev); | static int acpi_ibm_attach(device_t dev); | ||||
| static int acpi_ibm_detach(device_t dev); | static int acpi_ibm_detach(device_t dev); | ||||
| static int acpi_ibm_resume(device_t dev); | static int acpi_ibm_resume(device_t dev); | ||||
| static void ibm_led(void *softc, int onoff); | static void ibm_led(void *softc, int onoff); | ||||
| static void ibm_led_task(struct acpi_ibm_softc *sc, int pending __unused); | static void ibm_led_task(struct acpi_ibm_softc *sc, int pending __unused); | ||||
| static void ibm_kbd_backlight_led(void *softc, int onoff); | |||||
| static void ibm_kbd_backlight_led_task(struct acpi_ibm_softc *sc, | |||||
| int pending __unused); | |||||
| static void ibm_micmute_led(void *softc, int onoff); | |||||
| static void ibm_micmute_led_task(struct acpi_ibm_softc *sc, int pending __unused); | |||||
| static int acpi_ibm_sysctl(SYSCTL_HANDLER_ARGS); | static int acpi_ibm_sysctl(SYSCTL_HANDLER_ARGS); | ||||
| static int acpi_ibm_sysctl_init(struct acpi_ibm_softc *sc, int method); | static int acpi_ibm_sysctl_init(struct acpi_ibm_softc *sc, int method); | ||||
| static int acpi_ibm_sysctl_get(struct acpi_ibm_softc *sc, int method); | static int acpi_ibm_sysctl_get(struct acpi_ibm_softc *sc, int method); | ||||
| static int acpi_ibm_sysctl_set(struct acpi_ibm_softc *sc, int method, int val); | static int acpi_ibm_sysctl_set(struct acpi_ibm_softc *sc, int method, int val); | ||||
| static int acpi_ibm_eventmask_set(struct acpi_ibm_softc *sc, int val); | static int acpi_ibm_eventmask_set(struct acpi_ibm_softc *sc, int val); | ||||
| static int acpi_ibm_thermal_sysctl(SYSCTL_HANDLER_ARGS); | static int acpi_ibm_thermal_sysctl(SYSCTL_HANDLER_ARGS); | ||||
| static int acpi_ibm_handlerevents_sysctl(SYSCTL_HANDLER_ARGS); | static int acpi_ibm_handlerevents_sysctl(SYSCTL_HANDLER_ARGS); | ||||
| static void acpi_ibm_notify(ACPI_HANDLE h, UINT32 notify, void *context); | static void acpi_ibm_notify(ACPI_HANDLE h, UINT32 notify, void *context); | ||||
| static int acpi_ibm_brightness_set(struct acpi_ibm_softc *sc, int arg); | static int acpi_ibm_brightness_set(struct acpi_ibm_softc *sc, int arg); | ||||
| static int acpi_ibm_bluetooth_set(struct acpi_ibm_softc *sc, int arg); | static int acpi_ibm_bluetooth_set(struct acpi_ibm_softc *sc, int arg); | ||||
| static int acpi_ibm_thinklight_set(struct acpi_ibm_softc *sc, int arg); | static int acpi_ibm_thinklight_set(struct acpi_ibm_softc *sc, int arg); | ||||
| static int acpi_ibm_volume_set(struct acpi_ibm_softc *sc, int arg); | static int acpi_ibm_volume_set(struct acpi_ibm_softc *sc, int arg); | ||||
| static int acpi_ibm_mute_set(struct acpi_ibm_softc *sc, int arg); | static int acpi_ibm_mute_set(struct acpi_ibm_softc *sc, int arg); | ||||
| static int acpi_ibm_kbd_backlight_set(struct acpi_ibm_softc *sc, int arg); | |||||
| static int acpi_ibm_micmute_led_set(struct acpi_ibm_softc *sc, int arg); | |||||
| static device_method_t acpi_ibm_methods[] = { | static device_method_t acpi_ibm_methods[] = { | ||||
| /* Device interface */ | /* Device interface */ | ||||
| DEVMETHOD(device_probe, acpi_ibm_probe), | DEVMETHOD(device_probe, acpi_ibm_probe), | ||||
| DEVMETHOD(device_attach, acpi_ibm_attach), | DEVMETHOD(device_attach, acpi_ibm_attach), | ||||
| DEVMETHOD(device_detach, acpi_ibm_detach), | DEVMETHOD(device_detach, acpi_ibm_detach), | ||||
| DEVMETHOD(device_resume, acpi_ibm_resume), | DEVMETHOD(device_resume, acpi_ibm_resume), | ||||
| DEVMETHOD_END | DEVMETHOD_END | ||||
| }; | }; | ||||
| static driver_t acpi_ibm_driver = { | static driver_t acpi_ibm_driver = { | ||||
| "acpi_ibm", | "acpi_ibm", | ||||
| acpi_ibm_methods, | acpi_ibm_methods, | ||||
| sizeof(struct acpi_ibm_softc), | sizeof(struct acpi_ibm_softc), | ||||
| }; | }; | ||||
| static devclass_t acpi_ibm_devclass; | static devclass_t acpi_ibm_devclass; | ||||
| DRIVER_MODULE(acpi_ibm, acpi, acpi_ibm_driver, acpi_ibm_devclass, | DRIVER_MODULE(acpi_ibm, acpi, acpi_ibm_driver, acpi_ibm_devclass, | ||||
| 0, 0); | 0, 0); | ||||
| MODULE_DEPEND(acpi_ibm, acpi, 1, 1, 1); | MODULE_DEPEND(acpi_ibm, acpi, 1, 1, 1); | ||||
| static char *ibm_ids[] = {"IBM0068", "LEN0068", NULL}; | static char *ibm_ids[] = {"IBM0068", "LEN0068", "LEN0268", NULL}; | ||||
| static void | static void | ||||
| ibm_led(void *softc, int onoff) | ibm_led(void *softc, int onoff) | ||||
| { | { | ||||
| struct acpi_ibm_softc* sc = (struct acpi_ibm_softc*) softc; | struct acpi_ibm_softc* sc = (struct acpi_ibm_softc*) softc; | ||||
| ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); | ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); | ||||
| Show All 13 Lines | ibm_led_task(struct acpi_ibm_softc *sc, int pending __unused) | ||||
| ACPI_SERIAL_BEGIN(ibm); | ACPI_SERIAL_BEGIN(ibm); | ||||
| acpi_ibm_sysctl_set(sc, ACPI_IBM_METHOD_THINKLIGHT, sc->led_state); | acpi_ibm_sysctl_set(sc, ACPI_IBM_METHOD_THINKLIGHT, sc->led_state); | ||||
| ACPI_SERIAL_END(ibm); | ACPI_SERIAL_END(ibm); | ||||
| sc->led_busy = 0; | sc->led_busy = 0; | ||||
| } | } | ||||
| static void | |||||
| ibm_kbd_backlight_led(void *softc, int onoff) | |||||
| { | |||||
| struct acpi_ibm_softc* sc = (struct acpi_ibm_softc*) softc; | |||||
| ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); | |||||
| if (sc->kbd_backlight_led_busy) | |||||
| return; | |||||
| sc->kbd_backlight_led_busy = 1; | |||||
| sc->kbd_backlight_led_state = onoff; | |||||
| AcpiOsExecute(OSL_NOTIFY_HANDLER, (void *)ibm_kbd_backlight_led_task, | |||||
| sc); | |||||
| } | |||||
| static void | |||||
| ibm_kbd_backlight_led_task(struct acpi_ibm_softc *sc, int pending __unused) | |||||
| { | |||||
| ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); | |||||
| ACPI_SERIAL_BEGIN(ibm); | |||||
| acpi_ibm_sysctl_set(sc, ACPI_IBM_METHOD_KBD_BACKLIGHT, | |||||
| sc->kbd_backlight_led_state ? | |||||
| sc->kbd_backlight_ledon : sc->kbd_backlight_ledoff); | |||||
| ACPI_SERIAL_END(ibm); | |||||
| sc->kbd_backlight_led_busy = 0; | |||||
| } | |||||
| static void | |||||
| ibm_micmute_led(void *softc, int onoff) | |||||
| { | |||||
| struct acpi_ibm_softc* sc = (struct acpi_ibm_softc*) softc; | |||||
| ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); | |||||
| if (sc->micmute_led_busy) | |||||
| return; | |||||
| sc->micmute_led_busy = 1; | |||||
| sc->micmute_led_state = onoff; | |||||
| AcpiOsExecute(OSL_NOTIFY_HANDLER, (void *)ibm_micmute_led_task, sc); | |||||
| } | |||||
| static void | |||||
| ibm_micmute_led_task(struct acpi_ibm_softc *sc, int pending __unused) | |||||
| { | |||||
| ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); | |||||
| ACPI_SERIAL_BEGIN(ibm); | |||||
| acpi_ibm_sysctl_set(sc, ACPI_IBM_METHOD_MICMUTE_LED, | |||||
| sc->micmute_led_state); | |||||
| ACPI_SERIAL_END(ibm); | |||||
| sc->micmute_led_busy = 0; | |||||
| } | |||||
| static int | static int | ||||
| acpi_ibm_probe(device_t dev) | acpi_ibm_probe(device_t dev) | ||||
| { | { | ||||
| if (acpi_disabled("ibm") || | if (acpi_disabled("ibm") || | ||||
| ACPI_ID_PROBE(device_get_parent(dev), dev, ibm_ids) == NULL || | ACPI_ID_PROBE(device_get_parent(dev), dev, ibm_ids) == NULL || | ||||
| device_get_unit(dev) != 0) | device_get_unit(dev) != 0) | ||||
| return (ENXIO); | return (ENXIO); | ||||
| device_set_desc(dev, "IBM ThinkPad ACPI Extras"); | device_set_desc(dev, "IBM ThinkPad ACPI Extras"); | ||||
| return (0); | return (0); | ||||
| } | } | ||||
| static int | static int | ||||
| acpi_ibm_attach(device_t dev) | acpi_ibm_attach(device_t dev) | ||||
| { | { | ||||
| int i; | ACPI_OBJECT p, *bufp; | ||||
| ACPI_OBJECT_LIST args; | |||||
| ACPI_BUFFER buf; | |||||
| int hkey_version; | |||||
| struct acpi_ibm_softc *sc; | struct acpi_ibm_softc *sc; | ||||
| char *maker, *product; | char *maker, *product; | ||||
| devclass_t ec_devclass; | devclass_t ec_devclass; | ||||
| ACPI_FUNCTION_TRACE((char *)(uintptr_t) __func__); | ACPI_FUNCTION_TRACE((char *)(uintptr_t) __func__); | ||||
| sc = device_get_softc(dev); | sc = device_get_softc(dev); | ||||
| sc->dev = dev; | sc->dev = dev; | ||||
| Show All 21 Lines | sc->events_mask_supported = ACPI_SUCCESS(acpi_GetInteger(sc->handle, | ||||
| IBM_NAME_EVENTS_MASK_GET, &sc->events_initialmask)); | IBM_NAME_EVENTS_MASK_GET, &sc->events_initialmask)); | ||||
| if (sc->events_mask_supported) { | if (sc->events_mask_supported) { | ||||
| SYSCTL_ADD_UINT(sc->sysctl_ctx, | SYSCTL_ADD_UINT(sc->sysctl_ctx, | ||||
| SYSCTL_CHILDREN(sc->sysctl_tree), OID_AUTO, | SYSCTL_CHILDREN(sc->sysctl_tree), OID_AUTO, | ||||
| "initialmask", CTLFLAG_RD, | "initialmask", CTLFLAG_RD, | ||||
| &sc->events_initialmask, 0, "Initial eventmask"); | &sc->events_initialmask, 0, "Initial eventmask"); | ||||
| /* The availmask is the bitmask of supported events */ | /* | ||||
| * The availmask is the bitmask of supported events, it's determined | |||||
| * by calling MHKA. Old pre-0x100 versions of the hkey interface (MHKV) | |||||
emaste: s/MKHV/MHKV/ | |||||
| * take no parameter to determine the hotkey mask. Newer models | |||||
| * (post-2015, like T460, T470s, Carbon X1) take one integer parameter: | |||||
| * 1: Retrieve availmask like before | |||||
| * 2: Retrieve adaptive keyboard mask (currently not supported | |||||
| * by this driver), only supported on models featuring | |||||
| * the adaptive keyboard, otherwise returns 0 | |||||
| */ | |||||
| if (ACPI_FAILURE(acpi_GetInteger(sc->handle, | if (ACPI_FAILURE(acpi_GetInteger(sc->handle, | ||||
| IBM_NAME_EVENTS_VERSION, &hkey_version))) | |||||
| hkey_version = 0x100; /* default to version 1 of the hkey interface */ | |||||
| if ((hkey_version >> 8) < 2) { | |||||
| if (ACPI_FAILURE(acpi_GetInteger(sc->handle, | |||||
| IBM_NAME_EVENTS_AVAILMASK, &sc->events_availmask))) | IBM_NAME_EVENTS_AVAILMASK, &sc->events_availmask))) | ||||
| sc->events_availmask = 0xffffffff; | sc->events_availmask = 0xffffffff; | ||||
| } else { | |||||
| p.Type = ACPI_TYPE_INTEGER; | |||||
| p.Integer.Value = 1; | |||||
| args.Count = 1; | |||||
| args.Pointer = &p; | |||||
| buf.Length = ACPI_ALLOCATE_BUFFER; | |||||
| if (ACPI_FAILURE(AcpiEvaluateObjectTyped(sc->handle, | |||||
| IBM_NAME_EVENTS_AVAILMASK, &args, &buf, | |||||
| ACPI_TYPE_INTEGER))) | |||||
| sc->events_availmask = 0xffffffff; | |||||
| else { | |||||
| bufp = buf.Pointer; | |||||
| sc->events_availmask= bufp->Integer.Value; | |||||
| AcpiOsFree(buf.Pointer); | |||||
| } | |||||
| } | |||||
| SYSCTL_ADD_UINT(sc->sysctl_ctx, | SYSCTL_ADD_UINT(sc->sysctl_ctx, | ||||
| SYSCTL_CHILDREN(sc->sysctl_tree), OID_AUTO, | SYSCTL_CHILDREN(sc->sysctl_tree), OID_AUTO, | ||||
| "availmask", CTLFLAG_RD, | "availmask", CTLFLAG_RD, | ||||
| &sc->events_availmask, 0, "Mask of supported events"); | &sc->events_availmask, 0, "Mask of supported events"); | ||||
| } | } | ||||
| /* Hook up proc nodes */ | /* Hook up proc nodes */ | ||||
| Show All 38 Lines | acpi_ibm_attach(device_t dev) | ||||
| AcpiInstallNotifyHandler(sc->handle, ACPI_DEVICE_NOTIFY, | AcpiInstallNotifyHandler(sc->handle, ACPI_DEVICE_NOTIFY, | ||||
| acpi_ibm_notify, dev); | acpi_ibm_notify, dev); | ||||
| /* Hook up light to led(4) */ | /* Hook up light to led(4) */ | ||||
| if (sc->light_set_supported) | if (sc->light_set_supported) | ||||
| sc->led_dev = led_create_state(ibm_led, sc, "thinklight", | sc->led_dev = led_create_state(ibm_led, sc, "thinklight", | ||||
| (sc->light_val ? 1 : 0)); | (sc->light_val ? 1 : 0)); | ||||
| /* Hook up keyboard backlight to led(4) */ | |||||
| if (sc->kbd_backlight_supported) | |||||
| sc->kbd_backlight_led_dev = led_create_state( | |||||
| ibm_kbd_backlight_led, sc, "kbd_backlight", | |||||
| (sc->kbd_backlight_val ? 1 : 0)); | |||||
| if (sc->micmute_led_supported) | |||||
| sc->micmute_led_dev = led_create_state(ibm_micmute_led, sc, | |||||
| "micmute", 0); | |||||
| /* Enable per-model events. */ | /* Enable per-model events. */ | ||||
| maker = kern_getenv("smbios.system.maker"); | maker = kern_getenv("smbios.system.maker"); | ||||
| product = kern_getenv("smbios.system.product"); | product = kern_getenv("smbios.system.product"); | ||||
| if (maker == NULL || product == NULL) | if (maker == NULL || product == NULL) | ||||
| goto nosmbios; | goto nosmbios; | ||||
| for (i = 0; i < nitems(acpi_ibm_models); i++) { | for (int i = 0; i < nitems(acpi_ibm_models); i++) { | ||||
| if (strcmp(maker, acpi_ibm_models[i].maker) == 0 && | if (strcmp(maker, acpi_ibm_models[i].maker) == 0 && | ||||
| strcmp(product, acpi_ibm_models[i].product) == 0) { | strcmp(product, acpi_ibm_models[i].product) == 0) { | ||||
| ACPI_SERIAL_BEGIN(ibm); | ACPI_SERIAL_BEGIN(ibm); | ||||
| acpi_ibm_sysctl_set(sc, ACPI_IBM_METHOD_EVENTMASK, | acpi_ibm_sysctl_set(sc, ACPI_IBM_METHOD_EVENTMASK, | ||||
| acpi_ibm_models[i].eventmask); | acpi_ibm_models[i].eventmask); | ||||
| ACPI_SERIAL_END(ibm); | ACPI_SERIAL_END(ibm); | ||||
| } | } | ||||
| } | } | ||||
| Show All 24 Lines | acpi_ibm_detach(device_t dev) | ||||
| acpi_ibm_sysctl_set(sc, ACPI_IBM_METHOD_EVENTMASK, sc->events_initialmask); | acpi_ibm_sysctl_set(sc, ACPI_IBM_METHOD_EVENTMASK, sc->events_initialmask); | ||||
| ACPI_SERIAL_END(ibm); | ACPI_SERIAL_END(ibm); | ||||
| AcpiRemoveNotifyHandler(sc->handle, ACPI_DEVICE_NOTIFY, acpi_ibm_notify); | AcpiRemoveNotifyHandler(sc->handle, ACPI_DEVICE_NOTIFY, acpi_ibm_notify); | ||||
| if (sc->led_dev != NULL) | if (sc->led_dev != NULL) | ||||
| led_destroy(sc->led_dev); | led_destroy(sc->led_dev); | ||||
| if (sc->kbd_backlight_led_dev != NULL) | |||||
| led_destroy(sc->kbd_backlight_led_dev); | |||||
| if (sc->micmute_led_dev != NULL) | |||||
| led_destroy(sc->micmute_led_dev); | |||||
| return (0); | return (0); | ||||
| } | } | ||||
| static int | static int | ||||
| acpi_ibm_resume(device_t dev) | acpi_ibm_resume(device_t dev) | ||||
| { | { | ||||
| struct acpi_ibm_softc *sc = device_get_softc(dev); | struct acpi_ibm_softc *sc = device_get_softc(dev); | ||||
| ▲ Show 20 Lines • Show All 194 Lines • ▼ Show 20 Lines | acpi_ibm_sysctl_get(struct acpi_ibm_softc *sc, int method) | ||||
| case ACPI_IBM_METHOD_FANSTATUS: | case ACPI_IBM_METHOD_FANSTATUS: | ||||
| if (!sc->fan_handle) { | if (!sc->fan_handle) { | ||||
| ACPI_EC_READ(sc->ec_dev, IBM_EC_FANSTATUS, &val_ec, 1); | ACPI_EC_READ(sc->ec_dev, IBM_EC_FANSTATUS, &val_ec, 1); | ||||
| val = (val_ec & IBM_EC_MASK_FANSTATUS) == IBM_EC_MASK_FANSTATUS; | val = (val_ec & IBM_EC_MASK_FANSTATUS) == IBM_EC_MASK_FANSTATUS; | ||||
| } | } | ||||
| else | else | ||||
| val = -1; | val = -1; | ||||
| break; | break; | ||||
| case ACPI_IBM_METHOD_KBD_BACKLIGHT: | |||||
| if (sc->kbd_backlight_supported) | |||||
| acpi_GetInteger(sc->handle, IBM_NAME_KBD_BACKLIGHT_GET, &val); | |||||
| else | |||||
| val = sc->kbd_backlight_val; | |||||
| val &= IBM_NAME_MASK_KBD_BL_LEVEL; | |||||
| break; | |||||
| case ACPI_IBM_METHOD_KBD_BL_LEDON: | |||||
| val = sc->kbd_backlight_ledon; | |||||
| break; | |||||
| case ACPI_IBM_METHOD_KBD_BL_LEDOFF: | |||||
| val = sc->kbd_backlight_ledoff; | |||||
| break; | |||||
| case ACPI_IBM_METHOD_MICMUTE_LED: | |||||
| val = sc->micmute_led_val; | |||||
| break; | |||||
| } | } | ||||
| return (val); | return (val); | ||||
| } | } | ||||
| static int | static int | ||||
| acpi_ibm_sysctl_set(struct acpi_ibm_softc *sc, int method, int arg) | acpi_ibm_sysctl_set(struct acpi_ibm_softc *sc, int method, int arg) | ||||
| { | { | ||||
| ▲ Show 20 Lines • Show All 61 Lines • ▼ Show 20 Lines | case ACPI_IBM_METHOD_FANSTATUS: | ||||
| if (!sc->fan_handle) { | if (!sc->fan_handle) { | ||||
| /* Read the current fanstatus */ | /* Read the current fanstatus */ | ||||
| ACPI_EC_READ(sc->ec_dev, IBM_EC_FANSTATUS, &val_ec, 1); | ACPI_EC_READ(sc->ec_dev, IBM_EC_FANSTATUS, &val_ec, 1); | ||||
| return ACPI_EC_WRITE(sc->ec_dev, IBM_EC_FANSTATUS, | return ACPI_EC_WRITE(sc->ec_dev, IBM_EC_FANSTATUS, | ||||
| (arg == 1) ? (val_ec | IBM_EC_MASK_FANSTATUS) : (val_ec & (~IBM_EC_MASK_FANSTATUS)), 1); | (arg == 1) ? (val_ec | IBM_EC_MASK_FANSTATUS) : (val_ec & (~IBM_EC_MASK_FANSTATUS)), 1); | ||||
| } | } | ||||
| break; | break; | ||||
| case ACPI_IBM_METHOD_KBD_BACKLIGHT: | |||||
| return acpi_ibm_kbd_backlight_set(sc, arg); | |||||
| break; | |||||
| case ACPI_IBM_METHOD_KBD_BL_LEDON: | |||||
| if (arg < 0 || arg > 2) | |||||
| return (EINVAL); | |||||
Done Inline Actionsextra whitespace here emaste: extra whitespace here | |||||
| sc->kbd_backlight_ledon = arg; | |||||
| break; | |||||
| case ACPI_IBM_METHOD_KBD_BL_LEDOFF: | |||||
| if (arg < 0 || arg > 2) | |||||
| return (EINVAL); | |||||
Done Inline Actionsand here emaste: and here | |||||
| sc->kbd_backlight_ledoff = arg; | |||||
| break; | |||||
| case ACPI_IBM_METHOD_MICMUTE_LED: | |||||
| return acpi_ibm_micmute_led_set(sc, arg); | |||||
| break; | |||||
| } | } | ||||
| return (0); | return (0); | ||||
| } | } | ||||
| static int | static int | ||||
| acpi_ibm_sysctl_init(struct acpi_ibm_softc *sc, int method) | acpi_ibm_sysctl_init(struct acpi_ibm_softc *sc, int method) | ||||
| { | { | ||||
| ▲ Show 20 Lines • Show All 79 Lines • ▼ Show 20 Lines | case ACPI_IBM_METHOD_THERMAL: | ||||
| if (ACPI_SUCCESS(acpi_GetInteger(sc->ec_handle, IBM_NAME_THERMAL_GET, &dummy))) { | if (ACPI_SUCCESS(acpi_GetInteger(sc->ec_handle, IBM_NAME_THERMAL_GET, &dummy))) { | ||||
| sc->thermal_updt_supported = ACPI_SUCCESS(acpi_GetInteger(sc->ec_handle, IBM_NAME_THERMAL_UPDT, &dummy)); | sc->thermal_updt_supported = ACPI_SUCCESS(acpi_GetInteger(sc->ec_handle, IBM_NAME_THERMAL_UPDT, &dummy)); | ||||
| return (TRUE); | return (TRUE); | ||||
| } | } | ||||
| return (FALSE); | return (FALSE); | ||||
| case ACPI_IBM_METHOD_HANDLEREVENTS: | case ACPI_IBM_METHOD_HANDLEREVENTS: | ||||
| return (TRUE); | return (TRUE); | ||||
| case ACPI_IBM_METHOD_KBD_BACKLIGHT: | |||||
| if (ACPI_FAILURE(acpi_GetInteger(sc->handle, IBM_NAME_KBD_BACKLIGHT_GET, | |||||
| &sc->kbd_backlight_val))) | |||||
| sc->kbd_backlight_val = 0; | |||||
| sc->kbd_backlight_supported = sc->kbd_backlight_val & | |||||
| IBM_NAME_MASK_KBD_BL_SUPPORT; | |||||
| sc->kbd_backlight_val &= IBM_NAME_MASK_KBD_BL_LEVEL; | |||||
| if (sc->kbd_backlight_supported) | |||||
| return (TRUE); | |||||
| return (FALSE); | |||||
| case ACPI_IBM_METHOD_KBD_BL_LEDON: | |||||
| sc->kbd_backlight_ledon = 1; | |||||
| if (sc->kbd_backlight_supported) | |||||
| return (TRUE); | |||||
| return (FALSE); | |||||
| case ACPI_IBM_METHOD_KBD_BL_LEDOFF: | |||||
| sc->kbd_backlight_ledoff = 0; | |||||
| if (sc->kbd_backlight_supported) | |||||
| return (TRUE); | |||||
| return (FALSE); | |||||
| case ACPI_IBM_METHOD_MICMUTE_LED: | |||||
| sc->micmute_led_supported = ACPI_SUCCESS(acpi_SetInteger( | |||||
| sc->handle, IBM_NAME_MICMUTE_LED_SET, | |||||
| IBM_NAME_MICMUTE_LED_OFF)); | |||||
| if (sc->micmute_led_supported) | |||||
| return (TRUE); | |||||
| return (FALSE); | |||||
| } | } | ||||
| return (FALSE); | return (FALSE); | ||||
| } | } | ||||
| static int | static int | ||||
| acpi_ibm_thermal_sysctl(SYSCTL_HANDLER_ARGS) | acpi_ibm_thermal_sysctl(SYSCTL_HANDLER_ARGS) | ||||
| { | { | ||||
| struct acpi_ibm_softc *sc; | struct acpi_ibm_softc *sc; | ||||
| ▲ Show 20 Lines • Show All 283 Lines • ▼ Show 20 Lines | if (sc->cmos_handle) { | ||||
| status = AcpiEvaluateObject(sc->cmos_handle, NULL, &Args, NULL); | status = AcpiEvaluateObject(sc->cmos_handle, NULL, &Args, NULL); | ||||
| if (ACPI_FAILURE(status)) | if (ACPI_FAILURE(status)) | ||||
| return (status); | return (status); | ||||
| } | } | ||||
| val_ec = (arg == 1) ? val_ec | IBM_EC_MASK_MUTE : | val_ec = (arg == 1) ? val_ec | IBM_EC_MASK_MUTE : | ||||
| val_ec & (~IBM_EC_MASK_MUTE); | val_ec & (~IBM_EC_MASK_MUTE); | ||||
| return ACPI_EC_WRITE(sc->ec_dev, IBM_EC_VOLUME, val_ec, 1); | return ACPI_EC_WRITE(sc->ec_dev, IBM_EC_VOLUME, val_ec, 1); | ||||
| } | |||||
| static int | |||||
| acpi_ibm_kbd_backlight_set(struct acpi_ibm_softc *sc, int arg) | |||||
| { | |||||
| ACPI_STATUS status; | |||||
| ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); | |||||
| ACPI_SERIAL_ASSERT(ibm); | |||||
| if (arg < 0 || arg > 2) | |||||
| return (EINVAL); | |||||
| if (sc->kbd_backlight_supported) { | |||||
| status = acpi_SetInteger(sc->handle, IBM_NAME_KBD_BACKLIGHT_SET, arg); | |||||
| if (ACPI_SUCCESS(status)) | |||||
| sc->kbd_backlight_val = arg; | |||||
| return (status); | |||||
| } | |||||
| return (0); | |||||
| } | |||||
| static int | |||||
| acpi_ibm_micmute_led_set(struct acpi_ibm_softc *sc, int arg) | |||||
| { | |||||
| int led_arg; | |||||
| ACPI_STATUS status; | |||||
| ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); | |||||
| ACPI_SERIAL_ASSERT(ibm); | |||||
| if (arg < 0 || arg > 2) | |||||
| return (EINVAL); | |||||
| switch (arg) { | |||||
| case 0: | |||||
| led_arg = IBM_NAME_MICMUTE_LED_OFF; | |||||
| break; | |||||
| case 1: | |||||
| led_arg = IBM_NAME_MICMUTE_LED_ON; | |||||
| break; | |||||
| case 2: | |||||
| led_arg = IBM_NAME_MICMUTE_LED_BLINK; | |||||
| break; | |||||
| } | |||||
| if (sc->micmute_led_supported) { | |||||
| status = acpi_SetInteger(sc->handle, IBM_NAME_MICMUTE_LED_SET, led_arg); | |||||
| if (ACPI_SUCCESS(status)) | |||||
| sc->micmute_led_val = arg; | |||||
| return (status); | |||||
| } | |||||
| return (0); | |||||
| } | } | ||||
| static void | static void | ||||
| acpi_ibm_eventhandler(struct acpi_ibm_softc *sc, int arg) | acpi_ibm_eventhandler(struct acpi_ibm_softc *sc, int arg) | ||||
| { | { | ||||
| int val; | int val; | ||||
| UINT64 val_ec; | UINT64 val_ec; | ||||
| ACPI_STATUS status; | ACPI_STATUS status; | ||||
| ▲ Show 20 Lines • Show All 95 Lines • Show Last 20 Lines | |||||
s/MKHV/MHKV/