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.

1939 lines
52 KiB

  1. /*++
  2. Copyright (c) 1995,1996 Microsoft Corporation
  3. :ts=4
  4. Module Name:
  5. transfer.c
  6. Abstract:
  7. The module manages control type transactions on the USB.
  8. Environment:
  9. kernel mode only
  10. Notes:
  11. Revision History:
  12. 11-01-95 : created
  13. 04-26-96 : linked urb support
  14. --*/
  15. #include "wdm.h"
  16. #include "stdarg.h"
  17. #include "stdio.h"
  18. #include "usbdi.h"
  19. #include "hcdi.h"
  20. #include "uhcd.h"
  21. //
  22. // Use the flag to force all pending transfers to complete
  23. //
  24. typedef USBD_STATUS UHCD_INIT_TRANSFER_ROUTINE(PDEVICE_OBJECT DeviceObject,
  25. PUHCD_ENDPOINT Endpoint,
  26. PHCD_URB Urb);
  27. typedef USBD_STATUS UHCD_PROCESS_TRANSFER_ROUTINE(
  28. PDEVICE_OBJECT DeviceObject,
  29. PUHCD_ENDPOINT Endpoint,
  30. PHCD_URB Urb,
  31. PBOOLEAN Completed);
  32. UHCD_INIT_TRANSFER_ROUTINE UHCD_InitializeAsyncTransfer;
  33. UHCD_PROCESS_TRANSFER_ROUTINE UHCD_ProcessAsyncTransfer;
  34. UHCD_INIT_TRANSFER_ROUTINE UHCD_InitializeIsochTransfer;
  35. UHCD_PROCESS_TRANSFER_ROUTINE UHCD_ProcessIsochTransfer;
  36. typedef struct _UHCD_TRANSFER_DISPATCH_ENTRY {
  37. UHCD_INIT_TRANSFER_ROUTINE *InitializeTransfer;
  38. UHCD_PROCESS_TRANSFER_ROUTINE *ProcessTransfer;
  39. } UHCD_TRANSFER_DISPATCH_ENTRY;
  40. UHCD_TRANSFER_DISPATCH_ENTRY TransferDispatchTable[4] =
  41. {
  42. //Control
  43. UHCD_InitializeAsyncTransfer, UHCD_ProcessAsyncTransfer,
  44. //Isoch
  45. UHCD_InitializeIsochTransfer, UHCD_ProcessIsochTransfer,
  46. //Bulk
  47. UHCD_InitializeAsyncTransfer, UHCD_ProcessAsyncTransfer,
  48. //Interrupt
  49. UHCD_InitializeAsyncTransfer, UHCD_ProcessAsyncTransfer
  50. };
  51. VOID
  52. UHCD_ValidateIsoUrb(
  53. IN PDEVICE_OBJECT DeviceObject,
  54. IN PUHCD_ENDPOINT Endpoint,
  55. IN OUT PHCD_URB Urb
  56. )
  57. /*++
  58. Routine Description:
  59. Arguments:
  60. DeviceObject - pointer to a device object
  61. Irp - pointer to an I/O Request Packet
  62. Return Value:
  63. None.
  64. --*/
  65. {
  66. ULONG currentBusFrame;
  67. LONG offset;
  68. PDEVICE_EXTENSION deviceExtension;
  69. BOOLEAN late = FALSE;
  70. UHCD_ASSERT(Endpoint->Type == USB_ENDPOINT_TYPE_ISOCHRONOUS);
  71. deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  72. currentBusFrame = UHCD_GetCurrentFrame(DeviceObject);
  73. LOGENTRY(LOG_ISO,'ISxf', 0, Urb, currentBusFrame);
  74. if (Urb->HcdUrbCommonTransfer.TransferFlags &
  75. USBD_START_ISO_TRANSFER_ASAP) {
  76. if (Endpoint->EndpointFlags & EPFLAG_VIRGIN) {
  77. UHCD_KdPrint((2, "'ASAP flag set for virgin pipe\n"));
  78. // No transfers on this endpoint yet, set the StartFrame
  79. // to the current bus frame, plus a latency factor.
  80. //
  81. Urb->UrbIsochronousTransfer.StartFrame =
  82. currentBusFrame + UHCD_ASAP_LATENCY;
  83. } else {
  84. UHCD_KdPrint((2, "'ASAP flag set for non-virgin pipe\n"));
  85. // There have been transfers on this endpoint already,
  86. // set the StartFrame to the next free frame for this
  87. // endpoint.
  88. //
  89. Urb->UrbIsochronousTransfer.StartFrame =
  90. Endpoint->CurrentFrame;
  91. }
  92. } else {
  93. // If the StartFrame is explicitly specified and there was
  94. // a previous transfer on this endpoint, make sure the specified
  95. // StartFrame does not overlap the last transfer.
  96. //
  97. if (!(Endpoint->EndpointFlags & EPFLAG_VIRGIN)) {
  98. offset = Urb->UrbIsochronousTransfer.StartFrame -
  99. Endpoint->CurrentFrame;
  100. if (offset < 0) {
  101. UHCD_KdPrint((2, "'StartFrame overlap\n"));
  102. URB_HEADER(Urb).Status = USBD_STATUS_BAD_START_FRAME;
  103. }
  104. }
  105. }
  106. // Sanity check that the start frame is within a certain range
  107. // of the current bus frame
  108. UHCD_KdPrint((2, "'currentBusFrame = %d\n", currentBusFrame));
  109. offset = Urb->UrbIsochronousTransfer.StartFrame - currentBusFrame;
  110. if (offset < 0) {
  111. deviceExtension->IsoStats.LateUrbs++;
  112. late = TRUE;
  113. offset*=-1;
  114. // transfer was late count how may packets missed due
  115. // to tardyness
  116. deviceExtension->IsoStats.LateMissedCount += ((USHORT)offset);
  117. }
  118. if (late &&
  119. offset == (LONG) Urb->UrbIsochronousTransfer.NumberOfPackets) {
  120. deviceExtension->IsoStats.StaleUrbs++;
  121. }
  122. if (offset > USBD_ISO_START_FRAME_RANGE) {
  123. UHCD_KdPrint((2, "'StartFrame out of range\n"));
  124. URB_HEADER(Urb).Status = USBD_STATUS_BAD_START_FRAME;
  125. }
  126. // update our iso Stats
  127. if (offset == 0) {
  128. deviceExtension->IsoStats.LateUrbs++;
  129. } else if (offset == 1 && !late) {
  130. // client requests this transfer within 1ms
  131. deviceExtension->IsoStats.TransfersCF_1ms++;
  132. } else if (offset == 2 && !late) {
  133. // client requests this transfer within 2ms
  134. deviceExtension->IsoStats.TransfersCF_2ms++;
  135. } else if (offset <= 5 && !late) {
  136. // client requests this transfer within 5ms
  137. deviceExtension->IsoStats.TransfersCF_5ms++;
  138. }
  139. if (deviceExtension->IsoStats.SmallestUrbPacketCount == 0) {
  140. deviceExtension->IsoStats.SmallestUrbPacketCount =
  141. (USHORT) Urb->UrbIsochronousTransfer.NumberOfPackets;
  142. }
  143. if (Urb->UrbIsochronousTransfer.NumberOfPackets <
  144. deviceExtension->IsoStats.SmallestUrbPacketCount) {
  145. deviceExtension->IsoStats.SmallestUrbPacketCount =
  146. (USHORT) Urb->UrbIsochronousTransfer.NumberOfPackets;
  147. }
  148. if (Urb->UrbIsochronousTransfer.NumberOfPackets >
  149. deviceExtension->IsoStats.LargestUrbPacketCount) {
  150. deviceExtension->IsoStats.LargestUrbPacketCount =
  151. (USHORT) Urb->UrbIsochronousTransfer.NumberOfPackets;
  152. }
  153. }
  154. VOID
  155. UHCD_Transfer_StartIo(
  156. IN PDEVICE_OBJECT DeviceObject,
  157. IN PIRP Irp
  158. )
  159. /*++
  160. Routine Description:
  161. Called for each transfer request on a control endpoint, from the
  162. UHCD_StartIo routine.
  163. Arguments:
  164. DeviceObject - pointer to a device object
  165. Irp - pointer to an I/O Request Packet
  166. Return Value:
  167. None.
  168. --*/
  169. {
  170. PHCD_URB urb, urbtmp;
  171. PDEVICE_EXTENSION deviceExtension;
  172. PUHCD_ENDPOINT endpoint;
  173. KIRQL irql;
  174. UHCD_KdPrint((2, "'enter UHCD_Transfer_StartIo\n"));
  175. //
  176. // initialize pending count now
  177. //
  178. PENDING_URB_COUNT(Irp) = 0;
  179. deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  180. //
  181. // Get the endpoint
  182. //
  183. urb = URB_FROM_IRP(Irp);
  184. endpoint = HCD_AREA(urb).HcdEndpoint;
  185. ASSERT_ENDPOINT(endpoint);
  186. UHCD_EndpointWakeup(DeviceObject, endpoint);
  187. LOGENTRY(LOG_ISO, 'xSIO', 0, 0, 0);
  188. // If this is an iso transfer then see if we need to set the start frame
  189. //
  190. if (endpoint->Type == USB_ENDPOINT_TYPE_ISOCHRONOUS) {
  191. UHCD_ValidateIsoUrb(DeviceObject,
  192. endpoint,
  193. urb);
  194. if (URB_HEADER(urb).Status == USBD_STATUS_BAD_START_FRAME) {
  195. IoStartNextPacket(DeviceObject, FALSE);
  196. LOGENTRY(LOG_ISO,'BADf', 0, urb, 0);
  197. deviceExtension->IsoStats.BadStartFrame++;
  198. // NOTE: we only allow one urb per iso request
  199. // since we pended the original request bump
  200. // the pending count so we'll complete this request
  201. INCREMENT_PENDING_URB_COUNT(Irp);
  202. UHCD_CompleteIrp(DeviceObject, Irp, STATUS_SUCCESS, 0, urb);
  203. goto UHCD_Transfer_StartIo_Done;
  204. }
  205. // Advance the next free StartFrame for this endpoint to be the
  206. // frame immediately following the last frame of this transfer.
  207. //
  208. endpoint->CurrentFrame = urb->UrbIsochronousTransfer.StartFrame +
  209. urb->UrbIsochronousTransfer.NumberOfPackets;
  210. //
  211. // we lose our virginity when the first transfer starts
  212. //
  213. CLR_EPFLAG(endpoint, EPFLAG_VIRGIN);
  214. } else if (endpoint->Type == USB_ENDPOINT_TYPE_BULK) {
  215. //
  216. // turn on BW reclimation for bulk transfers
  217. //
  218. UHCD_BW_Reclimation(DeviceObject, TRUE);
  219. }
  220. //
  221. // check the endpoint state, if we are stalled we need
  222. // to refuse transfers.
  223. //
  224. if (endpoint->EndpointFlags & EPFLAG_HOST_HALTED) {
  225. //
  226. // mark all urbs submitted with an error
  227. //
  228. urbtmp = urb;
  229. do {
  230. INCREMENT_PENDING_URB_COUNT(Irp);
  231. urbtmp->HcdUrbCommonTransfer.Status =
  232. USBD_STATUS_ENDPOINT_HALTED;
  233. urbtmp = urbtmp->HcdUrbCommonTransfer.UrbLink;
  234. #if DBG
  235. if (urbtmp) {
  236. TEST_TRAP();
  237. }
  238. #endif
  239. } while (urbtmp);
  240. IoStartNextPacket(DeviceObject, FALSE);
  241. UHCD_CompleteIrp(DeviceObject, Irp, STATUS_SUCCESS, 0, urb);
  242. goto UHCD_Transfer_StartIo_Done;
  243. }
  244. if (endpoint->EndpointFlags & EPFLAG_FAST_ISO) {
  245. INCREMENT_PENDING_URB_COUNT(Irp);
  246. UHCD_ProcessFastIsoTransfer(DeviceObject,
  247. endpoint,
  248. Irp,
  249. urb);
  250. IoStartNextPacket(DeviceObject, FALSE);
  251. goto UHCD_Transfer_StartIo_Done;
  252. }
  253. //
  254. // Get exclusive access to the endpoint pending transfer
  255. // queue.
  256. //
  257. LOCK_ENDPOINT_PENDING_LIST(endpoint, irql, 'lck0');
  258. //
  259. // Insert all urbs that make up this request into
  260. // the transfer pending queue.
  261. //
  262. do {
  263. INCREMENT_PENDING_URB_COUNT(Irp);
  264. URB_HEADER(urb).Status = UHCD_STATUS_PENDING_QUEUED;
  265. InsertTailList(&endpoint->PendingTransferList,
  266. &HCD_AREA(urb).HcdListEntry);
  267. //#if DBG
  268. // if (urb->HcdUrbCommonTransfer.UrbLink) {
  269. // TEST_TRAP();
  270. // }
  271. //#endif
  272. urb = urb->HcdUrbCommonTransfer.UrbLink;
  273. } while (urb);
  274. //
  275. // release exclusive access to the endpoint pending list
  276. //
  277. UNLOCK_ENDPOINT_PENDING_LIST(endpoint, irql, 'ulk0');
  278. //
  279. // call the endpoint worker function to activate
  280. // any transfers if possible.
  281. //
  282. if (endpoint->EndpointFlags & EPFLAG_DBL_BUFFER) {
  283. UHCD_RequestInterrupt(DeviceObject, -2);
  284. } else {
  285. UHCD_EndpointWorker(DeviceObject, endpoint);
  286. }
  287. IoStartNextPacket(DeviceObject, FALSE);
  288. UHCD_Transfer_StartIo_Done:
  289. UHCD_KdPrint((2, "'exit UHCD_Transfer_StartIo\n"));
  290. }
  291. VOID
  292. UHCD_CompleteTransferDPC(
  293. IN PDEVICE_OBJECT DeviceObject,
  294. IN PUHCD_ENDPOINT Endpoint,
  295. IN LONG Slot
  296. )
  297. /*++
  298. Routine Description:
  299. Process a urb in the active list for an endpoint, complete if
  300. necessary and start more transfers.
  301. This routine is not reentrant for the same endpoint.
  302. Arguments:
  303. DeviceObject - pointer to a device object.
  304. Endpoint - endpoint to check for completed transfers.
  305. Slot - endpoint active slot to process.
  306. Return Value:
  307. --*/
  308. {
  309. PHCD_URB urb, urbtmp;
  310. BOOLEAN completed = FALSE;
  311. ULONG usbdStatus = USBD_STATUS_SUCCESS;
  312. PIRP irp = NULL;
  313. PDEVICE_EXTENSION deviceExtension;
  314. ULONG i;
  315. PVOID currentVa;
  316. PHCD_EXTENSION urbWork;
  317. KIRQL irql;
  318. //UHCD_KdPrint((2, "'enter UHCD_CompleteTransferDPC\n"));
  319. ASSERT_ENDPOINT(Endpoint);
  320. deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  321. //
  322. // Do we have an current transfer for this endpoint?
  323. //
  324. // if no the endpoint is 'idle' on the host end,
  325. // so we just exit.
  326. //
  327. // if yes then we need to see if we have completed
  328. // the transfer set, if we have then we complete the
  329. // urb and call EndpointWorker to start more transfers
  330. //
  331. //
  332. // ** BUGBUG
  333. // ** Optimization
  334. // an optimization we can add here is to remove
  335. // the endpoint from the endpoint list when it goes
  336. // idle -- we would then let the EndpointWorker
  337. // function actuvate it when more transfers get queued.
  338. //
  339. //
  340. // get the Transfer we are intetrested in
  341. //
  342. urb = Endpoint->ActiveTransfers[Slot];
  343. UHCD_ASSERT(urb != NULL);
  344. urbWork = HCD_AREA(urb).HcdExtension;
  345. // check the skip flag
  346. if (Endpoint->EndpointFlags & EPFLAG_ABORT_ACTIVE_TRANSFERS) {
  347. // clear the skip flag if we are in an abort scenario
  348. LOGENTRY(LOG_MISC, 'Cdfr', urb, urbWork, Slot);
  349. urbWork->Flags &= ~UHCD_TRANSFER_DEFER;
  350. }
  351. // check the skip flag
  352. if (urbWork->Flags & UHCD_TRANSFER_DEFER) {
  353. LOGENTRY(LOG_MISC, 'defr', urb, urbWork, Slot);
  354. return;
  355. }
  356. //
  357. // Determine if the current transfer request is finished.
  358. //
  359. UHCD_ASSERT(Endpoint->Type<=USB_ENDPOINT_TYPE_INTERRUPT);
  360. irp = HCD_AREA(urb).HcdIrp;
  361. //
  362. // If the urb is marked completed with an error then don't
  363. // bother calling the process routine.
  364. //
  365. // This will allow the process routine to mark additional
  366. // active urbs for completion.
  367. // This also allows the completion EndpointWorker routine
  368. // to complete any transfers that it could not initilaize.
  369. //
  370. if (USBD_ERROR(urb->HcdUrbCommonTransfer.Status)) {
  371. completed = TRUE;
  372. LOGENTRY(LOG_MISC, 'tErr', urb->HcdUrbCommonTransfer.Status, urb, 0);
  373. } else if (urbWork->Flags & UHCD_TRANSFER_ACTIVE) {
  374. usbdStatus =
  375. (TransferDispatchTable[Endpoint->Type].ProcessTransfer)
  376. (DeviceObject,
  377. Endpoint,
  378. urb,
  379. &completed);
  380. }
  381. if (completed) { // current transfer completed
  382. ULONG userBufferLength;
  383. LOGENTRY(LOG_ISO,'xfrC', Endpoint, urb, usbdStatus);
  384. LOGENTRY(LOG_ISO,'xfr2', urb->HcdUrbCommonTransfer.Status, 0, 0);
  385. UHCD_ASSERT(urbWork->BytesTransferred <=
  386. urb->HcdUrbCommonTransfer.TransferBufferLength);
  387. userBufferLength = urb->HcdUrbCommonTransfer.TransferBufferLength;
  388. urb->HcdUrbCommonTransfer.TransferBufferLength =
  389. urbWork->BytesTransferred;
  390. //
  391. // free the map registers now along with common buffers used to
  392. // double buffer packets.
  393. //
  394. if (urbWork->NumberOfLogicalAddresses) {
  395. currentVa =
  396. MmGetMdlVirtualAddress(urb->HcdUrbCommonTransfer.
  397. TransferBufferMDL);
  398. // Flush the DMA buffer. If this was an IN transfer and the
  399. // transfer was double-buffered (e.g. original buffer was located
  400. // above 4GB on a PAE system) this will flush the DMA buffer back
  401. // to the original transfer buffer.
  402. //
  403. // IoFlushAdapterBuffers() should only be called once per call
  404. // to IoAllocateAdapterChannel()
  405. //
  406. IoFlushAdapterBuffers(deviceExtension->AdapterObject,
  407. urb->HcdUrbCommonTransfer.TransferBufferMDL,
  408. urbWork->MapRegisterBase,
  409. currentVa,
  410. urb->HcdUrbCommonTransfer.TransferBufferLength,
  411. DATA_DIRECTION_OUT(urb));
  412. for (i=0; i<urbWork->NumberOfLogicalAddresses; i++) {
  413. if (urbWork->LogicalAddressList[i].PacketMemoryDescriptor) {
  414. // if this is an IN transfer then update the
  415. // client buffer
  416. ULONG copylen;
  417. if (DATA_DIRECTION_IN(urb)) {
  418. LOGENTRY(LOG_MISC, 'PAKd', Endpoint->MaxPacketSize,
  419. urbWork->LogicalAddressList[i].PacketOffset,
  420. urbWork->LogicalAddressList[i].
  421. PacketMemoryDescriptor->VirtualAddress);
  422. LOGENTRY(LOG_MISC, 'PAKd', 0,
  423. currentVa,
  424. (PUCHAR)urb->HcdUrbCommonTransfer.
  425. TransferBufferMDL->MappedSystemVa);
  426. // make sure we don't overrun the client buffer
  427. copylen = userBufferLength -
  428. urbWork->LogicalAddressList[i].PacketOffset;
  429. if (copylen > Endpoint->MaxPacketSize) {
  430. copylen = Endpoint->MaxPacketSize;
  431. }
  432. RtlCopyMemory((PUCHAR)urbWork->SystemAddressForMdl +
  433. urbWork->LogicalAddressList[i].PacketOffset,
  434. urbWork->LogicalAddressList[i].
  435. PacketMemoryDescriptor->VirtualAddress,
  436. copylen);
  437. }
  438. //
  439. // free the packet buffer if we have one
  440. //
  441. UHCD_FreeCommonBuffer(DeviceObject,
  442. urbWork->LogicalAddressList[i].
  443. PacketMemoryDescriptor);
  444. }
  445. (PUCHAR) currentVa += urbWork->LogicalAddressList[i].Length;
  446. }
  447. IoFreeMapRegisters(deviceExtension->AdapterObject,
  448. urbWork->MapRegisterBase,
  449. urbWork->NumberOfMapRegisters);
  450. if (urbWork->Flags & UHCD_MAPPED_LOCKED_PAGES) {
  451. PMDL mdl;
  452. mdl = urb->HcdUrbCommonTransfer.TransferBufferMDL;
  453. urbWork->Flags &= ~UHCD_MAPPED_LOCKED_PAGES;
  454. if (mdl->MdlFlags &
  455. (MDL_MAPPED_TO_SYSTEM_VA | MDL_SOURCE_IS_NONPAGED_POOL)) {
  456. // MmUnmapLockedPages(urbWork->SystemAddressForMdl, mdl);
  457. }
  458. }
  459. }
  460. UHCD_KdPrint((2, "'Transfer Completed\n"));
  461. UHCD_KdPrint((2, "'Status = %x\n", usbdStatus));
  462. UHCD_KdPrint((2, "'TransferBufferLength = %x\n",
  463. urb->HcdUrbCommonTransfer.TransferBufferLength));
  464. deviceExtension->Stats.BytesTransferred +=
  465. urb->HcdUrbCommonTransfer.TransferBufferLength;
  466. deviceExtension->IsoStats.IsoBytesTransferred +=
  467. urb->HcdUrbCommonTransfer.TransferBufferLength;
  468. //
  469. // retire this transfer, give the TransferCancel routine a chance to
  470. // mark it.
  471. //
  472. LOCK_ENDPOINT_ACTIVE_LIST(Endpoint, irql);
  473. Endpoint->ActiveTransfers[Slot] = NULL;
  474. // bump the current xfer count
  475. Endpoint->CurrentXferId++;
  476. UNLOCK_ENDPOINT_ACTIVE_LIST(Endpoint, irql);
  477. //
  478. // check if we have an error.
  479. //
  480. // if an error occurred on this transfer we need to
  481. // retire this transfer along with any other linked
  482. // transfers (urbs) associated with the same irp.
  483. //
  484. if (USBD_ERROR(usbdStatus)) {
  485. if (USBD_HALTED(usbdStatus)) {
  486. //
  487. // error code indicates a condition that should halt
  488. // the endpoint.
  489. //
  490. // check the endpoint state bit, if the endpoint
  491. // is marked for NO_HALT then clear the halt bit
  492. // and proceed to cancel this transfer.
  493. if (Endpoint->EndpointFlags & EPFLAG_NO_HALT) {
  494. //
  495. // clear the halt bit on the usbdStatus code
  496. //
  497. usbdStatus = USBD_STATUS(usbdStatus) | USBD_STATUS_ERROR;
  498. } else {
  499. //
  500. // mark the endpoint as halted, when the client
  501. // sends a reset we'll start processing with the
  502. // next queued transfer.
  503. //
  504. SET_EPFLAG(Endpoint, EPFLAG_HOST_HALTED);
  505. LOGENTRY(LOG_MISC, 'Hhlt', Endpoint, 0, 0);
  506. }
  507. }
  508. //
  509. // complete any additional urbs associated with this irp.
  510. //
  511. LOCK_ENDPOINT_PENDING_LIST(Endpoint, irql, 'lck1');
  512. //
  513. // mark active urbs so that they get retired
  514. //
  515. for (i=0; i<Endpoint->MaxRequests; i++) {
  516. urbtmp = Endpoint->ActiveTransfers[i];
  517. if (urbtmp != NULL &&
  518. HCD_AREA(urbtmp).HcdIrp == irp) {
  519. urbtmp->HcdUrbCommonTransfer.Status =
  520. UHCD_STATUS_PENDING_XXX;
  521. //
  522. // BUGBUG need a way to pass the error thru
  523. //
  524. TEST_TRAP();
  525. }
  526. }
  527. //
  528. // remove urbs associated with this Irp from the pending list
  529. //
  530. urbtmp = UHCD_RemoveQueuedUrbs(DeviceObject, urb, irp);
  531. UNLOCK_ENDPOINT_PENDING_LIST(Endpoint, irql, 'ulk1');
  532. //
  533. // request an interrupt to process any active urbs that
  534. // need canceling
  535. //
  536. UHCD_RequestInterrupt(DeviceObject, -2);
  537. while (urbtmp) {
  538. //
  539. // complete all linked urbs with status
  540. // USBD_CANCELED
  541. //
  542. TEST_TRAP();
  543. urbtmp->HcdUrbCommonTransfer.Status = USBD_STATUS_CANCELED;
  544. UHCD_ASSERT(irp == HCD_AREA(urbtmp).HcdIrp);
  545. UHCD_CompleteIrp(DeviceObject,
  546. irp,
  547. STATUS_SUCCESS,
  548. 0,
  549. urbtmp);
  550. urbtmp = urb->HcdUrbCommonTransfer.UrbLink;
  551. }
  552. //
  553. // complete the original request
  554. //
  555. urb->HcdUrbCommonTransfer.Status = usbdStatus;
  556. UHCD_ASSERT(irp != NULL);
  557. UHCD_CompleteIrp(DeviceObject,
  558. irp,
  559. STATUS_SUCCESS,
  560. 0,
  561. urb);
  562. if (!(Endpoint->EndpointFlags & EPFLAG_HOST_HALTED)) {
  563. //
  564. // if the endpoint is not halted then advance to
  565. // the next queued transfer.
  566. //
  567. UHCD_EndpointWorker(DeviceObject, Endpoint);
  568. }
  569. goto UHCD_CompleteTransferDPC_Done;
  570. }
  571. //
  572. // since the transfer completed at least one slot is free
  573. // so call EndpointWorker to activate another transfer.
  574. //
  575. UHCD_EndpointWorker(DeviceObject, Endpoint);
  576. //
  577. // Now we complete the irp for the urb transfer request
  578. // that just finished.
  579. //
  580. urb->HcdUrbCommonTransfer.Status = usbdStatus;
  581. UHCD_ASSERT(irp != NULL);
  582. UHCD_CompleteIrp(DeviceObject,
  583. irp,
  584. STATUS_SUCCESS,
  585. 0,
  586. urb);
  587. } // completed == TRUE
  588. UHCD_CompleteTransferDPC_Done:
  589. //UHCD_KdPrint((2, "'exit UHCD_CompleteTransferDPC\n"));
  590. return;
  591. }
  592. IO_ALLOCATION_ACTION
  593. UHCD_StartDmaTransfer(
  594. IN PDEVICE_OBJECT DeviceObject,
  595. IN PIRP Irp,
  596. IN PVOID MapRegisterBase,
  597. IN PVOID Context
  598. )
  599. /*++
  600. Routine Description:
  601. Begin a DMA transfer -- this is the adapter control routine called
  602. from IoAllocateAdapterChannel.
  603. Arguments:
  604. Return Value:
  605. see IoAllocateAdapterChannel
  606. --*/
  607. {
  608. PUHCD_ENDPOINT endpoint;
  609. PHCD_URB urb = Context;
  610. ULONG length, lengthMapped = 0;
  611. PHYSICAL_ADDRESS logicalAddress;
  612. PVOID currentVa;
  613. PDEVICE_EXTENSION deviceExtension;
  614. PHCD_EXTENSION urbWork;
  615. KIRQL irql;
  616. UHCD_KdPrint((2, "'enter UHCD_StartDmaTransfer\n"));
  617. UHCD_KdPrint((2, "'TransferBufferMDL = 0x%x Length = 0x%x\n",
  618. urb->HcdUrbCommonTransfer.TransferBufferMDL,
  619. urb->HcdUrbCommonTransfer.TransferBufferLength));
  620. deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  621. // allow dma operations now
  622. KeAcquireSpinLock(&deviceExtension->HcDmaSpin, &irql);
  623. UHCD_ASSERT(deviceExtension->HcDma >= 0);
  624. deviceExtension->HcDma--;
  625. LOGENTRY(LOG_MISC, '2DM-', 0, 0, 0);
  626. KeReleaseSpinLock(&deviceExtension->HcDmaSpin, irql);
  627. UHCD_ASSERT(urb->HcdUrbCommonTransfer.TransferBufferMDL != 0);
  628. urbWork = HCD_AREA(urb).HcdExtension;
  629. urbWork->MapRegisterBase = MapRegisterBase;
  630. endpoint = HCD_AREA(urb).HcdEndpoint;
  631. currentVa =
  632. MmGetMdlVirtualAddress(urb->HcdUrbCommonTransfer.TransferBufferMDL);
  633. length = urb->HcdUrbCommonTransfer.TransferBufferLength;
  634. //
  635. // keep calling IoMapTransfer until we get Logical Addresses for
  636. // the entire clinet buffer
  637. //
  638. UHCD_ASSERT(!urbWork->NumberOfLogicalAddresses);
  639. do {
  640. // make sure we don't overrun the work area.
  641. UHCD_ASSERT(urbWork->NumberOfLogicalAddresses <=
  642. (urb->HcdUrbCommonTransfer.
  643. TransferBufferLength / PAGE_SIZE + 1));
  644. // first map the transfer buffer
  645. logicalAddress =
  646. IoMapTransfer(deviceExtension->AdapterObject,
  647. urb->HcdUrbCommonTransfer.TransferBufferMDL,
  648. MapRegisterBase,
  649. currentVa,
  650. &length,
  651. DATA_DIRECTION_OUT(urb));
  652. // save the Logical Address and length
  653. UHCD_KdPrint((2, "'CurrentVa = 0x%x \n", currentVa));
  654. lengthMapped += length;
  655. (PUCHAR)currentVa += length;
  656. UHCD_KdPrint((2, "'IoMapTransfer length = 0x%x log address = 0x%x\n",
  657. length, logicalAddress.LowPart));
  658. //
  659. // update Urb work area with physical buffer addresses
  660. // that the HC can use.
  661. //
  662. urbWork->LogicalAddressList[urbWork->NumberOfLogicalAddresses].
  663. LogicalAddress = logicalAddress.LowPart;
  664. urbWork->LogicalAddressList[urbWork->NumberOfLogicalAddresses].
  665. Length = length;
  666. length = urb->HcdUrbCommonTransfer.TransferBufferLength -
  667. lengthMapped;
  668. urbWork->NumberOfLogicalAddresses++;
  669. } while (lengthMapped != urb->HcdUrbCommonTransfer.TransferBufferLength);
  670. //
  671. // Transfer is now ACTIVE.
  672. //
  673. urbWork->Flags |= UHCD_TRANSFER_MAPPED;
  674. UHCD_BeginTransfer(DeviceObject,
  675. endpoint,
  676. urb,
  677. urbWork->Slot);
  678. UHCD_KdPrint((2, "'exit UHCD_StartDmaTransfer\n"));
  679. return DeallocateObjectKeepRegisters;
  680. }
  681. VOID
  682. UHCD_InitializeDmaTransfer(
  683. IN PDEVICE_OBJECT DeviceObject,
  684. IN PHCD_URB Urb,
  685. IN PUHCD_ENDPOINT Endpoint,
  686. IN LONG Slot,
  687. IN UCHAR XferId
  688. )
  689. /*++
  690. Routine Description:
  691. Sets up a DMA transfer, this routine performs the mapping necessary
  692. for the HC to access the physical memory asssociated with the transfer.
  693. Arguments:
  694. Return Value:
  695. see IoAllocateAdapterChannel
  696. --*/
  697. {
  698. PDEVICE_EXTENSION deviceExtension;
  699. PVOID currentVa;
  700. NTSTATUS ntStatus;
  701. PHCD_EXTENSION urbWork;
  702. UHCD_KdPrint((2, "'enter UHCD_InitializeDmaTransfer\n"));
  703. deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  704. urbWork = HCD_AREA(Urb).HcdExtension;
  705. urbWork->Slot = (UCHAR) Slot;
  706. urbWork->XferId = XferId;
  707. if (Urb->HcdUrbCommonTransfer.TransferBufferLength) {
  708. currentVa =
  709. MmGetMdlVirtualAddress(
  710. Urb->HcdUrbCommonTransfer.TransferBufferMDL);
  711. // save the number of map registers in our work area
  712. // since the transferBufferLength may get changed by the
  713. // time the URB completes
  714. urbWork->NumberOfMapRegisters =
  715. ADDRESS_AND_SIZE_TO_SPAN_PAGES(
  716. currentVa,
  717. Urb->HcdUrbCommonTransfer.TransferBufferLength);
  718. UHCD_KdPrint((2, "'NumberOfMapRegistersRequired = 0x%x\n",
  719. urbWork->NumberOfMapRegisters));
  720. KeFlushIoBuffers(Urb->HcdUrbCommonTransfer.TransferBufferMDL,
  721. DATA_DIRECTION_IN(Urb),
  722. TRUE);
  723. // first we'll need to map the MDL for this transfer
  724. LOGENTRY(LOG_MISC, 'AChn', Endpoint,
  725. urbWork->NumberOfMapRegisters, Urb);
  726. ntStatus =
  727. IoAllocateAdapterChannel(deviceExtension->AdapterObject,
  728. DeviceObject,
  729. urbWork->NumberOfMapRegisters,
  730. UHCD_StartDmaTransfer,
  731. Urb);
  732. if (!NT_SUCCESS(ntStatus)) {
  733. //
  734. // if error, mark the transfer complete with error
  735. // now -- the TransferCompleteDPC routine will pick it up
  736. // and complete it.
  737. //
  738. LOGENTRY(LOG_MISC, 'ChnE', Endpoint,
  739. urbWork->NumberOfMapRegisters, ntStatus);
  740. TEST_TRAP();
  741. // BUGBUG do we need another error for this in usbdi.h?
  742. URB_HEADER(Urb).Status = USBD_STATUS_REQUEST_FAILED;
  743. //
  744. // Trigger an interrupt to process the endpoint
  745. //
  746. UHCD_RequestInterrupt(DeviceObject, -2);
  747. }
  748. } else {
  749. KIRQL irql;
  750. //
  751. // zero length transfer means no buffers to map.
  752. // begin the transfer now.
  753. //
  754. // allow dma operations now
  755. KeAcquireSpinLock(&deviceExtension->HcDmaSpin, &irql);
  756. UHCD_ASSERT(deviceExtension->HcDma >= 0);
  757. deviceExtension->HcDma--;
  758. LOGENTRY(LOG_MISC, '1DM-', 0, 0, 0);
  759. KeReleaseSpinLock(&deviceExtension->HcDmaSpin, irql);
  760. //
  761. // Transfer is now ACTIVE.
  762. //
  763. urbWork->Flags |= UHCD_TRANSFER_MAPPED;
  764. UHCD_BeginTransfer(DeviceObject,
  765. Endpoint,
  766. Urb,
  767. Slot);
  768. }
  769. UHCD_KdPrint((2, "'exit UHCD_InitializeDmaTransfer\n"));
  770. }
  771. VOID
  772. UHCD_TransferCancel(
  773. IN PDEVICE_OBJECT DeviceObject,
  774. IN PIRP Irp
  775. )
  776. /*++
  777. Routine Description:
  778. This function is called to cancel a transfer request that has been
  779. processed by the startio routine and is in the pending list for an
  780. endpoint.
  781. The pending transfer queue for the endpoint looks like this:
  782. ------------- ------------- ------------- ------------- -------------
  783. |Urb {irp 1}|->|Urb {irp 1}|->|Urb {irp 2}|->|Urb {irp 2}|->|Urb {irp x}|
  784. ------------- ------------- ------------- ------------- -------------
  785. | |
  786. remove --------------------------
  787. So if {irp 2} is canceled the we would have to remove multiple urbs
  788. from the chain. The cnacel routine does this, then completes the Irp
  789. with STATUS_CANCELED.
  790. Arguments:
  791. DeviceObject - pointer to a device object
  792. Irp - pointer to an I/O Request Packet
  793. Return Value:
  794. NT status code.
  795. --*/
  796. {
  797. PHCD_URB urb;
  798. PUHCD_ENDPOINT endpoint;
  799. ULONG i;
  800. PDEVICE_OBJECT deviceObject;
  801. KIRQL irql;
  802. UHCD_KdPrint((2, "'enter UHCD_TransferCancel\n"));
  803. {
  804. PUSBD_EXTENSION de;
  805. de = DeviceObject->DeviceExtension;
  806. if (de->TrueDeviceExtension == de) {
  807. deviceObject = DeviceObject;
  808. } else {
  809. de = de->TrueDeviceExtension;
  810. deviceObject = de->HcdDeviceObject;
  811. }
  812. }
  813. LOGENTRY(LOG_MISC, 'TCan', Irp, deviceObject, 0);
  814. UHCD_ASSERT(Irp->Cancel == TRUE);
  815. urb = (PHCD_URB) URB_FROM_IRP(Irp);
  816. endpoint = HCD_AREA(urb).HcdEndpoint;
  817. if (((PHCD_EXTENSION)HCD_AREA(urb).HcdExtension)->Flags
  818. & UHCD_TRANSFER_ACTIVE) {
  819. //
  820. // This request is on the active list, so we just request
  821. // that TransferComplete cancels it for us.
  822. //
  823. urb->HcdUrbCommonTransfer.Status = UHCD_STATUS_PENDING_XXX;
  824. IoReleaseCancelSpinLock(Irp->CancelIrql);
  825. return;
  826. }
  827. IoReleaseCancelSpinLock(Irp->CancelIrql);
  828. LOCK_ENDPOINT_PENDING_LIST(endpoint, irql, 'lck2');
  829. urb = UHCD_RemoveQueuedUrbs(deviceObject, urb, Irp);
  830. UNLOCK_ENDPOINT_PENDING_LIST(endpoint, irql, 'ulk2');
  831. //
  832. // complete the urbs we removed from the pending list.
  833. //
  834. while (urb) {
  835. urb->HcdUrbCommonTransfer.Status = USBD_STATUS_CANCELED;
  836. //
  837. // Note: request will not be completed by this routine if
  838. // the cancel flag is set.
  839. //
  840. #if DBG
  841. {
  842. PHCD_EXTENSION urbWork;
  843. urbWork = HCD_AREA(urb).HcdExtension;
  844. UHCD_ASSERT((urbWork->Flags & UHCD_TRANSFER_ACTIVE) == 0);
  845. }
  846. #endif
  847. LOGENTRY(LOG_MISC, 'pCan', Irp, urb, 0);
  848. UHCD_CompleteIrp(deviceObject,
  849. Irp,
  850. STATUS_CANCELLED,
  851. 0,
  852. urb);
  853. urb = urb->HcdUrbCommonTransfer.UrbLink;
  854. }
  855. //
  856. // NOTE: UHCD_CompleteIrp
  857. // will not complete the request if the cancel flag is set
  858. //
  859. if (PENDING_URB_COUNT(Irp) == 0) {
  860. //
  861. // All urbs for this request were in the pending
  862. // list so complete the irp now.
  863. //
  864. Irp->IoStatus.Status = STATUS_CANCELLED;
  865. Irp->IoStatus.Information = 0;
  866. USBD_CompleteRequest(Irp,
  867. IO_NO_INCREMENT);
  868. }
  869. UHCD_KdPrint((2, "'exit UHCD_TransferCancel\n"));
  870. }
  871. VOID
  872. UHCD_BeginTransfer(
  873. IN PDEVICE_OBJECT DeviceObject,
  874. IN PUHCD_ENDPOINT Endpoint,
  875. IN PHCD_URB Urb,
  876. IN ULONG Slot
  877. )
  878. /*++
  879. Routine Description:
  880. This routine actually starts the transfer, it sets up the TDs
  881. and puts them in the schedule.
  882. Arguments:
  883. Return Value:
  884. NT status code.
  885. --*/
  886. {
  887. PHCD_EXTENSION urbWork;
  888. USBD_STATUS usbdStatus;
  889. UHCD_KdPrint((2, "'enter UHCD_BeginTransfer\n"));
  890. ASSERT_ENDPOINT(Endpoint);
  891. UHCD_ASSERT(Endpoint == HCD_AREA(Urb).HcdEndpoint);
  892. UHCD_ASSERT(Endpoint->Type<=USB_ENDPOINT_TYPE_INTERRUPT);
  893. LOGENTRY(LOG_MISC, 'Bxfr', 0, Urb, 0);
  894. urbWork = HCD_AREA(Urb).HcdExtension;
  895. UHCD_ASSERT(urbWork->Flags & UHCD_TRANSFER_MAPPED);
  896. if (Urb->HcdUrbCommonTransfer.TransferBufferLength) {
  897. PMDL mdl;
  898. mdl = Urb->HcdUrbCommonTransfer.TransferBufferMDL;
  899. if (!(mdl->MdlFlags &
  900. (MDL_MAPPED_TO_SYSTEM_VA | MDL_SOURCE_IS_NONPAGED_POOL))) {
  901. urbWork->Flags |= UHCD_MAPPED_LOCKED_PAGES;
  902. }
  903. mdl->MdlFlags |= MDL_MAPPING_CAN_FAIL;
  904. urbWork->SystemAddressForMdl = MmGetSystemAddressForMdl(mdl);
  905. //
  906. // CIMEXCIMEX - handle failure case
  907. //
  908. mdl->MdlFlags &= ~MDL_MAPPING_CAN_FAIL;
  909. ASSERTMSG("UHCD: SystemAddressForMdl -- MDL mapping failed",
  910. urbWork->SystemAddressForMdl != NULL);
  911. } else {
  912. urbWork->SystemAddressForMdl = NULL;
  913. }
  914. // BUGBUG
  915. // verify that the request has not been canceled.
  916. if (Endpoint->Type != USB_ENDPOINT_TYPE_ISOCHRONOUS &&
  917. Endpoint->CurrentXferId != urbWork->XferId &&
  918. Endpoint->MaxRequests >1) {
  919. // set the defer flag
  920. LOGENTRY(LOG_MISC, 'sDFR', Endpoint->MaxRequests, urbWork,
  921. Endpoint->CurrentXferId);
  922. urbWork->Flags |= UHCD_TRANSFER_DEFER;
  923. }
  924. usbdStatus =
  925. (TransferDispatchTable[Endpoint->Type].InitializeTransfer)(
  926. DeviceObject,
  927. Endpoint,
  928. Urb);
  929. UHCD_KdPrint((2, "'New Transfer\n"));
  930. UHCD_KdPrint((2, "'TransferBufferLength = 0x%x\n",
  931. Urb->HcdUrbCommonTransfer.TransferBufferLength ));
  932. UHCD_KdPrint((2, "'TransferFlags = 0x%x\n",
  933. Urb->HcdUrbCommonTransfer.TransferFlags ));
  934. UHCD_KdPrint((2, "'MappedSystemAddress = 0x%x\n",
  935. urbWork->SystemAddressForMdl));
  936. //
  937. // start the transfer by linking the first TD to the
  938. // QUEUE head
  939. //
  940. if (USBD_ERROR(usbdStatus)) {
  941. //
  942. // An error occurred setting up the transfer set an error in the urb
  943. // so the next time the completion routine is called we'll complete
  944. // the request.
  945. //
  946. TEST_TRAP();
  947. URB_HEADER(Urb).Status = usbdStatus;
  948. } else {
  949. // BUGBUG
  950. // this won't work if we have mutiple requests
  951. // for a non-isoch endpoint
  952. //
  953. // this transfer id is now current
  954. //
  955. if (Endpoint->MaxRequests == 1) {
  956. // maxRequests == 1 is the old codepath
  957. UHCD_ASSERT(Endpoint->Type != USB_ENDPOINT_TYPE_ISOCHRONOUS);
  958. UHCD_ASSERT(Endpoint->CurrentXferId == urbWork->XferId);
  959. Endpoint->QueueHead->HW_VLink =
  960. Endpoint->TDList->TDs[0].PhysicalAddress;
  961. } else {
  962. //bugbug leave iso alone for now
  963. if (Endpoint->Type != USB_ENDPOINT_TYPE_ISOCHRONOUS) {
  964. // if this transfer is now current we need to muck with
  965. // the queue head, the TDs are already set up
  966. if (Endpoint->CurrentXferId == urbWork->XferId) {
  967. UHCD_ASSERT(!(urbWork->Flags & UHCD_TRANSFER_DEFER));
  968. // update the endpoints TDList
  969. // slot id corresponds to TD list
  970. LOGENTRY(LOG_MISC, 'mkCU', Endpoint->CurrentXferId, urbWork->Slot,
  971. Urb);
  972. Endpoint->TDList =
  973. Endpoint->SlotTDList[urbWork->Slot];
  974. // fix up the data toggle now if we need to
  975. if (!(urbWork->Flags & UHCD_TOGGLE_READY)) {
  976. UHCD_FixupDataToggle(
  977. DeviceObject,
  978. Endpoint,
  979. Urb);
  980. }
  981. Endpoint->QueueHead->HW_VLink =
  982. Endpoint->TDList->TDs[0].PhysicalAddress;
  983. } else {
  984. // we cant start this transfer becuse it is not
  985. // current yet -- just leave it in the slot for now
  986. LOGENTRY(LOG_MISC, 'xRDY', Endpoint->CurrentXferId, urbWork->Slot,
  987. Endpoint->SlotTDList[urbWork->Slot]);
  988. UHCD_ASSERT(urbWork->Flags & UHCD_TRANSFER_INITIALIZED);
  989. }
  990. }
  991. }
  992. }
  993. //
  994. // Completion routine will now process this transfer.
  995. //
  996. urbWork->Flags |= UHCD_TRANSFER_ACTIVE;
  997. UHCD_KdPrint((2, "'exit UHCD_BeginTransfer\n"));
  998. }
  999. PHCD_URB
  1000. UHCD_RemoveQueuedUrbs(
  1001. IN PDEVICE_OBJECT DeviceObject,
  1002. IN PHCD_URB Urb,
  1003. IN PIRP Irp
  1004. )
  1005. /*++
  1006. Routine Description:
  1007. Removes Urbs associated with a given irp from the pending queue.
  1008. NOTE: The endpoint must be held before calling this routine.
  1009. Arguments:
  1010. Return Value:
  1011. NT status code.
  1012. --*/
  1013. {
  1014. PHCD_URB urb, prevUrb, nextUrb, parentUrb = NULL;
  1015. PLIST_ENTRY listEntry, nextUrbLink, prevUrbLink;
  1016. PUHCD_ENDPOINT endpoint;
  1017. UHCD_KdPrint((2, "'enter UHCD_RemoveQueuedUrbs\n"));
  1018. endpoint = HCD_AREA(Urb).HcdEndpoint;
  1019. //
  1020. // we need to walk through the list of Urbs
  1021. // queued for this endpoint, any urbs associated
  1022. // with this irp must be removed.
  1023. //
  1024. ASSERT_ENDPOINT(endpoint);
  1025. listEntry = &endpoint->PendingTransferList;
  1026. if (!IsListEmpty(listEntry)) {
  1027. listEntry = endpoint->PendingTransferList.Flink;
  1028. }
  1029. while (listEntry != &endpoint->PendingTransferList) {
  1030. urb = (PHCD_URB) CONTAINING_RECORD(listEntry,
  1031. struct _URB_HCD_COMMON_TRANSFER,
  1032. hca.HcdListEntry);
  1033. if (HCD_AREA(urb).HcdIrp == Irp) {
  1034. parentUrb = urb;
  1035. //
  1036. // found the first Urb associated with
  1037. // this Irp
  1038. //
  1039. prevUrbLink = HCD_AREA(urb).HcdListEntry.Blink;
  1040. //
  1041. // Find the last Urb associated with this irp
  1042. // so we can remove the whole chain
  1043. //
  1044. while (urb->HcdUrbCommonTransfer.UrbLink != NULL) {
  1045. // yes, we are finished unlinking
  1046. urb = urb->HcdUrbCommonTransfer.UrbLink;
  1047. }
  1048. nextUrbLink = HCD_AREA(urb).HcdListEntry.Flink;
  1049. //
  1050. // we have found the group of URBs associated with this Irp
  1051. // it is now time to remove them.
  1052. //
  1053. if (nextUrbLink != &endpoint->PendingTransferList) {
  1054. // this is not the last one
  1055. nextUrb = (PHCD_URB) CONTAINING_RECORD(
  1056. nextUrbLink,
  1057. struct _URB_HCD_COMMON_TRANSFER,
  1058. hca.HcdListEntry);
  1059. UHCD_ASSERT(HCD_AREA(nextUrb).HcdIrp != Irp);
  1060. HCD_AREA(nextUrb).HcdListEntry.Blink =
  1061. prevUrbLink;
  1062. } else {
  1063. // this is the last one
  1064. endpoint->PendingTransferList.Blink =
  1065. prevUrbLink;
  1066. }
  1067. if (prevUrbLink != &endpoint->PendingTransferList) {
  1068. prevUrb = (PHCD_URB) CONTAINING_RECORD(
  1069. prevUrbLink,
  1070. struct _URB_HCD_COMMON_TRANSFER,
  1071. hca.HcdListEntry);
  1072. UHCD_ASSERT(HCD_AREA(prevUrb).HcdIrp != Irp);
  1073. HCD_AREA(prevUrb).HcdListEntry.Flink =
  1074. nextUrbLink;
  1075. } else {
  1076. endpoint->PendingTransferList.Flink =
  1077. nextUrbLink;
  1078. }
  1079. break;
  1080. }
  1081. listEntry = HCD_AREA(urb).HcdListEntry.Flink;
  1082. }
  1083. UHCD_KdPrint((2, "'exit UHCD_RemoveQueuedUrbs 0x%x\n", parentUrb));
  1084. return parentUrb;
  1085. }
  1086. VOID
  1087. UHCD_EndpointWorker(
  1088. IN PDEVICE_OBJECT DeviceObject,
  1089. IN PUHCD_ENDPOINT Endpoint
  1090. )
  1091. /*++
  1092. Routine Description:
  1093. Main worker function for an endpoint.
  1094. Called at DPC level - either call the DMA routine or
  1095. the non DMA version as appropriate.
  1096. Arguments:
  1097. Return Value:
  1098. None.
  1099. --*/
  1100. {
  1101. if (Endpoint->EndpointFlags & EPFLAG_DBL_BUFFER) {
  1102. LOGENTRY(LOG_MISC, 'nDMA', 0, Endpoint, 0);
  1103. UHCD_EndpointNoDMAWorker(DeviceObject,
  1104. Endpoint);
  1105. } else {
  1106. LOGENTRY(LOG_MISC, 'yDMA', 0, Endpoint, 0);
  1107. UHCD_EndpointDMAWorker(DeviceObject,
  1108. Endpoint);
  1109. }
  1110. }
  1111. VOID
  1112. UHCD_EndpointDMAWorker(
  1113. IN PDEVICE_OBJECT DeviceObject,
  1114. IN PUHCD_ENDPOINT Endpoint
  1115. )
  1116. /*++
  1117. Routine Description:
  1118. Main worker function for an endpoint.
  1119. Called at DPC level -- this routine activates any transfers for an
  1120. endpoint if possible by removing them from the pending queue and
  1121. initializing them.
  1122. Since EndpointWorker calls IoMapTransfer it cannot be reentered so
  1123. we set a flag to allow it to only run on one processor at a time.
  1124. Arguments:
  1125. Return Value:
  1126. None.
  1127. --*/
  1128. {
  1129. PLIST_ENTRY listEntry;
  1130. PHCD_URB urb;
  1131. LONG slot, i;
  1132. KIRQL irql;
  1133. PHCD_EXTENSION urbWork;
  1134. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  1135. UHCD_KdPrint((2, "'enter UHCD_EndpointWorker\n"));
  1136. // see if this endpoint is Halted, if so
  1137. // there is no need to check the DMA lock
  1138. if (Endpoint->EndpointFlags & EPFLAG_HOST_HALTED) {
  1139. //
  1140. // if the endpoint is halted then perform no
  1141. // processing.
  1142. //
  1143. #ifdef MAX_DEBUG
  1144. TEST_TRAP();
  1145. #endif
  1146. // allow DMA processing
  1147. LOGENTRY(LOG_MISC, 'Hhlt', 0, Endpoint, 0);
  1148. goto UHCD_EndpointWorker_Done;
  1149. }
  1150. UHCD_EndpointWorker_NextTransfer:
  1151. // attempt to take the DMA lock
  1152. KeAcquireSpinLock(&deviceExtension->HcDmaSpin, &irql);
  1153. deviceExtension->HcDma++;
  1154. LOGENTRY(LOG_MISC, '3DM+', 0, 0, 0);
  1155. if (deviceExtension->HcDma) {
  1156. // dma lock is already held, mark the
  1157. // endpoint so we process it later
  1158. SET_EPFLAG(Endpoint, EPFLAG_HAVE_WORK);
  1159. UHCD_ASSERT(deviceExtension->HcDma >= 0);
  1160. deviceExtension->HcDma--;
  1161. LOGENTRY(LOG_MISC, '4DM-', 0, 0, 0);
  1162. KeReleaseSpinLock(&deviceExtension->HcDmaSpin, irql);
  1163. LOGENTRY(LOG_MISC, 'Dbz1', 0, Endpoint, 0);
  1164. // busy, bail
  1165. goto UHCD_EndpointWorker_Done;
  1166. }
  1167. LOGENTRY(LOG_MISC, 'CHAN', 0, 0, 0);
  1168. // got the lock, process the transfer
  1169. CLR_EPFLAG(Endpoint, EPFLAG_HAVE_WORK);
  1170. KeReleaseSpinLock(&deviceExtension->HcDmaSpin, irql);
  1171. LOCK_ENDPOINT_ACTIVE_LIST(Endpoint, irql);
  1172. LOGENTRY(LOG_MISC, 'lka1', 0, Endpoint, 0);
  1173. //
  1174. // find an open slot
  1175. //
  1176. slot = -1;
  1177. for (i=0; i<Endpoint->MaxRequests; i++) {
  1178. if (Endpoint->ActiveTransfers[i] == NULL) {
  1179. //
  1180. // dequeue the next urb we want to start
  1181. //
  1182. LOCK_ENDPOINT_PENDING_LIST(Endpoint, irql, 'lck3');
  1183. if (IsListEmpty(&Endpoint->PendingTransferList)) {
  1184. //
  1185. // pending list is empty, reset the abort pending
  1186. // tranfers bit now -- this will allow a reset.
  1187. //
  1188. CLR_EPFLAG(Endpoint,
  1189. EPFLAG_ABORT_PENDING_TRANSFERS);
  1190. } else {
  1191. KIRQL cancelIrql;
  1192. PIRP pIrp;
  1193. IoAcquireCancelSpinLock(&cancelIrql);
  1194. pIrp
  1195. = HCD_AREA((PHCD_URB)
  1196. CONTAINING_RECORD(Endpoint->PendingTransferList.Flink,
  1197. struct _URB_HCD_COMMON_TRANSFER,
  1198. hca.HcdListEntry)).HcdIrp;
  1199. if (pIrp->Cancel) {
  1200. //
  1201. // Uh-oh, this IRP is being cancelled; we'll let the
  1202. // cancel routine finish the job. Leave it on the list.
  1203. //
  1204. IoReleaseCancelSpinLock(cancelIrql);
  1205. UNLOCK_ENDPOINT_PENDING_LIST(Endpoint, irql, 'ulk7');
  1206. continue;
  1207. }
  1208. listEntry = RemoveHeadList(&Endpoint->PendingTransferList);
  1209. IoReleaseCancelSpinLock(cancelIrql);
  1210. slot = i;
  1211. urb = (PHCD_URB) CONTAINING_RECORD(
  1212. listEntry,
  1213. struct _URB_HCD_COMMON_TRANSFER,
  1214. hca.HcdListEntry);
  1215. LOGENTRY(LOG_MISC, 'dqXF', urb, slot, 0);
  1216. URB_HEADER(urb).Status = UHCD_STATUS_PENDING_CURRENT;
  1217. }
  1218. UNLOCK_ENDPOINT_PENDING_LIST(Endpoint, irql, 'ulk3');
  1219. //
  1220. // found a transfer, start it
  1221. //
  1222. break;
  1223. }
  1224. }
  1225. if (slot != -1) {
  1226. //
  1227. // we have a transfer, start it.
  1228. //
  1229. UHCD_KdPrint((2, "'Starting Next Queued Transfer\n"));
  1230. //
  1231. // AbortPendingTransfers - indicates that all transfers in the
  1232. // pending queue should be canceled.
  1233. //
  1234. // If the abort flag is set then we just complete the queued
  1235. // transfer here.
  1236. //
  1237. if (Endpoint->EndpointFlags & EPFLAG_ABORT_PENDING_TRANSFERS) {
  1238. LOGENTRY(LOG_MISC, 'abrP', Endpoint, 0, urb);
  1239. // release the DMA lock now
  1240. KeAcquireSpinLock(&deviceExtension->HcDmaSpin, &irql);
  1241. UHCD_ASSERT(deviceExtension->HcDma >= 0);
  1242. deviceExtension->HcDma--;
  1243. LOGENTRY(LOG_MISC, '5DM-', 0, 0, 0);
  1244. KeReleaseSpinLock(&deviceExtension->HcDmaSpin, irql);
  1245. //
  1246. // release exclusive access.
  1247. //
  1248. UNLOCK_ENDPOINT_ACTIVE_LIST(Endpoint, irql);
  1249. LOGENTRY(LOG_MISC, 'uka1', 0, Endpoint, 0);
  1250. URB_HEADER(urb).Status = USBD_STATUS_CANCELED;
  1251. UHCD_CompleteIrp(DeviceObject,
  1252. HCD_AREA(urb).HcdIrp,
  1253. STATUS_CANCELLED,
  1254. 0,
  1255. urb);
  1256. } else {
  1257. UCHAR xferId;
  1258. //
  1259. // Urb is now in the active list.
  1260. //
  1261. urbWork = HCD_AREA(urb).HcdExtension;
  1262. //
  1263. // initialize worker flags
  1264. //
  1265. // give the transfer a sequence number
  1266. xferId = Endpoint->NextXferId;
  1267. Endpoint->NextXferId++;
  1268. Endpoint->ActiveTransfers[slot] = urb;
  1269. //
  1270. // release exclusive access.
  1271. //
  1272. UNLOCK_ENDPOINT_ACTIVE_LIST(Endpoint, irql);
  1273. LOGENTRY(LOG_MISC, 'uka2', 0, Endpoint, 0);
  1274. UHCD_InitializeDmaTransfer(DeviceObject, urb, Endpoint, slot, xferId);
  1275. }
  1276. // next transfer will attempt to grab the DMA lock again
  1277. // if the lock was released by InitializeDMAtransfer
  1278. // then we will be able to handle another transfer
  1279. goto UHCD_EndpointWorker_NextTransfer;
  1280. } else {
  1281. //
  1282. // no free slots, release the DMA lock
  1283. //
  1284. KeAcquireSpinLock(&deviceExtension->HcDmaSpin, &irql);
  1285. UHCD_ASSERT(deviceExtension->HcDma >= 0);
  1286. deviceExtension->HcDma--;
  1287. LOGENTRY(LOG_MISC, '6DM-', 0, 0, 0);
  1288. KeReleaseSpinLock(&deviceExtension->HcDmaSpin, irql);
  1289. }
  1290. UNLOCK_ENDPOINT_ACTIVE_LIST(Endpoint, irql);
  1291. LOGENTRY(LOG_MISC, 'uka3', 0, Endpoint, 0);
  1292. UHCD_EndpointWorker_Done:
  1293. UHCD_KdPrint((2, "'exit UHCD_EndpointWorker\n"));
  1294. return;
  1295. }
  1296. VOID
  1297. UHCD_EndpointIdle(
  1298. IN PDEVICE_OBJECT DeviceObject,
  1299. IN PUHCD_ENDPOINT Endpoint
  1300. )
  1301. /*++
  1302. Routine Description:
  1303. See if this endpoint has been idle for a while.
  1304. if so pull it from the schedule
  1305. Arguments:
  1306. Return Value:
  1307. None.
  1308. --*/
  1309. {
  1310. LARGE_INTEGER timeNow;
  1311. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  1312. KIRQL irql;
  1313. #if DBG
  1314. ULONG slot;
  1315. #endif
  1316. if (Endpoint->EndpointFlags & EPFLAG_IDLE) {
  1317. // already idle
  1318. #if DBG
  1319. for (slot=0; slot<Endpoint->MaxRequests; slot++) {
  1320. UHCD_ASSERT(Endpoint->ActiveTransfers[slot] == NULL);
  1321. }
  1322. #endif
  1323. return;
  1324. }
  1325. if (Endpoint->Type != USB_ENDPOINT_TYPE_BULK) {
  1326. // we only idle bulk endpoints
  1327. return;
  1328. }
  1329. KeQuerySystemTime(&timeNow);
  1330. if (Endpoint->IdleTime == 0) {
  1331. LOGENTRY(LOG_MISC, 'Bid0', Endpoint->IdleTime, 0, Endpoint);
  1332. KeQuerySystemTime(&Endpoint->LastIdleTime);
  1333. Endpoint->IdleTime = 1;
  1334. }
  1335. LOGENTRY(LOG_MISC, 'Bid1', Endpoint->IdleTime, 0, Endpoint);
  1336. Endpoint->IdleTime +=
  1337. (LONG) (timeNow.QuadPart -
  1338. Endpoint->LastIdleTime.QuadPart);
  1339. Endpoint->LastIdleTime = timeNow;
  1340. LOGENTRY(LOG_MISC, 'Bid2', Endpoint->IdleTime, 0, Endpoint);
  1341. if (// 10 seconds in 100ns units
  1342. Endpoint->IdleTime > 100000000) {
  1343. KeAcquireSpinLock(&deviceExtension->HcScheduleSpin, &irql);
  1344. SET_EPFLAG(Endpoint, EPFLAG_IDLE);
  1345. LOGENTRY(LOG_MISC, 'Bid3', Endpoint->IdleTime, 0, Endpoint);
  1346. // pull the ep from the schedule
  1347. UHCD_KdPrint((0, "'Bulk Enpoint (%x) going idle\n", Endpoint));
  1348. // TEST_TRAP();
  1349. #if DBG
  1350. for (slot=0; slot<Endpoint->MaxRequests; slot++) {
  1351. UHCD_ASSERT(Endpoint->ActiveTransfers[slot] == NULL);
  1352. }
  1353. UHCD_ASSERT(IsListEmpty(&Endpoint->PendingTransferList));
  1354. #endif
  1355. UHCD_RemoveQueueHeadFromSchedule(DeviceObject,
  1356. Endpoint,
  1357. Endpoint->QueueHead,
  1358. FALSE);
  1359. KeReleaseSpinLock(&deviceExtension->HcScheduleSpin, irql);
  1360. }
  1361. }
  1362. VOID
  1363. UHCD_EndpointWakeup(
  1364. IN PDEVICE_OBJECT DeviceObject,
  1365. IN PUHCD_ENDPOINT Endpoint
  1366. )
  1367. /*++
  1368. Routine Description:
  1369. Wakeup an idle endpoint
  1370. Arguments:
  1371. Return Value:
  1372. None.
  1373. --*/
  1374. {
  1375. PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
  1376. KIRQL irql;
  1377. Endpoint->IdleTime = 0;
  1378. KeAcquireSpinLock(&deviceExtension->HcScheduleSpin, &irql);
  1379. if (Endpoint->EndpointFlags & EPFLAG_IDLE) {
  1380. UHCD_ASSERT(Endpoint->Type == USB_ENDPOINT_TYPE_BULK);
  1381. LOGENTRY(LOG_MISC, 'Ewak', Endpoint, 0, Endpoint->EndpointFlags);
  1382. UHCD_KdPrint((0, "'Bulk Enpoint (%x) wakeup\n", Endpoint));
  1383. // TEST_TRAP();
  1384. UHCD_InsertQueueHeadInSchedule(DeviceObject,
  1385. Endpoint,
  1386. Endpoint->QueueHead,
  1387. 0); // no offset
  1388. CLR_EPFLAG(Endpoint, EPFLAG_IDLE);
  1389. }
  1390. KeReleaseSpinLock(&deviceExtension->HcScheduleSpin, irql);
  1391. }
  1392. #if DBG
  1393. VOID
  1394. UHCD_LockAccess(
  1395. IN PULONG c
  1396. )
  1397. /*++
  1398. Routine Description:
  1399. Arguments:
  1400. Return Value:
  1401. None.
  1402. --*/
  1403. {
  1404. UHCD_ASSERT(*c == 0);
  1405. (*c)++;
  1406. }
  1407. VOID
  1408. UHCD_UnLockAccess(
  1409. IN PULONG c
  1410. )
  1411. /*++
  1412. Routine Description:
  1413. Arguments:
  1414. Return Value:
  1415. None.
  1416. --*/
  1417. {
  1418. UHCD_ASSERT(*c>0);
  1419. (*c)--;
  1420. }
  1421. #endif