thinkpad_acpi.c
来自「linux 内核源代码」· C语言 代码 · 共 2,636 行 · 第 1/5 页
C
2,636 行
if (!tp_features.light) { len += sprintf(p + len, "status:\t\tnot supported\n"); } else if (!tp_features.light_status) { len += sprintf(p + len, "status:\t\tunknown\n"); len += sprintf(p + len, "commands:\ton, off\n"); } else { if (!acpi_evalf(ec_handle, &status, "KBLT", "d")) return -EIO; len += sprintf(p + len, "status:\t\t%s\n", onoff(status, 0)); len += sprintf(p + len, "commands:\ton, off\n"); } return len;}static int light_write(char *buf){ int cmos_cmd, lght_cmd; char *cmd; int success; if (!tp_features.light) return -ENODEV; while ((cmd = next_cmd(&buf))) { if (strlencmp(cmd, "on") == 0) { cmos_cmd = 0x0c; lght_cmd = 1; } else if (strlencmp(cmd, "off") == 0) { cmos_cmd = 0x0d; lght_cmd = 0; } else return -EINVAL; success = cmos_handle ? acpi_evalf(cmos_handle, NULL, NULL, "vd", cmos_cmd) : acpi_evalf(lght_handle, NULL, NULL, "vd", lght_cmd); if (!success) return -EIO; } return 0;}static struct ibm_struct light_driver_data = { .name = "light", .read = light_read, .write = light_write,};/************************************************************************* * Dock subdriver */#ifdef CONFIG_THINKPAD_ACPI_DOCKIBM_HANDLE(dock, root, "\\_SB.GDCK", /* X30, X31, X40 */ "\\_SB.PCI0.DOCK", /* 600e/x,770e,770x,A2xm/p,T20-22,X20-21 */ "\\_SB.PCI0.PCI1.DOCK", /* all others */ "\\_SB.PCI.ISA.SLCE", /* 570 */ ); /* A21e,G4x,R30,R31,R32,R40,R40e,R50e *//* don't list other alternatives as we install a notify handler on the 570 */IBM_HANDLE(pci, root, "\\_SB.PCI"); /* 570 */static const struct acpi_device_id ibm_pci_device_ids[] = { {PCI_ROOT_HID_STRING, 0}, {"", 0},};static struct tp_acpi_drv_struct ibm_dock_acpidriver[2] = { { .notify = dock_notify, .handle = &dock_handle, .type = ACPI_SYSTEM_NOTIFY, }, { /* THIS ONE MUST NEVER BE USED FOR DRIVER AUTOLOADING. * We just use it to get notifications of dock hotplug * in very old thinkpads */ .hid = ibm_pci_device_ids, .notify = dock_notify, .handle = &pci_handle, .type = ACPI_SYSTEM_NOTIFY, },};static struct ibm_struct dock_driver_data[2] = { { .name = "dock", .read = dock_read, .write = dock_write, .acpi = &ibm_dock_acpidriver[0], }, { .name = "dock", .acpi = &ibm_dock_acpidriver[1], },};#define dock_docked() (_sta(dock_handle) & 1)static int __init dock_init(struct ibm_init_struct *iibm){ vdbg_printk(TPACPI_DBG_INIT, "initializing dock subdriver\n"); IBM_ACPIHANDLE_INIT(dock); vdbg_printk(TPACPI_DBG_INIT, "dock is %s\n", str_supported(dock_handle != NULL)); return (dock_handle)? 0 : 1;}static int __init dock_init2(struct ibm_init_struct *iibm){ int dock2_needed; vdbg_printk(TPACPI_DBG_INIT, "initializing dock subdriver part 2\n"); if (dock_driver_data[0].flags.acpi_driver_registered && dock_driver_data[0].flags.acpi_notify_installed) { IBM_ACPIHANDLE_INIT(pci); dock2_needed = (pci_handle != NULL); vdbg_printk(TPACPI_DBG_INIT, "dock PCI handler for the TP 570 is %s\n", str_supported(dock2_needed)); } else { vdbg_printk(TPACPI_DBG_INIT, "dock subdriver part 2 not required\n"); dock2_needed = 0; } return (dock2_needed)? 0 : 1;}static void dock_notify(struct ibm_struct *ibm, u32 event){ int docked = dock_docked(); int pci = ibm->acpi->hid && ibm->acpi->device && acpi_match_device_ids(ibm->acpi->device, ibm_pci_device_ids); int data; if (event == 1 && !pci) /* 570 */ data = 1; /* button */ else if (event == 1 && pci) /* 570 */ data = 3; /* dock */ else if (event == 3 && docked) data = 1; /* button */ else if (event == 3 && !docked) data = 2; /* undock */ else if (event == 0 && docked) data = 3; /* dock */ else { printk(IBM_ERR "unknown dock event %d, status %d\n", event, _sta(dock_handle)); data = 0; /* unknown */ } acpi_bus_generate_proc_event(ibm->acpi->device, event, data); acpi_bus_generate_netlink_event(ibm->acpi->device->pnp.device_class, ibm->acpi->device->dev.bus_id, event, data);}static int dock_read(char *p){ int len = 0; int docked = dock_docked(); if (!dock_handle) len += sprintf(p + len, "status:\t\tnot supported\n"); else if (!docked) len += sprintf(p + len, "status:\t\tundocked\n"); else { len += sprintf(p + len, "status:\t\tdocked\n"); len += sprintf(p + len, "commands:\tdock, undock\n"); } return len;}static int dock_write(char *buf){ char *cmd; if (!dock_docked()) return -ENODEV; while ((cmd = next_cmd(&buf))) { if (strlencmp(cmd, "undock") == 0) { if (!acpi_evalf(dock_handle, NULL, "_DCK", "vd", 0) || !acpi_evalf(dock_handle, NULL, "_EJ0", "vd", 1)) return -EIO; } else if (strlencmp(cmd, "dock") == 0) { if (!acpi_evalf(dock_handle, NULL, "_DCK", "vd", 1)) return -EIO; } else return -EINVAL; } return 0;}#endif /* CONFIG_THINKPAD_ACPI_DOCK *//************************************************************************* * Bay subdriver */#ifdef CONFIG_THINKPAD_ACPI_BAYIBM_HANDLE(bay, root, "\\_SB.PCI.IDE.SECN.MAST", /* 570 */ "\\_SB.PCI0.IDE0.IDES.IDSM", /* 600e/x, 770e, 770x */ "\\_SB.PCI0.SATA.SCND.MSTR", /* T60, X60, Z60 */ "\\_SB.PCI0.IDE0.SCND.MSTR", /* all others */ ); /* A21e, R30, R31 */IBM_HANDLE(bay_ej, bay, "_EJ3", /* 600e/x, A2xm/p, A3x */ "_EJ0", /* all others */ ); /* 570,A21e,G4x,R30,R31,R32,R40e,R50e */IBM_HANDLE(bay2, root, "\\_SB.PCI0.IDE0.PRIM.SLAV", /* A3x, R32 */ "\\_SB.PCI0.IDE0.IDEP.IDPS", /* 600e/x, 770e, 770x */ ); /* all others */IBM_HANDLE(bay2_ej, bay2, "_EJ3", /* 600e/x, 770e, A3x */ "_EJ0", /* 770x */ ); /* all others */static int __init bay_init(struct ibm_init_struct *iibm){ vdbg_printk(TPACPI_DBG_INIT, "initializing bay subdriver\n"); IBM_ACPIHANDLE_INIT(bay); if (bay_handle) IBM_ACPIHANDLE_INIT(bay_ej); IBM_ACPIHANDLE_INIT(bay2); if (bay2_handle) IBM_ACPIHANDLE_INIT(bay2_ej); tp_features.bay_status = bay_handle && acpi_evalf(bay_handle, NULL, "_STA", "qv"); tp_features.bay_status2 = bay2_handle && acpi_evalf(bay2_handle, NULL, "_STA", "qv"); tp_features.bay_eject = bay_handle && bay_ej_handle && (strlencmp(bay_ej_path, "_EJ0") == 0 || experimental); tp_features.bay_eject2 = bay2_handle && bay2_ej_handle && (strlencmp(bay2_ej_path, "_EJ0") == 0 || experimental); vdbg_printk(TPACPI_DBG_INIT, "bay 1: status %s, eject %s; bay 2: status %s, eject %s\n", str_supported(tp_features.bay_status), str_supported(tp_features.bay_eject), str_supported(tp_features.bay_status2), str_supported(tp_features.bay_eject2)); return (tp_features.bay_status || tp_features.bay_eject || tp_features.bay_status2 || tp_features.bay_eject2)? 0 : 1;}static void bay_notify(struct ibm_struct *ibm, u32 event){ acpi_bus_generate_proc_event(ibm->acpi->device, event, 0); acpi_bus_generate_netlink_event(ibm->acpi->device->pnp.device_class, ibm->acpi->device->dev.bus_id, event, 0);}#define bay_occupied(b) (_sta(b##_handle) & 1)static int bay_read(char *p){ int len = 0; int occupied = bay_occupied(bay); int occupied2 = bay_occupied(bay2); int eject, eject2; len += sprintf(p + len, "status:\t\t%s\n", tp_features.bay_status ? (occupied ? "occupied" : "unoccupied") : "not supported"); if (tp_features.bay_status2) len += sprintf(p + len, "status2:\t%s\n", occupied2 ? "occupied" : "unoccupied"); eject = tp_features.bay_eject && occupied; eject2 = tp_features.bay_eject2 && occupied2; if (eject && eject2) len += sprintf(p + len, "commands:\teject, eject2\n"); else if (eject) len += sprintf(p + len, "commands:\teject\n"); else if (eject2) len += sprintf(p + len, "commands:\teject2\n"); return len;}static int bay_write(char *buf){ char *cmd; if (!tp_features.bay_eject && !tp_features.bay_eject2) return -ENODEV; while ((cmd = next_cmd(&buf))) { if (tp_features.bay_eject && strlencmp(cmd, "eject") == 0) { if (!acpi_evalf(bay_ej_handle, NULL, NULL, "vd", 1)) return -EIO; } else if (tp_features.bay_eject2 && strlencmp(cmd, "eject2") == 0) { if (!acpi_evalf(bay2_ej_handle, NULL, NULL, "vd", 1)) return -EIO; } else return -EINVAL; } return 0;}static struct tp_acpi_drv_struct ibm_bay_acpidriver = { .notify = bay_notify, .handle = &bay_handle, .type = ACPI_SYSTEM_NOTIFY,};static struct ibm_struct bay_driver_data = { .name = "bay", .read = bay_read, .write = bay_write, .acpi = &ibm_bay_acpidriver,};#endif /* CONFIG_THINKPAD_ACPI_BAY *//************************************************************************* * CMOS subdriver *//* sysfs cmos_command -------------------------------------------------- */static ssize_t cmos_command_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count){ unsigned long cmos_cmd; int res; if (parse_strtoul(buf, 21, &cmos_cmd)) return -EINVAL; res = issue_thinkpad_cmos_command(cmos_cmd); return (res)? res : count;}static struct device_attribute dev_attr_cmos_command = __ATTR(cmos_command, S_IWUSR, NULL, cmos_command_store);/* --------------------------------------------------------------------- */static int __init cmos_init(struct ibm_init_struct *iibm){ int res; vdbg_printk(TPACPI_DBG_INIT, "initializing cmos commands subdriver\n"); IBM_ACPIHANDLE_INIT(cmos); vdbg_printk(TPACPI_DBG_INIT, "cmos commands are %s\n", str_supported(cmos_handle != NULL)); res = device_create_file(&tpacpi_pdev->dev, &dev_attr_cmos_command); if (res) return res; return (cmos_handle)? 0 : 1;}static void cmos_exit(void){ device_remove_file(&tpacpi_pdev->dev, &dev_attr_cmos_command);}static int cmos_read(char *p){ int len = 0; /* cmos not supported on 570, 600e/x, 770e, 770x, A21e, A2xm/p, R30, R31, T20-22, X20-21 */ if (!cmos_handle) len += sprintf(p + len, "status:\t\tnot supported\n"); else { len += sprintf(p + len, "status:\t\tsupported\n"); len += sprintf(p + len, "commands:\t<cmd> (<cmd> is 0-21)\n"); } return len;}static int cmos_write(char *buf){ char *cmd; int cmos_cmd, res; while ((cmd = next_cmd(&buf))) { if (sscanf(cmd, "%u", &cmos_cmd) == 1 && cmos_cmd >= 0 && cmos_cmd <= 21) { /* cmos_cmd set */ } else return -EINVAL; res = issue_thinkpad_cmos_command(cmos_cmd); if (res) return res; } return 0;}static struct ibm_struct cmos_driver_data = { .name = "cmos", .read = cmos_read, .write = cmos_write, .exit = cmos_exit,};/************************************************************************* * LED subdriver */static enum led_access_mode led_supported;IBM_HANDLE(led, ec, "SLED", /* 570 */ "SYSL", /* 600e/x, 770e, 770x, A21e, A2xm/p, T20-22, X20-21 */ "LED", /* all others */ ); /* R30, R31 */static int __init led_init(struct ibm_init_struct *iibm){ vdbg_printk(TPACPI_DBG_INIT, "initializing LED subdriver\n"); IBM_ACPIHANDLE_INIT(led); if (!led_handle) /* led not supported on R30, R31 */ led_supported = TPACPI_LED_NONE; else if (strlencmp(led_path, "SLED") == 0) /* 570 */ led_supported = TPACPI_LED_570; else if (strlencmp(led_path, "SYSL") == 0) /* 600e/x, 770e, 770x, A21e, A2xm/p, T20-22, X20-21 */ led_supported = TPACPI_LED_OLD; else /* all others */ led_supported = TPACPI_LED_NEW; vdbg_printk(TPACPI_DBG_INIT, "LED commands are %s, mode %d\n", str_supported(led_supported), led_supported); return (led_supported != TPACPI_LED_NONE)? 0 : 1;}#define led_status(s) ((s) == 0 ? "off" : ((s) == 1 ? "on" : "blinking"))static int led_read(char *p){ int len = 0; if (!led_supported) { len += sprintf(p + len, "status:\t\tnot supported\n"); return len; } len += sprintf(p + len, "status:\t\tsupported\n"); if (led_supported == TPACPI_LED_570) { /* 570 */ int i, status; for (i = 0; i < 8; i++) { if (!acpi_evalf(ec_handle, &status, "GLED", "dd", 1 << i)) return -EIO; len += sprintf(p + len, "%d:\t\t%s\n", i, led_status(status)); } } len += sprintf(p + len, "commands:\t" "<led> on, <led> off, <led> blink (<led> is 0-7)\n"); return len;}/* off, on, blink */static const int led_sled_arg1[] = { 0, 1, 3 };static const int led_exp_hlbl[] = { 0, 0, 1 }; /* led# * */static const int led_exp_hlcl[] = { 0, 1, 1 }; /* led# * */static const int led_led_arg1[] = { 0, 0x80, 0xc0 };static int led_write(char *buf){ char *cmd; int led, ind, ret; if (!led_supported) return -ENODEV; while ((cmd = next_cmd(&buf))) { if (sscanf(cmd, "%d", &led) != 1 || led < 0 || led > 7) return -EINVAL; if (strstr(cmd, "off")) { ind = 0; } else if (strstr(cmd, "on")) { ind = 1; } else if (strstr(cmd, "blink")) { ind = 2; } else return -EINVAL; if (led_supported == TPACPI_LED_570) { /* 570 */ led = 1 << led; if (!acpi_evalf(led_handle, NULL, NULL, "vdd", led, led_sled_arg1[ind])) return -EIO; } else
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?