• 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
    ");
    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
    ", 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
    ", 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
    ", 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
    ", 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!
    ");
    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
    ", 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
    ", __FUNCTION__, __LINE__ ,ret);
    330         goto fail_reg_plat_dev;
    331     }
    332     printk("Register S3C %s Platform Device successfully.
    ", 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
    ", __FUNCTION__, __LINE__, ret);
    338         goto fail_reg_plat_drv;
    339     }
    340     printk("Register S3C %s Platform Driver successfully.
    ", 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
    ", __FUNCTION__, NAME, __LINE__);
    353     platform_driver_unregister(&globalfifo_driver);
    354 
    355     printk("%s():%s remove %d platform device
    ", __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
    ", buf, buf2);
    23 
    24     close(fd);
    25     return 0;
    26 } /* ----- End of main() ----- */
  • 相关阅读:
    js 脚本学习 索引
    nodejs 学习索引
    oracle 学习 笔记
    githut 的 管理 使用
    sublime text 插件记录
    web 学习 相关索引
    wpf 自定义 无边框 窗体 resize 实现
    vs 效率工具
    ANDROID开发实用小工具
    iOS开发之Core Animation
  • 原文地址:https://www.cnblogs.com/xiaoxing/p/3953420.html
Copyright © 2020-2023  润新知