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.

414 lines
11 KiB

  1. /*****************************************************************************
  2. *
  3. * Copyright (c) 1998-1999 Microsoft Corporation
  4. *
  5. * @doc
  6. * @module crystal.c | IrSIR NDIS Miniport Driver
  7. * @comm
  8. *
  9. *-----------------------------------------------------------------------------
  10. *
  11. * Author: Stan Adermann (stana)
  12. *
  13. * Date: 10/30/1997 (created)
  14. *
  15. * Contents: Crystal (AMP dongle specific code for initialization,
  16. * deinit, and setting the baud rate of the device.
  17. *
  18. *****************************************************************************/
  19. #include "irsir.h"
  20. #include "dongle.h"
  21. ULONG CRYSTAL_IRDA_SPEEDS = (
  22. NDIS_IRDA_SPEED_2400 |
  23. NDIS_IRDA_SPEED_9600 |
  24. NDIS_IRDA_SPEED_19200 |
  25. NDIS_IRDA_SPEED_38400 |
  26. NDIS_IRDA_SPEED_57600 |
  27. NDIS_IRDA_SPEED_115200
  28. );
  29. #define MS(d) ((d)*1000)
  30. /*
  31. ** Command sequences for configuring CRYSTAL chip.
  32. */
  33. UCHAR CrystalSetPrimaryRegisterSet[] = { 0xD0 };
  34. UCHAR CrystalSetSecondaryRegisterSet[] = { 0xD1 };
  35. UCHAR CrystalSetSpeed2400[] = { 0x10, 0x8F, 0x95, 0x11 };
  36. UCHAR CrystalSetSpeed9600[] = { 0x10, 0x87, 0x91, 0x11 };
  37. UCHAR CrystalSetSpeed19200[] = { 0x10, 0x8B, 0x90, 0x11 };
  38. UCHAR CrystalSetSpeed38400[] = { 0x10, 0x85, 0x90, 0x11 };
  39. UCHAR CrystalSetSpeed57600[] = { 0x10, 0x83, 0x90, 0x11 };
  40. UCHAR CrystalSetSpeed115200[] = { 0x10, 0x81, 0x90, 0x11 };
  41. UCHAR CrystalSetIrdaMode[] = { 0x0B, 0x53, 0x47, 0x63, 0x74, 0xD1, 0x56, 0xD0 };
  42. UCHAR CrystalSetASKMode[] = { 0x0b, 0x43, 0x62, 0x54 };
  43. UCHAR CrystalSetLowPower[] = { 0x09, 0x00 };
  44. #if 1
  45. static BOOLEAN
  46. CrystalWriteCommand(IN PDEVICE_OBJECT pSerialDevObj,
  47. IN PUCHAR pCommand, UINT Length)
  48. {
  49. SerialSetTimeouts(pSerialDevObj, &SerialTimeoutsInit);
  50. while (Length--)
  51. {
  52. UCHAR Response;
  53. ULONG BytesRead;
  54. ULONG BytesWritten = 0;
  55. NTSTATUS Status;
  56. (void)SerialSynchronousWrite(pSerialDevObj,
  57. pCommand,
  58. 1,
  59. &BytesWritten);
  60. if (BytesWritten!=1)
  61. {
  62. return FALSE;
  63. }
  64. Status = SerialSynchronousRead(pSerialDevObj,
  65. &Response,
  66. 1,
  67. &BytesRead);
  68. if (Status!=STATUS_SUCCESS || Response!=*pCommand)
  69. {
  70. if (BytesRead)
  71. {
  72. DEBUGMSG(DBG_ERROR, ("Expected: %02X Got: %02X\n", *pCommand, Response));
  73. }
  74. return FALSE;
  75. }
  76. pCommand++;
  77. }
  78. return TRUE;
  79. }
  80. #else
  81. BOOLEAN CrystalWriteCmd(IN PDEVICE_OBJECT pSerialDevObj, IN PUCHAR pCmd, IN ULONG Len)
  82. {
  83. NTSTATUS Status;
  84. ULONG BytesWritten, BytesRead, i, j;
  85. UCHAR c;
  86. SerialSetTimeouts(pSerialDevObj, &SerialTimeoutsInit);
  87. for (i=0;
  88. i<20000;
  89. i++)
  90. {
  91. if (SerialSynchronousRead(pSerialDevObj, &c, 1, &BytesRead)!=STATUS_SUCCESS)
  92. {
  93. break;
  94. }
  95. }
  96. for (i=0; i<Len; i++)
  97. {
  98. Status = SerialSynchronousWrite(pSerialDevObj, &pCmd[i], 1, &BytesWritten);
  99. if (Status!=STATUS_SUCCESS || BytesWritten!=1)
  100. return FALSE;
  101. // The dongle is not particularly responsive, so we need to give it some time.
  102. j = 0;
  103. do
  104. {
  105. Status = SerialSynchronousRead(pSerialDevObj, &c, 1, &BytesRead);
  106. if (BytesRead==0)
  107. {
  108. NdisMSleep(MS(10));
  109. }
  110. } while ( BytesRead==0 && j++<3);
  111. if (Status!=STATUS_SUCCESS || c!=pCmd[i])
  112. return FALSE;
  113. }
  114. return TRUE;
  115. }
  116. #endif
  117. BOOLEAN CrystalReadRev(IN PDEVICE_OBJECT pSerialDevObj, OUT PUCHAR pRev)
  118. {
  119. UCHAR readval, writeval = 0xC0;
  120. ULONG BytesWritten, BytesRead;
  121. NTSTATUS Status = STATUS_SUCCESS;
  122. /*
  123. ** Set secondary register set
  124. */
  125. if (!CrystalWriteCommand(pSerialDevObj,
  126. CrystalSetSecondaryRegisterSet,
  127. sizeof(CrystalSetSecondaryRegisterSet)))
  128. {
  129. Status = STATUS_UNSUCCESSFUL;
  130. }
  131. if (Status==STATUS_SUCCESS)
  132. {
  133. Status = SerialSynchronousWrite(pSerialDevObj, &writeval, 1, &BytesWritten);
  134. }
  135. if (Status==STATUS_SUCCESS && BytesWritten==1)
  136. {
  137. NdisMSleep(MS(10));
  138. Status = SerialSynchronousRead(pSerialDevObj, &readval, 1, &BytesRead);
  139. }
  140. if (Status==STATUS_SUCCESS && BytesRead==1)
  141. {
  142. if ((readval & 0xF0) != writeval){
  143. return FALSE;
  144. }
  145. *pRev = (readval & 0x0F);
  146. /*
  147. ** Switch back to primary register set
  148. */
  149. CrystalWriteCommand(pSerialDevObj,
  150. CrystalSetPrimaryRegisterSet,
  151. sizeof(CrystalSetPrimaryRegisterSet));
  152. }
  153. #if DBG
  154. if (Status!=STATUS_SUCCESS)
  155. {
  156. DEBUGMSG(DBG_ERR, ("CrystalReadRev failed 0x%08X\n", Status));
  157. }
  158. #endif
  159. return ((Status==STATUS_SUCCESS) ? TRUE : FALSE);
  160. }
  161. static BOOLEAN CrystalSetIrDAMode(IN PDEVICE_OBJECT pSerialDevObj, OUT PUCHAR pRev)
  162. {
  163. UINT i;
  164. ULONG BytesWritten;
  165. NTSTATUS Status;
  166. ULONG Speed9600 = 9600;
  167. //(void)SerialSetBaudRate(pSerialDevObj, &Speed9600);
  168. (void)SerialPurge(pSerialDevObj);
  169. for (i=0; i<5; i++)
  170. {
  171. (void)SerialSetDTR(pSerialDevObj);
  172. (void)SerialSetRTS(pSerialDevObj);
  173. NdisMSleep(MS(50));
  174. (void)SerialClrRTS(pSerialDevObj);
  175. NdisMSleep(MS(50));
  176. if (!CrystalWriteCommand(pSerialDevObj,
  177. CrystalSetIrdaMode,
  178. sizeof(CrystalSetIrdaMode)))
  179. {
  180. continue;
  181. }
  182. if (CrystalReadRev(pSerialDevObj, pRev))
  183. {
  184. return TRUE;
  185. }
  186. }
  187. DEBUGMSG(DBG_ERR, ("IRSIR: Failed to set CrystalIrDAMode\n"));
  188. return FALSE;
  189. }
  190. NDIS_STATUS
  191. Crystal_QueryCaps(
  192. OUT PDONGLE_CAPABILITIES pDongleCaps
  193. )
  194. {
  195. pDongleCaps->supportedSpeedsMask = CRYSTAL_IRDA_SPEEDS;
  196. pDongleCaps->turnAroundTime_usec = 100;
  197. pDongleCaps->extraBOFsRequired = 0;
  198. return NDIS_STATUS_SUCCESS;
  199. }
  200. /*****************************************************************************
  201. *
  202. * Function: Crystal_Init
  203. *
  204. * Synopsis: Initialize the Crystal dongle.
  205. *
  206. * Arguments:
  207. *
  208. * Returns: NDIS_STATUS_SUCCESS
  209. * DONGLE_CAPABILITIES
  210. *
  211. * Algorithm:
  212. *
  213. * History: dd-mm-yyyy Author Comment
  214. * 03-04-1998 stana author
  215. *
  216. * Notes:
  217. *
  218. *****************************************************************************/
  219. NDIS_STATUS
  220. Crystal_Init(
  221. IN PDEVICE_OBJECT pSerialDevObj
  222. )
  223. {
  224. ULONG BytesRead, BytesWritten;
  225. UCHAR Response, Revision;
  226. BOOLEAN Reset = FALSE;
  227. UINT i;
  228. DEBUGMSG(DBG_FUNC, ("+Crystal_Init\n"));
  229. if (!CrystalSetIrDAMode(pSerialDevObj, &Revision))
  230. {
  231. return NDIS_STATUS_FAILURE;
  232. }
  233. //
  234. // Clear command mode
  235. //
  236. (void)SerialClrDTR(pSerialDevObj);
  237. NdisMSleep(MS(50));
  238. if (Revision==0x1)
  239. {
  240. // This is Rev C, which doesn't support 115200
  241. CRYSTAL_IRDA_SPEEDS &= ~NDIS_IRDA_SPEED_115200;
  242. }
  243. else
  244. {
  245. CRYSTAL_IRDA_SPEEDS |= NDIS_IRDA_SPEED_115200;
  246. }
  247. DEBUGMSG(DBG_FUNC, ("-Crystal_Init\n"));
  248. return NDIS_STATUS_SUCCESS;
  249. }
  250. /*****************************************************************************
  251. *
  252. * Function: Crystal_Deinit
  253. *
  254. * Synopsis: The Crystal dongle doesn't require any special deinit, but for
  255. * purposes of being symmetrical with other dongles...
  256. *
  257. * Arguments:
  258. *
  259. * Returns:
  260. *
  261. * Algorithm:
  262. *
  263. * History: dd-mm-yyyy Author Comment
  264. * 03-04-1998 stana author
  265. *
  266. * Notes:
  267. *
  268. *
  269. *****************************************************************************/
  270. VOID
  271. Crystal_Deinit(
  272. IN PDEVICE_OBJECT pSerialDevObj
  273. )
  274. {
  275. DEBUGMSG(DBG_FUNC, ("+Crystal_Deinit\n"));
  276. (void)SerialClrDTR(pSerialDevObj);
  277. (void)SerialClrRTS(pSerialDevObj);
  278. DEBUGMSG(DBG_FUNC, ("-Crystal_Deinit\n"));
  279. return;
  280. }
  281. /*****************************************************************************
  282. *
  283. * Function: Crystal_SetSpeed
  284. *
  285. * Synopsis: set the baud rate of the Crystal dongle
  286. *
  287. * Arguments:
  288. *
  289. * Returns: NDIS_STATUS_SUCCESS if bitsPerSec = 9600 || 19200 || 115200
  290. * NDIS_STATUS_FAILURE otherwise
  291. *
  292. * Algorithm:
  293. *
  294. * History: dd-mm-yyyy Author Comment
  295. * 10/2/1996 stana author
  296. *
  297. * Notes:
  298. * The caller of this function should set the baud rate of the
  299. * serial driver (UART) to 9600 first to ensure that dongle
  300. * receives the commands.
  301. *
  302. *
  303. *****************************************************************************/
  304. NDIS_STATUS
  305. Crystal_SetSpeed(
  306. IN PDEVICE_OBJECT pSerialDevObj,
  307. IN UINT bitsPerSec,
  308. IN UINT currentSpeed
  309. )
  310. {
  311. ULONG WaitMask = SERIAL_EV_TXEMPTY;
  312. UCHAR *SetSpeedString, Revision;
  313. ULONG SetSpeedStringLength, BytesWritten;
  314. ULONG Speed9600 = 9600;
  315. BOOLEAN Result;
  316. DEBUGMSG(DBG_FUNC, ("+Crystal_SetSpeed\n"));
  317. switch (bitsPerSec)
  318. {
  319. #define MAKECASE(speed) \
  320. case speed: SetSpeedString = CrystalSetSpeed##speed; SetSpeedStringLength = sizeof(CrystalSetSpeed##speed); break;
  321. MAKECASE(2400)
  322. MAKECASE(9600)
  323. MAKECASE(19200)
  324. MAKECASE(38400)
  325. MAKECASE(57600)
  326. MAKECASE(115200)
  327. default:
  328. return NDIS_STATUS_FAILURE;
  329. }
  330. (void)SerialSetBaudRate(pSerialDevObj, &Speed9600);
  331. (void)SerialPurge(pSerialDevObj);
  332. NdisMSleep(MS(20));
  333. (void)SerialSetDTR(pSerialDevObj);
  334. NdisMSleep(MS(50));
  335. if (!CrystalWriteCommand(pSerialDevObj,
  336. SetSpeedString,
  337. SetSpeedStringLength))
  338. {
  339. if (!CrystalSetIrDAMode(pSerialDevObj, &Revision) ||
  340. !CrystalWriteCommand(pSerialDevObj, SetSpeedString, SetSpeedStringLength))
  341. {
  342. // Always clear DTR to get out of command mode.
  343. (void)SerialClrDTR(pSerialDevObj);
  344. return NDIS_STATUS_FAILURE;
  345. }
  346. }
  347. (void)SerialClrDTR(pSerialDevObj);
  348. NdisMSleep(MS(50));
  349. DEBUGMSG(DBG_FUNC, ("-Crystal_SetSpeed\n"));
  350. return NDIS_STATUS_SUCCESS;
  351. }