Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

429 lines
8.5 KiB

  1. /*++
  2. Copyright (c) 1997 - 1999 SCM Microsystems, Inc.
  3. Module Name:
  4. PscrRdWr.c
  5. Abstract:
  6. Hardware access functions for SCM PSCR smartcard reader
  7. Author:
  8. Andreas Straub
  9. Environment:
  10. Win 95 Sys... calls are resolved by Pscr95Wrap.asm functions and
  11. Pscr95Wrap.h macros, resp.
  12. NT 4.0 Sys... functions resolved by PscrNTWrap.c functions and
  13. PscrNTWrap.h macros, resp.
  14. Revision History:
  15. Andreas Straub 7/16/1997 1.00 Initial Version
  16. Klaus Schuetz 9/20/1997 1.01 Timing changed
  17. Andreas Straub 9/24/1997 1.02 Low Level error handling,
  18. minor bugfixes, clanup
  19. --*/
  20. #if defined( SMCLIB_VXD )
  21. #include <Pscr95.h>
  22. #else // SMCLIB_VXD
  23. #include <PscrNT.h>
  24. #endif // SMCLIB_VXD
  25. #include <PscrCmd.h>
  26. #include <PscrRdWr.h>
  27. #pragma optimize( "", off )
  28. VOID
  29. PscrFlushInterface( PREADER_EXTENSION ReaderExtension )
  30. /*++
  31. PscrFlushInterface:
  32. Read & discard data from the pcmcia interface
  33. Arguments:
  34. ReaderExtension context of call
  35. Return Value:
  36. void
  37. --*/
  38. {
  39. UCHAR Status;
  40. ULONG Length;
  41. PPSCR_REGISTERS IOBase;
  42. IOBase = ReaderExtension->IOBase;
  43. Status = READ_PORT_UCHAR( &IOBase->CmdStatusReg );
  44. if(( Status & PSCR_DATA_AVAIL_BIT ) && ( Status & PSCR_FREE_BIT ))
  45. {
  46. // take control over
  47. WRITE_PORT_UCHAR( &IOBase->CmdStatusReg, PSCR_HOST_CONTROL_BIT );
  48. // get number of available bytes
  49. Length = ((ULONG)READ_PORT_UCHAR( &IOBase->SizeMSReg )) << 8;
  50. Length |= READ_PORT_UCHAR( &IOBase->SizeLSReg );
  51. // perform a dummy read
  52. while( Length-- )
  53. {
  54. READ_PORT_UCHAR( &IOBase->DataReg );
  55. }
  56. WRITE_PORT_UCHAR( &IOBase->CmdStatusReg, CLEAR_BIT );
  57. }
  58. return;
  59. }
  60. NTSTATUS
  61. PscrRead(
  62. PREADER_EXTENSION ReaderExtension,
  63. PUCHAR pData,
  64. ULONG DataLen,
  65. PULONG pNBytes
  66. )
  67. /*++
  68. PscrRead:
  69. wait until data available & transfer data from reader to host
  70. Arguments:
  71. ReaderExtension context of call
  72. pData ptr to data buffer
  73. DataLen length of data buffer
  74. pNBytes number of bytes returned
  75. Return Value:
  76. STATUS_SUCCESS
  77. STATUS_BUFFER_TOO_SMALL
  78. STATUS_UNSUCCESSFUL
  79. --*/
  80. {
  81. NTSTATUS NTStatus = STATUS_UNSUCCESSFUL;
  82. USHORT ReaderStatus;
  83. PPSCR_REGISTERS IOBase;
  84. USHORT InDataLen;
  85. IOBase = ReaderExtension->IOBase;
  86. // wait until interface is ready to transfer
  87. InDataLen = 0;
  88. if( NT_SUCCESS( NTStatus = PscrWait( ReaderExtension, PSCR_DATA_AVAIL_BIT | PSCR_FREE_BIT )))
  89. {
  90. // take control over
  91. WRITE_PORT_UCHAR( &IOBase->CmdStatusReg, PSCR_HOST_CONTROL_BIT );
  92. // get number of available bytes
  93. InDataLen = ( READ_PORT_UCHAR( &IOBase->SizeMSReg ) << 8 );
  94. InDataLen |= READ_PORT_UCHAR( &IOBase->SizeLSReg );
  95. if (InDataLen <= PSCR_PROLOGUE_LENGTH) {
  96. // the buffer does not contain the minimum packet length
  97. NTStatus = STATUS_IO_TIMEOUT;
  98. } else if( ( ULONG )InDataLen <= DataLen ) {
  99. // check buffer size. if buffer to small, the data will be discarded
  100. // read data
  101. ULONG Idx;
  102. for (Idx = 0; Idx < InDataLen; Idx++) {
  103. pData[ Idx ] = READ_PORT_UCHAR( &IOBase->DataReg );
  104. }
  105. // error check
  106. if( pData[ InDataLen - 1 ] !=
  107. PscrCalculateLRC( pData, (USHORT)( InDataLen - 1 )))
  108. {
  109. NTStatus = STATUS_CRC_ERROR;
  110. }
  111. else
  112. {
  113. //
  114. // Evaluation of reader errors. A reader error is indicated
  115. // if the T1 length is 2 and the Nad indicates that this
  116. // packet came from the reader
  117. //
  118. if( ( ( pData[ PSCR_NAD ] & 0x0F ) == 0x01 ) &&
  119. ( pData[ PSCR_LEN ] == 0x02 )
  120. )
  121. {
  122. ReaderStatus = (( USHORT ) pData[3] ) << 8;
  123. ReaderStatus |= (( USHORT ) pData[4] );
  124. if( ( ReaderStatus != 0x9000 ) &&
  125. ( ReaderStatus != 0x9001 )
  126. )
  127. {
  128. SmartcardDebug(
  129. DEBUG_TRACE,
  130. ( "PSCR!PscrRead: ReaderStatus = %lx\n", ReaderStatus )
  131. );
  132. InDataLen = 0;
  133. if (ReaderStatus == PSCR_SW_PROTOCOL_ERROR) {
  134. NTStatus = STATUS_IO_TIMEOUT;
  135. } else {
  136. NTStatus = STATUS_UNSUCCESSFUL;
  137. }
  138. }
  139. }
  140. }
  141. }
  142. else {
  143. // flush interface in case of wrong buffer size
  144. do
  145. {
  146. READ_PORT_UCHAR( &IOBase->DataReg );
  147. } while( --InDataLen );
  148. NTStatus = STATUS_BUFFER_TOO_SMALL;
  149. }
  150. // clean up
  151. WRITE_PORT_UCHAR( &IOBase->CmdStatusReg, CLEAR_BIT );
  152. }
  153. // write number of bytes received
  154. if( InDataLen )
  155. {
  156. if( pNBytes != NULL )
  157. {
  158. ( *pNBytes ) = ( ULONG ) InDataLen;
  159. }
  160. NTStatus = STATUS_SUCCESS;
  161. }
  162. return ( NTStatus );
  163. }
  164. NTSTATUS
  165. PscrWrite(
  166. PREADER_EXTENSION ReaderExtension,
  167. PUCHAR pData,
  168. ULONG DataLen,
  169. PULONG pNBytes
  170. )
  171. /*++
  172. PscrWrite:
  173. calculates the LRC of the buffer & sends command to the reader
  174. Arguments:
  175. ReaderExtension context of call
  176. pData ptr to data buffer
  177. DataLen length of data buffer (exclusive LRC!)
  178. pNBytes number of bytes written
  179. Return Value:
  180. return value of PscrWriteDirect
  181. --*/
  182. {
  183. NTSTATUS NTStatus;
  184. // Add the EDC field to the end of the data
  185. pData[ DataLen ] = PscrCalculateLRC( pData, ( USHORT ) DataLen );
  186. // Send buffer
  187. NTStatus = PscrWriteDirect(
  188. ReaderExtension,
  189. pData,
  190. DataLen + PSCR_EPILOGUE_LENGTH,
  191. pNBytes
  192. );
  193. return( NTStatus );
  194. }
  195. NTSTATUS
  196. PscrWriteDirect(
  197. PREADER_EXTENSION ReaderExtension,
  198. PUCHAR pData,
  199. ULONG DataLen,
  200. PULONG pNBytes
  201. )
  202. /*++
  203. PscrWriteDirect:
  204. sends command to the reader. The LRC / CRC must be calculated by caller!
  205. Arguments:
  206. ReaderExtension context of call
  207. pData ptr to data buffer
  208. DataLen length of data buffer (exclusive LRC!)
  209. pNBytes number of bytes written
  210. Return Value:
  211. STATUS_SUCCESS
  212. STATUS_DEVICE_BUSY
  213. --*/
  214. {
  215. NTSTATUS NTStatus = STATUS_SUCCESS;
  216. UCHAR Status;
  217. PPSCR_REGISTERS IOBase;
  218. IOBase = ReaderExtension->IOBase;
  219. // in case of card change, there may be data available
  220. Status = READ_PORT_UCHAR( &IOBase->CmdStatusReg );
  221. if( Status & PSCR_DATA_AVAIL_BIT )
  222. {
  223. NTStatus = STATUS_DEVICE_BUSY;
  224. }
  225. else
  226. {
  227. //
  228. // wait until reader is ready
  229. //
  230. WRITE_PORT_UCHAR( &IOBase->CmdStatusReg, PSCR_HOST_CONTROL_BIT );
  231. NTStatus = PscrWait( ReaderExtension, PSCR_FREE_BIT );
  232. if( NT_SUCCESS( NTStatus ))
  233. {
  234. ULONG Idx;
  235. // take control over
  236. WRITE_PORT_UCHAR( &IOBase->CmdStatusReg, PSCR_HOST_CONTROL_BIT );
  237. // write the buffer size
  238. WRITE_PORT_UCHAR( &IOBase->SizeMSReg, ( UCHAR )( DataLen >> 8 ));
  239. SysDelay( DELAY_WRITE_PSCR_REG );
  240. WRITE_PORT_UCHAR( &IOBase->SizeLSReg, ( UCHAR )( DataLen & 0x00FF ));
  241. SysDelay( DELAY_WRITE_PSCR_REG );
  242. // write data
  243. for (Idx = 0; Idx < DataLen; Idx++) {
  244. WRITE_PORT_UCHAR( &IOBase->DataReg, pData[ Idx ] );
  245. }
  246. if( pNBytes != NULL )
  247. {
  248. *pNBytes = DataLen;
  249. }
  250. }
  251. // clean up
  252. WRITE_PORT_UCHAR( &IOBase->CmdStatusReg, CLEAR_BIT );
  253. }
  254. return( NTStatus );
  255. }
  256. UCHAR
  257. PscrCalculateLRC(
  258. PUCHAR pData,
  259. USHORT DataLen
  260. )
  261. /*++
  262. PscrCalculateLRC:
  263. calculates the XOR LRC of a buffer.
  264. Arguments:
  265. pData ptr to data buffer
  266. DataLen length of range
  267. Return Value:
  268. LRC
  269. --*/
  270. {
  271. UCHAR Lrc;
  272. USHORT Idx;
  273. //
  274. // Calculate LRC by XORing all the bytes.
  275. //
  276. Lrc = pData[ 0 ];
  277. for ( Idx = 1 ; Idx < DataLen; Idx++ )
  278. {
  279. Lrc ^= pData[ Idx ];
  280. }
  281. return ( Lrc );
  282. }
  283. NTSTATUS
  284. PscrWait(
  285. PREADER_EXTENSION ReaderExtension,
  286. UCHAR Mask
  287. )
  288. /*++
  289. PscrWait:
  290. Test the status port of the reader until ALL bits in the mask are set.
  291. The maximum of time until DEVICE_BUSY is returned is approx.
  292. MaxRetries * DELAY_PSCR_WAIT if MaxRetries != 0.
  293. If MaxRetries = 0 the driver waits until the requested status is reported or the
  294. user defines a timeout.
  295. Arguments:
  296. ReaderExtension context of call
  297. Mask mask of bits to test the status register
  298. Return Value:
  299. STATUS_SUCCESS
  300. STATUS_DEVICE_BUSY
  301. --*/
  302. {
  303. NTSTATUS NTStatus;
  304. PPSCR_REGISTERS IOBase;
  305. ULONG Retries;
  306. UCHAR Status;
  307. IOBase = ReaderExtension->IOBase;
  308. NTStatus = STATUS_DEVICE_BUSY;
  309. // wait until condition fulfilled or specified timeout expired
  310. for ( Retries = 0; Retries < ReaderExtension->MaxRetries; Retries++)
  311. {
  312. // canceled?
  313. if( ReaderExtension->RequestCancelled == TRUE )
  314. {
  315. NTStatus = STATUS_CANCELLED;
  316. break;
  317. }
  318. if (( (READ_PORT_UCHAR( &IOBase->CmdStatusReg )) == 0x01) &&
  319. ReaderExtension->InvalidStatus)
  320. {
  321. NTStatus = STATUS_CANCELLED;
  322. break;
  323. }
  324. // test requested bits
  325. if(( (READ_PORT_UCHAR( &IOBase->CmdStatusReg )) & Mask ) == Mask )
  326. {
  327. NTStatus = STATUS_SUCCESS;
  328. break;
  329. }
  330. SysDelay( DELAY_PSCR_WAIT );
  331. }
  332. Status = READ_PORT_UCHAR( &IOBase->CmdStatusReg );
  333. return NTStatus;
  334. }
  335. #pragma optimize( "", on )