最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

ic

运维笔记admin31浏览0评论

ic

ic

IC卡又称集成电路卡,它是在大小和普通 信用卡相同的塑料 卡片上嵌置一个或多个集成电路构成的。集成电路芯片可以是存储器或向处理器。作为一种身份验证的工具,IC卡经常出现于各种电子设备中,作为一种身份的确认的工具。

  下面以笔者参与的会议系统开发中的ICcard驱动程序为例,介绍linux系统下是如何进行IC card驱动程序开发的。

  1、是ic_card.h文件:

#ifndef    IC_CARD
#define    IC_CARD#include <mach/regs-gpio.h>
#include <linux/wait.h>
#include <linux/ioctl.h>#define IC_CARD_MAJOR    231#ifndef ICCARD_NR_DEVS
#define ICCARD_NR_DEVS 1    /*设备数*/
#endif#define IC_RMM_CMD     0x30    //读主存命令字
#define IC_WMM_CMD     0x38    //写主存命令字
#define IC_VER_CMD     0x33    //校验密码
#define IC_RSM_CMD     0x31    //读密码存储区
#define IC_WSM_CMD     0x39    //写密码存储区
#define IC_RPM_CMD     0x34    //读保护存储区
#define IC_WPM_CMD     0x3c    //写保护存储区#define IC_RDSTART_ADDR    (volatile unsigned char*)0X26
#define IC_WRSTART_ADDR    (volatile unsigned char*)0X26#define IC_IOCTL_MAGIC    'i'#define CFG_RD_COUNT    _IOW(IC_IOCTL_MAGIC,0,unsigned int)
#define CFG_WR_COUNT    _IOW(IC_IOCTL_MAGIC,1,unsigned int)#define SETB_CARD_CLK()   __raw_writel(__raw_readl(S3C2410_GPGDAT)|(1<<0),S3C2410_GPGDAT)
#define CLR_CARD_CLK()    __raw_writel(__raw_readl(S3C2410_GPGDAT)&(~(1<<0)),S3C2410_GPGDAT)#define SETB_CARD_RESRT() __raw_writel(__raw_readl(S3C2410_GPGDAT)|(1<<1),S3C2410_GPGDAT)
#define CLR_CARD_RESRT()  __raw_writel(__raw_readl(S3C2410_GPGDAT)&(~(1<<1)),S3C2410_GPGDAT)#define SETB_CARD_IO()    __raw_writel(__raw_readl(S3C2410_GPGDAT)|(1<<3),S3C2410_GPGDAT)
#define CLR_CARD_IO()    __raw_writel(__raw_readl(S3C2410_GPGDAT)&(~(1<<3)),S3C2410_GPGDAT)#define SETB_CARD_POWER()  __raw_writel(__raw_readl(S3C2410_GPGDAT)|(1<<7),S3C2410_GPGDAT)
#define CLR_CARD_POWER()  __raw_writel(__raw_readl(S3C2410_GPGDAT)&(~(1<<7)),S3C2410_GPGDAT)wait_queue_head_t r_wait;            //读等待队列
wait_queue_head_t w_wait;            //写等待队列

typedef struct _ic_card_dev
{unsigned char* readbufstart;    //读入数据缓冲区首指针
//    char* readbufend;    //读入数据缓冲区末指针 
    unsigned char* writebufstart;    //写入数据缓冲区首指针
//    char* writebufend;    //写入数据缓冲区末指针
    int readcount;        //读入数据量
    int writecount;        //写入数据量
    char* readp;            //读人数据当前指针
    int readnum;            //已经读入量
    char* writep;            //当前写入数据指针
    int writenum;        //当前写入量
    int ic_state;            //卡当前状态,O为无卡,1为有卡
    int statechange;        //卡状态变化标志 
    int irqno;int r_press;int w_press;}ic_card_dev;#endif /*IC_CARD*/

  2、实现模块的加载和卸载函数:

  1 /*注册设备驱动程序*/
  2  static int ic_card_init(void)
  3 {
  4     int ret;
  5     dev_t devno;
  6     ICDEBUG(KERN_ALERT "init ic card\n");
  7     devno = MKDEV(ic_major, 0);    
  8     if(IC_CARD_MAJOR)
  9     {    
 10         ret = register_chrdev_region(devno, 1, DEV_NAME);
 11         ICDEBUG(KERN_ALERT "register_chrdev_region ret:%d\n",ret);
 12     }
 13     else
 14     {
 15         ret=alloc_chrdev_region(&devno, 0, 2, DEV_NAME);
 16         ic_major=MAJOR(devno);
 17         ICDEBUG(KERN_ALERT "alloc_chrdev_region ret:%d,major:%d\n",ret,ic_major);
 18     }
 19     if(ret<0)
 20     {
 21         ICDEBUG(KERN_ALERT "if ret<0 ret:%d\n",ret);
 22         return ret;
 23     }
 24 
 25     cdev_init(&cdev_ic, &ic_fops);
 26     cdev_ic.owner=THIS_MODULE;
 27     cdev_ic.ops= &ic_fops;
 28     
 29      //向系统注册该字符设备
 30      ret = cdev_add(&cdev_ic, devno, ICCARD_NR_DEVS);
 31     ICDEBUG(KERN_ALERT "cdev_add ret:%d\n",ret);
 32 
 33     if (ret)
 34     {
 35         ICDEBUG("iccard init error\r\n");
 36         unregister_chrdev_region(devno,1);
 37         goto failregion;
 38     } 
 39 
 40 
 41     ic_card_class = class_create(THIS_MODULE, DEV_NAME);
 42     if(IS_ERR(ic_card_class))
 43     {
 44         ICDEBUG("can not creat a ic_card_class class!\n");
 45         goto failcls;
 46     }
 47     device_create(ic_card_class, NULL, MKDEV(IC_CARD_MAJOR, 0), NULL, DEV_NAME);
 48 
 49     /*注册中断*/
 50     ret=ic_request_irqs();
 51     if(ret<0)
 52     {
 53         ICDEBUG(KERN_ALERT "ic_card_request_irqs:ret:%d\n",ret);
 54         goto faildev;
 55     }    
 56 
 57     /*初始化时钟*/
 58     init_timer(&ic_timer);
 59     ic_timer.function=ic_timer_handler;
 60 
 61     spin_lock_init(&lock);
 62 
 63  /*    ic_dev_info=kmalloc(ICCARD_NR_DEVS*sizeof(struct ic_card_dev),GFP_KERNEL);
 64     if(!ic_dev_info)
 65     {
 66         ret =  -ENOMEM; 
 67         goto fail;
 68     }
 69  */
 70     //初始化等待对列
 71       init_waitqueue_head(&r_wait);
 72      init_waitqueue_head(&w_wait);
 73     ICDEBUG("ic card init success!\r\n");
 74     
 75      return 0;
 76 faildev:
 77     ICDEBUG(KERN_ALERT "init ic card fail\n");
 78     device_destroy(ic_card_class, MKDEV(IC_CARD_MAJOR, 0));
 79 failcls:
 80     class_destroy(ic_card_class);
 81 failregion:
 82     unregister_chrdev_region(devno, 1);
 83     return ret;
 84     
 85 }
 86 
 87  /*注销设备驱动程序*/
 88  static void ic_card_exit(void)
 89 {
 90     /*释放中断*/
 91     ic_free_irqs();
 92 
 93     cdev_del(&cdev_ic);
 94 //    kfree(ic_dev_info);
 95     device_destroy(ic_card_class, MKDEV(IC_CARD_MAJOR, 0));
 96     class_destroy(ic_card_class);
 97     unregister_chrdev_region(MKDEV(ic_major,0), 1);
 98     ICDEBUG(KERN_ALERT "ic card unregister\n");
 99 
100 }
101 
102 module_init(ic_card_init);
103 module_exit(ic_card_exit);

首先,判断IC_CARD_MAJOR,即是否为设备指定了主设备号,如果IC_CARD_MAJOR不为0,则调用register_chrdev_region()函数注册设备驱动程序。通过register_chrdev_region()函数用于分配指定的设备编号范围。如果申请的设备编号范围跨越了主设备号,它会把分配范围内的编号按主设备号分割成较小的子范围,并在每个子范围上调用 __register_chrdev_region() 。如果其中有一次分配失败的话,那会把之前成功分配的都全部退回。

如果IC_CARD_MAJOR为0,则调用 alloc_chrdev_region()动态分配主设备号给驱动程序。

 linux 2.6 内核采用struct cdev来记录字符设备的信息,通过cdev_init初始化一个静态分配的cdev对象,详细请参考.shtml 

调用cdev_add()函数向系统注册该字符设备.

  class_create()函数及device_create()函数使得module被加载时,udev daemon就会自动在/dev下创建IC_CARD设备文件。
  然后申请中断,初始化定时器,定时器ic_timer用于消除插卡中的抖动问题,再调用init_waitqueue_head()初始化等待队列。

至此,ic_card驱动程序加载完成。

3、各IC_card操作函数:

static struct file_operations ic_fops={.open    =ic_open,.write    =ic_card_wrtie,.read    =ic_card_read,.poll    =ic_poll,.ioctl    =ic_ioctl,.release=ic_release,.fsync    =NULL,
};

具体实现如下:

    /*调用ic_request_irqs注册中断处理程序
*配置引脚
*/int ic_open (struct inode *inode, struct file *filp)
{int num;int ret=0;unsigned long flags;ICDEBUG(KERN_ALERT "open ic card\n");//获取次设备号
        num = MINOR(inode->i_rdev);ICDEBUG(KERN_ALERT "MINOR:%d\n",num);if (num >= ICCARD_NR_DEVS) return -ENODEV;spin_lock_irqsave(&lock,flags);filp->private_data=&ic_dev_info[num];//检测IC卡是否已插入设备
    s3c2410_gpio_cfgpin(S3C2410_GPG6,S3C2410_GPG6_INP);    //ICCARD_INTEREPT
    if((__raw_readw(S3C2410_GPGDAT)&(1<<6))==0<<6){ic_dev_info[num].ic_state=1;    //代表卡已插入
        ic_dev_info[num].r_press=1;    //设备可读
        ic_dev_info[num].w_press=1;    //设备可写
        ICDEBUG(KERN_ALERT "has ic card device\n");}else{ic_dev_info[num].ic_state=0;    //代表卡已插入
        ic_dev_info[num].r_press=0;    //设备可读
        ic_dev_info[num].w_press=0;    //设备可写
        ICDEBUG(KERN_ALERT "no found ic card device\n");}spin_unlock_irqrestore(&lock,flags);//初始化输入输出引脚
    init_gpio();ICDEBUG(KERN_ALERT "open ic card success\n");return ret;
}int ic_release(struct inode *inode, struct file *filp)
{//ic_free_irqs();
    return 0;
}/*
*从ic卡中读出一个字节的数据
*/int ic_card_read_byte(char *ch)
{int ret=0;int ii;for(ii = 8; ii>0; ii--){CLR_CARD_CLK();udelay(5);*ch=(*ch)>>1;        //从低位读起 //if((__raw_readw(S3C2410_GPGDAT)&0x0008)==0x0008)
        if((__raw_readw(S3C2410_GPGDAT)&(1<<3))==1<<3){*ch|=0x80;ICDEBUG(KERN_ALERT "<------------->\n");}else{ICDEBUG(KERN_ALERT "<|||||||||||||>\n");}udelay(5);SETB_CARD_CLK();}ICDEBUG(KERN_ALERT "ic_card_read_byte:ch is>>>>>(%c)\n",*ch);return ret;
}int ic_card_write_byte(char *ch)
{int ret=0;int ii;ICDEBUG(KERN_ALERT "enter ic_card_write_byte,ch is %c\n",*ch);for(ii= 0; ii<8; ii++){CLR_CARD_CLK();udelay(5);if(*ch&0x01){ICDEBUG(KERN_ALERT "[+++++$++++++++]\n");SETB_CARD_IO();    //输入1
        }else{ICDEBUG(KERN_ALERT "[-----$--------]\n");CLR_CARD_IO();        //输入0
        }udelay(5);        SETB_CARD_CLK();udelay(10);*ch=*ch>>1;}return ret;}/*
*复位和复位应答
*/static int ic_card_reset(void)
{unsigned char temp_ch;int temp_i = 4;s3c2410_gpio_cfgpin(S3C2410_GPG3,S3C2410_GPG3_OUTP);    //OUT
    udelay(5);CLR_CARD_RESRT();CLR_CARD_CLK();SETB_CARD_IO();udelay(5);SETB_CARD_RESRT();udelay(5);SETB_CARD_CLK();udelay(30);CLR_CARD_CLK();udelay(5);CLR_CARD_RESRT();s3c2410_gpio_cfgpin(S3C2410_GPG3,S3C2410_GPG3_INP);    //IN
    udelay(10);do{//temp_ch = ic_card_read_byte();
        ic_card_read_byte(&temp_ch);ICDEBUG(KERN_ALERT "ic_card_reset:temp_ch is(%c)\n",temp_ch);}while(--temp_i>0);CLR_CARD_CLK();s3c2410_gpio_cfgpin(S3C2410_GPG3,S3C2410_GPG3_OUTP);    //IN
    udelay(5);SETB_CARD_IO();udelay(5);CLR_CARD_CLK();udelay(5);return 0;
}/*
*命令开始条件
*/void ic_card_start_cmd(void)
{s3c2410_gpio_cfgpin(S3C2410_GPG3,S3C2410_GPG3_OUTP);    //out
    CLR_CARD_CLK();SETB_CARD_IO();udelay(5);SETB_CARD_CLK();udelay(5);CLR_CARD_IO();udelay(5);
}/*
*命令结束条件
*/void ic_card_end_cmd(void)
{s3c2410_gpio_cfgpin(S3C2410_GPG3,S3C2410_GPG3_OUTP);    CLR_CARD_CLK();CLR_CARD_IO();udelay(5);SETB_CARD_CLK();udelay(5);SETB_CARD_IO();udelay(5);
}/*发送命令*/void ic_card_send_cmd(const char cmd,const char addr,const char count)
{ICDEBUG(KERN_ALERT "enter ic_card_read:cmd is %c,addr is %c,count is %c\n",cmd,addr,count);ic_card_start_cmd();ic_card_write_byte(&cmd);ic_card_write_byte(&addr);ic_card_write_byte(&count);ic_card_end_cmd();
}void ic_card_breakoperator(void)
{s3c2410_gpio_cfgpin(S3C2410_GPG3,S3C2410_GPG3_OUTP);    CLR_CARD_CLK();CLR_CARD_RESRT();CLR_CARD_IO();udelay(5);SETB_CARD_RESRT();SETB_CARD_IO();udelay(5);CLR_CARD_RESRT();udelay(5);
}/*从设备中读取指定长度的数据*/
ssize_t ic_dev_read(struct file *filep,const char *buf, size_t count, loff_t *offset)
{int ret=0;// wait_event_interruptible();    //char *kbuf;
    int istate;int sizetmp;char* pbuf;//unsigned char ch=0;
ic_card_dev* icdev=(ic_card_dev*)filep->private_data;ICDEBUG(KERN_ALERT "enter ic_dev_read\n");istate = icdev->ic_state;ICDEBUG(KERN_ALERT "ic_dev_istate:%d\n",istate);pbuf=buf;if(!istate){return -ENODEV;}if(!pbuf){return -1;}sizetmp=count;s3c2410_gpio_cfgpin(S3C2410_GPG3,S3C2410_GPG3_INP);    //将GPG3配置成输入引脚
CLR_CARD_CLK();udelay(5);do{ic_card_read_byte(pbuf++);//*buf++ = ic_card_read_byte();
        ret++;ICDEBUG(KERN_ALERT "[ic_card_read:buf is (%c) ret:%d]\n",*(pbuf-1),ret);}while(--sizetmp);return ret;}/*往设备中写入数据*/
ssize_t ic_dev_wrtie(struct file *filep, char *buf, size_t count, loff_t *offset)
{int ret = 0;int istate;unsigned long flags;int sizetmp;ICDEBUG(KERN_ALERT "enter ic_dev_wrtie\n");spin_lock_irqsave(&lock,flags);istate = ((ic_card_dev*)(filep->private_data))->ic_state;spin_unlock_irqrestore(&lock,flags);if(!istate){return -ENODEV;}if(!buf)return -1;//    wait_event_interruptible();
s3c2410_gpio_cfgpin(S3C2410_GPG3, S3C2410_GPG3_OUTP);//将GPG3配置成输出引脚
sizetmp=count;do{ic_card_write_byte(buf++);    //按字节发送至ic卡
    }while(--sizetmp);return ret;
}/*file_operations read*/
ssize_t ic_card_read(struct file *filep, char __user *buf, size_t count, loff_t *offset)
{//int ii;
    int ret;char* kbuf;unsigned long flags;int r_press;ICDEBUG(KERN_ALERT "enter ic_card_read\n");spin_lock_irqsave(&lock,flags);r_press=((ic_card_dev*)filep->private_data)->r_press;spin_unlock_irqrestore(&lock,flags);ICDEBUG(KERN_ALERT "ic_card_read:r_press is:%d\n",r_press);wait_event_interruptible(r_wait, r_press!=0);kbuf=kmalloc(count,GFP_KERNEL);if(!kbuf){return -ENOMEM;}spin_lock_irqsave(&lock,flags);((ic_card_dev*)filep->private_data)->w_press=0;spin_unlock_irqrestore(&lock,flags);ic_card_reset();ic_card_send_cmd((const char)IC_RMM_CMD,(const char)((ic_card_dev*)(filep->private_data))->readbufstart,0xff);ret = ic_dev_read(filep, kbuf,  count,  offset);ICDEBUG(KERN_ALERT "[ic_card_read kbuf is:%s]\n",kbuf);if(ret>=0){ret = copy_to_user(buf,kbuf,count);}ICDEBUG(KERN_ALERT "<ic_dev_read kbuf:(%s),buf:(%s)ret:%d;count:%d>\n",kbuf,buf,ret,count);ic_card_breakoperator();spin_lock_irqsave(&lock,flags);((ic_card_dev*)filep->private_data)->w_press=1;spin_unlock_irqrestore(&lock,flags);kfree(kbuf);return ret;
}/*file_operations write*/
ssize_t ic_card_wrtie(struct file *filep, char __user *buf, size_t count, loff_t *offset)
{int ret;char* kbuf;unsigned long flags;int w_press;ICDEBUG(KERN_ALERT "enter ic_card_wrtie\n");spin_lock_irqsave(&lock,flags);w_press=((ic_card_dev*)filep->private_data)->w_press;spin_unlock_irqrestore(&lock,flags);kbuf=kmalloc(count,GFP_KERNEL);if(!kbuf){return -ENOMEM;}wait_event_interruptible(r_wait, w_press!=0);//if(w_press)//{
    spin_lock_irqsave(&lock,flags);((ic_card_dev*)filep->private_data)->r_press=0;spin_unlock_irqrestore(&lock,flags);ic_card_reset();ic_card_send_cmd((const char)IC_WMM_CMD,(const char)((ic_card_dev*)(filep->private_data))->writebufstart,count);if(copy_from_user(kbuf, buf, count)){kfree(kbuf);return -EFAULT;}ICDEBUG(KERN_ALERT "copy_from_user kbuf------------->:%s\n",kbuf);ret = ic_dev_wrtie(filep, kbuf, count, offset);printk(KERN_ALERT "ic_dev_wrtie ret : %d\n",ret);ic_card_breakoperator();spin_lock_irqsave(&lock,flags);((ic_card_dev*)filep->private_data)->w_press=1;spin_unlock_irqrestore(&lock,flags);kfree(kbuf);ICDEBUG(KERN_ALERT "ic_card_wrtie success\n");return ret;
}int ic_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, unsigned long arg)
{unsigned int icount;unsigned long flags;spin_lock_irqsave(&lock,flags);switch(cmd){case CFG_RD_COUNT:icount = (unsigned int)arg;((ic_card_dev*)filep->private_data)->readcount=icount;break;case CFG_WR_COUNT:icount=(unsigned int)arg;((ic_card_dev*)filep->private_data)->writecount=icount;break;default:break;}spin_unlock_irqrestore(&lock,flags);return 0;
}/*
#define POLLIN   0x0001  //有数据可以读入,read不会阻塞,注意:select的请情况下,即使到EOF也是ready的.
#define POLLPRI  0x0002 //紧急数据,比如TCP,或者packet模式的peseudo-terminal发现slave的状态有变化.
#define POLLOUT  0x0004 //写入不会阻塞.
#define POLLERR  0x0008 //输出出错
#define POLLHUP  0x0010 //Hang up (output only).
#define POLLNVAL  0x0020 //Invalid request: fd not open (output only).
The rest seem to be more-or-less nonstandard. Check them! 
#define POLLRDNORM 0x0040 //POLLIN.
#define POLLRDBAND 0x0080 //高优先级的数据read for read (generally unused on Linux).
#define POLLWRNORM 0x0100 //Equivalent to POLLOUT.
#define POLLWRBAND 0x0200 //Priority data may be written.
#define POLLMSG  0x0400
#define POLLREMOVE 0x1000
*/
unsigned int ic_poll (struct file *filep, struct poll_table_struct *wait)
{int ic_num=0;//test
    unsigned int mask = 0;unsigned long flags;//加入这句话是为了在读写状态发生变化的时候,通知核心层,让核心层重新调用poll函数查询信息。也就是说这两句只会在select阻塞的时候用到//当利用select函数发现既不能读又不能写时,select函数会阻塞,但是此时的阻塞并不是轮询,而是睡眠,通过下面两个队列发生变化时通知select
    poll_wait(filep, &r_wait, wait);poll_wait(filep, &w_wait, wait);spin_lock_irqsave(&lock,flags);if(ic_dev_info[ic_num].r_press != 0)mask |= POLLIN | POLLRDNORM;    //可读,同时写上POLLRDNORM
if(ic_dev_info[ic_num].w_press !=0)mask |= POLLOUT | POLLWRNORM;spin_unlock_irqrestore(&lock,flags); return mask;}
    //#define ICDEBUG
#ifdef     ICDEBUG#ifdef __KERNEL__#define    ICDEBUG(fmt,args...)    printk(KERN_ALERT "ic card:"fmt,##args)#else#define ICDEBUG(fmt,args...)    fprintf(stderr,fmt,##args)#endif#else#define ICDEBUG(fmt,args...)#endif#define DEV_NAME    "ic_card"#define IC_TIMER_DELAY    (HZ/50)#define ICCARD_INT_NAME  "ic_irq_handler"static int ic_major=IC_CARD_MAJOR;static struct class* ic_card_class;/*linux 内核定时器
struct timer_list { 
struct list_head list; 
unsigned long expires; 
unsigned long data; 
void (*function)(unsigned long); 
};
*/static struct timer_list ic_timer;/*自旋锁基本API:头文件: <linux/spinlock.h> 
数据类型: spinlock_t 
初始化, 以下两种方法: 
静态: spinlock_t my_lock = SPIN_LOCK_UNLOCKED; 
动态: void spin_lock_init(spinlock_t *lock); 
获得锁: void spin_lock(spinlock_t *lock); 
释放锁: void spin_unlock(spinlock_t *lock); 
*/
spinlock_t lock;/*
内核中每个字符设备都对应一个 cdev 结构的变量,下面是它的定义:
struct cdev {struct kobject kobj;          // 每个 cdev 都是一个 kobjectstruct module *owner;       // 指向实现驱动的模块const struct file_operations *ops;   // 操纵这个字符设备文件的方法struct list_head list;       // 与 cdev 对应的字符设备文件的 inode->i_devices 的链表头dev_t dev;                   // 起始设备编号unsigned int count;       // 设备范围号大小
}; 
一个 cdev 一般它有两种定义初始化方式:静态的和动态的。
静态内存定义初始化:
struct cdev my_cdev;
cdev_init(&my_cdev, &fops);
my_cdev.owner = THIS_MODULE;动态内存定义初始化:
struct cdev *my_cdev = cdev_alloc();
my_cdev->ops = &fops;
my_cdev->owner = THIS_MODULE;两种使用方式的功能是一样的,只是使用的内存区不一样,一般视实际的数据结构需求而定。*/struct cdev cdev_ic;/*IC_CARD设备结构体*/static ic_card_dev ic_dev_info[ICCARD_NR_DEVS]=
{{IC_RDSTART_ADDR,    /*readbufstart*/IC_WRSTART_ADDR,    /*writebufstart*/0,                    /*readcount*/0,                    /*writecount*/NULL,                /*readp*/0,                    /*readnum*/NULL,                /*writep*/0,                    /*writenum*/0,                    /*ic_state*/0,                    /*statechange*/IRQ_EINT14,                    /*irqno*/0,                    /*r_press*/0,                    /*w_press*/},
};/*将输入引脚配置成中断引脚*/static void pin_input_to_int(void)
{__raw_writel((__raw_readl(S3C2410_GPGCON) & (~(0x03<<12))) | (0x02<<12),S3C2410_GPGCON);__raw_writel((__raw_readl(S3C2410_EXTINT1) & (~(0x07<<24))) |(0x06<<24),S3C2410_EXTINT1);
}/*将中断引脚配置成输入引脚*/static void pin_int_to_input(void)
{__raw_writel(__raw_readl(S3C2410_GPGCON)&(~(0x03<<12)),S3C2410_GPGCON);
}/**中断服务程序,通知ic卡已插入*/static irqreturn_t ic_interrupt_proc(int irq,void *dev_id)
{    unsigned long flags;spin_lock_irqsave(&lock,flags);if(ic_dev_info[0].statechange==0){ic_dev_info[0].statechange=1;spin_unlock_irqrestore(&lock,flags);}else{spin_unlock_irqrestore(&lock,flags);return IRQ_HANDLED;}ICDEBUG(KERN_ALERT "+++++++++++++++++++++++++++++++\n");/*将中断引脚配置成为输入引脚,消除抖动*/pin_int_to_input();ic_timer.expires = jiffies + IC_TIMER_DELAY;        //delay 20 ms         //全局变量jiffies用来记录自系统启动以来产生的节拍的总数
    add_timer(&ic_timer);return IRQ_HANDLED;
}/*定时器回调函数,当设定时间到来时,自动调用本程序*/static void ic_timer_handler(unsigned long time)
{int ic_num=0;//test
    unsigned long flags;ICDEBUG(KERN_ALERT "enter ic_interrupt_proc\n");spin_lock_irqsave(&lock,flags);if(ic_dev_info[ic_num].ic_state==0)    {ic_dev_info[ic_num].ic_state=1;    //代表卡已插入
        ic_dev_info[ic_num].r_press=1;    //设备可读
        ic_dev_info[ic_num].w_press=1;    //设备可写
        wake_up_interruptible(&r_wait);wake_up_interruptible(&w_wait);ICDEBUG(KERN_ALERT "ic device enter,wake up interrupt ic_interrupt_proc\n");}else{ic_dev_info[ic_num].ic_state=0;    //代表卡已拔出
        ic_dev_info[ic_num].r_press=0;    //设备不可读
        ic_dev_info[ic_num].w_press=0;    //设备不可写
        ICDEBUG(KERN_ALERT "ic device leave,wake up interrupt ic_interrupt_proc\n");}del_timer(&ic_timer);/*重新配置中断引脚*/pin_input_to_int();ic_dev_info[0].statechange=0;spin_unlock_irqrestore(&lock,flags);
}/*ic卡插入时和拔出时(下降沿/上升沿)产生的中断处理程序的注册*/static int ic_request_irqs(void)
{int ret,i;for(i=0;i<ICCARD_NR_DEVS;i++){ret = request_irq(ic_dev_info[i].irqno,ic_interrupt_proc,IRQ_TYPE_EDGE_BOTH,DEV_NAME,NULL);ICDEBUG(KERN_ALERT "interrupt:number:%d\n",ic_dev_info[i].irqno);}return ret;
}static void ic_free_irqs(void)
{int i;for(i=0;i<ICCARD_NR_DEVS;i++)free_irq(ic_dev_info[i].irqno,NULL);return;
}/*
*初始化通用输入/输出引脚
*/static void init_gpio(void)
发布评论

评论列表(0)

  1. 暂无评论