a539cf8aaccad7839f7149deefdf506ca3c96076
[osmocom-bb.git] / src / target / firmware / calypso / sim.c
1 /* Driver for Simcard Controller inside TI Calypso/Iota */
2
3 /* (C) 2010 by Philipp Fabian Benedikt Maier <philipp-maier@runningserver.com>
4  *
5  * All Rights Reserved
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License along
18  * with this program; if not, write to the Free Software Foundation, Inc.,
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  */
22
23 #include <stdint.h>
24 #include <stdio.h>
25
26 #include <debug.h>
27 #include <memory.h>
28 #include <abb/twl3025.h>
29 #include <calypso/sim.h>
30 #include <calypso/irq.h>
31
32 static int sim_rx_character_count = 0;  /* How many bytes have been received by calypso_sim_receive() */
33 static int sim_tx_character_count = 0;  /* How many bytes have been transmitted by calypso_sim_transmit() */
34 static int sim_tx_character_length = 0; /* How many bytes have to be transmitted by calypso_sim_transmit() */
35 static uint8_t *rx_buffer = 0;          /* RX-Buffer that is issued by calypso_sim_receive() */
36 static uint8_t *tx_buffer = 0;          /* TX-Buffer that is issued by calypso_sim_transmit() */
37 volatile static int rxDoneFlag = 0;     /* Used for rx synchronization instead of a semaphore in calypso_sim_receive() */
38 volatile static int txDoneFlag = 0;     /* Used for rx synchronization instead of a semaphore in calypso_sim_transmit() */
39
40 /* Display Register dump */
41 void calypso_sim_regdump(void)
42 {
43 #if (SIM_DEBUG == 1)
44         unsigned int regVal;
45
46
47           puts("\n\n\n");
48           puts("====================== CALYPSO SIM REGISTER DUMP =====================\n");
49           puts("Reg_sim_cmd register (R/W) - FFFE:0000\n");
50
51
52         regVal = readw(REG_SIM_CMD);
53         printf("  |-REG_SIM_CMD = %04x\n", readw(REG_SIM_CMD));
54
55         if(regVal & REG_SIM_CMD_CMDCARDRST)
56                 puts("  |  |-REG_SIM_CMD_CMDCARDRST = 1 ==> SIM card reset sequence enabled.\n");
57         else
58                 puts("  |  |-REG_SIM_CMD_CMDCARDRST = 0 ==> SIM card reset sequence disabled.\n");
59         delay_ms(SIM_DEBUG_OUTPUTDELAY);
60
61         if(regVal & REG_SIM_CMD_CMDIFRST)
62                 puts("  |  |-REG_SIM_CMD_CMDIFRST = 1\n");
63         else
64                 puts("  |  |-REG_SIM_CMD_CMDIFRST = 0\n");
65         delay_ms(SIM_DEBUG_OUTPUTDELAY);
66
67         if(regVal & REG_SIM_CMD_CMDSTOP)
68                 puts("  |  |-REG_SIM_CMD_CMDSTOP = 1\n");
69         else
70                 puts("  |  |-REG_SIM_CMD_CMDSTOP = 0\n");
71         delay_ms(SIM_DEBUG_OUTPUTDELAY);
72
73         if(regVal & REG_SIM_CMD_CMDSTART)
74                 puts("  |  |-REG_SIM_CMD_CMDSTART = 1 ==> SIM card start procedure active.\n");
75         else
76                 puts("  |  |-REG_SIM_CMD_CMDSTART = 0\n");
77         delay_ms(SIM_DEBUG_OUTPUTDELAY);
78
79         if(regVal & REG_SIM_CMD_CMDSTART)
80                 puts("  |  |-REG_SIM_CMD_MODULE_CLK_EN = 1 ==> Clock of the module enabled.\n");
81         else
82                 puts("  |  |-REG_SIM_CMD_MODULE_CLK_EN = 0 ==> Clock of the module disabled.\n");
83         delay_ms(SIM_DEBUG_OUTPUTDELAY);
84
85         regVal = readw(REG_SIM_STAT);
86         printf("  |-REG_SIM_STAT = %04x\n", regVal);
87         delay_ms(SIM_DEBUG_OUTPUTDELAY);
88
89         if(regVal & REG_SIM_STAT_STATNOCARD)
90                 puts("  |  |-REG_SIM_STAT_STATNOCARD = 1 ==> No card!\n");
91         else
92                 puts("  |  |-REG_SIM_STAT_STATNOCARD = 0 ==> Card detected!\n");
93         delay_ms(SIM_DEBUG_OUTPUTDELAY);
94
95         if(regVal & REG_SIM_STAT_STATTXPAR)
96                 puts("  |  |-REG_SIM_STAT_STATTXPAR = 1 ==> Parity ok!\n");
97         else
98                 puts("  |  |-REG_SIM_STAT_STATTXPAR = 0 ==> Parity error!\n");
99         delay_ms(SIM_DEBUG_OUTPUTDELAY);
100
101         if(regVal & REG_SIM_STAT_STATFIFOFULL)
102                 puts("  |  |-REG_SIM_STAT_STATFIFOFULL = 1 ==> Fifo full!\n");
103         else
104                 puts("  |  |-REG_SIM_STAT_STATFIFOFULL = 0\n");
105         delay_ms(SIM_DEBUG_OUTPUTDELAY);
106
107         if(regVal & REG_SIM_STAT_STATFIFOEMPTY)
108                 puts("  |  |-REG_SIM_STAT_STATFIFOEMPTY = 1 ==> Fifo empty!\n");
109         else
110                 puts("  |  |-REG_SIM_STAT_STATFIFOEMPTY = 0\n");
111         delay_ms(SIM_DEBUG_OUTPUTDELAY);
112
113         regVal = readw(REG_SIM_CONF1);
114         printf("  |-REG_SIM_CONF1 = %04x\n", regVal);
115         delay_ms(SIM_DEBUG_OUTPUTDELAY);
116
117         if(regVal & REG_SIM_CONF1_CONFCHKPAR)
118                 puts("  |  |-REG_SIM_CONF1_CONFCHKPAR = 1 ==> Parity check on reception enabled.\n");
119         else
120                 puts("  |  |-REG_SIM_CONF1_CONFCHKPAR = 0 ==> Parity check on reception disabled.\n");
121         delay_ms(SIM_DEBUG_OUTPUTDELAY);
122
123         if(regVal & REG_SIM_CONF1_CONFCODCONV)
124                 puts("  |  |-REG_SIM_CONF1_CONFCODCONV = 1 ==> Coding convention is inverse.\n");
125         else
126                 puts("  |  |-REG_SIM_CONF1_CONFCODCONV = 0 ==> Coding convention is direct (normal).\n");
127         delay_ms(SIM_DEBUG_OUTPUTDELAY);
128
129         if(regVal & REG_SIM_CONF1_CONFTXRX)
130                 puts("  |  |-REG_SIM_CONF1_CONFTXRX = 1 ==> SIO line direction is in transmit mode.\n");
131         else
132                 puts("  |  |-REG_SIM_CONF1_CONFTXRX = 0 ==> SIO line direction is in receive mode.\n");
133         delay_ms(SIM_DEBUG_OUTPUTDELAY);
134
135         if(regVal & REG_SIM_CONF1_CONFSCLKEN)
136                 puts("  |  |-REG_SIM_CONF1_CONFSCLKEN = 1 ==> SIM clock in normal mode.\n");
137         else
138                 puts("  |  |-REG_SIM_CONF1_CONFSCLKEN = 0 ==> SIM clock in standby mode.\n");
139         delay_ms(SIM_DEBUG_OUTPUTDELAY);
140
141         if(regVal & REG_SIM_CONF1_reserved)
142                 puts("  |  |-REG_SIM_CONF1_reserved = 1 ==> ETU period is 4*1/Fsclk.\n");
143         else
144                 puts("  |  |-REG_SIM_CONF1_reserved = 0 ==> ETU period is CONFETUPERIOD.\n");
145         delay_ms(SIM_DEBUG_OUTPUTDELAY);
146
147         if(regVal & REG_SIM_CONF1_CONFSCLKDIV)
148                 puts("  |  |-REG_SIM_CONF1_CONFSCLKDIV = 1 ==> SIM clock frequency is 13/8 Mhz.\n");
149         else
150                 puts("  |  |-REG_SIM_CONF1_CONFSCLKDIV = 0 ==> SIM clock frequency is 13/4 Mhz.\n");
151         delay_ms(SIM_DEBUG_OUTPUTDELAY);
152     
153         if(regVal & REG_SIM_CONF1_CONFSCLKLEV)
154                 puts("  |  |-REG_SIM_CONF1_CONFSCLKLEV = 1 ==> SIM clock idle level is high.\n");
155         else
156                 puts("  |  |-REG_SIM_CONF1_CONFSCLKLEV = 0 ==> SIM clock idle level is low.\n");
157         delay_ms(SIM_DEBUG_OUTPUTDELAY);
158               
159         if(regVal & REG_SIM_CONF1_CONFETUPERIOD)
160                 puts("  |  |-REG_SIM_CONF1_CONFETUPERIOD = 1 ==> ETU period is 512/8*1/Fsclk.\n");
161         else
162                 puts("  |  |-REG_SIM_CONF1_CONFETUPERIOD = 0 ==> ETU period is 372/8*1/Fsclk.\n");
163         delay_ms(SIM_DEBUG_OUTPUTDELAY);
164         
165         if(regVal & REG_SIM_CONF1_CONFBYPASS)
166                 puts("  |  |-REG_SIM_CONF1_CONFBYPASS = 1 ==> Hardware timers and start and stop sequences are bypassed.\n");
167         else
168                 puts("  |  |-REG_SIM_CONF1_CONFBYPASS = 0 ==> Hardware timers and start and stop sequences are normal.\n");
169         delay_ms(SIM_DEBUG_OUTPUTDELAY);
170           
171         if(regVal & REG_SIM_CONF1_CONFSVCCLEV)
172                 puts("  |  |-REG_SIM_CONF1_CONFSVCCLEV = 1 ==> SVCC Level is high (Only valid when CONFBYPASS = 1).\n");
173         else
174                 puts("  |  |-REG_SIM_CONF1_CONFSVCCLEV = 0 ==> SVCC Level is low (Only valid when CONFBYPASS = 1).\n");
175         delay_ms(SIM_DEBUG_OUTPUTDELAY);
176
177         if(regVal & REG_SIM_CONF1_CONFSRSTLEV)
178                 puts("  |  |-REG_SIM_CONF1_CONFSRSTLEV = 1 ==> SRST Level is high (Only valid when CONFBYPASS = 1).\n");
179         else
180                 puts("  |  |-REG_SIM_CONF1_CONFSRSTLEV = 0 ==> SRST Level is low (Only valid when CONFBYPASS = 1).\n");
181         delay_ms(SIM_DEBUG_OUTPUTDELAY);
182
183         printf("  |  |-REG_SIM_CONF1_CONFTRIG = 0x%x (FIFO trigger level)\n",(regVal >> REG_SIM_CONF1_CONFTRIG) & REG_SIM_CONF1_CONFTRIG_MASK);
184         delay_ms(SIM_DEBUG_OUTPUTDELAY);
185
186         if(regVal & REG_SIM_CONF1_CONFSIOLOW)
187                 puts("  |  |-REG_SIM_CONF1_CONFSIOLOW = 1 ==> I/O is forced to low.\n");
188         else
189                 puts("  |  |-REG_SIM_CONF1_CONFSIOLOW = 0\n");
190         delay_ms(SIM_DEBUG_OUTPUTDELAY);
191
192         regVal = readw(REG_SIM_CONF2);
193         printf("  |-REG_SIM_CONF2 = %04x\n", regVal);
194         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);
195         printf("  |  |-REG_SIM_CONF2_CONFTDSIM = 0x%x (time delay for contact activation/deactivation)\n",(regVal >> REG_SIM_CONF2_CONFTDSIM) & REG_SIM_CONF2_CONFTDSIM_MASK);
196         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);
197         delay_ms(SIM_DEBUG_OUTPUTDELAY);
198
199         regVal = readw(REG_SIM_IT);
200         printf("  |-REG_SIM_IT = %04x\n", regVal);
201         delay_ms(SIM_DEBUG_OUTPUTDELAY);
202
203         if(regVal & REG_SIM_IT_SIM_NATR)
204                 puts("  |  |-REG_SIM_IT_SIM_NATR = 1 ==> No answer to reset!\n");
205         else
206                 puts("  |  |-REG_SIM_IT_SIM_NATR = 0 ==> On read access to REG_SIM_IT.\n");
207         delay_ms(SIM_DEBUG_OUTPUTDELAY);
208
209         if(regVal & REG_SIM_IT_SIM_WT)
210                 puts("  |  |-REG_SIM_IT_SIM_WT = 1 ==> Character underflow!\n");
211         else
212                 puts("  |  |-REG_SIM_IT_SIM_WT = 0 ==> On read access to REG_SIM_IT.\n");
213         delay_ms(SIM_DEBUG_OUTPUTDELAY);
214
215         if(regVal & REG_SIM_IT_SIM_OV)
216                 puts("  |  |-REG_SIM_IT_SIM_OV = 1 ==> Receive overflow!\n");
217         else
218                 puts("  |  |-REG_SIM_IT_SIM_OV = 0 ==> On read access to REG_SIM_IT.\n");
219         delay_ms(SIM_DEBUG_OUTPUTDELAY);
220
221         if(regVal & REG_SIM_IT_SIM_TX)
222                 puts("  |  |-REG_SIM_IT_SIM_TX = 1 ==> Waiting for character to transmit...\n");
223         else
224         {
225                 puts("  |  |-REG_SIM_IT_SIM_TX = 0 ==> On write access to REG_SIM_DTX or on switching\n");
226                 puts("  |  |                           from transmit to receive mode (CONFTXRX bit)\n");
227         }
228         delay_ms(SIM_DEBUG_OUTPUTDELAY);
229
230         if(regVal & REG_SIM_IT_SIM_RX)
231                 puts("  |  |-REG_SIM_IT_SIM_RX = 1 ==> Waiting characters to be read...\n");
232         else
233                 puts("  |  |-REG_SIM_IT_SIM_RX = 0 ==> On read access to REG_SIM_DRX.\n");
234         delay_ms(SIM_DEBUG_OUTPUTDELAY);
235
236         regVal = readw(REG_SIM_DRX);
237         printf("  |-REG_SIM_DRX = %04x\n", regVal);
238         delay_ms(SIM_DEBUG_OUTPUTDELAY);
239
240         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);
241         delay_ms(SIM_DEBUG_OUTPUTDELAY);
242
243         if(regVal & REG_SIM_DRX_STATRXPAR)
244                 puts("  |  |-REG_SIM_DRX_STATRXPAR = 1 ==> Parity Ok.\n");
245         else
246                 puts("  |  |-REG_SIM_DRX_STATRXPAR = 0 ==> Parity error!\n");
247         delay_ms(SIM_DEBUG_OUTPUTDELAY);
248
249         regVal = readw(REG_SIM_DTX);
250         printf("  |-REG_SIM_DTX = %02x (next data byte to be transmitted)\n", regVal);
251         delay_ms(SIM_DEBUG_OUTPUTDELAY);
252
253         regVal = readw(REG_SIM_MASKIT);
254         printf("  |-REG_SIM_MASKIT = %04x\n", regVal);
255         delay_ms(SIM_DEBUG_OUTPUTDELAY);
256
257         if(regVal & REG_SIM_MASKIT_MASK_SIM_NATR)
258                 puts("  |  |-REG_SIM_MASKIT_MASK_SIM_NATR = 1 ==> No-answer-to-reset interrupt is masked.\n");
259         else
260                 puts("  |  |-REG_SIM_MASKIT_MASK_SIM_NATR = 0 ==> No-answer-to-reset interrupt is unmasked.\n");
261         delay_ms(SIM_DEBUG_OUTPUTDELAY);
262
263         if(regVal & REG_SIM_MASKIT_MASK_SIM_WT)
264                 puts("  |  |-REG_SIM_MASKIT_MASK_SIM_WT = 1 ==> Character wait-time overflow interrupt is masked.\n");
265         else
266                 puts("  |  |-REG_SIM_MASKIT_MASK_SIM_WT = 0 ==> Character wait-time overflow interrupt is unmasked.\n");
267         delay_ms(SIM_DEBUG_OUTPUTDELAY);
268
269         if(regVal & REG_SIM_MASKIT_MASK_SIM_OV)
270                 puts("  |  |-REG_SIM_MASKIT_MASK_SIM_OV = 1 ==> Receive overflow interrupt is masked.\n");
271         else
272                 puts("  |  |-REG_SIM_MASKIT_MASK_SIM_OV = 0 ==> Receive overflow interrupt is unmasked.\n");
273         delay_ms(SIM_DEBUG_OUTPUTDELAY);
274
275         if(regVal & REG_SIM_MASKIT_MASK_SIM_TX)
276                 puts("  |  |-REG_SIM_MASKIT_MASK_SIM_TX = 1 ==> Waiting characters to be transmit interrupt is masked.\n");
277         else
278                 puts("  |  |-REG_SIM_MASKIT_MASK_SIM_TX = 0 ==> Waiting characters to be transmit interrupt is unmasked.\n");
279         delay_ms(SIM_DEBUG_OUTPUTDELAY);
280
281         if(regVal & REG_SIM_MASKIT_MASK_SIM_RX)
282                 puts("  |  |-REG_SIM_MASKIT_MASK_SIM_RX = 1 ==> Waiting characters to be read interrupt is masked.\n");
283         else
284                 puts("  |  |-REG_SIM_MASKIT_MASK_SIM_RX = 0 ==> Waiting characters to be read interrupt is unmasked.\n");
285         delay_ms(SIM_DEBUG_OUTPUTDELAY);
286
287         if(regVal & REG_SIM_MASKIT_MASK_SIM_CD)
288                 puts("  |  |-REG_SIM_MASKIT_MASK_SIM_CD = 1 ==> SIM card insertion/extraction interrupt is masked.\n");
289         else
290                 puts("  |  |-REG_SIM_MASKIT_MASK_SIM_CD = 0 ==> SIM card insertion/extraction interrupt is unmasked.\n");
291         delay_ms(SIM_DEBUG_OUTPUTDELAY);
292
293         regVal = REG_SIM_IT_CD;
294         printf("  |-REG_SIM_IT_CD = %04x\n", regVal);
295         if(regVal & REG_SIM_IT_CD_IT_CD)
296                 puts("     |-REG_SIM_IT_CD_IT_CD = 1 ==> SIM card insertion/extraction interrupt is masked.\n");
297         else
298                 puts("     |-REG_SIM_IT_CD_IT_CD = 0 ==> SIM card insertion/extraction interrupt is unmasked.\n");
299         delay_ms(SIM_DEBUG_OUTPUTDELAY);
300 #endif
301         return;
302 }
303
304 /* Apply power to the simcard (use nullpointer to ignore atr) */
305 int calypso_sim_powerup(uint8_t *atr)
306 {
307         /* Enable level shifters and voltage regulator */
308         twl3025_reg_write(VRPCSIM, VRPCSIM_SIMLEN | VRPCSIM_RSIMEN | VRPCSIM_SIMSEL);
309 #if (SIM_DEBUG == 1)
310         puts(" * Power enabled!\n");
311 #endif
312         delay_ms(SIM_OPERATION_DELAY);
313
314         /* Enable clock */
315         writew(REG_SIM_CMD_MODULE_CLK_EN | REG_SIM_CMD_CMDSTART, REG_SIM_CMD);
316 #if (SIM_DEBUG == 1)
317         puts(" * Clock enabled!\n");
318 #endif
319         delay_ms(SIM_OPERATION_DELAY);
320
321         /* Release reset */
322         writew(readw(REG_SIM_CONF1) | REG_SIM_CONF1_CONFBYPASS | REG_SIM_CONF1_CONFSRSTLEV | REG_SIM_CONF1_CONFSVCCLEV, REG_SIM_CONF1);
323 #if (SIM_DEBUG == 1)
324         puts(" * Reset released!\n");
325 #endif
326
327         /* Catch ATR */
328         if(atr != 0)
329                 return calypso_sim_receive(atr);
330         else
331                 return 0;
332 }
333
334
335 /* Powerdown simcard */
336 void calypso_sim_powerdown(void)
337 {
338         writew(readw(REG_SIM_CONF1) & ~REG_SIM_CONF1_CONFBYPASS, REG_SIM_CONF1);
339 #if (SIM_DEBUG == 1)
340         puts(" * Reset pulled down!\n");
341 #endif
342         delay_ms(SIM_OPERATION_DELAY);
343
344         writew(REG_SIM_CMD_MODULE_CLK_EN | REG_SIM_CMD_CMDSTOP, REG_SIM_CMD);
345 #if (SIM_DEBUG == 1)
346         puts(" * Clock disabled!\n");
347 #endif
348         delay_ms(SIM_OPERATION_DELAY);
349
350         writew(0, REG_SIM_CMD);
351 #if (SIM_DEBUG == 1)
352         puts(" * Module disabled!\n");
353 #endif
354         delay_ms(SIM_OPERATION_DELAY);
355
356         /* Disable level shifters and voltage regulator */
357         twl3025_reg_write(VRPCSIM, 0);
358 #if (SIM_DEBUG == 1)
359         puts(" * Power disabled!\n");
360 #endif
361         delay_ms(SIM_OPERATION_DELAY);
362
363         return;
364 }
365
366 /* reset the simcard (see note 1) */
367 int calypso_sim_reset(uint8_t *atr)
368 {
369
370         /* Pull reset down */
371         writew(readw(REG_SIM_CONF1) & ~REG_SIM_CONF1_CONFSRSTLEV , REG_SIM_CONF1);
372 #if (SIM_DEBUG == 1)
373         puts(" * Reset pulled down!\n");
374 #endif
375
376         delay_ms(SIM_OPERATION_DELAY);
377
378         /* Pull reset down */
379         writew(readw(REG_SIM_CONF1) | REG_SIM_CONF1_CONFSRSTLEV , REG_SIM_CONF1);
380 #if (SIM_DEBUG == 1)
381         puts(" * Reset released!\n");
382 #endif
383
384         /* Catch ATR */
385         if(atr != 0)
386                 return calypso_sim_receive(atr);
387         else
388                 return 0;
389 }
390
391 /* Receive raw data through the sim interface */
392 int calypso_sim_receive(uint8_t *data)
393 {
394         /* Prepare buffers and flags */
395         rx_buffer = data;
396         sim_rx_character_count = 0;
397         rxDoneFlag = 0;
398
399         /* Switch I/O direction to input */
400         writew(readw(REG_SIM_CONF1) & ~REG_SIM_CONF1_CONFTXRX, REG_SIM_CONF1);
401
402         /* Unmask the interrupts that are needed to perform this action */
403         writew(~(REG_SIM_MASKIT_MASK_SIM_RX | REG_SIM_MASKIT_MASK_SIM_WT), REG_SIM_MASKIT);
404
405         /* Wait till rxDoneFlag is set */
406         while(rxDoneFlag == 0);
407
408         /* Disable all interrupt driven functions by masking all interrupts */
409         writew(0xFF, REG_SIM_MASKIT);
410
411         /* Hand back the number of bytes received */
412         return sim_rx_character_count;
413         
414         return;
415 }
416
417 /* Transmit raw data through the sim interface */
418 int calypso_sim_transmit(uint8_t *data, int length)
419 {
420         /* Prepare buffers and flags */
421         tx_buffer = data;
422         sim_tx_character_count = 0;
423         txDoneFlag = 0;
424         sim_tx_character_length = length;
425
426         /* Switch I/O direction to output */
427         writew(readw(REG_SIM_CONF1) | REG_SIM_CONF1_CONFTXRX, REG_SIM_CONF1);
428
429         /* Unmask the interrupts that are needed to perform this action */
430         writew(~(REG_SIM_MASKIT_MASK_SIM_TX), REG_SIM_MASKIT);
431
432         /* Transmit the first byte manually to start the interrupt cascade */
433         writew(*tx_buffer,REG_SIM_DTX);
434         tx_buffer++;
435         sim_tx_character_count++;
436
437         /* Wait till rxDoneFlag is set */
438         while(txDoneFlag == 0);
439
440         /* Disable all interrupt driven functions by masking all interrupts */
441         writew(0xFF, REG_SIM_MASKIT);
442
443         return 0;
444 }
445
446
447 /* IRQ-Handler for simcard interface */
448 void sim_irq_handler(enum irq_nr irq)
449 {
450         int regVal = readw(REG_SIM_IT);
451
452
453         /* Display interrupt information */
454 #if (SIM_DEBUG == 1)
455         puts("SIM-ISR: Interrupt caught: ");
456 #endif
457         if(regVal & REG_SIM_IT_SIM_NATR)
458         {
459 #if (SIM_DEBUG == 1)
460                 puts(" No answer to reset!\n");
461 #endif
462         }
463
464         /* Used by: calypso_sim_receive() to determine when the transmission is over */
465         if(regVal & REG_SIM_IT_SIM_WT)
466         {
467 #if (SIM_DEBUG == 1)
468                 puts(" Character underflow!\n");
469 #endif
470                 rxDoneFlag = 1;
471         }
472
473         if(regVal & REG_SIM_IT_SIM_OV)
474         {
475 #if (SIM_DEBUG == 1)
476                 puts(" Receive overflow!\n");
477 #endif
478         }
479
480         /* Used by: calypso_sim_transmit() to transmit the data */
481         if(regVal & REG_SIM_IT_SIM_TX)
482         {
483 #if (SIM_DEBUG == 1)
484                 puts(" Waiting for character to transmit...\n");
485 #endif
486                 if(sim_tx_character_count >= sim_tx_character_length)
487                         txDoneFlag = 1;
488                 else
489                 {
490                         writew(*tx_buffer,REG_SIM_DTX);
491                         tx_buffer++;
492                         sim_tx_character_count++;
493                 }
494         }
495
496         /* Used by: calypso_sim_receive() to receive the incoming data */
497         if(regVal & REG_SIM_IT_SIM_RX)
498         {
499 #if (SIM_DEBUG == 1)
500                 puts(" Waiting characters to be read...\n");
501 #endif
502                 /* Increment character count - this is what calypso_sim_receive() hands back */
503                 sim_rx_character_count++;
504
505                 /* Read byte from rx-fifo and write it to the issued buffer */
506                 *rx_buffer = (uint8_t) (readw(REG_SIM_DRX) & 0xFF);
507                 rx_buffer++;
508         }
509 }
510
511 /* Transceive T0 Apdu to sim acording to GSM 11.11 Page 34 */
512 int calypso_sim_transceive(uint8_t cla,                 /* Class (in GSM context mostly 0xA0 */
513                                 uint8_t ins,            /* Instruction */
514                                 uint8_t p1,             /* First parameter */
515                                 uint8_t p2,             /* Second parameter */
516                                 uint8_t p3le,           /* Length of the data that should be transceived */
517                                 uint8_t *data,          /* Data payload */
518                                 uint8_t *status,        /* Status word (2 byte array, see note 1) */
519                                 uint8_t mode)           /* Mode of operation: 1=GET, 0=PUT */
520
521                                 /* Note 1: You can use a null-pointer (0) if you are not interested in 
522                                            the status word */
523 {
524         uint8_t transmissionBuffer[256];
525         uint8_t numberOfReceivedBytes;
526
527 #if (SIM_DEBUG == 1)
528         printf("SIM-T0: Transceiving APDU-Header: (%02x %02x %02x %02x %02x)\n",cla,ins,p1,p2,p3le);
529 #endif
530
531         /* Transmit APDU header */
532         memset(transmissionBuffer,0,sizeof(transmissionBuffer));
533         transmissionBuffer[0] = cla;
534         transmissionBuffer[1] = ins;
535         transmissionBuffer[2] = p1;
536         transmissionBuffer[3] = p2;
537         transmissionBuffer[4] = p3le;
538         calypso_sim_transmit(transmissionBuffer,5);
539
540         /* Case 1: No input, No Output */
541         if(p3le == 0)
542         {
543 #if (SIM_DEBUG == 1)
544                 puts("SIM-T0: Case 1: No input, No Output (See also GSM 11.11 Page 34)\n");
545 #endif
546                 numberOfReceivedBytes = calypso_sim_receive(transmissionBuffer);
547                 
548                 if(numberOfReceivedBytes == 2)
549                 {
550 #if (SIM_DEBUG == 1)
551                         printf("SIM-T0: Status-word received: %02x %02x\n", transmissionBuffer[0], transmissionBuffer[1]);
552 #endif
553                         /* Hand back status word */
554                         if(status != 0)
555                         {
556                                 status[0] = transmissionBuffer[0];
557                                 status[1] = transmissionBuffer[1];
558                         }       
559
560                         return 0;
561                 }
562                 else
563                 {
564 #if (SIM_DEBUG == 1)
565                         puts("SIM-T0: T0 Protocol error -- aborting!\n");
566 #endif
567                         return -1;
568                 }
569         }
570
571         /* Case 2: No input / Output of known length */
572         else if(mode == SIM_APDU_PUT)
573         {
574 #if (SIM_DEBUG == 1)
575                 puts("SIM-T0: Case 2: No input / Output of known length (See also GSM 11.11 Page 34)\n");
576 #endif
577
578                 numberOfReceivedBytes = calypso_sim_receive(transmissionBuffer);
579
580                 /* Error situation: The card has aborted, sends no data but a status word */
581                 if(numberOfReceivedBytes == 2)
582                 {
583 #if (SIM_DEBUG == 1)
584                         printf("SIM-T0: Status-word received (ERROR): %02x %02x\n", transmissionBuffer[0], transmissionBuffer[1]);
585 #endif
586                         /* Hand back status word */
587                         if(status != 0)
588                         {
589                                 status[0] = transmissionBuffer[0];
590                                 status[1] = transmissionBuffer[1];
591                         }                               
592
593                         return 0;
594                 }
595                 /* Acknoledge byte received */
596                 else if(numberOfReceivedBytes == 1)
597                 {
598 #if (SIM_DEBUG == 1)
599                         printf("SIM-T0: ACK received: %02x\n", transmissionBuffer[0]);
600 #endif
601                         /* Check if ACK is valid */
602                         if(transmissionBuffer[0] != ins)
603                         {
604 #if (SIM_DEBUG == 1)
605                                 puts("SIM-T0: T0 Protocol error: Invalid ACK byte -- aborting!\n");
606 #endif                          
607                                 return -1;
608                         }
609
610                         /* Transmit body */
611                         calypso_sim_transmit(data,p3le);
612                         
613                         /* Receive status word */
614                         numberOfReceivedBytes = calypso_sim_receive(transmissionBuffer);
615
616                         /* Check status word */
617                         if(numberOfReceivedBytes == 2)
618                         {
619 #if (SIM_DEBUG == 1)
620                                 printf("SIM-T0: Status-word received: %02x %02x\n", transmissionBuffer[0], transmissionBuffer[1]);
621 #endif
622
623                                 /* Hand back status word */
624                                 if(status != 0)
625                                 {
626                                         status[0] = transmissionBuffer[0];
627                                         status[1] = transmissionBuffer[1];
628                                 }
629
630                                 return 0;
631                         }
632                         else
633                         {
634 #if (SIM_DEBUG == 1)
635                                 puts("SIM-T0: T0 Protocol error: Missing or invalid status word -- aborting!\n");
636 #endif                          
637                                 return -1;
638                         }
639                 }
640                 else
641                 {
642 #if (SIM_DEBUG == 1)
643                         puts("SIM-T0: T0 Protocol error: Missing ACK byte -- aborting!\n");
644 #endif
645                         return -1;
646                 }
647         }
648
649         /* Case 4: Input / No output */
650         else if(mode == SIM_APDU_GET)
651         {
652 #if (SIM_DEBUG == 1)
653                 puts("SIM-T0: Case 4: Input / No output (See also GSM 11.11 Page 34)\n");
654 #endif
655
656                 numberOfReceivedBytes = calypso_sim_receive(data);
657
658                 /* Error situation: The card has aborted, sends no data but a status word */
659                 if(numberOfReceivedBytes == 2)
660                 {
661
662 #if (SIM_DEBUG == 1)
663                         printf("SIM-T0: Status-word received (ERROR): %02x %02x\n", data[0], data[1]);
664 #endif
665                         /* Hand back status word */
666                         if(status != 0)
667                         {
668                                 status[0] = data[0];
669                                 status[1] = data[1];
670                         }                               
671
672                         return 0;
673                 }
674
675                 /* Data correctly received */
676                 else if(numberOfReceivedBytes == p3le + 1 + 2)
677                 {
678 #if (SIM_DEBUG == 1)
679                         printf("SIM-T0: ACK received: %02x\n", data[0]);
680 #endif
681                         /* Check if ACK is valid */
682                         if(data[0] != ins)
683                         {
684 #if (SIM_DEBUG == 1)
685                                 puts("SIM-T0: T0 Protocol error: Invalid ACK byte -- aborting!\n");
686 #endif                          
687                                 return -1;
688                         }
689
690 #if (SIM_DEBUG == 1)
691                         printf("SIM-T0: Status-word received: %02x %02x\n", data[p3le + 1], data[p3le + 2]);
692 #endif
693                         /* Hand back status word */
694                         if(status != 0)
695                         {
696                                 status[0] = data[p3le + 1];
697                                 status[1] = data[p3le + 2];
698                         }                               
699         
700                         /* Move data one position left to cut away the ACK-Byte */
701                         memcpy(data,data+1,p3le);
702
703                         return 0;
704                 }
705                 else
706                 {
707 #if (SIM_DEBUG == 1)
708                         puts("SIM-T0: T0 Protocol error: Incorrect or missing answer -- aborting!\n");
709 #endif
710                         return -1;
711                 }
712         }
713
714         /* Should not happen, if it happens then the programmer has submitted invalid parameters! */
715         else
716         {
717 #if (SIM_DEBUG == 1)
718                 puts("SIM-T0: T0 Protocol error: Invalid case (program bug!) -- aborting!\n");
719 #endif
720         }
721
722         /* Note: The other cases are not implemented because they are already covered
723                  by the CASE 1,2 and 4. */
724
725         return 0;
726 }
727
728
729 /* Initialize simcard interface */
730 void calypso_sim_init(void)
731 {
732         /* Register IRQ handler and turn interrupts on */
733 #if (SIM_DEBUG == 1)
734         puts("SIM: Registering interrupt handler for simcard-interface\n");
735 #endif
736         irq_register_handler(IRQ_SIMCARD, &sim_irq_handler);
737         irq_config(IRQ_SIMCARD, 0, 0, 0xff);
738         irq_enable(IRQ_SIMCARD);
739 }
740