platform总线globalfifo驱动
功能是使用内存的4k单元,实现读,写,偏移,清除。
1 /********************************************************************************* 2 * Copyright: (C) 2014 zhouguangfeng<zhouguangfeng91@gmail.com> 3 + plat_globalfifo.c 4 /********************************************************************************* 5 * Copyright: (C) 2014 zhouguangfeng<zhouguangfeng91@gmail.com> 6 * All rights reserved. 7 * 8 * Filename: plat_globalfifo.c 9 * Description: This file is a commom platform driver 10 * 11 * Version: 1.0.0(08/19/2014) 12 * Author: zhouguangfeng <zhouguangfeng91@gmail.com> 13 * ChangeLog: 1, Release initial version on "08/19/2014 02:31:17 PM" 14 * 15 ********************************************************************************/ 16 #include <linux/fs.h>//struct file_operations 17 #include <linux/types.h>//special type definition,like dev_t off_t defined by typedef 18 #include <linux/init.h> // init and exit 19 #include <linux/module.h>//support module load and unload 20 #include <linux/errno.h> 21 #include <linux/mm.h> //memory mannage ,include kmalloc.kfree and so on 22 #include <linux/sched.h> 23 #include <linux/cdev.h> //char device structure definition 24 #include <asm/io.h> //io operation function ,like ioremap,iowrite 25 #include <asm/system.h> 26 #include <asm/ioctl.h> //for ioctl command 27 #include <asm/uaccess.h> 28 #include <linux/platform_device.h> //platform support 29 #include <linux/kernel.h> 30 #include <linux/device.h> //class_create() and device_create() 31 32 33 #define GLOBALFIFO_SIZE 0x1000 /* 4K */ 34 #define NAME "globalfifo" 35 #define KELNEL_OLD 0 /* decsion ioctl() */ 36 37 #ifndef GLOBALFIFO_MAJOR 38 #define GLOBALFIFO_MAJOR 0 39 #endif 40 41 42 //#define GLOBALFIFO_CLEAR 0x17 43 //#define MEM_CLEAR __IO (GLOBALFIFO_CLEAR, 0x20) 44 #define MEM_CLEAR 0x20 45 46 47 static int globalfifo_major = GLOBALFIFO_MAJOR; 48 static int globalfifo_minor = 0; 49 50 51 /* ============================ Platform Device part =============================== */ 52 53 struct globalfifo_dev 54 { 55 struct cdev cdev; 56 unsigned int current_len; 57 unsigned char mem[GLOBALFIFO_SIZE]; 58 struct class *class; 59 60 61 //struct semaphrore sem; 62 // wait_queue_t r_wait; 63 //wait_queue_t r_wait; 64 } globalfifo_dev; 65 66 static void plat_release(struct device * dev) 67 { 68 return; 69 } 70 71 static struct platform_device globalfifo_device = { 72 .name = "globalfifo", 73 .id = 1, 74 .dev = { 75 .release = plat_release, 76 }, 77 }; 78 79 80 81 /* ===================== globalfifo driver part ===========================*/ 82 83 int globalfifo_open(struct inode *inode, struct file *filp) 84 { 85 struct globalfifo_dev *dev; 86 87 dev = container_of(inode->i_cdev, struct globalfifo_dev, cdev); 88 filp->private_data = dev; 89 90 return 0; 91 } 92 93 int globalfifo_release(struct inode *inode, struct file *filp) 94 { 95 return 0; 96 } 97 98 99 #if KELNEL_OLD 100 static ssize_t globalfifo_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) 101 { 102 struct globalfifo_dev *dev = filp->private_data; 103 switch(cmd) 104 { 105 case MEM_CLEAR: 106 memset(dev->mem, 0, GLOBALFIFO_SIZE); 107 printk(KERN_INFO "globalfifo is set to zero\n"); 108 break; 109 110 default: 111 return -EINVAL; 112 } 113 114 return 0; 115 } 116 #endif 117 118 static ssize_t globalfifo_read(struct file *filp, char __user *buf, size_t size, loff_t *opps) 119 { 120 unsigned long p = *opps; 121 unsigned int count = size; 122 int ret = 0; 123 124 struct globalfifo_dev *dev = filp->private_data; 125 126 if(p >= GLOBALFIFO_SIZE) 127 { 128 return count ? -ENXIO : 0; 129 } 130 if(count > GLOBALFIFO_SIZE - p) 131 { 132 count = GLOBALFIFO_SIZE - p; 133 } 134 135 if(copy_to_user(buf, (void *)((dev->mem)+p), count)) 136 { 137 ret = -EFAULT; 138 } 139 else 140 { 141 *opps += count; 142 ret = count; 143 printk(KERN_INFO"read %u bytes(s) from %lu\n", count, p); 144 } 145 146 return ret; 147 } 148 149 static ssize_t globalfifo_write(struct file *filp, const char __user *buf, size_t size, loff_t *opps) 150 { 151 unsigned long p = *opps; 152 unsigned int count = size; 153 int ret; 154 155 struct globalfifo_dev *dev = filp->private_data; 156 157 if(p >= GLOBALFIFO_SIZE) 158 { 159 return count ? -ENXIO : 0; 160 } 161 162 if(count > GLOBALFIFO_SIZE - p) 163 { 164 count = GLOBALFIFO_SIZE - p; 165 } 166 167 if(copy_from_user(((dev->mem)+p), buf, count)) 168 { 169 ret = -EFAULT; 170 } 171 else 172 { 173 *opps =+ count; 174 ret = count; 175 printk(KERN_INFO "written %u bytes(s) from %lu\n", count, p); 176 } 177 return ret; 178 } 179 180 181 #if 1 182 static loff_t globalfifo_llseek(struct file *filp, loff_t offset, int orig) 183 { 184 loff_t ret = 0; 185 186 switch(orig) 187 { 188 case 0: 189 if(offset <0 ) 190 { 191 ret = -EINVAL; 192 break; 193 } 194 195 if((unsigned int )offset > GLOBALFIFO_SIZE) 196 { 197 ret = -EINVAL; 198 break; 199 } 200 filp->f_pos = (unsigned int)offset; 201 ret = filp->f_pos; 202 break; 203 204 case 1: 205 if((filp->f_pos + offset) > GLOBALFIFO_SIZE) 206 { ret = -EINVAL; 207 break; 208 } 209 210 if((filp->f_pos + offset) < 0) 211 { 212 ret = -EINVAL; 213 break; 214 } 215 filp->f_pos += offset; 216 ret = filp->f_pos; 217 break; 218 219 default: 220 ret = -EINVAL; 221 break; 222 } 223 224 return ret; 225 } 226 #endif 227 228 static const struct file_operations globalfifo_fops ={ 229 .owner = THIS_MODULE, 230 .read = globalfifo_read, 231 .write = globalfifo_write, 232 .open = globalfifo_open, 233 .release = globalfifo_release, 234 .llseek = globalfifo_llseek, 235 236 #if KELNEL_OLD 237 .unlocked_ioctl = globalfifo_ioctl, 238 #endif 239 }; 240 241 static int globalfifo_probe(struct platform_device *dev) 242 { 243 int ret; 244 dev_t devno; 245 246 /* Alloc for device major */ 247 if(globalfifo_major) 248 { 249 devno = MKDEV(globalfifo_major, globalfifo_minor); 250 ret = register_chrdev_region(devno, 1, NAME); 251 } 252 else 253 { 254 ret = alloc_chrdev_region(&devno, 0, 1, NAME); 255 globalfifo_major= MAJOR(devno); 256 } 257 258 /* Alloc for device major failure */ 259 if (ret < 0) 260 { 261 printk("%s driver can't get major %d\n", NAME, globalfifo_major); 262 return ret; 263 } 264 265 /* Initialize globalfifo structure and register cdev*/ 266 memset(&globalfifo_dev, 0, sizeof(struct globalfifo_dev)); 267 cdev_init (&(globalfifo_dev.cdev), &globalfifo_fops); 268 globalfifo_dev.cdev.owner = THIS_MODULE; 269 270 ret = cdev_add (&(globalfifo_dev.cdev), devno , 1); 271 if (ret) 272 { 273 printk (KERN_NOTICE "error %d add %s device", ret, NAME); 274 goto fail_cdev_add; 275 } 276 277 globalfifo_dev.class = class_create(THIS_MODULE, NAME); 278 if(IS_ERR(globalfifo_dev.class)) 279 { 280 printk("%s driver create class failure\n", NAME); 281 goto fail_class; 282 } 283 284 device_create(globalfifo_dev.class, NULL, devno, NULL, NAME); 285 286 return 0; 287 fail_class: 288 cdev_del(&(globalfifo_dev.cdev)); 289 290 fail_cdev_add: 291 unregister_chrdev_region(devno, 1); 292 printk("failure to insmod!\n"); 293 return ret; 294 } 295 296 297 static int globalfifo_remove(struct platform_device *pdev) 298 { 299 dev_t devno = MKDEV(globalfifo_major, globalfifo_minor); 300 301 cdev_del(&globalfifo_dev.cdev); 302 device_destroy(globalfifo_dev.class, devno); 303 class_destroy(globalfifo_dev.class); 304 305 unregister_chrdev_region(devno, 1); 306 printk("s3c %s driver removed\n", NAME); 307 308 return 0; 309 } 310 311 312 static struct platform_driver globalfifo_driver = { 313 .probe = globalfifo_probe, 314 .remove = globalfifo_remove, 315 .driver = { 316 .name = "globalfifo", 317 .owner = THIS_MODULE, 318 }, 319 }; 320 321 322 static int __init globalfifo_init(void) 323 { 324 int ret = 0; 325 326 ret = platform_device_register(&globalfifo_device); 327 if(ret) 328 { 329 printk(KERN_ERR "%s:%d: Can't register platform device %d\n", __FUNCTION__, __LINE__ ,ret); 330 goto fail_reg_plat_dev; 331 } 332 printk("Register S3C %s Platform Device successfully.\n", NAME); 333 334 ret = platform_driver_register(&globalfifo_driver); 335 if(ret) 336 { 337 printk(KERN_ERR "%s:%d: Can't register platform driver %d\n", __FUNCTION__, __LINE__, ret); 338 goto fail_reg_plat_drv; 339 } 340 printk("Register S3C %s Platform Driver successfully.\n", NAME); 341 342 return 0; 343 344 fail_reg_plat_drv: 345 platform_device_unregister(&globalfifo_device); 346 fail_reg_plat_dev: 347 return ret; 348 } 349 350 static void __exit globalfifo_exit(void) 351 { 352 printk("%s():%s remove %d platform drvier\n", __FUNCTION__, NAME, __LINE__); 353 platform_driver_unregister(&globalfifo_driver); 354 355 printk("%s():%s remove %d platform device\n", __FUNCTION__, NAME, __LINE__); 356 platform_device_unregister(&globalfifo_device); 357 } 358 359 module_init(globalfifo_init); 360 module_exit(globalfifo_exit); 361 MODULE_ALIAS("platform: globalfifo"); 362 MODULE_LICENSE("GPL");
Makefile:
1 #ARCH=x86 2 ARCH=arm920t 3 #PROJ=fl2440 4 PWD=$(shell pwd) 5 6 ifneq ("${ARCH}", "x86") 7 CROSS_COMPILE ?= /opt/buildroot-2011.11/${ARCH}/usr/bin/arm-linux- 8 KERNEL_DIR = ../../kernel/linux-3.8/ 9 else 10 KERNEL_DIR = /lib/modules/$(shell uname -r)/build 11 endif 12 13 obj-m += plat_globalfifo.o 14 15 all: 16 make -C $(KERNEL_DIR) SUBDIRS=$(PWD) modules 17 @make clear 18 19 clear: 20 @rm -f *.o *.cmd *.mod.c 21 @rm -rf *~ core .depend .tmp_versions Module.symvers modules.order -f 22 @rm -f .*ko.* *ko.* .*.o.cmd 23 24 clean: 25 rm -f *.ko *.o 26 rm -f cscope.* tags
测试程序:
1 #include <stdio.h> 2 #include <sys/types.h> 3 #include <sys/stat.h> 4 #include <fcntl.h> 5 #include <unistd.h> 6 #include <sys/ioctl.h> 7 #include <string.h> 8 9 #define MEM_CLEAR 0x20 10 #define MAX 0x1000 11 12 int main (int argc, char **argv) 13 { 14 int fd; 15 char buf[MAX] = "hello world"; 16 char buf2[MAX]; 17 18 fd = open("/dev/globalfifo", O_RDWR, 0755); 19 write(fd, buf, sizeof(buf)); 20 lseek(fd, 6, SEEK_SET); 21 read(fd, buf2, sizeof(buf2)); 22 printf("buf=%s, buf2=%s\n", buf, buf2); 23 24 close(fd); 25 return 0; 26 } /* ----- End of main() ----- */