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.

2379 lines
65 KiB

  1. /**************************************************************************************************************************
  2. * HWIO.C SigmaTel STIR4200 hardware specific module (to access the registers)
  3. **************************************************************************************************************************
  4. * (C) Unpublished Copyright of Sigmatel, Inc. All Rights Reserved.
  5. *
  6. *
  7. * Created: 04/06/2000
  8. * Version 0.9
  9. * Edited: 04/27/2000
  10. * Version 0.92
  11. * Edited: 05/12/2000
  12. * Version 0.94
  13. * Edited: 07/27/2000
  14. * Version 1.01
  15. * Edited: 08/22/2000
  16. * Version 1.02
  17. * Edited: 09/16/2000
  18. * Version 1.03
  19. * Edited: 09/25/2000
  20. * Version 1.10
  21. * Edited: 11/10/2000
  22. * Version 1.12
  23. * Edited: 01/16/2001
  24. * Version 1.14
  25. * Edited: 02/20/2001
  26. * Version 1.15
  27. *
  28. **************************************************************************************************************************/
  29. #define DOBREAKS // enable debug breaks
  30. #include <ndis.h>
  31. #include <ntdef.h>
  32. #include <windef.h>
  33. #include "stdarg.h"
  34. #include "stdio.h"
  35. #include "debug.h"
  36. #include "usbdi.h"
  37. #include "usbdlib.h"
  38. #include "ircommon.h"
  39. #include "irusb.h"
  40. #include "irndis.h"
  41. #include "stir4200.h"
  42. /*****************************************************************************
  43. *
  44. * Function: St4200ResetFifo
  45. *
  46. * Synopsis: Reset the STIr4200 FIFO to clear several hangs
  47. *
  48. * Arguments: pDevice - pointer to current ir device object
  49. *
  50. * Returns: NT_STATUS
  51. *
  52. *
  53. *****************************************************************************/
  54. NTSTATUS
  55. St4200ResetFifo(
  56. IN PVOID pDevice
  57. )
  58. {
  59. NTSTATUS Status;
  60. PIR_DEVICE pThisDev = (PIR_DEVICE)pDevice;
  61. DEBUGMSG(DBG_INT_ERR, (" St4200ResetFifo: Issuing a FIFO reset()\n"));
  62. // MS Security bug #538703
  63. IRUSB_ASSERT(pDevice != NULL);
  64. #if !defined(FAST_WRITE_REGISTERS)
  65. if( (Status = St4200ReadRegisters(pThisDev, STIR4200_MODE_REG, 1)) != STATUS_SUCCESS )
  66. {
  67. DEBUGMSG(DBG_ERR, (" St4200ResetFifo(): USB failure\n"));
  68. goto done;
  69. }
  70. #endif
  71. //
  72. // Force a FIFO reset by clearing and setting again the RESET_OFF bit
  73. //
  74. pThisDev->StIrTranceiver.ModeReg &= (~STIR4200_MODE_RESET_OFF);
  75. if( (Status = St4200WriteRegister(pThisDev, STIR4200_MODE_REG)) != STATUS_SUCCESS )
  76. {
  77. DEBUGMSG(DBG_ERR, (" St4200ResetFifo(): USB failure\n"));
  78. goto done;
  79. }
  80. pThisDev->StIrTranceiver.ModeReg |= STIR4200_MODE_RESET_OFF;
  81. if( (Status = St4200WriteRegister(pThisDev, STIR4200_MODE_REG)) != STATUS_SUCCESS )
  82. {
  83. DEBUGMSG(DBG_ERR, (" St4200ResetFifo(): USB failure\n"));
  84. goto done;
  85. }
  86. done:
  87. return Status;
  88. }
  89. /*****************************************************************************
  90. *
  91. * Function: St4200DoubleResetFifo
  92. *
  93. * Synopsis: Reset the STIr4200 FIFO to clear several 4012 related hangs
  94. *
  95. * Arguments: pDevice - pointer to current ir device object
  96. *
  97. * Returns: NT_STATUS
  98. *
  99. *
  100. *****************************************************************************/
  101. NTSTATUS
  102. St4200DoubleResetFifo(
  103. IN PVOID pDevice
  104. )
  105. {
  106. NTSTATUS Status;
  107. PIR_DEVICE pThisDev = (PIR_DEVICE)pDevice;
  108. DEBUGMSG(DBG_INT_ERR, (" St4200DoubleResetFifo: Issuing a FIFO reset()\n"));
  109. // MS Security bug #538703
  110. IRUSB_ASSERT(pDevice != NULL);
  111. //
  112. // Turn off the receiver to clear the pointers
  113. //
  114. if( (Status = St4200TurnOffReceiver( pThisDev ) ) != STATUS_SUCCESS )
  115. {
  116. DEBUGMSG(DBG_ERR, (" St4200DoubleResetFifo(): USB failure\n"));
  117. goto done;
  118. }
  119. //
  120. // Now clear the fifo logic
  121. //
  122. #if !defined(FAST_WRITE_REGISTERS)
  123. if( (Status = St4200ReadRegisters(pThisDev, STIR4200_STATUS_REG, 1)) != STATUS_SUCCESS )
  124. {
  125. DEBUGMSG(DBG_ERR, (" St4200DoubleResetFifo(): USB failure\n"));
  126. goto done;
  127. }
  128. if( (Status = St4200ReadRegisters(pThisDev, STIR4200_STATUS_REG, 1)) != STATUS_SUCCESS )
  129. {
  130. DEBUGMSG(DBG_ERR, (" St4200DoubleResetFifo(): USB failure\n"));
  131. goto done;
  132. }
  133. #endif
  134. pThisDev->StIrTranceiver.StatusReg |= STIR4200_STAT_FFCLR;
  135. if( (Status = St4200WriteRegister(pThisDev, STIR4200_STATUS_REG)) != STATUS_SUCCESS )
  136. {
  137. DEBUGMSG(DBG_ERR, (" St4200DoubleResetFifo(): USB failure\n"));
  138. goto done;
  139. }
  140. //
  141. // All back on
  142. //
  143. pThisDev->StIrTranceiver.StatusReg &= (~STIR4200_STAT_FFCLR);
  144. if( (Status = St4200WriteRegister(pThisDev, STIR4200_STATUS_REG)) != STATUS_SUCCESS )
  145. {
  146. DEBUGMSG(DBG_ERR, (" St4200DoubleResetFifo(): USB failure\n"));
  147. goto done;
  148. }
  149. if( (Status = St4200TurnOnReceiver( pThisDev ) ) != STATUS_SUCCESS )
  150. {
  151. DEBUGMSG(DBG_ERR, (" St4200DoubleResetFifo(): USB failure\n"));
  152. goto done;
  153. }
  154. done:
  155. return Status;
  156. }
  157. /*****************************************************************************
  158. *
  159. * Function: St4200SoftReset
  160. *
  161. * Synopsis: Soft reset of the STIr4200 modulator
  162. *
  163. * Arguments: pDevice - pointer to current ir device object
  164. *
  165. * Returns: NT_STATUS
  166. *
  167. *
  168. *****************************************************************************/
  169. NTSTATUS
  170. St4200SoftReset(
  171. IN PVOID pDevice
  172. )
  173. {
  174. NTSTATUS Status;
  175. PIR_DEVICE pThisDev = (PIR_DEVICE)pDevice;
  176. DEBUGMSG(DBG_INT_ERR, (" St4200SoftReset: Issuing a soft reset()\n"));
  177. // MS Security bug #538703
  178. IRUSB_ASSERT(pDevice != NULL);
  179. #if !defined(FAST_WRITE_REGISTERS)
  180. if( (Status = St4200ReadRegisters(pThisDev, STIR4200_CONTROL_REG, 1)) != STATUS_SUCCESS )
  181. {
  182. DEBUGMSG(DBG_ERR, (" St4200SoftReset(): USB failure\n"));
  183. goto done;
  184. }
  185. #endif
  186. //
  187. // Force a FIFO reset by clearing and setting again the RESET_OFF bit
  188. //
  189. pThisDev->StIrTranceiver.ControlReg |= STIR4200_CTRL_SRESET;
  190. if( (Status = St4200WriteRegister(pThisDev, STIR4200_CONTROL_REG)) != STATUS_SUCCESS )
  191. {
  192. DEBUGMSG(DBG_ERR, (" St4200SoftReset(): USB failure\n"));
  193. goto done;
  194. }
  195. pThisDev->StIrTranceiver.ControlReg &= (~STIR4200_CTRL_SRESET);
  196. if( (Status = St4200WriteRegister(pThisDev, STIR4200_CONTROL_REG)) != STATUS_SUCCESS )
  197. {
  198. DEBUGMSG(DBG_ERR, (" St4200SoftReset(): USB failure\n"));
  199. goto done;
  200. }
  201. done:
  202. return Status;
  203. }
  204. /*****************************************************************************
  205. *
  206. * Function: St4200SetIrMode
  207. *
  208. * Synopsis: Sets the STIr4200 to the proper operational mode
  209. *
  210. * Arguments: pDevice - pointer to current ir device object
  211. * mode - mode to set the tranceiver to
  212. *
  213. * Returns: NT_STATUS
  214. *
  215. *
  216. *****************************************************************************/
  217. NTSTATUS
  218. St4200SetIrMode(
  219. IN OUT PVOID pDevice,
  220. ULONG mode
  221. )
  222. {
  223. NTSTATUS Status;
  224. PIR_DEVICE pThisDev = (PIR_DEVICE)pDevice;
  225. // MS Security bug #538703
  226. IRUSB_ASSERT(pDevice != NULL);
  227. #if !defined(FAST_WRITE_REGISTERS)
  228. if( (Status = St4200ReadRegisters(pThisDev, STIR4200_MODE_REG, 1)) != STATUS_SUCCESS )
  229. {
  230. DEBUGMSG(DBG_ERR, (" St4200SetIrMode(): USB failure\n"));
  231. goto done;
  232. }
  233. #endif
  234. //
  235. // Remove all mode bits and set the proper mode
  236. //
  237. pThisDev->StIrTranceiver.ModeReg &= ~STIR4200_MODE_MASK;
  238. pThisDev->StIrTranceiver.ModeReg |= STIR4200_MODE_RESET_OFF;
  239. //
  240. // Enable the bug fixing feature for LA8
  241. //
  242. #if defined(SUPPORT_LA8)
  243. if( pThisDev->ChipRevision >= CHIP_REVISION_8 )
  244. {
  245. pThisDev->StIrTranceiver.ModeReg &= ~STIR4200_MODE_AUTO_RESET;
  246. pThisDev->StIrTranceiver.ModeReg &= ~STIR4200_MODE_BULKIN_FIX;
  247. }
  248. #endif
  249. switch( (IR_MODE)mode )
  250. {
  251. case IR_MODE_SIR:
  252. #if defined(WORKAROUND_CASIO)
  253. if( pThisDev->linkSpeedInfo->BitsPerSec != SPEED_9600 )
  254. #endif
  255. pThisDev->StIrTranceiver.ModeReg |= STIR4200_MODE_BULKIN_FIX;
  256. pThisDev->StIrTranceiver.ModeReg |= STIR4200_MODE_SIR;
  257. //pThisDev->StIrTranceiver.ModeReg |= STIR4200_MODE_ASK;
  258. break;
  259. #if !defined(WORKAROUND_BROKEN_MIR)
  260. case IR_MODE_MIR:
  261. pThisDev->MirIncompleteBitCount = 0;
  262. pThisDev->MirOneBitCount = 0;
  263. pThisDev->MirIncompleteByte = 0;
  264. pThisDev->MirFlagCount = 0;
  265. pThisDev->StIrTranceiver.ModeReg |= STIR4200_MODE_MIR;
  266. break;
  267. #endif
  268. case IR_MODE_FIR:
  269. pThisDev->StIrTranceiver.ModeReg |= STIR4200_MODE_FIR;
  270. #if defined(SUPPORT_LA8)
  271. if( pThisDev->ChipRevision >= CHIP_REVISION_8 )
  272. {
  273. pThisDev->StIrTranceiver.ModeReg |= STIR4200_MODE_BULKIN_FIX;
  274. pThisDev->StIrTranceiver.ModeReg |= STIR4200_MODE_AUTO_RESET;
  275. }
  276. #endif
  277. break;
  278. default:
  279. IRUSB_ASSERT( 0 );
  280. }
  281. #ifdef NO_BULKIN_FIX
  282. // force clear of mode reg bit 3
  283. pThisDev->StIrTranceiver.ModeReg &= ~STIR4200_MODE_BULKIN_FIX;
  284. #endif
  285. if( (Status = St4200WriteRegister(pThisDev, STIR4200_MODE_REG) ) != STATUS_SUCCESS )
  286. {
  287. DEBUGMSG(DBG_ERR, (" St4200SetIrMode(): USB failure\n"));
  288. goto done;
  289. }
  290. /***********************************************/
  291. /* Set TEMIC transceiver... */
  292. /***********************************************/
  293. #if !defined(FAST_WRITE_REGISTERS)
  294. if( (Status = St4200ReadRegisters(pThisDev, STIR4200_CONTROL_REG, 1)) != STATUS_SUCCESS )
  295. {
  296. DEBUGMSG(DBG_ERR, (" St4200SetIrMode(): USB failure\n"));
  297. goto done;
  298. }
  299. #endif
  300. pThisDev->StIrTranceiver.ControlReg |= STIR4200_CTRL_SDMODE;
  301. if( (Status = St4200WriteRegister(pThisDev, STIR4200_CONTROL_REG)) != STATUS_SUCCESS )
  302. {
  303. DEBUGMSG(DBG_ERR, (" St4200SetIrMode(): USB failure\n"));
  304. goto done;
  305. }
  306. #if !defined(FAST_WRITE_REGISTERS)
  307. if( (Status = St4200ReadRegisters(pThisDev, STIR4200_CONTROL_REG, 1)) != STATUS_SUCCESS )
  308. {
  309. DEBUGMSG(DBG_ERR, (" St4200SetIrMode(): USB failure\n"));
  310. goto done;
  311. }
  312. #endif
  313. pThisDev->StIrTranceiver.ControlReg &= (~STIR4200_CTRL_SDMODE);
  314. if( (Status = St4200WriteRegister(pThisDev, STIR4200_CONTROL_REG)) != STATUS_SUCCESS )
  315. {
  316. DEBUGMSG(DBG_ERR, (" St4200SetIrMode(): USB failure\n"));
  317. goto done;
  318. }
  319. done:
  320. return Status;
  321. }
  322. /*****************************************************************************
  323. *
  324. * Function: St4200SetSpeed
  325. *
  326. * Synopsis: Sets the STIr4200 speed
  327. *
  328. * Arguments: pDevice - pointer to current ir device object
  329. *
  330. * Returns: NT_STATUS
  331. *
  332. *
  333. *****************************************************************************/
  334. NTSTATUS
  335. St4200SetSpeed(
  336. IN OUT PVOID pDevice
  337. )
  338. {
  339. NTSTATUS Status = STATUS_SUCCESS;
  340. PIR_DEVICE pThisDev = (PIR_DEVICE)pDevice;
  341. // MS Security bug #538703
  342. IRUSB_ASSERT(pDevice != NULL);
  343. //
  344. // MS Security bug #539173
  345. // These log files need either ACLs restricted to Admin, or need
  346. // to be put in a admin directory. For now we are punting on this because
  347. // logging is NEVER turned on in a driver that is released to customers.
  348. //
  349. #define RECEIVE_LOG_FILE_NAME L"\\DosDevices\\c:\\receive.log"
  350. #define RECEIVE_ERR_LOG_FILE_NAME L"\\DosDevices\\c:\\receive_error.log"
  351. #define SEND_LOG_FILE_NAME L"\\DosDevices\\c:\\send.log"
  352. #if defined(RECEIVE_LOGGING)
  353. if( pThisDev->linkSpeedInfo->BitsPerSec==SPEED_4000000 )
  354. {
  355. IO_STATUS_BLOCK IoStatusBlock;
  356. OBJECT_ATTRIBUTES ObjectAttributes;
  357. UNICODE_STRING FileName;
  358. NTSTATUS Status;
  359. RtlInitUnicodeString(&FileName, RECEIVE_LOG_FILE_NAME);
  360. InitializeObjectAttributes(
  361. &ObjectAttributes,
  362. &FileName,
  363. // MS Security bug #539151
  364. OBJ_CASE_INSENSITIVE || OBJ_KERNEL_HANDLE,
  365. NULL,
  366. NULL
  367. );
  368. // MS Security bug #539093
  369. if( pThisDev->ReceiveFileHandle )
  370. {
  371. ZwClose( pThisDev->ReceiveFileHandle );
  372. }
  373. Status=ZwCreateFile(
  374. &pThisDev->ReceiveFileHandle,
  375. GENERIC_WRITE | SYNCHRONIZE,
  376. &ObjectAttributes,
  377. &IoStatusBlock,
  378. 0,
  379. FILE_ATTRIBUTE_NORMAL,
  380. FILE_SHARE_READ,
  381. FILE_OVERWRITE_IF,
  382. FILE_SYNCHRONOUS_IO_NONALERT,
  383. NULL,
  384. 0
  385. );
  386. pThisDev->ReceiveFilePosition = 0;
  387. }
  388. else
  389. {
  390. if( pThisDev->ReceiveFileHandle )
  391. {
  392. ZwClose( pThisDev->ReceiveFileHandle );
  393. pThisDev->ReceiveFileHandle = 0;
  394. pThisDev->ReceiveFilePosition = 0;
  395. }
  396. }
  397. #endif
  398. #if defined(RECEIVE_ERROR_LOGGING)
  399. if( pThisDev->linkSpeedInfo->BitsPerSec==SPEED_4000000 )
  400. {
  401. IO_STATUS_BLOCK IoStatusBlock;
  402. OBJECT_ATTRIBUTES ObjectAttributes;
  403. UNICODE_STRING FileName;
  404. NTSTATUS Status;
  405. RtlInitUnicodeString(&FileName, RECEIVE_ERR_LOG_FILE_NAME);
  406. InitializeObjectAttributes(
  407. &ObjectAttributes,
  408. &FileName,
  409. // MS Security bug #539151
  410. OBJ_CASE_INSENSITIVE || OBJ_KERNEL_HANDLE,
  411. NULL,
  412. NULL
  413. );
  414. // MS Security bug #539093
  415. if( pThisDev->ReceiveErrorFileHandle )
  416. {
  417. ZwClose( pThisDev->ReceiveErrorFileHandle );
  418. }
  419. Status=ZwCreateFile(
  420. &pThisDev->ReceiveErrorFileHandle,
  421. GENERIC_WRITE | SYNCHRONIZE,
  422. &ObjectAttributes,
  423. &IoStatusBlock,
  424. 0,
  425. FILE_ATTRIBUTE_NORMAL,
  426. FILE_SHARE_READ,
  427. FILE_OVERWRITE_IF,
  428. FILE_SYNCHRONOUS_IO_NONALERT,
  429. NULL,
  430. 0
  431. );
  432. pThisDev->ReceiveErrorFilePosition = 0;
  433. }
  434. else
  435. {
  436. if( pThisDev->ReceiveErrorFileHandle )
  437. {
  438. ZwClose( pThisDev->ReceiveErrorFileHandle );
  439. pThisDev->ReceiveErrorFileHandle = 0;
  440. pThisDev->ReceiveErrorFilePosition = 0;
  441. }
  442. }
  443. #endif
  444. #if defined(SEND_LOGGING)
  445. if( pThisDev->linkSpeedInfo->BitsPerSec==SPEED_4000000 )
  446. {
  447. IO_STATUS_BLOCK IoStatusBlock;
  448. OBJECT_ATTRIBUTES ObjectAttributes;
  449. UNICODE_STRING FileName;
  450. NTSTATUS Status;
  451. RtlInitUnicodeString(&FileName, SEND_LOG_FILE_NAME);
  452. InitializeObjectAttributes(
  453. &ObjectAttributes,
  454. &FileName,
  455. // MS Security bug #539151
  456. OBJ_CASE_INSENSITIVE || OBJ_KERNEL_HANDLE,
  457. NULL,
  458. NULL
  459. );
  460. // MS Security bug #539093
  461. if( pThisDev->SendFileHandle )
  462. {
  463. ZwClose( pThisDev->SendFileHandle );
  464. }
  465. Status=ZwCreateFile(
  466. &pThisDev->SendFileHandle,
  467. GENERIC_WRITE | SYNCHRONIZE,
  468. &ObjectAttributes,
  469. &IoStatusBlock,
  470. 0,
  471. FILE_ATTRIBUTE_NORMAL,
  472. FILE_SHARE_READ,
  473. FILE_OVERWRITE_IF,
  474. FILE_SYNCHRONOUS_IO_NONALERT,
  475. NULL,
  476. 0
  477. );
  478. pThisDev->SendFilePosition = 0;
  479. }
  480. else
  481. {
  482. if( pThisDev->SendFileHandle )
  483. {
  484. ZwClose( pThisDev->SendFileHandle );
  485. pThisDev->SendFileHandle = 0;
  486. pThisDev->SendFilePosition = 0;
  487. }
  488. }
  489. #endif
  490. //
  491. // Always force a new tuning
  492. //
  493. if( (Status = St4200TuneDpllAndSensitivity(pThisDev, pThisDev->linkSpeedInfo->BitsPerSec)) != STATUS_SUCCESS )
  494. {
  495. DEBUGMSG(DBG_ERR, (" St4200TuneDpllAndSensitivity(): USB failure\n"));
  496. goto done;
  497. }
  498. //
  499. // First power down the modulator
  500. //
  501. /*
  502. #if !defined(FAST_WRITE_REGISTERS)
  503. if( (Status = St4200ReadRegisters(pThisDev, STIR4200_CONTROL_REG, 1)) != STATUS_SUCCESS )
  504. {
  505. DEBUGMSG(DBG_ERR, (" St4200SetSpeed(): USB failure\n"));
  506. goto done;
  507. }
  508. #endif
  509. pThisDev->StIrTranceiver.ControlReg |= (STIR4200_CTRL_TXPWD | STIR4200_CTRL_RXPWD);
  510. if( (Status = St4200WriteRegister(pThisDev, STIR4200_CONTROL_REG)) != STATUS_SUCCESS )
  511. {
  512. DEBUGMSG(DBG_ERR, (" St4200SetSpeed(): USB failure\n"));
  513. goto done;
  514. }*/
  515. //
  516. // Then set baudrate
  517. //
  518. pThisDev->StIrTranceiver.BaudrateReg = pThisDev->linkSpeedInfo->Stir4200Divisor;
  519. if( (Status = St4200WriteRegister(pThisDev, STIR4200_BAUDRATE_REG)) != STATUS_SUCCESS )
  520. {
  521. DEBUGMSG(DBG_ERR, (" St4200SetSpeed(): USB failure\n"));
  522. goto done;
  523. }
  524. //
  525. // We'll have to write the MSB of baud-rate too (only for 2400)
  526. //
  527. if( pThisDev->linkSpeedInfo->BitsPerSec == SPEED_2400 )
  528. {
  529. pThisDev->StIrTranceiver.ModeReg |= STIR4200_MODE_PDLCK8;
  530. if( (Status = St4200WriteRegister(pThisDev, STIR4200_MODE_REG)) != STATUS_SUCCESS )
  531. {
  532. DEBUGMSG(DBG_ERR, (" St4200SetSpeed(): USB failure\n"));
  533. goto done;
  534. }
  535. }
  536. else
  537. {
  538. if( pThisDev->StIrTranceiver.ModeReg & STIR4200_MODE_PDLCK8 )
  539. {
  540. pThisDev->StIrTranceiver.ModeReg &= ~STIR4200_MODE_PDLCK8;
  541. if( (Status = St4200WriteRegister(pThisDev, STIR4200_MODE_REG)) != STATUS_SUCCESS )
  542. {
  543. DEBUGMSG(DBG_ERR, (" St4200SetSpeed(): USB failure\n"));
  544. goto done;
  545. }
  546. }
  547. }
  548. //
  549. // Modulator back up
  550. //
  551. /*pThisDev->StIrTranceiver.ControlReg &= (~(STIR4200_CTRL_TXPWD | STIR4200_CTRL_RXPWD));
  552. if( (Status = St4200WriteRegister(pThisDev, STIR4200_CONTROL_REG)) != STATUS_SUCCESS )
  553. {
  554. DEBUGMSG(DBG_ERR, (" St4200SetSpeed(): USB failure\n"));
  555. goto done;
  556. }*/
  557. //
  558. // then IR mode
  559. //
  560. Status = St4200SetIrMode( pThisDev, pThisDev->linkSpeedInfo->IrMode );
  561. if( Status != STATUS_SUCCESS )
  562. {
  563. DEBUGMSG(DBG_ERR, (" St4200SetSpeed(): USB failure\n"));
  564. goto done;
  565. }
  566. //
  567. // optionally set the rx line
  568. //
  569. if( pThisDev->ReceiveMode == RXMODE_SLOWFAST )
  570. {
  571. if( pThisDev->linkSpeedInfo->BitsPerSec == SPEED_4000000 )
  572. {
  573. pThisDev->StIrTranceiver.ControlReg &= ~STIR4200_CTRL_RXSLOW;
  574. }
  575. else
  576. {
  577. pThisDev->StIrTranceiver.ControlReg |= STIR4200_CTRL_RXSLOW;
  578. }
  579. if( (Status = St4200WriteRegister(pThisDev, STIR4200_CONTROL_REG)) != STATUS_SUCCESS )
  580. {
  581. DEBUGMSG(DBG_ERR, (" St4200SetSpeed(): USB failure\n"));
  582. goto done;
  583. }
  584. }
  585. else if (pThisDev->ReceiveMode == RXMODE_SLOW )
  586. {
  587. pThisDev->StIrTranceiver.ControlReg |= STIR4200_CTRL_RXSLOW;
  588. if( (Status = St4200WriteRegister(pThisDev, STIR4200_CONTROL_REG)) != STATUS_SUCCESS )
  589. {
  590. DEBUGMSG(DBG_ERR, (" St4200SetSpeed(): USB failure\n"));
  591. goto done;
  592. }
  593. }
  594. //
  595. // Program the receive delay for FIR
  596. //
  597. if( pThisDev->linkSpeedInfo->BitsPerSec == SPEED_4000000 )
  598. {
  599. if( pThisDev->dongleCaps.windowSize == 2 )
  600. pThisDev->ReceiveAdaptiveDelay = STIR4200_MULTIPLE_READ_DELAY;
  601. else
  602. pThisDev->ReceiveAdaptiveDelay = 0;
  603. pThisDev->ReceiveAdaptiveDelayBoost = 0;
  604. }
  605. #if defined(WORKAROUND_GEAR_DOWN)
  606. //
  607. // Force a reset if going to 9600 from 4M
  608. //
  609. pThisDev->GearedDown = FALSE;
  610. if( pThisDev->linkSpeedInfo->BitsPerSec==SPEED_9600 && pThisDev->currentSpeed==SPEED_4000000 )
  611. {
  612. St4200ResetFifo( pThisDev );
  613. pThisDev->GearedDown = TRUE;
  614. }
  615. #endif
  616. done:
  617. return Status;
  618. }
  619. /*****************************************************************************
  620. *
  621. * Function: St4200GetFifoCount
  622. *
  623. * Synopsis: Verifies if there is data to be received
  624. *
  625. * Arguments: pDevice - pointer to current ir device object
  626. * pCountFifo - pointer to variable to return FIFO count
  627. *
  628. * Returns: NT_STATUS
  629. *
  630. *
  631. *****************************************************************************/
  632. NTSTATUS
  633. St4200GetFifoCount(
  634. IN PVOID pDevice,
  635. OUT PULONG pCountFifo
  636. )
  637. {
  638. NTSTATUS Status = STATUS_SUCCESS;
  639. PIR_DEVICE pThisDev = (PIR_DEVICE)pDevice;
  640. // MS Security bug #538703
  641. IRUSB_ASSERT(pDevice != NULL);
  642. IRUSB_ASSERT(pCountFifo != NULL);
  643. *pCountFifo = 0;
  644. if( pThisDev->PreFifoCount )
  645. {
  646. *pCountFifo = pThisDev->PreFifoCount;
  647. }
  648. else
  649. {
  650. Status = St4200ReadRegisters( pThisDev, STIR4200_FIFOCNT_LSB_REG, 2 );
  651. if( Status == STATUS_SUCCESS )
  652. {
  653. *pCountFifo =
  654. ((ULONG)MAKEUSHORT(pThisDev->StIrTranceiver.FifoCntLsbReg, pThisDev->StIrTranceiver.FifoCntMsbReg));
  655. }
  656. }
  657. pThisDev->PreFifoCount = 0;
  658. return Status;
  659. }
  660. /*****************************************************************************
  661. *
  662. * Function: St4200TuneDpllAndSensitivity
  663. *
  664. * Synopsis: tunes the DPLL and sensitivity registers
  665. *
  666. * Arguments: pDevice - pointer to current ir device object
  667. * Speed - speed to tune for
  668. *
  669. * Returns: NT_STATUS
  670. *
  671. *
  672. *****************************************************************************/
  673. NTSTATUS
  674. St4200TuneDpllAndSensitivity(
  675. IN OUT PVOID pDevice,
  676. ULONG Speed
  677. )
  678. {
  679. NTSTATUS Status;
  680. PIR_DEVICE pThisDev = (PIR_DEVICE)pDevice;
  681. // MS Security bug #538703
  682. IRUSB_ASSERT(pDevice != NULL);
  683. #if !defined(FAST_WRITE_REGISTERS)
  684. //
  685. // Read the current value of the DPLL
  686. //
  687. if( (Status = St4200ReadRegisters(pThisDev, STIR4200_DPLLTUNE_REG, 1)) != STATUS_SUCCESS )
  688. {
  689. DEBUGMSG(DBG_ERR, (" St4200TuneDpllAndSensitivity(): USB failure\n"));
  690. goto done;
  691. }
  692. #endif
  693. //
  694. // Tune the DPLL according to the installed transceiver
  695. //
  696. switch( pThisDev->TransceiverType )
  697. {
  698. case TRANSCEIVER_HP:
  699. pThisDev->StIrTranceiver.DpllTuneReg = STIR4200_DPLL_DESIRED_HP;
  700. break;
  701. case TRANSCEIVER_INFINEON:
  702. pThisDev->StIrTranceiver.DpllTuneReg = STIR4200_DPLL_DESIRED_INFI;
  703. break;
  704. case TRANSCEIVER_VISHAY:
  705. pThisDev->StIrTranceiver.DpllTuneReg = STIR4200_DPLL_DESIRED_VISHAY;
  706. break;
  707. case TRANSCEIVER_VISHAY_6102F:
  708. pThisDev->StIrTranceiver.DpllTuneReg = STIR4200_DPLL_DESIRED_VISHAY_6102F;
  709. break;
  710. case TRANSCEIVER_4000:
  711. pThisDev->StIrTranceiver.DpllTuneReg = STIR4200_DPLL_DESIRED_4000;
  712. break;
  713. case TRANSCEIVER_4012:
  714. switch( Speed )
  715. {
  716. case SPEED_9600:
  717. case SPEED_19200:
  718. case SPEED_38400:
  719. case SPEED_57600:
  720. case SPEED_115200:
  721. pThisDev->StIrTranceiver.DpllTuneReg = STIR4200_DPLL_DESIRED_4012_SIR;
  722. break;
  723. case SPEED_4000000:
  724. pThisDev->StIrTranceiver.DpllTuneReg = STIR4200_DPLL_DESIRED_4012_FIR;
  725. break;
  726. default:
  727. pThisDev->StIrTranceiver.DpllTuneReg = STIR4200_DPLL_DESIRED_4012;
  728. break;
  729. }
  730. break;
  731. case TRANSCEIVER_CUSTOM:
  732. default:
  733. switch( Speed )
  734. {
  735. case SPEED_9600:
  736. case SPEED_19200:
  737. case SPEED_38400:
  738. case SPEED_57600:
  739. case SPEED_115200:
  740. #if defined(VARIABLE_SETTINGS)
  741. pThisDev->StIrTranceiver.DpllTuneReg = (UCHAR)pThisDev->SirDpll;
  742. #else
  743. pThisDev->StIrTranceiver.DpllTuneReg = STIR4200_DPLL_DESIRED_CUSTOM_SIR;
  744. #endif
  745. break;
  746. case SPEED_4000000:
  747. #if defined(VARIABLE_SETTINGS)
  748. pThisDev->StIrTranceiver.DpllTuneReg = (UCHAR)pThisDev->FirDpll;
  749. #else
  750. pThisDev->StIrTranceiver.DpllTuneReg = STIR4200_DPLL_DESIRED_CUSTOM_FIR;
  751. #endif
  752. break;
  753. default:
  754. pThisDev->StIrTranceiver.DpllTuneReg = STIR4200_DPLL_DESIRED_CUSTOM;
  755. break;
  756. }
  757. break;
  758. }
  759. if( (Status = St4200WriteRegister(pThisDev, STIR4200_DPLLTUNE_REG)) != STATUS_SUCCESS )
  760. {
  761. DEBUGMSG(DBG_ERR, (" St4200TuneDpllAndSensitivity(): USB failure\n"));
  762. goto done;
  763. }
  764. #if !defined(FAST_WRITE_REGISTERS)
  765. //
  766. // Read the current value of the sensitivity
  767. //
  768. if( (Status = St4200ReadRegisters(pThisDev, STIR4200_SENSITIVITY_REG, 1)) != STATUS_SUCCESS )
  769. {
  770. DEBUGMSG(DBG_ERR, (" St4200TuneDpllAndSensitivity(): USB failure\n"));
  771. goto done;
  772. }
  773. #endif
  774. //
  775. // Tune the sensitivity
  776. //
  777. switch( pThisDev->TransceiverType )
  778. {
  779. case TRANSCEIVER_HP:
  780. switch( Speed )
  781. {
  782. default:
  783. case SPEED_9600:
  784. case SPEED_19200:
  785. case SPEED_38400:
  786. case SPEED_57600:
  787. case SPEED_115200:
  788. pThisDev->StIrTranceiver.SensitivityReg = STIR4200_SENS_RXDSNS_HP_SIR;
  789. break;
  790. case SPEED_4000000:
  791. pThisDev->StIrTranceiver.SensitivityReg = STIR4200_SENS_RXDSNS_HP_FIR;
  792. break;
  793. }
  794. break;
  795. case TRANSCEIVER_INFINEON:
  796. switch( Speed )
  797. {
  798. default:
  799. case SPEED_9600:
  800. case SPEED_19200:
  801. case SPEED_38400:
  802. case SPEED_57600:
  803. case SPEED_115200:
  804. pThisDev->StIrTranceiver.SensitivityReg = STIR4200_SENS_RXDSNS_INFI_SIR;
  805. break;
  806. case SPEED_4000000:
  807. pThisDev->StIrTranceiver.SensitivityReg = STIR4200_SENS_RXDSNS_INFI_FIR;
  808. break;
  809. }
  810. break;
  811. case TRANSCEIVER_VISHAY_6102F:
  812. switch( Speed )
  813. {
  814. default:
  815. case SPEED_9600:
  816. case SPEED_19200:
  817. case SPEED_38400:
  818. case SPEED_57600:
  819. case SPEED_115200:
  820. pThisDev->StIrTranceiver.SensitivityReg = STIR4200_SENS_RXDSNS_VISHAY_6102F_SIR;
  821. break;
  822. case SPEED_4000000:
  823. pThisDev->StIrTranceiver.SensitivityReg = STIR4200_SENS_RXDSNS_VISHAY_6102F_FIR;
  824. break;
  825. }
  826. break;
  827. case TRANSCEIVER_VISHAY:
  828. pThisDev->StIrTranceiver.SensitivityReg = STIR4200_SENS_RXDSNS_DEFAULT;
  829. break;
  830. case TRANSCEIVER_4000:
  831. pThisDev->StIrTranceiver.SensitivityReg = STIR4200_SENS_RXDSNS_DEFAULT;
  832. break;
  833. case TRANSCEIVER_4012:
  834. switch( Speed )
  835. {
  836. default:
  837. case SPEED_9600:
  838. pThisDev->StIrTranceiver.SensitivityReg = STIR4200_SENS_RXDSNS_4012_SIR_9600;
  839. break;
  840. case SPEED_19200:
  841. case SPEED_38400:
  842. case SPEED_57600:
  843. case SPEED_115200:
  844. pThisDev->StIrTranceiver.SensitivityReg = STIR4200_SENS_RXDSNS_4012_SIR;
  845. break;
  846. case SPEED_4000000:
  847. pThisDev->StIrTranceiver.SensitivityReg = STIR4200_SENS_RXDSNS_4012_FIR;
  848. break;
  849. }
  850. break;
  851. case TRANSCEIVER_CUSTOM:
  852. default:
  853. switch( Speed )
  854. {
  855. default:
  856. case SPEED_9600:
  857. #if defined(VARIABLE_SETTINGS)
  858. pThisDev->StIrTranceiver.SensitivityReg = (UCHAR)pThisDev->SirSensitivity;
  859. #else
  860. pThisDev->StIrTranceiver.SensitivityReg = STIR4200_SENS_RXDSNS_CUSTOM_SIR_9600;
  861. #endif
  862. break;
  863. case SPEED_19200:
  864. case SPEED_38400:
  865. case SPEED_57600:
  866. case SPEED_115200:
  867. #if defined(VARIABLE_SETTINGS)
  868. pThisDev->StIrTranceiver.SensitivityReg = (UCHAR)pThisDev->SirSensitivity;
  869. #else
  870. pThisDev->StIrTranceiver.SensitivityReg = STIR4200_SENS_RXDSNS_CUSTOM_SIR;
  871. #endif
  872. break;
  873. case SPEED_4000000:
  874. #if defined(VARIABLE_SETTINGS)
  875. pThisDev->StIrTranceiver.SensitivityReg = (UCHAR)pThisDev->FirSensitivity;
  876. #else
  877. pThisDev->StIrTranceiver.SensitivityReg = STIR4200_SENS_RXDSNS_CUSTOM_FIR;
  878. #endif
  879. break;
  880. }
  881. break;
  882. }
  883. if( (Status = St4200WriteRegister(pThisDev, STIR4200_SENSITIVITY_REG)) != STATUS_SUCCESS )
  884. {
  885. DEBUGMSG(DBG_ERR, (" St4200TuneDpllAndSensitivity(): USB failure\n"));
  886. goto done;
  887. }
  888. done:
  889. return Status;
  890. }
  891. /*****************************************************************************
  892. *
  893. * Function: St4200EnableOscillatorPowerDown
  894. *
  895. * Synopsis: enable the oscillator to power down when we go into suspend mode
  896. *
  897. * Arguments: pDevice - pointer to current ir device object
  898. *
  899. * Returns: NT_STATUS
  900. *
  901. *
  902. *****************************************************************************/
  903. NTSTATUS
  904. St4200EnableOscillatorPowerDown(
  905. IN OUT PVOID pDevice
  906. )
  907. {
  908. NTSTATUS Status;
  909. PIR_DEVICE pThisDev = (PIR_DEVICE)pDevice;
  910. // MS Security bug #538703
  911. IRUSB_ASSERT(pDevice != NULL);
  912. #if !defined(FAST_WRITE_REGISTERS)
  913. //
  914. // Read the current value
  915. //
  916. if( (Status = St4200ReadRegisters(pThisDev, pThisDev, 1)) != STATUS_SUCCESS )
  917. {
  918. DEBUGMSG(DBG_ERR, (" St4200EnableOscillatorPowerDown(): USB failure\n"));
  919. goto done;
  920. }
  921. #endif
  922. //
  923. // Enable
  924. //
  925. pThisDev->StIrTranceiver.TestReg |= STIR4200_TEST_EN_OSC_SUSPEND;
  926. if( (Status = St4200WriteRegister(pThisDev, STIR4200_TEST_REG)) != STATUS_SUCCESS )
  927. {
  928. DEBUGMSG(DBG_ERR, (" St4200EnableOscillatorPowerDown(): USB failure\n"));
  929. goto done;
  930. }
  931. done:
  932. return Status;
  933. }
  934. /*****************************************************************************
  935. *
  936. * Function: St4200TurnOnSuspend
  937. *
  938. * Synopsis: prepares the part to go into suspend mode
  939. *
  940. * Arguments: pDevice - pointer to current ir device object
  941. *
  942. * Returns: NT_STATUS
  943. *
  944. *
  945. *****************************************************************************/
  946. NTSTATUS
  947. St4200TurnOnSuspend(
  948. IN OUT PVOID pDevice
  949. )
  950. {
  951. NTSTATUS Status;
  952. PIR_DEVICE pThisDev = (PIR_DEVICE)pDevice;
  953. // MS Security bug #538703
  954. IRUSB_ASSERT(pDevice != NULL);
  955. #if !defined(FAST_WRITE_REGISTERS)
  956. //
  957. // Read the current value
  958. //
  959. if( (Status = St4200ReadRegisters(pThisDev, STIR4200_CONTROL_REG, 1)) != STATUS_SUCCESS )
  960. {
  961. DEBUGMSG(DBG_ERR, (" St4200TurnOnSuspend(): USB failure\n"));
  962. goto done;
  963. }
  964. #endif
  965. //
  966. // Control UOUT
  967. //
  968. pThisDev->StIrTranceiver.ControlReg |= STIR4200_CTRL_SDMODE;
  969. if( (Status = St4200WriteRegister(pThisDev, STIR4200_CONTROL_REG)) != STATUS_SUCCESS )
  970. {
  971. DEBUGMSG(DBG_ERR, (" St4200TurnOnSuspend(): USB failure\n"));
  972. goto done;
  973. }
  974. done:
  975. return Status;
  976. }
  977. /*****************************************************************************
  978. *
  979. * Function: St4200TurnOffSuspend
  980. *
  981. * Synopsis: prepares the part to go back into operational mode
  982. *
  983. * Arguments: pDevice - pointer to current ir device object
  984. *
  985. * Returns: NT_STATUS
  986. *
  987. *
  988. *****************************************************************************/
  989. NTSTATUS
  990. St4200TurnOffSuspend(
  991. IN OUT PVOID pDevice
  992. )
  993. {
  994. NTSTATUS Status;
  995. PIR_DEVICE pThisDev = (PIR_DEVICE)pDevice;
  996. // MS Security bug #538703
  997. IRUSB_ASSERT(pDevice != NULL);
  998. #if !defined(FAST_WRITE_REGISTERS)
  999. //
  1000. // Read the current value
  1001. //
  1002. if( (Status = St4200ReadRegisters(pThisDev, STIR4200_CONTROL_REG, 1)) != STATUS_SUCCESS )
  1003. {
  1004. DEBUGMSG(DBG_ERR, (" St4200TurnOffSuspend(): USB failure\n"));
  1005. goto done;
  1006. }
  1007. #endif
  1008. //
  1009. // Control UOUT
  1010. //
  1011. pThisDev->StIrTranceiver.ControlReg &= ~STIR4200_CTRL_SDMODE;
  1012. if( (Status = St4200WriteRegister(pThisDev, STIR4200_CONTROL_REG)) != STATUS_SUCCESS )
  1013. {
  1014. DEBUGMSG(DBG_ERR, (" St4200TurnOffSuspend(): USB failure\n"));
  1015. goto done;
  1016. }
  1017. done:
  1018. return Status;
  1019. }
  1020. /*****************************************************************************
  1021. *
  1022. * Function: St4200TurnOffReceiver
  1023. *
  1024. * Synopsis: turns of the STIr4200 receiver
  1025. *
  1026. * Arguments: pDevice - pointer to current ir device object
  1027. *
  1028. * Returns: NT_STATUS
  1029. *
  1030. *
  1031. *****************************************************************************/
  1032. NTSTATUS
  1033. St4200TurnOffReceiver(
  1034. IN OUT PVOID pDevice
  1035. )
  1036. {
  1037. NTSTATUS Status;
  1038. PIR_DEVICE pThisDev = (PIR_DEVICE)pDevice;
  1039. // MS Security bug #538703
  1040. IRUSB_ASSERT(pDevice != NULL);
  1041. #if !defined(FAST_WRITE_REGISTERS)
  1042. //
  1043. // Read the current value
  1044. //
  1045. if( (Status = St4200ReadRegisters(pThisDev, STIR4200_CONTROL_REG, 1)) != STATUS_SUCCESS )
  1046. {
  1047. DEBUGMSG(DBG_ERR, (" St4200TurnOffReceiver(): USB failure\n"));
  1048. goto done;
  1049. }
  1050. #endif
  1051. //
  1052. // Turn off receiver
  1053. //
  1054. pThisDev->StIrTranceiver.ControlReg |= STIR4200_CTRL_RXPWD;
  1055. if( (Status = St4200WriteRegister(pThisDev, STIR4200_CONTROL_REG)) != STATUS_SUCCESS )
  1056. {
  1057. DEBUGMSG(DBG_ERR, (" St4200TurnOffReceiver(): USB failure\n"));
  1058. goto done;
  1059. }
  1060. done:
  1061. return Status;
  1062. }
  1063. /*****************************************************************************
  1064. *
  1065. * Function: St4200TurnOnReceiver
  1066. *
  1067. * Synopsis: turns on the STIr4200 receiver
  1068. *
  1069. * Arguments: pDevice - pointer to current ir device object
  1070. *
  1071. * Returns: NT_STATUS
  1072. *
  1073. *
  1074. *****************************************************************************/
  1075. NTSTATUS
  1076. St4200TurnOnReceiver(
  1077. IN OUT PVOID pDevice
  1078. )
  1079. {
  1080. NTSTATUS Status;
  1081. PIR_DEVICE pThisDev = (PIR_DEVICE)pDevice;
  1082. // MS Security bug #538703
  1083. IRUSB_ASSERT(pDevice != NULL);
  1084. #if !defined(FAST_WRITE_REGISTERS)
  1085. //
  1086. // Read the current value
  1087. //
  1088. if( (Status = St4200ReadRegisters(pThisDev, STIR4200_CONTROL_REG, 1)) != STATUS_SUCCESS )
  1089. {
  1090. DEBUGMSG(DBG_ERR, (" St4200TurnOnReceiver(): USB failure\n"));
  1091. goto done;
  1092. }
  1093. #endif
  1094. //
  1095. // Turn on receiver
  1096. //
  1097. pThisDev->StIrTranceiver.ControlReg &= ~STIR4200_CTRL_RXPWD;
  1098. if( (Status = St4200WriteRegister(pThisDev, STIR4200_CONTROL_REG)) != STATUS_SUCCESS )
  1099. {
  1100. DEBUGMSG(DBG_ERR, (" St4200TurnOnReceiver(): USB failure\n"));
  1101. goto done;
  1102. }
  1103. done:
  1104. return Status;
  1105. }
  1106. /*****************************************************************************
  1107. *
  1108. * Function: St4200WriteMultipleRegisters
  1109. *
  1110. * Synopsis: reads multiple registers from the tranceiver
  1111. *
  1112. * Arguments: pDevice - pointer to current ir device object
  1113. * FirstRegister - first register to write
  1114. * RegistersToWrite - number of registers
  1115. *
  1116. * Returns: NT_STATUS
  1117. *
  1118. *
  1119. *****************************************************************************/
  1120. NTSTATUS
  1121. St4200WriteMultipleRegisters(
  1122. IN PVOID pDevice,
  1123. UCHAR FirstRegister,
  1124. UCHAR RegistersToWrite
  1125. )
  1126. {
  1127. NTSTATUS status = STATUS_SUCCESS;
  1128. PIRUSB_CONTEXT pThisContext;
  1129. PURB pUrb = NULL;
  1130. PDEVICE_OBJECT pUrbTargetDev;
  1131. PIO_STACK_LOCATION pNextStack;
  1132. PIRP pIrp;
  1133. PIR_DEVICE pThisDev = (PIR_DEVICE)pDevice;
  1134. PLIST_ENTRY pListEntry;
  1135. DEBUGMSG(DBG_FUNC, ("+St4200WriteMultipleRegisters\n"));
  1136. // MS Security bug #538703
  1137. IRUSB_ASSERT(pDevice != NULL);
  1138. IRUSB_ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );
  1139. //
  1140. // Make sure there isn't a halt/reset going on
  1141. //
  1142. if( pThisDev->fPendingHalt || pThisDev->fPendingReset || pThisDev->fPendingClearTotalStall )
  1143. {
  1144. DEBUGMSG(DBG_ERR, (" St4200WriteMultipleRegisters abort due to pending reset\n"));
  1145. status = STATUS_UNSUCCESSFUL;
  1146. goto done;
  1147. }
  1148. //
  1149. // Validate the parameters
  1150. //
  1151. if( (FirstRegister+RegistersToWrite)>(STIR4200_MAX_REG+1) )
  1152. {
  1153. DEBUGMSG(DBG_ERR, (" St4200WriteMultipleRegisters invalid input parameters\n"));
  1154. status = STATUS_UNSUCCESSFUL;
  1155. goto done;
  1156. }
  1157. pListEntry = ExInterlockedRemoveHeadList( &pThisDev->SendAvailableQueue, &pThisDev->SendLock );
  1158. if( NULL == pListEntry )
  1159. {
  1160. //
  1161. // This must not happen
  1162. //
  1163. DEBUGMSG(DBG_ERR, (" St4200WriteMultipleRegisters failed to find a free context struct\n"));
  1164. IRUSB_ASSERT( 0 );
  1165. status = STATUS_UNSUCCESSFUL;
  1166. goto done;
  1167. }
  1168. InterlockedDecrement( &pThisDev->SendAvailableCount );
  1169. pThisContext = CONTAINING_RECORD( pListEntry, IRUSB_CONTEXT, ListEntry );
  1170. pThisContext->ContextType = CONTEXT_READ_WRITE_REGISTER;
  1171. //
  1172. // MS Security recommendation - allocate a new urb.
  1173. //
  1174. pThisContext->UrbLen = sizeof( struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST );
  1175. pThisContext->pUrb = MyUrbAlloc(pThisContext->UrbLen);
  1176. if (pThisContext->pUrb == NULL)
  1177. {
  1178. DEBUGMSG(DBG_ERR, (" St4200WriteMultipleRegisters abort due to urb alloc failure\n"));
  1179. goto done;
  1180. }
  1181. pUrb = pThisContext->pUrb;
  1182. //
  1183. // Now that we have created the urb, we will send a
  1184. // request to the USB device object.
  1185. //
  1186. pUrbTargetDev = pThisDev->pUsbDevObj;
  1187. //
  1188. // make an irp sending to usbhub
  1189. //
  1190. pIrp = IoAllocateIrp( (CCHAR)(pThisDev->pUsbDevObj->StackSize + 1), FALSE );
  1191. if( NULL == pIrp )
  1192. {
  1193. DEBUGMSG(DBG_ERR, (" St4200WriteMultipleRegisters failed to alloc IRP\n"));
  1194. ExInterlockedInsertTailList(
  1195. &pThisDev->SendAvailableQueue,
  1196. &pThisContext->ListEntry,
  1197. &pThisDev->SendLock
  1198. );
  1199. InterlockedIncrement( &pThisDev->SendAvailableCount );
  1200. MyUrbFree(pThisContext->pUrb, pThisContext->UrbLen);
  1201. pThisContext->pUrb = NULL;
  1202. status = STATUS_UNSUCCESSFUL;
  1203. goto done;
  1204. }
  1205. pIrp->IoStatus.Status = STATUS_PENDING;
  1206. pIrp->IoStatus.Information = 0;
  1207. pThisContext->pIrp = pIrp;
  1208. //
  1209. // Build our URB for USBD
  1210. //
  1211. pUrb->UrbControlVendorClassRequest.Hdr.Length = (USHORT)sizeof( struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST );
  1212. pUrb->UrbControlVendorClassRequest.Hdr.Function = URB_FUNCTION_VENDOR_DEVICE;
  1213. pUrb->UrbControlVendorClassRequest.TransferFlags = USBD_TRANSFER_DIRECTION_OUT;
  1214. // short packet is not treated as an error.
  1215. pUrb->UrbControlVendorClassRequest.TransferFlags |= USBD_SHORT_TRANSFER_OK;
  1216. pUrb->UrbControlVendorClassRequest.UrbLink = NULL;
  1217. pUrb->UrbControlVendorClassRequest.TransferBufferMDL = NULL;
  1218. pUrb->UrbControlVendorClassRequest.TransferBuffer = &(pThisDev->StIrTranceiver.FifoDataReg)+FirstRegister;
  1219. pUrb->UrbControlVendorClassRequest.TransferBufferLength = RegistersToWrite;
  1220. pUrb->UrbControlVendorClassRequest.Request = STIR4200_WRITE_REGS_REQ;
  1221. pUrb->UrbControlVendorClassRequest.RequestTypeReservedBits = 0;
  1222. pUrb->UrbControlVendorClassRequest.Index = FirstRegister;
  1223. //
  1224. // Call the class driver to perform the operation.
  1225. //
  1226. pNextStack = IoGetNextIrpStackLocation( pIrp );
  1227. IRUSB_ASSERT( pNextStack != NULL );
  1228. //
  1229. // pass the URB to the USB driver stack
  1230. //
  1231. pNextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  1232. pNextStack->Parameters.Others.Argument1 = pUrb;
  1233. pNextStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
  1234. IoSetCompletionRoutine(
  1235. pIrp, // irp to use
  1236. St4200CompleteReadWriteRequest, // routine to call when irp is done
  1237. DEV_TO_CONTEXT(pThisContext), // context to pass routine
  1238. TRUE, // call on success
  1239. TRUE, // call on error
  1240. TRUE // call on cancel
  1241. );
  1242. KeClearEvent( &pThisDev->EventSyncUrb );
  1243. //
  1244. // Call IoCallDriver to send the irp to the usb port.
  1245. //
  1246. ExInterlockedInsertTailList(
  1247. &pThisDev->ReadWritePendingQueue,
  1248. &pThisContext->ListEntry,
  1249. &pThisDev->SendLock
  1250. );
  1251. InterlockedIncrement( &pThisDev->ReadWritePendingCount );
  1252. status = MyIoCallDriver( pThisDev, pUrbTargetDev, pIrp );
  1253. //
  1254. // The USB driver should always return STATUS_PENDING when
  1255. // it receives a write irp
  1256. //
  1257. if( (status == STATUS_PENDING) || (status == STATUS_SUCCESS) )
  1258. {
  1259. // wait, but dump out on timeout
  1260. if( status == STATUS_PENDING )
  1261. {
  1262. status = MyKeWaitForSingleObject( pThisDev, &pThisDev->EventSyncUrb, 0 );
  1263. if( status == STATUS_TIMEOUT )
  1264. {
  1265. KIRQL OldIrql;
  1266. DEBUGMSG( DBG_ERR,(" St4200WriteMultipleRegisters() TIMED OUT! return from IoCallDriver USBD %x\n", status));
  1267. KeAcquireSpinLock( &pThisDev->SendLock, &OldIrql );
  1268. RemoveEntryList( &pThisContext->ListEntry );
  1269. KeReleaseSpinLock( &pThisDev->SendLock, OldIrql );
  1270. InterlockedDecrement( &pThisDev->ReadWritePendingCount );
  1271. // MS Security recommendation - cannot cancel IRP.
  1272. }
  1273. }
  1274. }
  1275. else
  1276. {
  1277. DEBUGMSG( DBG_ERR, (" St4200WriteMultipleRegisters IoCallDriver FAILED(%x)\n",status));
  1278. IRUSB_ASSERT( status == STATUS_PENDING );
  1279. }
  1280. done:
  1281. DEBUGMSG(DBG_FUNC, ("-St4200WriteMultipleRegisters\n"));
  1282. return status;
  1283. }
  1284. /*****************************************************************************
  1285. *
  1286. * Function: St4200WriteRegister
  1287. *
  1288. * Synopsis: writes a STIr4200 register
  1289. *
  1290. * Arguments: pDevice - pointer to current ir device object
  1291. * FirstRegister - first register to write
  1292. *
  1293. * Returns: NT_STATUS
  1294. *
  1295. *
  1296. *****************************************************************************/
  1297. NTSTATUS
  1298. St4200WriteRegister(
  1299. IN PVOID pDevice,
  1300. UCHAR RegisterToWrite
  1301. )
  1302. {
  1303. NTSTATUS status = STATUS_SUCCESS;
  1304. PIRUSB_CONTEXT pThisContext;
  1305. PURB pUrb = NULL;
  1306. PDEVICE_OBJECT pUrbTargetDev;
  1307. PIO_STACK_LOCATION pNextStack;
  1308. PIRP pIrp;
  1309. PIR_DEVICE pThisDev = (PIR_DEVICE)pDevice;
  1310. PLIST_ENTRY pListEntry;
  1311. DEBUGMSG(DBG_FUNC, ("+St4200WriteRegister\n"));
  1312. // MS Security bug #538703
  1313. IRUSB_ASSERT(pDevice != NULL);
  1314. IRUSB_ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );
  1315. //
  1316. // Make sure there isn't a halt/reset going on
  1317. //
  1318. if( pThisDev->fPendingHalt || pThisDev->fPendingReset || pThisDev->fPendingClearTotalStall )
  1319. {
  1320. DEBUGMSG(DBG_ERR, (" St4200WriteRegister abort due to pending reset\n"));
  1321. status = STATUS_UNSUCCESSFUL;
  1322. goto done;
  1323. }
  1324. //
  1325. // Validate the parameters
  1326. //
  1327. if( RegisterToWrite>STIR4200_MAX_REG )
  1328. {
  1329. DEBUGMSG(DBG_ERR, (" St4200WriteRegister invalid input parameters\n"));
  1330. status = STATUS_UNSUCCESSFUL;
  1331. goto done;
  1332. }
  1333. pListEntry = ExInterlockedRemoveHeadList( &pThisDev->SendAvailableQueue, &pThisDev->SendLock );
  1334. if( NULL == pListEntry )
  1335. {
  1336. //
  1337. // This must not happen
  1338. //
  1339. DEBUGMSG(DBG_ERR, (" St4200WriteRegister failed to find a free context struct\n"));
  1340. IRUSB_ASSERT( 0 );
  1341. status = STATUS_UNSUCCESSFUL;
  1342. goto done;
  1343. }
  1344. InterlockedDecrement( &pThisDev->SendAvailableCount );
  1345. pThisContext = CONTAINING_RECORD( pListEntry, IRUSB_CONTEXT, ListEntry );
  1346. pThisContext->ContextType = CONTEXT_READ_WRITE_REGISTER;
  1347. //
  1348. // MS Security recommendation - allocate a new urb.
  1349. //
  1350. pThisContext->UrbLen = sizeof( struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST );
  1351. pThisContext->pUrb = MyUrbAlloc(pThisContext->UrbLen);
  1352. if (pThisContext->pUrb == NULL)
  1353. {
  1354. DEBUGMSG(DBG_ERR, (" St4200WriteMultipleRegisters abort due to urb alloc failure\n"));
  1355. goto done;
  1356. }
  1357. pUrb = pThisContext->pUrb;
  1358. //
  1359. // Now that we have created the urb, we will send a
  1360. // request to the USB device object.
  1361. //
  1362. pUrbTargetDev = pThisDev->pUsbDevObj;
  1363. //
  1364. // make an irp sending to usbhub
  1365. //
  1366. pIrp = IoAllocateIrp( (CCHAR)(pThisDev->pUsbDevObj->StackSize + 1), FALSE );
  1367. if( NULL == pIrp )
  1368. {
  1369. DEBUGMSG(DBG_ERR, (" St4200WriteRegister failed to alloc IRP\n"));
  1370. MyUrbFree(pThisContext->pUrb, pThisContext->UrbLen);
  1371. pThisContext->pUrb = NULL;
  1372. ExInterlockedInsertTailList(
  1373. &pThisDev->SendAvailableQueue,
  1374. &pThisContext->ListEntry,
  1375. &pThisDev->SendLock
  1376. );
  1377. InterlockedIncrement( &pThisDev->SendAvailableCount );
  1378. status = STATUS_UNSUCCESSFUL;
  1379. goto done;
  1380. }
  1381. pIrp->IoStatus.Status = STATUS_PENDING;
  1382. pIrp->IoStatus.Information = 0;
  1383. pThisContext->pIrp = pIrp;
  1384. //
  1385. // Build our URB for USBD
  1386. //
  1387. pUrb->UrbControlVendorClassRequest.Hdr.Length = (USHORT) sizeof( struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST );
  1388. pUrb->UrbControlVendorClassRequest.Hdr.Function = URB_FUNCTION_VENDOR_DEVICE;
  1389. pUrb->UrbControlVendorClassRequest.TransferFlags = USBD_TRANSFER_DIRECTION_OUT;
  1390. // short packet is not treated as an error.
  1391. pUrb->UrbControlVendorClassRequest.TransferFlags |= USBD_SHORT_TRANSFER_OK;
  1392. pUrb->UrbControlVendorClassRequest.UrbLink = NULL;
  1393. pUrb->UrbControlVendorClassRequest.TransferBufferMDL = NULL;
  1394. pUrb->UrbControlVendorClassRequest.Value = *(&pThisDev->StIrTranceiver.FifoDataReg+RegisterToWrite);
  1395. pUrb->UrbControlVendorClassRequest.Request = STIR4200_WRITE_REG_REQ;
  1396. pUrb->UrbControlVendorClassRequest.RequestTypeReservedBits = 0;
  1397. pUrb->UrbControlVendorClassRequest.Index = RegisterToWrite;
  1398. //
  1399. // Call the class driver to perform the operation.
  1400. //
  1401. pNextStack = IoGetNextIrpStackLocation( pIrp );
  1402. IRUSB_ASSERT( pNextStack != NULL );
  1403. //
  1404. // pass the URB to the USB driver stack
  1405. //
  1406. pNextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  1407. pNextStack->Parameters.Others.Argument1 = pUrb;
  1408. pNextStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
  1409. IoSetCompletionRoutine(
  1410. pIrp, // irp to use
  1411. St4200CompleteReadWriteRequest, // routine to call when irp is done
  1412. DEV_TO_CONTEXT(pThisContext), // context to pass routine
  1413. TRUE, // call on success
  1414. TRUE, // call on error
  1415. TRUE // call on cancel
  1416. );
  1417. KeClearEvent( &pThisDev->EventSyncUrb );
  1418. //
  1419. // Call IoCallDriver to send the irp to the usb port.
  1420. //
  1421. ExInterlockedInsertTailList(
  1422. &pThisDev->ReadWritePendingQueue,
  1423. &pThisContext->ListEntry,
  1424. &pThisDev->SendLock
  1425. );
  1426. InterlockedIncrement( &pThisDev->ReadWritePendingCount );
  1427. status = MyIoCallDriver( pThisDev, pUrbTargetDev, pIrp );
  1428. //
  1429. // The USB driver should always return STATUS_PENDING when
  1430. // it receives a write irp
  1431. //
  1432. if( (status == STATUS_PENDING) || (status == STATUS_SUCCESS) )
  1433. {
  1434. // wait, but dump out on timeout
  1435. if( status == STATUS_PENDING )
  1436. {
  1437. status = MyKeWaitForSingleObject( pThisDev, &pThisDev->EventSyncUrb, 0 );
  1438. if( status == STATUS_TIMEOUT )
  1439. {
  1440. KIRQL OldIrql;
  1441. DEBUGMSG( DBG_ERR,(" St4200WriteRegister() TIMED OUT! return from IoCallDriver USBD %x\n", status));
  1442. KeAcquireSpinLock( &pThisDev->SendLock, &OldIrql );
  1443. RemoveEntryList( &pThisContext->ListEntry );
  1444. KeReleaseSpinLock( &pThisDev->SendLock, OldIrql );
  1445. InterlockedDecrement( &pThisDev->ReadWritePendingCount );
  1446. // MS Security recommendation - cannot cancel IRP.
  1447. }
  1448. }
  1449. }
  1450. else
  1451. {
  1452. DEBUGMSG( DBG_ERR, (" St4200WriteRegister IoCallDriver FAILED(%x)\n",status));
  1453. IRUSB_ASSERT( status == STATUS_PENDING );
  1454. }
  1455. done:
  1456. DEBUGMSG(DBG_FUNC, ("-St4200WriteRegister\n"));
  1457. return status;
  1458. }
  1459. /*****************************************************************************
  1460. *
  1461. * Function: St4200ReadRegisters
  1462. *
  1463. * Synopsis: reads multiple STIr4200 register
  1464. *
  1465. * Arguments: pDevice - pointer to current ir device object
  1466. * FirstRegister - first register to read
  1467. * RegistersToWrite - number of registers to read
  1468. *
  1469. * Returns: NT_STATUS
  1470. *
  1471. *
  1472. *****************************************************************************/
  1473. NTSTATUS
  1474. St4200ReadRegisters(
  1475. IN OUT PVOID pDevice,
  1476. UCHAR FirstRegister,
  1477. UCHAR RegistersToRead
  1478. )
  1479. {
  1480. NTSTATUS status = STATUS_SUCCESS;
  1481. PIRUSB_CONTEXT pThisContext;
  1482. PURB pUrb = NULL;
  1483. PDEVICE_OBJECT pUrbTargetDev;
  1484. PIO_STACK_LOCATION pNextStack;
  1485. PIRP pIrp;
  1486. PIR_DEVICE pThisDev = (PIR_DEVICE)pDevice;
  1487. PLIST_ENTRY pListEntry;
  1488. DEBUGMSG(DBG_FUNC, ("+St4200ReadRegisters\n"));
  1489. // MS Security bug #538703
  1490. IRUSB_ASSERT(pDevice != NULL);
  1491. IRUSB_ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );
  1492. //
  1493. // Make sure there isn't a halt/reset going on
  1494. //
  1495. if( pThisDev->fPendingHalt || pThisDev->fPendingReset || pThisDev->fPendingClearTotalStall )
  1496. {
  1497. DEBUGMSG(DBG_ERR, (" St4200ReadRegisters abort due to pending reset\n"));
  1498. status = STATUS_UNSUCCESSFUL;
  1499. goto done;
  1500. }
  1501. //
  1502. // Validate the parameters
  1503. //
  1504. if( (FirstRegister+RegistersToRead)>(STIR4200_MAX_REG+1) )
  1505. {
  1506. DEBUGMSG(DBG_ERR, (" St4200ReadRegisters invalid input parameters\n"));
  1507. status = STATUS_UNSUCCESSFUL;
  1508. goto done;
  1509. }
  1510. pListEntry = ExInterlockedRemoveHeadList( &pThisDev->SendAvailableQueue, &pThisDev->SendLock );
  1511. if( NULL == pListEntry )
  1512. {
  1513. //
  1514. // This must not happen
  1515. //
  1516. DEBUGMSG(DBG_ERR, (" St4200ReadRegisters failed to find a free context struct\n"));
  1517. IRUSB_ASSERT( 0 );
  1518. status = STATUS_UNSUCCESSFUL;
  1519. goto done;
  1520. }
  1521. InterlockedDecrement( &pThisDev->SendAvailableCount );
  1522. pThisContext = CONTAINING_RECORD( pListEntry, IRUSB_CONTEXT, ListEntry );
  1523. pThisContext->ContextType = CONTEXT_READ_WRITE_REGISTER;
  1524. //
  1525. // MS Security recommendation - allocate a new urb.
  1526. //
  1527. pThisContext->UrbLen = sizeof( struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST );
  1528. pThisContext->pUrb = MyUrbAlloc(pThisContext->UrbLen);
  1529. if (pThisContext->pUrb == NULL)
  1530. {
  1531. DEBUGMSG(DBG_ERR, (" St4200ReadRegisters abort due to urb alloc failure\n"));
  1532. goto done;
  1533. }
  1534. pUrb = pThisContext->pUrb;
  1535. //
  1536. // Now that we have created the urb, we will send a
  1537. // request to the USB device object.
  1538. //
  1539. pUrbTargetDev = pThisDev->pUsbDevObj;
  1540. //
  1541. // make an irp sending to usbhub
  1542. //
  1543. pIrp = IoAllocateIrp( (CCHAR)(pThisDev->pUsbDevObj->StackSize + 1), FALSE );
  1544. if( NULL == pIrp )
  1545. {
  1546. DEBUGMSG(DBG_ERR, (" St4200ReadRegisters failed to alloc IRP\n"));
  1547. MyUrbFree(pThisContext->pUrb, pThisContext->UrbLen);
  1548. pThisContext->pUrb = NULL;
  1549. ExInterlockedInsertTailList(
  1550. &pThisDev->SendAvailableQueue,
  1551. &pThisContext->ListEntry,
  1552. &pThisDev->SendLock
  1553. );
  1554. InterlockedIncrement( &pThisDev->SendAvailableCount );
  1555. status = STATUS_UNSUCCESSFUL;
  1556. goto done;
  1557. }
  1558. pIrp->IoStatus.Status = STATUS_PENDING;
  1559. pIrp->IoStatus.Information = 0;
  1560. pThisContext->pIrp = pIrp;
  1561. //
  1562. // Build our URB for USBD
  1563. //
  1564. pUrb->UrbControlVendorClassRequest.Hdr.Length = (USHORT) sizeof( struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST );
  1565. pUrb->UrbControlVendorClassRequest.Hdr.Function = URB_FUNCTION_VENDOR_DEVICE ;
  1566. pUrb->UrbControlVendorClassRequest.TransferFlags = USBD_TRANSFER_DIRECTION_IN ;
  1567. // short packet is not treated as an error.
  1568. pUrb->UrbControlVendorClassRequest.TransferFlags |= USBD_SHORT_TRANSFER_OK;
  1569. pUrb->UrbControlVendorClassRequest.UrbLink = NULL;
  1570. pUrb->UrbControlVendorClassRequest.TransferBufferMDL = NULL;
  1571. pUrb->UrbControlVendorClassRequest.TransferBuffer = &(pThisDev->StIrTranceiver.FifoDataReg)+FirstRegister;
  1572. pUrb->UrbControlVendorClassRequest.TransferBufferLength = RegistersToRead;
  1573. pUrb->UrbControlVendorClassRequest.Request = STIR4200_READ_REGS_REQ;
  1574. pUrb->UrbControlVendorClassRequest.RequestTypeReservedBits = 0;
  1575. pUrb->UrbControlVendorClassRequest.Index = FirstRegister;
  1576. //
  1577. // Call the class driver to perform the operation.
  1578. //
  1579. pNextStack = IoGetNextIrpStackLocation( pIrp );
  1580. IRUSB_ASSERT( pNextStack != NULL );
  1581. //
  1582. // pass the URB to the USB driver stack
  1583. //
  1584. pNextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  1585. pNextStack->Parameters.Others.Argument1 = pUrb;
  1586. pNextStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
  1587. IoSetCompletionRoutine(
  1588. pIrp, // irp to use
  1589. St4200CompleteReadWriteRequest, // routine to call when irp is done
  1590. DEV_TO_CONTEXT(pThisContext), // context to pass routine
  1591. TRUE, // call on success
  1592. TRUE, // call on error
  1593. TRUE // call on cancel
  1594. );
  1595. KeClearEvent( &pThisDev->EventSyncUrb );
  1596. //
  1597. // Call IoCallDriver to send the irp to the usb port.
  1598. //
  1599. ExInterlockedInsertTailList(
  1600. &pThisDev->ReadWritePendingQueue,
  1601. &pThisContext->ListEntry,
  1602. &pThisDev->SendLock
  1603. );
  1604. InterlockedIncrement( &pThisDev->ReadWritePendingCount );
  1605. status = MyIoCallDriver( pThisDev, pUrbTargetDev, pIrp );
  1606. //
  1607. // The USB driver should always return STATUS_PENDING when
  1608. // it receives a write irp
  1609. //
  1610. if( (status == STATUS_PENDING) || (status == STATUS_SUCCESS) )
  1611. {
  1612. // wait, but dump out on timeout
  1613. if( status == STATUS_PENDING )
  1614. {
  1615. status = MyKeWaitForSingleObject( pThisDev, &pThisDev->EventSyncUrb, 0 );
  1616. if( status == STATUS_TIMEOUT )
  1617. {
  1618. KIRQL OldIrql;
  1619. DEBUGMSG( DBG_ERR,(" St4200ReadRegisters() TIMED OUT! return from IoCallDriver USBD %x\n", status));
  1620. KeAcquireSpinLock( &pThisDev->SendLock, &OldIrql );
  1621. RemoveEntryList( &pThisContext->ListEntry );
  1622. KeReleaseSpinLock( &pThisDev->SendLock, OldIrql );
  1623. InterlockedDecrement( &pThisDev->ReadWritePendingCount );
  1624. // MS Security recommendation - cannot cancel IRP.
  1625. }
  1626. else
  1627. {
  1628. //
  1629. // Update the status to reflect the real return code
  1630. //
  1631. status = pThisDev->StatusReadWrite;
  1632. }
  1633. }
  1634. }
  1635. else
  1636. {
  1637. DEBUGMSG( DBG_ERR, (" St4200ReadRegisters IoCallDriver FAILED(%x)\n",status));
  1638. //
  1639. // Don't assert, as such a failure can happen at shutdown
  1640. //
  1641. //IRUSB_ASSERT( status == STATUS_PENDING );
  1642. }
  1643. done:
  1644. DEBUGMSG(DBG_FUNC, ("-St4200ReadRegisters\n"));
  1645. return status;
  1646. }
  1647. /*****************************************************************************
  1648. *
  1649. * Function: St4200CompleteReadWriteRequest
  1650. *
  1651. * Synopsis: completes a read/write ST4200 register request
  1652. *
  1653. * Arguments: pUsbDevObj - pointer to the device object which
  1654. * completed the irp
  1655. * pIrp - the irp which was completed by the device
  1656. * object
  1657. * Context - send context
  1658. *
  1659. * Returns: NT_STATUS
  1660. *
  1661. *
  1662. *****************************************************************************/
  1663. NTSTATUS
  1664. St4200CompleteReadWriteRequest(
  1665. IN PDEVICE_OBJECT pUsbDevObj,
  1666. IN PIRP pIrp,
  1667. IN PVOID Context
  1668. )
  1669. {
  1670. PIR_DEVICE pThisDev;
  1671. NTSTATUS status;
  1672. PIRUSB_CONTEXT pThisContext = (PIRUSB_CONTEXT)Context;
  1673. PIRP pContextIrp;
  1674. PURB pContextUrb;
  1675. PLIST_ENTRY pListEntry;
  1676. DEBUGMSG(DBG_FUNC, ("+St4200CompleteReadWriteRequest\n"));
  1677. //
  1678. // The context given to IoSetCompletionRoutine is an IRUSB_CONTEXT struct
  1679. //
  1680. IRUSB_ASSERT( NULL != pThisContext ); // we better have a non NULL buffer
  1681. pThisDev = pThisContext->pThisDev;
  1682. IRUSB_ASSERT( NULL != pThisDev );
  1683. pContextIrp = pThisContext->pIrp;
  1684. pContextUrb = pThisContext->pUrb;
  1685. //
  1686. // Perform various IRP, URB, and buffer 'sanity checks'
  1687. //
  1688. IRUSB_ASSERT( pContextIrp == pIrp ); // check we're not a bogus IRP
  1689. IRUSB_ASSERT( pContextUrb != NULL );
  1690. status = pIrp->IoStatus.Status;
  1691. //
  1692. // we should have failed, succeeded, or cancelled, but NOT be pending
  1693. //
  1694. IRUSB_ASSERT( STATUS_PENDING != status );
  1695. //
  1696. // Remove from the pending queue (only if NOT cancelled)
  1697. //
  1698. if( status != STATUS_CANCELLED )
  1699. {
  1700. KIRQL OldIrql;
  1701. KeAcquireSpinLock( &pThisDev->SendLock, &OldIrql );
  1702. RemoveEntryList( &pThisContext->ListEntry );
  1703. KeReleaseSpinLock( &pThisDev->SendLock, OldIrql );
  1704. InterlockedDecrement( &pThisDev->ReadWritePendingCount );
  1705. }
  1706. //pIrp->IoStatus.Information = pContextUrb->UrbControlVendorClassRequest.TransferBufferLength;
  1707. DEBUGMSG(DBG_OUT,
  1708. (" St4200CompleteReadWriteRequest pIrp->IoStatus.Status = 0x%x\n", status));
  1709. //DEBUGMSG(DBG_OUT,
  1710. // (" St4200CompleteReadWriteRequest pIrp->IoStatus.Information = 0x%x, dec %d\n", pIrp->IoStatus.Information,pIrp->IoStatus.Information));
  1711. //
  1712. // Free the IRP.
  1713. //
  1714. IoFreeIrp( pIrp );
  1715. InterlockedIncrement( &pThisDev->NumReadWrites );
  1716. IrUsb_DecIoCount( pThisDev ); // we will track count of pending irps
  1717. // Free the URB.
  1718. MyUrbFree(pThisContext->pUrb, pThisContext->UrbLen);
  1719. pThisContext->pUrb = NULL;
  1720. //
  1721. // Put back on the available queue
  1722. //
  1723. ExInterlockedInsertTailList(
  1724. &pThisDev->SendAvailableQueue,
  1725. &pThisContext->ListEntry,
  1726. &pThisDev->SendLock
  1727. );
  1728. InterlockedIncrement( &pThisDev->SendAvailableCount );
  1729. if( ( STATUS_SUCCESS != status ) && ( STATUS_CANCELLED != status ) )
  1730. {
  1731. InterlockedIncrement( (PLONG)&pThisDev->NumReadWriteErrors );
  1732. //
  1733. // We have a serious USB failure, we'll have to issue a total reset
  1734. //
  1735. if( !pThisDev->fPendingClearTotalStall && !pThisDev->fPendingHalt
  1736. && !pThisDev->fPendingReset && pThisDev->fProcessing )
  1737. {
  1738. DEBUGMSG(DBG_ERR, (" St4200CompleteReadWriteRequest error, will schedule an entire reset\n"));
  1739. InterlockedExchange( (PLONG)&pThisDev->fPendingClearTotalStall, TRUE );
  1740. ScheduleWorkItem( pThisDev, RestoreIrDevice, NULL, 0 );
  1741. }
  1742. }
  1743. //
  1744. // This will only work as long as we serialize the access to the hardware
  1745. //
  1746. pThisDev->StatusReadWrite = status;
  1747. //
  1748. // Signal we're done
  1749. //
  1750. KeSetEvent( &pThisDev->EventSyncUrb, 0, FALSE );
  1751. DEBUGMSG(DBG_FUNC, ("-St4200CompleteReadWriteRequest\n"));
  1752. return STATUS_MORE_PROCESSING_REQUIRED;
  1753. }
  1754. #if defined( WORKAROUND_STUCK_AFTER_GEAR_DOWN )
  1755. /*****************************************************************************
  1756. *
  1757. * Function: St4200FakeSend
  1758. *
  1759. * Synopsis: forces a bulk out transfer
  1760. *
  1761. * Arguments: pDevice - pointer to current ir device object
  1762. * pData - pointer to bulk data
  1763. * DataSize - size of bulk data
  1764. *
  1765. * Returns: NT_STATUS
  1766. *
  1767. *
  1768. *****************************************************************************/
  1769. NTSTATUS
  1770. St4200FakeSend(
  1771. IN PVOID pDevice,
  1772. PUCHAR pData,
  1773. ULONG DataSize
  1774. )
  1775. {
  1776. NTSTATUS status = STATUS_SUCCESS;
  1777. PIRUSB_CONTEXT pThisContext;
  1778. PURB pUrb = NULL;
  1779. PDEVICE_OBJECT pUrbTargetDev;
  1780. PIO_STACK_LOCATION pNextStack;
  1781. PIRP pIrp;
  1782. PIR_DEVICE pThisDev = (PIR_DEVICE)pDevice;
  1783. PLIST_ENTRY pListEntry;
  1784. DEBUGMSG(DBG_FUNC, ("+St4200FakeSend\n"));
  1785. // MS Security bug #538703
  1786. IRUSB_ASSERT(pDevice != NULL);
  1787. IRUSB_ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );
  1788. pListEntry = ExInterlockedRemoveHeadList( &pThisDev->SendAvailableQueue, &pThisDev->SendLock );
  1789. if( NULL == pListEntry )
  1790. {
  1791. //
  1792. // This must not happen
  1793. //
  1794. DEBUGMSG(DBG_ERR, (" St4200FakeSend failed to find a free context struct\n"));
  1795. IRUSB_ASSERT( 0 );
  1796. status = STATUS_UNSUCCESSFUL;
  1797. goto done;
  1798. }
  1799. InterlockedDecrement( &pThisDev->SendAvailableCount );
  1800. pThisContext = CONTAINING_RECORD( pListEntry, IRUSB_CONTEXT, ListEntry );
  1801. pThisContext->ContextType = CONTEXT_READ_WRITE_REGISTER;
  1802. //
  1803. // MS Security recommendation - allocate a new urb.
  1804. //
  1805. pThisContext->UrbLen = sizeof( struct _URB_BULK_OR_INTERRUPT_TRANSFER );
  1806. pThisContext->pUrb = MyUrbAlloc(pThisContext->UrbLen);
  1807. if (pThisContext->pUrb == NULL)
  1808. {
  1809. DEBUGMSG(DBG_ERR, (" St4200FakeSend abort due to urb alloc failure\n"));
  1810. goto done;
  1811. }
  1812. pUrb = pThisContext->pUrb;
  1813. //
  1814. // Now that we have created the urb, we will send a
  1815. // request to the USB device object.
  1816. //
  1817. pUrbTargetDev = pThisDev->pUsbDevObj;
  1818. //
  1819. // make an irp sending to usbhub
  1820. //
  1821. pIrp = IoAllocateIrp( (CCHAR)(pThisDev->pUsbDevObj->StackSize + 1), FALSE );
  1822. if( NULL == pIrp )
  1823. {
  1824. DEBUGMSG(DBG_ERR, (" St4200FakeSend failed to alloc IRP\n"));
  1825. MyUrbFree(pThisContext->pUrb, pThisContext->UrbLen);
  1826. pThisContext->pUrb = NULL;
  1827. ExInterlockedInsertTailList(
  1828. &pThisDev->SendAvailableQueue,
  1829. &pThisContext->ListEntry,
  1830. &pThisDev->SendLock
  1831. );
  1832. InterlockedIncrement( &pThisDev->SendAvailableCount );
  1833. status = STATUS_UNSUCCESSFUL;
  1834. goto done;
  1835. }
  1836. pIrp->IoStatus.Status = STATUS_PENDING;
  1837. pIrp->IoStatus.Information = 0;
  1838. pThisContext->pIrp = pIrp;
  1839. //
  1840. // Build our URB for USBD
  1841. //
  1842. pUrb->UrbBulkOrInterruptTransfer.Hdr.Length = (USHORT)sizeof( struct _URB_BULK_OR_INTERRUPT_TRANSFER );
  1843. pUrb->UrbBulkOrInterruptTransfer.Hdr.Function = URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER;
  1844. pUrb->UrbBulkOrInterruptTransfer.PipeHandle = pThisDev->BulkOutPipeHandle;
  1845. pUrb->UrbBulkOrInterruptTransfer.TransferFlags = USBD_TRANSFER_DIRECTION_OUT ;
  1846. // short packet is not treated as an error.
  1847. pUrb->UrbBulkOrInterruptTransfer.TransferFlags |= USBD_SHORT_TRANSFER_OK;
  1848. pUrb->UrbBulkOrInterruptTransfer.UrbLink = NULL;
  1849. pUrb->UrbBulkOrInterruptTransfer.TransferBufferMDL = NULL;
  1850. pUrb->UrbBulkOrInterruptTransfer.TransferBuffer = pData;
  1851. pUrb->UrbBulkOrInterruptTransfer.TransferBufferLength = (int)DataSize;
  1852. //
  1853. // Call the class driver to perform the operation.
  1854. //
  1855. pNextStack = IoGetNextIrpStackLocation( pIrp );
  1856. IRUSB_ASSERT( pNextStack != NULL );
  1857. //
  1858. // pass the URB to the USB driver stack
  1859. //
  1860. pNextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  1861. pNextStack->Parameters.Others.Argument1 = pUrb;
  1862. pNextStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
  1863. IoSetCompletionRoutine(
  1864. pIrp, // irp to use
  1865. St4200CompleteReadWriteRequest, // routine to call when irp is done
  1866. DEV_TO_CONTEXT(pThisContext), // context to pass routine
  1867. TRUE, // call on success
  1868. TRUE, // call on error
  1869. TRUE // call on cancel
  1870. );
  1871. KeClearEvent( &pThisDev->EventSyncUrb );
  1872. //
  1873. // Call IoCallDriver to send the irp to the usb port.
  1874. //
  1875. ExInterlockedInsertTailList(
  1876. &pThisDev->ReadWritePendingQueue,
  1877. &pThisContext->ListEntry,
  1878. &pThisDev->SendLock
  1879. );
  1880. InterlockedIncrement( &pThisDev->ReadWritePendingCount );
  1881. status = MyIoCallDriver( pThisDev, pUrbTargetDev, pIrp );
  1882. DEBUGMSG( DBG_ERR,(" St4200FakeSend() Did it\n"));
  1883. //
  1884. // The USB driver should always return STATUS_PENDING when
  1885. // it receives a write irp
  1886. //
  1887. if( (status == STATUS_PENDING) || (status == STATUS_SUCCESS) )
  1888. {
  1889. // wait, but dump out on timeout
  1890. if( status == STATUS_PENDING )
  1891. {
  1892. status = MyKeWaitForSingleObject( pThisDev, &pThisDev->EventSyncUrb, 0 );
  1893. if( status == STATUS_TIMEOUT )
  1894. {
  1895. KIRQL OldIrql;
  1896. DEBUGMSG( DBG_ERR,(" St4200FakeSend() TIMED OUT! return from IoCallDriver USBD %x\n", status));
  1897. KeAcquireSpinLock( &pThisDev->SendLock, &OldIrql );
  1898. RemoveEntryList( &pThisContext->ListEntry );
  1899. KeReleaseSpinLock( &pThisDev->SendLock, OldIrql );
  1900. InterlockedDecrement( &pThisDev->ReadWritePendingCount );
  1901. // MS Security recommendation - cannot cancel IRP.
  1902. }
  1903. }
  1904. }
  1905. else
  1906. {
  1907. DEBUGMSG( DBG_ERR, (" St4200FakeSend IoCallDriver FAILED(%x)\n",status));
  1908. IRUSB_ASSERT( status == STATUS_PENDING );
  1909. }
  1910. done:
  1911. DEBUGMSG(DBG_FUNC, ("-St4200FakeSend\n"));
  1912. return status;
  1913. }
  1914. /*****************************************************************************
  1915. *
  1916. * Function: St4200FakeReceive
  1917. *
  1918. * Synopsis: forces a bulk in transfer
  1919. *
  1920. * Arguments: pDevice - pointer to current ir device object
  1921. * pData - pointer to bulk data
  1922. * DataSize - size of bulk data
  1923. *
  1924. * Returns: NT_STATUS
  1925. *
  1926. *
  1927. *****************************************************************************/
  1928. NTSTATUS
  1929. St4200FakeReceive(
  1930. IN PVOID pDevice,
  1931. PUCHAR pData,
  1932. ULONG DataSize
  1933. )
  1934. {
  1935. NTSTATUS status = STATUS_SUCCESS;
  1936. PIRUSB_CONTEXT pThisContext;
  1937. PURB pUrb = NULL;
  1938. PDEVICE_OBJECT pUrbTargetDev;
  1939. PIO_STACK_LOCATION pNextStack;
  1940. PIRP pIrp;
  1941. PIR_DEVICE pThisDev = (PIR_DEVICE)pDevice;
  1942. PLIST_ENTRY pListEntry;
  1943. DEBUGMSG(DBG_FUNC, ("+St4200FakeReceive\n"));
  1944. // MS Security bug #538703
  1945. IRUSB_ASSERT(pDevice != NULL);
  1946. IRUSB_ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );
  1947. pListEntry = ExInterlockedRemoveHeadList( &pThisDev->SendAvailableQueue, &pThisDev->SendLock );
  1948. if( NULL == pListEntry )
  1949. {
  1950. //
  1951. // This must not happen
  1952. //
  1953. DEBUGMSG(DBG_ERR, (" St4200FakeReceive failed to find a free context struct\n"));
  1954. IRUSB_ASSERT( 0 );
  1955. status = STATUS_UNSUCCESSFUL;
  1956. goto done;
  1957. }
  1958. InterlockedDecrement( &pThisDev->SendAvailableCount );
  1959. pThisContext = CONTAINING_RECORD( pListEntry, IRUSB_CONTEXT, ListEntry );
  1960. pThisContext->ContextType = CONTEXT_READ_WRITE_REGISTER;
  1961. //
  1962. // MS Security recommendation - allocate a new urb.
  1963. //
  1964. pThisContext->UrbLen = sizeof( struct _URB_BULK_OR_INTERRUPT_TRANSFER );
  1965. pThisContext->pUrb = MyUrbAlloc(pThisContext->UrbLen);
  1966. if (pThisContext->pUrb == NULL)
  1967. {
  1968. DEBUGMSG(DBG_ERR, (" St4200FakeReceive abort due to urb alloc failure\n"));
  1969. goto done;
  1970. }
  1971. pUrb = pThisContext->pUrb;
  1972. //
  1973. // Now that we have created the urb, we will send a
  1974. // request to the USB device object.
  1975. //
  1976. pUrbTargetDev = pThisDev->pUsbDevObj;
  1977. //
  1978. // make an irp sending to usbhub
  1979. //
  1980. pIrp = IoAllocateIrp( (CCHAR)(pThisDev->pUsbDevObj->StackSize + 1), FALSE );
  1981. if( NULL == pIrp )
  1982. {
  1983. DEBUGMSG(DBG_ERR, (" St4200FakeReceive failed to alloc IRP\n"));
  1984. MyUrbFree(pThisContext->pUrb, pThisContext->UrbLen);
  1985. pThisContext->pUrb = NULL;
  1986. ExInterlockedInsertTailList(
  1987. &pThisDev->SendAvailableQueue,
  1988. &pThisContext->ListEntry,
  1989. &pThisDev->SendLock
  1990. );
  1991. InterlockedIncrement( &pThisDev->SendAvailableCount );
  1992. status = STATUS_UNSUCCESSFUL;
  1993. goto done;
  1994. }
  1995. pIrp->IoStatus.Status = STATUS_PENDING;
  1996. pIrp->IoStatus.Information = 0;
  1997. pThisContext->pIrp = pIrp;
  1998. //
  1999. // Build our URB for USBD
  2000. //
  2001. pUrb->UrbBulkOrInterruptTransfer.Hdr.Length = (USHORT)sizeof( struct _URB_BULK_OR_INTERRUPT_TRANSFER );
  2002. pUrb->UrbBulkOrInterruptTransfer.Hdr.Function = URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER;
  2003. pUrb->UrbBulkOrInterruptTransfer.PipeHandle = pThisDev->BulkInPipeHandle;
  2004. pUrb->UrbBulkOrInterruptTransfer.TransferFlags = USBD_TRANSFER_DIRECTION_IN ;
  2005. // short packet is not treated as an error.
  2006. pUrb->UrbBulkOrInterruptTransfer.TransferFlags |= USBD_SHORT_TRANSFER_OK;
  2007. pUrb->UrbBulkOrInterruptTransfer.UrbLink = NULL;
  2008. pUrb->UrbBulkOrInterruptTransfer.TransferBufferMDL = NULL;
  2009. pUrb->UrbBulkOrInterruptTransfer.TransferBuffer = pData;
  2010. pUrb->UrbBulkOrInterruptTransfer.TransferBufferLength = (int)DataSize;
  2011. //
  2012. // Call the class driver to perform the operation.
  2013. //
  2014. pNextStack = IoGetNextIrpStackLocation( pIrp );
  2015. IRUSB_ASSERT( pNextStack != NULL );
  2016. //
  2017. // pass the URB to the USB driver stack
  2018. //
  2019. pNextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  2020. pNextStack->Parameters.Others.Argument1 = pUrb;
  2021. pNextStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
  2022. IoSetCompletionRoutine(
  2023. pIrp, // irp to use
  2024. St4200CompleteReadWriteRequest, // routine to call when irp is done
  2025. DEV_TO_CONTEXT(pThisContext), // context to pass routine
  2026. TRUE, // call on success
  2027. TRUE, // call on error
  2028. TRUE // call on cancel
  2029. );
  2030. KeClearEvent( &pThisDev->EventSyncUrb );
  2031. //
  2032. // Call IoCallDriver to send the irp to the usb port.
  2033. //
  2034. ExInterlockedInsertTailList(
  2035. &pThisDev->ReadWritePendingQueue,
  2036. &pThisContext->ListEntry,
  2037. &pThisDev->SendLock
  2038. );
  2039. InterlockedIncrement( &pThisDev->ReadWritePendingCount );
  2040. status = MyIoCallDriver( pThisDev, pUrbTargetDev, pIrp );
  2041. DEBUGMSG( DBG_ERR,(" St4200FakeReceive() Did it\n"));
  2042. //
  2043. // The USB driver should always return STATUS_PENDING when
  2044. // it receives a write irp
  2045. //
  2046. if( (status == STATUS_PENDING) || (status == STATUS_SUCCESS) )
  2047. {
  2048. // wait, but dump out on timeout
  2049. if( status == STATUS_PENDING )
  2050. {
  2051. status = MyKeWaitForSingleObject( pThisDev, &pThisDev->EventSyncUrb, 0 );
  2052. if( status == STATUS_TIMEOUT )
  2053. {
  2054. KIRQL OldIrql;
  2055. DEBUGMSG( DBG_ERR,(" St4200FakeReceive() TIMED OUT! return from IoCallDriver USBD %x\n", status));
  2056. KeAcquireSpinLock( &pThisDev->SendLock, &OldIrql );
  2057. RemoveEntryList( &pThisContext->ListEntry );
  2058. KeReleaseSpinLock( &pThisDev->SendLock, OldIrql );
  2059. InterlockedDecrement( &pThisDev->ReadWritePendingCount );
  2060. // MS Security recommendation - cannot cancel IRP.
  2061. }
  2062. }
  2063. }
  2064. else
  2065. {
  2066. DEBUGMSG( DBG_ERR, (" St4200FakeReceive IoCallDriver FAILED(%x)\n",status));
  2067. IRUSB_ASSERT( status == STATUS_PENDING );
  2068. }
  2069. done:
  2070. DEBUGMSG(DBG_FUNC, ("-St4200FakeReceive\n"));
  2071. return status;
  2072. }
  2073. #endif