Leaked source code of windows server 2003
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.

403 lines
11 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. // take control over
  46. WRITE_PORT_UCHAR( &IOBase->CmdStatusReg, PSCR_HOST_CONTROL_BIT );
  47. // get number of available bytes
  48. Length = ((ULONG)READ_PORT_UCHAR( &IOBase->SizeMSReg )) << 8;
  49. Length |= READ_PORT_UCHAR( &IOBase->SizeLSReg );
  50. // perform a dummy read
  51. while ( Length-- ) {
  52. READ_PORT_UCHAR( &IOBase->DataReg );
  53. }
  54. WRITE_PORT_UCHAR( &IOBase->CmdStatusReg, CLEAR_BIT );
  55. }
  56. return;
  57. }
  58. NTSTATUS
  59. PscrRead(
  60. PREADER_EXTENSION ReaderExtension,
  61. PUCHAR pData,
  62. ULONG DataLen,
  63. PULONG pNBytes
  64. )
  65. /*++
  66. PscrRead:
  67. wait until data available & transfer data from reader to host
  68. Arguments:
  69. ReaderExtension context of call
  70. pData ptr to data buffer
  71. DataLen length of data buffer
  72. pNBytes number of bytes returned
  73. Return Value:
  74. STATUS_SUCCESS
  75. STATUS_BUFFER_TOO_SMALL
  76. STATUS_UNSUCCESSFUL
  77. --*/
  78. {
  79. NTSTATUS NTStatus = STATUS_UNSUCCESSFUL;
  80. USHORT ReaderStatus;
  81. PPSCR_REGISTERS IOBase;
  82. USHORT InDataLen;
  83. IOBase = ReaderExtension->IOBase;
  84. // wait until interface is ready to transfer
  85. InDataLen = 0;
  86. if ( NT_SUCCESS( NTStatus = PscrWait( ReaderExtension, PSCR_DATA_AVAIL_BIT | PSCR_FREE_BIT ))) {
  87. // take control over
  88. WRITE_PORT_UCHAR( &IOBase->CmdStatusReg, PSCR_HOST_CONTROL_BIT );
  89. // get number of available bytes
  90. InDataLen = ( READ_PORT_UCHAR( &IOBase->SizeMSReg ) << 8 );
  91. InDataLen |= READ_PORT_UCHAR( &IOBase->SizeLSReg );
  92. if (InDataLen <= PSCR_PROLOGUE_LENGTH) {
  93. // the buffer does not contain the minimum packet length
  94. NTStatus = STATUS_IO_TIMEOUT;
  95. } else if ( ( ULONG )InDataLen <= DataLen ) {
  96. // check buffer size. if buffer to small, the data will be discarded
  97. // read data
  98. ULONG Idx;
  99. for (Idx = 0; Idx < InDataLen; Idx++) {
  100. pData[ Idx ] = READ_PORT_UCHAR( &IOBase->DataReg );
  101. }
  102. // error check
  103. if ( pData[ InDataLen - 1 ] !=
  104. PscrCalculateLRC( pData, (USHORT)( InDataLen - 1 ))) {
  105. NTStatus = STATUS_CRC_ERROR;
  106. } else {
  107. //
  108. // Evaluation of reader errors. A reader error is indicated
  109. // if the T1 length is 2 and the Nad indicates that this
  110. // packet came from the reader
  111. //
  112. if ( ( ( pData[ PSCR_NAD ] & 0x0F ) == 0x01 ) &&
  113. ( pData[ PSCR_LEN ] == 0x02 )
  114. ) {
  115. ReaderStatus = (( USHORT ) pData[3] ) << 8;
  116. ReaderStatus |= (( USHORT ) pData[4] );
  117. if ( ( ReaderStatus != 0x9000 ) &&
  118. ( ReaderStatus != 0x9001 )
  119. ) {
  120. SmartcardDebug(
  121. DEBUG_TRACE,
  122. ( "PSCR!PscrRead: ReaderStatus = %lx\n", ReaderStatus )
  123. );
  124. InDataLen = 0;
  125. if (ReaderStatus == PSCR_SW_PROTOCOL_ERROR) {
  126. NTStatus = STATUS_IO_TIMEOUT;
  127. } else {
  128. NTStatus = STATUS_UNSUCCESSFUL;
  129. }
  130. }
  131. }
  132. }
  133. } else {
  134. // flush interface in case of wrong buffer size
  135. do {
  136. READ_PORT_UCHAR( &IOBase->DataReg );
  137. } while ( --InDataLen );
  138. NTStatus = STATUS_BUFFER_TOO_SMALL;
  139. }
  140. // clean up
  141. WRITE_PORT_UCHAR( &IOBase->CmdStatusReg, CLEAR_BIT );
  142. }
  143. // write number of bytes received
  144. if ( InDataLen ) {
  145. if ( pNBytes != NULL ) {
  146. ( *pNBytes ) = ( ULONG ) InDataLen;
  147. }
  148. NTStatus = STATUS_SUCCESS;
  149. }
  150. return( NTStatus );
  151. }
  152. NTSTATUS
  153. PscrWrite(
  154. PREADER_EXTENSION ReaderExtension,
  155. PUCHAR pData,
  156. ULONG DataLen,
  157. PULONG pNBytes
  158. )
  159. /*++
  160. PscrWrite:
  161. calculates the LRC of the buffer & sends command to the reader
  162. Arguments:
  163. ReaderExtension context of call
  164. pData ptr to data buffer
  165. DataLen length of data buffer (exclusive LRC!)
  166. pNBytes number of bytes written
  167. Return Value:
  168. return value of PscrWriteDirect
  169. --*/
  170. {
  171. NTSTATUS NTStatus;
  172. // Add the EDC field to the end of the data
  173. pData[ DataLen ] = PscrCalculateLRC( pData, ( USHORT ) DataLen );
  174. // Send buffer
  175. NTStatus = PscrWriteDirect(
  176. ReaderExtension,
  177. pData,
  178. DataLen + PSCR_EPILOGUE_LENGTH,
  179. pNBytes
  180. );
  181. return( NTStatus );
  182. }
  183. NTSTATUS
  184. PscrWriteDirect(
  185. PREADER_EXTENSION ReaderExtension,
  186. PUCHAR pData,
  187. ULONG DataLen,
  188. PULONG pNBytes
  189. )
  190. /*++
  191. PscrWriteDirect:
  192. sends command to the reader. The LRC / CRC must be calculated by caller!
  193. Arguments:
  194. ReaderExtension context of call
  195. pData ptr to data buffer
  196. DataLen length of data buffer (exclusive LRC!)
  197. pNBytes number of bytes written
  198. Return Value:
  199. STATUS_SUCCESS
  200. STATUS_DEVICE_BUSY
  201. --*/
  202. {
  203. NTSTATUS NTStatus = STATUS_SUCCESS;
  204. UCHAR Status;
  205. PPSCR_REGISTERS IOBase;
  206. IOBase = ReaderExtension->IOBase;
  207. // in case of card change, there may be data available
  208. Status = READ_PORT_UCHAR( &IOBase->CmdStatusReg );
  209. if ( Status & PSCR_DATA_AVAIL_BIT ) {
  210. NTStatus = STATUS_DEVICE_BUSY;
  211. } else {
  212. //
  213. // wait until reader is ready
  214. //
  215. WRITE_PORT_UCHAR( &IOBase->CmdStatusReg, PSCR_HOST_CONTROL_BIT );
  216. NTStatus = PscrWait( ReaderExtension, PSCR_FREE_BIT );
  217. if ( NT_SUCCESS( NTStatus )) {
  218. ULONG Idx;
  219. // take control over
  220. WRITE_PORT_UCHAR( &IOBase->CmdStatusReg, PSCR_HOST_CONTROL_BIT );
  221. // write the buffer size
  222. WRITE_PORT_UCHAR( &IOBase->SizeMSReg, ( UCHAR )( DataLen >> 8 ));
  223. SysDelay( DELAY_WRITE_PSCR_REG );
  224. WRITE_PORT_UCHAR( &IOBase->SizeLSReg, ( UCHAR )( DataLen & 0x00FF ));
  225. SysDelay( DELAY_WRITE_PSCR_REG );
  226. // write data
  227. for (Idx = 0; Idx < DataLen; Idx++) {
  228. WRITE_PORT_UCHAR( &IOBase->DataReg, pData[ Idx ] );
  229. }
  230. if ( pNBytes != NULL ) {
  231. *pNBytes = DataLen;
  232. }
  233. }
  234. // clean up
  235. WRITE_PORT_UCHAR( &IOBase->CmdStatusReg, CLEAR_BIT );
  236. }
  237. return( NTStatus );
  238. }
  239. UCHAR
  240. PscrCalculateLRC(
  241. PUCHAR pData,
  242. USHORT DataLen
  243. )
  244. /*++
  245. PscrCalculateLRC:
  246. calculates the XOR LRC of a buffer.
  247. Arguments:
  248. pData ptr to data buffer
  249. DataLen length of range
  250. Return Value:
  251. LRC
  252. --*/
  253. {
  254. UCHAR Lrc;
  255. USHORT Idx;
  256. //
  257. // Calculate LRC by XORing all the bytes.
  258. //
  259. Lrc = pData[ 0 ];
  260. for ( Idx = 1 ; Idx < DataLen; Idx++ ) {
  261. Lrc ^= pData[ Idx ];
  262. }
  263. return( Lrc );
  264. }
  265. NTSTATUS
  266. PscrWait(
  267. PREADER_EXTENSION ReaderExtension,
  268. UCHAR Mask
  269. )
  270. /*++
  271. PscrWait:
  272. Test the status port of the reader until ALL bits in the mask are set.
  273. The maximum of time until DEVICE_BUSY is returned is approx.
  274. MaxRetries * DELAY_PSCR_WAIT if MaxRetries != 0.
  275. If MaxRetries = 0 the driver waits until the requested status is reported or the
  276. user defines a timeout.
  277. Arguments:
  278. ReaderExtension context of call
  279. Mask mask of bits to test the status register
  280. Return Value:
  281. STATUS_SUCCESS
  282. STATUS_DEVICE_BUSY
  283. --*/
  284. {
  285. NTSTATUS NTStatus;
  286. PPSCR_REGISTERS IOBase;
  287. ULONG Retries;
  288. UCHAR Status;
  289. IOBase = ReaderExtension->IOBase;
  290. NTStatus = STATUS_DEVICE_BUSY;
  291. // wait until condition fulfilled or specified timeout expired
  292. for ( Retries = 0; Retries < ReaderExtension->MaxRetries; Retries++) {
  293. if (( (READ_PORT_UCHAR( &IOBase->CmdStatusReg )) == 0x01) &&
  294. ReaderExtension->InvalidStatus) {
  295. NTStatus = STATUS_CANCELLED;
  296. break;
  297. }
  298. // test requested bits
  299. if (( (READ_PORT_UCHAR( &IOBase->CmdStatusReg )) & Mask ) == Mask ) {
  300. NTStatus = STATUS_SUCCESS;
  301. break;
  302. }
  303. SysDelay( DELAY_PSCR_WAIT );
  304. }
  305. Status = READ_PORT_UCHAR( &IOBase->CmdStatusReg );
  306. return NTStatus;
  307. }
  308. #pragma optimize( "", on )