summaryrefslogtreecommitdiffstats
path: root/src/target
diff options
context:
space:
mode:
authorIngo Albrecht <prom@berlin.ccc.de>2010-07-15 21:41:29 +0200
committerIngo Albrecht <prom@berlin.ccc.de>2010-07-15 21:41:29 +0200
commit1c8c9b8cfdf7cf6e160d0baee6e89bcb8782c25b (patch)
tree6422a3d31b4080dc3e28517c73810290bdf89657 /src/target
parenta806bb015abe4ea539dfb3200f7233db0b6c7cce (diff)
firmware: sim controller driver by dexter
Diffstat (limited to 'src/target')
-rw-r--r--src/target/firmware/Makefile2
-rwxr-xr-xsrc/target/firmware/apps/simtest/main.c325
-rw-r--r--src/target/firmware/calypso/Makefile2
-rwxr-xr-xsrc/target/firmware/calypso/sim.c740
-rwxr-xr-xsrc/target/firmware/include/calypso/sim.h191
5 files changed, 1258 insertions, 2 deletions
diff --git a/src/target/firmware/Makefile b/src/target/firmware/Makefile
index ca0a13c1..a78d5227 100644
--- a/src/target/firmware/Makefile
+++ b/src/target/firmware/Makefile
@@ -25,7 +25,7 @@ ramload_LDS=board/common/compal_ramload.lds
osmoload_LDS=board/common/compal_osmoload.lds
# List of all applications (add yours here!)
-APPLICATIONS=hello_world compal_dump compal_dsp_dump layer1 loader
+APPLICATIONS=hello_world compal_dump compal_dsp_dump layer1 loader simtest
# Things that go in all applications
ANY_APP_OBJS+=$(START:.S=.o) $(ABB_OBJS) $(RF_OBJS) $(DISPLAY_OBJS) $(FLASH_OBJS)
diff --git a/src/target/firmware/apps/simtest/main.c b/src/target/firmware/apps/simtest/main.c
new file mode 100755
index 00000000..00775111
--- /dev/null
+++ b/src/target/firmware/apps/simtest/main.c
@@ -0,0 +1,325 @@
+/* main program of Free Software for Calypso Phone */
+
+/* (C) 2010 by Harald Welte <laforge@gnumonks.org>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <debug.h>
+#include <memory.h>
+#include <rffe.h>
+#include <keypad.h>
+#include <board.h>
+#include <abb/twl3025.h>
+#include <display.h>
+#include <rf/trf6151.h>
+#include <calypso/clock.h>
+#include <calypso/tpu.h>
+#include <calypso/tsp.h>
+#include <calypso/dsp.h>
+#include <calypso/irq.h>
+#include <calypso/misc.h>
+#include <comm/sercomm.h>
+#include <comm/timer.h>
+
+
+#include <calypso/sim.h>
+
+
+#define DEBUG
+
+/* Dump bytes in hex on the console */
+static void myHexdump(uint8_t *data, int len)
+{
+ int i;
+
+ for(i=0;i<len;i++)
+ printf("%x ",data[i]);
+
+ printf("(%i bytes)\n", len);
+
+ return;
+}
+
+/* SIM instructions
+ All instructions a standard sim card must feature: */
+#define SIM_CLASS 0xA0 /* Class that contains the following instructions */
+#define SIM_SELECT 0xA4 /* Select a file on the card */
+#define SIM_STATUS 0xF2 /* Get the status of the currently selected file */
+#define SIM_READ_BINARY 0xB0 /* Read file in binary mode */
+#define SIM_UPDATE_BINARY 0xD6 /* Write file in binary mode */
+#define SIM_READ_RECORD 0xB2 /* Read record of a record based file */
+#define SIM_UPDATE_RECORD 0xDC /* Write record of a record based file */
+#define SIM_SEEK 0xA2 /* Seek in a record based file */
+#define SIM_INCREASE 0x32 /* Increase a record in a record based file */
+#define SIM_VERIFY_CHV 0x20 /* Authenicate with card (enter pin) */
+#define SIM_CHANGE_CHV 0x24 /* Change pin */
+#define SIM_DISABLE_CHV 0x26 /* Disable pin so that no authentication is needed anymore */
+#define SIM_ENABLE_CHV 0x28 /* Enable pin, authentication is now needed again */
+#define SIM_UNBLOCK_CHV 0x2C /* Unblock pin when it is blocked by entering a wrong pin three times */
+#define SIM_INVALIDATE 0x04 /* Invalidate the current elementry file (file in a subdirectory) */
+#define SIM_REHABILITATE 0x44 /* Rehabilitate the current elementry file (file in a subdirectory) */
+#define SIM_RUN_GSM_ALGORITHM 0x88 /* Run the GSM A3 authentication algorithm in the card */
+#define SIM_SLEEP 0xFA /* Sleep command (only used in Phase 1 GSM) */
+#define SIM_GET_RESPONSE 0xC0 /* Get the response of a command from the card */
+
+/* File identifiers (filenames)
+ The file identifiers are the standartized file identfiers mentiond in the
+ GSM-11-11 specification. */
+#define SIM_MF 0x3F00
+#define SIM_EF_ICCID 0x2FE2
+#define SIM_DF_TELECOM 0x7F10
+#define SIM_EF_ADN 0x6F3A
+#define SIM_EF_FDN 0x6F3B
+#define SIM_EF_SMS 0x6F3C
+#define SIM_EF_CCP 0x6F3D
+#define SIM_EF_MSISDN 0x6F40
+#define SIM_EF_SMSP 0x6F42
+#define SIM_EF_SMSS 0x6F43
+#define SIM_EF_LND 0x6F44
+#define SIM_EF_EXT1 0x6F4A
+#define SIM_EF_EXT2 0x6F4B
+#define SIM_DF_GSM 0x7F20
+#define SIM_EF_LP 0x6F05
+#define SIM_EF_IMSI 0x6F07
+#define SIM_EF_KC 0x6F20
+#define SIM_EF_PLMNsel 0x6F30
+#define SIM_EF_HPLMN 0x6F31
+#define SIM_EF_ACMmax 0x6F37
+#define SIM_EF_SST 0x6F38
+#define SIM_EF_ACM 0x6F39
+#define SIM_EF_GID1 0x6F3E
+#define SIM_EF_GID2 0x6F3F
+#define SIM_EF_PUCT 0x6F41
+#define SIM_EF_CBMI 0x6F45
+#define SIM_EF_SPN 0x6F46
+#define SIM_EF_BCCH 0x6F74
+#define SIM_EF_ACC 0x6F78
+#define SIM_EF_FPLMN 0x6F7B
+#define SIM_EF_LOCI 0x6F7E
+#define SIM_EF_AD 0x6FAD
+#define SIM_EF_PHASE 0x6FAE
+
+/* Select a file on the card */
+uint16_t sim_select(uint16_t fid)
+{
+ uint8_t txBuffer[2];
+ uint8_t status_word[2];
+
+ txBuffer[1] = (uint8_t) fid;
+ txBuffer[0] = (uint8_t) (fid >> 8);
+
+ if(calypso_sim_transceive(SIM_CLASS, SIM_SELECT, 0x00, 0x00, 0x02,txBuffer,status_word, SIM_APDU_PUT) != 0)
+ return 0xFFFF;
+
+ return (status_word[0] << 8) | status_word[1];
+}
+
+/* Get the status of the currently selected file */
+uint16_t sim_status(void)
+{
+ uint8_t status_word[2];
+
+ if(calypso_sim_transceive(SIM_CLASS, SIM_STATUS, 0x00, 0x00, 0x00,0,status_word, SIM_APDU_PUT) != 0)
+ return 0xFFFF;
+
+ return (status_word[0] << 8) | status_word[1];
+}
+
+/* Read file in binary mode */
+uint16_t sim_readbinary(uint8_t offset_high, uint8_t offset_low, uint8_t length, uint8_t *data)
+{
+ uint8_t status_word[2];
+ if(calypso_sim_transceive(SIM_CLASS, SIM_READ_BINARY, offset_high, offset_low, length, data ,status_word, SIM_APDU_GET) != 0)
+ return 0xFFFF;
+
+ return (status_word[0] << 8) | status_word[1];
+}
+
+
+
+
+
+/* FIXME: We need proper calibrated delay loops at some point! */
+void delay_us(unsigned int us)
+{
+ volatile unsigned int i;
+
+ for (i= 0; i < us*4; i++) { i; }
+}
+
+void delay_ms(unsigned int ms)
+{
+ volatile unsigned int i;
+ for (i= 0; i < ms*1300; i++) { i; }
+}
+
+
+
+
+/* Execute my (dexter's) personal test */
+void do_sim_test(void)
+{
+ uint8_t testBuffer[20];
+ uint8_t testtxBuffer[20];
+
+ uint8_t testDataBody[257];
+ uint8_t testStatusWord[2];
+ int recivedChars;
+ int i;
+
+ uint8_t atr[20];
+ uint8_t atrLength = 0;
+
+ memset(atr,0,sizeof(atr));
+
+
+
+ uint8_t buffer[20];
+
+
+ memset(testtxBuffer,0,sizeof(testtxBuffer));
+
+ puts("----------------SIMTEST----8<-----------------\n");
+
+ /* Initalize Sim-Controller driver */
+ puts("Initalizing driver:\n");
+ calypso_sim_init();
+
+ /* Power up sim and display ATR */
+ puts("Power up simcard:\n");
+ memset(atr,0,sizeof(atr));
+ atrLength = calypso_sim_powerup(atr);
+ myHexdump(atr,atrLength);
+
+ /* Reset sim and display ATR */
+ puts("Reset simcard:\n");
+ memset(atr,0,sizeof(atr));
+ atrLength = calypso_sim_reset(atr);
+ myHexdump(atr,atrLength);
+
+
+
+ testDataBody[0] = 0x3F;
+ testDataBody[1] = 0x00;
+ calypso_sim_transceive(0xA0, 0xA4, 0x00, 0x00, 0x02, testDataBody,0, SIM_APDU_PUT);
+ calypso_sim_transceive(0xA0, 0xC0, 0x00, 0x00, 0x0f, testDataBody,0, SIM_APDU_GET);
+ myHexdump(testDataBody,0x0F);
+
+ puts("Test Phase 1: Testing bare sim commands...\n");
+
+ puts(" * Testing SELECT: Selecting MF\n");
+ printf(" ==> Status word: %x\n", sim_select(SIM_MF));
+
+ puts(" * Testing SELECT: Selecting DF_GSM\n");
+ printf(" ==> Status word: %x\n", sim_select(SIM_DF_GSM));
+
+ puts(" * Testing SELECT: Selecting EF_IMSI\n");
+ printf(" ==> Status word: %x\n", sim_select(SIM_EF_IMSI));
+
+ puts(" * Testing STATUS:\n");
+ printf(" ==> Status word: %x\n", sim_status());
+
+ memset(buffer,0,sizeof(buffer));
+ puts(" * Testing READ BINARY:\n");
+ printf(" ==> Status word: %x\n", sim_readbinary(0,0,9,buffer));
+ printf(" Data: ");
+ myHexdump(buffer,9);
+
+ delay_ms(5000);
+
+ calypso_sim_powerdown();
+
+ puts("------------END SIMTEST----8<-----------------\n");
+}
+
+
+
+
+/* Main Program */
+const char *hr = "======================================================================\n";
+
+void key_handler(enum key_codes code, enum key_states state);
+
+static void *console_rx_cb(uint8_t dlci, struct msgb *msg)
+{
+ if (dlci != SC_DLCI_CONSOLE) {
+ printf("Message for unknown DLCI %u\n", dlci);
+ return;
+ }
+
+ printf("Message on console DLCI: '%s'\n", msg->data);
+ msgb_free(msg);
+}
+
+int main(void)
+{
+ puts("\n\nSIM-Test from " __FILE__ " program code\n");
+ puts(hr);
+ /* Dump device identification */
+ dump_dev_id();
+ puts(hr);
+
+ /* Dump clock config before PLL set */
+ calypso_clk_dump();
+ puts(hr);
+
+ keypad_set_handler(&key_handler);
+
+ /* Dump clock config aftee PLL set */
+ calypso_clk_dump();
+ puts(hr);
+
+ /* Dump all memory */
+ //dump_mem();
+#if 0
+ /* Dump Bootloader */
+ memdump_range((void *)0x00000000, 0x2000);
+ puts(hr);
+#endif
+
+ display_set_attr(DISP_ATTR_INVERT);
+ display_puts("SIM-TEST");
+
+ sercomm_register_rx_cb(SC_DLCI_CONSOLE, console_rx_cb);
+
+ do_sim_test();
+
+ /* beyond this point we only react to interrupts */
+ puts("entering interrupt loop\n");
+ while (1) {
+ }
+
+ twl3025_power_off();
+ while (1) {}
+}
+
+void key_handler(enum key_codes code, enum key_states state)
+{
+ if (state != PRESSED)
+ return;
+
+ switch (code) {
+ default:
+ break;
+ }
+}
diff --git a/src/target/firmware/calypso/Makefile b/src/target/firmware/calypso/Makefile
index ff62cb8a..8fcad7b6 100644
--- a/src/target/firmware/calypso/Makefile
+++ b/src/target/firmware/calypso/Makefile
@@ -1,4 +1,4 @@
LIBRARIES+=calypso
calypso_DIR=calypso
-calypso_SRCS=arm.c clock.c delay.c dma.c dsp.c du.c i2c.c irq.c rtc.c spi.c tpu.c tsp.c keypad.c misc.c timer.c backlight.c uart.c uwire.c
+calypso_SRCS=arm.c clock.c delay.c dma.c dsp.c du.c i2c.c irq.c rtc.c sim.c spi.c tpu.c tsp.c keypad.c misc.c timer.c backlight.c uart.c uwire.c
diff --git a/src/target/firmware/calypso/sim.c b/src/target/firmware/calypso/sim.c
new file mode 100755
index 00000000..610f968f
--- /dev/null
+++ b/src/target/firmware/calypso/sim.c
@@ -0,0 +1,740 @@
+/* Driver for Simcard Controller inside TI Calypso/Iota */
+
+/* (C) 2010 by Philipp Fabian Benedikt Maier <philipp-maier@runningserver.com>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <stdint.h>
+#include <stdio.h>
+
+#include <debug.h>
+#include <memory.h>
+#include <abb/twl3025.h>
+#include <calypso/sim.h>
+#include <calypso/irq.h>
+
+static int sim_rx_character_count = 0; /* How many bytes have been received by calypso_sim_receive() */
+static int sim_tx_character_count = 0; /* How many bytes have been transmitted by calypso_sim_transmit() */
+static int sim_tx_character_length = 0; /* How many bytes have to be transmitted by calypso_sim_transmit() */
+static uint8_t *rx_buffer = 0; /* RX-Buffer that is issued by calypso_sim_receive() */
+static uint8_t *tx_buffer = 0; /* TX-Buffer that is issued by calypso_sim_transmit() */
+volatile static int rxDoneFlag = 0; /* Used for rx syncronization instead of a semaphore in calypso_sim_receive() */
+volatile static int txDoneFlag = 0; /* Used for rx syncronization instead of a semaphore in calypso_sim_transmit() */
+
+/* Display Register dump */
+void calypso_sim_regdump(void)
+{
+#if (SIM_DEBUG == 1)
+ unsigned int regVal;
+
+
+ puts("\n\n\n");
+ puts("====================== CALYPSO SIM REGISTER DUMP =====================\n");
+ puts("Reg_sim_cmd register (R/W) - FFFE:0000\n");
+
+
+ regVal = readw(REG_SIM_CMD);
+ printf(" |-REG_SIM_CMD = %04x\n", readw(REG_SIM_CMD));
+
+ if(regVal & REG_SIM_CMD_CMDCARDRST)
+ puts(" | |-REG_SIM_CMD_CMDCARDRST = 1 ==> SIM card reset sequence enabled.\n");
+ else
+ puts(" | |-REG_SIM_CMD_CMDCARDRST = 0 ==> SIM card reset sequence disabled.\n");
+ delay_ms(SIM_DEBUG_OUTPUTDELAY);
+
+ if(regVal & REG_SIM_CMD_CMDIFRST)
+ puts(" | |-REG_SIM_CMD_CMDIFRST = 1\n");
+ else
+ puts(" | |-REG_SIM_CMD_CMDIFRST = 0\n");
+ delay_ms(SIM_DEBUG_OUTPUTDELAY);
+
+ if(regVal & REG_SIM_CMD_CMDSTOP)
+ puts(" | |-REG_SIM_CMD_CMDSTOP = 1\n");
+ else
+ puts(" | |-REG_SIM_CMD_CMDSTOP = 0\n");
+ delay_ms(SIM_DEBUG_OUTPUTDELAY);
+
+ if(regVal & REG_SIM_CMD_CMDSTART)
+ puts(" | |-REG_SIM_CMD_CMDSTART = 1 ==> SIM card start procedure active.\n");
+ else
+ puts(" | |-REG_SIM_CMD_CMDSTART = 0\n");
+ delay_ms(SIM_DEBUG_OUTPUTDELAY);
+
+ if(regVal & REG_SIM_CMD_CMDSTART)
+ puts(" | |-REG_SIM_CMD_MODULE_CLK_EN = 1 ==> Clock of the module enabled.\n");
+ else
+ puts(" | |-REG_SIM_CMD_MODULE_CLK_EN = 0 ==> Clock of the module disabled.\n");
+ delay_ms(SIM_DEBUG_OUTPUTDELAY);
+
+ regVal = readw(REG_SIM_STAT);
+ printf(" |-REG_SIM_STAT = %04x\n", regVal);
+ delay_ms(SIM_DEBUG_OUTPUTDELAY);
+
+ if(regVal & REG_SIM_STAT_STATNOCARD)
+ puts(" | |-REG_SIM_STAT_STATNOCARD = 1 ==> No card!\n");
+ else
+ puts(" | |-REG_SIM_STAT_STATNOCARD = 0 ==> Card detected!\n");
+ delay_ms(SIM_DEBUG_OUTPUTDELAY);
+
+ if(regVal & REG_SIM_STAT_STATTXPAR)
+ puts(" | |-REG_SIM_STAT_STATTXPAR = 1 ==> Parity ok!\n");
+ else
+ puts(" | |-REG_SIM_STAT_STATTXPAR = 0 ==> Parity error!\n");
+ delay_ms(SIM_DEBUG_OUTPUTDELAY);
+
+ if(regVal & REG_SIM_STAT_STATFIFOFULL)
+ puts(" | |-REG_SIM_STAT_STATFIFOFULL = 1 ==> Fifo full!\n");
+ else
+ puts(" | |-REG_SIM_STAT_STATFIFOFULL = 0\n");
+ delay_ms(SIM_DEBUG_OUTPUTDELAY);
+
+ if(regVal & REG_SIM_STAT_STATFIFOEMPTY)
+ puts(" | |-REG_SIM_STAT_STATFIFOEMPTY = 1 ==> Fifo empty!\n");
+ else
+ puts(" | |-REG_SIM_STAT_STATFIFOEMPTY = 0\n");
+ delay_ms(SIM_DEBUG_OUTPUTDELAY);
+
+ regVal = readw(REG_SIM_CONF1);
+ printf(" |-REG_SIM_CONF1 = %04x\n", regVal);
+ delay_ms(SIM_DEBUG_OUTPUTDELAY);
+
+ if(regVal & REG_SIM_CONF1_CONFCHKPAR)
+ puts(" | |-REG_SIM_CONF1_CONFCHKPAR = 1 ==> Parity check on reception enabled.\n");
+ else
+ puts(" | |-REG_SIM_CONF1_CONFCHKPAR = 0 ==> Parity check on reception disabled.\n");
+ delay_ms(SIM_DEBUG_OUTPUTDELAY);
+
+ if(regVal & REG_SIM_CONF1_CONFCODCONV)
+ puts(" | |-REG_SIM_CONF1_CONFCODCONV = 1 ==> Coding convention is inverse.\n");
+ else
+ puts(" | |-REG_SIM_CONF1_CONFCODCONV = 0 ==> Coding convention is direct (normal).\n");
+ delay_ms(SIM_DEBUG_OUTPUTDELAY);
+
+ if(regVal & REG_SIM_CONF1_CONFTXRX)
+ puts(" | |-REG_SIM_CONF1_CONFTXRX = 1 ==> SIO line direction is in transmit mode.\n");
+ else
+ puts(" | |-REG_SIM_CONF1_CONFTXRX = 0 ==> SIO line direction is in receive mode.\n");
+ delay_ms(SIM_DEBUG_OUTPUTDELAY);
+
+ if(regVal & REG_SIM_CONF1_CONFSCLKEN)
+ puts(" | |-REG_SIM_CONF1_CONFSCLKEN = 1 ==> SIM clock in normal mode.\n");
+ else
+ puts(" | |-REG_SIM_CONF1_CONFSCLKEN = 0 ==> SIM clock in standby mode.\n");
+ delay_ms(SIM_DEBUG_OUTPUTDELAY);
+
+ if(regVal & REG_SIM_CONF1_reserved)
+ puts(" | |-REG_SIM_CONF1_reserved = 1 ==> ETU period is 4*1/Fsclk.\n");
+ else
+ puts(" | |-REG_SIM_CONF1_reserved = 0 ==> ETU period is CONFETUPERIOD.\n");
+ delay_ms(SIM_DEBUG_OUTPUTDELAY);
+
+ if(regVal & REG_SIM_CONF1_CONFSCLKDIV)
+ puts(" | |-REG_SIM_CONF1_CONFSCLKDIV = 1 ==> SIM clock frequency is 13/8 Mhz.\n");
+ else
+ puts(" | |-REG_SIM_CONF1_CONFSCLKDIV = 0 ==> SIM clock frequency is 13/4 Mhz.\n");
+ delay_ms(SIM_DEBUG_OUTPUTDELAY);
+
+ if(regVal & REG_SIM_CONF1_CONFSCLKLEV)
+ puts(" | |-REG_SIM_CONF1_CONFSCLKLEV = 1 ==> SIM clock idle level is high.\n");
+ else
+ puts(" | |-REG_SIM_CONF1_CONFSCLKLEV = 0 ==> SIM clock idle level is low.\n");
+ delay_ms(SIM_DEBUG_OUTPUTDELAY);
+
+ if(regVal & REG_SIM_CONF1_CONFETUPERIOD)
+ puts(" | |-REG_SIM_CONF1_CONFETUPERIOD = 1 ==> ETU period is 512/8*1/Fsclk.\n");
+ else
+ puts(" | |-REG_SIM_CONF1_CONFETUPERIOD = 0 ==> ETU period is 372/8*1/Fsclk.\n");
+ delay_ms(SIM_DEBUG_OUTPUTDELAY);
+
+ if(regVal & REG_SIM_CONF1_CONFBYPASS)
+ puts(" | |-REG_SIM_CONF1_CONFBYPASS = 1 ==> Hardware timers and start and stop sequences are bypassed.\n");
+ else
+ puts(" | |-REG_SIM_CONF1_CONFBYPASS = 0 ==> Hardware timers and start and stop sequences are normal.\n");
+ delay_ms(SIM_DEBUG_OUTPUTDELAY);
+
+ if(regVal & REG_SIM_CONF1_CONFSVCCLEV)
+ puts(" | |-REG_SIM_CONF1_CONFSVCCLEV = 1 ==> SVCC Level is high (Only valid when CONFBYPASS = 1).\n");
+ else
+ puts(" | |-REG_SIM_CONF1_CONFSVCCLEV = 0 ==> SVCC Level is low (Only valid when CONFBYPASS = 1).\n");
+ delay_ms(SIM_DEBUG_OUTPUTDELAY);
+
+ if(regVal & REG_SIM_CONF1_CONFSRSTLEV)
+ puts(" | |-REG_SIM_CONF1_CONFSRSTLEV = 1 ==> SRST Level is high (Only valid when CONFBYPASS = 1).\n");
+ else
+ puts(" | |-REG_SIM_CONF1_CONFSRSTLEV = 0 ==> SRST Level is low (Only valid when CONFBYPASS = 1).\n");
+ delay_ms(SIM_DEBUG_OUTPUTDELAY);
+
+ printf(" | |-REG_SIM_CONF1_CONFTRIG = 0x%x (FIFO trigger level)\n",(regVal >> REG_SIM_CONF1_CONFTRIG) & REG_SIM_CONF1_CONFTRIG_MASK);
+ delay_ms(SIM_DEBUG_OUTPUTDELAY);
+
+ if(regVal & REG_SIM_CONF1_CONFSIOLOW)
+ puts(" | |-REG_SIM_CONF1_CONFSIOLOW = 1 ==> I/O is forced to low.\n");
+ else
+ puts(" | |-REG_SIM_CONF1_CONFSIOLOW = 0\n");
+ delay_ms(SIM_DEBUG_OUTPUTDELAY);
+
+ regVal = readw(REG_SIM_CONF2);
+ printf(" |-REG_SIM_CONF2 = %04x\n", regVal);
+ printf(" | |-REG_SIM_CONF2_CONFTFSIM = 0x%x (time delay for filtering of SIM_CD)\n",(regVal >> REG_SIM_CONF2_CONFTFSIM) & REG_SIM_CONF2_CONFTFSIM_MASK);
+ printf(" | |-REG_SIM_CONF2_CONFTDSIM = 0x%x (time delay for contact activation/deactivation)\n",(regVal >> REG_SIM_CONF2_CONFTDSIM) & REG_SIM_CONF2_CONFTDSIM_MASK);
+ printf(" | |-REG_SIM_CONF2_CONFWAITI = 0x%x (CONFWAITI overflow wait time between two received chars)\n",(regVal >> REG_SIM_CONF2_CONFWAITI) & REG_SIM_CONF2_CONFWAITI_MASK);
+ delay_ms(SIM_DEBUG_OUTPUTDELAY);
+
+ regVal = readw(REG_SIM_IT);
+ printf(" |-REG_SIM_IT = %04x\n", regVal);
+ delay_ms(SIM_DEBUG_OUTPUTDELAY);
+
+ if(regVal & REG_SIM_IT_SIM_NATR)
+ puts(" | |-REG_SIM_IT_SIM_NATR = 1 ==> No answer to reset!\n");
+ else
+ puts(" | |-REG_SIM_IT_SIM_NATR = 0 ==> On read access to REG_SIM_IT.\n");
+ delay_ms(SIM_DEBUG_OUTPUTDELAY);
+
+ if(regVal & REG_SIM_IT_SIM_WT)
+ puts(" | |-REG_SIM_IT_SIM_WT = 1 ==> Character underflow!\n");
+ else
+ puts(" | |-REG_SIM_IT_SIM_WT = 0 ==> On read access to REG_SIM_IT.\n");
+ delay_ms(SIM_DEBUG_OUTPUTDELAY);
+
+ if(regVal & REG_SIM_IT_SIM_OV)
+ puts(" | |-REG_SIM_IT_SIM_OV = 1 ==> Receive overflow!\n");
+ else
+ puts(" | |-REG_SIM_IT_SIM_OV = 0 ==> On read access to REG_SIM_IT.\n");
+ delay_ms(SIM_DEBUG_OUTPUTDELAY);
+
+ if(regVal & REG_SIM_IT_SIM_TX)
+ puts(" | |-REG_SIM_IT_SIM_TX = 1 ==> Waiting for character to transmit...\n");
+ else
+ {
+ puts(" | |-REG_SIM_IT_SIM_TX = 0 ==> On write access to REG_SIM_DTX or on switching\n");
+ puts(" | | from transmit to receive mode (CONFTXRX bit)\n");
+ }
+ delay_ms(SIM_DEBUG_OUTPUTDELAY);
+
+ if(regVal & REG_SIM_IT_SIM_RX)
+ puts(" | |-REG_SIM_IT_SIM_RX = 1 ==> Waiting characters to be read...\n");
+ else
+ puts(" | |-REG_SIM_IT_SIM_RX = 0 ==> On read access to REG_SIM_DRX.\n");
+ delay_ms(SIM_DEBUG_OUTPUTDELAY);
+
+ regVal = readw(REG_SIM_DRX);
+ printf(" |-REG_SIM_DRX = %04x\n", regVal);
+ delay_ms(SIM_DEBUG_OUTPUTDELAY);
+
+ printf(" | |-REG_SIM_DRX_SIM_DRX = 0x%x (next data byte in FIFO available for reading)\n",(regVal >> REG_SIM_DRX_SIM_DRX) & REG_SIM_DRX_SIM_DRX_MASK);
+ delay_ms(SIM_DEBUG_OUTPUTDELAY);
+
+ if(regVal & REG_SIM_DRX_STATRXPAR)
+ puts(" | |-REG_SIM_DRX_STATRXPAR = 1 ==> Parity Ok.\n");
+ else
+ puts(" | |-REG_SIM_DRX_STATRXPAR = 0 ==> Parity error!\n");
+ delay_ms(SIM_DEBUG_OUTPUTDELAY);
+
+ regVal = readw(REG_SIM_DTX);
+ printf(" |-REG_SIM_DTX = %02x (next data byte to be transmitted)\n", regVal);
+ delay_ms(SIM_DEBUG_OUTPUTDELAY);
+
+ regVal = readw(REG_SIM_MASKIT);
+ printf(" |-REG_SIM_MASKIT = %04x\n", regVal);
+ delay_ms(SIM_DEBUG_OUTPUTDELAY);
+
+ if(regVal & REG_SIM_MASKIT_MASK_SIM_NATR)
+ puts(" | |-REG_SIM_MASKIT_MASK_SIM_NATR = 1 ==> No-answer-to-reset interrupt is masked.\n");
+ else
+ puts(" | |-REG_SIM_MASKIT_MASK_SIM_NATR = 0 ==> No-answer-to-reset interrupt is unmasked.\n");
+ delay_ms(SIM_DEBUG_OUTPUTDELAY);
+
+ if(regVal & REG_SIM_MASKIT_MASK_SIM_WT)
+ puts(" | |-REG_SIM_MASKIT_MASK_SIM_WT = 1 ==> Character wait-time overflow interrupt is masked.\n");
+ else
+ puts(" | |-REG_SIM_MASKIT_MASK_SIM_WT = 0 ==> Character wait-time overflow interrupt is unmasked.\n");
+ delay_ms(SIM_DEBUG_OUTPUTDELAY);
+
+ if(regVal & REG_SIM_MASKIT_MASK_SIM_OV)
+ puts(" | |-REG_SIM_MASKIT_MASK_SIM_OV = 1 ==> Receive overflow interrupt is masked.\n");
+ else
+ puts(" | |-REG_SIM_MASKIT_MASK_SIM_OV = 0 ==> Receive overflow interrupt is unmasked.\n");
+ delay_ms(SIM_DEBUG_OUTPUTDELAY);
+
+ if(regVal & REG_SIM_MASKIT_MASK_SIM_TX)
+ puts(" | |-REG_SIM_MASKIT_MASK_SIM_TX = 1 ==> Waiting characters to be transmit interrupt is masked.\n");
+ else
+ puts(" | |-REG_SIM_MASKIT_MASK_SIM_TX = 0 ==> Waiting characters to be transmit interrupt is unmasked.\n");
+ delay_ms(SIM_DEBUG_OUTPUTDELAY);
+
+ if(regVal & REG_SIM_MASKIT_MASK_SIM_RX)
+ puts(" | |-REG_SIM_MASKIT_MASK_SIM_RX = 1 ==> Waiting characters to be read interrupt is masked.\n");
+ else
+ puts(" | |-REG_SIM_MASKIT_MASK_SIM_RX = 0 ==> Waiting characters to be read interrupt is unmasked.\n");
+ delay_ms(SIM_DEBUG_OUTPUTDELAY);
+
+ if(regVal & REG_SIM_MASKIT_MASK_SIM_CD)
+ puts(" | |-REG_SIM_MASKIT_MASK_SIM_CD = 1 ==> SIM card insertion/extraction interrupt is masked.\n");
+ else
+ puts(" | |-REG_SIM_MASKIT_MASK_SIM_CD = 0 ==> SIM card insertion/extraction interrupt is unmasked.\n");
+ delay_ms(SIM_DEBUG_OUTPUTDELAY);
+
+ regVal = REG_SIM_IT_CD;
+ printf(" |-REG_SIM_IT_CD = %04x\n", regVal);
+ if(regVal & REG_SIM_IT_CD_IT_CD)
+ puts(" |-REG_SIM_IT_CD_IT_CD = 1 ==> SIM card insertion/extraction interrupt is masked.\n");
+ else
+ puts(" |-REG_SIM_IT_CD_IT_CD = 0 ==> SIM card insertion/extraction interrupt is unmasked.\n");
+ delay_ms(SIM_DEBUG_OUTPUTDELAY);
+#endif
+ return;
+}
+
+/* Apply power to the simcard (use nullpointer to ignore atr) */
+int calypso_sim_powerup(uint8_t *atr)
+{
+ /* Enable level shifters and voltage regulator */
+ twl3025_reg_write(VRPCSIM, VRPCSIM_SIMLEN | VRPCSIM_RSIMEN | VRPCSIM_SIMSEL);
+#if (SIM_DEBUG == 1)
+ puts(" * Power enabled!\n");
+#endif
+ delay_ms(SIM_OPERATION_DELAY);
+
+ /* Enable clock */
+ writew(REG_SIM_CMD_MODULE_CLK_EN | REG_SIM_CMD_CMDSTART, REG_SIM_CMD);
+#if (SIM_DEBUG == 1)
+ puts(" * Clock enabled!\n");
+#endif
+ delay_ms(SIM_OPERATION_DELAY);
+
+ /* Release reset */
+ writew(readw(REG_SIM_CONF1) | REG_SIM_CONF1_CONFBYPASS | REG_SIM_CONF1_CONFSRSTLEV | REG_SIM_CONF1_CONFSVCCLEV, REG_SIM_CONF1);
+#if (SIM_DEBUG == 1)
+ puts(" * Reset released!\n");
+#endif
+
+ /* Catch ATR */
+ if(atr != 0)
+ return calypso_sim_receive(atr);
+ else
+ return 0;
+}
+
+
+/* Powerdown simcard */
+void calypso_sim_powerdown(void)
+{
+ writew(readw(REG_SIM_CONF1) & ~REG_SIM_CONF1_CONFBYPASS, REG_SIM_CONF1);
+#if (SIM_DEBUG == 1)
+ puts(" * Reset pulled down!\n");
+#endif
+ delay_ms(SIM_OPERATION_DELAY);
+
+ writew(REG_SIM_CMD_MODULE_CLK_EN | REG_SIM_CMD_CMDSTOP, REG_SIM_CMD);
+#if (SIM_DEBUG == 1)
+ puts(" * Clock disabled!\n");
+#endif
+ delay_ms(SIM_OPERATION_DELAY);
+
+ writew(0, REG_SIM_CMD);
+#if (SIM_DEBUG == 1)
+ puts(" * Module disabled!\n");
+#endif
+ delay_ms(SIM_OPERATION_DELAY);
+
+ /* Disable level shifters and voltage regulator */
+ twl3025_reg_write(VRPCSIM, 0);
+#if (SIM_DEBUG == 1)
+ puts(" * Power disabled!\n");
+#endif
+ delay_ms(SIM_OPERATION_DELAY);
+
+ return;
+}
+
+/* reset the simcard (see note 1) */
+int calypso_sim_reset(uint8_t *atr)
+{
+
+ /* Pull reset down */
+ writew(readw(REG_SIM_CONF1) & ~REG_SIM_CONF1_CONFSRSTLEV , REG_SIM_CONF1);
+#if (SIM_DEBUG == 1)
+ puts(" * Reset pulled down!\n");
+#endif
+
+ delay_ms(SIM_OPERATION_DELAY);
+
+ /* Pull reset down */
+ writew(readw(REG_SIM_CONF1) | REG_SIM_CONF1_CONFSRSTLEV , REG_SIM_CONF1);
+#if (SIM_DEBUG == 1)
+ puts(" * Reset released!\n");
+#endif
+
+ /* Catch ATR */
+ if(atr != 0)
+ return calypso_sim_receive(atr);
+ else
+ return 0;
+}
+
+/* Receive raw data through the sim interface */
+int calypso_sim_receive(uint8_t *data)
+{
+ /* Prepare buffers and flags */
+ rx_buffer = data;
+ sim_rx_character_count = 0;
+ rxDoneFlag = 0;
+
+ /* Switch I/O direction to input */
+ writew(readw(REG_SIM_CONF1) & ~REG_SIM_CONF1_CONFTXRX, REG_SIM_CONF1);
+
+ /* Unmask the interrupts that are needed to perform this action */
+ writew(~(REG_SIM_MASKIT_MASK_SIM_RX | REG_SIM_MASKIT_MASK_SIM_WT), REG_SIM_MASKIT);
+
+ /* Wait till rxDoneFlag is set */
+ while(rxDoneFlag == 0);
+
+ /* Disable all interrupt driven functions by masking all interrupts */
+ writew(0xFF, REG_SIM_MASKIT);
+
+ /* Hand back the number of bytes received */
+ return sim_rx_character_count;
+
+ return;
+}
+
+/* Transmit raw data through the sim interface */
+int calypso_sim_transmit(uint8_t *data, int length)
+{
+ /* Prepare buffers and flags */
+ tx_buffer = data;
+ sim_tx_character_count = 0;
+ txDoneFlag = 0;
+ sim_tx_character_length = length;
+
+ /* Switch I/O direction to output */
+ writew(readw(REG_SIM_CONF1) | REG_SIM_CONF1_CONFTXRX, REG_SIM_CONF1);
+
+ /* Unmask the interrupts that are needed to perform this action */
+ writew(~(REG_SIM_MASKIT_MASK_SIM_TX), REG_SIM_MASKIT);
+
+ /* Transmit the first byte manually to start the interrupt cascade */
+ writew(*tx_buffer,REG_SIM_DTX);
+ tx_buffer++;
+ sim_tx_character_count++;
+
+ /* Wait till rxDoneFlag is set */
+ while(txDoneFlag == 0);
+
+ /* Disable all interrupt driven functions by masking all interrupts */
+ writew(0xFF, REG_SIM_MASKIT);
+
+ return 0;
+}
+
+
+/* IRQ-Handler for simcard interface */
+void sim_irq_handler(enum irq_nr irq)
+{
+ int regVal = readw(REG_SIM_IT);
+
+
+ /* Display interrupt information */
+#if (SIM_DEBUG == 1)
+ puts("SIM-ISR: Interrupt caught: ");
+#endif
+ if(regVal & REG_SIM_IT_SIM_NATR)
+ {
+#if (SIM_DEBUG == 1)
+ puts(" No answer to reset!\n");
+#endif
+ }
+
+ /* Used by: calypso_sim_receive() to determine when the transmission is over */
+ if(regVal & REG_SIM_IT_SIM_WT)
+ {
+#if (SIM_DEBUG == 1)
+ puts(" Character underflow!\n");
+#endif
+ rxDoneFlag = 1;
+ }
+
+ if(regVal & REG_SIM_IT_SIM_OV)
+ {
+#if (SIM_DEBUG == 1)
+ puts(" Receive overflow!\n");
+#endif
+ }
+
+ /* Used by: calypso_sim_transmit() to transmit the data */
+ if(regVal & REG_SIM_IT_SIM_TX)
+ {
+#if (SIM_DEBUG == 1)
+ puts(" Waiting for character to transmit...\n");
+#endif
+ if(sim_tx_character_count >= sim_tx_character_length)
+ txDoneFlag = 1;
+ else
+ {
+ writew(*tx_buffer,REG_SIM_DTX);
+ tx_buffer++;
+ sim_tx_character_count++;
+ }
+ }
+
+ /* Used by: calypso_sim_receive() to receive the incoming data */
+ if(regVal & REG_SIM_IT_SIM_RX)
+ {
+#if (SIM_DEBUG == 1)
+ puts(" Waiting characters to be read...\n");
+#endif
+ /* Increment character count - this is what calypso_sim_receive() hands back */
+ sim_rx_character_count++;
+
+ /* Read byte from rx-fifo and write it to the issued buffer */
+ *rx_buffer = (uint8_t) (readw(REG_SIM_DRX) & 0xFF);
+ rx_buffer++;
+ }
+}
+
+/* Transceive T0 Apdu to sim acording to GSM 11.11 Page 34 */
+int calypso_sim_transceive(uint8_t cla, /* Class (in GSM context mostly 0xA0 */
+ uint8_t ins, /* Instruction */
+ uint8_t p1, /* First parameter */
+ uint8_t p2, /* Second parameter */
+ uint8_t p3le, /* Length of the data that should be transceived */
+ uint8_t *data, /* Data payload */
+ uint8_t *status, /* Status word (2 byte array, see note 1) */
+ uint8_t mode) /* Mode of operation: 1=GET, 0=PUT */
+
+ /* Note 1: You can use a null-pointer (0) if you are not interested in
+ the status word */
+{
+ uint8_t transmissionBuffer[256];
+ uint8_t numberOfReceivedBytes;
+
+#if (SIM_DEBUG == 1)
+ printf("SIM-T0: Transceiving APDU-Header: (%02x %02x %02x %02x %02x)\n",cla,ins,p1,p2,p3le);
+#endif
+
+ /* Transmit APDU header */
+ memset(transmissionBuffer,0,sizeof(transmissionBuffer));
+ transmissionBuffer[0] = cla;
+ transmissionBuffer[1] = ins;
+ transmissionBuffer[2] = p1;
+ transmissionBuffer[3] = p2;
+ transmissionBuffer[4] = p3le;
+ calypso_sim_transmit(transmissionBuffer,5);
+
+ /* Case 1: No input, No Output */
+ if(p3le == 0)
+ {
+#if (SIM_DEBUG == 1)
+ puts("SIM-T0: Case 1: No input, No Output (See also GSM 11.11 Page 34)\n");
+#endif
+ numberOfReceivedBytes = calypso_sim_receive(transmissionBuffer);
+
+ if(numberOfReceivedBytes == 2)
+ {
+#if (SIM_DEBUG == 1)
+ printf("SIM-T0: Status-word received: %02x %02x\n", transmissionBuffer[0], transmissionBuffer[1]);
+#endif
+ /* Hand back status word */
+ if(status != 0)
+ {
+ status[0] = transmissionBuffer[0];
+ status[1] = transmissionBuffer[1];
+ }
+
+ return 0;
+ }
+ else
+ {
+#if (SIM_DEBUG == 1)
+ puts("SIM-T0: T0 Protocol error -- aborting!\n");
+#endif
+ return -1;
+ }
+ }
+
+ /* Case 2: No input / Output of known length */
+ else if(mode == SIM_APDU_PUT)
+ {
+#if (SIM_DEBUG == 1)
+ puts("SIM-T0: Case 2: No input / Output of known length (See also GSM 11.11 Page 34)\n");
+#endif
+
+ numberOfReceivedBytes = calypso_sim_receive(transmissionBuffer);
+
+ /* Error situation: The card has aborted, sends no data but a status word */
+ if(numberOfReceivedBytes == 2)
+ {
+#if (SIM_DEBUG == 1)
+ printf("SIM-T0: Status-word received (ERROR): %02x %02x\n", transmissionBuffer[0], transmissionBuffer[1]);
+#endif
+ /* Hand back status word */
+ if(status != 0)
+ {
+ status[0] = transmissionBuffer[0];
+ status[1] = transmissionBuffer[1];
+ }
+
+ return 0;
+ }
+ /* Acknoledge byte received */
+ else if(numberOfReceivedBytes == 1)
+ {
+#if (SIM_DEBUG == 1)
+ printf("SIM-T0: ACK received: %02x\n", transmissionBuffer[0]);
+#endif
+ /* Check if ACK is valid */
+ if(transmissionBuffer[0] != ins)
+ {
+#if (SIM_DEBUG == 1)
+ puts("SIM-T0: T0 Protocol error: Invalid ACK byte -- aborting!\n");
+#endif
+ return -1;
+ }
+
+ /* Transmit body */
+ calypso_sim_transmit(data,p3le);
+
+ /* Receive status word */
+ numberOfReceivedBytes = calypso_sim_receive(transmissionBuffer);
+
+ /* Check status word */
+ if(numberOfReceivedBytes == 2)
+ {
+#if (SIM_DEBUG == 1)
+ printf("SIM-T0: Status-word received: %02x %02x\n", transmissionBuffer[0], transmissionBuffer[1]);
+#endif
+
+ /* Hand back status word */
+ if(status != 0)
+ {
+ status[0] = transmissionBuffer[0];
+ status[1] = transmissionBuffer[1];
+ }
+
+ return 0;
+ }
+ else
+ {
+#if (SIM_DEBUG == 1)
+ puts("SIM-T0: T0 Protocol error: Missing or invalid status word -- aborting!\n");
+#endif
+ return -1;
+ }
+ }
+ else
+ {
+#if (SIM_DEBUG == 1)
+ puts("SIM-T0: T0 Protocol error: Missing ACK byte -- aborting!\n");
+#endif
+ return -1;
+ }
+ }
+
+ /* Case 4: Input / No output */
+ else if(mode == SIM_APDU_GET)
+ {
+#if (SIM_DEBUG == 1)
+ puts("SIM-T0: Case 4: Input / No output (See also GSM 11.11 Page 34)\n");
+#endif
+
+ numberOfReceivedBytes = calypso_sim_receive(data);
+
+ /* Error situation: The card has aborted, sends no data but a status word */
+ if(numberOfReceivedBytes == 2)
+ {
+
+#if (SIM_DEBUG == 1)
+ printf("SIM-T0: Status-word received (ERROR): %02x %02x\n", data[0], data[1]);
+#endif
+ /* Hand back status word */
+ if(status != 0)
+ {
+ status[0] = data[0];
+ status[1] = data[1];
+ }
+
+ return 0;
+ }
+
+ /* Data correctly received */
+ else if(numberOfReceivedBytes == p3le + 1 + 2)
+ {
+#if (SIM_DEBUG == 1)
+ printf("SIM-T0: ACK received: %02x\n", data[0]);
+#endif
+ /* Check if ACK is valid */
+ if(data[0] != ins)
+ {
+#if (SIM_DEBUG == 1)
+ puts("SIM-T0: T0 Protocol error: Invalid ACK byte -- aborting!\n");
+#endif
+ return -1;
+ }
+
+#if (SIM_DEBUG == 1)
+ printf("SIM-T0: Status-word received: %02x %02x\n", data[p3le + 1], data[p3le + 2]);
+#endif
+ /* Hand back status word */
+ if(status != 0)
+ {
+ status[0] = data[p3le + 1];
+ status[1] = data[p3le + 2];
+ }
+
+ /* Move data one position left to cut away the ACK-Byte */
+ memcpy(data,data+1,p3le);
+
+ return 0;
+ }
+ else
+ {
+#if (SIM_DEBUG == 1)
+ puts("SIM-T0: T0 Protocol error: Incorrect or missing answer -- aborting!\n");
+#endif
+ return -1;
+ }
+ }
+
+ /* Should not happen, if it happens then the programmer has submitted invalid parameters! */
+ else
+ {
+#if (SIM_DEBUG == 1)
+ puts("SIM-T0: T0 Protocol error: Invalid case (program bug!) -- aborting!\n");
+#endif
+ }
+
+ /* Note: The other cases are not implemented because they are already covered
+ by the CASE 1,2 and 4. */
+
+ return 0;
+}
+
+
+/* Initialize simcard interface */
+void calypso_sim_init(void)
+{
+ /* Register IRQ handler and turn interrupts on */
+#if (SIM_DEBUG == 1)
+ puts("SIM: Registering interrupt handler for simcard-interface\n");
+#endif
+ irq_register_handler(IRQ_SIMCARD, &sim_irq_handler);
+ irq_config(IRQ_SIMCARD, 0, 0, 0xff);
+ irq_enable(IRQ_SIMCARD);
+}
+
diff --git a/src/target/firmware/include/calypso/sim.h b/src/target/firmware/include/calypso/sim.h
new file mode 100755
index 00000000..b2a21642
--- /dev/null
+++ b/src/target/firmware/include/calypso/sim.h
@@ -0,0 +1,191 @@
+/* Driver for Simcard Controller inside TI Calypso/Iota */
+
+/* (C) 2010 by Philipp Fabian Benedikt Maier <philipp-maier@runningserver.com>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#ifndef _CALYPSO_SIM_H
+#define _CALYPSO_SIM_H
+
+/* == REGISTERS IN THE IOTA BASEBAND == */
+
+/* SimCard Control Register */
+#define VRPCSIM_SIMLEN (1 << 3) /* Enable level shifter */
+#define VRPCSIM_SIMRSU (1 << 2) /* voltage regulator output status */
+#define VRPCSIM_RSIMEN (1 << 1) /* Voltage regulator enable */
+#define VRPCSIM_SIMSEL 1 /* Select the VRSIM output voltage 1=2.9V, 0=1.8V */
+
+
+
+/* == REGISTERS IN THE CALYPSO CPU == */
+
+/* Reg_sim_cmd register (R/W) - FFFE:0000 */
+#define REG_SIM_CMD 0xFFFE0000 /* register address */
+#define REG_SIM_CMD_CMDCARDRST 1 /* SIM card reset sequence */
+#define REG_SIM_CMD_CMDIFRST (1 << 1) /* SIM interface software reset */
+#define REG_SIM_CMD_CMDSTOP (1 << 2) /* SIM card stop procedure */
+#define REG_SIM_CMD_CMDSTART (1 << 3) /* SIM card start procedure */
+#define REG_SIM_CMD_MODULE_CLK_EN (1 << 4) /* Clock of the module */
+
+/* Reg_sim_stat register (R) - FFFE:0002 */
+#define REG_SIM_STAT 0xFFFE0002 /* register address */
+#define REG_SIM_STAT_STATNOCARD 1 /* card presence, 0 = no card, 1 = card detected */
+#define REG_SIM_STAT_STATTXPAR (1 << 1) /* parity check for transmit byte, 0 = parity error, 1 = parity OK */
+#define REG_SIM_STAT_STATFIFOFULL (1 << 2) /* FIFO content, 1 = FIFO full */
+#define REG_SIM_STAT_STATFIFOEMPTY (1 << 3) /* FIFO content, 1 = FIFO empty */
+
+/* Reg_sim_conf1 register (R/W) - FFFE:0004 */
+#define REG_SIM_CONF1 0xFFFE0004 /* register address */
+#define REG_SIM_CONF1_CONFCHKPAR 1 /* enable parity check on reception */
+#define REG_SIM_CONF1_CONFCODCONV (1 << 1) /* coding convention: (TS character) */
+#define REG_SIM_CONF1_CONFTXRX (1 << 2) /* SIO line direction */
+#define REG_SIM_CONF1_CONFSCLKEN (1 << 3) /* SIM clock */
+#define REG_SIM_CONF1_reserved (1 << 4) /* ETU period */
+#define REG_SIM_CONF1_CONFSCLKDIV (1 << 5) /* SIM clock frequency */
+#define REG_SIM_CONF1_CONFSCLKLEV (1 << 6) /* SIM clock idle level */
+#define REG_SIM_CONF1_CONFETUPERIOD (1 << 7) /* ETU period */
+#define REG_SIM_CONF1_CONFBYPASS (1 << 8) /* bypass hardware timers and start and stop sequences */
+#define REG_SIM_CONF1_CONFSVCCLEV (1 << 9) /* logic level on SVCC (used if CONFBYPASS = 1) */
+#define REG_SIM_CONF1_CONFSRSTLEV (1 << 10) /* logic level on SRST (used if CONFBYPASS = 1) */
+#define REG_SIM_CONF1_CONFTRIG 11 /* FIFO trigger level */
+#define REG_SIM_CONF1_CONFTRIG_0 (1 << 11)
+#define REG_SIM_CONF1_CONFTRIG_1 (1 << 12)
+#define REG_SIM_CONF1_CONFTRIG_2 (1 << 13)
+#define REG_SIM_CONF1_CONFTRIG_3 (1 << 14)
+#define REG_SIM_CONF1_CONFTRIG_MASK 0xF
+#define REG_SIM_CONF1_CONFSIOLOW (1 << 15) /* SIO - 0 = no effect, 1 = force low */
+
+/* Reg_sim_conf2 register (R/W) - FFFE:0006 */
+#define REG_SIM_CONF2 0xFFFE0006 /* register address */
+#define REG_SIM_CONF2_CONFTFSIM 0 /* time delay for filtering of SIM_CD */
+#define REG_SIM_CONF2_CONFTFSIM_0 1 /* time-unit = 1024 * TCK13M (card extraction) */
+#define REG_SIM_CONF2_CONFTFSIM_1 (1 << 1) /* or */
+#define REG_SIM_CONF2_CONFTFSIM_2 (1 << 2) /* time-unit = 8192 * TCK13M (card insertion) */
+#define REG_SIM_CONF2_CONFTFSIM_3 (1 << 3)
+#define REG_SIM_CONF2_CONFTFSIM_MASK 0xF
+#define REG_SIM_CONF2_CONFTDSIM 4 /* time delay for contact activation/deactivation */
+#define REG_SIM_CONF2_CONFTDSIM_0 (1 << 4) /* time unit = 8 * TCKETU */
+#define REG_SIM_CONF2_CONFTDSIM_1 (1 << 5)
+#define REG_SIM_CONF2_CONFTDSIM_2 (1 << 6)
+#define REG_SIM_CONF2_CONFTDSIM_3 (1 << 7)
+#define REG_SIM_CONF2_CONFTDSIM_MASK 0xF
+#define REG_SIM_CONF2_CONFWAITI 8 /* CONFWAITI overflow wait time between two received */
+#define REG_SIM_CONF2_CONFWAITI_0 (1 << 8) /* character time unit = 960 *D * TCKETU */
+#define REG_SIM_CONF2_CONFWAITI_1 (1 << 9) /* with D parameter = 1 or 8 (TA1 character) */
+#define REG_SIM_CONF2_CONFWAITI_2 (1 << 10)
+#define REG_SIM_CONF2_CONFWAITI_3 (1 << 11)
+#define REG_SIM_CONF2_CONFWAITI_4 (1 << 12)
+#define REG_SIM_CONF2_CONFWAITI_5 (1 << 13)
+#define REG_SIM_CONF2_CONFWAITI_6 (1 << 14)
+#define REG_SIM_CONF2_CONFWAITI_7 (1 << 15)
+#define REG_SIM_CONF2_CONFWAITI_MASK 0xFF
+
+/* Reg_sim_it register (R) - FFFE:0008 */
+#define REG_SIM_IT 0xFFFE0008 /* register address */
+#define REG_SIM_IT_SIM_NATR 1 /* 0 = on read access to REG_SIM_IT, 1 = no answer to reset */
+#define REG_SIM_IT_SIM_WT (1 << 1) /* 0 = on read access to REG_SIM_IT, 1 = character underflow */
+#define REG_SIM_IT_SIM_OV (1 << 2) /* 0 = on read access to REG_SIM_IT, 1 = receive overflow */
+#define REG_SIM_IT_SIM_TX (1 << 3) /* 0 = on write access to REG_SIM_DTX or */
+ /* on switching from transmit to receive, mode (CONFTXRX bit) */
+ /* 1 = waiting for character to transmit */
+#define REG_SIM_IT_SIM_RX (1 << 4) /* 0 = on read access to REG_SIM_DRX */
+ /* 1 = waiting characters to be read */
+
+/* Reg_sim_drx register (R) - FFFE:000A */
+#define REG_SIM_DRX 0xFFFE000A /* register address */
+#define REG_SIM_DRX_SIM_DRX 0 /* next data byte in FIFO available for reading */
+#define REG_SIM_DRX_SIM_DRX_0 1
+#define REG_SIM_DRX_SIM_DRX_1 (1 << 1)
+#define REG_SIM_DRX_SIM_DRX_2 (1 << 2)
+#define REG_SIM_DRX_SIM_DRX_3 (1 << 3)
+#define REG_SIM_DRX_SIM_DRX_4 (1 << 4)
+#define REG_SIM_DRX_SIM_DRX_5 (1 << 5)
+#define REG_SIM_DRX_SIM_DRX_6 (1 << 6)
+#define REG_SIM_DRX_SIM_DRX_7 (1 << 7)
+#define REG_SIM_DRX_SIM_DRX_MASK 0xFF
+#define REG_SIM_DRX_STATRXPAR (1 << 8) /* parity-check for received byte */
+
+/* Reg_sim_dtx register (R/W) - FFFE:000C */
+#define REG_SIM_DTX 0xFFFE000C /* register address */
+#define REG_SIM_DTX_SIM_DTX_0 /* next data byte to be transmitted */
+#define REG_SIM_DTX_SIM_DTX_1
+#define REG_SIM_DTX_SIM_DTX_2
+#define REG_SIM_DTX_SIM_DTX_3
+#define REG_SIM_DTX_SIM_DTX_4
+#define REG_SIM_DTX_SIM_DTX_5
+#define REG_SIM_DTX_SIM_DTX_6
+#define REG_SIM_DTX_SIM_DTX_7
+
+/* Reg_sim_maskit register (R/W) - FFFE:000E */
+#define REG_SIM_MASKIT 0xFFFE000E /* register address */
+#define REG_SIM_MASKIT_MASK_SIM_NATR 1 /* No-answer-to-reset interrupt */
+#define REG_SIM_MASKIT_MASK_SIM_WT (1 << 1) /* Character wait-time overflow interrupt */
+#define REG_SIM_MASKIT_MASK_SIM_OV (1 << 2) /* Receive overflow interrupt */
+#define REG_SIM_MASKIT_MASK_SIM_TX (1 << 3) /* Waiting character to transmit interrupt */
+#define REG_SIM_MASKIT_MASK_SIM_RX (1 << 4) /* Waiting characters to be read interrupt */
+#define REG_SIM_MASKIT_MASK_SIM_CD (1 << 5) /* SIM card insertion/extraction interrupt */
+
+/* Reg_sim_it_cd register (R) - FFFE:0010 */
+#define REG_SIM_IT_CD 0xFFFE0010 /* register address */
+#define REG_SIM_IT_CD_IT_CD 1 /* 0 = on read access to REG_SIM_IT_CD, */
+ /* 1 = SIM card insertion/extraction */
+
+
+#define SIM_DEBUG_OUTPUTDELAY 200 /* Output delay to minimize stress with some uart bugs */
+#define SIM_DEBUG 0 /* 0=Debug messages are off / 1=Debug messages are on */
+#define SIM_OPERATION_DELAY 100 /* Time between operations like reset, vcc apply ect... */
+
+
+void calypso_sim_regdump(void); /* Display Register dump */
+
+int calypso_sim_powerup(uint8_t *atr); /* Apply power to the simcard (see note 1) */
+int calypso_sim_reset(uint8_t *atr); /* reset the simcard (see note 1) */
+
+
+void calypso_sim_powerdown(void); /* Powerdown simcard */
+
+/* APDU transmission modes */
+#define SIM_APDU_PUT 0 /* Transmit a data body to the card */
+#define SIM_APDU_GET 1 /* Fetch data from the card eg. GET RESOPNSE */
+
+/* Transceive T0 Apdu to sim acording to GSM 11.11 Page 34 */
+int calypso_sim_transceive(uint8_t cla, /* Class (in GSM context mostly 0xA0 */
+ uint8_t ins, /* Instruction */
+ uint8_t p1, /* First parameter */
+ uint8_t p2, /* Second parameter */
+ uint8_t p3le, /* Length of the data that should be transceived */
+ uint8_t *data, /* Data payload */
+ uint8_t *status, /* Status word (2 byte array, see note 1) */
+ uint8_t mode); /* Mode of operation: 1=GET, 0=PUT */
+
+ /* Note 1: You can use a null-pointer (0) if you are not interested in
+ the status word */
+
+/* Transmission of raw data */
+int calypso_sim_receive(uint8_t *data); /* Receive raw data through the sim interface */
+int calypso_sim_transmit(uint8_t *data, int length); /* Transmit raw data through the sim interface */
+
+void calypso_sim_init(void); /* Initialize simcard interface */
+
+
+/* Known Bugs:
+ 1.) After powering down the simcard communication stops working
+*/
+
+#endif /* _CALYPSO_SIM_H */