📄 ph8550_sc.c
字号:
/**************************************************************************** * * Copyright (c) 2007 - 2009 AERO-SPACE INFO Corp. All rights reserved. * ****************************************************************************/ /**************************************************************************** * * FILENAME * Ph8550_sc.c * * VERSION * 1.0 * * DESCRIPTION * Smart Card driver supported by AeroInfo for PNX8550 SmartCart Uar1. * * FUNCTIONS * all functions, if they has return value, return 0 if they success, others failed. * ( see below for detail ) * * HISTORY * 2007/03/01 Ver 1.0 Created by MengFanJie * * REMARK * None *************************************************************************/#include "Ph8550_sc.h"static unsigned int reset_ss = 0;static SmartCard_Dev smartcard_dev;static unsigned char* p_atr; static sc_parameter para;static unsigned char PPS_R[6]; static unsigned char APDU_CMD[MAX_BUF_LEN];static unsigned char APDU_RESULT[MAX_BUF_LEN];static unsigned int APDU_CMD_NUM = 0;static unsigned int APDU_RESULT_MUN = 0;static unsigned char AtrOrWr_flag = 0;void __inline sc_InitReader(void){ UCR1 = 0x80; // set RIU bit of UCR1 to one FCR = 0x100; // TOC = 0x01; // set TOR1 as counter for rstin, TOR2 and TOR3 linked as one timer TOR1 = 121; // set couter is 121 ETU in order to set rstin as high after vcc is high TOR2 = 0x80; TOR3 = 0x25; // set the TOR3-TOR2 as a timer , the delay is 9600 etu return ; } static int Sc_Rawsccksetting(void){ PDR = 12; CCR = 0x05; // set ac2:ac0 as '100' , so clk_card = core_clk/16. return 0;}static int Sc_DeactivateCard(void){ UCR2 &= (~0x80); // reset rstin bit UCR2 &= (~0x20); // reset start bit return 0;} static int Sc_ActivateCard(void){ sc_InitReader(); Sc_Rawsccksetting(); //set the raw clock; if(MSR & 0x10) // there is a card in card-socked smartcard_dev.exist = 1; else smartcard_dev.exist = 0; reset_ss = 0; UCR1 |= 0x03; // set the ss bit before ATR UCR2 |= 0x20; // set the start bit as high TOC = 0x09; // set the toc1 work in the mode of software triggered with start bit on i/o return 0;}static int sc_RawRead(char *buf, unsigned int *count){ int tc_num = 0; if(!smartcard_dev.exist) // in the state of Deactivate mode return SC_ERROR_RW_NOCARD; for(tc_num = 0; tc_num < *count; tc_num++) { TOC = 0x81; // start to count the timer3 for delay of data while(!(USR&0x01) || (USR&0x80)) { if(USR&0x80) { SCIF_INT_CLEAR = 0x01; RER = 0x400; return SC_ERROR_RW_OUTTIME; } } buf[tc_num] = URR; TOC = 0x01; // end to count the timer3 CRE |= 0x01; RER = 0x08; } if(USR & 0x08) // parity error happend { *count = tc_num; RER = 0x40; #ifdef DEBUG printk(KERN_INFO"pe-r\n"); #endif return SC_ERROR_RW_PE; } if(USR & 0x04) // ovr error happend { *count = tc_num; RER = 0x20; return SC_ERROR_RW_OVR; } *count = tc_num; return 0;} /*int sc_read(struct file *filp, char *buf, size_t count, loff_t *f_pos){ unsigned int k_count = count; AtrOrWr_flag = 1; if(smartcard_dev.state) return -1; if(k_count == 0) return -2; if( k_count > MAX_BUF_LEN) k_count = MAX_BUF_LEN-1; if((smartcard_dev.errno = sc_RawRead(read_local_buf, &k_count))!= 0) return -3; if(copy_to_user((void *)buf, (void *)read_local_buf, k_count)) return -4; *f_pos += k_count;// AtrOrWr_flag = 0; return k_count;}*/static int sc_RawWrite(unsigned char *buf, size_t *count){ int tc_num = 0; if(!smartcard_dev.exist) // in the state of Deactivate mode return SC_ERROR_RW_NOCARD; UCR1 |= 0x08; //set the transmit mode //wait for the chance to write the char for(tc_num = 0; tc_num < *count; tc_num++) { TOC = 0x81; // start to count the timer3 for delay of data while(!(USR&0x01) || (USR&0x80)) { if(USR&0x80) { SCIF_INT_CLEAR = 0x01; RER = 0x400; UCR1 &= (~0x08); //set the receive mod return SC_ERROR_RW_OUTTIME; } } //set the transmit mode, is important for warm-reset UTR = buf[tc_num]; TOC = 0x01; } while(!(USR&0x01)) ; if(USR & 0x08) // parity error happend { *count = tc_num; RER = 0x40; #ifdef DEBUG printk(KERN_INFO"AZ\n"); #endif UCR1 &= (~0x08); //set the receive mod return SC_ERROR_RW_PE; } if(USR & 0x04) // ovr error happend { *count = tc_num; RER = 0x20; #ifdef DEBUG printk(KERN_INFO"AAZ\n"); #endif UCR1 &= (~0x08); //set the receive mod return SC_ERROR_RW_OVR; } *count = tc_num; UCR1 &= (~0x08); //set the receive mod return 0;} /*int sc_write(struct file *filp, const char *buf, size_t count, loff_t *f_pos){ unsigned int k_count = 0; AtrOrWr_flag = 1; k_count = count; if(smartcard_dev.state) return -1; if(count == 0) return -2; if( count > MAX_BUF_LEN) count = MAX_BUF_LEN; if(copy_from_user(write_local_buf, buf, k_count)) return -3; if((smartcard_dev.errno = sc_RawWrite(write_local_buf, &k_count))!= 0) return -4; *f_pos += k_count; return k_count;} */static int sc_InsertOrRemove(void){ if((MSR & 0x18) == 0x18) { printk(KERN_INFO"card insert\n"); SCIF_INT_ENABLE = 0x0cff; smartcard_dev.atr_len = 0; p_atr = smartcard_dev.atr_buffer; Sc_ActivateCard(); } else { AtrOrWr_flag = 0; smartcard_dev.exist = 0; printk(KERN_INFO"card outside\n"); smartcard_dev.exist = 0; // the card is removed Sc_DeactivateCard(); } SCIF_INT_CLEAR = 0x400; // clear OCH interrupt RER = 0x2000; return 0;}static int sc_RstinToHigh(void){ UCR2 |= 0x80; // set the rstin as high; #ifdef DEBUG printk(KERN_INFO"TOR1\n"); #endif SCIF_INT_CLEAR = 0x20; // clear TO1 interrupt RER = 0x100; // reset TO1 bit return 0;}static int sc_TOR3Interrupt(void){ SCIF_INT_CLEAR = 0x80; // clear TO3 interrupt #ifdef DEBUG printk(KERN_INFO"TOR3\n"); #endif return 0;}static int sc_TOR2Interrupt(void){ SCIF_INT_CLEAR = 0x40; // clear TOR2 interrupt RER = 0x200; #ifdef DEBUG printk(KERN_INFO"TOR2\n"); #endif return 0;}static int sc_OVRInterrupt(void){ SCIF_INT_CLEAR = 0x04; #ifdef DEBUG printk(KERN_INFO"OVR\n"); #endif return 0;}static int sc_ReceiveATR(void){ *p_atr = URR; p_atr++; smartcard_dev.atr_len++; if(!reset_ss) { UCR1 &= 0xfffffffd; //reset ss bit reset_ss = 1; } SCIF_INT_CLEAR = 0x01; CRE |= 0x01; RER = 0x08; return 0;}static int sc_DMADone(void){ SCIF_INT_CLEAR = 0x800; RER = 0x8000; return 0;}static int sc_EA_Interrupt(void){ SCIF_INT_CLEAR = 0x10; RER = 0x80; #ifdef DEBUG printk(KERN_INFO"EA\n"); #endif return 0;}static int sc_FER_Interrupt(void){ SCIF_INT_CLEAR = 0x02; RER = 0x10; #ifdef DEBUG printk(KERN_INFO"FER\n"); #endif return 0;}static int sc_ParityError(void){ SCIF_INT_CLEAR = 0x08; #ifdef DEBUG printk(KERN_INFO"PE\n"); #endif return 0;}static int sc_DMAABORT_Interrupt(void){ SCIF_INT_CLEAR = 0x100; RER = 0x800; #ifdef DEBUG printk(KERN_INFO"DMAABORT\n"); #endif return 0;}static int sc_DMAERROR_Interrupt(void){ SCIF_INT_CLEAR = 0x200; RER = 0x1000; #ifdef DEBUG printk(KERN_INFO"DMAERROR\n"); #endif return 0;}static int warm_reset(void){ UCR2 &= (~0x80); // reset the reset sc_InitReader(); Sc_Rawsccksetting(); //set the raw clock; UCR1 |= 0x03; // set the ss bit before ATR UCR1 &= (~0x08); //set the receive mod AtrOrWr_flag = 0; smartcard_dev.atr_len = 0; p_atr = smartcard_dev.atr_buffer; reset_ss = 0; SCIF_INT_ENABLE = 0x0cff; TOC = 0x09; // set the toc1 work in the mode of software triggered with start bit on i/o return 0;}irqreturn_t sc_Interrupt(int irq, void * dev_id, struct pt_regs *regs){ unsigned int status = SCIF_INT_STATUS; if(status & 0x01) { if(!AtrOrWr_flag) sc_ReceiveATR(); else SCIF_INT_CLEAR = 0x01; return 0; } else if(status & 0x02) { sc_FER_Interrupt(); return 0; } else if(status & 0x04) { sc_OVRInterrupt(); return 0; } else if(status & 0x08) { sc_ParityError(); return 0; } else if(status & 0x10) { sc_EA_Interrupt(); return 0; } else if(status & 0x20) { sc_RstinToHigh(); return 0; } else if(status & 0x40) { sc_TOR2Interrupt(); return 0; } else if(status & 0x80) { sc_TOR3Interrupt(); return 0; } else if(status & 0x100) { sc_DMAABORT_Interrupt(); return 0; } else if(status & 0x200) { sc_DMAERROR_Interrupt(); return 0; } else if(status & 0x400) { // BOF or OCH happens in MSR sc_InsertOrRemove(); return 0; } else if(status & 0x800) { sc_DMADone(); return 0; } return 0;}static int sc_open(struct inode *inode, struct file *filp){ unsigned char irq_result = 255; if(smartcard_dev.openflag) /* one card slot, one open */ return -1; else smartcard_dev.openflag = 1; try_module_get(THIS_MODULE); irq_result = request_irq(SMARTCARD_IRQ_NO, &sc_Interrupt,SA_INTERRUPT, "smcard", NULL); //disable_irq(SMARTCARD_IRQ_NO); //enable_irq(SMARTCARD_IRQ_NO); SCIF_INT_ENABLE = 0x0cff; #ifdef DEBUG printk(KERN_INFO"irq_result = %d\n",irq_result); #endif smartcard_dev.atr_len = 0; p_atr = smartcard_dev.atr_buffer; if(MSR & 0x10) // there is a card in card-socked Sc_ActivateCard(); printk(KERN_INFO"card open!\n"); return 0;}static int sc_release(struct inode *inode, struct file *flip){ AtrOrWr_flag = 0; if(smartcard_dev.openflag) /* no card in slot, close */ smartcard_dev.openflag = 0; else return -1; SCIF_INT_ENABLE = 0x0; free_irq(SMARTCARD_IRQ_NO, NULL); module_put(THIS_MODULE); Sc_DeactivateCard(); printk(KERN_INFO"card close!\n"); return 0;}static int sc_SetDivClock(unsigned char ac){ unsigned char ccr_val = 0; ccr_val = CCR; CCR = (ccr_val & 0xf8)+ ac; smartcard_dev.clock = 54*1024/supported_div_Hz[ac].multiple; return 0;}static int sc_SetBaudRate(int fi, int di){ int i; int find_baudrate = 0; /* check error is done already */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -