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.

2224 lines
67 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. ohcixfer.c
  5. Abstract:
  6. The module manages transactions on the USB.
  7. Environment:
  8. kernel mode only
  9. Notes:
  10. Revision History:
  11. 03-07-96 : created jfuller
  12. 03-20-96 : rewritten kenray
  13. --*/
  14. #include "openhci.h"
  15. #define abs(x) ( (0 < (x)) ? (x) : (0 - (x)))
  16. IO_ALLOCATION_ACTION
  17. OpenHCI_QueueGeneralRequest(PDEVICE_OBJECT,
  18. PIRP,
  19. PVOID,
  20. PVOID);
  21. VOID
  22. OpenHCI_LockAndCheckEndpoint(
  23. PHCD_ENDPOINT Endpoint,
  24. PBOOLEAN QueuedTransfers,
  25. PBOOLEAN ActiveTransfers,
  26. PKIRQL OldIrql
  27. )
  28. /*++
  29. Routine Description:
  30. Arguments:
  31. Endpoint - pointer to the endpoint for which to perform action
  32. Return Value:
  33. None.
  34. --*/
  35. {
  36. ASSERT_ENDPOINT(Endpoint);
  37. LOGENTRY(G, 'lkEP', Endpoint, 0, 0);
  38. // see if there are any pending transfers
  39. KeAcquireSpinLock(&Endpoint->QueueLock, OldIrql);
  40. if (QueuedTransfers) {
  41. *QueuedTransfers = !IsListEmpty(&Endpoint->RequestQueue);
  42. }
  43. // EndpointStatus is initialized to 0 when the endpoint is opened,
  44. // incremented every time a request is queued on the hardware, and
  45. // decremented every time a request is completed off of the hardware.
  46. // If it is greater than 0 then a request is currently on the
  47. // hardware.
  48. //
  49. if (ActiveTransfers) {
  50. *ActiveTransfers = Endpoint->EndpointStatus > 0;
  51. }
  52. LOGENTRY(G, 'lkEP', Endpoint,
  53. QueuedTransfers ? *QueuedTransfers : 0,
  54. ActiveTransfers ? *ActiveTransfers : 0);
  55. }
  56. VOID
  57. OpenHCI_UnlockEndpoint(
  58. PHCD_ENDPOINT Endpoint,
  59. KIRQL Irql
  60. )
  61. /*++
  62. Routine Description:
  63. Arguments:
  64. Endpoint - pointer to the endpoint for which to perform action
  65. Return Value:
  66. None.
  67. --*/
  68. {
  69. ASSERT_ENDPOINT(Endpoint);
  70. // see if there are any pending transfers
  71. KeReleaseSpinLock(&Endpoint->QueueLock, Irql);
  72. LOGENTRY(G, 'ukEP', Endpoint, 0, 0);
  73. }
  74. VOID
  75. OpenHCI_ProcessEndpoint(
  76. PHCD_DEVICE_DATA DeviceData,
  77. PHCD_ENDPOINT Endpoint
  78. )
  79. /*++
  80. Routine Description:
  81. Either calls ep worker or puts the ep on a list
  82. to be processed later
  83. Arguments:
  84. Endpoint - pointer to the endpoint for which to perform action
  85. Return Value:
  86. None.
  87. --*/
  88. {
  89. KIRQL irql;
  90. KeAcquireSpinLock(&DeviceData->HcDmaSpin, &irql);
  91. DeviceData->HcDma++;
  92. if (DeviceData->HcDma) {
  93. // ep worker is busy
  94. LOGENTRY(G, 'wkBS', Endpoint, 0, 0);
  95. // put the ep in the list only once
  96. if (!(Endpoint->EpFlags & EP_IN_ACTIVE_LIST)) {
  97. InsertTailList(&DeviceData->ActiveEndpointList,
  98. &Endpoint->EndpointListEntry);
  99. SET_EPFLAG(Endpoint, EP_IN_ACTIVE_LIST);
  100. }
  101. KeReleaseSpinLock(&DeviceData->HcDmaSpin, irql);
  102. } else {
  103. LOGENTRY(G, 'wkNB', Endpoint, 0, 0);
  104. KeReleaseSpinLock(&DeviceData->HcDmaSpin, irql);
  105. OpenHCI_EndpointWorker(Endpoint);
  106. }
  107. KeAcquireSpinLock(&DeviceData->HcDmaSpin, &irql);
  108. DeviceData->HcDma--;
  109. KeReleaseSpinLock(&DeviceData->HcDmaSpin, irql);
  110. }
  111. VOID
  112. OpenHCI_EndpointWorker(
  113. PHCD_ENDPOINT Endpoint
  114. )
  115. /*++
  116. Routine Description:
  117. formerly "StartEndpoint"
  118. Worker function that drives an endpoint...
  119. Dequeues a URB from an endpoint's queue and programs the DMA transfer
  120. on the controller thru Qgeneral request.
  121. Arguments:
  122. Endpoint - pointer to the endpoint for which to perform action
  123. Return Value:
  124. None.
  125. --*/
  126. {
  127. PHCD_DEVICE_DATA DeviceData;
  128. PHCD_URB urb;
  129. KIRQL oldIrql;
  130. NTSTATUS ntStatus;
  131. ULONG numberOfMapEntries;
  132. PLIST_ENTRY entry;
  133. LONG endpointStatus = 0;
  134. struct _URB_HCD_COMMON_TRANSFER *transfer;
  135. PIRP irp;
  136. BOOLEAN queuedTransfers;
  137. DeviceData = Endpoint->DeviceData;
  138. OpenHCI_KdPrintDD(DeviceData, OHCI_DBG_TD_TRACE, ("'enter EW\n"));
  139. LOGENTRY(G, 'EPwk', Endpoint, Endpoint->EndpointStatus, Endpoint->MaxTransfer);
  140. LOGIRQL();
  141. if (Endpoint->MaxRequest == Endpoint->EndpointStatus) {
  142. // if > 0 then we have programmed all the requests possible
  143. // to the hardare
  144. LOGENTRY(G, 'EPbs', Endpoint, Endpoint->EndpointStatus, 0);
  145. OpenHCI_KdPrintDD(DeviceData,
  146. OHCI_DBG_TD_NOISE, ("' Endpoint busy!\n"));
  147. } else {
  148. //
  149. // endpoint not busy, see if we can queue a tranfer to the controller
  150. //
  151. do {
  152. OpenHCI_LockAndCheckEndpoint(Endpoint,
  153. &queuedTransfers,
  154. NULL,
  155. &oldIrql);
  156. if (!queuedTransfers) {
  157. LOGENTRY(G, 'EQmt', Endpoint, 0, 0);
  158. OpenHCI_KdPrintDD(DeviceData,
  159. OHCI_DBG_TD_NOISE, ("'queue empty\n"));
  160. OpenHCI_UnlockEndpoint(Endpoint, oldIrql);
  161. // nothing to do
  162. break;
  163. }
  164. entry = RemoveHeadList(&Endpoint->RequestQueue);
  165. urb = CONTAINING_RECORD(entry,
  166. HCD_URB,
  167. HcdUrbCommonTransfer.hca.HcdListEntry);
  168. transfer = &urb->HcdUrbCommonTransfer;
  169. transfer->hca.HcdListEntry.Flink = NULL;
  170. transfer->hca.HcdListEntry.Blink = NULL;
  171. // one more request to the hardware
  172. endpointStatus = InterlockedIncrement(&Endpoint->EndpointStatus);
  173. OpenHCI_UnlockEndpoint(Endpoint, oldIrql);
  174. LOGENTRY(G, 'dQTR', transfer, endpointStatus, Endpoint);
  175. LOGIRQL();
  176. irp = transfer->hca.HcdIrp;
  177. //
  178. // check for a canceled irp, this handles the case where
  179. // the irp is canceled after being removed from the endpoint
  180. // queue but before we get a chance to program it to the
  181. // hardawre
  182. //
  183. IoAcquireCancelSpinLock(&oldIrql);
  184. if (irp->Cancel)
  185. {
  186. //
  187. // If we got the URB here, then it was poped off the request
  188. // list. Therefore it must have been cancelled right after it
  189. // was poped.
  190. // (If it was canceled before than then the cancel routine
  191. // would have removed it from the queue.)
  192. //
  193. // Therefore, the cancel routine did not complete the IRP so
  194. // we must do it now.
  195. //
  196. OpenHCI_KdPrintDD(DeviceData, OHCI_DBG_TD_TRACE,
  197. ("' Removing cancelled URB %x\n", urb));
  198. LOGENTRY(G, 'Ican', irp, transfer, Endpoint);
  199. ASSERT(urb->UrbHeader.Status == HCD_PENDING_STATUS_QUEUED);
  200. transfer->Status = USBD_STATUS_CANCELED;
  201. //
  202. // complete the irp
  203. //
  204. IoSetCancelRoutine(transfer->hca.HcdIrp, NULL);
  205. IoReleaseCancelSpinLock(oldIrql);
  206. if (0 == transfer->UrbLink) {
  207. OpenHCI_CompleteIrp(Endpoint->DeviceData->DeviceObject,
  208. irp,
  209. STATUS_CANCELLED);
  210. }
  211. endpointStatus =
  212. InterlockedDecrement(&Endpoint->EndpointStatus);
  213. LOGENTRY(G, 'dcS2', 0, Endpoint, endpointStatus);
  214. OHCI_ASSERT(endpointStatus >= 0);
  215. #if DBG
  216. if (Endpoint->MaxRequest == 1) {
  217. // in limit xfer mode we should always be 0 here.
  218. OHCI_ASSERT(endpointStatus == 0);
  219. }
  220. #endif
  221. continue;
  222. }
  223. else
  224. {
  225. urb->UrbHeader.Status = HCD_PENDING_STATUS_SUBMITTING;
  226. // The request needs to pass through IoAllocateAdapterChannel()
  227. // before it gets to OpenHCI_QueueGeneralRequest(). Until the
  228. // request makes it through to OpenHCI_QueueGeneralRequest(), we
  229. // can't cancel the request so clear the cancel routine.
  230. //
  231. IoSetCancelRoutine(transfer->hca.HcdIrp, NULL);
  232. IoReleaseCancelSpinLock(oldIrql);
  233. }
  234. //
  235. // map the transfer
  236. //
  237. LOGENTRY(G, 'MAPt', transfer, transfer->TransferBufferLength, 0);
  238. if (transfer->TransferBufferLength != 0) {
  239. numberOfMapEntries = ADDRESS_AND_SIZE_TO_SPAN_PAGES(
  240. MmGetMdlVirtualAddress(transfer->TransferBufferMDL),
  241. transfer->TransferBufferLength);
  242. } else {
  243. numberOfMapEntries = 0; // no data ==> no map registers, no
  244. // MDL
  245. ASSERT(NULL == transfer->TransferBufferMDL);
  246. }
  247. OpenHCI_KdPrintDD(DeviceData, OHCI_DBG_TD_TRACE,
  248. ("'EW: submitting URB %08x\n", urb));
  249. LOGENTRY(G, 'MAPr', urb, numberOfMapEntries, 0);
  250. KeRaiseIrql(DISPATCH_LEVEL, &oldIrql);
  251. ntStatus = IoAllocateAdapterChannel(DeviceData->AdapterObject,
  252. DeviceData->DeviceObject,
  253. numberOfMapEntries,
  254. OpenHCI_QueueGeneralRequest,
  255. urb);
  256. KeLowerIrql(oldIrql);
  257. LOGENTRY(G, 'ALch', urb, ntStatus, oldIrql);
  258. if (!NT_SUCCESS(ntStatus)) {
  259. // FUTURE ISSUE:
  260. // Figure out what to do when IoAllocateAdapterChannel fails.
  261. // This should only happen when NumberOfMapRegisters is too big,
  262. // which should only happen when "map registers" actually do
  263. // anything. This should only ever be an issue on >4GB PAE
  264. // machines.
  265. //
  266. // To really address this possible issue, when starting a
  267. // request compare the number of map registers needed for the
  268. // request against the number of map registers returned by
  269. // IoGetDmaAdapter. If more than the available number are
  270. // necessary then the request needs to be split up somehow.
  271. //
  272. OpenHCI_KdPrintDD(DeviceData, OHCI_DBG_TD_ERROR,
  273. ("'EW: IoAllocateAdapterChannel: %d\n",
  274. ntStatus));
  275. TRAP(); // Failed IoAdapter Channel
  276. }
  277. } while (Endpoint->MaxRequest > endpointStatus);
  278. //
  279. // EndpointStatus is now zero based, not -1 based so the rest of the
  280. // comment below is not quite correct...
  281. //
  282. // We allow for two outstanding transfers on the endpoint at a time.
  283. // These are accounted by EndpointStatus = -1 and = 0. When
  284. // we have two transfers actually turned into TD's (via the
  285. // Queue General Request) then we stop until EndpointWorker is
  286. // called again.
  287. //
  288. }
  289. OpenHCI_KdPrintDD(DeviceData, OHCI_DBG_TD_TRACE, ("'exit EW\n"));
  290. LOGENTRY(G, 'EPw>', Endpoint, 0, 0);
  291. LOGIRQL();
  292. }
  293. VOID
  294. OpenHCI_SetTranferError(
  295. PHCD_URB Urb,
  296. USBD_STATUS usbdStatus
  297. )
  298. {
  299. struct _URB_HCD_COMMON_TRANSFER *transfer;
  300. transfer = &Urb->HcdUrbCommonTransfer;
  301. while (Urb != NULL) {
  302. Urb->UrbHeader.Status = usbdStatus;
  303. transfer->TransferBufferLength = 0;
  304. // 0 => nothing xfered
  305. Urb = transfer->UrbLink;
  306. transfer = &Urb->HcdUrbCommonTransfer;
  307. }
  308. }
  309. NTSTATUS
  310. OpenHCI_QueueTransfer(
  311. PDEVICE_OBJECT DeviceObject,
  312. PIRP Irp
  313. )
  314. {
  315. /*++
  316. Routine Description:
  317. formerly "StartTransfer"
  318. Queues transfers to endpoint, called from the process URB function.
  319. Arguments:
  320. DeviceObject - pointer to a device object
  321. Irp - pointer to an I/O Request Packet with transfer type URB
  322. Return Value:
  323. returns STATUS_PENDING if the request is succesfully queued otherwise
  324. an error is returned.
  325. NOTE: if an error is returned we expect the IRP to be completed by the
  326. caller
  327. --*/
  328. PHCD_DEVICE_DATA DeviceData;
  329. PHC_OPERATIONAL_REGISTER HC;
  330. PHCD_URB urb;
  331. PHCD_ENDPOINT endpoint;
  332. NTSTATUS ntStatus = STATUS_PENDING;
  333. KIRQL oldIrql, oldIrql2;
  334. struct _URB_HCD_COMMON_TRANSFER *transfer;
  335. DeviceData = (PHCD_DEVICE_DATA) DeviceObject->DeviceExtension;
  336. OpenHCI_KdPrintDD(DeviceData,
  337. OHCI_DBG_TD_TRACE, ("'enter StartTransfer\n"));
  338. urb = (PHCD_URB) URB_FROM_IRP(Irp);
  339. transfer = &urb->HcdUrbCommonTransfer;
  340. transfer->hca.HcdIrp = Irp;
  341. endpoint = transfer->hca.HcdEndpoint;
  342. ASSERT_ENDPOINT(endpoint);
  343. LOGENTRY(G, 'Xfer', transfer, endpoint, Irp);
  344. LOGIRQL();
  345. HC = DeviceData->HC;
  346. if (READ_REGISTER_ULONG(&HC->HcRevision.ul) == 0xFFFFFFFF)
  347. {
  348. OpenHCI_KdPrint((0, "'QueueTransfer, controller not there!\n"));
  349. ntStatus = STATUS_DEVICE_DOES_NOT_EXIST;
  350. OpenHCI_SetTranferError(urb, USBD_STATUS_REQUEST_FAILED);
  351. goto OpenHCI_QueueTransfer_Done;
  352. }
  353. //
  354. // Check for Root Hub transfers
  355. //
  356. if (endpoint->EpFlags & EP_ROOT_HUB) {
  357. ntStatus = OpenHCI_RootHubStartXfer(DeviceObject,
  358. DeviceData,
  359. Irp,
  360. urb,
  361. endpoint);
  362. ASSERT(urb->HcdUrbCommonTransfer.UrbLink == NULL);
  363. goto OpenHCI_QueueTransfer_Done;
  364. }
  365. //
  366. // This is an ordinary transfer
  367. //
  368. // first some parameter validation
  369. if (USB_ENDPOINT_TYPE_ISOCHRONOUS == endpoint->Type) {
  370. // Test to make sure that the start of Frame is within a
  371. // #define 'd range.
  372. if (USBD_START_ISO_TRANSFER_ASAP &
  373. urb->UrbIsochronousTransfer.TransferFlags) {
  374. OpenHCI_KdPrintDD(DeviceData,
  375. OHCI_DBG_TD_TRACE, ("'ASAP ISO\n"));
  376. LOGENTRY(G, 'qASA', transfer, endpoint, Irp);
  377. } else if (abs((LONG) (urb->UrbIsochronousTransfer.StartFrame
  378. - Get32BitFrameNumber(DeviceData)))
  379. > USBD_ISO_START_FRAME_RANGE) {
  380. OpenHCI_KdPrintDD(DeviceData,
  381. OHCI_DBG_TD_ERROR, ("'Bad start Frame\n"));
  382. LOGENTRY(G, 'BADs', transfer, endpoint, Irp);
  383. OpenHCI_KdBreak(("Bad Start Frame\n"));
  384. ntStatus = STATUS_INVALID_PARAMETER;
  385. OpenHCI_SetTranferError(urb, USBD_STATUS_BAD_START_FRAME);
  386. goto OpenHCI_QueueTransfer_Done;
  387. }
  388. }
  389. // We were told during open what the largest number of bytes transfered
  390. // per URB were going to be. Fail if this transfer is greater than that
  391. // given number.
  392. if (transfer->TransferBufferLength > endpoint->MaxTransfer) {
  393. OpenHCI_KdPrintDD(DeviceData,
  394. OHCI_DBG_TD_ERROR, ("'Max Trans exceeded\n"));
  395. LOGENTRY(G, 'BADt', transfer, transfer->TransferBufferLength, Irp);
  396. ntStatus = STATUS_INVALID_PARAMETER;
  397. OpenHCI_SetTranferError(urb, USBD_STATUS_INVALID_PARAMETER);
  398. goto OpenHCI_QueueTransfer_Done;
  399. }
  400. //
  401. // OK to queue the transfer, grab the queue lock and queue
  402. // the transfer to the endpoint.
  403. //
  404. // Must acquire spinlocks in the same order as OpenHCI_CancelTransfer(),
  405. // which is called with the cancel spinlock already held and then it
  406. // acquires the endpoint QueueLock spinlock.
  407. //
  408. IoAcquireCancelSpinLock(&oldIrql2);
  409. KeAcquireSpinLock(&endpoint->QueueLock, &oldIrql);
  410. if (Irp->Cancel) {
  411. // cancel it now
  412. ntStatus = STATUS_CANCELLED;
  413. IoSetCancelRoutine(Irp, NULL);
  414. OpenHCI_SetTranferError(urb, USBD_STATUS_CANCELED);
  415. LOGENTRY(G, 'Qcan', transfer, endpoint, Irp);
  416. } else if (endpoint->EpFlags & EP_CLOSED) {
  417. // we should not see this,
  418. // it means we got a transfer after the
  419. // endpoint was closed
  420. TEST_TRAP();
  421. ntStatus = STATUS_TRANSACTION_ABORTED;
  422. IoSetCancelRoutine(Irp, NULL);
  423. OpenHCI_SetTranferError(urb, USBD_STATUS_CANCELED);
  424. LOGENTRY(G, 'epcl', transfer, endpoint, Irp);
  425. } else {
  426. //
  427. // not closed, queue the transfer
  428. //
  429. while (urb != NULL) {
  430. LOGENTRY(G, 'qURB', urb, endpoint, Irp);
  431. ASSERT(endpoint == transfer->hca.HcdEndpoint);
  432. InitializeListHead(&transfer->hca.HcdListEntry2);
  433. urb->UrbHeader.Status = HCD_PENDING_STATUS_QUEUED;
  434. InsertTailList(&endpoint->RequestQueue,
  435. &transfer->hca.HcdListEntry);
  436. urb = transfer->UrbLink;
  437. transfer = &urb->HcdUrbCommonTransfer;
  438. }
  439. Irp->IoStatus.Status = STATUS_PENDING;
  440. IoMarkIrpPending(Irp);
  441. ASSERT(Irp->Cancel == FALSE);
  442. LOGENTRY(G, 'IPRX', urb, endpoint, Irp);
  443. IoSetCancelRoutine(Irp, OpenHCI_CancelTransfer);
  444. }
  445. KeReleaseSpinLock(&endpoint->QueueLock, oldIrql);
  446. IoReleaseCancelSpinLock(oldIrql2);
  447. //
  448. // attempt to start this transfer
  449. //
  450. OpenHCI_ProcessEndpoint(DeviceData, endpoint);
  451. OpenHCI_QueueTransfer_Done:
  452. LOGENTRY(G, 'XfrD', transfer, endpoint, Irp);
  453. LOGIRQL();
  454. OpenHCI_KdPrintDD(DeviceData, OHCI_DBG_TD_TRACE,
  455. ("'exit OpenHCI_StartTransfer with status = %x\n",
  456. ntStatus));
  457. return ntStatus;
  458. }
  459. #define INITIALIZE_TD(td, ep, urb) \
  460. {\
  461. td->UsbdRequest = (PHCD_URB)(urb);\
  462. td->Endpoint = (ep);\
  463. td->Canceled = FALSE;\
  464. td->TransferCount = 0; \
  465. td->HcTD.Control = 0; \
  466. td->HcTD.CBP = 0;\
  467. td->HcTD.BE = 0;\
  468. }
  469. #define OHCI_PAGE_ALIGN(Va) ((PVOID)((ULONG_PTR)(Va) & ~(OHCI_PAGE_SIZE - 1)))
  470. ULONG
  471. GetLengthToMap(
  472. PUCHAR BaseVa,
  473. ULONG StartOffset,
  474. ULONG RequestLength
  475. )
  476. {
  477. ULONG pgBreakOffset, length;
  478. //
  479. // see how far it is to the next page boundry
  480. //
  481. LOGENTRY(G, 'GLM0', BaseVa, StartOffset, RequestLength);
  482. pgBreakOffset = (ULONG)(((PUCHAR) OHCI_PAGE_ALIGN(BaseVa+StartOffset) + \
  483. OHCI_PAGE_SIZE) - (BaseVa));
  484. //
  485. // compute length to map
  486. //
  487. if (StartOffset + RequestLength > pgBreakOffset) {
  488. length = pgBreakOffset - StartOffset;
  489. } else {
  490. length = RequestLength;
  491. }
  492. LOGENTRY(G, 'GLM1', pgBreakOffset, length, 0);
  493. return length;
  494. }
  495. PVOID
  496. OpenHCI_MapTransferToTD(
  497. PHCD_DEVICE_DATA DeviceData,
  498. PMAP_CONTEXT MapContext,
  499. ULONG TotalLength,
  500. PUCHAR BaseVa,
  501. PHCD_ENDPOINT Endpoint,
  502. PHCD_TRANSFER_DESCRIPTOR Td,
  503. struct _URB_HCD_COMMON_TRANSFER *Transfer,
  504. PUCHAR CurrentVa,
  505. PULONG LengthMapped1stPage,
  506. PULONG LengthMapped
  507. )
  508. /*++
  509. Routine Description:
  510. Maps a data buffer to TDs according to OHCI rules
  511. An OHCI TD can cover up to 8k with a single page crossing.
  512. Arguments:
  513. DeviceObject - pointer to a device object
  514. Irp - pointer to an I/O Request Packet (ignored)
  515. LengthMapped - how much is mapped so far
  516. CurrentVa - current virtual address of buffer described by MDL
  517. returns
  518. LengthMapped1stPage - number of bytes in the first mapped page
  519. LengthMapped - total data mapped so far
  520. Return Value:
  521. updated CurrentVa
  522. --*/
  523. {
  524. PVOID mapRegisterBase;
  525. BOOLEAN input;
  526. PHYSICAL_ADDRESS logicalStart;
  527. PHYSICAL_ADDRESS logicalEnd;
  528. ULONG length, lengthThisTD, lengthToMap, remainder;
  529. #if DBG
  530. ULONG requestLength;
  531. #endif
  532. mapRegisterBase = Transfer->hca.HcdExtension;
  533. input = (BOOLEAN) (Transfer->TransferFlags & USBD_TRANSFER_DIRECTION_IN);
  534. lengthToMap = Transfer->TransferBufferLength - (*LengthMapped);
  535. OHCI_ASSERT(lengthToMap > 0);
  536. // A TD can have up to one page crossing. This means we need
  537. // to call IoMapTransfer twice, once for the first physical
  538. // page, and once for the second.
  539. // Also
  540. // IoMapTransfer may return us more than one page if the
  541. // buffer if physically contiguous we need to make sure
  542. // we only call IoMapTranfer for enough bytes up to the next
  543. // page boundry
  544. //
  545. // map first page
  546. length = GetLengthToMap(BaseVa,
  547. *LengthMapped,
  548. lengthToMap);
  549. LOGENTRY(G, 'Mp1r', Transfer, length, CurrentVa);
  550. #if DBG
  551. requestLength = length;
  552. #endif
  553. logicalStart = OpenHCI_IoMapTransfer(
  554. MapContext,
  555. DeviceData->AdapterObject,
  556. Transfer->TransferBufferMDL,
  557. mapRegisterBase,
  558. CurrentVa,
  559. &length,
  560. TotalLength,
  561. (BOOLEAN) !input);
  562. #if DBG
  563. // since we always compute the length to start on or before
  564. // the next page break we should always get what we ask for
  565. OHCI_ASSERT(requestLength == length);
  566. #endif
  567. // length is how much we mapped
  568. CurrentVa += length;
  569. (*LengthMapped) += length;
  570. lengthThisTD = length;
  571. lengthToMap -= length;
  572. if (LengthMapped1stPage) {
  573. *LengthMapped1stPage = length;
  574. }
  575. LOGENTRY(G, 'Mp1d', Transfer, length, logicalStart.LowPart);
  576. // see if we have more buffer to map
  577. if (lengthToMap) {
  578. // yes,
  579. // map second page
  580. length = GetLengthToMap(BaseVa,
  581. *LengthMapped,
  582. lengthToMap);
  583. LOGENTRY(G, 'Mp2r', Transfer, length, CurrentVa);
  584. // if this is not the last TD of the transfer then we need
  585. // to ensure that this TD ends on a max packet boundry.
  586. //
  587. // ie we may map more than we can use, we will adjust
  588. // the length
  589. //
  590. // lengthToMap will be zero if this is the last TD
  591. lengthThisTD += length;
  592. lengthToMap -= length;
  593. remainder = lengthThisTD % Endpoint->MaxPacket;
  594. if (remainder > 0 && lengthToMap) {
  595. // make the adjustment
  596. lengthThisTD -= remainder;
  597. length -= remainder;
  598. lengthToMap += remainder;
  599. LOGENTRY(G, 'Mrem', Transfer, length, remainder);
  600. }
  601. #if DBG
  602. requestLength = length;
  603. #endif
  604. logicalEnd = OpenHCI_IoMapTransfer(
  605. MapContext,
  606. DeviceData->AdapterObject,
  607. Transfer->TransferBufferMDL,
  608. mapRegisterBase,
  609. CurrentVa,
  610. &length,
  611. TotalLength,
  612. (BOOLEAN)!input);
  613. #if DBG
  614. // since we always compute the length to start on or before
  615. // the next page break we should always get what we ask for
  616. OHCI_ASSERT(requestLength == length);
  617. #endif
  618. CurrentVa += length;
  619. (*LengthMapped) += length;
  620. LOGENTRY(G, 'Mp2d', Transfer, length, logicalEnd.LowPart);
  621. } else {
  622. logicalEnd = logicalStart;
  623. }
  624. LOGENTRY(G, 'MpT1', Transfer, *LengthMapped, lengthToMap);
  625. ASSERT(*LengthMapped + lengthToMap == Transfer->TransferBufferLength);
  626. logicalEnd.LowPart += length;
  627. // now we check to see if the mapped length is a multiple of
  628. // maxpacket size
  629. // buffer has been mapped, now set up the TD
  630. Td->HcTD.CBP = logicalStart.LowPart;
  631. // buffer end points to last byte in the buffer
  632. Td->HcTD.BE = logicalEnd.LowPart-1;
  633. Td->TransferCount = lengthThisTD;
  634. LOGENTRY(G, 'MpTD', Td->HcTD.CBP, Td->HcTD.BE, lengthThisTD);
  635. LOGENTRY(G, 'MPTD', Td, 0, 0);
  636. return CurrentVa;
  637. }
  638. VOID
  639. OpenHCI_ControlTransfer(
  640. PHCD_DEVICE_DATA DeviceData,
  641. PHCD_ENDPOINT Endpoint,
  642. PHCD_URB Urb,
  643. struct _URB_HCD_COMMON_TRANSFER *Transfer
  644. )
  645. /*++
  646. Routine Description:
  647. Arguments:
  648. Return Value:
  649. --*/
  650. {
  651. PHCD_TRANSFER_DESCRIPTOR td, lastTD = NULL;
  652. MAP_CONTEXT mapContext;
  653. // PHCD_TRANSFER_DESCRIPTOR tailTD;
  654. ULONG lengthMapped;
  655. PUCHAR currentVa, baseVa;
  656. // first data packet is always data1
  657. ULONG toggleForDataPhase = HcTDControl_TOGGLE_DATA1;
  658. ULONG dataTDcount = 0;
  659. //
  660. // first prepare a TD for the setup packet
  661. //
  662. LOGENTRY(G, 'CTRp', Endpoint, Transfer, Transfer->hca.HcdIrp);
  663. RtlZeroMemory(&mapContext, sizeof(mapContext));
  664. if (Transfer->TransferBufferLength) {
  665. baseVa = currentVa = MmGetMdlVirtualAddress(Transfer->TransferBufferMDL);
  666. }
  667. // grab the dummy TD from the tail of the queue
  668. lastTD = td = Endpoint->HcdTailP;
  669. OHCI_ASSERT(td);
  670. INITIALIZE_TD(td, Endpoint, Urb);
  671. InsertTailList(&Transfer->hca.HcdListEntry2, &td->RequestList);
  672. //
  673. // Move setup data into TD (8 chars long)
  674. //
  675. *((PLONGLONG) &td->HcTD.Packet[0])
  676. = *((PLONGLONG) &Transfer->Extension.u.SetupPacket[0]);
  677. td->HcTD.CBP = (ULONG)(((PCHAR) & td->HcTD.Packet[0])
  678. - ((PCHAR) &td->HcTD)) + td->PhysicalAddress;
  679. td->HcTD.BE = td->HcTD.CBP + 7;
  680. td->HcTD.Control =
  681. HcTDControl_DIR_SETUP |
  682. HcTDControl_TOGGLE_DATA0 |
  683. HcTDControl_INT_DELAY_NO_INT |
  684. (HcCC_NotAccessed << HcTDControl_CONDITION_CODE_SHIFT);
  685. OpenHCI_KdPrintDD(DeviceData,
  686. OHCI_DBG_TD_NOISE, ("'SETUP TD 0x%x \n", td));
  687. LOGENTRY(G, 'setP',
  688. td,
  689. *((PLONG) &Transfer->Extension.u.SetupPacket[0]),
  690. *((PLONG) &Transfer->Extension.u.SetupPacket[4]));
  691. // allocate another TD
  692. lastTD = td;
  693. td = OpenHCI_Alloc_HcdTD(DeviceData);
  694. OHCI_ASSERT(td);
  695. INITIALIZE_TD(td, Endpoint, Urb);
  696. InsertTailList(&Transfer->hca.HcdListEntry2, &td->RequestList);
  697. lastTD->NextHcdTD = td;
  698. lastTD->HcTD.NextTD = td->PhysicalAddress;
  699. //
  700. // now setup the data phase
  701. //
  702. lengthMapped = 0;
  703. while (lengthMapped < Transfer->TransferBufferLength) {
  704. //
  705. // fields for data TD
  706. //
  707. dataTDcount++;
  708. td->HcTD.Control =
  709. HcTDControl_INT_DELAY_NO_INT |
  710. (HcCC_NotAccessed << HcTDControl_CONDITION_CODE_SHIFT) |
  711. ((Transfer->TransferFlags & USBD_TRANSFER_DIRECTION_IN) ?
  712. HcTDControl_DIR_IN :
  713. HcTDControl_DIR_OUT);
  714. td->HcTD.Control |= toggleForDataPhase;
  715. //after the first TD get the toggle from ED
  716. toggleForDataPhase = HcTDControl_TOGGLE_FROM_ED;
  717. LOGENTRY(G, 'data', td, lengthMapped, Transfer->TransferBufferLength);
  718. currentVa = OpenHCI_MapTransferToTD(DeviceData,
  719. &mapContext,
  720. Transfer->TransferBufferLength,
  721. baseVa,
  722. Endpoint,
  723. td,
  724. Transfer,
  725. currentVa,
  726. NULL,
  727. &lengthMapped);
  728. // allocate another TD
  729. lastTD = td;
  730. td = OpenHCI_Alloc_HcdTD(DeviceData);
  731. OHCI_ASSERT(td);
  732. INITIALIZE_TD(td, Endpoint, Urb);
  733. InsertTailList(&Transfer->hca.HcdListEntry2, &td->RequestList);
  734. lastTD->NextHcdTD = td;
  735. lastTD->HcTD.NextTD = td->PhysicalAddress;
  736. }
  737. //
  738. // set the shortxfer OK bit on the last TD only
  739. //
  740. if (USBD_SHORT_TRANSFER_OK & Transfer->TransferFlags) {
  741. lastTD->HcTD.ShortXferOk = 1;
  742. }
  743. //
  744. // now do the status phase
  745. //
  746. LOGENTRY(G, 'staP', td, 0, dataTDcount);
  747. #if DBG
  748. if (dataTDcount > 1) {
  749. TEST_TRAP();
  750. }
  751. #endif
  752. // status direction is opposite data direction,
  753. // specify interrupt on completion
  754. if (Transfer->TransferFlags & USBD_TRANSFER_DIRECTION_IN) {
  755. td->HcTD.Control = HcTDControl_DIR_OUT
  756. | HcTDControl_INT_DELAY_0_MS
  757. | HcTDControl_TOGGLE_DATA1
  758. | (HcCC_NotAccessed << HcTDControl_CONDITION_CODE_SHIFT);
  759. } else {
  760. td->HcTD.Control = HcTDControl_DIR_IN
  761. | HcTDControl_INT_DELAY_0_MS
  762. | HcTDControl_TOGGLE_DATA1
  763. | (HcCC_NotAccessed << HcTDControl_CONDITION_CODE_SHIFT);
  764. td->HcTD.ShortXferOk = 1;
  765. }
  766. //
  767. // now put a new dummy TD on the tail of the EP queue
  768. //
  769. OpenHCI_KdPrintDD(DeviceData,
  770. OHCI_DBG_TD_NOISE, ("'STATUS TD 0x%x \n", td));
  771. // allocate a new tail
  772. lastTD = td;
  773. td = OpenHCI_Alloc_HcdTD(DeviceData);
  774. OHCI_ASSERT(td);
  775. INITIALIZE_TD(td, Endpoint, Urb);
  776. lastTD->NextHcdTD = td;
  777. lastTD->HcTD.NextTD = td->PhysicalAddress;
  778. //
  779. // Set new TailP in ED
  780. // note: This is the last TD in the list and the place holder.
  781. //
  782. td->UsbdRequest = TD_NOREQUEST_SIG;
  783. // zero bytes transferred so far
  784. Transfer->TransferBufferLength = 0;
  785. Endpoint->HcdTailP = td;
  786. // put the request on the hardware queue
  787. LOGENTRY(G, 'cTal', Endpoint->HcdED->HcED.TailP , td->PhysicalAddress, 0);
  788. Endpoint->HcdED->HcED.TailP = td->PhysicalAddress;
  789. // tell the hc we have control transfers available
  790. ENABLE_LIST(DeviceData->HC, Endpoint);
  791. }
  792. VOID
  793. OpenHCI_BulkOrInterruptTransfer(
  794. PHCD_DEVICE_DATA DeviceData,
  795. PHCD_ENDPOINT Endpoint,
  796. PHCD_URB Urb,
  797. struct _URB_HCD_COMMON_TRANSFER *Transfer
  798. )
  799. /*++
  800. Routine Description:
  801. Arguments:
  802. Return Value:
  803. --*/
  804. {
  805. PHCD_TRANSFER_DESCRIPTOR td, lastTD = NULL;
  806. PHCD_TRANSFER_DESCRIPTOR tailTD = NULL;
  807. ULONG lengthMapped;
  808. PUCHAR currentVa = NULL, baseVa = NULL;
  809. MAP_CONTEXT mapContext;
  810. // first data packet is always data1
  811. ULONG dataTDcount = 0;
  812. OHCI_ASSERT(Endpoint->TrueTail == NULL);
  813. RtlZeroMemory(&mapContext, sizeof(mapContext));
  814. //
  815. // first prepare a TD for the setup packet
  816. //
  817. LOGENTRY(G, 'BITp', Endpoint, Transfer, Transfer->hca.HcdIrp);
  818. if (Transfer->TransferBufferLength) {
  819. baseVa = currentVa = MmGetMdlVirtualAddress(Transfer->TransferBufferMDL);
  820. }
  821. // grab the dummy TD from the tail of the queue
  822. lastTD = td = Endpoint->HcdTailP;
  823. LOGENTRY(G, 'bitT', lastTD, Endpoint->HcdED->HcED.TailP, 0);
  824. OHCI_ASSERT(td);
  825. INITIALIZE_TD(td, Endpoint, Urb);
  826. // map the transfer
  827. lengthMapped = 0;
  828. do {
  829. LOGENTRY(G, 'qTR_', Endpoint, Transfer, td);
  830. InsertTailList(&Transfer->hca.HcdListEntry2, &td->RequestList);
  831. //
  832. // fields for data TD
  833. //
  834. dataTDcount++;
  835. td->HcTD.Control =
  836. HcTDControl_INT_DELAY_NO_INT |
  837. (HcCC_NotAccessed << HcTDControl_CONDITION_CODE_SHIFT) |
  838. ((Transfer->TransferFlags & USBD_TRANSFER_DIRECTION_IN) ?
  839. HcTDControl_DIR_IN :
  840. HcTDControl_DIR_OUT);
  841. // always interrupt
  842. td->HcTD.IntDelay = 0;
  843. // use toggle from ED
  844. td->HcTD.Control |= HcTDControl_TOGGLE_FROM_ED;
  845. LOGENTRY(G, 'datA', td, lengthMapped, Transfer->TransferBufferLength);
  846. if (Transfer->TransferBufferLength) {
  847. currentVa = OpenHCI_MapTransferToTD(DeviceData,
  848. &mapContext,
  849. Transfer->TransferBufferLength,
  850. baseVa,
  851. Endpoint,
  852. td,
  853. Transfer,
  854. currentVa,
  855. NULL,
  856. &lengthMapped);
  857. }
  858. // allocate another TD
  859. lastTD = td;
  860. td = OpenHCI_Alloc_HcdTD(DeviceData);
  861. OHCI_ASSERT(td);
  862. INITIALIZE_TD(td, Endpoint, Urb);
  863. if (Endpoint->EpFlags & EP_ONE_TD) {
  864. LOGENTRY(G, 'limT', td, Endpoint, tailTD);
  865. lastTD->HcTD.IntDelay = 0; // interrupt on completion
  866. lastTD->HcTD.ShortXferOk = 1; // make sure NEC ACKs short packets
  867. if (tailTD == NULL) {
  868. tailTD = td; // next TD after the first TD
  869. }
  870. }
  871. // Set the next pointer of the previous TD to the one we just allocated.
  872. //
  873. lastTD->NextHcdTD = td;
  874. lastTD->HcTD.NextTD = td->PhysicalAddress;
  875. } while (lengthMapped < Transfer->TransferBufferLength);
  876. //
  877. // set the shortxfer OK bit on the last TD only
  878. //
  879. if (USBD_SHORT_TRANSFER_OK & Transfer->TransferFlags) {
  880. lastTD->HcTD.ShortXferOk = 1;
  881. }
  882. #ifdef MAX_DEBUG
  883. if (dataTDcount > 1) {
  884. TEST_TRAP();
  885. }
  886. #endif
  887. lastTD->HcTD.IntDelay = 0; // interrupt on completion of last packet
  888. //
  889. // now put a new dummy TD on the tail of the EP queue
  890. //
  891. //
  892. // Set new TailP in ED
  893. // note: This is the last TD in the list and the place holder.
  894. //
  895. td->UsbdRequest = TD_NOREQUEST_SIG;
  896. // zero bytes transferred so far
  897. Transfer->TransferBufferLength = 0;
  898. if (tailTD != NULL) {
  899. LOGENTRY(G, 'truT', td, Endpoint->TrueTail, tailTD);
  900. Endpoint->TrueTail = td; // dummy TD at end of transfer
  901. td = tailTD; // next TD after the first TD
  902. }
  903. // Update the software tail pointer
  904. //
  905. Endpoint->HcdTailP = td;
  906. LOGENTRY(G, 'aTAL', td, Endpoint->HcdED->HcED.TailP, td->PhysicalAddress);
  907. LOGENTRY(G, 'aTL2', td, Endpoint->HcdED->HcED.HeadP, 0);
  908. // Update hardware tail pointer, putting the request on the hardware queue
  909. //
  910. Endpoint->HcdED->HcED.TailP = td->PhysicalAddress;
  911. // tell the hc we have transfers available
  912. //
  913. ENABLE_LIST(DeviceData->HC, Endpoint);
  914. }
  915. //////////////////////////////////////////////////////////////////////
  916. // //
  917. // START OF ISOCHRONOUS TD BUILDING CODE //
  918. // //
  919. //////////////////////////////////////////////////////////////////////
  920. // These defines are bitmasks of frame case conditions, which are OR'd
  921. // together to enumerate 12 different frame cases. There are not 16 different
  922. // frame cases since FRAME_CASE_END_AT_PAGE and FRAME_CASE_END_NEXT_PAGE are
  923. // mutually exclusive.
  924. // FRAME_CASE_LAST_FRAME is TRUE if the current frame will fill the eigth and
  925. // final Offset/PSW slot in the current TD.
  926. //
  927. #define FRAME_CASE_LAST_FRAME 1
  928. // FRAME_CASE_START_SECOND_PAGE is TRUE if the current frame starts in the
  929. // second physical page spanned by the current TD.
  930. //
  931. #define FRAME_CASE_START_SECOND_PAGE 2
  932. // FRAME_CASE_END_AT_PAGE is TRUE if the current frame ends exactly at a
  933. // physical page boundary, excluding the case where a zero length frame
  934. // starts and ends at the same physyical page boundary.
  935. //
  936. #define FRAME_CASE_END_AT_PAGE 4
  937. // FRAME_CASE_END_NEXT_PAGE is TRUE if the current frame starts in one physical
  938. // page and ends in another physical page.
  939. //
  940. #define FRAME_CASE_END_NEXT_PAGE 8
  941. //
  942. // +-------+ +-------+
  943. // 9: | i = 7 | 11: | i = 7 |
  944. // +-------+ +-------+
  945. //
  946. // +-------+ +-------+
  947. // 8: | i < 7 | 10: | i < 7 |
  948. // +-------+ +-------+
  949. //
  950. // +-------+ +-------+ +-------+ +-------+
  951. // 1: | i = 7 | 5: | i = 7 | 3: | i = 7 | 7: | i = 7 |
  952. // +-------+ +-------+ +-------+ +-------+
  953. //
  954. // +-------+ +-------+ +-------+ +-------+
  955. // 0: | i < 7 | 4: | i < 7 | 2: | i < 7 | 6: | i < 7 |
  956. // +-------+ +-------+ +-------+ +-------+
  957. //
  958. // +------------------------------+------------------------------+
  959. // | First TD Page | Second TD Page |
  960. // +------------------------------+------------------------------+
  961. //
  962. typedef struct _FRAME_CASE_ACTIONS
  963. {
  964. // AddFrameToTD == 1, Add frame to TD during first pass
  965. // AddFrameToTD == 2, Add frame to TD during second pass
  966. // AddFrameToTD == 3, Add frame to TD during third pass
  967. //
  968. UCHAR AddFrameToTD;
  969. // AllocNextTD == 0, Don't allocate next TD
  970. // AllocNextTD == 1, Allocate next TD during first pass
  971. // AllocNextTD == 2, Allocate next TD during second pass
  972. //
  973. UCHAR AllocNextTD;
  974. // MapNextPage == 0, Don't map next physical page
  975. // MapNextPage == 1, Map next physical page during first pass
  976. // MapNextPage == 2, Map next physical page during second pass
  977. //
  978. UCHAR MapNextPage;
  979. } FRAME_CASE_ACTIONS;
  980. FRAME_CASE_ACTIONS FrameCaseActions[12] =
  981. {
  982. // AddFrameToTD, AllocNextTD, MapNextPage
  983. {1, 0, 0}, // case 0
  984. {1, 1, 0}, // case 1
  985. {1, 0, 0}, // case 2
  986. {1, 1, 0}, // case 3
  987. {1, 0, 1}, // case 4
  988. {1, 1, 1}, // case 5
  989. {1, 1, 1}, // case 6
  990. {1, 1, 1}, // case 7
  991. {2, 0, 1}, // case 8
  992. {2, 2, 1}, // case 9
  993. {3, 1, 2}, // case 10
  994. {3, 1, 2} // case 11
  995. };
  996. PHCD_TRANSFER_DESCRIPTOR
  997. OpenHCI_Alloc_IsoTD(
  998. PHCD_DEVICE_DATA DeviceData,
  999. PHCD_ENDPOINT Endpoint,
  1000. PHCD_TRANSFER_DESCRIPTOR LastTD
  1001. )
  1002. {
  1003. PHCD_TRANSFER_DESCRIPTOR td;
  1004. td = OpenHCI_Alloc_HcdTD(DeviceData);
  1005. OHCI_ASSERT(td);
  1006. INITIALIZE_TD(td, Endpoint, TD_NOREQUEST_SIG);
  1007. LastTD->NextHcdTD = td;
  1008. LastTD->HcTD.NextTD = td->PhysicalAddress;
  1009. return td;
  1010. }
  1011. VOID
  1012. OpenHCI_IsoTransfer(
  1013. PHCD_DEVICE_DATA DeviceData,
  1014. PHCD_ENDPOINT Endpoint,
  1015. PHCD_URB Urb,
  1016. struct _URB_HCD_COMMON_TRANSFER *Transfer
  1017. )
  1018. {
  1019. PADAPTER_OBJECT adapterObject;
  1020. PMDL mdl;
  1021. PVOID mapRegisterBase;
  1022. PUCHAR currentVa;
  1023. ULONG lengthToMap;
  1024. BOOLEAN writeToDevice;
  1025. ULONG lengthMapped;
  1026. ULONG lengthMappedRemaining;
  1027. PHYSICAL_ADDRESS physAddr;
  1028. struct _URB_ISOCH_TRANSFER *iso;
  1029. ULONG packetIndex;
  1030. ULONG frameIndex;
  1031. ULONG frameOffset;
  1032. ULONG frameLength;
  1033. ULONG frameCase;
  1034. ULONG framePass;
  1035. ULONG framePassNext;
  1036. PHCD_TRANSFER_DESCRIPTOR td;
  1037. LOGENTRY(G, 'ITRN', Endpoint, Transfer, Transfer->hca.HcdIrp);
  1038. //
  1039. // These values are static across every call to IoMapTranfer()
  1040. //
  1041. adapterObject = DeviceData->AdapterObject;
  1042. mdl = Transfer->TransferBufferMDL;
  1043. mapRegisterBase = Transfer->hca.HcdExtension;
  1044. writeToDevice = !(Transfer->TransferFlags & USBD_TRANSFER_DIRECTION_IN);
  1045. //
  1046. // These values are updated after every call to IoMapTransfer()
  1047. //
  1048. currentVa = MmGetMdlVirtualAddress(mdl);
  1049. lengthToMap = Transfer->TransferBufferLength;
  1050. //
  1051. // select a start frame for the transfer
  1052. //
  1053. iso = (struct _URB_ISOCH_TRANSFER *)Transfer;
  1054. if (USBD_START_ISO_TRANSFER_ASAP & iso->TransferFlags)
  1055. {
  1056. //
  1057. // If the iso packet is set for start asap:
  1058. //
  1059. // If we have had no transfers (ie virgin) then use currentframe + 2,
  1060. // otherwise use the current next frame value from the endpoint.
  1061. //
  1062. if (Endpoint->EpFlags & EP_VIRGIN)
  1063. {
  1064. iso->StartFrame =
  1065. Endpoint->NextIsoFreeFrame =
  1066. Get32BitFrameNumber(DeviceData) + 2;
  1067. }
  1068. else
  1069. {
  1070. iso->StartFrame = Endpoint->NextIsoFreeFrame;
  1071. }
  1072. }
  1073. else
  1074. {
  1075. //
  1076. // absolute frame start specified
  1077. //
  1078. Endpoint->NextIsoFreeFrame = iso->StartFrame;
  1079. }
  1080. if (USBD_TRANSFER_DIRECTION(iso->TransferFlags) ==
  1081. USBD_TRANSFER_DIRECTION_OUT)
  1082. {
  1083. // preset the length fields for OUT transfers
  1084. //
  1085. for (packetIndex=0; packetIndex<iso->NumberOfPackets-1; packetIndex++)
  1086. {
  1087. iso->IsoPacket[packetIndex].Length =
  1088. iso->IsoPacket[packetIndex+1].Offset -
  1089. iso->IsoPacket[packetIndex].Offset;
  1090. }
  1091. iso->IsoPacket[iso->NumberOfPackets-1].Length =
  1092. iso->TransferBufferLength -
  1093. iso->IsoPacket[iso->NumberOfPackets-1].Offset;
  1094. }
  1095. Endpoint->NextIsoFreeFrame += iso->NumberOfPackets;
  1096. CLR_EPFLAG(Endpoint, EP_VIRGIN);
  1097. //
  1098. // Grab the current tail TD from the endpoint to use as the first TD
  1099. // for the transfer.
  1100. //
  1101. td = Endpoint->HcdTailP;
  1102. OHCI_ASSERT(td);
  1103. INITIALIZE_TD(td, Endpoint, TD_NOREQUEST_SIG);
  1104. //
  1105. // Map the initial physically contiguous page(s) of the tranfer
  1106. //
  1107. currentVa += iso->IsoPacket[0].Offset;
  1108. lengthToMap -= iso->IsoPacket[0].Offset;
  1109. lengthMapped = lengthToMap;
  1110. LOGENTRY(G, 'IMP1', currentVa, lengthToMap, iso->IsoPacket[0].Offset);
  1111. physAddr = IoMapTransfer(adapterObject,
  1112. mdl,
  1113. mapRegisterBase,
  1114. currentVa,
  1115. &lengthMapped,
  1116. writeToDevice);
  1117. LOGENTRY(G, 'imp1', physAddr.LowPart, lengthMapped, 0);
  1118. lengthMappedRemaining = lengthMapped;
  1119. currentVa += lengthMapped;
  1120. lengthToMap -= lengthMapped;
  1121. frameOffset = physAddr.LowPart & HcPSW_OFFSET_MASK;
  1122. packetIndex = 0;
  1123. frameIndex = 0;
  1124. framePass = 1;
  1125. //
  1126. // Loop building TDs and mapping pages until the entire transfer
  1127. // buffer has been mapped and built into TDs.
  1128. //
  1129. while (1)
  1130. {
  1131. if (td->HcTD.CBP == 0)
  1132. {
  1133. td->HcTD.CBP = physAddr.LowPart & ~HcPSW_OFFSET_MASK;
  1134. // This is a new TD, so initialize the BaseIsocURBOffset field
  1135. // to the current packet index, and initialize the HcTD.Control
  1136. // with the starting frame number. The frame count will be
  1137. // filled in later.
  1138. td->BaseIsocURBOffset = (UCHAR)packetIndex;
  1139. td->HcTD.Control = HcTDControl_ISOCHRONOUS |
  1140. ((iso->StartFrame + packetIndex) &
  1141. HcTDControl_STARTING_FRAME);
  1142. LOGENTRY(G, 'ITD1', td, td->HcTD.CBP, packetIndex);
  1143. LOGENTRY(G, 'itd1', td->HcTD.StartingFrame, 0, 0);
  1144. // Add this TD to the list of TDs for this request
  1145. InsertTailList(&Transfer->hca.HcdListEntry2,
  1146. &td->RequestList);
  1147. td->UsbdRequest = (PHCD_URB)Transfer;
  1148. }
  1149. else
  1150. {
  1151. // This is not a new TD, so store the physical address in the
  1152. // second physical address slot of the TD.
  1153. td->HcTD.BE = physAddr.LowPart;
  1154. LOGENTRY(G, 'ITD2', td, td->HcTD.CBP, td->HcTD.BE);
  1155. LOGENTRY(G, 'itd2', packetIndex, td->HcTD.StartingFrame, framePass);
  1156. if (framePass == 1)
  1157. {
  1158. // We are starting a new frame in the second physical page
  1159. // of the current TD. The second physical page select bit
  1160. // (bit 12) better be set in the current frameOffset.
  1161. //
  1162. OHCI_ASSERT((frameOffset & ~HcPSW_OFFSET_MASK) != 0);
  1163. }
  1164. else
  1165. {
  1166. // We are finishing a frame in the second physical page
  1167. // of the current TD, but the frame started in the first
  1168. // physical page of the current TD. The second physical
  1169. // page select bit (bit 12) better not be set in the
  1170. // current frameOffset.
  1171. //
  1172. OHCI_ASSERT((frameOffset & ~HcPSW_OFFSET_MASK) == 0);
  1173. }
  1174. }
  1175. NextFrame:
  1176. if (framePass == 1)
  1177. {
  1178. // The curent frame length is the difference between the current
  1179. // frame offset and the next frame offset, or between the current
  1180. // frame offset and the transfer buffer length if this is the last
  1181. // frame.
  1182. if (packetIndex == iso->NumberOfPackets - 1)
  1183. {
  1184. frameLength = iso->TransferBufferLength -
  1185. iso->IsoPacket[packetIndex].Offset;
  1186. }
  1187. else
  1188. {
  1189. frameLength = iso->IsoPacket[packetIndex + 1].Offset -
  1190. iso->IsoPacket[packetIndex].Offset;
  1191. }
  1192. //
  1193. // Determine which of the twelve cases the current frame is
  1194. // for the current TD.
  1195. //
  1196. frameCase = 0;
  1197. if (frameIndex == 7)
  1198. {
  1199. // The current frame will fill the eigth and final
  1200. // Offset/PSW slot in the current TD.
  1201. frameCase |= FRAME_CASE_LAST_FRAME;
  1202. }
  1203. if (td->HcTD.BE != 0)
  1204. {
  1205. // The current frame starts in the second physical page
  1206. // spanned by the current TD.
  1207. frameCase |= FRAME_CASE_START_SECOND_PAGE;
  1208. }
  1209. if ((frameOffset & ~HcPSW_OFFSET_MASK) !=
  1210. ((frameOffset + frameLength) & ~HcPSW_OFFSET_MASK))
  1211. {
  1212. if (((frameOffset + frameLength) & HcPSW_OFFSET_MASK) == 0)
  1213. {
  1214. // The current frame ends exactly at a physical page
  1215. // boundary, excluding the case where a zero length
  1216. // frame starts and ends at the same physyical page
  1217. // boundary.
  1218. frameCase |= FRAME_CASE_END_AT_PAGE;
  1219. }
  1220. else
  1221. {
  1222. // The current frame starts in one physical page and
  1223. // ends in another physical page.
  1224. frameCase |= FRAME_CASE_END_NEXT_PAGE;
  1225. }
  1226. }
  1227. }
  1228. LOGENTRY(G, 'IFM1', packetIndex, frameIndex, frameOffset);
  1229. LOGENTRY(G, 'IFM2', frameLength, frameCase, framePass);
  1230. LOGENTRY(G, 'IFM3', lengthMappedRemaining, 0, 0);
  1231. //
  1232. // Add the current frame to the current TD, if appropriate at this
  1233. // point.
  1234. //
  1235. if (FrameCaseActions[frameCase].AddFrameToTD == framePass)
  1236. {
  1237. // Add the current frame starting offset to the current frame
  1238. // offset slot in the current TD.
  1239. td->HcTD.Packet[frameIndex].PSW = (USHORT)(HcPSW_ONES | frameOffset);
  1240. // Advance past the current frame to the starting offset of the
  1241. // next frame.
  1242. frameOffset += frameLength;
  1243. // Advance to the next frame offset slot in the current TD.
  1244. frameIndex++;
  1245. // Advance to the next frame in the Iso Urb.
  1246. packetIndex++;
  1247. // Decrement the remaining length of the currently mapped chunk
  1248. // of the transfer buffer by the amount we just consumed for the
  1249. // current frame.
  1250. lengthMappedRemaining -= frameLength;
  1251. // Indicate that if the next page is mapped after adding the
  1252. // curent frame to the current TD that IoMapTransfer() should
  1253. // be called only if lengthMappedRemaining is now zero.
  1254. //
  1255. frameLength = 0;
  1256. framePassNext = 1;
  1257. }
  1258. else
  1259. {
  1260. // The current frame will be added after the next page is mapped.
  1261. // The current frame will be added to either the current TD or to
  1262. // a newly allocated TD. When the next page is mapped before
  1263. // adding the current frame, IoMapTransfer() should be called
  1264. // only if the current frameLength is greater than the current
  1265. // lengthMappedRemaining.
  1266. framePassNext = framePass + 1;
  1267. }
  1268. //
  1269. // Finish off the current TD and allocate the next TD, if appropriate
  1270. // at this point.
  1271. //
  1272. if ((FrameCaseActions[frameCase].AllocNextTD == framePass) ||
  1273. ((lengthMappedRemaining == 0) && (lengthToMap == 0)))
  1274. {
  1275. // If the second physical page of the current TD is not in use,
  1276. // the buffer end physical page is the same as the first physical
  1277. // page of the TD, else the buffer end physical page is the
  1278. // second physical page currently in use.
  1279. if (td->HcTD.BE == 0)
  1280. {
  1281. td->HcTD.BE = td->HcTD.CBP +
  1282. ((frameOffset - 1) & HcPSW_OFFSET_MASK);
  1283. }
  1284. else
  1285. {
  1286. td->HcTD.BE += (frameOffset - 1) & HcPSW_OFFSET_MASK;
  1287. }
  1288. // The zero-based frameIndex was already incremented after the
  1289. // last frame was added to the current TD, so the zero-based
  1290. // FrameCount for current TD is one less than the current
  1291. // frameIndex.
  1292. td->HcTD.FrameCount = frameIndex - 1;
  1293. LOGENTRY(G, 'ITD3', td->HcTD.CBP, td->HcTD.BE, td->HcTD.FrameCount);
  1294. // Reset the current frameIndex back to zero since we are starting
  1295. // a new TD.
  1296. frameIndex = 0;
  1297. // Wrap the current frameOffset back to the first page since we
  1298. // are starting a new TD.
  1299. frameOffset &= HcPSW_OFFSET_MASK;
  1300. // Allocate another TD
  1301. td = OpenHCI_Alloc_IsoTD(DeviceData, Endpoint, td);
  1302. }
  1303. //
  1304. // If the entire transfer buffer has been mapped and built into TDs,
  1305. // we are done. This is the exit condition of the while loop.
  1306. //
  1307. if ((lengthMappedRemaining == 0) && (lengthToMap == 0))
  1308. {
  1309. break; // All Done!
  1310. }
  1311. //
  1312. // Map the next physical page, if appropriate at this point.
  1313. //
  1314. if (FrameCaseActions[frameCase].MapNextPage == framePass)
  1315. {
  1316. if (((frameLength == 0) && (lengthMappedRemaining == 0)) ||
  1317. (frameLength > lengthMappedRemaining))
  1318. {
  1319. // The currently mapped chunk of transfer buffer was either
  1320. // exactly exhausted by the current frame which was already
  1321. // added to a TD, or the remaining currently mapped chunk of
  1322. // the transfer buffer is not sufficient for the current TD
  1323. // and the next chunk of the transfer buffer needs to be
  1324. // mapped before the current frame can be added to a TD.
  1325. lengthMapped = lengthToMap;
  1326. LOGENTRY(G, 'IMP2', currentVa, lengthToMap, lengthMappedRemaining);
  1327. physAddr = IoMapTransfer(adapterObject,
  1328. mdl,
  1329. mapRegisterBase,
  1330. currentVa,
  1331. &lengthMapped,
  1332. writeToDevice);
  1333. LOGENTRY(G, 'imp2', physAddr.LowPart, lengthMapped, 0);
  1334. lengthMappedRemaining += lengthMapped;
  1335. currentVa += lengthMapped;
  1336. lengthToMap -= lengthMapped;
  1337. }
  1338. else
  1339. {
  1340. // The currently mapped chunk of the transfer buffer contains
  1341. // the next page. Advance physAddr to the next page boundary.
  1342. physAddr.LowPart &= ~HcPSW_OFFSET_MASK;
  1343. physAddr.LowPart += HcPSW_OFFSET_MASK + 1;
  1344. }
  1345. // The next physical page address better start on a page
  1346. // boundary.
  1347. //
  1348. OHCI_ASSERT((physAddr.LowPart & HcPSW_OFFSET_MASK) == 0);
  1349. }
  1350. // If we allocated the next TD or mapped the next page, we need
  1351. // to go up to the top of the loop again and initialize the new
  1352. // TD, or set the second physical page of the current TD.
  1353. //
  1354. // If we didn't allocate a new TD or map the next page, we just
  1355. // need to go back up to NextFrame: and finish the current frame
  1356. // or start a new frame
  1357. if ((FrameCaseActions[frameCase].AllocNextTD == framePass) ||
  1358. (FrameCaseActions[frameCase].MapNextPage == framePass))
  1359. {
  1360. framePass = framePassNext;
  1361. }
  1362. else
  1363. {
  1364. framePass = framePassNext;
  1365. goto NextFrame;
  1366. }
  1367. }
  1368. LOGENTRY(G, 'itrn', Transfer, packetIndex, iso->NumberOfPackets);
  1369. //
  1370. // We broke out of the while loop when the entire transfer buffer was
  1371. // mapped and built into TDs.
  1372. //
  1373. // We better have used all of the packets in the Iso Urb
  1374. //
  1375. OHCI_ASSERT(packetIndex == iso->NumberOfPackets);
  1376. iso->ErrorCount = 0;
  1377. // zero bytes transferred so far
  1378. //
  1379. Transfer->TransferBufferLength = 0;
  1380. // Set new TailP in ED
  1381. //
  1382. Endpoint->HcdTailP = td;
  1383. // put the request on the hardware queue
  1384. //
  1385. Endpoint->HcdED->HcED.TailP = td->PhysicalAddress;
  1386. }
  1387. //////////////////////////////////////////////////////////////////////
  1388. // //
  1389. // END OF ISOCHRONOUS TD BUILDING CODE //
  1390. // //
  1391. //////////////////////////////////////////////////////////////////////
  1392. IO_ALLOCATION_ACTION
  1393. OpenHCI_QueueGeneralRequest(
  1394. IN PDEVICE_OBJECT DeviceObject,
  1395. IN PIRP Invalid,
  1396. IN PVOID MapRegisterBase,
  1397. IN PVOID Context
  1398. )
  1399. /*++
  1400. Routine Description:
  1401. Queues transfers to endpoint, this is an Adapter Control routine
  1402. NOTE: for a given AdapterObject only one instance of an Adapter Control
  1403. routine may be active at any time
  1404. Our mission here is to turn the transfer in to TDs and put them on the
  1405. controllers queues.
  1406. Arguments:
  1407. DeviceObject - pointer to a device object
  1408. Irp - pointer to an I/O Request Packet (ignored)
  1409. MapRegisterBase - handle to system map registers to use
  1410. Context - pointer to URB
  1411. Return Value:
  1412. IO_ALLOCATION_ACTION DeallocateObjectKeepRegisters
  1413. --*/
  1414. {
  1415. PHCD_ENDPOINT endpoint;
  1416. PHCD_DEVICE_DATA DeviceData;
  1417. struct _URB_HCD_COMMON_TRANSFER *transfer;
  1418. PHCD_URB urb;
  1419. KIRQL oldIrql;
  1420. PIRP irp;
  1421. transfer = &((PHCD_URB) Context)->HcdUrbCommonTransfer;
  1422. endpoint = transfer->hca.HcdEndpoint;
  1423. ASSERT_ENDPOINT(endpoint);
  1424. DeviceData = endpoint->DeviceData;
  1425. urb = Context;
  1426. irp = transfer->hca.HcdIrp;
  1427. OpenHCI_KdPrintDD(DeviceData, OHCI_DBG_TD_TRACE,
  1428. ("'e: QueueGeneralRequest urb: %x\n", Context));
  1429. LOGENTRY(G, 'qGEN', urb, endpoint, irp);
  1430. // remember this value for IoFreeMapRegisters
  1431. transfer->hca.HcdExtension = MapRegisterBase;
  1432. ASSERT(transfer->Status == HCD_PENDING_STATUS_SUBMITTING);
  1433. // **
  1434. // program the transfer
  1435. // NOTE: these functions actually start the transfer on the
  1436. // adapter
  1437. // **
  1438. switch(endpoint->Type) {
  1439. case USB_ENDPOINT_TYPE_ISOCHRONOUS:
  1440. OpenHCI_IsoTransfer(DeviceData,
  1441. endpoint,
  1442. urb,
  1443. transfer);
  1444. break;
  1445. case USB_ENDPOINT_TYPE_CONTROL:
  1446. OpenHCI_ControlTransfer(DeviceData,
  1447. endpoint,
  1448. urb,
  1449. transfer);
  1450. break;
  1451. case USB_ENDPOINT_TYPE_BULK:
  1452. case USB_ENDPOINT_TYPE_INTERRUPT:
  1453. OpenHCI_BulkOrInterruptTransfer(DeviceData,
  1454. endpoint,
  1455. urb,
  1456. transfer);
  1457. break;
  1458. default:
  1459. TRAP();
  1460. }
  1461. //
  1462. // for cancel:
  1463. //
  1464. // it is possible for the transfer to be canceled before we complete
  1465. // this operation, we handle this case by checking one last time
  1466. // before we set the urb to STATUS_PENDING_SUBMITTED
  1467. //
  1468. // ie the status is HCD_PENDING_STATUS_QUEUED but the transfer is
  1469. // not on the queue ao the cancel routine will have taken
  1470. // no action.
  1471. IoAcquireCancelSpinLock(&oldIrql);
  1472. if (irp->Cancel)
  1473. {
  1474. OpenHCI_KdPrintDD(DeviceData, OHCI_DBG_TD_TRACE,
  1475. ("' Removing cancelled URB %x\n", urb));
  1476. LOGENTRY(G, 'Mcan', irp, transfer, 0);
  1477. transfer->Status = HCD_PENDING_STATUS_SUBMITTED;
  1478. // we will need to call the cancel routine ourselves
  1479. // now that the tranfser has been fully programmed
  1480. // set cancel irql so that we release the cancel spinlock
  1481. // at the proper level
  1482. irp->CancelIrql = oldIrql;
  1483. OpenHCI_CancelTransfer(DeviceObject,
  1484. irp);
  1485. // NOTE: cancel routine will release the spinlock
  1486. }
  1487. else
  1488. {
  1489. // cancel routine will know what to do
  1490. transfer->Status = HCD_PENDING_STATUS_SUBMITTED;
  1491. // The request made it through IoAllocateAdapterChannel() and
  1492. // now we own it again. Set the cancel routine again.
  1493. //
  1494. IoSetCancelRoutine(irp, OpenHCI_CancelTransfer);
  1495. IoReleaseCancelSpinLock(oldIrql);
  1496. }
  1497. OpenHCI_KdPrintDD(DeviceData,
  1498. OHCI_DBG_TD_TRACE, ("'exit QueueGenRequest\n"));
  1499. return (DeallocateObjectKeepRegisters);
  1500. }
  1501. NTSTATUS
  1502. OpenHCI_AbortEndpoint(
  1503. PDEVICE_OBJECT DeviceObject,
  1504. PIRP Irp,
  1505. PHCD_DEVICE_DATA DeviceData,
  1506. PHCD_URB Urb
  1507. )
  1508. /*++
  1509. Routine Description:
  1510. Cancel all URB's associated with this Endpoint.
  1511. --*/
  1512. {
  1513. NTSTATUS ntStatus;
  1514. PHCD_ENDPOINT endpoint;
  1515. PLIST_ENTRY entry;
  1516. struct _URB_HCD_COMMON_TRANSFER *transfer;
  1517. PHCD_URB urb;
  1518. KIRQL oldIrq;
  1519. PHC_OPERATIONAL_REGISTER HC;
  1520. LIST_ENTRY QueuedListHead;
  1521. ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
  1522. endpoint = Urb->HcdUrbAbortEndpoint.HcdEndpoint;
  1523. ASSERT_ENDPOINT(endpoint);
  1524. OpenHCI_KdPrintDD(DeviceData,
  1525. OHCI_DBG_CANCEL_TRACE, ("'Abort Endpoint \n"));
  1526. LOGENTRY(G, '>ABR', endpoint, 0, 0);
  1527. HC = DeviceData->HC;
  1528. if (READ_REGISTER_ULONG(&HC->HcRevision.ul) == 0xFFFFFFFF)
  1529. {
  1530. OpenHCI_KdPrint((0, "'AbortEndpoint, controller not there!\n"));
  1531. // The assumption here is that if the controller disappeared,
  1532. // it disappeared while the machine was suspended and no transfers
  1533. // should have been queued at that time. Also, all transfers that
  1534. // were submitted after the machine resumed without the controller
  1535. // were immediately failed. If those assumptions are true, we
  1536. // don't have to do anything except complete the Abort Irp.
  1537. //
  1538. // If we want to handle the general case of surprise removing the
  1539. // host controller, there might actually be queued transfers we
  1540. // need to cleanup somehow.
  1541. //
  1542. OpenHCI_CompleteIrp(DeviceObject, Irp, STATUS_SUCCESS);
  1543. return STATUS_SUCCESS;
  1544. }
  1545. // Remove all of the transfers which are queued on the software queue
  1546. // for this endpoint and which are not yet active on the hardware.
  1547. //
  1548. InitializeListHead(&QueuedListHead);
  1549. IoAcquireCancelSpinLock(&oldIrq);
  1550. KeAcquireSpinLockAtDpcLevel(&endpoint->QueueLock);
  1551. while (!IsListEmpty(&endpoint->RequestQueue))
  1552. {
  1553. entry = RemoveHeadList(&endpoint->RequestQueue);
  1554. InsertTailList(&QueuedListHead, entry);
  1555. urb = CONTAINING_RECORD(entry,
  1556. HCD_URB,
  1557. HcdUrbCommonTransfer.hca.HcdListEntry);
  1558. transfer = &urb->HcdUrbCommonTransfer;
  1559. IoSetCancelRoutine(transfer->hca.HcdIrp, NULL);
  1560. LOGENTRY(G, 'rABR', urb, transfer, transfer->hca.HcdIrp);
  1561. OpenHCI_KdPrintDD(DeviceData, OHCI_DBG_CANCEL_NOISE,
  1562. ("'URB 0x%x on endpoint 0x%x\n", urb, endpoint));
  1563. }
  1564. KeReleaseSpinLockFromDpcLevel(&endpoint->QueueLock);
  1565. IoReleaseCancelSpinLock(oldIrq);
  1566. // Now complete all of the transfers which were queued on the software
  1567. // queue.
  1568. //
  1569. while (!IsListEmpty(&QueuedListHead))
  1570. {
  1571. entry = RemoveHeadList(&QueuedListHead);
  1572. urb = CONTAINING_RECORD(entry,
  1573. HCD_URB,
  1574. HcdUrbCommonTransfer.hca.HcdListEntry);
  1575. transfer = &urb->HcdUrbCommonTransfer;
  1576. transfer->hca.HcdListEntry.Flink = NULL;
  1577. transfer->hca.HcdListEntry.Blink = NULL;
  1578. transfer->Status = USBD_STATUS_CANCELED;
  1579. transfer->TransferBufferLength = 0;
  1580. LOGENTRY(G, 'qABR', urb, transfer, transfer->hca.HcdIrp);
  1581. OpenHCI_CompleteIrp(DeviceObject,
  1582. transfer->hca.HcdIrp,
  1583. STATUS_CANCELLED);
  1584. }
  1585. // Now pause the endpoint, which will cause OpenHCI_IsrDPC() to call
  1586. // OpenHCI_CancelTDsForED() to complete all of the transfer which were
  1587. // active on the hardware.
  1588. //
  1589. KeAcquireSpinLock(&DeviceData->PausedSpin, &oldIrq);
  1590. if (endpoint->EpFlags & EP_ROOT_HUB) {
  1591. ntStatus = STATUS_SUCCESS;
  1592. LOGENTRY(G, 'cAbr', Irp, endpoint, 0);
  1593. KeReleaseSpinLock(&DeviceData->PausedSpin, oldIrq);
  1594. OpenHCI_CompleteIrp(DeviceObject, Irp, STATUS_SUCCESS);
  1595. } else {
  1596. SET_EPFLAG(endpoint, EP_ABORT);
  1597. LOGENTRY(G, 'pAbr', Irp, endpoint, 0);
  1598. IoMarkIrpPending(Irp);
  1599. ntStatus =
  1600. Irp->IoStatus.Status = STATUS_PENDING;
  1601. endpoint->AbortIrp = Irp;
  1602. KeReleaseSpinLock(&DeviceData->PausedSpin, oldIrq);
  1603. OpenHCI_PauseED(endpoint);
  1604. }
  1605. return ntStatus;
  1606. }
  1607. PHYSICAL_ADDRESS
  1608. OpenHCI_IoMapTransfer(
  1609. IN PMAP_CONTEXT MapContext,
  1610. IN PDMA_ADAPTER DmaAdapter,
  1611. IN PMDL Mdl,
  1612. IN PVOID MapRegisterBase,
  1613. IN PVOID CurrentVa,
  1614. IN OUT PULONG Length,
  1615. IN ULONG TotalLength,
  1616. IN BOOLEAN WriteToDevice
  1617. )
  1618. /*++
  1619. Routine Description:
  1620. Our goal here is to call IoMapTransfer once for the whole
  1621. buffer, subsequent calls just return offsets to the mapped
  1622. buffer.
  1623. --*/
  1624. {
  1625. PHYSICAL_ADDRESS PhysAddress;
  1626. if (!MapContext->Mapped) {
  1627. // first call attempts to map the
  1628. // entire buffer
  1629. LOGENTRY(G, 'mpIT', TotalLength, *Length, MapContext->Flags);
  1630. if (MapContext->Flags & OHCI_MAP_INIT) {
  1631. MapContext->LengthMapped =
  1632. MapContext->TotalLength;
  1633. LOGENTRY(G, 'mIT2', MapContext->TotalLength, *Length, MapContext->Flags);
  1634. } else {
  1635. MapContext->Flags |= OHCI_MAP_INIT;
  1636. MapContext->MapRegisterBase =
  1637. MapRegisterBase;
  1638. MapContext->LengthMapped =
  1639. MapContext->TotalLength = TotalLength;
  1640. LOGENTRY(G, 'mIT1', MapContext->TotalLength, *Length, MapContext->Flags);
  1641. }
  1642. MapContext->CurrentVa = CurrentVa;
  1643. LOGENTRY(G, 'cIOM', Mdl, MapContext->MapRegisterBase, MapContext->CurrentVa);
  1644. MapContext->PhysAddress =
  1645. IoMapTransfer(DmaAdapter,
  1646. Mdl,
  1647. MapContext->MapRegisterBase,
  1648. MapContext->CurrentVa,
  1649. &MapContext->LengthMapped,
  1650. WriteToDevice);
  1651. MapContext->Mapped = TRUE;
  1652. MapContext->TotalLength -=
  1653. MapContext->LengthMapped;
  1654. LOGENTRY(G, 'mped', MapContext->LengthMapped,
  1655. MapContext->CurrentVa, *Length);
  1656. // OK, we mapped it, the caller will may have requested less
  1657. // if so adjust the values and prepare for the next call
  1658. if (*Length < MapContext->LengthMapped) {
  1659. // caller requested less
  1660. LOGENTRY(G, 'mpls', MapContext->LengthMapped,
  1661. MapContext->CurrentVa, *Length);
  1662. MapContext->LengthMapped -= *Length;
  1663. MapContext->CurrentVa = CurrentVa;
  1664. MapRegisterBase = MapContext->MapRegisterBase;
  1665. PhysAddress = MapContext->PhysAddress;
  1666. MapContext->PhysAddress.QuadPart += *Length;
  1667. //TEST_TRAP();
  1668. } else {
  1669. // we mapped exactly what the caller asked for
  1670. LOGENTRY(G, 'mpxa', MapContext->LengthMapped,
  1671. MapContext->CurrentVa, *Length);
  1672. OHCI_ASSERT(*Length == MapContext->LengthMapped);
  1673. MapContext->Mapped = FALSE;
  1674. CurrentVa = MapContext->CurrentVa;
  1675. MapRegisterBase = MapContext->MapRegisterBase;
  1676. PhysAddress = MapContext->PhysAddress;
  1677. }
  1678. } else {
  1679. // we can satisfy this request based on the last call,
  1680. // just bump currentVa and return parms.
  1681. LOGENTRY(G, 'mpco', CurrentVa, *Length, MapContext->LengthMapped);
  1682. MapContext->CurrentVa = CurrentVa;
  1683. MapRegisterBase = MapContext->MapRegisterBase;
  1684. MapContext->LengthMapped -= *Length;
  1685. // adjust the Phys Address
  1686. PhysAddress = MapContext->PhysAddress;
  1687. MapContext->PhysAddress.QuadPart += *Length;
  1688. //TEST_TRAP();
  1689. if (MapContext->LengthMapped == 0) {
  1690. // we have used everything we mapped,
  1691. // next time in call IoMapTransfer again
  1692. LOGENTRY(G, 'mall', 0, *Length, MapContext->LengthMapped);
  1693. MapContext->Mapped = FALSE;
  1694. //TEST_TRAP();
  1695. }
  1696. }
  1697. LOGENTRY(G, 'mpDN', MapContext, PhysAddress.HighPart, PhysAddress.LowPart);
  1698. return PhysAddress;
  1699. }