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.

1589 lines
40 KiB

  1. /**************************************************************************************************************************
  2. * IRUSB.C SigmaTel STIR4200 main module (contains main NDIS entry points)
  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/24/2000
  10. * Version 0.91
  11. * Edited: 04/27/2000
  12. * Version 0.92
  13. * Edited: 05/03/2000
  14. * Version 0.93
  15. * Edited: 05/12/2000
  16. * Version 0.94
  17. * Edited: 05/19/2000
  18. * Version 0.95
  19. * Edited: 05/24/2000
  20. * Version 0.96
  21. * Edited: 08/22/2000
  22. * Version 1.02
  23. * Edited: 09/25/2000
  24. * Version 1.10
  25. * Edited: 10/13/2000
  26. * Version 1.11
  27. * Edited: 11/13/2000
  28. * Version 1.12
  29. * Edited: 12/29/2000
  30. * Version 1.13
  31. *
  32. *
  33. **************************************************************************************************************************/
  34. #define DOBREAKS // enable debug breaks
  35. #include <ndis.h>
  36. #include <ntddndis.h> // defines OID's
  37. #include <usbdi.h>
  38. #include <usbdlib.h>
  39. #include "debug.h"
  40. #include "ircommon.h"
  41. #include "irusb.h"
  42. #include "irndis.h"
  43. #include "diags.h"
  44. //
  45. // Diagnostic global variables
  46. //
  47. #if defined(DIAGS)
  48. NDIS_HANDLE hSavedWrapper;
  49. PIR_DEVICE pGlobalDev;
  50. #endif
  51. //
  52. // Mark the DriverEntry function to run once during initialization.
  53. //
  54. NDIS_STATUS DriverEntry( PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath );
  55. #pragma NDIS_INIT_FUNCTION( DriverEntry )
  56. /*****************************************************************************
  57. *
  58. * Function: DriverEntry
  59. *
  60. * Synopsis: register driver entry functions with NDIS
  61. *
  62. * Arguments: DriverObject - the driver object being initialized
  63. * RegistryPath - registry path of the driver
  64. *
  65. * Returns: value returned by NdisMRegisterMiniport
  66. *
  67. * Algorithm:
  68. *
  69. *
  70. * Notes:
  71. *
  72. * This routine runs at IRQL PASSIVE_LEVEL.
  73. *
  74. *****************************************************************************/
  75. NDIS_STATUS
  76. DriverEntry(
  77. IN PDRIVER_OBJECT pDriverObject,
  78. IN PUNICODE_STRING pRegistryPath
  79. )
  80. {
  81. NDIS_STATUS status = NDIS_STATUS_SUCCESS;
  82. NDIS50_MINIPORT_CHARACTERISTICS characteristics;
  83. NDIS_HANDLE hWrapper;
  84. DEBUGMSG(DBG_FUNC, ("+DriverEntry(IrUsb)\n"));
  85. DEBUGMSG( DBG_FUNC ,(" Entering IRUSB DriverEntry(), pRegistryPath=\n %ws\n", pRegistryPath->Buffer ));
  86. NdisMInitializeWrapper(
  87. &hWrapper,
  88. pDriverObject,
  89. pRegistryPath,
  90. NULL
  91. );
  92. #if defined(DIAGS)
  93. hSavedWrapper = hWrapper;
  94. #endif
  95. DEBUGMSG(DBG_FUNC, (" DriverEntry(IrUsb) called NdisMInitializeWrapper()\n"));
  96. NdisZeroMemory(
  97. &characteristics,
  98. sizeof(NDIS50_MINIPORT_CHARACTERISTICS)
  99. );
  100. characteristics.MajorNdisVersion = (UCHAR)NDIS_MAJOR_VERSION;
  101. characteristics.MinorNdisVersion = (UCHAR)NDIS_MINOR_VERSION;
  102. characteristics.Reserved = 0;
  103. characteristics.HaltHandler = StIrUsbHalt;
  104. characteristics.InitializeHandler = StIrUsbInitialize;
  105. characteristics.QueryInformationHandler = StIrUsbQueryInformation;
  106. characteristics.SetInformationHandler = StIrUsbSetInformation;
  107. characteristics.ResetHandler = StIrUsbReset;
  108. //
  109. // For now we will allow NDIS to send only one packet at a time.
  110. //
  111. characteristics.SendHandler = StIrUsbSend;
  112. characteristics.SendPacketsHandler = StIrUsbSendPackets;
  113. //
  114. // We don't use NdisMIndicateXxxReceive function, so we will
  115. // need a ReturnPacketHandler to retrieve our packet resources.
  116. //
  117. characteristics.ReturnPacketHandler = StIrUsbReturnPacket;
  118. characteristics.TransferDataHandler = NULL;
  119. //
  120. // NDIS never calls the ReconfigureHandler.
  121. //
  122. characteristics.ReconfigureHandler = NULL;
  123. characteristics.CheckForHangHandler = StIrUsbCheckForHang;
  124. //
  125. // This miniport driver does not handle interrupts.
  126. //
  127. characteristics.HandleInterruptHandler = NULL;
  128. characteristics.ISRHandler = NULL;
  129. characteristics.DisableInterruptHandler = NULL;
  130. characteristics.EnableInterruptHandler = NULL;
  131. //
  132. // This miniport does not control a busmaster DMA with
  133. // NdisMAllocateShareMemoryAsysnc, AllocateCompleteHandler won't be
  134. // called from NDIS.
  135. //
  136. characteristics.AllocateCompleteHandler = NULL;
  137. DEBUGMSG(DBG_FUNC, (" DriverEntry(IrUsb) initted locks and events\n"));
  138. DEBUGMSG(DBG_FUNC, (" DriverEntry(IrUsb) about to NdisMRegisterMiniport()\n"));
  139. status = NdisMRegisterMiniport(
  140. hWrapper,
  141. &characteristics,
  142. sizeof(NDIS50_MINIPORT_CHARACTERISTICS)
  143. );
  144. DEBUGMSG(DBG_FUNC, (" DriverEntry(IrUsb) after NdisMRegisterMiniport() status 0x%x\n", status));
  145. DEBUGMSG(DBG_WARN, ("-DriverEntry(IrUsb) status = 0x%x\n", status));
  146. return status;
  147. }
  148. /*****************************************************************************
  149. *
  150. * Function: StIrUsbInitialize
  151. *
  152. * Synopsis: Initializes the device (usbd.sys) and allocates all resources
  153. * required to carry out 'network' io operations.
  154. *
  155. * Arguments: OpenErrorStatus - allows StIrUsbInitialize to return additional
  156. * status code NDIS_STATUS_xxx if returning
  157. * NDIS_STATUS_OPEN_FAILED
  158. * SelectedMediumIndex - specifies to NDIS the medium type the
  159. * driver uses
  160. * MediumArray - array of NdisMediumXXX the driver can choose
  161. * MediumArraySize
  162. * MiniportAdapterHandle - handle identifying miniport's NIC
  163. * WrapperConfigurationContext - used with Ndis config and init
  164. * routines
  165. *
  166. * Returns: NDIS_STATUS_SUCCESS if properly configure and resources allocated
  167. * NDIS_STATUS_FAILURE, otherwise
  168. *
  169. * more specific failures:
  170. * NDIS_STATUS_UNSUPPORTED_MEDIA - driver can't support any medium
  171. * NDIS_STATUS_ADAPTER_NOT_FOUND - NdisOpenConfiguration or
  172. * NdisReadConfiguration failed
  173. * NDIS_STATUS_OPEN_FAILED - failed to open serial.sys
  174. * NDIS_STATUS_NOT_ACCEPTED - serial.sys does not accept the
  175. * configuration
  176. * NDIS_STATUS_RESOURCES - could not claim sufficient
  177. * resources
  178. *
  179. *
  180. * Notes: NDIS will not submit requests until this is complete.
  181. *
  182. * This routine runs at IRQL PASSIVE_LEVEL.
  183. *
  184. *****************************************************************************/
  185. NDIS_STATUS
  186. StIrUsbInitialize(
  187. OUT PNDIS_STATUS OpenErrorStatus,
  188. OUT PUINT SelectedMediumIndex,
  189. IN PNDIS_MEDIUM MediumArray,
  190. IN UINT MediumArraySize,
  191. IN NDIS_HANDLE NdisAdapterHandle,
  192. IN NDIS_HANDLE WrapperConfigurationContext
  193. )
  194. {
  195. UINT i;
  196. PIR_DEVICE pThisDev = NULL;
  197. NDIS_STATUS status = NDIS_STATUS_SUCCESS;
  198. NTSTATUS ntStatus = STATUS_SUCCESS;
  199. PDEVICE_OBJECT pPhysicalDeviceObject = NULL;
  200. PDEVICE_OBJECT pNextDeviceObject = NULL;
  201. #if defined(DIAGS)
  202. UNICODE_STRING SymbolicLinkName;
  203. UNICODE_STRING DeviceName;
  204. PDEVICE_OBJECT pDeviceObject;
  205. PDRIVER_DISPATCH MajorFunction[IRP_MJ_MAXIMUM_FUNCTION+1];
  206. #endif
  207. DEBUGMSG(DBG_WARN, ("+StIrUsbInitialize\n"));
  208. //
  209. // Search for the irda medium in the medium array.
  210. //
  211. for( i = 0; i < MediumArraySize; i++ )
  212. {
  213. if( MediumArray[i] == NdisMediumIrda )
  214. {
  215. break;
  216. }
  217. }
  218. if( i < MediumArraySize )
  219. {
  220. *SelectedMediumIndex = i;
  221. }
  222. else
  223. {
  224. //
  225. // Irda medium not found.
  226. //
  227. DEBUGMSG(DBG_ERROR, (" Failure: NdisMediumIrda not found!\n"));
  228. status = NDIS_STATUS_UNSUPPORTED_MEDIA;
  229. //
  230. // Log the error
  231. //
  232. NdisWriteErrorLogEntry(
  233. NdisAdapterHandle,
  234. NDIS_STATUS_UNSUPPORTED_MEDIA,
  235. 1,
  236. status
  237. );
  238. goto done;
  239. }
  240. //
  241. // This will connect to a specific bus
  242. //
  243. NdisMGetDeviceProperty(
  244. NdisAdapterHandle,
  245. &pPhysicalDeviceObject,
  246. NULL,
  247. &pNextDeviceObject,
  248. NULL,
  249. NULL
  250. );
  251. IRUSB_ASSERT( pPhysicalDeviceObject );
  252. IRUSB_ASSERT( pNextDeviceObject );
  253. DEBUGMSG(
  254. DBG_OUT,
  255. ("NdisMGetDeviceProperty PDO 0x%x,Next DO 0x%x\n",
  256. pPhysicalDeviceObject, pNextDeviceObject)
  257. );
  258. //
  259. // Allocate a functional device object.
  260. //
  261. ntStatus = IrUsb_AddDevice( &pThisDev );
  262. IRUSB_ASSERT( pThisDev );
  263. if( (ntStatus != STATUS_SUCCESS) || (pThisDev == NULL) )
  264. {
  265. //
  266. // Log the error
  267. //
  268. NdisWriteErrorLogEntry(
  269. NdisAdapterHandle,
  270. NDIS_STATUS_RESOURCES,
  271. 1,
  272. ntStatus
  273. );
  274. DEBUGMSG(DBG_ERROR, (" IrUsb_AddDevice() FAILED.\n"));
  275. status = NDIS_STATUS_RESOURCES;
  276. goto done;
  277. }
  278. pThisDev->pUsbDevObj = pNextDeviceObject;
  279. pThisDev->pPhysDevObj = pPhysicalDeviceObject;
  280. //
  281. // Initialize device object and resources.
  282. // All the queues and buffer/packets etc. are allocated here.
  283. //
  284. status = InitializeDevice( pThisDev );
  285. if( status != NDIS_STATUS_SUCCESS )
  286. {
  287. //
  288. // Log the error
  289. //
  290. NdisWriteErrorLogEntry(
  291. NdisAdapterHandle,
  292. NDIS_STATUS_RESOURCES,
  293. 1,
  294. status
  295. );
  296. DEBUGMSG(DBG_ERROR, (" InitializeDevice failed. Returned 0x%.8x\n", status));
  297. status = NDIS_STATUS_RESOURCES;
  298. goto done;
  299. }
  300. //
  301. // Record the NdisAdapterHandle.
  302. //
  303. pThisDev->hNdisAdapter = NdisAdapterHandle;
  304. //
  305. // NdisMSetAttributes will associate our adapter handle with the wrapper's
  306. // adapter handle. The wrapper will then always use our handle
  307. // when calling us. We use a pointer to the device object as the context.
  308. //
  309. NdisMSetAttributesEx(
  310. NdisAdapterHandle,
  311. (NDIS_HANDLE)pThisDev,
  312. 0,
  313. NDIS_ATTRIBUTE_DESERIALIZE,
  314. NdisInterfaceInternal
  315. );
  316. //
  317. // Now we're ready to do our own startup processing.
  318. // USB client drivers such as us set up URBs (USB Request Packets) to send requests
  319. // to the host controller driver (HCD). The URB structure defines a format for all
  320. // possible commands that can be sent to a USB device.
  321. // Here, we request the device descriptor and store it,
  322. // and configure the device.
  323. // In USB, no special HW processing is required to 'open' or 'close' the pipes
  324. //
  325. pThisDev->WrapperConfigurationContext = WrapperConfigurationContext;
  326. ntStatus = IrUsb_StartDevice( pThisDev );
  327. if( ntStatus != STATUS_SUCCESS )
  328. {
  329. //
  330. // Log the error
  331. //
  332. NdisWriteErrorLogEntry(
  333. pThisDev->hNdisAdapter,
  334. NDIS_STATUS_ADAPTER_NOT_FOUND,
  335. 1,
  336. ntStatus
  337. );
  338. DEBUGMSG(DBG_ERROR, (" IrUsb_StartDevice FAILED. Returned 0x%.8x\n", ntStatus));
  339. status = NDIS_STATUS_ADAPTER_NOT_FOUND;
  340. goto done;
  341. }
  342. //
  343. // Create an irp and begin our receives.
  344. // NOTE: All other receive processing will be done in the read completion
  345. // routine and PollingThread started therein.
  346. //
  347. status = InitializeProcessing( pThisDev, TRUE );
  348. if( status != NDIS_STATUS_SUCCESS )
  349. {
  350. //
  351. // Log the error
  352. //
  353. NdisWriteErrorLogEntry(
  354. pThisDev->hNdisAdapter,
  355. NDIS_STATUS_RESOURCES,
  356. 1,
  357. status
  358. );
  359. DEBUGMSG(DBG_ERROR, (" InitializeProcessing failed. Returned 0x%.8x\n", status));
  360. status = NDIS_STATUS_RESOURCES;
  361. goto done;
  362. }
  363. //
  364. // Initialize the diagnostic portion
  365. //
  366. #if defined(DIAGS)
  367. NdisZeroMemory( MajorFunction, sizeof(PDRIVER_DISPATCH)*(IRP_MJ_MAXIMUM_FUNCTION+1) );
  368. RtlInitUnicodeString( &SymbolicLinkName, L"\\DosDevices\\Stirusb" );
  369. RtlInitUnicodeString( &DeviceName, L"\\Device\\Stirusb" );
  370. MajorFunction[IRP_MJ_CREATE] = StIrUsbCreate;
  371. MajorFunction[IRP_MJ_CLOSE] = StIrUsbClose;
  372. MajorFunction[IRP_MJ_DEVICE_CONTROL] = StIrUsbDispatch;
  373. NdisMRegisterDevice(
  374. hSavedWrapper,
  375. &DeviceName,
  376. &SymbolicLinkName,
  377. MajorFunction,
  378. &pDeviceObject,
  379. &pThisDev->NdisDeviceHandle
  380. );
  381. pGlobalDev = pThisDev;
  382. #endif
  383. done:
  384. if( status != NDIS_STATUS_SUCCESS )
  385. {
  386. if( pThisDev != NULL )
  387. {
  388. DeinitializeDevice( pThisDev );
  389. FreeDevice( pThisDev );
  390. }
  391. }
  392. if( status!=NDIS_STATUS_SUCCESS )
  393. {
  394. DEBUGMSG(DBG_ERR, (" IrUsb: StIrUsbInitialize failed %x\n", status));
  395. }
  396. else
  397. {
  398. DEBUGMSG(DBG_ERR, (" IrUsb: StIrUsbInitialize SUCCESS %x\n", status));
  399. }
  400. DEBUGMSG(DBG_FUNC, ("-StIrUsbInitialize\n"));
  401. return status;
  402. }
  403. /*****************************************************************************
  404. *
  405. * Function: StIrUsbHalt
  406. *
  407. * Synopsis: Deallocates resources when the NIC is removed and halts the
  408. * device.
  409. *
  410. * Arguments: Context - pointer to the ir device object
  411. *
  412. * Returns: None
  413. *
  414. * Algorithm: Mirror image of StIrUsbInitialize...undoes everything initialize
  415. * did.
  416. * Notes:
  417. *
  418. * This routine runs at IRQL PASSIVE_LEVEL.
  419. *
  420. * BUGBUG: Could StIrUsbReset fail and then StIrUsbHalt be called. If so, we need
  421. * to chech validity of all the pointers, etc. before trying to
  422. * deallocate.
  423. *
  424. *****************************************************************************/
  425. VOID
  426. StIrUsbHalt(
  427. IN NDIS_HANDLE Context
  428. )
  429. {
  430. PIR_DEVICE pThisDev;
  431. NTSTATUS ntstatus;
  432. DEBUGMSG(DBG_WARN, ("+StIrUsbHalt\n")); // change to FUNC later?
  433. pThisDev = CONTEXT_TO_DEV( Context );
  434. if( TRUE == pThisDev->fPendingHalt )
  435. {
  436. DEBUGMSG(DBG_ERR, (" StIrUsbHalt called with halt already pending\n"));
  437. IRUSB_ASSERT( 0 );
  438. goto done;
  439. }
  440. //
  441. // Let the send completion and receive completion routine know that there
  442. // is a pending reset.
  443. //
  444. pThisDev->fPendingHalt = TRUE;
  445. IrUsb_CommonShutdown( pThisDev, TRUE ); //shutdown logic common to halt and reset; see below
  446. //
  447. // We had better not have left any pending read, write, or control IRPS hanging out there!
  448. //
  449. IRUSB_ASSERT( 0 == pThisDev->PendingIrpCount );
  450. if ( 0 != pThisDev->PendingIrpCount )
  451. {
  452. DEBUGMSG(DBG_ERR, (" StIrUsbHalt WE LEFT %d PENDING IRPS!!!!!\n", pThisDev->PendingIrpCount));
  453. }
  454. IRUSB_ASSERT( FALSE == pThisDev->fSetpending );
  455. IRUSB_ASSERT( FALSE == pThisDev->fQuerypending );
  456. //
  457. // Destroy diags
  458. //
  459. #if defined(DIAGS)
  460. NdisMDeregisterDevice( pThisDev->NdisDeviceHandle );
  461. #endif
  462. //
  463. // Free our own IR device object.
  464. //
  465. FreeDevice( pThisDev );
  466. done:
  467. DEBUGMSG(DBG_ERR, (" StIrUsbHalt HALT complete\n"));
  468. DEBUGMSG(DBG_WARN, ("-StIrUsbHalt\n")); // change to FUNC later?
  469. }
  470. /*****************************************************************************
  471. *
  472. * Function: IrUsb_CommonShutdown
  473. *
  474. * Synopsis: Deallocates resources when the NIC is removed and halts the
  475. * device. This is stuff common to IrUsbHalt and IrUsbReset and is called by both
  476. *
  477. * Arguments: pThisDev - pointer to IR device
  478. * KillPassiveThread - determines whether we need to kill the passive thread
  479. *
  480. * Returns: None
  481. *
  482. * Algorithm: Mirror image of IrUsbInitialize...undoes everything initialize
  483. * did.
  484. *
  485. * Notes:
  486. *
  487. * This routine runs at IRQL PASSIVE_LEVEL.
  488. *
  489. *
  490. *****************************************************************************/
  491. VOID
  492. IrUsb_CommonShutdown(
  493. IN OUT PIR_DEVICE pThisDev,
  494. BOOLEAN KillPassiveThread
  495. )
  496. {
  497. DEBUGMSG(DBG_WARN, ("+IrUsb_CommonShutdown\n")); //chg to FUNC later?
  498. //
  499. // Stop processing and sleep 50 milliseconds.
  500. //
  501. InterlockedExchange( (PLONG)&pThisDev->fProcessing, FALSE );
  502. NdisMSleep( 50000 );
  503. //
  504. // Kill the passive thread
  505. //
  506. if( KillPassiveThread )
  507. {
  508. DEBUGMSG(DBG_WARN, (" IrUsb_CommonShutdown About to Kill PassiveLevelThread\n"));
  509. pThisDev->fKillPassiveLevelThread = TRUE;
  510. KeSetEvent(&pThisDev->EventPassiveThread, 0, FALSE);
  511. while( pThisDev->hPassiveThread != NULL )
  512. {
  513. //
  514. // Sleep 50 milliseconds.
  515. //
  516. NdisMSleep( 50000 );
  517. }
  518. DEBUGMSG(DBG_WARN, (" passive thread killed\n"));
  519. }
  520. //
  521. // Kill the polling thread
  522. //
  523. DEBUGMSG(DBG_WARN, (" IrUsb_CommonShutdown About to kill Polling thread\n"));
  524. pThisDev->fKillPollingThread = TRUE;
  525. while( pThisDev->hPollingThread != NULL )
  526. {
  527. //
  528. // Sleep 50 milliseconds.
  529. //
  530. NdisMSleep( 50000 );
  531. }
  532. IRUSB_ASSERT( pThisDev->packetsHeldByProtocol == 0 );
  533. DEBUGMSG( DBG_WARN, (" Polling thread killed\n") );
  534. //
  535. // Sleep 50 milliseconds so pending io might finish normally
  536. //
  537. NdisMSleep( 50000 );
  538. DEBUGMSG(DBG_WARN, (" IrUsb_CommonShutdown About to IrUsb_CancelPendingIo()\n"));
  539. //
  540. // Cancel any outstandig IO we may have
  541. //
  542. IrUsb_CancelPendingIo( pThisDev );
  543. //
  544. // Deinitialize our own ir device object.
  545. //
  546. DeinitializeDevice( pThisDev );
  547. pThisDev->fDeviceStarted = FALSE;
  548. DEBUGMSG(DBG_WARN, ("-IrUsb_CommonShutdown\n")); //chg to FUNC later?
  549. }
  550. /*****************************************************************************
  551. *
  552. * Function: StIrUsbReset
  553. *
  554. * Synopsis: Resets the drivers software state.
  555. *
  556. * Arguments: AddressingReset - return arg. If set to TRUE, NDIS will call
  557. * MiniportSetInformation to restore addressing
  558. * information to the current values.
  559. * Context - pointer to ir device object
  560. *
  561. * Returns: NDIS_STATUS_PENDING
  562. *
  563. *
  564. * Notes:
  565. *
  566. *
  567. *****************************************************************************/
  568. NDIS_STATUS
  569. StIrUsbReset(
  570. OUT PBOOLEAN AddressingReset,
  571. IN NDIS_HANDLE MiniportAdapterContext
  572. )
  573. {
  574. PIR_DEVICE pThisDev;
  575. NDIS_STATUS status = NDIS_STATUS_PENDING;
  576. DEBUGMSG(DBG_WARN, ("+StIrUsbReset\n")); // CHANGE TO FUNC?
  577. pThisDev = CONTEXT_TO_DEV( MiniportAdapterContext );
  578. if( TRUE == pThisDev->fPendingReset )
  579. {
  580. DEBUGMSG(DBG_ERROR, (" StIrUsbReset called with reset already pending\n"));
  581. status = NDIS_STATUS_RESET_IN_PROGRESS ;
  582. goto done;
  583. }
  584. //
  585. // Let the send completion and receive completion routine know that there
  586. // is a pending reset.
  587. //
  588. pThisDev->fPendingReset = TRUE;
  589. InterlockedExchange( (PLONG)&pThisDev->fProcessing, FALSE );
  590. *AddressingReset = TRUE;
  591. if( FALSE == ScheduleWorkItem( pThisDev, ResetIrDevice, NULL, 0) )
  592. {
  593. status = NDIS_STATUS_FAILURE;
  594. }
  595. done:
  596. DEBUGMSG(DBG_WARN, ("-StIrUsbReset\n")); // change to FUNC later?
  597. return status;
  598. }
  599. /*****************************************************************************
  600. *
  601. * Function: StIrUsbCheckForHang
  602. *
  603. * Synopsis: Makes sure the device/driver operating state is correct
  604. *
  605. * Arguments: Context - pointer to ir device object
  606. *
  607. * Returns: TRUE - driver is hung
  608. * FALSE - otherwise
  609. *
  610. * Notes:
  611. *
  612. *
  613. *****************************************************************************/
  614. BOOLEAN
  615. StIrUsbCheckForHang(
  616. IN NDIS_HANDLE MiniportAdapterContext
  617. )
  618. {
  619. PIR_DEVICE pThisDev;
  620. pThisDev = CONTEXT_TO_DEV( MiniportAdapterContext );
  621. /*if( pThisDev->fPendingClearTotalStall )
  622. {
  623. DEBUGMSG(DBG_ERROR, (" StIrUsbCheckForHang USB hang, will ask for a reset\n"));
  624. return TRUE;
  625. }
  626. else*/
  627. return FALSE;
  628. }
  629. /*****************************************************************************
  630. *
  631. * Function: SuspendIrDevice
  632. *
  633. * Synopsis: Callback for a going into suspend mode
  634. *
  635. * Arguments: pWorkItem - pointer to the reset work item
  636. *
  637. * Returns: None
  638. *
  639. * Notes:
  640. *
  641. *****************************************************************************/
  642. VOID
  643. SuspendIrDevice(
  644. IN PIR_WORK_ITEM pWorkItem
  645. )
  646. {
  647. PIR_DEVICE pThisDev = (PIR_DEVICE)pWorkItem->pIrDevice;
  648. NTSTATUS Status = STATUS_SUCCESS;
  649. //
  650. // We no longer need the work item
  651. //
  652. FreeWorkItem( pWorkItem );
  653. //
  654. // Now cancel everything that's pending, after a little time to complete
  655. //
  656. NdisMSleep( 100*1000 );
  657. DEBUGMSG(DBG_ERROR, (" SuspendIrDevice(), cancelling pending IRPs\n"));
  658. IrUsb_CancelPendingIo( pThisDev );
  659. //
  660. // Prepare the part
  661. //
  662. #if defined(SUPPORT_LA8)
  663. if( pThisDev->ChipRevision >= CHIP_REVISION_8 )
  664. {
  665. Status = St4200EnableOscillatorPowerDown( pThisDev );
  666. if( Status == STATUS_SUCCESS )
  667. {
  668. Status = St4200TurnOnSuspend( pThisDev );
  669. }
  670. }
  671. #endif
  672. //
  673. // Tell the OS
  674. //
  675. if( pThisDev->fQuerypending )
  676. MyNdisMQueryInformationComplete( pThisDev, Status );
  677. }
  678. /*****************************************************************************
  679. *
  680. * Function: ResumeIrDevice
  681. *
  682. * Synopsis: Callback for a going out of suspend mode
  683. *
  684. * Arguments: pWorkItem - pointer to the reset work item
  685. *
  686. * Returns: None
  687. *
  688. * Notes:
  689. *
  690. *****************************************************************************/
  691. VOID
  692. ResumeIrDevice(
  693. IN PIR_WORK_ITEM pWorkItem
  694. )
  695. {
  696. PIR_DEVICE pThisDev = (PIR_DEVICE)pWorkItem->pIrDevice;
  697. //
  698. // We no longer need the work item
  699. //
  700. FreeWorkItem( pWorkItem );
  701. //
  702. // Get the device back up and running
  703. //
  704. #if defined(SUPPORT_LA8)
  705. if( pThisDev->ChipRevision >= CHIP_REVISION_8 )
  706. {
  707. St4200TurnOffSuspend( pThisDev );
  708. }
  709. #endif
  710. St4200SetSpeed( pThisDev );
  711. InterlockedExchange( (PLONG)&pThisDev->currentSpeed, pThisDev->linkSpeedInfo->BitsPerSec );
  712. InterlockedExchange( (PLONG)&pThisDev->fProcessing, TRUE );
  713. }
  714. /*****************************************************************************
  715. *
  716. * Function: RestoreIrDevice
  717. *
  718. * Synopsis: Callback for a on-the-fly reset
  719. *
  720. * Arguments: pWorkItem - pointer to the reset work item
  721. *
  722. * Returns: None
  723. *
  724. * Notes:
  725. *
  726. *****************************************************************************/
  727. VOID
  728. RestoreIrDevice(
  729. IN PIR_WORK_ITEM pWorkItem
  730. )
  731. {
  732. NDIS_STATUS status = STATUS_SUCCESS;
  733. PIR_DEVICE pThisDev = (PIR_DEVICE)pWorkItem->pIrDevice;
  734. UINT CurrentSpeed, i;
  735. DEBUGMSG(DBG_WARN, ("+RestoreIrDevice\n"));
  736. DEBUGMSG(DBG_ERROR, (" RestoreIrDevice USB hang, resetting\n"));
  737. //
  738. // We no longer need the work item
  739. //
  740. FreeWorkItem( pWorkItem );
  741. //
  742. // Give a little time to complete
  743. //
  744. NdisMSleep( 100*1000 );
  745. //
  746. // Force a reset on the USB bus
  747. //
  748. status = IrUsb_ResetUSBD( pThisDev, FALSE );
  749. if( status != NDIS_STATUS_SUCCESS )
  750. {
  751. //IrUsb_ResetUSBD( pThisDev, TRUE );
  752. pThisDev->fDeviceStarted = FALSE;
  753. InterlockedExchange( (PLONG)&pThisDev->fProcessing, FALSE );
  754. DEBUGMSG(DBG_ERROR, (" RestoreIrDevice() IrUsb_ResetUSBD failed. Returned 0x%.8x\n", status));
  755. goto done;
  756. }
  757. //
  758. // Save the current speed
  759. //
  760. CurrentSpeed = pThisDev->currentSpeed;
  761. //
  762. // Shutdown the device
  763. //
  764. DEBUGMSG(DBG_WARN, (" RestoreIrDevice() about to call IrUsb_CommonShutdown()\n")); // change to FUNC later?
  765. IrUsb_CommonShutdown( pThisDev, FALSE ); //shutdown logic common to halt and reset; see above
  766. DEBUGMSG(DBG_WARN, (" RestoreIrDevice() after IrUsb_CommonShutdown()\n")); // change to FUNC later?
  767. //
  768. // Destroy and create again the USB portion of the device
  769. //
  770. DEBUGMSG(DBG_WARN, (" RestoreIrDevice() about to refresh USB info\n")); // change to FUNC later?
  771. FreeUsbInfo( pThisDev );
  772. if( !AllocUsbInfo( pThisDev ) )
  773. {
  774. DEBUGMSG(DBG_ERROR, (" RestoreIrDevice() AllocUsbInfo failed\n"));
  775. goto done;
  776. }
  777. DEBUGMSG(DBG_WARN, (" RestoreIrDevice() after refreshing USB info\n")); // change to FUNC later?
  778. //
  779. // Reinitialize the device
  780. //
  781. DEBUGMSG(DBG_WARN, (" RestoreIrDevice() about to call InitializeDevice()\n")); // change to FUNC later?
  782. status = InitializeDevice( pThisDev );
  783. if( status != NDIS_STATUS_SUCCESS )
  784. {
  785. DEBUGMSG(DBG_ERROR, (" RestoreIrDevice() InitializeDevice failed. Returned 0x%.8x\n", status));
  786. goto done;
  787. }
  788. DEBUGMSG(DBG_WARN, (" RestoreIrDevice() InitializeProcessing() SUCCESS, about to call InitializeReceive()\n")); // change to FUNC later?
  789. //
  790. // Restart it
  791. //
  792. status = IrUsb_StartDevice( pThisDev );
  793. if( status != STATUS_SUCCESS )
  794. {
  795. DEBUGMSG(DBG_ERROR, (" RestoreIrDevice() IrUsb_StartDevice failed. Returned 0x%.8x\n", status));
  796. goto done;
  797. }
  798. //
  799. // Keep a pointer to the link speed which was previously set
  800. //
  801. for( i = 0; i < NUM_BAUDRATES; i++ )
  802. {
  803. if( supportedBaudRateTable[i].BitsPerSec == CurrentSpeed )
  804. {
  805. pThisDev->linkSpeedInfo = &supportedBaudRateTable[i];
  806. break; //for
  807. }
  808. }
  809. //
  810. // restore the old speed
  811. //
  812. DEBUGMSG( DBG_ERR, (" Restoring speed to: %d\n", pThisDev->linkSpeedInfo->BitsPerSec));
  813. status = St4200SetSpeed( pThisDev );
  814. if( status != STATUS_SUCCESS )
  815. {
  816. DEBUGMSG(DBG_ERROR, (" RestoreIrDevice() St4200SetSpeed failed. Returned 0x%.8x\n", status));
  817. goto done;
  818. }
  819. InterlockedExchange( (PLONG)&pThisDev->currentSpeed, CurrentSpeed );
  820. //
  821. // Initialize receive loop.
  822. //
  823. status = InitializeProcessing( pThisDev, FALSE );
  824. if( status != NDIS_STATUS_SUCCESS )
  825. {
  826. DEBUGMSG(DBG_ERROR, (" RestoreIrDevice() InitializeProcessing failed. Returned 0x%.8x\n", status));
  827. goto done;
  828. }
  829. done:
  830. DEBUGCOND(DBG_ERROR, (status != NDIS_STATUS_SUCCESS), (" RestoreIrDevice failed = 0x%.8x\n", status));
  831. }
  832. /*****************************************************************************
  833. *
  834. * Function: ResetIrDevice
  835. *
  836. * Synopsis: Callback for StIrUsbReset
  837. *
  838. * Arguments: pWorkItem - pointer to the reset work item
  839. *
  840. * Returns: None
  841. *
  842. * Notes:
  843. *
  844. * The following elements of the ir device object outlast the reset:
  845. *
  846. * pUsbDevObj
  847. * hNdisAdapter
  848. *
  849. *****************************************************************************/
  850. VOID
  851. ResetIrDevice(
  852. IN PIR_WORK_ITEM pWorkItem
  853. )
  854. {
  855. NDIS_STATUS status = STATUS_SUCCESS;
  856. PIR_DEVICE pThisDev = (PIR_DEVICE)pWorkItem->pIrDevice;
  857. DEBUGMSG(DBG_WARN, ("+ResetIrDevice\n")); // change to FUNC later?
  858. //
  859. // We no longer need the work item
  860. //
  861. FreeWorkItem( pWorkItem );
  862. //
  863. // Now cancel everything that's pending, after a little time to complete
  864. //
  865. NdisMSleep( 100*1000 );
  866. DEBUGMSG(DBG_ERROR, (" ResetIrDevice(), cancelling pending IRPs\n"));
  867. IrUsb_CancelPendingIo( pThisDev );
  868. //
  869. // reset the part
  870. //
  871. status = IrUsb_ResetUSBD( pThisDev, FALSE );
  872. if( status != STATUS_SUCCESS )
  873. {
  874. pThisDev->fDeviceStarted = FALSE;
  875. //
  876. // Log the error
  877. //
  878. NdisWriteErrorLogEntry(
  879. pThisDev->hNdisAdapter,
  880. NDIS_STATUS_ADAPTER_NOT_FOUND,
  881. 1,
  882. status
  883. );
  884. DEBUGMSG(DBG_ERROR, (" ResetIrDevice() IrUsb_ResetUSBD failed. Returned 0x%.8x\n", status));
  885. status = NDIS_STATUS_ADAPTER_NOT_FOUND;
  886. goto done;
  887. }
  888. //
  889. // Shutdown the device
  890. //
  891. DEBUGMSG(DBG_WARN, (" ResetIrDevice() about to call IrUsb_CommonShutdown()\n")); // change to FUNC later?
  892. IrUsb_CommonShutdown( pThisDev, FALSE ); //shutdown logic common to halt and reset; see above
  893. DEBUGMSG(DBG_WARN, (" ResetIrDevice() after IrUsb_CommonShutdown()\n")); // change to FUNC later?
  894. //
  895. // Destroy and create again the USB portion of the device
  896. //
  897. DEBUGMSG(DBG_WARN, (" ResetIrDevice() about to refresh USB info\n")); // change to FUNC later?
  898. FreeUsbInfo( pThisDev );
  899. if( !AllocUsbInfo( pThisDev ) )
  900. {
  901. //
  902. // Log the error
  903. //
  904. NdisWriteErrorLogEntry(
  905. pThisDev->hNdisAdapter,
  906. NDIS_STATUS_RESOURCES,
  907. 1,
  908. status
  909. );
  910. DEBUGMSG(DBG_ERROR, (" ResetIrDevice() AllocUsbInfo failed\n"));
  911. status = NDIS_STATUS_FAILURE;
  912. goto done;
  913. }
  914. DEBUGMSG(DBG_WARN, (" ResetIrDevice() after refreshing USB info\n")); // change to FUNC later?
  915. //
  916. // Reinitialize the device
  917. //
  918. DEBUGMSG(DBG_WARN, (" ResetIrDevice() about to call InitializeDevice()\n")); // change to FUNC later?
  919. status = InitializeDevice( pThisDev );
  920. if( status != NDIS_STATUS_SUCCESS )
  921. {
  922. //
  923. // Log the error
  924. //
  925. NdisWriteErrorLogEntry(
  926. pThisDev->hNdisAdapter,
  927. NDIS_STATUS_RESOURCES,
  928. 1,
  929. status
  930. );
  931. DEBUGMSG(DBG_ERROR, (" ResetIrDevice() InitializeDevice failed. Returned 0x%.8x\n", status));
  932. status = NDIS_STATUS_FAILURE;
  933. goto done;
  934. }
  935. DEBUGMSG(DBG_WARN, (" ResetIrDevice() InitializeProcessing() SUCCESS, about to call InitializeReceive()\n")); // change to FUNC later?
  936. //
  937. // Restart it
  938. //
  939. status = IrUsb_StartDevice( pThisDev );
  940. if( status != STATUS_SUCCESS )
  941. {
  942. //
  943. // Log the error
  944. //
  945. NdisWriteErrorLogEntry(
  946. pThisDev->hNdisAdapter,
  947. NDIS_STATUS_ADAPTER_NOT_FOUND,
  948. 1,
  949. status
  950. );
  951. DEBUGMSG(DBG_ERROR, (" ResetIrDevice() IrUsb_StartDevice failed. Returned 0x%.8x\n", status));
  952. status = NDIS_STATUS_ADAPTER_NOT_FOUND;
  953. goto done;
  954. }
  955. //
  956. // Initialize receive loop.
  957. //
  958. status = InitializeProcessing( pThisDev, FALSE );
  959. if( status != NDIS_STATUS_SUCCESS )
  960. {
  961. //
  962. // Log the error
  963. //
  964. NdisWriteErrorLogEntry(
  965. pThisDev->hNdisAdapter,
  966. NDIS_STATUS_RESOURCES,
  967. 1,
  968. status
  969. );
  970. DEBUGMSG(DBG_ERROR, (" ResetIrDevice() InitializeProcessing failed. Returned 0x%.8x\n", status));
  971. status = NDIS_STATUS_FAILURE;
  972. goto done;
  973. }
  974. done:
  975. DEBUGCOND(DBG_ERROR, (status != NDIS_STATUS_SUCCESS), (" ResetIrDevice failed = 0x%.8x\n", status));
  976. //
  977. // Deal with possible errors
  978. //
  979. if( status != STATUS_SUCCESS )
  980. {
  981. status = NDIS_STATUS_HARD_ERRORS;
  982. }
  983. NdisMResetComplete(
  984. pThisDev->hNdisAdapter,
  985. status,
  986. TRUE
  987. );
  988. DEBUGMSG(DBG_WARN, ("-ResetIrDevice\n")); // change to FUNC later?
  989. }
  990. /*****************************************************************************
  991. *
  992. * Function: GetPacketInfo
  993. *
  994. * Synopsis: Gets the IR specific information for an input packet
  995. *
  996. * Arguments: pPacket - pointer to packet
  997. *
  998. * Returns: PNDIS_IRDA_PACKET_INFO structure for the packet
  999. *
  1000. * Notes:
  1001. *
  1002. *****************************************************************************/
  1003. PNDIS_IRDA_PACKET_INFO
  1004. GetPacketInfo(
  1005. IN PNDIS_PACKET pPacket
  1006. )
  1007. {
  1008. PMEDIA_SPECIFIC_INFORMATION pMediaInfo;
  1009. UINT Size;
  1010. NDIS_GET_PACKET_MEDIA_SPECIFIC_INFO( pPacket, &pMediaInfo, &Size );
  1011. if( Size )
  1012. return (PNDIS_IRDA_PACKET_INFO)pMediaInfo->ClassInformation;
  1013. else
  1014. return NULL;
  1015. }
  1016. /*****************************************************************************
  1017. *
  1018. * Function: MyNdisMSetInformationComplete
  1019. *
  1020. * Synopsis: Call NdisMSetInformationComplete()
  1021. *
  1022. * Arguments: pThisDev - pointer to IR device
  1023. * Status - status to signal
  1024. *
  1025. * Returns: None
  1026. *
  1027. * Notes:
  1028. *
  1029. *****************************************************************************/
  1030. VOID
  1031. MyNdisMSetInformationComplete(
  1032. IN PIR_DEVICE pThisDev,
  1033. IN NDIS_STATUS Status
  1034. )
  1035. {
  1036. DEBUGMSG( DBG_FUNC,("+MyNdisMSetInformationComplete\n"));
  1037. NdisMSetInformationComplete( (NDIS_HANDLE)pThisDev->hNdisAdapter, Status );
  1038. pThisDev->LastSetTime.QuadPart = 0;
  1039. pThisDev->fSetpending = FALSE;
  1040. DEBUGMSG( DBG_FUNC,("-MyNdisMSetInformationComplete\n"));
  1041. }
  1042. /*****************************************************************************
  1043. *
  1044. * Function: MyNdisMQueryInformationComplete
  1045. *
  1046. * Synopsis: Call NdisMQueryInformationComplete()
  1047. *
  1048. * Arguments: pThisDev - pointer to IR device
  1049. * Status - status to signal
  1050. *
  1051. * Returns: None
  1052. *
  1053. * Notes:
  1054. *
  1055. *****************************************************************************/
  1056. VOID
  1057. MyNdisMQueryInformationComplete(
  1058. IN PIR_DEVICE pThisDev,
  1059. IN NDIS_STATUS Status
  1060. )
  1061. {
  1062. DEBUGMSG( DBG_FUNC,("+MyNdisMQueryInformationComplete\n"));
  1063. NdisMQueryInformationComplete( (NDIS_HANDLE)pThisDev->hNdisAdapter, Status );
  1064. pThisDev->LastQueryTime.QuadPart = 0;
  1065. pThisDev->fQuerypending = FALSE;
  1066. DEBUGMSG( DBG_FUNC,("-MyNdisMQueryInformationComplete\n"));
  1067. }
  1068. /*****************************************************************************
  1069. *
  1070. * Function: IndicateMediaBusy
  1071. *
  1072. * Synopsis: Call NdisMIndicateStatus()
  1073. *
  1074. * Arguments: pThisDev - pointer to IR device
  1075. *
  1076. * Returns: None
  1077. *
  1078. * Notes:
  1079. *
  1080. *****************************************************************************/
  1081. VOID
  1082. IndicateMediaBusy(
  1083. IN PIR_DEVICE pThisDev
  1084. )
  1085. {
  1086. DEBUGMSG( DBG_FUNC,("+IndicateMediaBusy\n"));
  1087. NdisMIndicateStatus(
  1088. pThisDev->hNdisAdapter,
  1089. NDIS_STATUS_MEDIA_BUSY,
  1090. NULL,
  1091. 0
  1092. );
  1093. NdisMIndicateStatusComplete(
  1094. pThisDev->hNdisAdapter,
  1095. );
  1096. #if DBG
  1097. pThisDev->NumMediaBusyIndications ++;
  1098. #endif
  1099. #if !defined(ONLY_ERROR_MESSAGES)
  1100. DEBUGMSG(DBG_ERR, (" IndicateMediaBusy()\n"));
  1101. #endif
  1102. DEBUGMSG( DBG_FUNC,("-IndicateMediaBusy\n"));
  1103. }
  1104. /*****************************************************************************
  1105. *
  1106. * Function: StIrUsbSendPackets
  1107. *
  1108. * Synopsis: Send a packet to the USB driver and add the sent irp and io context to
  1109. * To the pending send queue; this que is really just needed for possible later error cancellation
  1110. *
  1111. *
  1112. * Arguments: MiniportAdapterContext - pointer to current ir device object
  1113. * PacketArray - pointer to array of packets to send
  1114. * NumberOfPackets - number of packets in the array
  1115. *
  1116. * Returns: VOID
  1117. *
  1118. * Notes: This routine does nothing but calling StIrUsbSend
  1119. *
  1120. *
  1121. *****************************************************************************/
  1122. VOID
  1123. StIrUsbSendPackets(
  1124. IN NDIS_HANDLE MiniportAdapterContext,
  1125. IN PPNDIS_PACKET PacketArray,
  1126. IN UINT NumberOfPackets
  1127. )
  1128. {
  1129. ULONG i;
  1130. //
  1131. // This is a great opportunity to be lazy.
  1132. // Just call StIrUsbSend with each packet
  1133. // in sequence and set the result in the
  1134. // packet array object.
  1135. //
  1136. for( i=0; i<NumberOfPackets; i++ )
  1137. {
  1138. StIrUsbSend( MiniportAdapterContext, PacketArray[i], 0 );
  1139. }
  1140. }
  1141. /*****************************************************************************
  1142. *
  1143. * Function: StIrUsbSend
  1144. *
  1145. * Synopsis: Send a packet to the USB driver and add the sent irp and io context to
  1146. * To the pending send queue; this que is really just needed for possible later error cancellation
  1147. *
  1148. *
  1149. * Arguments: MiniportAdapterContext - pointer to current ir device object
  1150. * pPacketToSend - pointer to packet to send
  1151. * Flags - any flags set by protocol
  1152. *
  1153. * Returns: NDIS_STATUS_PENDING - This is generally what we should
  1154. * return. We will call NdisMSendComplete
  1155. * when the USB driver completes the
  1156. * send.
  1157. *
  1158. * Unsupported returns:
  1159. * NDIS_STATUS_SUCCESS - We should never return this since
  1160. * results will always be pending from
  1161. * the USB driver.
  1162. * NDIS_STATUS_RESOURCES - This indicates to the protocol that the
  1163. * device currently has no resources to complete
  1164. * the request. The protocol will resend
  1165. * the request when it receives either
  1166. * NdisMSendResourcesAvailable or
  1167. * NdisMSendComplete from the device.
  1168. *
  1169. * Notes: This routine delegates all the real work to SendPacketPreprocess in send.c
  1170. *
  1171. *
  1172. *****************************************************************************/
  1173. NDIS_STATUS
  1174. StIrUsbSend(
  1175. IN NDIS_HANDLE MiniportAdapterContext,
  1176. IN PNDIS_PACKET pPacketToSend,
  1177. IN UINT Flags
  1178. )
  1179. {
  1180. PIR_DEVICE pThisDev = (PIR_DEVICE)MiniportAdapterContext;
  1181. NDIS_STATUS Status;
  1182. DEBUGMSG( DBG_FUNC,("+StIrUsbSend()\n"));
  1183. //
  1184. // Make sure we are in the proper status, i.e. we are processing
  1185. // and no diagnostics are active
  1186. //
  1187. #if defined(DIAGS)
  1188. if( !pThisDev->fProcessing || pThisDev->DiagsPendingActivation )
  1189. #else
  1190. if( !pThisDev->fProcessing )
  1191. #endif
  1192. {
  1193. Status = NDIS_STATUS_FAILURE;
  1194. goto done;
  1195. }
  1196. //
  1197. // Send the packet to the hardware
  1198. //
  1199. NDIS_SET_PACKET_STATUS( pPacketToSend, NDIS_STATUS_PENDING );
  1200. Status = SendPacketPreprocess(
  1201. pThisDev,
  1202. pPacketToSend
  1203. );
  1204. done:
  1205. //
  1206. // If the operation didn't pend we have to complete
  1207. // We are really bouncing the packets...
  1208. //
  1209. if( Status != NDIS_STATUS_PENDING )
  1210. {
  1211. NdisMSendComplete(
  1212. pThisDev->hNdisAdapter,
  1213. pPacketToSend,
  1214. NDIS_STATUS_SUCCESS
  1215. );
  1216. }
  1217. DEBUGMSG( DBG_FUNC,("-StIrUsbSend()\n"));
  1218. return Status;
  1219. }
  1220. // Diagnostic entry points
  1221. #if defined(DIAGS)
  1222. /*****************************************************************************
  1223. *
  1224. * Function: StIrUsbDispatch
  1225. *
  1226. * Synopsis: Processes the diagnostic Irps
  1227. *
  1228. * Arguments: DeviceObject - pointer to the device object
  1229. * Irp - pointer to the Irp
  1230. *
  1231. * Returns: NT status code
  1232. *
  1233. * Notes:
  1234. *
  1235. *****************************************************************************/
  1236. NTSTATUS
  1237. StIrUsbDispatch(
  1238. IN PDEVICE_OBJECT DeviceObject,
  1239. IN PIRP Irp
  1240. )
  1241. {
  1242. PIR_DEVICE pThisDev = pGlobalDev;
  1243. PIO_STACK_LOCATION irpSp;
  1244. ULONG FunctionCode;
  1245. NTSTATUS status;
  1246. PVOID pBuffer;
  1247. ULONG BufferLength;
  1248. USHORT DiagsCode;
  1249. DEBUGMSG( DBG_FUNC,("+StIrUsbDispatch()\n"));
  1250. //
  1251. // Get the Irp
  1252. //
  1253. irpSp = IoGetCurrentIrpStackLocation( Irp );
  1254. //
  1255. // Get the data
  1256. //
  1257. FunctionCode = irpSp->Parameters.DeviceIoControl.IoControlCode;
  1258. pBuffer = Irp->AssociatedIrp.SystemBuffer;
  1259. BufferLength = irpSp->Parameters.DeviceIoControl.InputBufferLength;
  1260. DiagsCode = *(PUSHORT)pBuffer;
  1261. //
  1262. // Process the diagnostic operation
  1263. //
  1264. switch( FunctionCode )
  1265. {
  1266. case IOCTL_PROTOCOL_DIAGS:
  1267. switch( DiagsCode )
  1268. {
  1269. case DIAGS_ENABLE:
  1270. status = Diags_Enable( pThisDev );
  1271. break;
  1272. case DIAGS_DISABLE:
  1273. status = Diags_Disable( pThisDev );
  1274. break;
  1275. case DIAGS_READ_REGISTERS:
  1276. status = Diags_ReadRegisters( pThisDev, pBuffer, BufferLength );
  1277. if( status == STATUS_SUCCESS )
  1278. {
  1279. Irp->IoStatus.Information = sizeof(DIAGS_READ_REGISTERS_IOCTL);
  1280. }
  1281. break;
  1282. case DIAGS_WRITE_REGISTER:
  1283. status = Diags_WriteRegister( pThisDev, pBuffer, BufferLength );
  1284. break;
  1285. case DIAGS_BULK_OUT:
  1286. status = Diags_PrepareBulk( pThisDev, pBuffer, BufferLength, TRUE );
  1287. break;
  1288. case DIAGS_BULK_IN:
  1289. status = Diags_PrepareBulk( pThisDev, pBuffer, BufferLength, FALSE );
  1290. if( status == STATUS_SUCCESS )
  1291. {
  1292. PDIAGS_BULK_IOCTL pIOCTL = pThisDev->pIOCTL;
  1293. Irp->IoStatus.Information = sizeof(DIAGS_BULK_IOCTL)+pIOCTL->DataSize-1;
  1294. }
  1295. break;
  1296. case DIAGS_SEND:
  1297. status = Diags_PrepareSend( pThisDev, pBuffer, BufferLength );
  1298. break;
  1299. case DIAGS_RECEIVE:
  1300. status = Diags_Receive( pThisDev, pBuffer, BufferLength );
  1301. if( status == STATUS_SUCCESS )
  1302. {
  1303. PDIAGS_RECEIVE_IOCTL pIOCTL = pThisDev->pIOCTL;
  1304. Irp->IoStatus.Information = sizeof(DIAGS_RECEIVE_IOCTL)+pIOCTL->DataSize-1;
  1305. }
  1306. break;
  1307. case DIAGS_GET_SPEED:
  1308. status = Diags_GetSpeed( pThisDev, pBuffer, BufferLength );
  1309. if( status == STATUS_SUCCESS )
  1310. {
  1311. Irp->IoStatus.Information = sizeof(DIAGS_SPEED_IOCTL);
  1312. }
  1313. break;
  1314. case DIAGS_SET_SPEED:
  1315. status = Diags_SetSpeed( pThisDev, pBuffer, BufferLength );
  1316. break;
  1317. default:
  1318. status = STATUS_NOT_SUPPORTED;
  1319. break;
  1320. }
  1321. break;
  1322. default:
  1323. status = STATUS_NOT_SUPPORTED;
  1324. break;
  1325. }
  1326. //
  1327. // Complete and return
  1328. //
  1329. Irp->IoStatus.Status = status;
  1330. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  1331. DEBUGMSG( DBG_FUNC,("-StIrUsbDispatch()\n"));
  1332. return status;
  1333. }
  1334. /*****************************************************************************
  1335. *
  1336. * Function: StIrUsbCreate
  1337. *
  1338. * Synopsis: Creates a new diagnostic object (it does nothing)
  1339. *
  1340. * Arguments: DeviceObject - pointer to the device object
  1341. * Irp - pointer to the Irp
  1342. *
  1343. * Returns: NT status code
  1344. *
  1345. * Notes:
  1346. *
  1347. *****************************************************************************/
  1348. NTSTATUS
  1349. StIrUsbCreate(
  1350. IN PDEVICE_OBJECT DeviceObject,
  1351. IN PIRP Irp
  1352. )
  1353. {
  1354. PIR_DEVICE pThisDev = pGlobalDev;
  1355. //
  1356. // Initialize list for holding pending read requests
  1357. //
  1358. KeInitializeSpinLock( &pThisDev->DiagsReceiveLock );
  1359. InitializeListHead( &pThisDev->DiagsReceiveQueue );
  1360. Irp->IoStatus.Status = STATUS_SUCCESS;
  1361. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  1362. return STATUS_SUCCESS;
  1363. }
  1364. /*****************************************************************************
  1365. *
  1366. * Function: StIrUsbClose
  1367. *
  1368. * Synopsis: Destroys a new diagnostic object (it does nothing)
  1369. *
  1370. * Arguments: DeviceObject - pointer to the device object
  1371. * Irp - pointer to the Irp
  1372. *
  1373. * Returns: NT status code
  1374. *
  1375. * Notes:
  1376. *
  1377. *****************************************************************************/
  1378. NTSTATUS
  1379. StIrUsbClose(
  1380. IN PDEVICE_OBJECT DeviceObject,
  1381. IN PIRP Irp
  1382. )
  1383. {
  1384. Irp->IoStatus.Status = STATUS_SUCCESS;
  1385. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  1386. return STATUS_SUCCESS;
  1387. }
  1388. #endif