⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 iccard0911.c

📁 嵌入式系统上用的SMARTCARD的驱动
💻 C
📖 第 1 页 / 共 3 页
字号:
/************************************************************************************************
* 								
*	Copyright (C) EVOC  Co., LTD. 2003		
*								
*	File name:	IcCard.c				
*	Description:    
*	  							
*	Revision history					
*               2006.05.17      Zou Hong Bo	start.	
*								
************************************************************************************************/
/* Include files--------------------------------------------------------------*/
 
//#include "iccard_hw.h"
#include <linux/version.h>
#include <linux/kernel.h>     /* We're doing kernel work */
#include <linux/module.h>     /* Specifically, a module */ 
#include <linux/interrupt.h>  /* We want interrupts */

#include <linux/miscdevice.h> /* for misc_register() and misc_deregister() */

#include <linux/fs.h>         /* for struct 'file_operations' */

#include <linux/timer.h>     /* for timeout interrupts */
#include <linux/param.h>     /* for HZ. HZ = 100 and the timer step is 1/100 */
#include <linux/sched.h>     /* for jiffies definition. jiffies is incremented*/
                              /* once for each clock tick; thus it's incremented*/			      
                              /* HZ times per secondes.*/
#include <linux/mm.h>        /* for verify_area */
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/sched.h>
#include <linux/init.h>
#include <linux/iccard.h>

#include <asm/irq.h>         /* For IRQ_MACHSPEC */
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/arch/irqs.h>
#include <asm/arch/hardware.h>
#include <asm/44b.h>
#include <asm/def.h>



#define DEBUG_ICCARD	// for debug only
//#define NULL 0

#define	CPU_CARD	0x01
#define	SAM_CARD	0x02

#define	CPU_CARD_POW	(1<<3)
#define	SAM_CARD_POW	(1<<2)

#define	CPU_CARD_RST	(1<<6)
#define	SAM_CARD_RST	(1)

#define IC_LED_POW    (1<<8)

//#define	TIMEROUT_ERR	0xff
#define	MAX_TIME_OUT	0XFFF0
#define	CARD_OUT	(1<<12)
#define	CARD_IN	(1<<13)

//#define CARD_RX 		(rPDATC&CARD_IN	)? 1:0	
//#define CARD_TX_SET		rPDATC = rPDATC|CARD_OUT
//#define CARD_TX_CLR		rPDATC = rPDATC&(~CARD_OUT)

#define CARD_RX 		(inl(S3C44B0X_PDATC) & CARD_IN	)? 1:0	
#define CARD_TX_SET		outl(inl(S3C44B0X_PDATC) | CARD_OUT,S3C44B0X_PDATC)
#define CARD_TX_CLR		outl(inl(S3C44B0X_PDATC) &(~CARD_OUT),S3C44B0X_PDATC)

#define RE_REVEIVE_TIMES	3			//重发重收的次数
#define RE_SEND_TIMES		3			//重发重收的次数

#define etu_time_all  0x2ac
#define etu_time_half  0x366


#define ATR_MAX_LEN		32			//max atr len

#define TS_BIT		1
#define NOT_TS_BIT	0

#define LAST_BYTE		1
#define NOT_LAST_BYTE		0

#define POSITIVE_LOGIC	0
#define NEGATIVE_LOGIC	1

#define EVOC_ICCARD_BUF_SIZE 1024

#define TIMEOUT_MAX_CYCLE  (360000*TC2_WI)			//120000 about 1s 960etu
#define REV_TS_TIMEOUT_CYCLE	  180000	

static struct ICCARDFIFO {
	unsigned char buffer[EVOC_ICCARD_BUF_SIZE];
	int len;
}iccardfifo;

#ifdef CONFIG_DEVFS_FS 
	static devfs_handle_t devfs_IC_dir,devfs_ICraw;
#endif

#define IC_MAJOR   115
#define IC_MINOR   0
#define DEVICE_NAME    "s3c44b0ic"

static int TC2_WI = 10;

static int logic_mode_sam = POSITIVE_LOGIC;
static int logic_mode_usr = POSITIVE_LOGIC;

static unsigned char protect_time_sam = 0;
static unsigned char protect_time_usr = 0;

static int samcard_err = -1;
static int usrcard_err = -1;

static int card_selected=NONECARD;

unsigned char iccard_ctr=0;

static const char* __file__ = __FILE__;
static int    iccard_device_open = 0;   /* number of open device to prevent concurrent*/
                                         /* access to the same device */
static char time_flag=0;
//*******************************************************
//*******************************************************
static unsigned char swapbits(unsigned char i) 
{
  return i >> 7
       | (i & 0x40) >> 5
       | (i & 0x20) >> 3
       | (i & 0x10) >> 1
       | (i & 0x08) << 1
       | (i & 0x04) << 3
       | (i & 0x02) << 5
       | i << 7;
}

//*******************************************************
//*******************************************************
static void EVOC_LED_ON(void)
{
	outl((inl(S3C44B0X_PDATC) & (~IC_LED_POW )),S3C44B0X_PDATC);
	
}
//*******************************************************
//*******************************************************
static void EVOC_LED_OFF(void)
{
	outl((inl(S3C44B0X_PDATC) | (IC_LED_POW)),S3C44B0X_PDATC);
}
//*******************************************************
//*******************************************************
static void etu_time_handle(int irq,void *dev_id,struct pt_regs *regs)
{
		time_flag = 1;
		printk("input time interrupt\n");
		//outl(0x777, S3C44B0X_TCNTB1);
		s3c44b0x_clear_pb(S3C44B0X_INTERRUPT_TIMER1);
		//outl(0x1000, S3C44B0X_F_ISPC);
}
//*******************************************************
//*******************************************************
static void delay_1200_cycle(void)
{	
	//500 cycles=148us
	int i;
	for(i=0;i<3000;i++);
}
//*******************************************************
//*******************************************************
static void delay_cycle(unsigned int count)
{	
	//500 cycles=148us
	//int i;
	for(;count>0;count--);
}
//*******************************************************
//*******************************************************
static void EVOC_iccard_set_port(void)
{
		u_int32_t tmod;
		outl(0xf1555555,S3C44B0X_PCONC);
		//rPCONC = 0xf1555555;	// rxd1 as input; txd1 as output
								// pc12 is txd1; pc13 is rxd1
		outl(0xF9FF,S3C44B0X_PDATC);						
		//rPDATC = 0xF9FF;
		tmod = inl(S3C44B0X_PCONE);
		tmod &= ~(0x03<<6);
		tmod |= 0x01<<6;
		tmod &= ~(0x03<<16);
		tmod |= 0x01<<16;
				
		outl(tmod,S3C44B0X_PCONE);
		
		outl((inl(S3C44B0X_PDATE) & 0x77),S3C44B0X_PDATE);
		
		tmod = inl(S3C44B0X_PCONG);
		tmod &= ~(0x03<<12);
		tmod |= 0x01<<12;
				
		outl(tmod,S3C44B0X_PCONG);
		
		outl((inl(S3C44B0X_PDATG) | 0x40),S3C44B0X_PDATG);
		
		// zhp add 20060608 for GPF6
		outl(0X8040A,S3C44B0X_PCONF);
		outl(0X14F,S3C44B0X_PDATF);
		//rPCONF = 0X8040A;		     
		//rPDATF = 0X14F;

}
//*******************************************************
//*******************************************************
static void EVOC_select_usr(void)
{
	outl((inl(S3C44B0X_PDATE) | 0x08),S3C44B0X_PDATE);
}
//*******************************************************
//*******************************************************
static void EVOC_select_sam(void)
{
	outl((inl(S3C44B0X_PDATE) & 0x77),S3C44B0X_PDATE);
}
//*******************************************************
//*******************************************************
static void EVOC_usr_set_card_rst(void)
{
	//outl(inl(S3C44B0X_PDATE) | 0x08,S3C44B0X_PDATE);
	outl((inl(S3C44B0X_PDATG) & (~CPU_CARD_RST)),S3C44B0X_PDATG);
}
//*******************************************************
//*******************************************************
static void EVOC_usr_clr_card_rst(void)
{
	//outl(inl(S3C44B0X_PDATE) | 0x08,S3C44B0X_PDATE);
	outl((inl(S3C44B0X_PDATG) | (CPU_CARD_RST)),S3C44B0X_PDATG);
}
//*******************************************************
//*******************************************************
static void EVOC_usr_card_pwr_off(void)
{
	outl((inl(S3C44B0X_PDATC) | (CPU_CARD_POW)),S3C44B0X_PDATC);
	EVOC_LED_OFF();
}
//*******************************************************
//*******************************************************
static void EVOC_usr_card_pwr_on(void)
{
	outl((inl(S3C44B0X_PDATC) & (~CPU_CARD_POW)),S3C44B0X_PDATC);
	EVOC_LED_ON();
}
//*******************************************************
//*******************************************************
static void EVOC_sam_set_card_rst(void)
{
	//outl(inl(S3C44B0X_PDATE) & 0x77,S3C44B0X_PDATE);
	outl((inl(S3C44B0X_PDATC) & (~SAM_CARD_RST)),S3C44B0X_PDATC);
}
//*******************************************************
//*******************************************************
static void EVOC_sam_clr_card_rst(void){
	//outl(inl(S3C44B0X_PDATE) & 0x77,S3C44B0X_PDATE);
	outl((inl(S3C44B0X_PDATC) | (SAM_CARD_RST)),S3C44B0X_PDATC);
}
//*******************************************************
//*******************************************************
static void EVOC_sam_card_pwr_off(void){
	outl((inl(S3C44B0X_PDATC) | (SAM_CARD_POW)),S3C44B0X_PDATC);
	EVOC_LED_OFF();
}
//*******************************************************
//*******************************************************
static void EVOC_sam_card_pwr_on(void){
	outl((inl(S3C44B0X_PDATC) & (~SAM_CARD_POW)),S3C44B0X_PDATC);
	EVOC_LED_ON();
}

//*******************************************************
//*******************************************************
static void EVOC_sam_card_release(void){
	EVOC_sam_clr_card_rst();
	EVOC_sam_card_pwr_off();
	iccardfifo.len = 0;
}
//*******************************************************
//*******************************************************
static void EVOC_usr_card_release(void){
	EVOC_usr_clr_card_rst();
	EVOC_usr_card_pwr_off();
	iccardfifo.len = 0;		

}
//*******************************************************
//*******************************************************
int EVOC_show_card_err_msg(int errcode){
	printk("\nerrcode = %d ,  ",errcode); 
	if (errcode>=0){
		printk("OK!\n"); 	
	}
	else if (errcode == TIMEROUT_ERR) {
		printk("Time out err\n"); 
	}
	else if (errcode == PARITY1_ERR) {
		printk("receive parity err\n"); 
	}
	else if (errcode == PARITY2_ERR) {
		printk("send parity err\n"); 
	}
	else if (errcode == CARD_ERR) {
		printk("card err, not cpu card\n"); 
	}
	else if (errcode == ATR_LEN_ERR) {
		printk("card response len err\n"); 
	}
	else if (errcode == ATR_XOR_ERR) {
		printk("card response parity err\n"); 
	}
	else if (errcode == NO_SELECTED_CARD_ERR) {
		printk("No card be selected err\n"); 
	}
	else if (errcode == ADPU_ERR) {
		printk("ADPU CMD format err\n"); 
	}
	else if (errcode == NO_CARD_ERR) {
		printk("No card in card slot err\n"); 
	}
	else { 
		printk("other  err\n"); 
	}
	return 0;
}
//*******************************************************
//*******************************************************
void	delay_half_etu(void)
{	// about 52u	//40MHz
	int i;
	for(i=0;i<730;i++);//768
}
//*******************************************************
//*******************************************************
void	delay_one_etu(void)
{	// about 104u	//40MHz
	int i;
	for(i=0;i<1500;i++);//1547
}
//*******************************************************
//*******************************************************
static int EVOC_send_one_byte(unsigned char * send_data, int send_last_byte){

	int i;
	unsigned char senddata;
	int re_send_times;
	int send_parity_bit;
	unsigned char protect_time=0;

	re_send_times = 0;

	if (card_selected==SAMCARD) {
		protect_time = protect_time_sam;
		if (logic_mode_sam == NEGATIVE_LOGIC) {
			senddata =  swapbits(*send_data);
		}
		else{
			senddata =  (*send_data);
		}
	}
	else if(card_selected==USRCARD){
		protect_time = protect_time_usr;
		if (logic_mode_usr == NEGATIVE_LOGIC){
			senddata =  swapbits(*send_data);
		}
		else {
			senddata =  (*send_data);
		}
	}
	else return NO_SELECTED_CARD_ERR;

	send_parity_bit =  ( (  senddata         >> 7)
			    ^( (senddata & 0x40) >> 6)
			    ^( (senddata & 0x20) >> 5)
			    ^( (senddata & 0x10) >> 4)
			    ^( (senddata & 0x08) >> 3)
		            ^( (senddata & 0x04) >> 2)
		            ^( (senddata & 0x02) >> 1)
		            ^( (senddata & 0x01)     ) ); 
		            
//	if (senddata==0x84) send_parity_bit=1;
	
	CARD_TX_SET;
	
	while ( re_send_times < RE_SEND_TIMES )
	{
		if (card_selected==SAMCARD) 
		{
			//EVOC_select_sam();		
		}
		else if(card_selected==USRCARD)
		{
			//EVOC_select_usr();	
		}
		else return NO_SELECTED_CARD_ERR;	
			
		CARD_TX_CLR;	//start bit
		delay_one_etu();	// 1 etu
		
		for(i=0;i<8;i++)
		{	//8 bit data
			if ( (senddata>>i)&0x01 ) 
				CARD_TX_SET;
			else 	
				CARD_TX_CLR;

			delay_one_etu();	//2 - 9 etu
		}
			
		if ( send_parity_bit ) 		//parity bit
			CARD_TX_SET;
		else 	
			CARD_TX_CLR;
		delay_one_etu();		//10 etu
	
		delay_one_etu();		//11 etu
		
		if ( CARD_RX ) 
		{		// send protect bit	
			delay_one_etu();  //12 etu
			
			if (send_last_byte==LAST_BYTE)
				return 0;
			if ( (protect_time==0)||(protect_time==0xff) )
				return 0;
			else
			{
				for(i=0;i<protect_time;i++)
				{
					delay_one_etu(); 	// 13 ~ (12+N) etu
				}
				return 0;
			}
		}

		delay_one_etu();	//12 etu, send err
		delay_one_etu();	//13 etu
		re_send_times++;
	}
	return PARITY2_ERR;
}
//*******************************************************

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -