📄 led.c
字号:
/*********************************************************************** * * (C) Copyright 2002,12 * * Qi zhaoling * All rights left. * * * a simple Device Driver for UT850GE led device * * Can be loaded as module * * $Id: led.c,v 1.1 2000/01/14 16:28:49 wd Exp $ * ***********************************************************************//* * Standard in kernel modules */#include <linux/kernel.h> /* We're doing kernel work */#include <linux/module.h> /* Specifically, a module */#include <asm/uaccess.h> /* for put_user */#include <asm/init.h> /* for __initfunc */#include <asm/8xx_immap.h>#include <asm/mpc8xx.h>static volatile iop8xx_t *iop_p = 0; /*i/o port point of UT850GE*/#define DEBUG#ifdef DEBUG# define debugk(fmt,args...) printk(fmt ,##args)#else# define debugk(fmt,args...)#endif/* * Deal with CONFIG_MODVERSIONS */#if CONFIG_MODVERSIONS==1/* # define MODVERSIONS */# include <linux/modversions.h>#endif/* * For character devices */#include <linux/fs.h> /* character device definitions */#include <linux/wrapper.h> /* wrapper for compatibility with future versions */#ifndef KERNEL_VERSION# define KERNEL_VERSION(a,b,c) ((a)*65536+(b)*256+(c))#endif#define DEBUG 1#define SUCCESS 0#define LED_MAJOR 42 /* free for demo/sample use */#define MAX_LED 2#define LINK_LED 0#define ALARM_LED 1static ushort UTLed[MAX_LED] = {0x1000, 0x0800};/* * Device Declarations *//* * The name for our device, as it will appear in /proc/devices */#define DEVICE_NAME "ut_led"/* * prevent concurent access of the same device */static int Device_Open = 0;/* * Prototypes */int led_init (void );static int device_open(struct inode *, struct file *);static int device_release(struct inode *, struct file *);static ssize_t device_read(struct file *, char *, size_t, loff_t *);static ssize_t device_write(struct file *, const char *, size_t, loff_t *);int init_module(void);void cleanup_module(void);#if 0struct file_operations led_ops ={ NULL, /* seek */ device_read, device_write, NULL, /* readdir */ NULL, /* select */ NULL, /* ioctl */ NULL, /* mmap */ device_open, NULL, /* flush */ device_release /* close */};#endifstruct file_operations led_ops = { read: device_read, write: device_write, open: device_open, release: device_release,};static int Major;/* * Initialize the driver - Register the character device *//*__initfunc( int led_init (void) )*/int led_init(void){ if (!iop_p) { /* init i/o port ptr */ unsigned long immr; asm( "mfspr %0,638": "=r"(immr) : ); immr &= 0xFFFF0000; iop_p = (iop8xx_t *)&((volatile immap_t *)immr)->im_ioport; } /* * Register the character device */ Major = register_chrdev (LED_MAJOR, DEVICE_NAME, &led_ops); /* Negative values signify an error */ if (Major < 0) { printk ("UT_LED init_module: failed with %d\n", Major); return Major; } Major = LED_MAJOR; printk ("TQM_LED registred: major = %d\n", Major); return 0;}/* * called whenever a process attempts to open the device */static int device_open (struct inode *inode, struct file *file){ volatile iop8xx_t *cp = iop_p; debugk ("device_open(%p,%p)\n", inode, file); /* * Get major / minor numbers when needed */ debugk ("Device: %d.%d\n", inode->i_rdev >> 8, inode->i_rdev & 0xFF); /* * exclusive open only */ if (Device_Open) { return -EBUSY; } /* * Be careful here on SMP kernels! */ Device_Open++; /* * Make sure that the module isn't removed while * the file is open by incrementing the usage count */ MOD_INC_USE_COUNT; cp->iop_pdpar &= ~UTLed[LINK_LED]; cp->iop_pddir |= UTLed[LINK_LED]; /*set to output IO*/ cp->iop_pdpar &= ~UTLed[ALARM_LED]; cp->iop_pddir |= UTLed[ALARM_LED]; /*set to output IO*/ /* default is turned on */ cp->iop_pddat &= ~UTLed[ALARM_LED]; cp->iop_pddat &= ~UTLed[LINK_LED]; debugk ("LED_OPEN: pdpar=0x%x pddir=0x%x pddat=0x%x\n", cp->iop_pdpar, cp->iop_pddir, cp->iop_pddat); return SUCCESS;}/* * Called when a process closes the device. * Doesn't have a return value in version 2.0.x because it can't fail, * but in version 2.2.x it is allowed to fail */static int device_release (struct inode *inode, struct file *file){ volatile iop8xx_t *cp = iop_p; debugk ("device_release(%p,%p)\n", inode, file); /* We're now ready for our next caller */ Device_Open--; MOD_DEC_USE_COUNT; debugk ("LED_CLOSE: pdpar=0x%x pddir=0x%x pddat=0x%x\n", cp->iop_pdpar, cp->iop_pddir, cp->iop_pddat); /*turn off led*/ cp->iop_pddat &= ~UTLed[ALARM_LED]; cp->iop_pddat &= ~UTLed[LINK_LED]; debugk ("LED_CLOSE: pdpar=0x%x pddir=0x%x pddat=0x%x\n", cp->iop_pdpar, cp->iop_pddir, cp->iop_pddat); return 0;}/* * read entry point: */static ssize_t device_read (struct file *file, char *buffer, /* The buffer to fill with data */ size_t length, /* The length of the buffer */ loff_t * offset) /* Our offset in the file */{ volatile iop8xx_t *cp = iop_p; unsigned char c[2]; c[0] = cp->iop_pddat & UTLed[LINK_LED]; c[1] = cp->iop_pddat & UTLed[ALARM_LED]; put_user (c[0], buffer++); put_user (c[1], buffer); debugk ("Read: value = 0x%02x%02x\n", c[0],c[1]); return (2); /* read() always returns exactly two byte */}/* * write entry point: dummy here */static ssize_t device_write (struct file *file, const char *buffer, /* buffer */ size_t length, /* length of buffer */ loff_t * offset) /* offset in the file */{ volatile iop8xx_t *cp = iop_p; int error; ushort pddat; unsigned char c1,c2; ushort data; if(length > 2) return -9; pddat = cp->iop_pddat; pddat &= ~UTLed[LINK_LED]; pddat &= ~UTLed[ALARM_LED]; if ((error = get_user (c1, buffer++)) != 0) { return (-10); } if ((error = get_user (c2, buffer++)) != 0) { return (-20); } data = (c1 << 8) | c2; cp->iop_pddat = pddat | (data & 0x1800) ; return (length);}/****************************** **** Module Declarations ***** **************************** */#ifdef MODULE/* * Initialize the module */int init_module (void){ return led_init();}/* * Cleanup - unregister the appropriate file from /proc */void cleanup_module (void){ int ret; /* * Unregister the device */ ret = unregister_chrdev (Major, DEVICE_NAME); /* * If there's an error, report it */ if (ret < 0) { printk ("unregister_chrdev: error %d\n", ret); }}#endif /* MODULE */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -