📄 sci_osd.c
字号:
/*-----------------------------------------------------------------------------+| This source code has been made available to you by IBM on an AS-IS| basis. Anyone receiving this source is licensed under IBM| copyrights to use it in any way he or she deems fit, including| copying it, modifying it, compiling it, and redistributing it either| with or without modifications. No license under IBM patents or| patent applications is to be implied by the copyright license.|| Any user of this software should understand that IBM cannot provide| technical support for this software and will not be responsible for| any consequences resulting from the use of this software.|| Any person who transfers this source code or any derivative work| must include the IBM copyright notice, this paragraph, and the| preceding two paragraphs in the transferred software.|| COPYRIGHT I B M CORPORATION 2001| LICENSED MATERIAL - PROGRAM PROPERTY OF I B M+-----------------------------------------------------------------------------*//*-----------------------------------------------------------------------------+| Author: Mike Lepore, Zongwei Liu| Component: sci| File: sci_osd.c| Purpose: The OS-dependency functions of Smart Card Interface| Changes:|| Date: Author Comment:| ---------- ---------------- -----------------------------------------------| 03/22/2001 MAL Initial check-in.| 03/26/2001 Zongwei Liu Port to Linux| 09/26/2001 Zongwei Liu Port to pallas| 10/10/2001 Zongwei Liu Port to OS-Adaption layer| 12/13/2001 MAL, Zongwei Liu Added sci_osd_init() parameters to set detect | and Vcc enable active polarities | (which are board dependent).| 12/13/2001 MAL, Zongwei Liu Added EMV2000 support and made several changes | to improve PIO efficiency.| 01/11/2002 MAL, zongwei Liu Add timeout to read/write function+----------------------------------------------------------------------------*/#include "os/os-sync.h"#include "os/os-interrupt.h"#include "os/os-types.h"#include "os/drv_debug.h"#include <asm/io.h>#include <linux/sched.h>#include "sci_osd.h"#include "sci_atom.h"#include "sci_osi.h"extern SCI_CONTROL_BLOCK sci_cb[SCI_NUMBER_OF_CONTROLLERS];ULONG sci_driver_init;SCI_DRV_MODES sci_drv_modes;static DECLARE_WAIT_QUEUE_HEAD(_SCI_WAIT_Q_0);static DECLARE_WAIT_QUEUE_HEAD(_SCI_WAIT_Q_1);static wait_queue_head_t *sci_wait_q[2];static void sci_osd_irq_handler(UINT uIrq, void *v);/****************************************************************************** Function: sci_osd_init**** Purpose: Initialize the Smart Card interface controller(s) and driver** and enter deac state.**** Parameters: detect_polarity: active polarity of the card detect signal** 0: active low - detect line is low when card is inserted** 1: active high - detect line is high when card is inserted** vcc_polarity: active polarity of the Vcc enable signal** 0: active low - Vcc enable is low to apply power to card** 1: active high - Vcc enable is high to apply power to card**** Returns: SCI_ERROR_OK: if successful** SCI_ERROR_KERNEL_FAIL: if interrupt handler install fails or** reader demon task creation fails****************************************************************************/SCI_ERROR sci_osd_init(ULONG detect_polarity, ULONG vcc_polarity){ SCI_ERROR rc = SCI_ERROR_OK; ULONG sci_id; ULONG sci_interrupt_masks[] = { SCI_INTERRUPT_MASK_0, SCI_INTERRUPT_MASK_1 }; ULONG sci_interrupt_levels[] = { SCI_INTERRUPT_LEVEL_0, SCI_INTERRUPT_LEVEL_1 }; ULONG sci_base_addresses[] = { SCI_BASE_ADDRESS_0, SCI_BASE_ADDRESS_1 }; PDEBUG("enter\n"); if(((detect_polarity != ACTIVE_LOW) && (detect_polarity != ACTIVE_HIGH)) || ((vcc_polarity != ACTIVE_LOW) && (vcc_polarity != ACTIVE_HIGH))) { rc = SCI_ERROR_PARAMETER_OUT_OF_RANGE; } if((sci_driver_init == 0) && (rc == SCI_ERROR_OK)) { /* configure the chip internal connection register */ sci_atom_set_chip_connection(); /* initialize globals driver mode */ sci_drv_modes.detect_polarity = detect_polarity; sci_drv_modes.vcc_polarity = vcc_polarity; sci_drv_modes.emv_supported = sci_atom_emv_check(); /* initialize the wait queue */ sci_wait_q[0] = &(_SCI_WAIT_Q_0); sci_wait_q[1] = &(_SCI_WAIT_Q_1); /* initialize global device structure for each smart card controller */ for(sci_id=0; sci_id<SCI_NUMBER_OF_CONTROLLERS; sci_id++) { /* initialize control block values */ sci_cb[sci_id].sci_interrupt_mask = sci_interrupt_masks [sci_id]; sci_cb[sci_id].sci_interrupt_level = sci_interrupt_levels[sci_id]; sci_cb[sci_id].sci_base_address = (ULONG) ioremap(sci_base_addresses[sci_id], SCI_IO_SIZE); /* assign the register addresses */ sci_atom_assign_reg_address(sci_id); sci_cb[sci_id].state = SCI_STATE_INIT; sci_cb[sci_id].driver_inuse = 0; sci_cb[sci_id].atr_status = SCI_WITHOUT_ATR; sci_cb[sci_id].waiting = 0; sci_cb[sci_id].sci_modes.emv2000 = 0; sci_cb[sci_id].sci_modes.dma = 0; sci_cb[sci_id].sci_modes.man_act = 0; //sci_cb[sci_id].sci_modes.rw_mode = SCI_SYNC | SCI_DATA_ANY; sci_cb[sci_id].sci_modes.rw_mode = SCI_SYNC; sci_cb[sci_id].bytes_expected = -1; /* initialize registers */ sci_atom_reg_init(sci_id); if(os_install_irq(sci_cb[sci_id].sci_interrupt_level, IRQ_LEVEL_TRIG | IRQ_POSITIVE_TRIG, sci_osd_irq_handler, NULL) == 0) { sci_driver_init = 1; rc = sci_osd_deactivate(sci_id); } else { PDEBUG("unable to request interrupt %d\n", (UINT) sci_cb[sci_id].sci_interrupt_level); rc = SCI_ERROR_KERNEL_FAIL; } } } if(rc != SCI_ERROR_OK) { PDEBUG("error\n"); } PDEBUG("exit\n"); return(rc);}/****************************************************************************** Function: scd_osd_uninit**** Purpose: Uninitialize the Smart Card interface controllers and driver** and enter deac state.****************************************************************************/void sci_osd_uninit (void){ ULONG sci_id; PDEBUG("enter\n"); for (sci_id = 0; sci_id < SCI_NUMBER_OF_CONTROLLERS; sci_id++) { sci_osd_deactivate(sci_id); /* free the IRQ */ os_disable_irq(sci_cb[sci_id].sci_interrupt_level); os_uninstall_irq(sci_cb[sci_id].sci_interrupt_level); /* unmap IO */ iounmap((void *) sci_cb[sci_id].sci_base_address); } PDEBUG("exit\n");}/****************************************************************************** Function: sci_osd_irq_handler**** Purpose: Smart Card Interface interrupt handler****************************************************************************/static void sci_osd_irq_handler (UINT uIrq, void *v){ ULONG state = 0; ULONG sci_id; USHORT isr; INT bytes_left; if(uIrq==sci_cb[0].sci_interrupt_level) { sci_id = 0; } else if(uIrq==sci_cb[1].sci_interrupt_level) { sci_id = 1; } else { sci_id = 2; } if(sci_id < 2) { state = os_enter_critical_section(); isr = sci_atom_get_interrupt_status(sci_id); if(isr != 0) { /* check for card being inserted or removed */ if((isr & CDI) == CDI) { if(sci_cb[sci_id].waiting == 1) { sci_cb[sci_id].waiting = 0; wake_up_interruptible(sci_wait_q[sci_id]); //os_release_mutex(sci_cb[sci_id].mutex); sci_cb[sci_id].rx_complete = 1; } sci_cb[sci_id].atr_status = SCI_WITHOUT_ATR; sci_cb[sci_id].state = SCI_STATE_DEAC; sci_atom_clear_interrupt_status(sci_id, isr); } else { switch(sci_cb[sci_id].state) { case SCI_STATE_RX: if((isr & TSI) == TSI) { sci_cb[sci_id].error = SCI_ERROR_TS_CHARACTER_INVALID; sci_cb[sci_id].rx_complete = 1; sci_atom_clear_interrupt_status(sci_id, TSI); } if((isr & RFI) == RFI) { if(sci_cb[sci_id].first_rx == 1) { /* we have received some data */ sci_cb[sci_id].error = SCI_ERROR_AWT_TIMEOUT; } else { /* no data received */ sci_cb[sci_id].error = SCI_ERROR_NO_ATR; } sci_cb[sci_id].rx_complete = 1; sci_atom_clear_interrupt_status(sci_id, RFI); } if((isr & FRXI) == FRXI) { sci_cb[sci_id].first_rx = 1; sci_atom_clear_interrupt_status(sci_id, FRXI); } if((isr & BOI) == BOI) { sci_cb[sci_id].error = SCI_ERROR_RX_OVERFLOW_FAIL; sci_cb[sci_id].rx_complete = 1; sci_atom_clear_interrupt_status(sci_id, BOI); } if((isr & PARI) == PARI) { sci_cb[sci_id].error = SCI_ERROR_PARITY_FAIL; sci_cb[sci_id].rx_complete = 1; sci_atom_clear_interrupt_status(sci_id, PARI); } if(((isr & RFTHI) == RFTHI) || ((isr & REI) == REI)) { /* in either case, read any pending data */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -