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() ----- */

 

posted on 2014-09-03 12:38  小猩  阅读(454)  评论(0编辑  收藏  举报

导航