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.

1185 lines
31 KiB

  1. /*++
  2. Copyright (c) 1999, 2000 Microsoft Corporation
  3. Module Name:
  4. usbuhci.h
  5. Abstract:
  6. Environment:
  7. Kernel & user mode
  8. Revision History:
  9. 1-1-00 : created
  10. --*/
  11. #ifndef __USBUHCI_H__
  12. #define __USBUHCI_H__
  13. #define FIXPIIX4
  14. #define SOF_TD_COUNT 8
  15. #define ANY_VIA(dd) ((dd)->ControllerFlavor >= UHCI_VIA)
  16. #define MASK_CHANGE_BITS(p)\
  17. do {\
  18. (p).PortEnableChange = 0;\
  19. (p).PortConnectChange = 0;\
  20. } while (0);
  21. /*
  22. define resource consumption for endpoints types
  23. */
  24. #define T_64K 0x10000
  25. #define T_16K 0x4000
  26. #define T_4K 0x1000
  27. // Control:
  28. // largest possible transfer for control is 64k
  29. // therefore we support up to 2 transfers of this
  30. // size in HW. Most control transfers are much
  31. // smaller than this.
  32. // NOTE: we MUST support at least one 64k transfer in
  33. // HW since a single control transfer cannot be
  34. // broken up.
  35. //#define MAX_CONTROL_TRANSFER_SIZE T_4K
  36. #define MAX_ASYNC_PACKET_SIZE 64
  37. //#define MAX_CONTROL_DOUBLE_BUFFERS MAX_CONTROL_TRANSFER_SIZE/PAGE_SIZE
  38. //#define TDS_PER_CONTROL_ENDPOINT (MAX_CONTROL_TRANSFER_SIZE/MAX_CONTROL_PACKET_SIZE+2) // 2 EXTRA FOR SETUP AND STATUS
  39. // Bulk:
  40. // bugbug temprarily set to 64k
  41. #define MAX_BULK_TRANSFER_SIZE T_4K
  42. //#define MAX_BULK_TRANSFER_SIZE T_4K // T_16K // T_64K
  43. //#define MAX_BULK_PACKET_SIZE 64
  44. #define MAX_BULK_DOUBLE_BUFFERS MAX_BULK_TRANSFER_SIZE/PAGE_SIZE
  45. #define TDS_PER_BULK_ENDPOINT (MAX_BULK_TRANSFER_SIZE/MAX_BULK_PACKET_SIZE)
  46. // Interrupt:
  47. //#define MAX_INTERRUPT_TRANSFER_SIZE T_4K // T_16K
  48. //#define MAX_INTERRUPT_PACKET_SIZE 64
  49. //#define MAX_INTERRUPT_DOUBLE_BUFFERS MAX_INTERRUPT_TRANSFER_SIZE/PAGE_SIZE
  50. //#define TDS_PER_INTERRUPT_ENDPOINT (MAX_INTERRUPT_TRANSFER_SIZE/MAX_INTERRUPT_PACKET_SIZE)
  51. #define MAX_INTERRUPT_TDS_PER_TRANSFER 8
  52. // Isochronous:
  53. #define MAX_ISOCH_TRANSFER_SIZE T_64K
  54. #define MAX_ISOCH_PACKET_SIZE 1023
  55. //#define MAX_ISOCH_DOUBLE_BUFFERS MAX_ISOCH_TRANSFER_SIZE/PAGE_SIZE
  56. //#define TDS_PER_ISOCH_ENDPOINT 1024
  57. // Maximum Polling Interval we support for interrupt (ms)
  58. #define MAX_INTERVAL 32
  59. #define MAX_INTERVAL_MASK(i) (i&0x1f)
  60. // default size of frame list
  61. #define UHCI_MAX_FRAME 1024
  62. #define ACTUAL_FRAME(f) ((f)&0x000003FF)
  63. //
  64. // These values index in to the interrupt QH list
  65. //
  66. #define QH_INTERRUPT_1ms 0
  67. #define QH_INTERRUPT_2ms 1
  68. #define QH_INTERRUPT_4ms 3
  69. #define QH_INTERRUPT_8ms 7
  70. #define QH_INTERRUPT_16ms 15
  71. #define QH_INTERRUPT_32ms 31
  72. #define QH_INTERRUPT_INDEX(x) (x)-1
  73. #define NO_INTERRUPT_INTERVALS 6
  74. #define NO_INTERRUPT_QH_LISTS 63
  75. // debug signatures
  76. #define SIG_HCD_IQH 'qi01'
  77. #define SIG_HCD_CQH 'qa01'
  78. #define SIG_HCD_BQH 'qb01'
  79. #define SIG_HCD_QH 'hq01'
  80. #define SIG_HCD_DQH 'qd01'
  81. #define SIG_HCD_TD 'dt01'
  82. #define SIG_HCD_RTD 'dtlr'
  83. #define SIG_HCD_SOFTD 'dtos'
  84. #define SIG_HCD_ADB 'bd01'
  85. #define SIG_HCD_IDB 'id01'
  86. #define SIG_EP_DATA 'pe01'
  87. #define SIG_UHCI_TRANSFER 'rt01'
  88. #define SIG_UHCI_DD 'ichu'
  89. // What gets returned by READ_PORT_USHORT when hardware is surprise removed.
  90. #define UHCI_HARDWARE_GONE 0xffff
  91. #undef PDEVICE_DATA
  92. typedef struct _TRANSFER_CONTEXT {
  93. ULONG Sig;
  94. ULONG PendingTds;
  95. PTRANSFER_PARAMETERS TransferParameters;
  96. USBD_STATUS UsbdStatus;
  97. ULONG BytesTransferred;
  98. struct _ENDPOINT_DATA *EndpointData;
  99. PMINIPORT_ISO_TRANSFER IsoTransfer;
  100. } TRANSFER_CONTEXT, *PTRANSFER_CONTEXT;
  101. // HCD Endpoint Descriptor (contains the HW descriptor)
  102. // values for HCD_QUEUEHEAD_DESCRIPTOR.Flags
  103. #define UHCI_QH_FLAG_IN_SCHEDULE 0x00000001
  104. #define UHCI_QH_FLAG_QH_REMOVED 0x00000002
  105. struct _ENDPOINT_DATA;
  106. typedef struct _HCD_QUEUEHEAD_DESCRIPTOR {
  107. HW_QUEUE_HEAD HwQH; // 2 dwords
  108. HW_32BIT_PHYSICAL_ADDRESS PhysicalAddress;
  109. ULONG Sig;
  110. ULONG QhFlags;
  111. struct _HCD_QUEUEHEAD_DESCRIPTOR *NextQh;
  112. struct _HCD_QUEUEHEAD_DESCRIPTOR *PrevQh;
  113. struct _ENDPOINT_DATA *EndpointData;
  114. #ifdef _WIN64
  115. ULONG PadTo64[4];
  116. #else
  117. ULONG PadTo64[8];
  118. #endif
  119. } HCD_QUEUEHEAD_DESCRIPTOR, *PHCD_QUEUEHEAD_DESCRIPTOR;
  120. C_ASSERT((sizeof(HCD_QUEUEHEAD_DESCRIPTOR) == 64));
  121. //
  122. // HCD Transfer Descriptor (contains the HW descriptor)
  123. //
  124. #define ENDPOINT_DATA_PTR(p) ((struct _ENDPOINT_DATA *) (p).Pointer)
  125. #define TRANSFER_CONTEXT_PTR(p) ((struct _TRANSFER_CONTEXT *) (p).Pointer)
  126. #define TRANSFER_DESCRIPTOR_PTR(p) ((struct _HCD_TRANSFER_DESCRIPTOR *) (p).Pointer)
  127. #define QH_DESCRIPTOR_PTR(p) ((struct _HCD_QUEUEHEAD_DESCRIPTOR *) (p).Pointer)
  128. #define HW_PTR(p) ((UCHAR * ) (p).Pointer)
  129. #define DB_FLAG_BUSY 0x00000001
  130. typedef struct _TRANSFER_BUFFER_HEADER {
  131. HW_32BIT_PHYSICAL_ADDRESS PhysicalAddress;
  132. PUCHAR SystemAddress;
  133. ULONG Sig;
  134. ULONG Flags;
  135. ULONG Size;
  136. #ifdef _WIN64
  137. ULONG PadTo32[1];
  138. #else
  139. ULONG PadTo32[3];
  140. #endif
  141. } TRANSFER_BUFFER_HEADER, *PTRANSFER_BUFFER_HEADER;
  142. C_ASSERT((sizeof(TRANSFER_BUFFER_HEADER) == 32));
  143. //
  144. // NOTE: The buffer must go first, since the physical address
  145. // depends on it. If not, you must change the init code.
  146. //
  147. typedef struct _ASYNC_TRANSFER_BUFFER {
  148. UCHAR Buffer[MAX_ASYNC_PACKET_SIZE];
  149. TRANSFER_BUFFER_HEADER;
  150. } ASYNC_TRANSFER_BUFFER, *PASYNC_TRANSFER_BUFFER;
  151. C_ASSERT((sizeof(ASYNC_TRANSFER_BUFFER) == 64+32));
  152. typedef struct _ISOCH_TRANSFER_BUFFER {
  153. UCHAR Buffer[MAX_ISOCH_PACKET_SIZE+1]; // bump it to 1024
  154. TRANSFER_BUFFER_HEADER;
  155. } ISOCH_TRANSFER_BUFFER, *PISOCH_TRANSFER_BUFFER;
  156. C_ASSERT((sizeof(ISOCH_TRANSFER_BUFFER) == 1024+32));
  157. typedef union _TRANSFER_BUFFER {
  158. ISOCH_TRANSFER_BUFFER Isoch;
  159. ASYNC_TRANSFER_BUFFER Async;
  160. } TRANSFER_BUFFER, *PTRANSFER_BUFFER;
  161. typedef struct _DOUBLE_BUFFER_LIST {
  162. union {
  163. ASYNC_TRANSFER_BUFFER Async[1];
  164. ISOCH_TRANSFER_BUFFER Isoch[1];
  165. };
  166. } DOUBLE_BUFFER_LIST, *PDOUBLE_BUFFER_LIST;
  167. // values for HCD_TRANSFER_DESCRIPTOR.Flags
  168. #define TD_FLAG_BUSY 0x00000001
  169. #define TD_FLAG_XFER 0x00000002
  170. //#define TD_FLAG_CONTROL_STATUS 0x00000004
  171. #define TD_FLAG_DONE 0x00000008
  172. #define TD_FLAG_SKIP 0x00000010
  173. #define TD_FLAG_DOUBLE_BUFFERED 0x00000020
  174. #define TD_FLAG_ISO_QUEUED 0x00000040
  175. #define TD_FLAG_SETUP_TD 0x00000100
  176. #define TD_FLAG_DATA_TD 0x00000200
  177. #define TD_FLAG_STATUS_TD 0x00000400
  178. #define TD_FLAG_TIMEOUT_ERROR 0x00000800
  179. typedef struct _HCD_TRANSFER_DESCRIPTOR {
  180. HW_QUEUE_ELEMENT_TD HwTD;
  181. HW_32BIT_PHYSICAL_ADDRESS PhysicalAddress;
  182. ULONG Sig;
  183. union {
  184. PTRANSFER_CONTEXT TransferContext;
  185. ULONG RequestFrame;
  186. };
  187. PMINIPORT_ISO_PACKET IsoPacket;
  188. ULONG Flags;
  189. struct _HCD_TRANSFER_DESCRIPTOR *NextTd;
  190. PTRANSFER_BUFFER DoubleBuffer;
  191. LIST_ENTRY DoneLink;
  192. #ifdef _WIN64
  193. ULONG PadTo128[12];
  194. #else
  195. ULONG PadTo64[3];
  196. #endif
  197. } HCD_TRANSFER_DESCRIPTOR, *PHCD_TRANSFER_DESCRIPTOR;
  198. #ifdef _WIN64
  199. C_ASSERT((sizeof(HCD_TRANSFER_DESCRIPTOR) == 128));
  200. #else
  201. C_ASSERT((sizeof(HCD_TRANSFER_DESCRIPTOR) == 64));
  202. #endif
  203. typedef struct _HCD_TD_LIST {
  204. HCD_TRANSFER_DESCRIPTOR Td[1];
  205. } HCD_TD_LIST, *PHCD_TD_LIST;
  206. #define UHCI_EDFLAG_HALTED 0x00000001
  207. #define UHCI_EDFLAG_SHORT_PACKET 0x00000002
  208. #define UHCI_EDFLAG_NOHALT 0x00000004
  209. typedef struct _ENDPOINT_DATA {
  210. ULONG Sig;
  211. ULONG Flags;
  212. ENDPOINT_PARAMETERS Parameters;
  213. PHCD_QUEUEHEAD_DESCRIPTOR QueueHead;
  214. ULONG PendingTransfers;
  215. ULONG MaxPendingTransfers;
  216. PHCD_TRANSFER_DESCRIPTOR TailTd;
  217. PHCD_TRANSFER_DESCRIPTOR HeadTd;
  218. //
  219. // Transfer descriptor cache.
  220. //
  221. PHCD_TD_LIST TdList;
  222. ULONG TdCount;
  223. ULONG TdLastAllocced;
  224. ULONG TdsUsed;
  225. //
  226. // Double buffer cache.
  227. //
  228. PDOUBLE_BUFFER_LIST DbList;
  229. ULONG DbCount;
  230. ULONG DbLastAllocced;
  231. ULONG DbsUsed;
  232. ULONG MaxErrorCount;
  233. ULONG Toggle;
  234. LIST_ENTRY DoneTdList;
  235. } ENDPOINT_DATA, *PENDPOINT_DATA;
  236. #define UHCI_NUMBER_PORTS 2
  237. #define UHCI_DDFLAG_USBBIOS 0x00000001
  238. #define UHCI_DDFLAG_SUSPENDED 0x00000002
  239. #define UHCI_HC_MAX_ERRORS 0x10
  240. typedef struct _DEVICE_DATA {
  241. ULONG Sig;
  242. ULONG Flags;
  243. PHC_REGISTER Registers;
  244. ULONG HCErrorCount;
  245. // Save the command register thru power downs
  246. USBCMD SuspendCommandReg;
  247. FRNUM SuspendFrameNumber;
  248. FRBASEADD SuspendFrameListBasePhys;
  249. USBINTR SuspendInterruptEnable;
  250. USBINTR EnabledInterrupts;
  251. ULONG IsoPendingTransfers;
  252. //
  253. // Base queue head that we link all control/bulk transfer
  254. // queues to.
  255. //
  256. USB_CONTROLLER_FLAVOR ControllerFlavor;
  257. // ULONG LastFrameCounter;
  258. ULONG FrameNumberHighPart;
  259. ULONG LastFrameProcessed;
  260. ULONG SynchronizeIsoCleanup;
  261. ULONG PortInReset;
  262. ULONG PortResetChange;
  263. ULONG PortSuspendChange;
  264. ULONG PortOvercurrentChange;
  265. BOOLEAN PortResuming[UHCI_NUMBER_PORTS];
  266. USHORT IrqStatus;
  267. USHORT PortPowerControl;
  268. PHW_32BIT_PHYSICAL_ADDRESS FrameListVA;
  269. HW_32BIT_PHYSICAL_ADDRESS FrameListPA;
  270. // Virtual Addresses for the control and bulk queue heads in the
  271. // schedule.
  272. PHCD_QUEUEHEAD_DESCRIPTOR ControlQueueHead;
  273. PHCD_QUEUEHEAD_DESCRIPTOR BulkQueueHead;
  274. PHCD_QUEUEHEAD_DESCRIPTOR LastBulkQueueHead;
  275. // Virtual Addresses for the interrupt queue heads in the
  276. // schedule.
  277. PHCD_QUEUEHEAD_DESCRIPTOR InterruptQueueHeads[NO_INTERRUPT_QH_LISTS];
  278. // Virtual Address for the TD that gives us an interrupt at the end
  279. // of every frame, so that things don't get stuck in the schedule.
  280. PHCD_TRANSFER_DESCRIPTOR RollOverTd;
  281. UCHAR SavedSOFModify;
  282. PHCD_TD_LIST SofTdList;
  283. } DEVICE_DATA, *PDEVICE_DATA;
  284. /*
  285. Callouts to port driver services
  286. */
  287. extern USBPORT_REGISTRATION_PACKET RegistrationPacket;
  288. #define USBPORT_DBGPRINT(dd, l, f, arg0, arg1, arg2, arg3, arg4, arg5) \
  289. RegistrationPacket.USBPORTSVC_DbgPrint((dd), (l), (f), (arg0), (arg1), \
  290. (arg2), (arg3), (arg4), (arg5))
  291. #define USBPORT_GET_REGISTRY_KEY_VALUE(dd, branch, keystring, keylen, data, datalen) \
  292. RegistrationPacket.USBPORTSVC_GetMiniportRegistryKeyValue((dd), (branch), \
  293. (keystring), (keylen), (data), (datalen))
  294. #define USBPORT_INVALIDATE_ROOTHUB(dd) \
  295. RegistrationPacket.USBPORTSVC_InvalidateRootHub((dd))
  296. #define USBPORT_COMPLETE_TRANSFER(dd, ep, tp, status, length) \
  297. RegistrationPacket.USBPORTSVC_CompleteTransfer((dd), (ep), (tp), \
  298. (status), (length))
  299. #define USBPORT_COMPLETE_ISOCH_TRANSFER(dd, ep, tp, iso) \
  300. RegistrationPacket.USBPORTSVC_CompleteIsoTransfer((dd), (ep), (tp), (iso))
  301. #define USBPORT_INVALIDATE_ENDPOINT(dd, ep) \
  302. RegistrationPacket.USBPORTSVC_InvalidateEndpoint((dd), (ep))
  303. #define USBPORT_PHYSICAL_TO_VIRTUAL(addr, dd, ep) \
  304. RegistrationPacket.USBPORTSVC_MapHwPhysicalToVirtual((addr), (dd), (ep))
  305. #define USBPORT_REQUEST_ASYNC_CALLBACK(dd, t, c, cl, f) \
  306. RegistrationPacket.USBPORTSVC_RequestAsyncCallback((dd), (t), \
  307. (c), (cl), (f))
  308. #define USBPORT_READ_CONFIG_SPACE(dd, b, o, l) \
  309. RegistrationPacket.USBPORTSVC_ReadWriteConfigSpace((dd), TRUE, \
  310. (b), (o), (l))
  311. #define USBPORT_WRITE_CONFIG_SPACE(dd, b, o, l) \
  312. RegistrationPacket.USBPORTSVC_ReadWriteConfigSpace((dd), FALSE, \
  313. (b), (o), (l))
  314. #define USBPORT_INVALIDATE_CONTROLLER(dd, s) \
  315. RegistrationPacket.USBPORTSVC_InvalidateController((dd), (s))
  316. #define USBPORT_WAIT(dd, t) \
  317. RegistrationPacket.USBPORTSVC_Wait((dd), (t))
  318. #define USBPORT_NOTIFY_DOUBLEBUFFER(dd, tp, addr, length) \
  319. RegistrationPacket.USBPORTSVC_NotifyDoubleBuffer((dd), (tp), \
  320. (addr), (length))
  321. #ifdef _WIN64
  322. #define DUMMY_TD_CONTEXT ((PVOID) 0xABADBABEABADBABE)
  323. #else
  324. #define DUMMY_TD_CONTEXT ((PVOID) 0xABADBABE)
  325. #endif
  326. #define UhciCheckIsochTransferInsertion(dd, r, df) {\
  327. ULONG cf = UhciGet32BitFrameNumber((dd));\
  328. if ((df) > (cf)) {\
  329. if ((df) < (dd)->LastFrameProcessed + UHCI_MAX_FRAME) \
  330. r = USBD_STATUS_SUCCESS;\
  331. else\
  332. r = USBD_STATUS_PENDING;\
  333. } else {\
  334. if ((df)-(cf) < UHCI_MAX_FRAME )\
  335. r = USBD_STATUS_SUCCESS;\
  336. else \
  337. r = USBD_STATUS_BAD_START_FRAME;}}
  338. //
  339. // This macro is protected from double queueing the TD, by using
  340. // interlocked function. Unless the HwAddress is NULL, it won't
  341. // replace the value.
  342. //
  343. #define INSERT_ISOCH_TD(dd, td, fn) \
  344. (td)->Flags |= TD_FLAG_ISO_QUEUED;\
  345. InterlockedCompareExchange(&(td)->HwTD.LinkPointer.HwAddress,\
  346. *( ((PULONG) ((dd)->FrameListVA)+ACTUAL_FRAME(fn)) ), 0);\
  347. *( ((PULONG) ((dd)->FrameListVA)+ACTUAL_FRAME(fn)) ) = \
  348. (td)->PhysicalAddress;
  349. //
  350. // Must account for both the regular and overflow cases:
  351. //
  352. /*#define CAN_INSERT_ISOCH_TD(fr, cfr) \
  353. ((fr - cfr < USBUHCI_MAX_FRAME) ||\
  354. ((fr + cfr < USBUHCI_MAX_FRAME) && fr < USBUHCI_MAX_FRAME))
  355. #define INSERT_ISOCH_TD(dd, td, ep) \
  356. (td)->PrevTd = (PHCD_TRANSFER_DESCRIPTOR)((PULONG) ((dd)->FrameListVA) + \
  357. ACTUAL_FRAME((td)->IsoPacket->FrameNumber)); \
  358. (td)->HwTD.LinkPointer.HwAddress = (td)->PrevTd->HwTD.LinkPointer.HwAddress; \
  359. if (!(td)->HwTD.LinkPointer.QHTDSelect) {\
  360. PHCD_TRANSFER_DESCRIPTOR rtd = (PHCD_TRANSFER_DESCRIPTOR)\
  361. USBPORT_PHYSICAL_TO_VIRTUAL((td)->HwTD.LinkPointer.HwAddress, \
  362. (dd), \
  363. (ep));\
  364. rtd->PrevTd = (td);\
  365. }\
  366. (td)->PrevTd->HwTD.LinkPointer.HwAddress = td->PhysicalAddress;
  367. #define REMOVE_ISOCH_TD(td) \
  368. (td)->PrevTd->HwTD.LinkPointer.HwAddress = (td)->HwTD.LinkPointer.HwAddress;
  369. */
  370. // We must set the frame to the highest ULONG prior to setting the
  371. // TD_FLAG_XFER flag, so that this TD doesn't get completed before
  372. // we've had chance to queue it.
  373. #define INITIALIZE_TD_FOR_TRANSFER(td, tc) \
  374. (td)->TransferContext = (tc);\
  375. (td)->Flags |= TD_FLAG_XFER; \
  376. (td)->HwTD.LinkPointer.HwAddress = 0;\
  377. (td)->HwTD.Control.ul = 0;\
  378. (td)->HwTD.Control.LowSpeedDevice = ((tc)->EndpointData->Parameters.DeviceSpeed == LowSpeed);\
  379. (td)->HwTD.Control.Active = 1;\
  380. (td)->HwTD.Control.ErrorCount = 3;\
  381. (td)->HwTD.Token.ul = 0;\
  382. (td)->HwTD.Token.Endpoint = (tc)->EndpointData->Parameters.EndpointAddress;\
  383. (td)->HwTD.Token.DeviceAddress = (tc)->EndpointData->Parameters.DeviceAddress;\
  384. (td)->NextTd = NULL;
  385. #define SET_QH_TD(dd, ed, td) {\
  386. TD_LINK_POINTER newLink;\
  387. if ((td)) {\
  388. (ed)->HeadTd = (td);\
  389. } else {\
  390. (ed)->HeadTd = (ed)->TailTd = NULL;\
  391. }\
  392. if (!(td) || TEST_FLAG((ed)->Flags, UHCI_EDFLAG_HALTED)) {\
  393. newLink.HwAddress = 0;\
  394. newLink.Terminate = 1;\
  395. } else {\
  396. newLink.HwAddress = (td)->PhysicalAddress;\
  397. newLink.Terminate = 0;\
  398. }\
  399. newLink.QHTDSelect = 0;\
  400. LOGENTRY((dd), G, '_sqt', (td), (ed), 0);\
  401. (ed)->QueueHead->HwQH.VLink = newLink;}
  402. /*#define SET_QH_TD_NULL(qh) \
  403. { TD_LINK_POINTER newLink;\
  404. newLink.HwAddress = 0;\
  405. newLink.Terminate = 1;\
  406. newLink.QHTDSelect = 0;\
  407. (qh)->HwQH.VLink = newLink;\
  408. }
  409. */
  410. #define SET_NEXT_TD(linkTd, nextTd) \
  411. (linkTd)->HwTD.LinkPointer.HwAddress = (nextTd)->PhysicalAddress;\
  412. (linkTd)->HwTD.LinkPointer.Terminate = 0;\
  413. (linkTd)->HwTD.LinkPointer.QHTDSelect = 0;\
  414. (linkTd)->HwTD.LinkPointer.DepthBreadthSelect = 0;\
  415. (linkTd)->NextTd = (nextTd);
  416. #define SET_NEXT_TD_NULL(linkTd) \
  417. (linkTd)->NextTd = NULL;\
  418. (linkTd)->HwTD.LinkPointer.HwAddress = 0;\
  419. (linkTd)->HwTD.LinkPointer.Terminate = 1;
  420. #define PAGE_CROSSING(PhysicalAddress, length) \
  421. ((PhysicalAddress+length)%PAGE_SIZE < length && (PhysicalAddress+length)%PAGE_SIZE != 0)
  422. #ifdef _WIN64
  423. #define UHCI_BAD_POINTER ((PVOID) 0xDEADFACEDEADFACE)
  424. #else
  425. #define UHCI_BAD_POINTER ((PVOID) 0xDEADFACE)
  426. #endif
  427. #define UHCI_BAD_HW_POINTER 0x0BADF00D
  428. // Note how we free any double buffering in here instead of relying
  429. // on the c code to do it.
  430. #define UHCI_FREE_TD(dd, ep, td) \
  431. if (TEST_FLAG((td)->Flags, TD_FLAG_DOUBLE_BUFFERED)) { \
  432. UHCI_FREE_DB((dd), (ep), (td)->DoubleBuffer);}\
  433. (ep)->TdsUsed--;\
  434. (td)->HwTD.LinkPointer.HwAddress = UHCI_BAD_HW_POINTER;\
  435. LOGENTRY((dd), G, '_fTD', (td), (ep), 0);\
  436. (td)->TransferContext = UHCI_BAD_POINTER;\
  437. (td)->Flags = 0;
  438. #define UHCI_ALLOC_TD(dd, ep) UhciAllocTd((dd), (ep));
  439. #define UHCI_FREE_DB(dd, ep, db) \
  440. LOGENTRY((dd), G, '_fDB', (db), (ep), 0);\
  441. (ep)->DbsUsed--;\
  442. if ((ep)->Parameters.TransferType == Isochronous) { (db)->Isoch.Flags = 0; }\
  443. else { (db)->Async.Flags = 0; }
  444. #define UHCI_ALLOC_DB(dd, ep, i) UhciAllocDb((dd), (ep), (i));
  445. // bugbug UHCI_ASSERT((dd), (ed)->PendingTransfers);
  446. #define DecPendingTransfers(dd, ed) \
  447. InterlockedDecrement(&(ed)->PendingTransfers);\
  448. if ((ed)->Parameters.TransferType == Isochronous)\
  449. InterlockedDecrement(&(dd)->IsoPendingTransfers);
  450. #define ActivateRolloverTd(dd) \
  451. *( ((PULONG) ((dd)->FrameListVA)) ) = (dd)->RollOverTd->PhysicalAddress;
  452. //#define IncPendingTransfers(dd, ed) \
  453. // InterlockedIncrement(&(ed)->PendingTransfers);\
  454. // if ((ed)->Parameters.TransferType == Isochronous) {\
  455. // if (1 == InterlockedIncrement(&(dd)->IsoPendingTransfers)) {\
  456. // //*( ((PULONG) ((dd)->FrameListVA)) ) = (dd)->RollOverTd->PhysicalAddress; \
  457. // (dd)->LastFrameProcessed = UhciGet32BitFrameNumber((dd));\
  458. // }}
  459. // bugbug UHCI_ASSERT((dd), (ed)->PendingTransfers);
  460. #define IncPendingTransfers(dd, ed) \
  461. InterlockedIncrement(&(ed)->PendingTransfers);\
  462. if ((ed)->Parameters.TransferType == Isochronous) {\
  463. if (1 == InterlockedIncrement(&(dd)->IsoPendingTransfers)) {\
  464. (dd)->LastFrameProcessed = UhciGet32BitFrameNumber((dd));\
  465. }}
  466. // bugbug UHCI_ASSERT((dd), (ed)->PendingTransfers);
  467. #define UhciCleanFrameOfIsochTds(dd, i)\
  468. if ((i) == 0) {\
  469. *( ((PULONG) ((dd)->FrameListVA)) ) = (dd)->RollOverTd->PhysicalAddress;\
  470. } else {\
  471. QH_LINK_POINTER newLink;\
  472. newLink.HwAddress = (dd)->InterruptQueueHeads[QH_INTERRUPT_32ms + MAX_INTERVAL_MASK((i))]->PhysicalAddress;\
  473. newLink.QHTDSelect = 1;\
  474. *( ((PULONG) ((dd)->FrameListVA)+(i)) ) = newLink.HwAddress;\
  475. }
  476. #define TEST_BIT(value, bitNumber) ((value) & (1<<(bitNumber))) ? TRUE : FALSE
  477. #define SET_BIT(value, bitNumber) ((value) |= (1<<(bitNumber)))
  478. #define CLEAR_BIT(value, bitNumber) ((value) &= ~(1<<(bitNumber)))
  479. //
  480. // Controller functions
  481. //
  482. USB_MINIPORT_STATUS
  483. USBMPFN
  484. UhciStartController(
  485. IN PDEVICE_DATA DeviceData,
  486. IN PHC_RESOURCES HcResources
  487. );
  488. VOID
  489. USBMPFN
  490. UhciStopController(
  491. IN PDEVICE_DATA DeviceData,
  492. IN BOOLEAN HwPresent
  493. );
  494. VOID
  495. USBMPFN
  496. UhciSuspendController(
  497. IN PDEVICE_DATA DeviceData
  498. );
  499. USB_MINIPORT_STATUS
  500. USBMPFN
  501. UhciResumeController(
  502. IN PDEVICE_DATA DeviceData
  503. );
  504. VOID
  505. USBMPFN
  506. UhciPollController(
  507. IN PDEVICE_DATA DeviceData
  508. );
  509. ULONG
  510. USBMPFN
  511. UhciGet32BitFrameNumber(
  512. IN PDEVICE_DATA DeviceData
  513. );
  514. VOID
  515. USBMPFN
  516. UhciInterruptNextSOF(
  517. IN PDEVICE_DATA DeviceData
  518. );
  519. VOID
  520. UhciUpdateCounter(
  521. IN PDEVICE_DATA DeviceData
  522. );
  523. VOID
  524. UhciDisableAsyncList(
  525. IN PDEVICE_DATA DeviceData
  526. );
  527. VOID
  528. UhciInitailizeInterruptSchedule(
  529. IN PDEVICE_DATA DeviceData
  530. );
  531. VOID
  532. UhciEnableAsyncList(
  533. IN PDEVICE_DATA DeviceData
  534. );
  535. USB_MINIPORT_STATUS
  536. USBMPFN
  537. UhciPassThru (
  538. IN PDEVICE_DATA DeviceData,
  539. IN GUID *FunctionGuid,
  540. IN ULONG ParameterLength,
  541. IN OUT PVOID Parameters
  542. );
  543. //
  544. // Root hub functions
  545. //
  546. VOID
  547. USBMPFN
  548. UhciRHGetRootHubData(
  549. IN PDEVICE_DATA DeviceData,
  550. OUT PROOTHUB_DATA HubData
  551. );
  552. USB_MINIPORT_STATUS
  553. USBMPFN
  554. UhciRHGetStatus(
  555. IN PDEVICE_DATA DeviceData,
  556. OUT PUSHORT Status
  557. );
  558. USB_MINIPORT_STATUS
  559. USBMPFN
  560. UhciRHGetHubStatus(
  561. IN PDEVICE_DATA DeviceData,
  562. OUT PRH_HUB_STATUS HubStatus
  563. );
  564. VOID
  565. USBMPFN
  566. UhciRHDisableIrq(
  567. IN PDEVICE_DATA DeviceData
  568. );
  569. VOID
  570. USBMPFN
  571. UhciRHEnableIrq(
  572. IN PDEVICE_DATA DeviceData
  573. );
  574. //
  575. // Root hub port functions
  576. //
  577. USB_MINIPORT_STATUS
  578. USBMPFN
  579. UhciRHSetFeaturePortReset(
  580. PDEVICE_DATA DeviceData,
  581. USHORT PortNumber
  582. );
  583. USB_MINIPORT_STATUS
  584. USBMPFN
  585. UhciRHSetFeaturePortSuspend(
  586. PDEVICE_DATA DeviceData,
  587. USHORT PortNumber
  588. );
  589. USB_MINIPORT_STATUS
  590. USBMPFN
  591. UhciRHClearFeaturePortSuspend(
  592. PDEVICE_DATA DeviceData,
  593. USHORT PortNumber
  594. );
  595. USB_MINIPORT_STATUS
  596. USBMPFN
  597. UhciRHSetFeaturePortPower(
  598. PDEVICE_DATA DeviceData,
  599. USHORT PortNumber
  600. );
  601. USB_MINIPORT_STATUS
  602. USBMPFN
  603. UhciRHClearFeaturePortPower(
  604. IN PDEVICE_DATA DeviceData,
  605. IN USHORT PortNumber
  606. );
  607. USB_MINIPORT_STATUS
  608. USBMPFN
  609. UhciRHSetFeaturePortEnable(
  610. PDEVICE_DATA DeviceData,
  611. USHORT PortNumber
  612. );
  613. USB_MINIPORT_STATUS
  614. USBMPFN
  615. UhciRHClearFeaturePortEnable(
  616. IN PDEVICE_DATA DeviceData,
  617. IN USHORT PortNumber
  618. );
  619. USB_MINIPORT_STATUS
  620. USBMPFN
  621. UhciRHGetPortStatus(
  622. PDEVICE_DATA DeviceData,
  623. USHORT PortNumber,
  624. PRH_PORT_STATUS portStatus
  625. );
  626. //
  627. // Clear change bits for hub ports
  628. //
  629. USB_MINIPORT_STATUS
  630. USBMPFN
  631. UhciRHClearFeaturePortConnectChange(
  632. PDEVICE_DATA DeviceData,
  633. USHORT PortNumber
  634. );
  635. USB_MINIPORT_STATUS
  636. USBMPFN
  637. UhciRHClearFeaturePortResetChange(
  638. PDEVICE_DATA DeviceData,
  639. USHORT PortNumber
  640. );
  641. USB_MINIPORT_STATUS
  642. USBMPFN
  643. UhciRHClearFeaturePortSuspendChange(
  644. PDEVICE_DATA DeviceData,
  645. USHORT PortNumber
  646. );
  647. USB_MINIPORT_STATUS
  648. USBMPFN
  649. UhciRHClearFeaturePortOvercurrentChange(
  650. PDEVICE_DATA DeviceData,
  651. USHORT PortNumber
  652. );
  653. USB_MINIPORT_STATUS
  654. USBMPFN
  655. UhciRHClearFeaturePortEnableChange(
  656. PDEVICE_DATA DeviceData,
  657. USHORT PortNumber
  658. );
  659. //
  660. // Interrupt functions
  661. //
  662. BOOLEAN
  663. USBMPFN
  664. UhciInterruptService (
  665. IN PDEVICE_DATA DeviceData
  666. );
  667. VOID
  668. USBMPFN
  669. UhciEnableInterrupts(
  670. IN PDEVICE_DATA DeviceData
  671. );
  672. VOID
  673. USBMPFN
  674. UhciInterruptDpc (
  675. IN PDEVICE_DATA DeviceData,
  676. IN BOOLEAN EnableInterrupts
  677. );
  678. VOID
  679. USBMPFN
  680. UhciDisableInterrupts(
  681. IN PDEVICE_DATA DeviceData
  682. );
  683. //
  684. // Endpoint functions
  685. //
  686. USB_MINIPORT_STATUS
  687. USBMPFN
  688. UhciOpenEndpoint(
  689. IN PDEVICE_DATA DeviceData,
  690. IN PENDPOINT_PARAMETERS EndpointParameters,
  691. OUT PENDPOINT_DATA EndpointData
  692. );
  693. USB_MINIPORT_STATUS
  694. USBMPFN
  695. UhciPokeEndpoint(
  696. IN PDEVICE_DATA DeviceData,
  697. IN PENDPOINT_PARAMETERS EndpointParameters,
  698. OUT PENDPOINT_DATA EndpointData
  699. );
  700. USB_MINIPORT_STATUS
  701. USBMPFN
  702. UhciQueryEndpointRequirements(
  703. IN PDEVICE_DATA DeviceData,
  704. IN PENDPOINT_PARAMETERS EndpointParameters,
  705. OUT PENDPOINT_REQUIREMENTS EndpointRequirements
  706. );
  707. VOID
  708. USBMPFN
  709. UhciCloseEndpoint(
  710. IN PDEVICE_DATA DeviceData,
  711. IN PENDPOINT_DATA EndpointData
  712. );
  713. VOID
  714. USBMPFN
  715. UhciAbortTransfer(
  716. IN PDEVICE_DATA DeviceData,
  717. IN PENDPOINT_DATA EndpointData,
  718. IN PTRANSFER_CONTEXT TransferContext,
  719. OUT PULONG BytesTransferred
  720. );
  721. USB_MINIPORT_STATUS
  722. USBMPFN
  723. UhciStartSendOnePacket(
  724. IN PDEVICE_DATA DeviceData,
  725. IN PMP_PACKET_PARAMETERS PacketParameters,
  726. IN PUCHAR PacketData,
  727. IN PULONG PacketLength,
  728. IN PUCHAR WorkspaceVirtualAddress,
  729. IN HW_32BIT_PHYSICAL_ADDRESS WorkspacePhysicalAddress,
  730. IN ULONG WorkSpaceLength,
  731. IN OUT USBD_STATUS *UsbdStatus
  732. );
  733. USB_MINIPORT_STATUS
  734. USBMPFN
  735. UhciEndSendOnePacket(
  736. IN PDEVICE_DATA DeviceData,
  737. IN PMP_PACKET_PARAMETERS PacketParameters,
  738. IN PUCHAR PacketData,
  739. IN PULONG PacketLength,
  740. IN PUCHAR WorkspaceVirtualAddress,
  741. IN HW_32BIT_PHYSICAL_ADDRESS WorkspacePhysicalAddress,
  742. IN ULONG WorkSpaceLength,
  743. IN OUT USBD_STATUS *UsbdStatus
  744. );
  745. VOID
  746. USBMPFN
  747. UhciSetEndpointStatus(
  748. IN PDEVICE_DATA DeviceData,
  749. IN PENDPOINT_DATA EndpointData,
  750. IN MP_ENDPOINT_STATUS Status
  751. );
  752. MP_ENDPOINT_STATUS
  753. USBMPFN
  754. UhciGetEndpointStatus(
  755. IN PDEVICE_DATA DeviceData,
  756. IN PENDPOINT_DATA EndpointData
  757. );
  758. PHCD_QUEUEHEAD_DESCRIPTOR
  759. UhciInitializeQH(
  760. IN PDEVICE_DATA DeviceData,
  761. IN PENDPOINT_DATA EndpointData,
  762. IN PHCD_QUEUEHEAD_DESCRIPTOR Qh,
  763. IN HW_32BIT_PHYSICAL_ADDRESS HwPhysAddress
  764. );
  765. VOID
  766. USBMPFN
  767. UhciSetEndpointDataToggle(
  768. IN PDEVICE_DATA DeviceData,
  769. IN PENDPOINT_DATA EndpointData,
  770. IN ULONG Toggle
  771. );
  772. VOID
  773. USBMPFN
  774. UhciPollEndpoint(
  775. IN PDEVICE_DATA DeviceData,
  776. IN PENDPOINT_DATA EndpointData
  777. );
  778. MP_ENDPOINT_STATE
  779. USBMPFN
  780. UhciGetEndpointState(
  781. IN PDEVICE_DATA DeviceData,
  782. IN PENDPOINT_DATA EndpointData
  783. );
  784. VOID
  785. USBMPFN
  786. UhciSetEndpointState(
  787. IN PDEVICE_DATA DeviceData,
  788. IN PENDPOINT_DATA EndpointData,
  789. IN MP_ENDPOINT_STATE State
  790. );
  791. VOID
  792. UhciSetAsyncEndpointState(
  793. IN PDEVICE_DATA DeviceData,
  794. IN PENDPOINT_DATA EndpointData,
  795. IN MP_ENDPOINT_STATE State
  796. );
  797. USB_MINIPORT_STATUS
  798. USBMPFN
  799. UhciSubmitTransfer(
  800. IN PDEVICE_DATA DeviceData,
  801. IN PENDPOINT_DATA EndpointData,
  802. IN PTRANSFER_PARAMETERS TransferUrb,
  803. IN PTRANSFER_CONTEXT TransferContext,
  804. IN PTRANSFER_SG_LIST TransferSGList
  805. );
  806. //
  807. // Async
  808. //
  809. VOID
  810. UhciProcessDoneAsyncTd(
  811. PDEVICE_DATA DeviceData,
  812. PHCD_TRANSFER_DESCRIPTOR Td
  813. );
  814. VOID
  815. UhciPollAsyncEndpoint(
  816. IN PDEVICE_DATA DeviceData,
  817. IN PENDPOINT_DATA EndpointData
  818. );
  819. USB_MINIPORT_STATUS
  820. UhciBulkOrInterruptTransfer(
  821. IN PDEVICE_DATA DeviceData,
  822. IN PENDPOINT_DATA EndpointData,
  823. IN PTRANSFER_PARAMETERS TransferParameters,
  824. IN PTRANSFER_CONTEXT TransferContext,
  825. IN PTRANSFER_SG_LIST TransferSGList
  826. );
  827. VOID
  828. UhciUnlinkQh(
  829. IN PDEVICE_DATA DeviceData,
  830. IN PHCD_QUEUEHEAD_DESCRIPTOR Qh
  831. );
  832. VOID
  833. UhciAbortAsyncTransfer(
  834. IN PDEVICE_DATA DeviceData,
  835. IN PENDPOINT_DATA EndpointData,
  836. IN PTRANSFER_CONTEXT TransferContext,
  837. OUT PULONG BytesTransferred
  838. );
  839. VOID
  840. UhciInsertQh(
  841. IN PDEVICE_DATA DeviceData,
  842. IN PHCD_QUEUEHEAD_DESCRIPTOR FirstQh,
  843. IN PHCD_QUEUEHEAD_DESCRIPTOR LinkQh
  844. );
  845. USB_MINIPORT_STATUS
  846. UhciControlTransfer(
  847. IN PDEVICE_DATA DeviceData,
  848. IN PENDPOINT_DATA EndpointData,
  849. IN PTRANSFER_PARAMETERS TransferUrb,
  850. IN PTRANSFER_CONTEXT TransferContext,
  851. IN PTRANSFER_SG_LIST TransferSGList
  852. );
  853. //
  854. // Isoch
  855. //
  856. USB_MINIPORT_STATUS
  857. USBMPFN
  858. UhciIsochTransfer(
  859. IN PDEVICE_DATA DeviceData,
  860. IN PENDPOINT_DATA EndpointData,
  861. IN PTRANSFER_PARAMETERS TransferParameters,
  862. IN PTRANSFER_CONTEXT TransferContext,
  863. IN PMINIPORT_ISO_TRANSFER IsoTransfer
  864. );
  865. VOID
  866. UhciPollIsochEndpoint(
  867. IN PDEVICE_DATA DeviceData,
  868. IN PENDPOINT_DATA EndpointData
  869. );
  870. VOID
  871. UhciAbortIsochTransfer(
  872. IN PDEVICE_DATA DeviceData,
  873. IN PENDPOINT_DATA EndpointData,
  874. IN PTRANSFER_CONTEXT TransferContext
  875. );
  876. VOID
  877. UhciSetIsochEndpointState(
  878. IN PDEVICE_DATA DeviceData,
  879. IN PENDPOINT_DATA EndpointData,
  880. IN MP_ENDPOINT_STATE State
  881. );
  882. VOID
  883. UhciCleanOutIsoch(
  884. IN PDEVICE_DATA DeviceData,
  885. IN BOOLEAN ForceClean
  886. );
  887. //
  888. // Utility
  889. //
  890. USBD_STATUS
  891. UhciGetErrorFromTD(
  892. PDEVICE_DATA DeviceData,
  893. PHCD_TRANSFER_DESCRIPTOR Td
  894. );
  895. PHCD_TRANSFER_DESCRIPTOR
  896. UhciAllocTd(
  897. IN PDEVICE_DATA DeviceData,
  898. IN PENDPOINT_DATA EndpointData
  899. );
  900. PTRANSFER_BUFFER
  901. UhciAllocDb(
  902. IN PDEVICE_DATA DeviceData,
  903. IN PENDPOINT_DATA EndpointData,
  904. IN BOOLEAN Isoch
  905. );
  906. //
  907. // Bios handoff and handback
  908. //
  909. USB_MINIPORT_STATUS
  910. UhciStopBIOS(
  911. IN PDEVICE_DATA DeviceData,
  912. IN PHC_RESOURCES HcResources
  913. );
  914. ULONG
  915. UhciQueryControlRequirements(
  916. IN PDEVICE_DATA DeviceData,
  917. IN PENDPOINT_PARAMETERS EndpointParameters,
  918. IN OUT PULONG NumberOfTDs,
  919. IN OUT PULONG NumberOfDoubleBuffers
  920. );
  921. ULONG
  922. UhciQueryBulkRequirements(
  923. IN PDEVICE_DATA DeviceData,
  924. IN PENDPOINT_PARAMETERS EndpointParameters,
  925. IN OUT PULONG NumberOfTDs,
  926. IN OUT PULONG NumberOfDoubleBuffers
  927. );
  928. ULONG
  929. UhciQueryIsoRequirements(
  930. IN PDEVICE_DATA DeviceData,
  931. IN PENDPOINT_PARAMETERS EndpointParameters,
  932. IN OUT PULONG NumberOfTDs,
  933. IN OUT PULONG NumberOfDoubleBuffers
  934. );
  935. ULONG
  936. UhciQueryInterruptRequirements(
  937. IN PDEVICE_DATA DeviceData,
  938. IN PENDPOINT_PARAMETERS EndpointParameters,
  939. IN OUT PULONG NumberOfTDs,
  940. IN OUT PULONG NumberOfDoubleBuffers
  941. );
  942. BOOLEAN
  943. UhciHardwarePresent(
  944. PDEVICE_DATA DeviceData
  945. );
  946. VOID
  947. UhciCheckController(
  948. PDEVICE_DATA DeviceData
  949. );
  950. VOID
  951. UhciFlushInterrupts(
  952. IN PDEVICE_DATA DeviceData
  953. );
  954. /*
  955. USB_MINIPORT_STATUS
  956. UhciStartBIOS(
  957. IN PDEVICE_DATA DeviceData
  958. );
  959. */
  960. #endif /* __USBUHCI_H__ */