|
尽管在2.6的内核版本已经支持udev,可以很方便的使用,并且使用也很舒服。但是使用udev,在启动过程中扫描/sys/class目录并生成设备节点的时间稍微有点长,在一些系统中是无法忍受的,所以没办法只好放弃udev,回到静态设备节点的时代,以加快启动速度。
2.6内核中,引入了cdev概念,使用cdev的驱动与传统的2.4的字符驱动又不一样,下面给出一个使用cdev和静态设备节点的驱动范例。
beepdrv.c
1 /* beepdrv.c 2 beep driver. GUANGZHOU ZHIYUAN 3 4 Copyright (c) 2009 GUANGZHOU ZHIYUAN ELECTRONICS CO.LTD 5 By Chenxibing <Linux@zlgmcu.com> 6 */ 7 8 #include <linux/init.h> 9 #include <linux/module.h> 10 #include <linux/moduleparam.h> 11 #include <linux/kernel.h> 12 #include <linux/fs.h> 13 #include <linux/errno.h> 14 #include <linux/device.h> 15 #include <linux/miscdevice.h> 16 #include <linux/platform_device.h> 17 #include <linux/types.h> 18 #include <linux/io.h> 19 #include <linux/delay.h> 20 #include <linux/irq.h> 21 #include <linux/interrupt.h> 22 #include <linux/cdev.h> 23 24 #include <asm/arch/hardware.h> 25 #include <asm/uaccess.h> 26 #include <asm/arch/irq.h> 27 #include <asm/io.h> 28 #include <asm/pgtable.h> 29 #include <asm/page.h> 30 31 #include <mach/hardware.h> 32 #include <mach/platform.h> 33 34 #include <asm/arch/lpc32xx_gpio.h> 35 36 #include "beepdrv.h" 37 38 #define DEV_NAME "beep" 39 struct cdev *beep_cdev; 40 #define BEEP_MAJOR 231 41 #define BEEP_MINOR 0 42 int beep_major = BEEP_MAJOR; 43 int beep_minor = BEEP_MINOR; 44 45 module_param(beep_major, int, 0); 46 module_param(beep_minor, int, 0); 47 48 #define GPIO_IOBASE io_p2v(GPIO_BASE) 49 50 static struct semaphore beep_sem; 51 52 static int beep_open(struct inode *inode, struct file *filp) 53 { 54 __raw_writel(_BIT(5), GPIO_P3_OUTP_SET(GPIO_IOBASE));//SET GPIO_05 BEEP OFF 55 56 try_module_get(THIS_MODULE); 57 printk( KERN_INFO DEV_NAME " opened!\n"); 58 return 0; 59 } 60 61 static int beep_release(struct inode *inode, struct file *filp) 62 { 63 __raw_writel(_BIT(5), GPIO_P3_OUTP_SET(GPIO_IOBASE));//SET GPIO_05 BEEP OFF 64 65 module_put(THIS_MODULE); 66 printk(KERN_INFO DEV_NAME " released!\n"); 67 return 0; 68 } 69 70 static int beep_ioctl(struct inode *inode, struct file *filp, 71 unsigned int cmd, unsigned long arg) 72 { 73 int level; 74 75 if (_IOC_TYPE(cmd) != BEEP_IOC_MAGIC) { 76 return -ENOTTY; 77 } 78 79 if (_IOC_NR(cmd) >= BEEP_IOC_MAXNR) { 80 return -ENOTTY; 81 } 82 83 // printk("arg=0x%x\n", arg); 84 85 86 87 switch (cmd) { 88 case SET_BEEP_ON: 89 __raw_writel(_BIT(5), GPIO_P3_OUTP_CLR(GPIO_IOBASE));//CLR GPIO_05 90 91 udelay(10); 92 break; 93 94 case SET_BEEP_OFF: 95 __raw_writel(_BIT(5), GPIO_P3_OUTP_SET(GPIO_IOBASE));//SET GPIO_05 96 97 udelay(10); 98 break; 99 100 default: 101 __raw_writel(_BIT(5), GPIO_P3_OUTP_SET(GPIO_IOBASE));//SET GPIO_05 102 103 break; 104 } 105 106 return 0; 107 } 108 109 static struct file_operations beep_fops = { 110 .owner = THIS_MODULE, 111 .ioctl = beep_ioctl, 112 .open = beep_open, 113 .release = beep_release, 114 }; 115 116 static void beep_setup_cdev(struct cdev *dev) 117 { 118 int err, devno = MKDEV(beep_major, beep_minor); 119 120 cdev_init(dev, &beep_fops); 121 dev->owner = THIS_MODULE; 122 dev->ops = &beep_fops; 123 err = cdev_add (dev, devno, 1); 124 /* Fail gracefully if need be */ 125 if (err) 126 printk(KERN_NOTICE "Error %d adding gpio.\n", err); 127 } 128 129 static int __init beep_init(void) 130 { 131 int result; 132 printk(DEV_NAME " init starting......\n"); 133 134 __raw_writel(_BIT(5), GPIO_P3_OUTP_SET(GPIO_IOBASE));//SET GPIO_05 BEEP OFF 135 136 137 dev_t dev = 0;// MKDEV(gpio_major, 0); 138 139 /* 140 * Register your major, and accept a dynamic number. 141 */ 142 if (beep_major) 143 result = register_chrdev_region(beep_minor, 1, DEV_NAME); 144 else { 145 result = alloc_chrdev_region(&dev, 0, 1, DEV_NAME); 146 beep_major = MAJOR(dev); 147 } 148 if (result < 0) 149 return result; 150 151 beep_cdev = cdev_alloc(); 152 if (!beep_cdev) { 153 result = -ENOMEM; 154 goto fail; /* Make this more graceful */ 155 } 156 beep_setup_cdev(&beep_cdev); 157 printk(DEV_NAME " registered OK.\n"); 158 return 0; 159 fail: 160 cdev_del(&beep_cdev); 161 unregister_chrdev_region(MKDEV(beep_major, beep_minor), 1); 162 // beep_exit(); 163 164 return result; 165 } 166 167 static int __exit beep_exit(void) 168 { 169 cdev_del(&beep_cdev); 170 unregister_chrdev_region(MKDEV(beep_major, beep_minor), 1); 171 printk(DEV_NAME " unregistered.\n"); 172 } 173 174 175 module_init(beep_init); 176 module_exit(beep_exit); 177 178 MODULE_AUTHOR("Abing <Linux@zlgmcu.com>"); 179 MODULE_DESCRIPTION("ZHIYUAN tp-beep Driver"); 180 MODULE_LICENSE("GPL");
beepdrv.h
1 #ifndef __BEEPDRV_H 2 #define __BEEPDRV_H 3 #include <linux/ioctl.h> 4 5 #define BEEP_IOC_MAGIC 'b' 6 7 #define SET_BEEP_ON _IO(BEEP_IOC_MAGIC, 0) 8 #define SET_BEEP_OFF _IO(BEEP_IOC_MAGIC, 1) 9 10 #define BEEP_IOC_MAXNR 2 11 12 #endif //__BEEPDRV_H