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 + -
显示快捷键?