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

337 lines
9.0 KiB

  1. /*++
  2. Copyright (c) 1999, 2000 Microsoft Corporation
  3. Module Name:
  4. async.c
  5. Abstract:
  6. miniport transfer code for sstool (single step tool) interface
  7. Environment:
  8. kernel mode only
  9. Notes:
  10. THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  11. KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  12. IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  13. PURPOSE.
  14. Copyright (c) 1999, 2000 Microsoft Corporation. All Rights Reserved.
  15. Revision History:
  16. 1-1-00 : created, jdunn
  17. --*/
  18. #include "common.h"
  19. typedef struct _SS_PACKET_CONTEXT {
  20. MP_HW_POINTER Qh;
  21. MP_HW_POINTER Td;
  22. MP_HW_POINTER Data;
  23. ULONG padTo8[2];
  24. } SS_PACKET_CONTEXT, *PSS_PACKET_CONTEXT;
  25. #define EHCI_TEST_TD_ALIGNMENT 256
  26. C_ASSERT((sizeof(SS_PACKET_CONTEXT) <= EHCI_TEST_TD_ALIGNMENT));
  27. C_ASSERT((sizeof(HCD_QUEUEHEAD_DESCRIPTOR) <= EHCI_TEST_TD_ALIGNMENT));
  28. C_ASSERT((sizeof(HCD_TRANSFER_DESCRIPTOR) <= EHCI_TEST_TD_ALIGNMENT));
  29. //implements the following miniport functions:
  30. //non paged
  31. //EHCI_StartSendOnePacket
  32. //EHCI_EndSendOnePacket
  33. USB_MINIPORT_STATUS
  34. USBMPFN
  35. EHCI_StartSendOnePacket(
  36. PDEVICE_DATA DeviceData,
  37. PMP_PACKET_PARAMETERS PacketParameters,
  38. PUCHAR PacketData,
  39. PULONG PacketLength,
  40. PUCHAR WorkspaceVirtualAddress,
  41. HW_32BIT_PHYSICAL_ADDRESS WorkspacePhysicalAddress,
  42. ULONG WorkSpaceLength,
  43. OUT USBD_STATUS *UsbdStatus
  44. )
  45. /*++
  46. Routine Description:
  47. insert structures to transmit a single packet -- this is for debug
  48. tool purposes only so we can be a little creative here.
  49. Arguments:
  50. Return Value:
  51. --*/
  52. {
  53. PHC_OPERATIONAL_REGISTER hcOp;
  54. PHCD_QUEUEHEAD_DESCRIPTOR qh;
  55. PHCD_TRANSFER_DESCRIPTOR td;
  56. PUCHAR pch, data;
  57. PSS_PACKET_CONTEXT context;
  58. HW_LINK_POINTER hwQh, tdLink;
  59. ULONG phys, qhPhys, tdPhys, dataPhys, i;
  60. ULONG siz;
  61. hcOp = DeviceData->OperationalRegisters;
  62. // allocate an TD from the scratch space and
  63. // initialize it
  64. phys = WorkspacePhysicalAddress;
  65. pch = WorkspaceVirtualAddress;
  66. LOGENTRY(DeviceData, G, '_ssS', phys, 0, pch);
  67. // specify a TD alignment to work around HW bugs.
  68. siz = EHCI_TEST_TD_ALIGNMENT;
  69. context = (PSS_PACKET_CONTEXT) pch;
  70. pch += siz;
  71. phys += siz;
  72. // carve out a qh
  73. qhPhys = phys;
  74. qh = (PHCD_QUEUEHEAD_DESCRIPTOR) pch;
  75. pch += siz;
  76. phys += siz;
  77. LOGENTRY(DeviceData, G, '_ssQ', qh, 0, qhPhys);
  78. // carve out a TD
  79. tdPhys = phys;
  80. td = (PHCD_TRANSFER_DESCRIPTOR) pch;
  81. pch += siz;
  82. phys += siz;
  83. LOGENTRY(DeviceData, G, '_ssT', td, 0, tdPhys);
  84. // use the rest for data
  85. LOGENTRY(DeviceData, G, '_ssD', PacketData, *PacketLength, 0);
  86. dataPhys = phys;
  87. data = pch;
  88. RtlCopyMemory(data, PacketData, *PacketLength);
  89. pch+=*PacketLength;
  90. phys+=*PacketLength;
  91. // init qh
  92. RtlZeroMemory(qh, sizeof(*qh));
  93. qh->PhysicalAddress = qhPhys;
  94. ENDPOINT_DATA_PTR(qh->EndpointData) = NULL;
  95. qh->Sig = SIG_HCD_DQH;
  96. hwQh.HwAddress = qh->PhysicalAddress;
  97. SET_QH(hwQh.HwAddress);
  98. //qh->HwQH.EpChars.HeadOfReclimationList = 1;
  99. // manual Toggle
  100. qh->HwQH.EpChars.DataToggleControl = HcEPCHAR_Toggle_From_qTD;
  101. // init the hw descriptor
  102. qh->HwQH.EpChars.DeviceAddress =
  103. PacketParameters->DeviceAddress;
  104. qh->HwQH.EpChars.EndpointNumber =
  105. PacketParameters->EndpointAddress;
  106. qh->HwQH.EpCaps.HighBWPipeMultiplier = 1;
  107. qh->HwQH.EpCaps.HubAddress = 0;
  108. qh->HwQH.EpCaps.PortNumber = 0;
  109. // link back to ourselves
  110. //qh->HwQH.HLink.HwAddress = hwQh.HwAddress;
  111. switch (PacketParameters->Speed) {
  112. case ss_Low:
  113. qh->HwQH.EpChars.EndpointSpeed = HcEPCHAR_LowSpeed;
  114. qh->HwQH.EpCaps.HubAddress = PacketParameters->HubDeviceAddress;
  115. qh->HwQH.EpCaps.PortNumber = PacketParameters->PortTTNumber;
  116. break;
  117. case ss_Full:
  118. qh->HwQH.EpChars.EndpointSpeed = HcEPCHAR_FullSpeed;
  119. qh->HwQH.EpCaps.HubAddress = PacketParameters->HubDeviceAddress;
  120. qh->HwQH.EpCaps.PortNumber = PacketParameters->PortTTNumber;
  121. break;
  122. case ss_High:
  123. qh->HwQH.EpChars.EndpointSpeed = HcEPCHAR_HighSpeed;
  124. break;
  125. default:
  126. USBPORT_BUGCHECK(DeviceData);
  127. }
  128. // jdxxx
  129. //qh->HwQH.EpChars.EndpointSpeed = HcEPCHAR_HighSpeed;
  130. qh->HwQH.EpChars.MaximumPacketLength =
  131. PacketParameters->MaximumPacketSize;
  132. // init td
  133. RtlZeroMemory(td, sizeof(*td));
  134. for (i=0; i<5; i++) {
  135. td->HwTD.BufferPage[i].ul = 0x0badf000;
  136. }
  137. td->PhysicalAddress = tdPhys;
  138. td->Sig = SIG_HCD_TD;
  139. switch(PacketParameters->Type) {
  140. case ss_Setup:
  141. LOGENTRY(DeviceData, G, '_sSU', 0, 0, 0);
  142. td->HwTD.Token.Pid = HcTOK_Setup;
  143. break;
  144. case ss_In:
  145. LOGENTRY(DeviceData, G, '_ssI', 0, 0, 0);
  146. td->HwTD.Token.Pid = HcTOK_In;
  147. break;
  148. case ss_Out:
  149. td->HwTD.Token.Pid = HcTOK_Out;
  150. LOGENTRY(DeviceData, G, '_ssO', 0, 0, 0);
  151. break;
  152. case ss_Iso_In:
  153. break;
  154. case ss_Iso_Out:
  155. break;
  156. }
  157. switch(PacketParameters->Toggle) {
  158. case ss_Toggle0:
  159. td->HwTD.Token.DataToggle = HcTOK_Toggle0;
  160. break;
  161. case ss_Toggle1:
  162. td->HwTD.Token.DataToggle = HcTOK_Toggle1;
  163. break;
  164. }
  165. // prime the overlay with td so that this td
  166. // becomes the current td.
  167. qh->HwQH.Overlay.qTD.Next_qTD.HwAddress =
  168. td->PhysicalAddress;
  169. td->HwTD.Token.Active = 1;
  170. td->HwTD.Token.ErrorCounter = PacketParameters->ErrorCount;
  171. // point TD at the data
  172. td->HwTD.BufferPage[0].ul = dataPhys;
  173. td->HwTD.Token.BytesToTransfer = *PacketLength;
  174. tdLink.HwAddress = 0;
  175. SET_T_BIT(tdLink.HwAddress);
  176. td->HwTD.Next_qTD.HwAddress = tdLink.HwAddress;
  177. td->HwTD.AltNext_qTD.HwAddress = tdLink.HwAddress;
  178. QH_DESCRIPTOR_PTR(context->Qh) = qh;
  179. TRANSFER_DESCRIPTOR_PTR(context->Td) = td;
  180. HW_PTR(context->Data) = data;
  181. *UsbdStatus = USBD_STATUS_SUCCESS;
  182. // stick the QH in the schedule and wait for it to complete
  183. // swap the async qh, wait one frame then
  184. // replace the old value.
  185. // NOTE: This will interrupt normal bus operation for one ms
  186. //WRITE_REGISTER_ULONG(&hcOp->AsyncListAddr, hwQh.HwAddress);
  187. EHCI_InsertQueueHeadInAsyncList(DeviceData, qh);
  188. EHCI_EnableAsyncList(DeviceData);
  189. return USBMP_STATUS_SUCCESS;
  190. }
  191. USB_MINIPORT_STATUS
  192. USBMPFN
  193. EHCI_EndSendOnePacket(
  194. PDEVICE_DATA DeviceData,
  195. PMP_PACKET_PARAMETERS PacketParameters,
  196. PUCHAR PacketData,
  197. PULONG PacketLength,
  198. PUCHAR WorkspaceVirtualAddress,
  199. HW_32BIT_PHYSICAL_ADDRESS WorkspacePhysicalAddress,
  200. ULONG WorkSpaceLength,
  201. OUT USBD_STATUS *UsbdStatus
  202. )
  203. /*++
  204. Routine Description:
  205. Arguments:
  206. Return Value:
  207. --*/
  208. {
  209. PHC_OPERATIONAL_REGISTER hcOp;
  210. PUCHAR pch;
  211. PSS_PACKET_CONTEXT context;
  212. HW_LINK_POINTER asyncHwQh;
  213. PHCD_QUEUEHEAD_DESCRIPTOR qh;
  214. PHCD_TRANSFER_DESCRIPTOR td;
  215. PUCHAR data;
  216. LOGENTRY(DeviceData, G, '_ssE', 0, 0, 0);
  217. hcOp = DeviceData->OperationalRegisters;
  218. context = (PSS_PACKET_CONTEXT) WorkspaceVirtualAddress;
  219. qh = QH_DESCRIPTOR_PTR(context->Qh);
  220. td = TRANSFER_DESCRIPTOR_PTR(context->Td);
  221. data = HW_PTR(context->Data);
  222. LOGENTRY(DeviceData, G, '_sE2', qh, td, *PacketLength );
  223. asyncHwQh.HwAddress = DeviceData->AsyncQueueHead->PhysicalAddress;
  224. SET_QH(asyncHwQh.HwAddress);
  225. *PacketLength = *PacketLength - td->HwTD.Token.BytesToTransfer;
  226. LOGENTRY(DeviceData, G, '_sE3', td->HwTD.Token.BytesToTransfer, td,
  227. *PacketLength );
  228. RtlCopyMemory(PacketData, data, *PacketLength);
  229. EHCI_DisableAsyncList(DeviceData);
  230. EHCI_RemoveQueueHeadFromAsyncList(DeviceData, qh);
  231. // WRITE_REGISTER_ULONG(&hcOp->AsyncListAddr, asyncHwQh.HwAddress);
  232. // return the error here
  233. *UsbdStatus = USBD_STATUS_SUCCESS;
  234. if (td->HwTD.Token.Halted == 1) {
  235. if (td->HwTD.Token.XactErr) {
  236. *UsbdStatus = USBD_STATUS_XACT_ERROR;
  237. } else if (td->HwTD.Token.BabbleDetected) {
  238. *UsbdStatus = USBD_STATUS_BABBLE_DETECTED;
  239. } else if (td->HwTD.Token.DataBufferError) {
  240. *UsbdStatus = USBD_STATUS_DATA_BUFFER_ERROR;
  241. } else {
  242. *UsbdStatus = USBD_STATUS_STALL_PID;
  243. }
  244. }
  245. EHCI_KdPrint((DeviceData, 1, "'Status.XactErr %d\n",
  246. td->HwTD.Token.XactErr));
  247. EHCI_KdPrint((DeviceData, 1, "'Status.BabbleDetected %d\n",
  248. td->HwTD.Token.BabbleDetected));
  249. EHCI_KdPrint((DeviceData, 1, "'Status.DataBufferError %d\n",
  250. td->HwTD.Token.DataBufferError));
  251. return USBMP_STATUS_SUCCESS;
  252. }