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.

1953 lines
51 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. #if !defined(FAST_WRITE_REGISTERS)
  63. if( (Status = St4200ReadRegisters(pThisDev, STIR4200_MODE_REG, 1)) != STATUS_SUCCESS )
  64. {
  65. DEBUGMSG(DBG_ERR, (" St4200ResetFifo(): USB failure\n"));
  66. goto done;
  67. }
  68. #endif
  69. //
  70. // Force a FIFO reset by clearing and setting again the RESET_OFF bit
  71. //
  72. pThisDev->StIrTranceiver.ModeReg &= (~STIR4200_MODE_RESET_OFF);
  73. if( (Status = St4200WriteRegister(pThisDev, STIR4200_MODE_REG)) != STATUS_SUCCESS )
  74. {
  75. DEBUGMSG(DBG_ERR, (" St4200ResetFifo(): USB failure\n"));
  76. goto done;
  77. }
  78. pThisDev->StIrTranceiver.ModeReg |= STIR4200_MODE_RESET_OFF;
  79. if( (Status = St4200WriteRegister(pThisDev, STIR4200_MODE_REG)) != STATUS_SUCCESS )
  80. {
  81. DEBUGMSG(DBG_ERR, (" St4200ResetFifo(): USB failure\n"));
  82. goto done;
  83. }
  84. done:
  85. return Status;
  86. }
  87. /*****************************************************************************
  88. *
  89. * Function: St4200DoubleResetFifo
  90. *
  91. * Synopsis: Reset the STIr4200 FIFO to clear several 4012 related hangs
  92. *
  93. * Arguments: pDevice - pointer to current ir device object
  94. *
  95. * Returns: NT_STATUS
  96. *
  97. *
  98. *****************************************************************************/
  99. NTSTATUS
  100. St4200DoubleResetFifo(
  101. IN PVOID pDevice
  102. )
  103. {
  104. NTSTATUS Status;
  105. PIR_DEVICE pThisDev = (PIR_DEVICE)pDevice;
  106. DEBUGMSG(DBG_INT_ERR, (" St4200DoubleResetFifo: Issuing a FIFO reset()\n"));
  107. //
  108. // Turn off the receiver to clear the pointers
  109. //
  110. if( (Status = St4200TurnOffReceiver( pThisDev ) ) != STATUS_SUCCESS )
  111. {
  112. DEBUGMSG(DBG_ERR, (" St4200DoubleResetFifo(): USB failure\n"));
  113. goto done;
  114. }
  115. //
  116. // Now clear the fifo logic
  117. //
  118. #if !defined(FAST_WRITE_REGISTERS)
  119. if( (Status = St4200ReadRegisters(pThisDev, STIR4200_STATUS_REG, 1)) != STATUS_SUCCESS )
  120. {
  121. DEBUGMSG(DBG_ERR, (" St4200DoubleResetFifo(): USB failure\n"));
  122. goto done;
  123. }
  124. if( (Status = St4200ReadRegisters(pThisDev, STIR4200_STATUS_REG, 1)) != STATUS_SUCCESS )
  125. {
  126. DEBUGMSG(DBG_ERR, (" St4200DoubleResetFifo(): USB failure\n"));
  127. goto done;
  128. }
  129. #endif
  130. pThisDev->StIrTranceiver.StatusReg |= STIR4200_STAT_FFCLR;
  131. if( (Status = St4200WriteRegister(pThisDev, STIR4200_STATUS_REG)) != STATUS_SUCCESS )
  132. {
  133. DEBUGMSG(DBG_ERR, (" St4200DoubleResetFifo(): USB failure\n"));
  134. goto done;
  135. }
  136. //
  137. // All back on
  138. //
  139. pThisDev->StIrTranceiver.StatusReg &= (~STIR4200_STAT_FFCLR);
  140. if( (Status = St4200WriteRegister(pThisDev, STIR4200_STATUS_REG)) != STATUS_SUCCESS )
  141. {
  142. DEBUGMSG(DBG_ERR, (" St4200DoubleResetFifo(): USB failure\n"));
  143. goto done;
  144. }
  145. if( (Status = St4200TurnOnReceiver( pThisDev ) ) != STATUS_SUCCESS )
  146. {
  147. DEBUGMSG(DBG_ERR, (" St4200DoubleResetFifo(): USB failure\n"));
  148. goto done;
  149. }
  150. done:
  151. return Status;
  152. }
  153. /*****************************************************************************
  154. *
  155. * Function: St4200SoftReset
  156. *
  157. * Synopsis: Soft reset of the STIr4200 modulator
  158. *
  159. * Arguments: pDevice - pointer to current ir device object
  160. *
  161. * Returns: NT_STATUS
  162. *
  163. *
  164. *****************************************************************************/
  165. NTSTATUS
  166. St4200SoftReset(
  167. IN PVOID pDevice
  168. )
  169. {
  170. NTSTATUS Status;
  171. PIR_DEVICE pThisDev = (PIR_DEVICE)pDevice;
  172. DEBUGMSG(DBG_INT_ERR, (" St4200SoftReset: Issuing a soft reset()\n"));
  173. #if !defined(FAST_WRITE_REGISTERS)
  174. if( (Status = St4200ReadRegisters(pThisDev, STIR4200_CONTROL_REG, 1)) != STATUS_SUCCESS )
  175. {
  176. DEBUGMSG(DBG_ERR, (" St4200SoftReset(): USB failure\n"));
  177. goto done;
  178. }
  179. #endif
  180. //
  181. // Force a FIFO reset by clearing and setting again the RESET_OFF bit
  182. //
  183. pThisDev->StIrTranceiver.ControlReg |= STIR4200_CTRL_SRESET;
  184. if( (Status = St4200WriteRegister(pThisDev, STIR4200_CONTROL_REG)) != STATUS_SUCCESS )
  185. {
  186. DEBUGMSG(DBG_ERR, (" St4200SoftReset(): USB failure\n"));
  187. goto done;
  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. done:
  196. return Status;
  197. }
  198. /*****************************************************************************
  199. *
  200. * Function: St4200SetIrMode
  201. *
  202. * Synopsis: Sets the STIr4200 to the proper operational mode
  203. *
  204. * Arguments: pDevice - pointer to current ir device object
  205. * mode - mode to set the tranceiver to
  206. *
  207. * Returns: NT_STATUS
  208. *
  209. *
  210. *****************************************************************************/
  211. NTSTATUS
  212. St4200SetIrMode(
  213. IN OUT PVOID pDevice,
  214. ULONG mode
  215. )
  216. {
  217. NTSTATUS Status;
  218. PIR_DEVICE pThisDev = (PIR_DEVICE)pDevice;
  219. #if !defined(FAST_WRITE_REGISTERS)
  220. if( (Status = St4200ReadRegisters(pThisDev, STIR4200_MODE_REG, 1)) != STATUS_SUCCESS )
  221. {
  222. DEBUGMSG(DBG_ERR, (" St4200SetIrMode(): USB failure\n"));
  223. goto done;
  224. }
  225. #endif
  226. //
  227. // Remove all mode bits and set the proper mode
  228. //
  229. pThisDev->StIrTranceiver.ModeReg &= ~STIR4200_MODE_MASK;
  230. pThisDev->StIrTranceiver.ModeReg |= STIR4200_MODE_RESET_OFF;
  231. //
  232. // Enable the bug fixing feature for LA8
  233. //
  234. #if defined(SUPPORT_LA8)
  235. if( pThisDev->ChipRevision >= CHIP_REVISION_8 )
  236. {
  237. pThisDev->StIrTranceiver.ModeReg &= ~STIR4200_MODE_AUTO_RESET;
  238. pThisDev->StIrTranceiver.ModeReg &= ~STIR4200_MODE_BULKIN_FIX;
  239. }
  240. #endif
  241. switch( (IR_MODE)mode )
  242. {
  243. case IR_MODE_SIR:
  244. pThisDev->StIrTranceiver.ModeReg |= STIR4200_MODE_SIR;
  245. //if( pThisDev->linkSpeedInfo->BitsPerSec != SPEED_9600 )
  246. pThisDev->StIrTranceiver.ModeReg |= STIR4200_MODE_BULKIN_FIX;
  247. //pThisDev->StIrTranceiver.ModeReg |= STIR4200_MODE_ASK;
  248. break;
  249. #if !defined(WORKAROUND_BROKEN_MIR)
  250. case IR_MODE_MIR:
  251. pThisDev->MirIncompleteBitCount = 0;
  252. pThisDev->MirOneBitCount = 0;
  253. pThisDev->MirIncompleteByte = 0;
  254. pThisDev->MirFlagCount = 0;
  255. pThisDev->StIrTranceiver.ModeReg |= STIR4200_MODE_MIR;
  256. break;
  257. #endif
  258. case IR_MODE_FIR:
  259. pThisDev->StIrTranceiver.ModeReg |= STIR4200_MODE_FIR;
  260. #if defined(SUPPORT_LA8)
  261. if( pThisDev->ChipRevision >= CHIP_REVISION_8 )
  262. {
  263. pThisDev->StIrTranceiver.ModeReg |= STIR4200_MODE_BULKIN_FIX;
  264. pThisDev->StIrTranceiver.ModeReg |= STIR4200_MODE_AUTO_RESET;
  265. }
  266. #endif
  267. break;
  268. default:
  269. IRUSB_ASSERT( 0 );
  270. }
  271. if( (Status = St4200WriteRegister(pThisDev, STIR4200_MODE_REG) ) != STATUS_SUCCESS )
  272. {
  273. DEBUGMSG(DBG_ERR, (" St4200SetIrMode(): USB failure\n"));
  274. goto done;
  275. }
  276. /***********************************************/
  277. /* Set TEMIC transceiver... */
  278. /***********************************************/
  279. #if !defined(FAST_WRITE_REGISTERS)
  280. if( (Status = St4200ReadRegisters(pThisDev, STIR4200_CONTROL_REG, 1)) != STATUS_SUCCESS )
  281. {
  282. DEBUGMSG(DBG_ERR, (" St4200SetIrMode(): USB failure\n"));
  283. goto done;
  284. }
  285. #endif
  286. pThisDev->StIrTranceiver.ControlReg |= STIR4200_CTRL_SDMODE;
  287. if( (Status = St4200WriteRegister(pThisDev, STIR4200_CONTROL_REG)) != STATUS_SUCCESS )
  288. {
  289. DEBUGMSG(DBG_ERR, (" St4200SetIrMode(): USB failure\n"));
  290. goto done;
  291. }
  292. #if !defined(FAST_WRITE_REGISTERS)
  293. if( (Status = St4200ReadRegisters(pThisDev, STIR4200_CONTROL_REG, 1)) != STATUS_SUCCESS )
  294. {
  295. DEBUGMSG(DBG_ERR, (" St4200SetIrMode(): USB failure\n"));
  296. goto done;
  297. }
  298. #endif
  299. pThisDev->StIrTranceiver.ControlReg &= (~STIR4200_CTRL_SDMODE);
  300. if( (Status = St4200WriteRegister(pThisDev, STIR4200_CONTROL_REG)) != STATUS_SUCCESS )
  301. {
  302. DEBUGMSG(DBG_ERR, (" St4200SetIrMode(): USB failure\n"));
  303. goto done;
  304. }
  305. done:
  306. return Status;
  307. }
  308. /*****************************************************************************
  309. *
  310. * Function: St4200SetSpeed
  311. *
  312. * Synopsis: Sets the STIr4200 speed
  313. *
  314. * Arguments: pDevice - pointer to current ir device object
  315. *
  316. * Returns: NT_STATUS
  317. *
  318. *
  319. *****************************************************************************/
  320. NTSTATUS
  321. St4200SetSpeed(
  322. IN OUT PVOID pDevice
  323. )
  324. {
  325. NTSTATUS Status;
  326. PIR_DEVICE pThisDev = (PIR_DEVICE)pDevice;
  327. #if defined(RECEIVE_LOGGING)
  328. if( pThisDev->linkSpeedInfo->BitsPerSec==SPEED_4000000 )
  329. {
  330. IO_STATUS_BLOCK IoStatusBlock;
  331. OBJECT_ATTRIBUTES ObjectAttributes;
  332. UNICODE_STRING FileName;
  333. NTSTATUS Status;
  334. RtlInitUnicodeString(&FileName, L"\\DosDevices\\c:\\receive.log");
  335. InitializeObjectAttributes(
  336. &ObjectAttributes,
  337. &FileName,
  338. OBJ_CASE_INSENSITIVE,
  339. NULL,
  340. NULL
  341. );
  342. Status=ZwCreateFile(
  343. &pThisDev->ReceiveFileHandle,
  344. GENERIC_WRITE | SYNCHRONIZE,
  345. &ObjectAttributes,
  346. &IoStatusBlock,
  347. 0,
  348. FILE_ATTRIBUTE_NORMAL,
  349. FILE_SHARE_READ,
  350. FILE_OVERWRITE_IF,
  351. FILE_SYNCHRONOUS_IO_NONALERT,
  352. NULL,
  353. 0
  354. );
  355. pThisDev->ReceiveFilePosition = 0;
  356. }
  357. else
  358. {
  359. if( pThisDev->ReceiveFileHandle )
  360. {
  361. ZwClose( pThisDev->ReceiveFileHandle );
  362. pThisDev->ReceiveFileHandle = 0;
  363. pThisDev->ReceiveFilePosition = 0;
  364. }
  365. }
  366. #endif
  367. #if defined(RECEIVE_ERROR_LOGGING)
  368. if( pThisDev->linkSpeedInfo->BitsPerSec==SPEED_4000000 )
  369. {
  370. IO_STATUS_BLOCK IoStatusBlock;
  371. OBJECT_ATTRIBUTES ObjectAttributes;
  372. UNICODE_STRING FileName;
  373. NTSTATUS Status;
  374. RtlInitUnicodeString(&FileName, L"\\DosDevices\\c:\\receive_error.log");
  375. InitializeObjectAttributes(
  376. &ObjectAttributes,
  377. &FileName,
  378. OBJ_CASE_INSENSITIVE,
  379. NULL,
  380. NULL
  381. );
  382. Status=ZwCreateFile(
  383. &pThisDev->ReceiveErrorFileHandle,
  384. GENERIC_WRITE | SYNCHRONIZE,
  385. &ObjectAttributes,
  386. &IoStatusBlock,
  387. 0,
  388. FILE_ATTRIBUTE_NORMAL,
  389. FILE_SHARE_READ,
  390. FILE_OVERWRITE_IF,
  391. FILE_SYNCHRONOUS_IO_NONALERT,
  392. NULL,
  393. 0
  394. );
  395. pThisDev->ReceiveErrorFilePosition = 0;
  396. }
  397. else
  398. {
  399. if( pThisDev->ReceiveErrorFileHandle )
  400. {
  401. ZwClose( pThisDev->ReceiveErrorFileHandle );
  402. pThisDev->ReceiveErrorFileHandle = 0;
  403. pThisDev->ReceiveErrorFilePosition = 0;
  404. }
  405. }
  406. #endif
  407. #if defined(SEND_LOGGING)
  408. if( pThisDev->linkSpeedInfo->BitsPerSec==SPEED_4000000 )
  409. {
  410. IO_STATUS_BLOCK IoStatusBlock;
  411. OBJECT_ATTRIBUTES ObjectAttributes;
  412. UNICODE_STRING FileName;
  413. NTSTATUS Status;
  414. RtlInitUnicodeString(&FileName, L"\\DosDevices\\c:\\send.log");
  415. InitializeObjectAttributes(
  416. &ObjectAttributes,
  417. &FileName,
  418. OBJ_CASE_INSENSITIVE,
  419. NULL,
  420. NULL
  421. );
  422. Status=ZwCreateFile(
  423. &pThisDev->SendFileHandle,
  424. GENERIC_WRITE | SYNCHRONIZE,
  425. &ObjectAttributes,
  426. &IoStatusBlock,
  427. 0,
  428. FILE_ATTRIBUTE_NORMAL,
  429. FILE_SHARE_READ,
  430. FILE_OVERWRITE_IF,
  431. FILE_SYNCHRONOUS_IO_NONALERT,
  432. NULL,
  433. 0
  434. );
  435. pThisDev->SendFilePosition = 0;
  436. }
  437. else
  438. {
  439. if( pThisDev->SendFileHandle )
  440. {
  441. ZwClose( pThisDev->SendFileHandle );
  442. pThisDev->SendFileHandle = 0;
  443. pThisDev->SendFilePosition = 0;
  444. }
  445. }
  446. #endif
  447. //
  448. // Always force a new tuning
  449. //
  450. if( (Status = St4200TuneDpllAndSensitivity(pThisDev, pThisDev->linkSpeedInfo->BitsPerSec)) != STATUS_SUCCESS )
  451. {
  452. DEBUGMSG(DBG_ERR, (" St4200TuneDpllAndSensitivity(): USB failure\n"));
  453. goto done;
  454. }
  455. //
  456. // First power down the modulator
  457. //
  458. #if !defined(FAST_WRITE_REGISTERS)
  459. if( (Status = St4200ReadRegisters(pThisDev, STIR4200_CONTROL_REG, 1)) != STATUS_SUCCESS )
  460. {
  461. DEBUGMSG(DBG_ERR, (" St4200SetSpeed(): USB failure\n"));
  462. goto done;
  463. }
  464. #endif
  465. pThisDev->StIrTranceiver.ControlReg |= (STIR4200_CTRL_TXPWD | STIR4200_CTRL_RXPWD);
  466. pThisDev->StIrTranceiver.ControlReg |= STIR4200_CTRL_RXSLOW;
  467. if( (Status = St4200WriteRegister(pThisDev, STIR4200_CONTROL_REG)) != STATUS_SUCCESS )
  468. {
  469. DEBUGMSG(DBG_ERR, (" St4200SetSpeed(): USB failure\n"));
  470. goto done;
  471. }
  472. //
  473. // Then set baudrate
  474. //
  475. pThisDev->StIrTranceiver.BaudrateReg = pThisDev->linkSpeedInfo->Stir4200Divisor;
  476. if( (Status = St4200WriteRegister(pThisDev, STIR4200_BAUDRATE_REG)) != STATUS_SUCCESS )
  477. {
  478. DEBUGMSG(DBG_ERR, (" St4200SetSpeed(): USB failure\n"));
  479. goto done;
  480. }
  481. //
  482. // We'll have to write the MSB of baud-rate too (only for 2400)
  483. //
  484. if( pThisDev->linkSpeedInfo->BitsPerSec == SPEED_2400 )
  485. {
  486. pThisDev->StIrTranceiver.ModeReg |= STIR4200_MODE_PDLCK8;
  487. if( (Status = St4200WriteRegister(pThisDev, STIR4200_MODE_REG)) != STATUS_SUCCESS )
  488. {
  489. DEBUGMSG(DBG_ERR, (" St4200SetSpeed(): USB failure\n"));
  490. goto done;
  491. }
  492. }
  493. else
  494. {
  495. if( pThisDev->StIrTranceiver.ModeReg & STIR4200_MODE_PDLCK8 )
  496. {
  497. pThisDev->StIrTranceiver.ModeReg &= ~STIR4200_MODE_PDLCK8;
  498. if( (Status = St4200WriteRegister(pThisDev, STIR4200_MODE_REG)) != STATUS_SUCCESS )
  499. {
  500. DEBUGMSG(DBG_ERR, (" St4200SetSpeed(): USB failure\n"));
  501. goto done;
  502. }
  503. }
  504. }
  505. //
  506. // Modulator back up
  507. //
  508. pThisDev->StIrTranceiver.ControlReg &= (~(STIR4200_CTRL_TXPWD | STIR4200_CTRL_RXPWD));
  509. if( (Status = St4200WriteRegister(pThisDev, STIR4200_CONTROL_REG)) != STATUS_SUCCESS )
  510. {
  511. DEBUGMSG(DBG_ERR, (" St4200SetSpeed(): USB failure\n"));
  512. goto done;
  513. }
  514. //
  515. // then IR mode
  516. //
  517. Status = St4200SetIrMode( pThisDev, pThisDev->linkSpeedInfo->IrMode );
  518. if( Status != STATUS_SUCCESS )
  519. {
  520. DEBUGMSG(DBG_ERR, (" St4200SetSpeed(): USB failure\n"));
  521. goto done;
  522. }
  523. //
  524. // Unmute it
  525. //
  526. pThisDev->StIrTranceiver.ControlReg &= ~STIR4200_CTRL_RXSLOW;
  527. if( (Status = St4200WriteRegister(pThisDev, STIR4200_CONTROL_REG)) != STATUS_SUCCESS )
  528. {
  529. DEBUGMSG(DBG_ERR, (" St4200SetSpeed(): USB failure\n"));
  530. goto done;
  531. }
  532. //
  533. // Program the receive delay for FIR
  534. //
  535. if( pThisDev->linkSpeedInfo->BitsPerSec == SPEED_4000000 )
  536. {
  537. if( pThisDev->dongleCaps.windowSize == 2 )
  538. pThisDev->ReceiveAdaptiveDelay = STIR4200_MULTIPLE_READ_DELAY;
  539. else
  540. pThisDev->ReceiveAdaptiveDelay = 0;
  541. pThisDev->ReceiveAdaptiveDelayBoost = 0;
  542. }
  543. #if defined(WORKAROUND_GEAR_DOWN)
  544. //
  545. // Force a reset if going to 9600 from 4M
  546. //
  547. pThisDev->GearedDown = FALSE;
  548. if( pThisDev->linkSpeedInfo->BitsPerSec==SPEED_9600 && pThisDev->currentSpeed==SPEED_4000000 )
  549. {
  550. St4200ResetFifo( pThisDev );
  551. pThisDev->GearedDown = TRUE;
  552. }
  553. #endif
  554. done:
  555. return STATUS_SUCCESS;
  556. }
  557. /*****************************************************************************
  558. *
  559. * Function: St4200GetFifoCount
  560. *
  561. * Synopsis: Verifies if there is data to be received
  562. *
  563. * Arguments: pDevice - pointer to current ir device object
  564. * pCountFifo - pointer to variable to return FIFO count
  565. *
  566. * Returns: NT_STATUS
  567. *
  568. *
  569. *****************************************************************************/
  570. NTSTATUS
  571. St4200GetFifoCount(
  572. IN PVOID pDevice,
  573. OUT PULONG pCountFifo
  574. )
  575. {
  576. NTSTATUS Status = STATUS_SUCCESS;
  577. PIR_DEVICE pThisDev = (PIR_DEVICE)pDevice;
  578. *pCountFifo = 0;
  579. if( pThisDev->PreFifoCount )
  580. {
  581. *pCountFifo = pThisDev->PreFifoCount;
  582. }
  583. else
  584. {
  585. Status = St4200ReadRegisters( pThisDev, STIR4200_FIFOCNT_LSB_REG, 2 );
  586. if( Status == STATUS_SUCCESS )
  587. {
  588. *pCountFifo =
  589. ((ULONG)MAKEUSHORT(pThisDev->StIrTranceiver.FifoCntLsbReg, pThisDev->StIrTranceiver.FifoCntMsbReg));
  590. }
  591. }
  592. pThisDev->PreFifoCount = 0;
  593. return Status;
  594. }
  595. /*****************************************************************************
  596. *
  597. * Function: St4200TuneDpllAndSensitivity
  598. *
  599. * Synopsis: tunes the DPLL and sensitivity registers
  600. *
  601. * Arguments: pDevice - pointer to current ir device object
  602. * Speed - speed to tune for
  603. *
  604. * Returns: NT_STATUS
  605. *
  606. *
  607. *****************************************************************************/
  608. NTSTATUS
  609. St4200TuneDpllAndSensitivity(
  610. IN OUT PVOID pDevice,
  611. ULONG Speed
  612. )
  613. {
  614. NTSTATUS Status;
  615. PIR_DEVICE pThisDev = (PIR_DEVICE)pDevice;
  616. #if !defined(FAST_WRITE_REGISTERS)
  617. //
  618. // Read the current value of the DPLL
  619. //
  620. if( (Status = St4200ReadRegisters(pThisDev, STIR4200_DPLLTUNE_REG, 1)) != STATUS_SUCCESS )
  621. {
  622. DEBUGMSG(DBG_ERR, (" St4200TuneDpllAndSensitivity(): USB failure\n"));
  623. goto done;
  624. }
  625. #endif
  626. //
  627. // Tune the DPLL according to the installed transceiver
  628. //
  629. switch( pThisDev->TransceiverType )
  630. {
  631. case TRANSCEIVER_INFINEON:
  632. pThisDev->StIrTranceiver.DpllTuneReg = STIR4200_DPLL_DESIRED_INFI;
  633. break;
  634. case TRANSCEIVER_VISHAY:
  635. pThisDev->StIrTranceiver.DpllTuneReg = STIR4200_DPLL_DESIRED_VISHAY;
  636. break;
  637. case TRANSCEIVER_4000:
  638. pThisDev->StIrTranceiver.DpllTuneReg = STIR4200_DPLL_DESIRED_4000;
  639. break;
  640. case TRANSCEIVER_4012:
  641. default:
  642. switch( Speed )
  643. {
  644. case SPEED_9600:
  645. case SPEED_19200:
  646. case SPEED_38400:
  647. case SPEED_57600:
  648. case SPEED_115200:
  649. pThisDev->StIrTranceiver.DpllTuneReg = STIR4200_DPLL_DESIRED_4012_SIR; //(UCHAR)pThisDev->SirDpll;
  650. break;
  651. case SPEED_4000000:
  652. pThisDev->StIrTranceiver.DpllTuneReg = STIR4200_DPLL_DESIRED_4012_FIR; //(UCHAR)pThisDev->FirDpll;
  653. break;
  654. default:
  655. pThisDev->StIrTranceiver.DpllTuneReg = STIR4200_DPLL_DESIRED_4012;
  656. break;
  657. }
  658. break;
  659. }
  660. if( (Status = St4200WriteRegister(pThisDev, STIR4200_DPLLTUNE_REG)) != STATUS_SUCCESS )
  661. {
  662. DEBUGMSG(DBG_ERR, (" St4200TuneDpllAndSensitivity(): USB failure\n"));
  663. goto done;
  664. }
  665. #if !defined(FAST_WRITE_REGISTERS)
  666. //
  667. // Read the current value of the sensitivity
  668. //
  669. if( (Status = St4200ReadRegisters(pThisDev, STIR4200_SENSITIVITY_REG, 1)) != STATUS_SUCCESS )
  670. {
  671. DEBUGMSG(DBG_ERR, (" St4200TuneDpllAndSensitivity(): USB failure\n"));
  672. goto done;
  673. }
  674. #endif
  675. //
  676. // Tune the sensitivity
  677. //
  678. switch( pThisDev->TransceiverType )
  679. {
  680. case TRANSCEIVER_INFINEON:
  681. switch( Speed )
  682. {
  683. default:
  684. case SPEED_9600:
  685. case SPEED_19200:
  686. case SPEED_38400:
  687. case SPEED_57600:
  688. case SPEED_115200:
  689. pThisDev->StIrTranceiver.SensitivityReg = STIR4200_SENS_RXDSNS_INFI_SIR;//(UCHAR)pThisDev->SirSensitivity;
  690. break;
  691. case SPEED_4000000:
  692. pThisDev->StIrTranceiver.SensitivityReg = STIR4200_SENS_RXDSNS_INFI_FIR;//(UCHAR)pThisDev->FirSensitivity;
  693. break;
  694. }
  695. break;
  696. case TRANSCEIVER_VISHAY:
  697. pThisDev->StIrTranceiver.SensitivityReg = STIR4200_SENS_RXDSNS_DEFAULT;
  698. break;
  699. case TRANSCEIVER_4000:
  700. pThisDev->StIrTranceiver.SensitivityReg = STIR4200_SENS_RXDSNS_DEFAULT;
  701. break;
  702. case TRANSCEIVER_4012:
  703. default:
  704. switch( Speed )
  705. {
  706. default:
  707. case SPEED_9600:
  708. pThisDev->StIrTranceiver.SensitivityReg = STIR4200_SENS_RXDSNS_4012_SIR_9600;
  709. break;
  710. case SPEED_19200:
  711. case SPEED_38400:
  712. case SPEED_57600:
  713. case SPEED_115200:
  714. pThisDev->StIrTranceiver.SensitivityReg = STIR4200_SENS_RXDSNS_4012_SIR;//(UCHAR)pThisDev->SirSensitivity;
  715. break;
  716. case SPEED_4000000:
  717. pThisDev->StIrTranceiver.SensitivityReg = STIR4200_SENS_RXDSNS_4012_FIR;//(UCHAR)pThisDev->FirSensitivity;
  718. break;
  719. }
  720. break;
  721. }
  722. if( (Status = St4200WriteRegister(pThisDev, STIR4200_SENSITIVITY_REG)) != STATUS_SUCCESS )
  723. {
  724. DEBUGMSG(DBG_ERR, (" St4200TuneDpllAndSensitivity(): USB failure\n"));
  725. goto done;
  726. }
  727. done:
  728. return Status;
  729. }
  730. /*****************************************************************************
  731. *
  732. * Function: St4200EnableOscillatorPowerDown
  733. *
  734. * Synopsis: enable the oscillator to power down when we go into suspend mode
  735. *
  736. * Arguments: pDevice - pointer to current ir device object
  737. *
  738. * Returns: NT_STATUS
  739. *
  740. *
  741. *****************************************************************************/
  742. NTSTATUS
  743. St4200EnableOscillatorPowerDown(
  744. IN OUT PVOID pDevice
  745. )
  746. {
  747. NTSTATUS Status;
  748. PIR_DEVICE pThisDev = (PIR_DEVICE)pDevice;
  749. #if !defined(FAST_WRITE_REGISTERS)
  750. //
  751. // Read the current value
  752. //
  753. if( (Status = St4200ReadRegisters(pThisDev, STIR4200_TEST_REG, 1)) != STATUS_SUCCESS )
  754. {
  755. DEBUGMSG(DBG_ERR, (" St4200EnableOscillatorPowerDown(): USB failure\n"));
  756. goto done;
  757. }
  758. #endif
  759. //
  760. // Enable
  761. //
  762. pThisDev->StIrTranceiver.TestReg |= STIR4200_TEST_EN_OSC_SUSPEND;
  763. if( (Status = St4200WriteRegister(pThisDev, STIR4200_TEST_REG)) != STATUS_SUCCESS )
  764. {
  765. DEBUGMSG(DBG_ERR, (" St4200EnableOscillatorPowerDown(): USB failure\n"));
  766. goto done;
  767. }
  768. done:
  769. return Status;
  770. }
  771. /*****************************************************************************
  772. *
  773. * Function: St4200TurnOnSuspend
  774. *
  775. * Synopsis: prepares the part to go into suspend mode
  776. *
  777. * Arguments: pDevice - pointer to current ir device object
  778. *
  779. * Returns: NT_STATUS
  780. *
  781. *
  782. *****************************************************************************/
  783. NTSTATUS
  784. St4200TurnOnSuspend(
  785. IN OUT PVOID pDevice
  786. )
  787. {
  788. NTSTATUS Status;
  789. PIR_DEVICE pThisDev = (PIR_DEVICE)pDevice;
  790. #if !defined(FAST_WRITE_REGISTERS)
  791. //
  792. // Read the current value
  793. //
  794. if( (Status = St4200ReadRegisters(pThisDev, STIR4200_CONTROL_REG, 1)) != STATUS_SUCCESS )
  795. {
  796. DEBUGMSG(DBG_ERR, (" St4200TurnOnSuspend(): USB failure\n"));
  797. goto done;
  798. }
  799. #endif
  800. //
  801. // Control UOUT
  802. //
  803. pThisDev->StIrTranceiver.ControlReg |= STIR4200_CTRL_SDMODE;
  804. if( (Status = St4200WriteRegister(pThisDev, STIR4200_CONTROL_REG)) != STATUS_SUCCESS )
  805. {
  806. DEBUGMSG(DBG_ERR, (" St4200TurnOnSuspend(): USB failure\n"));
  807. goto done;
  808. }
  809. done:
  810. return Status;
  811. }
  812. /*****************************************************************************
  813. *
  814. * Function: St4200TurnOffSuspend
  815. *
  816. * Synopsis: prepares the part to go back into operational mode
  817. *
  818. * Arguments: pDevice - pointer to current ir device object
  819. *
  820. * Returns: NT_STATUS
  821. *
  822. *
  823. *****************************************************************************/
  824. NTSTATUS
  825. St4200TurnOffSuspend(
  826. IN OUT PVOID pDevice
  827. )
  828. {
  829. NTSTATUS Status;
  830. PIR_DEVICE pThisDev = (PIR_DEVICE)pDevice;
  831. #if !defined(FAST_WRITE_REGISTERS)
  832. //
  833. // Read the current value
  834. //
  835. if( (Status = St4200ReadRegisters(pThisDev, STIR4200_CONTROL_REG, 1)) != STATUS_SUCCESS )
  836. {
  837. DEBUGMSG(DBG_ERR, (" St4200TurnOffSuspend(): USB failure\n"));
  838. goto done;
  839. }
  840. #endif
  841. //
  842. // Control UOUT
  843. //
  844. pThisDev->StIrTranceiver.ControlReg &= ~STIR4200_CTRL_SDMODE;
  845. if( (Status = St4200WriteRegister(pThisDev, STIR4200_CONTROL_REG)) != STATUS_SUCCESS )
  846. {
  847. DEBUGMSG(DBG_ERR, (" St4200TurnOffSuspend(): USB failure\n"));
  848. goto done;
  849. }
  850. done:
  851. return Status;
  852. }
  853. /*****************************************************************************
  854. *
  855. * Function: St4200TurnOffReceiver
  856. *
  857. * Synopsis: turns of the STIr4200 receiver
  858. *
  859. * Arguments: pDevice - pointer to current ir device object
  860. *
  861. * Returns: NT_STATUS
  862. *
  863. *
  864. *****************************************************************************/
  865. NTSTATUS
  866. St4200TurnOffReceiver(
  867. IN OUT PVOID pDevice
  868. )
  869. {
  870. NTSTATUS Status;
  871. PIR_DEVICE pThisDev = (PIR_DEVICE)pDevice;
  872. #if !defined(FAST_WRITE_REGISTERS)
  873. //
  874. // Read the current value
  875. //
  876. if( (Status = St4200ReadRegisters(pThisDev, STIR4200_CONTROL_REG, 1)) != STATUS_SUCCESS )
  877. {
  878. DEBUGMSG(DBG_ERR, (" St4200TurnOffReceiver(): USB failure\n"));
  879. goto done;
  880. }
  881. #endif
  882. //
  883. // Turn off receiver
  884. //
  885. pThisDev->StIrTranceiver.ControlReg |= STIR4200_CTRL_RXPWD;
  886. if( (Status = St4200WriteRegister(pThisDev, STIR4200_CONTROL_REG)) != STATUS_SUCCESS )
  887. {
  888. DEBUGMSG(DBG_ERR, (" St4200TurnOffReceiver(): USB failure\n"));
  889. goto done;
  890. }
  891. done:
  892. return Status;
  893. }
  894. /*****************************************************************************
  895. *
  896. * Function: St4200TurnOnReceiver
  897. *
  898. * Synopsis: turns on the STIr4200 receiver
  899. *
  900. * Arguments: pDevice - pointer to current ir device object
  901. *
  902. * Returns: NT_STATUS
  903. *
  904. *
  905. *****************************************************************************/
  906. NTSTATUS
  907. St4200TurnOnReceiver(
  908. IN OUT PVOID pDevice
  909. )
  910. {
  911. NTSTATUS Status;
  912. PIR_DEVICE pThisDev = (PIR_DEVICE)pDevice;
  913. #if !defined(FAST_WRITE_REGISTERS)
  914. //
  915. // Read the current value
  916. //
  917. if( (Status = St4200ReadRegisters(pThisDev, STIR4200_CONTROL_REG, 1)) != STATUS_SUCCESS )
  918. {
  919. DEBUGMSG(DBG_ERR, (" St4200TurnOnReceiver(): USB failure\n"));
  920. goto done;
  921. }
  922. #endif
  923. //
  924. // Turn on receiver
  925. //
  926. pThisDev->StIrTranceiver.ControlReg &= ~STIR4200_CTRL_RXPWD;
  927. if( (Status = St4200WriteRegister(pThisDev, STIR4200_CONTROL_REG)) != STATUS_SUCCESS )
  928. {
  929. DEBUGMSG(DBG_ERR, (" St4200TurnOnReceiver(): USB failure\n"));
  930. goto done;
  931. }
  932. done:
  933. return Status;
  934. }
  935. /*****************************************************************************
  936. *
  937. * Function: St4200WriteMultipleRegisters
  938. *
  939. * Synopsis: reads multiple registers from the tranceiver
  940. *
  941. * Arguments: pDevice - pointer to current ir device object
  942. * FirstRegister - first register to write
  943. * RegistersToWrite - number of registers
  944. *
  945. * Returns: NT_STATUS
  946. *
  947. *
  948. *****************************************************************************/
  949. NTSTATUS
  950. St4200WriteMultipleRegisters(
  951. IN PVOID pDevice,
  952. UCHAR FirstRegister,
  953. UCHAR RegistersToWrite
  954. )
  955. {
  956. NTSTATUS status;
  957. PIRUSB_CONTEXT pThisContext;
  958. PURB pUrb = NULL;
  959. PDEVICE_OBJECT pUrbTargetDev;
  960. PIO_STACK_LOCATION pNextStack;
  961. PIRP pIrp;
  962. PIR_DEVICE pThisDev = (PIR_DEVICE)pDevice;
  963. PLIST_ENTRY pListEntry;
  964. DEBUGMSG(DBG_FUNC, ("+St4200WriteMultipleRegisters\n"));
  965. IRUSB_ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );
  966. //
  967. // Make sure there isn't a halt/reset going on
  968. //
  969. if( pThisDev->fPendingHalt || pThisDev->fPendingReset || pThisDev->fPendingClearTotalStall )
  970. {
  971. DEBUGMSG(DBG_ERR, (" St4200WriteMultipleRegisters abort due to pending reset\n"));
  972. status = STATUS_UNSUCCESSFUL;
  973. goto done;
  974. }
  975. //
  976. // Validate the parameters
  977. //
  978. if( (FirstRegister+RegistersToWrite)>(STIR4200_MAX_REG+1) )
  979. {
  980. DEBUGMSG(DBG_ERR, (" St4200WriteMultipleRegisters invalid input parameters\n"));
  981. status = STATUS_UNSUCCESSFUL;
  982. goto done;
  983. }
  984. pListEntry = ExInterlockedRemoveHeadList( &pThisDev->SendAvailableQueue, &pThisDev->SendLock );
  985. if( NULL == pListEntry )
  986. {
  987. //
  988. // This must not happen
  989. //
  990. DEBUGMSG(DBG_ERR, (" St4200WriteMultipleRegisters failed to find a free context struct\n"));
  991. IRUSB_ASSERT( 0 );
  992. status = STATUS_UNSUCCESSFUL;
  993. goto done;
  994. }
  995. InterlockedDecrement( &pThisDev->SendAvailableCount );
  996. pThisContext = CONTAINING_RECORD( pListEntry, IRUSB_CONTEXT, ListEntry );
  997. pThisContext->ContextType = CONTEXT_READ_WRITE_REGISTER;
  998. pUrb = pThisDev->pUrb;
  999. NdisZeroMemory( pUrb, pThisDev->UrbLen );
  1000. //
  1001. // Now that we have created the urb, we will send a
  1002. // request to the USB device object.
  1003. //
  1004. pUrbTargetDev = pThisDev->pUsbDevObj;
  1005. //
  1006. // make an irp sending to usbhub
  1007. //
  1008. pIrp = IoAllocateIrp( (CCHAR)(pThisDev->pUsbDevObj->StackSize + 1), FALSE );
  1009. if( NULL == pIrp )
  1010. {
  1011. DEBUGMSG(DBG_ERR, (" St4200WriteMultipleRegisters failed to alloc IRP\n"));
  1012. ExInterlockedInsertTailList(
  1013. &pThisDev->SendAvailableQueue,
  1014. &pThisContext->ListEntry,
  1015. &pThisDev->SendLock
  1016. );
  1017. InterlockedIncrement( &pThisDev->SendAvailableCount );
  1018. status = STATUS_UNSUCCESSFUL;
  1019. goto done;
  1020. }
  1021. pIrp->IoStatus.Status = STATUS_PENDING;
  1022. pIrp->IoStatus.Information = 0;
  1023. pThisContext->pIrp = pIrp;
  1024. //
  1025. // Build our URB for USBD
  1026. //
  1027. pUrb->UrbControlVendorClassRequest.Hdr.Length = (USHORT)sizeof( struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST );
  1028. pUrb->UrbControlVendorClassRequest.Hdr.Function = URB_FUNCTION_VENDOR_DEVICE;
  1029. pUrb->UrbControlVendorClassRequest.TransferFlags = USBD_TRANSFER_DIRECTION_OUT;
  1030. // short packet is not treated as an error.
  1031. pUrb->UrbControlVendorClassRequest.TransferFlags |= USBD_SHORT_TRANSFER_OK;
  1032. pUrb->UrbControlVendorClassRequest.UrbLink = NULL;
  1033. pUrb->UrbControlVendorClassRequest.TransferBufferMDL = NULL;
  1034. pUrb->UrbControlVendorClassRequest.TransferBuffer = &(pThisDev->StIrTranceiver.FifoDataReg)+FirstRegister;
  1035. pUrb->UrbControlVendorClassRequest.TransferBufferLength = RegistersToWrite;
  1036. pUrb->UrbControlVendorClassRequest.Request = STIR4200_WRITE_REGS_REQ;
  1037. pUrb->UrbControlVendorClassRequest.RequestTypeReservedBits = 0;
  1038. pUrb->UrbControlVendorClassRequest.Index = FirstRegister;
  1039. //
  1040. // Call the class driver to perform the operation.
  1041. //
  1042. pNextStack = IoGetNextIrpStackLocation( pIrp );
  1043. IRUSB_ASSERT( pNextStack != NULL );
  1044. //
  1045. // pass the URB to the USB driver stack
  1046. //
  1047. pNextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  1048. pNextStack->Parameters.Others.Argument1 = pUrb;
  1049. pNextStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
  1050. IoSetCompletionRoutine(
  1051. pIrp, // irp to use
  1052. St4200CompleteReadWriteRequest, // routine to call when irp is done
  1053. DEV_TO_CONTEXT(pThisContext), // context to pass routine
  1054. TRUE, // call on success
  1055. TRUE, // call on error
  1056. TRUE // call on cancel
  1057. );
  1058. KeClearEvent( &pThisDev->EventSyncUrb );
  1059. //
  1060. // Call IoCallDriver to send the irp to the usb port.
  1061. //
  1062. ExInterlockedInsertTailList(
  1063. &pThisDev->ReadWritePendingQueue,
  1064. &pThisContext->ListEntry,
  1065. &pThisDev->SendLock
  1066. );
  1067. InterlockedIncrement( &pThisDev->ReadWritePendingCount );
  1068. status = MyIoCallDriver( pThisDev, pUrbTargetDev, pIrp );
  1069. //
  1070. // The USB driver should always return STATUS_PENDING when
  1071. // it receives a write irp
  1072. //
  1073. if( (status == STATUS_PENDING) || (status == STATUS_SUCCESS) )
  1074. {
  1075. // wait, but dump out on timeout
  1076. if( status == STATUS_PENDING )
  1077. {
  1078. status = MyKeWaitForSingleObject( pThisDev, &pThisDev->EventSyncUrb, NULL, 0 );
  1079. if( status == STATUS_TIMEOUT )
  1080. {
  1081. KIRQL OldIrql;
  1082. DEBUGMSG( DBG_ERR,(" St4200WriteMultipleRegisters() TIMED OUT! return from IoCallDriver USBD %x\n", status));
  1083. KeAcquireSpinLock( &pThisDev->SendLock, &OldIrql );
  1084. RemoveEntryList( &pThisContext->ListEntry );
  1085. KeReleaseSpinLock( &pThisDev->SendLock, OldIrql );
  1086. InterlockedDecrement( &pThisDev->ReadWritePendingCount );
  1087. IrUsb_CancelIo( pThisDev, pIrp, &pThisDev->EventSyncUrb );
  1088. }
  1089. }
  1090. }
  1091. else
  1092. {
  1093. DEBUGMSG( DBG_ERR, (" St4200WriteMultipleRegisters IoCallDriver FAILED(%x)\n",status));
  1094. IRUSB_ASSERT( status == STATUS_PENDING );
  1095. }
  1096. done:
  1097. DEBUGMSG(DBG_FUNC, ("-St4200WriteMultipleRegisters\n"));
  1098. return status;
  1099. }
  1100. /*****************************************************************************
  1101. *
  1102. * Function: St4200WriteRegister
  1103. *
  1104. * Synopsis: writes a STIr4200 register
  1105. *
  1106. * Arguments: pDevice - pointer to current ir device object
  1107. * FirstRegister - first register to write
  1108. *
  1109. * Returns: NT_STATUS
  1110. *
  1111. *
  1112. *****************************************************************************/
  1113. NTSTATUS
  1114. St4200WriteRegister(
  1115. IN PVOID pDevice,
  1116. UCHAR RegisterToWrite
  1117. )
  1118. {
  1119. NTSTATUS status;
  1120. PIRUSB_CONTEXT pThisContext;
  1121. PURB pUrb = NULL;
  1122. PDEVICE_OBJECT pUrbTargetDev;
  1123. PIO_STACK_LOCATION pNextStack;
  1124. PIRP pIrp;
  1125. PIR_DEVICE pThisDev = (PIR_DEVICE)pDevice;
  1126. PLIST_ENTRY pListEntry;
  1127. DEBUGMSG(DBG_FUNC, ("+St4200WriteRegister\n"));
  1128. IRUSB_ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );
  1129. //
  1130. // Make sure there isn't a halt/reset going on
  1131. //
  1132. if( pThisDev->fPendingHalt || pThisDev->fPendingReset || pThisDev->fPendingClearTotalStall )
  1133. {
  1134. DEBUGMSG(DBG_ERR, (" St4200WriteRegister abort due to pending reset\n"));
  1135. status = STATUS_UNSUCCESSFUL;
  1136. goto done;
  1137. }
  1138. //
  1139. // Validate the parameters
  1140. //
  1141. if( RegisterToWrite>STIR4200_MAX_REG )
  1142. {
  1143. DEBUGMSG(DBG_ERR, (" St4200WriteRegister invalid input parameters\n"));
  1144. status = STATUS_UNSUCCESSFUL;
  1145. goto done;
  1146. }
  1147. pListEntry = ExInterlockedRemoveHeadList( &pThisDev->SendAvailableQueue, &pThisDev->SendLock );
  1148. if( NULL == pListEntry )
  1149. {
  1150. //
  1151. // This must not happen
  1152. //
  1153. DEBUGMSG(DBG_ERR, (" St4200WriteRegister failed to find a free context struct\n"));
  1154. IRUSB_ASSERT( 0 );
  1155. status = STATUS_UNSUCCESSFUL;
  1156. goto done;
  1157. }
  1158. InterlockedDecrement( &pThisDev->SendAvailableCount );
  1159. pThisContext = CONTAINING_RECORD( pListEntry, IRUSB_CONTEXT, ListEntry );
  1160. pThisContext->ContextType = CONTEXT_READ_WRITE_REGISTER;
  1161. pUrb = pThisDev->pUrb;
  1162. NdisZeroMemory( pUrb, pThisDev->UrbLen );
  1163. //
  1164. // Now that we have created the urb, we will send a
  1165. // request to the USB device object.
  1166. //
  1167. pUrbTargetDev = pThisDev->pUsbDevObj;
  1168. //
  1169. // make an irp sending to usbhub
  1170. //
  1171. pIrp = IoAllocateIrp( (CCHAR)(pThisDev->pUsbDevObj->StackSize + 1), FALSE );
  1172. if( NULL == pIrp )
  1173. {
  1174. DEBUGMSG(DBG_ERR, (" St4200WriteRegister failed to alloc IRP\n"));
  1175. ExInterlockedInsertTailList(
  1176. &pThisDev->SendAvailableQueue,
  1177. &pThisContext->ListEntry,
  1178. &pThisDev->SendLock
  1179. );
  1180. InterlockedIncrement( &pThisDev->SendAvailableCount );
  1181. status = STATUS_UNSUCCESSFUL;
  1182. goto done;
  1183. }
  1184. pIrp->IoStatus.Status = STATUS_PENDING;
  1185. pIrp->IoStatus.Information = 0;
  1186. pThisContext->pIrp = pIrp;
  1187. //
  1188. // Build our URB for USBD
  1189. //
  1190. pUrb->UrbControlVendorClassRequest.Hdr.Length = (USHORT) sizeof( struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST );
  1191. pUrb->UrbControlVendorClassRequest.Hdr.Function = URB_FUNCTION_VENDOR_DEVICE;
  1192. pUrb->UrbControlVendorClassRequest.TransferFlags = USBD_TRANSFER_DIRECTION_OUT;
  1193. // short packet is not treated as an error.
  1194. pUrb->UrbControlVendorClassRequest.TransferFlags |= USBD_SHORT_TRANSFER_OK;
  1195. pUrb->UrbControlVendorClassRequest.UrbLink = NULL;
  1196. pUrb->UrbControlVendorClassRequest.TransferBufferMDL = NULL;
  1197. pUrb->UrbControlVendorClassRequest.Value = *(&pThisDev->StIrTranceiver.FifoDataReg+RegisterToWrite);
  1198. pUrb->UrbControlVendorClassRequest.Request = STIR4200_WRITE_REG_REQ;
  1199. pUrb->UrbControlVendorClassRequest.RequestTypeReservedBits = 0;
  1200. pUrb->UrbControlVendorClassRequest.Index = RegisterToWrite;
  1201. //
  1202. // Call the class driver to perform the operation.
  1203. //
  1204. pNextStack = IoGetNextIrpStackLocation( pIrp );
  1205. IRUSB_ASSERT( pNextStack != NULL );
  1206. //
  1207. // pass the URB to the USB driver stack
  1208. //
  1209. pNextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  1210. pNextStack->Parameters.Others.Argument1 = pUrb;
  1211. pNextStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
  1212. IoSetCompletionRoutine(
  1213. pIrp, // irp to use
  1214. St4200CompleteReadWriteRequest, // routine to call when irp is done
  1215. DEV_TO_CONTEXT(pThisContext), // context to pass routine
  1216. TRUE, // call on success
  1217. TRUE, // call on error
  1218. TRUE // call on cancel
  1219. );
  1220. KeClearEvent( &pThisDev->EventSyncUrb );
  1221. //
  1222. // Call IoCallDriver to send the irp to the usb port.
  1223. //
  1224. ExInterlockedInsertTailList(
  1225. &pThisDev->ReadWritePendingQueue,
  1226. &pThisContext->ListEntry,
  1227. &pThisDev->SendLock
  1228. );
  1229. InterlockedIncrement( &pThisDev->ReadWritePendingCount );
  1230. status = MyIoCallDriver( pThisDev, pUrbTargetDev, pIrp );
  1231. //
  1232. // The USB driver should always return STATUS_PENDING when
  1233. // it receives a write irp
  1234. //
  1235. if( (status == STATUS_PENDING) || (status == STATUS_SUCCESS) )
  1236. {
  1237. // wait, but dump out on timeout
  1238. if( status == STATUS_PENDING )
  1239. {
  1240. status = MyKeWaitForSingleObject( pThisDev, &pThisDev->EventSyncUrb, NULL, 0 );
  1241. if( status == STATUS_TIMEOUT )
  1242. {
  1243. KIRQL OldIrql;
  1244. DEBUGMSG( DBG_ERR,(" St4200WriteRegister() TIMED OUT! return from IoCallDriver USBD %x\n", status));
  1245. KeAcquireSpinLock( &pThisDev->SendLock, &OldIrql );
  1246. RemoveEntryList( &pThisContext->ListEntry );
  1247. KeReleaseSpinLock( &pThisDev->SendLock, OldIrql );
  1248. InterlockedDecrement( &pThisDev->ReadWritePendingCount );
  1249. IrUsb_CancelIo( pThisDev, pIrp, &pThisDev->EventSyncUrb );
  1250. }
  1251. }
  1252. }
  1253. else
  1254. {
  1255. DEBUGMSG( DBG_ERR, (" St4200WriteRegister IoCallDriver FAILED(%x)\n",status));
  1256. IRUSB_ASSERT( status == STATUS_PENDING );
  1257. }
  1258. done:
  1259. DEBUGMSG(DBG_FUNC, ("-St4200WriteRegister\n"));
  1260. return status;
  1261. }
  1262. /*****************************************************************************
  1263. *
  1264. * Function: St4200ReadRegisters
  1265. *
  1266. * Synopsis: reads multiple STIr4200 register
  1267. *
  1268. * Arguments: pDevice - pointer to current ir device object
  1269. * FirstRegister - first register to read
  1270. * RegistersToWrite - number of registers to read
  1271. *
  1272. * Returns: NT_STATUS
  1273. *
  1274. *
  1275. *****************************************************************************/
  1276. NTSTATUS
  1277. St4200ReadRegisters(
  1278. IN OUT PVOID pDevice,
  1279. UCHAR FirstRegister,
  1280. UCHAR RegistersToRead
  1281. )
  1282. {
  1283. NTSTATUS status;
  1284. PIRUSB_CONTEXT pThisContext;
  1285. PURB pUrb = NULL;
  1286. PDEVICE_OBJECT pUrbTargetDev;
  1287. PIO_STACK_LOCATION pNextStack;
  1288. PIRP pIrp;
  1289. PIR_DEVICE pThisDev = (PIR_DEVICE)pDevice;
  1290. PLIST_ENTRY pListEntry;
  1291. DEBUGMSG(DBG_FUNC, ("+St4200ReadRegisters\n"));
  1292. IRUSB_ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );
  1293. //
  1294. // Make sure there isn't a halt/reset going on
  1295. //
  1296. if( pThisDev->fPendingHalt || pThisDev->fPendingReset || pThisDev->fPendingClearTotalStall )
  1297. {
  1298. DEBUGMSG(DBG_ERR, (" St4200ReadRegisters abort due to pending reset\n"));
  1299. status = STATUS_UNSUCCESSFUL;
  1300. goto done;
  1301. }
  1302. //
  1303. // Validate the parameters
  1304. //
  1305. if( (FirstRegister+RegistersToRead)>(STIR4200_MAX_REG+1) )
  1306. {
  1307. DEBUGMSG(DBG_ERR, (" St4200ReadRegisters invalid input parameters\n"));
  1308. status = STATUS_UNSUCCESSFUL;
  1309. goto done;
  1310. }
  1311. pListEntry = ExInterlockedRemoveHeadList( &pThisDev->SendAvailableQueue, &pThisDev->SendLock );
  1312. if( NULL == pListEntry )
  1313. {
  1314. //
  1315. // This must not happen
  1316. //
  1317. DEBUGMSG(DBG_ERR, (" St4200ReadRegisters failed to find a free context struct\n"));
  1318. IRUSB_ASSERT( 0 );
  1319. status = STATUS_UNSUCCESSFUL;
  1320. goto done;
  1321. }
  1322. InterlockedDecrement( &pThisDev->SendAvailableCount );
  1323. pThisContext = CONTAINING_RECORD( pListEntry, IRUSB_CONTEXT, ListEntry );
  1324. pThisContext->ContextType = CONTEXT_READ_WRITE_REGISTER;
  1325. pUrb = pThisDev->pUrb;
  1326. NdisZeroMemory( pUrb, pThisDev->UrbLen );
  1327. //
  1328. // Now that we have created the urb, we will send a
  1329. // request to the USB device object.
  1330. //
  1331. pUrbTargetDev = pThisDev->pUsbDevObj;
  1332. //
  1333. // make an irp sending to usbhub
  1334. //
  1335. pIrp = IoAllocateIrp( (CCHAR)(pThisDev->pUsbDevObj->StackSize + 1), FALSE );
  1336. if( NULL == pIrp )
  1337. {
  1338. DEBUGMSG(DBG_ERR, (" St4200ReadRegisters failed to alloc IRP\n"));
  1339. ExInterlockedInsertTailList(
  1340. &pThisDev->SendAvailableQueue,
  1341. &pThisContext->ListEntry,
  1342. &pThisDev->SendLock
  1343. );
  1344. InterlockedIncrement( &pThisDev->SendAvailableCount );
  1345. status = STATUS_UNSUCCESSFUL;
  1346. goto done;
  1347. }
  1348. pIrp->IoStatus.Status = STATUS_PENDING;
  1349. pIrp->IoStatus.Information = 0;
  1350. pThisContext->pIrp = pIrp;
  1351. //
  1352. // Build our URB for USBD
  1353. //
  1354. pUrb->UrbControlVendorClassRequest.Hdr.Length = (USHORT) sizeof( struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST );
  1355. pUrb->UrbControlVendorClassRequest.Hdr.Function = URB_FUNCTION_VENDOR_DEVICE ;
  1356. pUrb->UrbControlVendorClassRequest.TransferFlags = USBD_TRANSFER_DIRECTION_IN ;
  1357. // short packet is not treated as an error.
  1358. pUrb->UrbControlVendorClassRequest.TransferFlags |= USBD_SHORT_TRANSFER_OK;
  1359. pUrb->UrbControlVendorClassRequest.UrbLink = NULL;
  1360. pUrb->UrbControlVendorClassRequest.TransferBufferMDL = NULL;
  1361. pUrb->UrbControlVendorClassRequest.TransferBuffer = &(pThisDev->StIrTranceiver.FifoDataReg)+FirstRegister;
  1362. pUrb->UrbControlVendorClassRequest.TransferBufferLength = RegistersToRead;
  1363. pUrb->UrbControlVendorClassRequest.Request = STIR4200_READ_REGS_REQ;
  1364. pUrb->UrbControlVendorClassRequest.RequestTypeReservedBits = 0;
  1365. pUrb->UrbControlVendorClassRequest.Index = FirstRegister;
  1366. //
  1367. // Call the class driver to perform the operation.
  1368. //
  1369. pNextStack = IoGetNextIrpStackLocation( pIrp );
  1370. IRUSB_ASSERT( pNextStack != NULL );
  1371. //
  1372. // pass the URB to the USB driver stack
  1373. //
  1374. pNextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  1375. pNextStack->Parameters.Others.Argument1 = pUrb;
  1376. pNextStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
  1377. IoSetCompletionRoutine(
  1378. pIrp, // irp to use
  1379. St4200CompleteReadWriteRequest, // routine to call when irp is done
  1380. DEV_TO_CONTEXT(pThisContext), // context to pass routine
  1381. TRUE, // call on success
  1382. TRUE, // call on error
  1383. TRUE // call on cancel
  1384. );
  1385. KeClearEvent( &pThisDev->EventSyncUrb );
  1386. //
  1387. // Call IoCallDriver to send the irp to the usb port.
  1388. //
  1389. ExInterlockedInsertTailList(
  1390. &pThisDev->ReadWritePendingQueue,
  1391. &pThisContext->ListEntry,
  1392. &pThisDev->SendLock
  1393. );
  1394. InterlockedIncrement( &pThisDev->ReadWritePendingCount );
  1395. status = MyIoCallDriver( pThisDev, pUrbTargetDev, pIrp );
  1396. //
  1397. // The USB driver should always return STATUS_PENDING when
  1398. // it receives a write irp
  1399. //
  1400. if( (status == STATUS_PENDING) || (status == STATUS_SUCCESS) )
  1401. {
  1402. // wait, but dump out on timeout
  1403. if( status == STATUS_PENDING )
  1404. {
  1405. status = MyKeWaitForSingleObject( pThisDev, &pThisDev->EventSyncUrb, NULL, 0 );
  1406. if( status == STATUS_TIMEOUT )
  1407. {
  1408. KIRQL OldIrql;
  1409. DEBUGMSG( DBG_ERR,(" St4200ReadRegisters() TIMED OUT! return from IoCallDriver USBD %x\n", status));
  1410. KeAcquireSpinLock( &pThisDev->SendLock, &OldIrql );
  1411. RemoveEntryList( &pThisContext->ListEntry );
  1412. KeReleaseSpinLock( &pThisDev->SendLock, OldIrql );
  1413. InterlockedDecrement( &pThisDev->ReadWritePendingCount );
  1414. IrUsb_CancelIo( pThisDev, pIrp, &pThisDev->EventSyncUrb );
  1415. }
  1416. else
  1417. {
  1418. //
  1419. // Update the status to reflect the real return code
  1420. //
  1421. status = pThisDev->StatusReadWrite;
  1422. }
  1423. }
  1424. }
  1425. else
  1426. {
  1427. DEBUGMSG( DBG_ERR, (" St4200ReadRegisters IoCallDriver FAILED(%x)\n",status));
  1428. //
  1429. // Don't assert, as such a failure can happen at shutdown
  1430. //
  1431. //IRUSB_ASSERT( status == STATUS_PENDING );
  1432. }
  1433. done:
  1434. DEBUGMSG(DBG_FUNC, ("-St4200ReadRegisters\n"));
  1435. return status;
  1436. }
  1437. /*****************************************************************************
  1438. *
  1439. * Function: St4200CompleteReadWriteRequest
  1440. *
  1441. * Synopsis: completes a read/write ST4200 register request
  1442. *
  1443. * Arguments: pUsbDevObj - pointer to the device object which
  1444. * completed the irp
  1445. * pIrp - the irp which was completed by the device
  1446. * object
  1447. * Context - send context
  1448. *
  1449. * Returns: NT_STATUS
  1450. *
  1451. *
  1452. *****************************************************************************/
  1453. NTSTATUS
  1454. St4200CompleteReadWriteRequest(
  1455. IN PDEVICE_OBJECT pUsbDevObj,
  1456. IN PIRP pIrp,
  1457. IN PVOID Context
  1458. )
  1459. {
  1460. PIR_DEVICE pThisDev;
  1461. NTSTATUS status;
  1462. PIRUSB_CONTEXT pThisContext = (PIRUSB_CONTEXT)Context;
  1463. PIRP pContextIrp;
  1464. PURB pContextUrb;
  1465. PLIST_ENTRY pListEntry;
  1466. DEBUGMSG(DBG_FUNC, ("+St4200CompleteReadWriteRequest\n"));
  1467. //
  1468. // The context given to IoSetCompletionRoutine is an IRUSB_CONTEXT struct
  1469. //
  1470. IRUSB_ASSERT( NULL != pThisContext ); // we better have a non NULL buffer
  1471. pThisDev = pThisContext->pThisDev;
  1472. IRUSB_ASSERT( NULL != pThisDev );
  1473. pContextIrp = pThisContext->pIrp;
  1474. pContextUrb = pThisDev->pUrb;
  1475. //
  1476. // Perform various IRP, URB, and buffer 'sanity checks'
  1477. //
  1478. IRUSB_ASSERT( pContextIrp == pIrp ); // check we're not a bogus IRP
  1479. status = pIrp->IoStatus.Status;
  1480. //
  1481. // we should have failed, succeeded, or cancelled, but NOT be pending
  1482. //
  1483. IRUSB_ASSERT( STATUS_PENDING != status );
  1484. //
  1485. // Remove from the pending queue (only if NOT cancelled)
  1486. //
  1487. if( status != STATUS_CANCELLED )
  1488. {
  1489. KIRQL OldIrql;
  1490. KeAcquireSpinLock( &pThisDev->SendLock, &OldIrql );
  1491. RemoveEntryList( &pThisContext->ListEntry );
  1492. KeReleaseSpinLock( &pThisDev->SendLock, OldIrql );
  1493. InterlockedDecrement( &pThisDev->ReadWritePendingCount );
  1494. }
  1495. //pIrp->IoStatus.Information = pContextUrb->UrbControlVendorClassRequest.TransferBufferLength;
  1496. DEBUGMSG(DBG_OUT,
  1497. (" St4200CompleteReadWriteRequest pIrp->IoStatus.Status = 0x%x\n", status));
  1498. //DEBUGMSG(DBG_OUT,
  1499. // (" St4200CompleteReadWriteRequest pIrp->IoStatus.Information = 0x%x, dec %d\n", pIrp->IoStatus.Information,pIrp->IoStatus.Information));
  1500. //
  1501. // Free the IRP because we alloced it ourselves,
  1502. //
  1503. IoFreeIrp( pIrp );
  1504. InterlockedIncrement( &pThisDev->NumReadWrites );
  1505. IrUsb_DecIoCount( pThisDev ); // we will track count of pending irps
  1506. //
  1507. // Put back on the available queue
  1508. //
  1509. ExInterlockedInsertTailList(
  1510. &pThisDev->SendAvailableQueue,
  1511. &pThisContext->ListEntry,
  1512. &pThisDev->SendLock
  1513. );
  1514. InterlockedIncrement( &pThisDev->SendAvailableCount );
  1515. if( ( STATUS_SUCCESS != status ) && ( STATUS_CANCELLED != status ) )
  1516. {
  1517. InterlockedIncrement( (PLONG)&pThisDev->NumReadWriteErrors );
  1518. //
  1519. // We have a serious USB failure, we'll have to issue a total reset
  1520. //
  1521. if( !pThisDev->fPendingClearTotalStall && !pThisDev->fPendingHalt
  1522. && !pThisDev->fPendingReset && pThisDev->fProcessing )
  1523. {
  1524. DEBUGMSG(DBG_ERR, (" St4200CompleteReadWriteRequest error, will schedule an entire reset\n"));
  1525. //DbgPrint(" St4200CompleteReadWriteRequest error, will schedule an entire reset\n");
  1526. InterlockedExchange( (PLONG)&pThisDev->fPendingClearTotalStall, TRUE );
  1527. ScheduleWorkItem( pThisDev, RestoreIrDevice, NULL, 0 );
  1528. }
  1529. }
  1530. //
  1531. // This will only work as long as we serialize the access to the hardware
  1532. //
  1533. pThisDev->StatusReadWrite = status;
  1534. //
  1535. // Signal we're done
  1536. //
  1537. KeSetEvent( &pThisDev->EventSyncUrb, 0, FALSE );
  1538. DEBUGMSG(DBG_FUNC, ("-St4200CompleteReadWriteRequest\n"));
  1539. return STATUS_MORE_PROCESSING_REQUIRED;
  1540. }
  1541. #if defined( WORKAROUND_STUCK_AFTER_GEAR_DOWN )
  1542. /*****************************************************************************
  1543. *
  1544. * Function: St4200FakeSend
  1545. *
  1546. * Synopsis: forces a bulk transfer
  1547. *
  1548. * Arguments: pDevice - pointer to current ir device object
  1549. * pData - pointer to bulk data
  1550. * DataSize - size of bulk data
  1551. *
  1552. * Returns: NT_STATUS
  1553. *
  1554. *
  1555. *****************************************************************************/
  1556. NTSTATUS
  1557. St4200FakeSend(
  1558. IN PVOID pDevice,
  1559. PUCHAR pData,
  1560. ULONG DataSize
  1561. )
  1562. {
  1563. NTSTATUS status;
  1564. PIRUSB_CONTEXT pThisContext;
  1565. PURB pUrb = NULL;
  1566. PDEVICE_OBJECT pUrbTargetDev;
  1567. PIO_STACK_LOCATION pNextStack;
  1568. PIRP pIrp;
  1569. PIR_DEVICE pThisDev = (PIR_DEVICE)pDevice;
  1570. PLIST_ENTRY pListEntry;
  1571. DEBUGMSG(DBG_FUNC, ("+St4200FakeSend\n"));
  1572. IRUSB_ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );
  1573. //
  1574. // Stop if a halt/reset/suspend is going on
  1575. //
  1576. if( pThisDev->fPendingWriteClearStall || pThisDev->fPendingHalt ||
  1577. pThisDev->fPendingReset || pThisDev->fPendingClearTotalStall || !pThisDev->fProcessing )
  1578. {
  1579. DEBUGMSG(DBG_ERR, (" St4200FakeSend abort due to pending reset\n"));
  1580. status = STATUS_UNSUCCESSFUL;
  1581. goto done;
  1582. }
  1583. pListEntry = ExInterlockedRemoveHeadList( &pThisDev->SendAvailableQueue, &pThisDev->SendLock );
  1584. if( NULL == pListEntry )
  1585. {
  1586. //
  1587. // This must not happen
  1588. //
  1589. DEBUGMSG(DBG_ERR, (" St4200FakeSend failed to find a free context struct\n"));
  1590. IRUSB_ASSERT( 0 );
  1591. status = STATUS_UNSUCCESSFUL;
  1592. goto done;
  1593. }
  1594. InterlockedDecrement( &pThisDev->SendAvailableCount );
  1595. pThisContext = CONTAINING_RECORD( pListEntry, IRUSB_CONTEXT, ListEntry );
  1596. pThisContext->ContextType = CONTEXT_READ_WRITE_REGISTER;
  1597. pUrb = pThisDev->pUrb;
  1598. NdisZeroMemory( pUrb, pThisDev->UrbLen );
  1599. //
  1600. // Now that we have created the urb, we will send a
  1601. // request to the USB device object.
  1602. //
  1603. pUrbTargetDev = pThisDev->pUsbDevObj;
  1604. //
  1605. // make an irp sending to usbhub
  1606. //
  1607. pIrp = IoAllocateIrp( (CCHAR)(pThisDev->pUsbDevObj->StackSize + 1), FALSE );
  1608. if( NULL == pIrp )
  1609. {
  1610. DEBUGMSG(DBG_ERR, (" St4200FakeSend failed to alloc IRP\n"));
  1611. ExInterlockedInsertTailList(
  1612. &pThisDev->SendAvailableQueue,
  1613. &pThisContext->ListEntry,
  1614. &pThisDev->SendLock
  1615. );
  1616. InterlockedIncrement( &pThisDev->SendAvailableCount );
  1617. status = STATUS_UNSUCCESSFUL;
  1618. goto done;
  1619. }
  1620. pIrp->IoStatus.Status = STATUS_PENDING;
  1621. pIrp->IoStatus.Information = 0;
  1622. pThisContext->pIrp = pIrp;
  1623. //
  1624. // Build our URB for USBD
  1625. //
  1626. pUrb->UrbBulkOrInterruptTransfer.Hdr.Length = (USHORT)sizeof( struct _URB_BULK_OR_INTERRUPT_TRANSFER );
  1627. pUrb->UrbBulkOrInterruptTransfer.Hdr.Function = URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER;
  1628. pUrb->UrbBulkOrInterruptTransfer.PipeHandle = pThisDev->BulkOutPipeHandle;
  1629. pUrb->UrbBulkOrInterruptTransfer.TransferFlags = USBD_TRANSFER_DIRECTION_OUT ;
  1630. // short packet is not treated as an error.
  1631. pUrb->UrbBulkOrInterruptTransfer.TransferFlags |= USBD_SHORT_TRANSFER_OK;
  1632. pUrb->UrbBulkOrInterruptTransfer.UrbLink = NULL;
  1633. pUrb->UrbBulkOrInterruptTransfer.TransferBufferMDL = NULL;
  1634. pUrb->UrbBulkOrInterruptTransfer.TransferBuffer = pData;
  1635. pUrb->UrbBulkOrInterruptTransfer.TransferBufferLength = (int)DataSize;
  1636. //
  1637. // Call the class driver to perform the operation.
  1638. //
  1639. pNextStack = IoGetNextIrpStackLocation( pIrp );
  1640. IRUSB_ASSERT( pNextStack != NULL );
  1641. //
  1642. // pass the URB to the USB driver stack
  1643. //
  1644. pNextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
  1645. pNextStack->Parameters.Others.Argument1 = pUrb;
  1646. pNextStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
  1647. IoSetCompletionRoutine(
  1648. pIrp, // irp to use
  1649. St4200CompleteReadWriteRequest, // routine to call when irp is done
  1650. DEV_TO_CONTEXT(pThisContext), // context to pass routine
  1651. TRUE, // call on success
  1652. TRUE, // call on error
  1653. TRUE // call on cancel
  1654. );
  1655. KeClearEvent( &pThisDev->EventSyncUrb );
  1656. //
  1657. // Call IoCallDriver to send the irp to the usb port.
  1658. //
  1659. ExInterlockedInsertTailList(
  1660. &pThisDev->ReadWritePendingQueue,
  1661. &pThisContext->ListEntry,
  1662. &pThisDev->SendLock
  1663. );
  1664. InterlockedIncrement( &pThisDev->ReadWritePendingCount );
  1665. status = MyIoCallDriver( pThisDev, pUrbTargetDev, pIrp );
  1666. //
  1667. // The USB driver should always return STATUS_PENDING when
  1668. // it receives a write irp
  1669. //
  1670. if( (status == STATUS_PENDING) || (status == STATUS_SUCCESS) )
  1671. {
  1672. // wait, but dump out on timeout
  1673. if( status == STATUS_PENDING )
  1674. {
  1675. status = MyKeWaitForSingleObject( pThisDev, &pThisDev->EventSyncUrb, NULL, 0 );
  1676. if( status == STATUS_TIMEOUT )
  1677. {
  1678. KIRQL OldIrql;
  1679. DEBUGMSG( DBG_ERR,(" St4200FakeSend() TIMED OUT! return from IoCallDriver USBD %x\n", status));
  1680. KeAcquireSpinLock( &pThisDev->SendLock, &OldIrql );
  1681. RemoveEntryList( &pThisContext->ListEntry );
  1682. KeReleaseSpinLock( &pThisDev->SendLock, OldIrql );
  1683. InterlockedDecrement( &pThisDev->ReadWritePendingCount );
  1684. IrUsb_CancelIo( pThisDev, pIrp, &pThisDev->EventSyncUrb );
  1685. }
  1686. }
  1687. }
  1688. else
  1689. {
  1690. DEBUGMSG( DBG_ERR, (" St4200FakeSend IoCallDriver FAILED(%x)\n",status));
  1691. IRUSB_ASSERT( status == STATUS_PENDING );
  1692. }
  1693. done:
  1694. DEBUGMSG(DBG_FUNC, ("-St4200FakeSend\n"));
  1695. return status;
  1696. }
  1697. #endif