Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1034 lines
28 KiB

  1. /* ++
  2. Copyright (c) 1999-2000 Microsoft Corporation
  3. Module Name:
  4. PNP.C
  5. Abstract:
  6. WinCE Host PnP functions
  7. Environment:
  8. kernel mode only
  9. Revision History:
  10. 07-14-99 : created
  11. Authors:
  12. Jeff Midkiff (jeffmi)
  13. -- */
  14. #include "wceusbsh.h"
  15. NTSTATUS
  16. StartDevice(
  17. IN PDEVICE_OBJECT PDevObj,
  18. IN PIRP PIrp
  19. );
  20. NTSTATUS
  21. StopDevice(
  22. IN PDEVICE_OBJECT DeviceObject,
  23. IN PIRP Irp
  24. );
  25. NTSTATUS
  26. RemoveDevice(
  27. IN PDEVICE_OBJECT DeviceObject,
  28. IN PIRP Irp
  29. );
  30. NTSTATUS
  31. SyncCompletion(
  32. IN PDEVICE_OBJECT PDevObj,
  33. IN PIRP PIrp,
  34. IN PKEVENT PSyncEvent
  35. );
  36. #ifdef ALLOC_PRAGMA
  37. #pragma alloc_text(PAGEWCE1, StartDevice)
  38. #pragma alloc_text(PAGEWCE1, StopIo)
  39. #pragma alloc_text(PAGEWCE1, StopDevice)
  40. #pragma alloc_text(PAGEWCE1, RemoveDevice)
  41. #pragma alloc_text(PAGEWCE1, Power)
  42. #endif
  43. NTSTATUS
  44. StartDevice(
  45. IN PDEVICE_OBJECT PDevObj,
  46. IN PIRP PIrp
  47. )
  48. /*++
  49. Routine Description:
  50. This routine handles IRP_MN_START_DEVICE to either
  51. to start a newly enumerated device or to restart
  52. an existing device that was stopped.
  53. PnP Manager postpones exposing device interfaces
  54. and blocks create requests for the device until
  55. the start IRP succeeds.
  56. See: Setup, Plug & Play, Power Management: Preliminary Windows 2000 DDK
  57. Section 3.1 Starting a Device
  58. Arguments:
  59. DeviceObject
  60. Irp
  61. Return Value:
  62. NTSTATUS
  63. --*/
  64. {
  65. PDEVICE_EXTENSION pDevExt = PDevObj->DeviceExtension;
  66. NTSTATUS status = STATUS_SUCCESS;
  67. PNP_STATE oldPnPState;
  68. KEVENT event;
  69. DbgDump(DBG_PNP, (">StartDevice (%x)\n", PDevObj));
  70. PAGED_CODE();
  71. oldPnPState = pDevExt->PnPState;
  72. //
  73. // Pass the Start Irp down the stack.
  74. // We do are Start on the way back up.
  75. //
  76. KeInitializeEvent( &event, SynchronizationEvent, FALSE );
  77. IoCopyCurrentIrpStackLocationToNext( PIrp );
  78. IoSetCompletionRoutine( PIrp,
  79. SyncCompletion,
  80. &event,
  81. TRUE, TRUE, TRUE );
  82. status = IoCallDriver( pDevExt->NextDevice, PIrp );
  83. //
  84. // SyncCompletion simple signals the event
  85. // and returns STATUS_MORE_PROCESSING_REQUIRED,
  86. // so we still own the Irp.
  87. //
  88. if ( status == STATUS_PENDING ) {
  89. KeWaitForSingleObject( &event, Suspended, KernelMode, FALSE, NULL );
  90. }
  91. status = PIrp->IoStatus.Status;
  92. if (status != STATUS_SUCCESS) {
  93. DbgDump(DBG_PNP, ("ERROR: StartDevice returned 0x%x\n", status));
  94. goto ExitStartDevice;
  95. }
  96. //
  97. // The USB stack started OK, start our device...
  98. //
  99. //
  100. // Initialize our DPC's
  101. //
  102. KeInitializeDpc(&pDevExt->TotalReadTimeoutDpc,
  103. ReadTimeout,
  104. pDevExt);
  105. KeInitializeDpc( &pDevExt->IntervalReadTimeoutDpc,
  106. IntervalReadTimeout,
  107. pDevExt);
  108. //
  109. // Initialize timers
  110. //
  111. KeInitializeTimer(&pDevExt->ReadRequestTotalTimer);
  112. KeInitializeTimer(&pDevExt->ReadRequestIntervalTimer);
  113. //
  114. // Get our USB_DEVICE_DESCRIPTOR
  115. //
  116. status = UsbGetDeviceDescriptor(PDevObj);
  117. if (status != STATUS_SUCCESS) {
  118. DbgDump(DBG_ERR, ("UsbGetDeviceDescriptor error: 0x%x\n", status));
  119. goto ExitStartDevice;
  120. }
  121. //
  122. // Configure USB stack
  123. //
  124. status = UsbConfigureDevice( PDevObj );
  125. if (status != STATUS_SUCCESS) {
  126. DbgDump(DBG_ERR, ("UsbConfigureDevice error: 0x%x\n", status));
  127. goto ExitStartDevice;
  128. }
  129. // set state
  130. InterlockedExchange((PULONG)&pDevExt->PnPState, PnPStateStarted);
  131. InterlockedExchange(&pDevExt->DeviceRemoved, FALSE);
  132. InterlockedExchange(&pDevExt->AcceptingRequests, TRUE);
  133. //
  134. // reset logical Serial interface
  135. //
  136. status = SerialResetDevice(pDevExt, PIrp, FALSE);
  137. if ( STATUS_SUCCESS != status ) {
  138. DbgDump(DBG_ERR, ("SerialResetDevice ERROR: 0x%x\n", status));
  139. TEST_TRAP();
  140. }
  141. //
  142. // allocate our read endpoint context
  143. //
  144. status = AllocUsbRead( pDevExt );
  145. if ( STATUS_SUCCESS != status ) {
  146. DbgDump(DBG_ERR, ("AllocUsbRead ERROR: 0x%x\n", status));
  147. TEST_TRAP();
  148. }
  149. //
  150. // allocate our interrupt endpoint context
  151. //
  152. if ( pDevExt->IntPipe.hPipe ) {
  153. status = AllocUsbInterrupt( pDevExt );
  154. if ( STATUS_SUCCESS != status ) {
  155. DbgDump(DBG_ERR, ("AllocUsbRead ERROR: 0x%x\n", status));
  156. TEST_TRAP();
  157. }
  158. }
  159. //
  160. // Now set the interface state active
  161. //
  162. status = IoSetDeviceInterfaceState(&pDevExt->DeviceClassSymbolicName, TRUE);
  163. if ( STATUS_SUCCESS != status ) {
  164. DbgDump(DBG_ERR, ("IoSetDeviceInterfaceState error: 0x%x\n", status));
  165. TEST_TRAP();
  166. } else{
  167. DbgDump(DBG_WRN, ("IoSetDeviceInterfaceState: ON\n"));
  168. }
  169. ExitStartDevice:
  170. if ( STATUS_SUCCESS != status ) {
  171. pDevExt->PnPState = oldPnPState;
  172. UsbFreeReadBuffer( PDevObj );
  173. }
  174. //
  175. // complete the Irp
  176. //
  177. PIrp->IoStatus.Status = status;
  178. DbgDump(DBG_PNP, ("<StartDevice(0x%x)\n", status));
  179. return status;
  180. }
  181. NTSTATUS
  182. StopIo(
  183. IN PDEVICE_OBJECT DeviceObject
  184. )
  185. {
  186. PDEVICE_EXTENSION pDevExt = DeviceObject->DeviceExtension;
  187. NTSTATUS status = STATUS_SUCCESS;
  188. KIRQL irql;
  189. DbgDump(DBG_PNP|DBG_INIT, (">StopIo\n"));
  190. PAGED_CODE();
  191. if ((pDevExt->PnPState < PnPStateInitialized) || (pDevExt->PnPState > PnPStateMax)) {
  192. DbgDump(DBG_ERR, ("StopIo:STATUS_INVALID_PARAMETER\n"));
  193. return STATUS_INVALID_PARAMETER;
  194. }
  195. InterlockedExchange(&pDevExt->DeviceOpened, FALSE);
  196. //
  197. // cancel any pending user Read Irps
  198. //
  199. KillAllPendingUserReads( DeviceObject,
  200. &pDevExt->UserReadQueue,
  201. &pDevExt->UserReadIrp);
  202. //
  203. // cancel our USB INT irp
  204. //
  205. if (pDevExt->IntIrp)
  206. {
  207. status = CancelUsbInterruptIrp(DeviceObject);
  208. if (STATUS_SUCCESS == status) {
  209. InterlockedExchange(&pDevExt->IntState, IRP_STATE_COMPLETE);
  210. } else {
  211. DbgDump(DBG_ERR, ("CancelUsbInterruptIrp ERROR: 0x%x\n", status));
  212. TEST_TRAP();
  213. }
  214. }
  215. //
  216. // cancel our USB Read irp
  217. //
  218. if (pDevExt->UsbReadIrp)
  219. {
  220. status = CancelUsbReadIrp(DeviceObject);
  221. if (STATUS_SUCCESS == status) {
  222. InterlockedExchange(&pDevExt->UsbReadState, IRP_STATE_COMPLETE);
  223. } else {
  224. DbgDump(DBG_ERR, ("CancelUsbReadIrp ERROR: 0x%x\n", status));
  225. TEST_TRAP();
  226. }
  227. }
  228. //
  229. // cancel pending USB Writes
  230. //
  231. CleanUpPacketList( DeviceObject,
  232. &pDevExt->PendingWritePackets,
  233. &pDevExt->PendingDataOutEvent );
  234. //
  235. // cancel pending USB Reads
  236. //
  237. CleanUpPacketList(DeviceObject,
  238. &pDevExt->PendingReadPackets,
  239. &pDevExt->PendingDataInEvent );
  240. //
  241. // cancel the pending serial port Irp
  242. //
  243. if (pDevExt->SerialPort.ControlIrp) {
  244. if ( !IoCancelIrp(pDevExt->SerialPort.ControlIrp) ) {
  245. //
  246. // We can get here if we are holding the Irp, i.e. we didn't set a cancel routine.
  247. // Wait for the default timeout, which was set on the corresponding Urb (Set/Clear DTR/RTS).
  248. //
  249. LARGE_INTEGER timeOut;
  250. timeOut.QuadPart = MILLISEC_TO_100NANOSEC( DEFAULT_PENDING_TIMEOUT );
  251. DbgDump(DBG_ERR, ("!IoCancelIrp(%p)\n", pDevExt->SerialPort.ControlIrp));
  252. KeDelayExecutionThread(KernelMode, FALSE, &timeOut);
  253. TEST_TRAP();
  254. }
  255. }
  256. //
  257. // cancel the pending serial port wait mask Irp
  258. //
  259. if (pDevExt->SerialPort.CurrentWaitMaskIrp) {
  260. if ( !IoCancelIrp(pDevExt->SerialPort.CurrentWaitMaskIrp) ) {
  261. // We should never get here because we set a cancel routine on this Irp
  262. DbgDump(DBG_ERR, ("!IoCancelIrp(%p)\n", pDevExt->SerialPort.CurrentWaitMaskIrp));
  263. TEST_TRAP();
  264. }
  265. }
  266. //
  267. // wait for pending Work Items to complets
  268. //
  269. status = WaitForPendingItem(DeviceObject,
  270. &pDevExt->PendingWorkItemsEvent,
  271. &pDevExt->PendingWorkItemsCount );
  272. if ( STATUS_SUCCESS != status ) {
  273. DbgDump(DBG_ERR, ("WaitForPendingItem ERROR: 0x%x\n", status));
  274. TEST_TRAP();
  275. }
  276. ASSERT( 0 == pDevExt->PendingReadCount );
  277. ASSERT( 0 == pDevExt->PendingWriteCount );
  278. ASSERT( 0 == pDevExt->PendingDataOutCount );
  279. ASSERT( 0 == pDevExt->PendingIntCount );
  280. ASSERT( 0 == pDevExt->PendingWorkItemsCount );
  281. ASSERT( NULL == pDevExt->SerialPort.ControlIrp );
  282. ASSERT( NULL == pDevExt->SerialPort.CurrentWaitMaskIrp );
  283. DbgDump(DBG_PNP|DBG_INIT, ("<StopIo(%x)\n", status));
  284. return status;
  285. }
  286. NTSTATUS
  287. StopDevice(
  288. IN PDEVICE_OBJECT DeviceObject,
  289. IN PIRP Irp
  290. )
  291. /*++
  292. Routine Description:
  293. This routine handles IRP_MN_STOP_DEVICE.
  294. Arguments:
  295. DeviceObject
  296. Irp
  297. Return Value:
  298. NTSTATUS
  299. --*/
  300. {
  301. PDEVICE_EXTENSION pDevExt = DeviceObject->DeviceExtension;
  302. NTSTATUS status = STATUS_SUCCESS;
  303. UNREFERENCED_PARAMETER( Irp );
  304. DbgDump(DBG_PNP, (">StopDevice (%x)\n", DeviceObject));
  305. PAGED_CODE();
  306. //
  307. // if we are not already in stopped state
  308. //
  309. if ((pDevExt->PnPState != PnPStateStopped) &&
  310. (pDevExt->PnPState != PnPStateSupriseRemove)) {
  311. //
  312. // Signal that we are no longer AcceptingRequests
  313. //
  314. InterlockedExchange(&pDevExt->AcceptingRequests, FALSE);
  315. //
  316. // set the interface state inactive
  317. //
  318. if (pDevExt->DeviceClassSymbolicName.Buffer )
  319. {
  320. status = IoSetDeviceInterfaceState(&pDevExt->DeviceClassSymbolicName, FALSE);
  321. if (NT_SUCCESS(status)) {
  322. DbgDump(DBG_WRN, ("IoSetDeviceInterfaceState.2: OFF\n"));
  323. }
  324. }
  325. status = StopIo(DeviceObject);
  326. if (STATUS_SUCCESS != status) {
  327. DbgDump(DBG_ERR, ("StopIo ERROR: 0x%x\n", status));
  328. TEST_TRAP();
  329. }
  330. //
  331. // free the Read Irp
  332. //
  333. if (pDevExt->UsbReadIrp) {
  334. ASSERT( (IRP_STATE_COMPLETE == pDevExt->UsbReadState)
  335. || (IRP_STATE_CANCELLED== pDevExt->UsbReadState) );
  336. IoFreeIrp(pDevExt->UsbReadIrp);
  337. pDevExt->UsbReadIrp = NULL;
  338. }
  339. //
  340. // free the INT Irp
  341. //
  342. if (pDevExt->IntIrp) {
  343. ASSERT( (IRP_STATE_COMPLETE == pDevExt->IntState)
  344. || (IRP_STATE_CANCELLED== pDevExt->IntState) );
  345. IoFreeIrp(pDevExt->IntIrp);
  346. pDevExt->IntIrp = NULL;
  347. }
  348. //
  349. // free the INT Urb
  350. //
  351. if (pDevExt->IntUrb) {
  352. ExFreeToNPagedLookasideList( &pDevExt->BulkTransferUrbPool, pDevExt->IntUrb );
  353. pDevExt->IntUrb = NULL;
  354. }
  355. }
  356. DbgDump(DBG_PNP, ("<StopDevice(0x%x)\n", status));
  357. return status;
  358. }
  359. NTSTATUS
  360. CleanUpPacketList(
  361. IN PDEVICE_OBJECT DeviceObject,
  362. IN PLIST_ENTRY PListHead,
  363. IN PKEVENT PEvent
  364. )
  365. /* ++
  366. Routine Description:
  367. Walks the pending packet list and
  368. cancels the packet's timer and Irp
  369. Arguments:
  370. DeviceObject
  371. PListHead - pointer to head of packet List
  372. Return Value:
  373. NTSTATUS
  374. -- */
  375. {
  376. PDEVICE_EXTENSION pDevExt = DeviceObject->DeviceExtension;
  377. PUSB_PACKET pPacket;
  378. KIRQL irql;
  379. PLIST_ENTRY pleHead, pleCurrent, pleNext;
  380. NTSTATUS status = STATUS_SUCCESS;
  381. DbgDump(DBG_PNP|DBG_IRP, (">CleanUpPacketLists (%x)\n", DeviceObject));
  382. // acquire lock
  383. KeAcquireSpinLock( &pDevExt->ControlLock, &irql );
  384. if ( !PListHead || !PEvent) {
  385. DbgDump(DBG_ERR, ("CleanUpPacketLists: !(Head|Event)\n"));
  386. TEST_TRAP();
  387. KeReleaseSpinLock( &pDevExt->ControlLock, irql );
  388. return STATUS_INVALID_PARAMETER;
  389. }
  390. // walk the list...
  391. for ( pleHead = PListHead, // get 1st ListEntry
  392. pleCurrent = pleHead->Flink,
  393. pleNext = pleCurrent->Flink;
  394. pleCurrent != pleHead, // done when we loop back to head
  395. !pleHead, // or hit a trashed list
  396. !pleCurrent,
  397. !pleNext;
  398. pleCurrent = pleNext, // get the next in the list
  399. pleNext = pleCurrent->Flink
  400. )
  401. {
  402. // did the list get trashed?
  403. ASSERT( pleHead );
  404. ASSERT( pleCurrent );
  405. ASSERT( pleNext );
  406. // extract packet pointer
  407. pPacket = CONTAINING_RECORD( pleCurrent,
  408. USB_PACKET,
  409. ListEntry );
  410. if ( pPacket &&
  411. pPacket->DeviceExtension &&
  412. pPacket->Irp ) {
  413. // cancel packet's timer
  414. KeCancelTimer( &pPacket->TimerObj);
  415. if ( !IoCancelIrp( pPacket->Irp ) ) {
  416. //
  417. // This means USB has the Irp in a non-canceable state.
  418. // We need to wait for either the pending read event, or the cancel event.
  419. //
  420. DbgDump(DBG_IRP, ("CleanUpPacketLists: Irp (%p) was not cancelled\n", pPacket->Irp));
  421. }
  422. //
  423. // we need to wait for the Irp to complete from USB
  424. //
  425. DbgDump(DBG_IRP, ("Waiting for Irp (%p) to complete...\n", pPacket->Irp ));
  426. KeReleaseSpinLock( &pDevExt->ControlLock, irql );
  427. PAGED_CODE();
  428. KeWaitForSingleObject( PEvent,
  429. Executive,
  430. KernelMode,
  431. FALSE,
  432. NULL );
  433. KeAcquireSpinLock( &pDevExt->ControlLock, &irql );
  434. DbgDump(DBG_IRP, ("...Irp (%p) signalled completion.\n", pPacket->Irp ));
  435. } else {
  436. // it was completed already
  437. DbgDump(DBG_WRN, ("CleanUpPacketLists: No Packet\n" ));
  438. if ( pPacket &&
  439. (!pPacket->ListEntry.Flink || !pPacket->ListEntry.Blink)) {
  440. DbgDump(DBG_ERR, ("CleanUpPacketLists: corrupt List!!\n" ));
  441. TEST_TRAP();
  442. break;
  443. }
  444. }
  445. //
  446. // The Irp should percolate back to our R/W completion
  447. // routine, which puts the packet back in packet pool.
  448. //
  449. }
  450. #if DBG
  451. if ( !pleHead || !pleCurrent || !pleNext) {
  452. DbgDump(DBG_ERR, ("CleanUpPacketLists: corrupt List!!\n" ));
  453. TEST_TRAP();
  454. }
  455. #endif
  456. KeReleaseSpinLock( &pDevExt->ControlLock, irql );
  457. DbgDump(DBG_PNP|DBG_IRP, ("<CleanUpPacketLists (0x%x)\n", STATUS_SUCCESS));
  458. return status;
  459. }
  460. NTSTATUS
  461. RemoveDevice(
  462. IN PDEVICE_OBJECT DeviceObject,
  463. IN PIRP Irp
  464. )
  465. /*++
  466. Routine Description:
  467. This routine handles IRP_MN_REMOVE_DEVICE.
  468. See: Setup, Plug & Play, Power Management: Preliminary Windows 2000 DDK
  469. Section 3.3.3.1 Removing a Device in a Function Driver
  470. Arguments:
  471. DeviceObject
  472. Irp
  473. Return Value:
  474. NTSTATUS
  475. --*/
  476. {
  477. PDEVICE_EXTENSION pDevExt = DeviceObject->DeviceExtension;
  478. NTSTATUS status = STATUS_SUCCESS;
  479. DbgDump(DBG_PNP|DBG_TRACE, (">RemoveDevice (%x)\n", DeviceObject));
  480. PAGED_CODE();
  481. //
  482. // stop the device
  483. //
  484. status = StopDevice( DeviceObject, Irp );
  485. InterlockedExchange((PULONG)&pDevExt->PnPState, PnPStateRemoved);
  486. //
  487. // Pass the Irp down the stack now that we've done our work.
  488. // REMOVE_DEVICE must be handled first by the driver at the top of the device stack (this device)
  489. // and then by each next-lower driver (USBD) in the stack. A driver is not required to wait for underlying drivers to
  490. // finish their remove operations before continuing with its remove activities.
  491. //
  492. IoCopyCurrentIrpStackLocationToNext(Irp);
  493. status = IoCallDriver( pDevExt->NextDevice, Irp );
  494. //
  495. // wait for any pending I/O
  496. //
  497. ReleaseRemoveLockAndWait(&pDevExt->RemoveLock, Irp);
  498. //
  499. // cleanup any resources...
  500. //
  501. UsbFreeReadBuffer( DeviceObject );
  502. // free up notification buffer
  503. if(pDevExt->IntBuff) {
  504. ExFreePool(pDevExt->IntBuff);
  505. pDevExt->IntBuff = NULL;
  506. }
  507. //
  508. // delete LookasideLists
  509. //
  510. ExDeleteNPagedLookasideList( &pDevExt->PacketPool );
  511. ExDeleteNPagedLookasideList( &pDevExt->BulkTransferUrbPool );
  512. ExDeleteNPagedLookasideList( &pDevExt->PipeRequestUrbPool );
  513. ExDeleteNPagedLookasideList( &pDevExt->VendorRequestUrbPool );
  514. ExDeleteNPagedLookasideList( &pDevExt->WorkItemPool );
  515. if ( !g_isWin9x && g_ExposeComPort ) {
  516. // cleanup "COMx:" namespace
  517. UndoSerialPortNaming(pDevExt);
  518. }
  519. //
  520. // Dump PERF data
  521. //
  522. #if PERFORMANCE
  523. if (DebugLevel & DBG_PERF )
  524. {
  525. DumpPerfCounters();
  526. DbgPrint("USB IN wMaxPacketSize: %d\n", pDevExt->ReadPipe.MaxPacketSize);
  527. DbgPrint("USB OUT wMaxPacketSize: %d\n\n", pDevExt->WritePipe.MaxPacketSize );
  528. if ( pDevExt->IntPipe.hPipe) {
  529. DbgPrint("USB INT wMaxPacketSize: %d\n", pDevExt->IntPipe.MaxPacketSize);
  530. DbgPrint("USB INT Timeout: %d msec\n\n", -(pDevExt->IntReadTimeOut.QuadPart) / 10000 );
  531. }
  532. DbgPrint("TTL User Write Bytes : %d\n", pDevExt->TtlWriteBytes );
  533. DbgPrint("TTL User Write Requests: %d\n\n", pDevExt->TtlWriteRequests );
  534. DbgPrint("TTL User Read Bytes: %d\n", pDevExt->TtlReadBytes );
  535. DbgPrint("TTL User Read Requests: %d\n\n", pDevExt->TtlReadRequests );
  536. DbgPrint("TTL USB Read Bytes: %d\n", pDevExt->TtlUSBReadBytes );
  537. DbgPrint("TTL USB Read Requests: %d\n\n", pDevExt->TtlUSBReadRequests );
  538. DbgPrint("USB Read Buffer Size: %d\n", pDevExt->UsbReadBuffSize );
  539. // Note: this signals the error condition: USB overran the *UsbReadBuffer* pending down the stack.
  540. DbgPrint("USB Read Buffer Overruns: %d\n\n", pDevExt->TtlUSBReadBuffOverruns );
  541. #if USE_RING_BUFF
  542. DbgPrint("Internal RingBuffer Size: %d\n", pDevExt->RingBuff.Size );
  543. DbgPrint("Internal RingBuffer Overruns: %d\n\n", pDevExt->TtlRingBuffOverruns);
  544. #endif
  545. }
  546. #endif
  547. DbgDump(DBG_PNP|DBG_TRACE, ("<RemoveDevice (0x%x)\n", status));
  548. return status;
  549. }
  550. NTSTATUS
  551. Pnp(
  552. IN PDEVICE_OBJECT PDevObj,
  553. IN PIRP PIrp
  554. )
  555. {
  556. NTSTATUS status = STATUS_SUCCESS;
  557. PIO_STACK_LOCATION pIrpSp;
  558. PDEVICE_EXTENSION pDevExt = PDevObj->DeviceExtension;
  559. PVOID IoBuffer;
  560. ULONG InputBufferLength;
  561. UCHAR MinorFunction;
  562. BOOLEAN PassDown = TRUE;
  563. DbgDump(DBG_PNP|DBG_TRACE, (">Pnp)\n"));
  564. PAGED_CODE();
  565. status = AcquireRemoveLock(&pDevExt->RemoveLock, PIrp);
  566. if ( !NT_SUCCESS(status) ) {
  567. DbgDump(DBG_ERR, ("Pnp:(0x%x)\n", status));
  568. PIrp->IoStatus.Status = status;
  569. IoCompleteRequest(PIrp, IO_NO_INCREMENT);
  570. return status;
  571. }
  572. pIrpSp = IoGetCurrentIrpStackLocation(PIrp);
  573. MinorFunction = pIrpSp->MinorFunction;
  574. IoBuffer = PIrp->AssociatedIrp.SystemBuffer;
  575. InputBufferLength = pIrpSp->Parameters.DeviceIoControl.InputBufferLength;
  576. DbgDump(DBG_PNP, ("%s\n", PnPMinorFunctionString(MinorFunction)));
  577. switch (MinorFunction) {
  578. case IRP_MN_START_DEVICE:
  579. //
  580. // We cannot send the device any Non-PnP IRPs until
  581. // START_DEVICE has been propogated down the device stack
  582. //
  583. ASSERT( (PnPStateAttached == pDevExt->PnPState) ||
  584. (PnPStateStopped == pDevExt->PnPState) );
  585. status = StartDevice(PDevObj, PIrp);
  586. PassDown = FALSE;
  587. break;
  588. case IRP_MN_STOP_DEVICE:
  589. status = StopDevice(PDevObj, PIrp);
  590. InterlockedExchange((PULONG)&pDevExt->PnPState, PnPStateStopped);
  591. break;
  592. case IRP_MN_SURPRISE_REMOVAL:
  593. //
  594. // * Win 2000 only *
  595. //
  596. status = StopDevice(PDevObj, PIrp);
  597. InterlockedExchange((PULONG)&pDevExt->PnPState, PnPStateSupriseRemove);
  598. break;
  599. case IRP_MN_REMOVE_DEVICE:
  600. //
  601. // sent when the device has been removed and probably physically detached
  602. // from the computer. As with STOP_DEVICE, the driver cannot
  603. // assume it has received any previous query and may have to
  604. // explicitly cancel any pending I/O IRPs it has staged.
  605. //
  606. status = RemoveDevice(PDevObj, PIrp);
  607. //
  608. // detach device from stack &
  609. //
  610. IoDetachDevice(pDevExt->NextDevice);
  611. //
  612. // delete our FDO and symbolic link
  613. //
  614. DeleteDevObjAndSymLink(PDevObj);
  615. //
  616. // A function driver does not specify an IoCompletion routine for a remove IRP,
  617. // nor does it complete the IRP. Remove IRPs are completed by the parent bus driver.
  618. // The device object & extension are now gone... don't touch it.
  619. //
  620. PassDown = FALSE;
  621. break;
  622. case IRP_MN_QUERY_REMOVE_DEVICE:
  623. InterlockedExchange((PULONG)&pDevExt->PnPState, PnPStateRemovePending);
  624. break;
  625. case IRP_MN_CANCEL_REMOVE_DEVICE:
  626. InterlockedExchange((PULONG)&pDevExt->PnPState, PnPStateStarted);
  627. break;
  628. case IRP_MN_QUERY_STOP_DEVICE:
  629. InterlockedExchange((PULONG)&pDevExt->PnPState, PnPStateStopPending);
  630. break;
  631. case IRP_MN_CANCEL_STOP_DEVICE:
  632. InterlockedExchange((PULONG)&pDevExt->PnPState, PnPStateStarted);
  633. break;
  634. case IRP_MN_QUERY_CAPABILITIES: {
  635. KEVENT Event;
  636. KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
  637. IoCopyCurrentIrpStackLocationToNext(PIrp);
  638. IoSetCompletionRoutine( PIrp, SyncCompletion, &Event, TRUE, TRUE, TRUE);
  639. status = IoCallDriver(pDevExt->NextDevice, PIrp);
  640. if (status == STATUS_PENDING) {
  641. KeWaitForSingleObject( &Event, Executive, KernelMode, FALSE, NULL);
  642. }
  643. status = PIrp->IoStatus.Status;
  644. if ( STATUS_SUCCESS == status ) {
  645. //
  646. // add in our capabilities
  647. //
  648. PDEVICE_CAPABILITIES pDevCaps = NULL;
  649. pDevCaps = pIrpSp->Parameters.DeviceCapabilities.Capabilities;
  650. //
  651. // touch Device PnP capabilities here...
  652. //
  653. pDevCaps->LockSupported = 0;
  654. pDevCaps->Removable = 1;
  655. pDevCaps->DockDevice = 0;
  656. pDevCaps->SilentInstall = 1;
  657. pDevCaps->SurpriseRemovalOK = 1;
  658. //
  659. // touch Device Power capabilities here...
  660. //
  661. }
  662. PassDown = FALSE;
  663. }
  664. break;
  665. case IRP_MN_FILTER_RESOURCE_REQUIREMENTS: {
  666. if (g_isWin9x) {
  667. status = PIrp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
  668. PassDown = FALSE;
  669. }
  670. }
  671. break;
  672. case IRP_MN_QUERY_PNP_DEVICE_STATE: {
  673. //
  674. // If the device took too many device errors then UsbResetOrAbortPipeWorkItem
  675. // disabled the device and called IoInvalidateDeviceState.
  676. // We only handle this Irp if we were disabled or marked as removed
  677. //
  678. KIRQL irql;
  679. #if PnP_AS
  680. BOOLEAN bDisableInterface = FALSE;
  681. #endif
  682. KeAcquireSpinLock(&pDevExt->ControlLock, &irql);
  683. if (InterlockedCompareExchange(&pDevExt->DeviceRemoved, TRUE, TRUE)) {
  684. //
  685. // Do not set the PNP_DEVICE_REMOVED bit, else DevMan will mark the driver as banged out
  686. // until the next reboot; but stop taking requests.
  687. //
  688. DbgDump(DBG_WRN, ("PnP State: PNP_DEVICE_REMOVED\n"));
  689. InterlockedExchange(&pDevExt->AcceptingRequests, FALSE);
  690. #if PnP_AS
  691. bDisableInterface = TRUE;
  692. #endif
  693. } else if ( !CanAcceptIoRequests(PDevObj, FALSE, FALSE) ) {
  694. DbgDump(DBG_WRN, ("PnP State: PNP_DEVICE_FAILED\n"));
  695. PIrp->IoStatus.Information |= PNP_DEVICE_FAILED;
  696. status = PIrp->IoStatus.Status = STATUS_SUCCESS;
  697. #if PnP_AS
  698. bDisableInterface = TRUE;
  699. #endif
  700. }
  701. KeReleaseSpinLock(&pDevExt->ControlLock, irql);
  702. #if PnP_AS
  703. // This is a great place to disable the interface, but unfortunately ActiveSync 3.1 will not reopen the device afterwards...
  704. // It misses about every other PnP this way. By *not* disableing the interface here then AS's only indication that anything is wrong is
  705. // by noticing that it's Read/Write/Serial requests get rejected, and AS will eventually timeout after some time dT ...
  706. // sometimes more than 5 seconds on Read/Writes. However, it does not sense Timeouts on Serial IOCTLS so will keep
  707. // sending us Serial requests, which will cause the bugcheck 0xCE in Set DTR. Disabeling the interface has the desired effect of
  708. // disallowing apps from sending us *ANY* requests.
  709. // This is an AS bug - there is pending email with kentce about this.
  710. if (bDisableInterface && pDevExt->DeviceClassSymbolicName.Buffer) {
  711. //
  712. // set the interface state to inactive to let ActiveSync know to release the handle. Must be done @ PASSIVE_LEVEL
  713. //
  714. status = IoSetDeviceInterfaceState(&pDevExt->DeviceClassSymbolicName, FALSE );
  715. if (NT_SUCCESS(status)) {
  716. DbgDump(DBG_WRN, ("IoSetDeviceInterfaceState.1: OFF\n"));
  717. }
  718. }
  719. #endif // PnP_AS
  720. }
  721. break;
  722. default:
  723. break;
  724. }
  725. if (IRP_MN_REMOVE_DEVICE != MinorFunction) {
  726. ReleaseRemoveLock(&pDevExt->RemoveLock, PIrp);
  727. }
  728. if (PassDown) {
  729. IoCopyCurrentIrpStackLocationToNext(PIrp);
  730. status = IoCallDriver(pDevExt->NextDevice, PIrp);
  731. } else if (IRP_MN_REMOVE_DEVICE != MinorFunction) {
  732. IoCompleteRequest(PIrp, IO_NO_INCREMENT);
  733. }
  734. DbgDump(DBG_PNP|DBG_TRACE, ("<Pnp (0x%x)\n", status));
  735. return status;
  736. }
  737. NTSTATUS
  738. SyncCompletion(
  739. IN PDEVICE_OBJECT PDevObj,
  740. IN PIRP PIrp,
  741. IN PKEVENT PSyncEvent
  742. )
  743. /*++
  744. Routine Description:
  745. This function is used to signal an event.
  746. It is used as a default completion routine.
  747. Arguments:
  748. PDevObj - Pointer to Device Object
  749. PIrp - Pointer to IRP that is being completed
  750. PSyncEvent - Pointer to event that we should set
  751. Return Value:
  752. STATUS_MORE_PROCESSING_REQUIRED
  753. --*/
  754. {
  755. UNREFERENCED_PARAMETER( PDevObj );
  756. UNREFERENCED_PARAMETER( PIrp );
  757. KeSetEvent( PSyncEvent, IO_NO_INCREMENT, FALSE );
  758. return STATUS_MORE_PROCESSING_REQUIRED;
  759. }
  760. NTSTATUS
  761. Power(
  762. IN PDEVICE_OBJECT DeviceObject,
  763. IN PIRP Irp
  764. )
  765. {
  766. PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
  767. DbgDump(DBG_PNP, (">PnpPower (%p, %p)\n", DeviceObject, Irp));
  768. //
  769. // If the device has been removed, the driver should not pass
  770. // the IRP down to the next lower driver.
  771. //
  772. if ( PnPStateRemoved == pDevExt->PnPState ) {
  773. PoStartNextPowerIrp(Irp);
  774. Irp->IoStatus.Status = STATUS_DELETE_PENDING;
  775. IoCompleteRequest(Irp, IO_NO_INCREMENT );
  776. return STATUS_DELETE_PENDING;
  777. }
  778. //
  779. // passthrough
  780. //
  781. PoStartNextPowerIrp( Irp );
  782. IoSkipCurrentIrpStackLocation( Irp );
  783. DbgDump( DBG_PNP, ("<PnpPower\n") );
  784. return PoCallDriver( pDevExt->NextDevice, Irp );
  785. }
  786. // EOF