⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 apm2.c

📁 ARM 嵌入式 系统 设计与实例开发 实验教材 二源码
💻 C
字号:
/* * bios-less APM driver for ARM Linux  *  Jamey Hicks <jamey@crl.dec.com> *  adapted from the APM BIOS driver for Linux by Stephen Rothwell (sfr@linuxcare.com) * * APM 1.2 Reference: *   Intel Corporation, Microsoft Corporation. Advanced Power Management *   (APM) BIOS Interface Specification, Revision 1.2, February 1996. * * [This document is available from Microsoft at: *    http://www.microsoft.com/hwdev/busbios/amp_12.htm] *   Thr 29 Nov 2001 Nandy Lyu <nandy@mizi.com>   - Modified for MIZI Power Management   Mon 14 Jan 2002 Yong-iL Joh <tolkien@mizi.com>   - modified followed by MIZI's "kernel vs Application API spec (0.3, draft)"   Fri May 10 2002 Yong-iL Joh <tolkien@mizi.com>   - kernel vs app. API spec (draft) v1.33 * * This file is subject to the terms and conditions of the GNU General Public * License.  See the file COPYING in the main directory of this archive * for more details. */#include <linux/config.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/init.h>#include <linux/poll.h>#include <linux/miscdevice.h>#include <linux/apm_bios.h>#include <linux/pm.h>#include <linux/errno.h>#include <asm/hardware.h>#include <linux/proc_fs.h>/* *  Debug macros  *//* 0 : Quiet 1 : Audible 2 : Loud 3 : Noisy */#undef CONFIG_APM_DEBUG	1#ifdef CONFIG_APM_DEBUG#define DEBUG(n, args...)		\	if (n <= CONFIG_APM_DEBUG) {	\	    printk(KERN_INFO args);	\	}#else#define DEBUG(n, args...)#endifextern wait_queue_head_t mz_event_queue;#define INCBUF(x,mod) (((x)+1) & ((mod) - 1))extern struct mz_event_queue_t mz_event_q;extern int pm_suggest_suspend(void);extern int pm_do_suspend(void);static int apm_bios_ioctl(struct inode * inode, struct file *filp,		    u_int cmd, u_long arg){    int ret = 0;    struct pm_dev *pm_dev = NULL;    static int apm_lcd_status = LCD_ON;    switch (cmd) {    case APM_IOC_SUSPEND:      pm_suggest_suspend();      break;    case APM_MZ_SLEEP:      pm_do_suspend();      break;    case APM_LCD_OFF:      DEBUG(2, __FILE__ ": LCD OFF\n");      while ((pm_dev = pm_find(PM_USER_DEV, pm_dev)) != NULL) {	if ((pm_dev->id == PM_USER_LCD) || (pm_dev->id == PM_USER_LIGHT)) {	  DEBUG(2, __FILE__ ": find LCD device\n");	  ret = pm_send(pm_dev, PM_SUSPEND, (void *)2);	  if (ret) {	    DEBUG(1, __FILE__ ": error in pm_send(0x%lx)\n", pm_dev->id);	    return ret;	  }	}      }      apm_lcd_status = LCD_OFF;      break;    case APM_LCD_ON:      DEBUG(2, __FILE__ ": LCD ON\n");      while ((pm_dev = pm_find(PM_USER_DEV, pm_dev)) != NULL) {	if ((pm_dev->id == PM_USER_LCD) || (pm_dev->id == PM_USER_LIGHT)) {	  DEBUG(2, __FILE__ ": find LCD device\n");	  ret = pm_send(pm_dev, PM_RESUME, (void *)0);	  if (ret) {	    DEBUG(1, __FILE__ ": error in pm_send(0x%lx)\n", pm_dev->id);	    return ret;	  }	}      }      apm_lcd_status = LCD_ON;      break;    case APM_DEV_LIST:#ifdef CONFIG_APM_DEBUG      printk("type \t\t id \t\t state \t prev_state \n");      while ((pm_dev = pm_find(PM_UNKNOWN_DEV, pm_dev)) != NULL) {	printk("0x%08x \t 0x%08lx \t %d \t %d\n",	       (int)pm_dev->type, (unsigned long)pm_dev->id,	       (int)pm_dev->state, (int)pm_dev->prev_state);      }#endif      break;    case APM_DEV_ONOFF: {      struct pm_dev *pm_dev2;      pm_dev2 = (struct pm_dev *)kmalloc(sizeof(struct pm_dev), GFP_KERNEL);      if (pm_dev2 == NULL)	return -ENOMEM;      ret = copy_from_user(pm_dev2, (struct pm_dev *)arg,			   sizeof(struct pm_dev));      if (ret)	return ret;      while ((pm_dev = pm_find(pm_dev2->type, pm_dev)) != NULL) {	if (pm_dev->id == pm_dev2->id)	  ret = pm_send(pm_dev, pm_dev2->state, pm_dev2->data);	break;      }      kfree(pm_dev2);      return ret;    } break;    case GET_BATTERY_STATUS: {      BATTERY_RET bat_dev = {	sec:	0,	level:	-1,	ac:	AC_UNKNOWN,	battery: BATTERY_UNKNOWN,      };      if (mz_pm_ops.get_power_status == NULL)	return -EIO;      if (!(ret = (*(mz_pm_ops.get_power_status))(&bat_dev))) {	if (copy_to_user((BATTERY_RET *)arg, &bat_dev, sizeof(BATTERY_RET)))	    return -EINVAL;      } else return -EIO;    } break;    case GET_JIFFIES:      return put_user(pm_last_jiffies, (unsigned long *)arg);      break;    case GET_LCD_STATUS:      return put_user(apm_lcd_status, (unsigned int *)arg);      break;    case GET_MZ_EVENT:      if (mz_event_q.head == mz_event_q.tail)	return -EAGAIN;      else {	ret = put_user(mz_event_q.buf[mz_event_q.tail], (unsigned long *)arg);	mz_event_q.tail = INCBUF(mz_event_q.tail, MZ_EVENT_BUF_SIZE);	return ret;      }      break;    case SET_INPUT_DEV: {      unsigned int apm_input_tmp;      ret = get_user(apm_input_tmp, (unsigned int *)arg);      if (ret)	return ret;      while ((pm_dev = pm_find(PM_USER_DEV, pm_dev)) != NULL) {	if (pm_dev->id == PM_USER_INPUT) {	  if (apm_input_tmp == INPUT_DEV_ON)	    ret = pm_send(pm_dev, PM_RESUME, NULL);	  else if (apm_input_tmp == INPUT_DEV_OFF)	    ret = pm_send(pm_dev, PM_SUSPEND, NULL);	  else	    return -EINVAL;	}      }      return ret;    } break;    default:      return -ENOIOCTLCMD;    }    return 0;}static unsigned int apm_bios_poll(struct file *filp, poll_table *wait){    poll_wait(filp, &mz_event_queue, wait);    return (mz_event_q.head == mz_event_q.tail ? 0 : (POLLIN | POLLRDNORM));}struct file_operations apm_bios_fops = {    owner:	THIS_MODULE,    ioctl:	apm_bios_ioctl,    poll:	apm_bios_poll,};static struct miscdevice apm_device = {	MISC_DYNAMIC_MINOR,	"apm_bios",	&apm_bios_fops};/* * Just start the APM thread. We do NOT want to do APM BIOS * calls from anything but the APM thread, if for no other reason * than the fact that we don't trust the APM BIOS. This way, * most common APM BIOS problems that lead to protection errors * etc will have at least some level of being contained... * * In short, if something bad happens, at least we have a choice * of just killing the apm thread.. */static int __init apm_init(void){    if (PM_IS_ACTIVE()) {      printk(KERN_NOTICE "apm: overridden by ACPI.\n");      return -1;    }    pm_active = 1;    misc_register(&apm_device);    return 0;}static void __exit apm_exit(void){    misc_deregister(&apm_device);    pm_active = 0;}module_init(apm_init);module_exit(apm_exit);MODULE_AUTHOR("Yong-iL Joh");MODULE_DESCRIPTION("Advanced Power Management by MIZI");EXPORT_NO_SYMBOLS;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -