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.

2796 lines
76 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. usbohci.c
  5. Abstract:
  6. USB OHCI driver
  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 Microsoft Corporation. All Rights Reserved.
  15. Revision History:
  16. 2-19-99 : created, jdunn
  17. --*/
  18. #include "common.h"
  19. //implements the following miniport functions:
  20. //OHCI_InitializeHardware
  21. //OHCI_StartController
  22. //OHCI_StopController
  23. //OHCI_OpenEndpoint
  24. //OHCI_QueryEndpointRequirements
  25. //OHCI_PokeEndpoint
  26. USB_MINIPORT_STATUS
  27. OHCI_InitializeHardware(
  28. PDEVICE_DATA DeviceData
  29. )
  30. /*++
  31. Routine Description:
  32. Initializes the hardware registers for the host controller.
  33. Arguments:
  34. Return Value:
  35. --*/
  36. {
  37. PHC_OPERATIONAL_REGISTER hc;
  38. HC_CONTROL control;
  39. ULONG reg;
  40. ULONG sofModifyValue;
  41. LARGE_INTEGER finishTime, currentTime;
  42. hc = DeviceData->HC;
  43. //
  44. // if we made it here then we now own the HC and can initialize it.
  45. //
  46. //
  47. // Get current frame interval (could account for a known clock error)
  48. //
  49. DeviceData->BIOS_Interval.ul = READ_REGISTER_ULONG(&hc->HcFmInterval.ul);
  50. // If FrameInterval is outside the range of the nominal value of 11999
  51. // +/- 1% then assume the value is bogus and set it to the nominal value.
  52. //
  53. if ((DeviceData->BIOS_Interval.FrameInterval < 11879) ||
  54. (DeviceData->BIOS_Interval.FrameInterval > 12119)) {
  55. DeviceData->BIOS_Interval.FrameInterval = 11999; // 0x2EDF
  56. }
  57. //
  58. // Set largest data packet (in case BIOS did not set)
  59. //
  60. DeviceData->BIOS_Interval.FSLargestDataPacket =
  61. ((DeviceData->BIOS_Interval.FrameInterval - MAXIMUM_OVERHEAD) * 6) / 7;
  62. DeviceData->BIOS_Interval.FrameIntervalToggle ^= 1;
  63. //
  64. // do a hardware reset of the controller
  65. //
  66. WRITE_REGISTER_ULONG(&hc->HcCommandStatus.ul, HcCmd_HostControllerReset);
  67. //
  68. // Wait at least 10 microseconds for the reset to complete
  69. //
  70. KeStallExecutionProcessor(20);
  71. //
  72. // Take HC to USBReset state,
  73. // NOTE: this generates global reset signaling on the bus
  74. //
  75. control.ul = READ_REGISTER_ULONG(&hc->HcControl.ul);
  76. control.HostControllerFunctionalState = HcCtrl_HCFS_USBReset;
  77. WRITE_REGISTER_ULONG(&hc->HcControl.ul, control.ul);
  78. //
  79. // Restore original frame interval, if we have a registry override
  80. // value we use it instead.
  81. //
  82. // check for a registry based SOF modify Value.
  83. // if we have one override the BIOS value
  84. if (DeviceData->Flags & HMP_FLAG_SOF_MODIFY_VALUE) {
  85. DeviceData->BIOS_Interval.FrameInterval =
  86. DeviceData->SofModifyValue;
  87. }
  88. // for some reason writing this register does not always take on
  89. // the hydra so we loop until it sticks
  90. KeQuerySystemTime(&finishTime);
  91. // figure when we quit (.5 seconds later)
  92. finishTime.QuadPart += 5000000;
  93. do {
  94. WRITE_REGISTER_ULONG(&hc->HcFmInterval.ul, DeviceData->BIOS_Interval.ul);
  95. reg = READ_REGISTER_ULONG(&hc->HcFmInterval.ul);
  96. OHCI_KdPrint((DeviceData, 2, "'fi reg = %x set = %x\n", reg,
  97. DeviceData->BIOS_Interval.ul));
  98. KeQuerySystemTime(&currentTime);
  99. if (currentTime.QuadPart >= finishTime.QuadPart) {
  100. // half a second has elapsed ,give up and fail the hardware
  101. OHCI_KdPrint((DeviceData, 0,
  102. "'frame interval not set\n"));
  103. LOGENTRY(DeviceData, G, '_fr!', 0, 0, 0);
  104. return USBMP_STATUS_HARDWARE_FAILURE;
  105. }
  106. } while (reg != DeviceData->BIOS_Interval.ul);
  107. OHCI_KdPrint((DeviceData, 2, "'fi = %x\n", DeviceData->BIOS_Interval.ul));
  108. //
  109. // Set the HcPeriodicStart register to 90% of the FrameInterval
  110. //
  111. WRITE_REGISTER_ULONG(&hc->HcPeriodicStart,
  112. (DeviceData->BIOS_Interval.FrameInterval * 9 + 5)
  113. / 10);
  114. // set the ptr to the HCCA
  115. WRITE_REGISTER_ULONG(&hc->HcHCCA, DeviceData->HcHCCAPhys);
  116. //
  117. // Enable interrupts, this will not cause the controller
  118. // to generate any because master-enable is not set yet.
  119. //
  120. WRITE_REGISTER_ULONG(&hc->HcInterruptEnable,
  121. HcInt_OwnershipChange |
  122. HcInt_SchedulingOverrun |
  123. HcInt_WritebackDoneHead |
  124. HcInt_FrameNumberOverflow |
  125. HcInt_UnrecoverableError);
  126. return USBMP_STATUS_SUCCESS;
  127. }
  128. USB_MINIPORT_STATUS
  129. OHCI_StopBIOS(
  130. PDEVICE_DATA DeviceData,
  131. PHC_RESOURCES HcResources
  132. )
  133. /*++
  134. Routine Description:
  135. Arguments:
  136. Return Value:
  137. --*/
  138. {
  139. PHC_OPERATIONAL_REGISTER hc;
  140. ULONG hcControl;
  141. hc = DeviceData->HC;
  142. //
  143. // Check to see if a System Management Mode driver owns the HC
  144. //
  145. hcControl = READ_REGISTER_ULONG(&hc->HcControl.ul);
  146. if (hcControl & HcCtrl_InterruptRouting) {
  147. OHCI_KdPrint((DeviceData, 1, "'detected Legacy BIOS\n"));
  148. HcResources->DetectedLegacyBIOS = TRUE;
  149. if ((hcControl == HcCtrl_InterruptRouting) &&
  150. (READ_REGISTER_ULONG(&hc->HcInterruptEnable) == 0)) {
  151. // Major assumption: If HcCtrl_InterruptRouting is set but
  152. // no other bits in HcControl are set, i.e. HCFS==UsbReset,
  153. // and no interrupts are enabled, then assume that the BIOS
  154. // is not actually using the host controller. In this case
  155. // just clear the erroneously set HcCtrl_InterruptRouting.
  156. //
  157. // This assumption appears to be correct on a Portege 3010CT,
  158. // where HcCtrl_InterruptRouting is set during a Resume from
  159. // Standby, but the BIOS doesn't actually appear to be using
  160. // the host controller. If we were to continue on and set
  161. // HcCmd_OwnershipChangeRequest, the BIOS appears to wake up
  162. // and try to take ownership of the host controller instead of
  163. // giving it up.
  164. //
  165. OHCI_KdPrint((DeviceData, 0,
  166. "'HcCtrl_InterruptRouting erroneously set\n"));
  167. WRITE_REGISTER_ULONG(&hc->HcControl.ul, 0);
  168. } else {
  169. LARGE_INTEGER finishTime, currentTime;
  170. //
  171. // A SMM driver does own the HC, it will take some time to
  172. // get the SMM driver to relinquish control of the HC. We
  173. // will ping the SMM driver, and then wait repeatedly until
  174. // the SMM driver has relinquished control of the HC.
  175. //
  176. // THIS CODE ONLY WORKS IF WE ARE EXECUTING IN THE CONTEXT
  177. // OF A SYSTEM THREAD.
  178. //
  179. // The HAL has disabled interrupts on the HC. Since
  180. // interruptrouting is set we assume there is a functional
  181. // smm BIOS. The BIOS will need the master interrupt
  182. // enabled to complete the handoff (if it is disabled the
  183. // machine will hang). So we re-enable the master interrupt
  184. // here.
  185. WRITE_REGISTER_ULONG(&hc->HcInterruptEnable,
  186. HcInt_MasterInterruptEnable);
  187. WRITE_REGISTER_ULONG(&hc->HcCommandStatus.ul,
  188. HcCmd_OwnershipChangeRequest);
  189. // hack for NEC -- disable the root hub status change
  190. // to prevent an unhandled interrupt from being asserted
  191. // after handoff
  192. WRITE_REGISTER_ULONG(&hc->HcInterruptDisable,
  193. HcInt_RootHubStatusChange);
  194. // bugbug expose with service
  195. KeQuerySystemTime(&finishTime);
  196. // figure when we quit (.5 seconds later)
  197. finishTime.QuadPart += 5000000;
  198. //
  199. // We told the SMM driver we want the HC, now all we can do is wait
  200. // for the SMM driver to be done with the HC.
  201. //
  202. while (READ_REGISTER_ULONG(&hc->HcControl.ul) &
  203. HcCtrl_InterruptRouting) {
  204. KeQuerySystemTime(&currentTime);
  205. if (currentTime.QuadPart >= finishTime.QuadPart) {
  206. OHCI_KdPrint((DeviceData, 0,
  207. "'SMM has not relinquised HC -- this is a HW bug\n"));
  208. LOGENTRY(DeviceData, G, '_sm!', 0, 0, 0);
  209. return USBMP_STATUS_HARDWARE_FAILURE;
  210. }
  211. }
  212. // we have control, disable master interrupt until we
  213. // finish intializing
  214. WRITE_REGISTER_ULONG(&hc->HcInterruptStatus,
  215. 0xffffffff);
  216. WRITE_REGISTER_ULONG(&hc->HcInterruptDisable,
  217. HcInt_MasterInterruptEnable);
  218. }
  219. }
  220. return USBMP_STATUS_SUCCESS;
  221. }
  222. USB_MINIPORT_STATUS
  223. OHCI_InitializeSchedule(
  224. PDEVICE_DATA DeviceData,
  225. PUCHAR StaticEDs,
  226. HW_32BIT_PHYSICAL_ADDRESS StaticEDsPhys,
  227. PUCHAR EndCommonBuffer
  228. )
  229. /*++
  230. Routine Description:
  231. Build the schedule of static Eds
  232. Arguments:
  233. Return Value:
  234. --*/
  235. {
  236. USB_MINIPORT_STATUS mpStatus;
  237. ULONG length;
  238. ULONG i;
  239. PHC_OPERATIONAL_REGISTER hc;
  240. //
  241. // Allocate staticly disabled EDs, and set head pointers for
  242. // scheduling lists
  243. //
  244. // The static ED list is contains all the static interrupt EDs (64)
  245. // plus the static ED for bulk and control (2)
  246. //
  247. // the array looks like this:
  248. // 1, 2, 2, 4, 4, 4, 4, 8,
  249. // 8, 8, 8, 8, 8, 8, 8,16,
  250. // 16,16,16,16,16,16,16,16,
  251. // 16,16,16,16,16,16,16,32,
  252. // 32,32,32,32,32,32,32,32,
  253. // 32,32,32,32,32,32,32,32,
  254. // 32,32,32,32,32,32,32,32,
  255. // 32,32,32,32,32,32,32,
  256. // CONTROL
  257. // BULK
  258. // each static ED points to another static ED
  259. // (except for the 1ms ed) the INDEX of the next
  260. // ED in the StaticEDList is stored in NextIdx,
  261. // these values are constent
  262. CHAR nextIdxTable[63] = {
  263. // 0 1 2 3 4 5 6 7
  264. (CHAR)ED_EOF, 0, 0, 1, 1, 2, 2, 3,
  265. // 8 9 10 11 12 13 14 15
  266. 3, 4, 4, 5, 5, 6, 6, 7,
  267. //16 17 18 19 20 21 22 23
  268. 7, 8, 8, 9, 9,10,10,11,
  269. //24 25 26 27 28 29 30 31
  270. 11,12,12,13,13,14,14,15,
  271. //32 33 34 35 36 37 38 39
  272. 15,16,16,17,17,18,18,19,
  273. //40 41 42 43 44 45 46 47
  274. 19,20,20,21,21,22,22,23,
  275. //48 49 50 51 52 53 54 55
  276. 23,24,24,25,25,26,26,27,
  277. //56 57 58 59 60 61 62 63
  278. 27,28,28,29,29,30,30
  279. };
  280. /*
  281. Numbers are the index into the static ed table
  282. (31) -\
  283. (15)-\
  284. (32) -/ \
  285. (7 )-\
  286. (33) -\ / \
  287. (16)-/ \
  288. (34) -/ \
  289. (3)-\
  290. (35) -\ / \
  291. (17)-\ / \
  292. (36) -/ \ / \
  293. (8 )-/ \
  294. (37) -\ / \
  295. (18)-/ \
  296. (38) -/ \
  297. (1)-\
  298. (39) -\ / \
  299. (19)-\ / \
  300. (40) -/ \ / \
  301. (9 )-\ / \
  302. (41) -\ / \ / \
  303. (20)-/ \ / \
  304. (42) -/ \ / \
  305. (4)-/ \
  306. (43) -\ / \
  307. (21)-\ / \
  308. (44) -/ \ / \
  309. (10)-/ \
  310. (45) -\ / \
  311. (22)-/ \
  312. (46) -/ \
  313. (0)
  314. (47) -\ /
  315. (23)-\ /
  316. (48) -/ \ /
  317. (11)-\ /
  318. (49) -\ / \ /
  319. (24)-/ \ /
  320. (50) -/ \ /
  321. (5)-\ /
  322. (51) -\ / \ /
  323. (25)-\ / \ /
  324. (52) -/ \ / \ /
  325. (12)-/ \ /
  326. (53) -\ / \ /
  327. (26)-/ \ /
  328. (54) -/ \ /
  329. (2)-/
  330. (55) -\ /
  331. (27)-\ /
  332. (56) -/ \ /
  333. (13)-\ /
  334. (57) -\ / \ /
  335. (28)-/ \ /
  336. (58) -/ \ /
  337. (6)-/
  338. (59) -\ /
  339. (29)-\ /
  340. (60) -/ \ /
  341. (14)-/
  342. (61) -\ /
  343. (30)-/
  344. (62) -/
  345. */
  346. // corresponding offsets for the 32ms list heads in the
  347. // HCCA -- these are entries 31..62
  348. ULONG used = 0;
  349. CHAR Hcca32msOffsets[32] = {
  350. 0, 16, 8, 24, 4, 20, 12, 28,
  351. 2, 18, 10, 26, 6, 22, 14, 30,
  352. 1, 17, 9, 25, 5, 21, 13, 29,
  353. 3, 19, 11, 27, 7, 23, 15, 31
  354. };
  355. DeviceData->StaticEDs = StaticEDs;
  356. DeviceData->StaticEDsPhys = StaticEDsPhys;
  357. hc = DeviceData->HC;
  358. // initailze all interrupt EDs
  359. for (i=0; i<ED_CONTROL; i++) {
  360. CHAR n;
  361. PHW_ENDPOINT_DESCRIPTOR hwED;
  362. //
  363. // Carve EDs from the common buffer
  364. //
  365. hwED = (PHW_ENDPOINT_DESCRIPTOR) StaticEDs;
  366. n = nextIdxTable[i];
  367. // initialize the hardware ED
  368. hwED->TailP = hwED->HeadP = 0xDEAD0000;
  369. //hwED->TailP = hwED->HeadP = StaticEDsPhys;
  370. hwED->Control = HcEDControl_SKIP; // ED is disabled
  371. LOGENTRY(DeviceData, G, '_isc', n, &DeviceData->StaticEDList[0], 0);
  372. if (n == (CHAR)ED_EOF) {
  373. hwED->NextED = 0;
  374. } else {
  375. OHCI_ASSERT(DeviceData, n>=0 && n<31);
  376. hwED->NextED = DeviceData->StaticEDList[n].HwEDPhys;
  377. }
  378. // initailze the list we use for real EDs
  379. InitializeListHead(&DeviceData->StaticEDList[i].TransferEdList);
  380. DeviceData->StaticEDList[i].HwED = hwED;
  381. DeviceData->StaticEDList[i].HwEDPhys = StaticEDsPhys;
  382. DeviceData->StaticEDList[i].NextIdx = n;
  383. DeviceData->StaticEDList[i].EdFlags = EDFLAG_INTERRUPT;
  384. // store address of hcc table entry
  385. DeviceData->StaticEDList[i].PhysicalHead =
  386. &hwED->NextED;
  387. // next ED
  388. StaticEDs += sizeof(HW_ENDPOINT_DESCRIPTOR);
  389. StaticEDsPhys += sizeof(HW_ENDPOINT_DESCRIPTOR);
  390. }
  391. // now set the head pointers in the HCCA
  392. // the HCCA points to all the 32ms list heads
  393. for (i=0; i<32; i++) {
  394. ULONG hccaOffset;
  395. hccaOffset = Hcca32msOffsets[i];
  396. DeviceData->HcHCCA->HccaInterruptTable[hccaOffset] =
  397. DeviceData->StaticEDList[i+ED_INTERRUPT_32ms].HwEDPhys;
  398. DeviceData->StaticEDList[i+ED_INTERRUPT_32ms].HccaOffset =
  399. hccaOffset;
  400. // physical head for 32ms list point to HCCA
  401. DeviceData->StaticEDList[i+ED_INTERRUPT_32ms].PhysicalHead =
  402. &DeviceData->HcHCCA->HccaInterruptTable[hccaOffset];
  403. }
  404. //
  405. // Setup EDList entries for Control & Bulk
  406. //
  407. InitializeListHead(&DeviceData->StaticEDList[ED_CONTROL].TransferEdList);
  408. DeviceData->StaticEDList[ED_CONTROL].NextIdx = (CHAR) ED_EOF;
  409. DeviceData->StaticEDList[ED_CONTROL].PhysicalHead = &hc->HcControlHeadED;
  410. DeviceData->StaticEDList[ED_CONTROL].EdFlags = EDFLAG_CONTROL | EDFLAG_REGISTER;
  411. InitializeListHead(&DeviceData->StaticEDList[ED_BULK].TransferEdList);
  412. DeviceData->StaticEDList[ED_BULK].NextIdx = (CHAR) ED_EOF;
  413. DeviceData->StaticEDList[ED_BULK].PhysicalHead = &hc->HcBulkHeadED;
  414. DeviceData->StaticEDList[ED_BULK].EdFlags = EDFLAG_BULK | EDFLAG_REGISTER;
  415. if (DeviceData->ControllerFlavor == OHCI_Hydra) {
  416. used = InitializeHydraHsLsFix(DeviceData, StaticEDs, StaticEDsPhys);
  417. }
  418. StaticEDs += used;
  419. StaticEDsPhys += used;
  420. OHCI_ASSERT(DeviceData, StaticEDs <= EndCommonBuffer);
  421. mpStatus = USBMP_STATUS_SUCCESS;
  422. return mpStatus;
  423. }
  424. VOID
  425. OHCI_GetRegistryParameters(
  426. PDEVICE_DATA DeviceData
  427. )
  428. /*++
  429. Routine Description:
  430. sets the registry based sof modify value
  431. Arguments:
  432. Return Value:
  433. --*/
  434. {
  435. USB_MINIPORT_STATUS mpStatus;
  436. ULONG clocksPerFrame;
  437. // get SOF modify value from registry
  438. mpStatus =
  439. USBPORT_GET_REGISTRY_KEY_VALUE(DeviceData,
  440. TRUE, // software branch
  441. SOF_MODIFY_KEY,
  442. sizeof(SOF_MODIFY_KEY),
  443. &clocksPerFrame,
  444. sizeof(clocksPerFrame));
  445. // if this call fails we just use the default
  446. if (mpStatus == USBMP_STATUS_SUCCESS) {
  447. SET_FLAG(DeviceData->Flags, HMP_FLAG_SOF_MODIFY_VALUE);
  448. DeviceData->SofModifyValue = clocksPerFrame;
  449. OHCI_KdPrint((DeviceData, 1, "'Recommended Clocks/Frame %d \n",
  450. clocksPerFrame));
  451. }
  452. }
  453. VOID
  454. USBMPFN
  455. OHCI_StopController(
  456. PDEVICE_DATA DeviceData,
  457. BOOLEAN HwPresent
  458. )
  459. /*++
  460. Routine Description:
  461. Arguments:
  462. Return Value:
  463. --*/
  464. {
  465. HC_CONTROL control;
  466. PHC_OPERATIONAL_REGISTER hc = NULL;
  467. hc = DeviceData->HC;
  468. control.ul = READ_REGISTER_ULONG(&hc->HcControl.ul);
  469. control.ul &= ~(HcCtrl_PeriodicListEnable |
  470. HcCtrl_IsochronousEnable |
  471. HcCtrl_ControlListEnable |
  472. HcCtrl_BulkListEnable |
  473. HcCtrl_RemoteWakeupEnable);
  474. control.HostControllerFunctionalState =
  475. HcHCFS_USBSuspend;
  476. WRITE_REGISTER_ULONG(&hc->HcControl.ul, control.ul);
  477. WRITE_REGISTER_ULONG(&hc->HcInterruptDisable, 0xFFFFffff);
  478. WRITE_REGISTER_ULONG(&hc->HcInterruptStatus, 0xFFFFffff);
  479. }
  480. USB_MINIPORT_STATUS
  481. USBMPFN
  482. OHCI_StartController(
  483. PDEVICE_DATA DeviceData,
  484. PHC_RESOURCES HcResources
  485. )
  486. /*++
  487. Routine Description:
  488. Arguments:
  489. Return Value:
  490. --*/
  491. {
  492. USB_MINIPORT_STATUS mpStatus;
  493. PHC_OPERATIONAL_REGISTER hc = NULL;
  494. PUCHAR endCommonBuffer;
  495. OHCI_KdPrint((DeviceData, 1, "'OPENHCI Miniport\n"));
  496. // clear the suspend flag in case this is a restart
  497. CLEAR_FLAG(DeviceData->Flags, HMP_FLAG_SUSPENDED);
  498. // assume success
  499. mpStatus = USBMP_STATUS_SUCCESS;
  500. OHCI_ASSERT(DeviceData, HcResources->CommonBufferVa != NULL);
  501. // validate our resources
  502. if ((HcResources->Flags & (HCR_MEM_REGS | HCR_IRQ)) !=
  503. (HCR_MEM_REGS | HCR_IRQ)) {
  504. mpStatus = USBMP_STATUS_INIT_FAILURE;
  505. }
  506. // set up or device data structure
  507. hc = DeviceData->HC = HcResources->DeviceRegisters;
  508. DeviceData->Sig = SIG_OHCI_DD;
  509. DeviceData->ControllerFlavor =
  510. HcResources->ControllerFlavor;
  511. if (DeviceData->ControllerFlavor == OHCI_Hydra) {
  512. OHCI_KdPrint((DeviceData, 1, "'OPENHCI Hydra Detected\n"));
  513. }
  514. OHCI_GetRegistryParameters(DeviceData);
  515. // init misc fields in the extension
  516. // attempt to stop the BIOS
  517. if (mpStatus == USBMP_STATUS_SUCCESS) {
  518. mpStatus = OHCI_StopBIOS(DeviceData, HcResources);
  519. }
  520. if (mpStatus == USBMP_STATUS_SUCCESS) {
  521. PUCHAR staticEDs;
  522. HW_32BIT_PHYSICAL_ADDRESS staticEDsPhys;
  523. // carve the common buffer block in to HCCA and
  524. // static EDs
  525. //
  526. // set the HCCA and
  527. // set up the schedule
  528. DeviceData->HcHCCA = (PHCCA_BLOCK)
  529. HcResources->CommonBufferVa;
  530. DeviceData->HcHCCAPhys =
  531. HcResources->CommonBufferPhys;
  532. endCommonBuffer = HcResources->CommonBufferVa +
  533. OHCI_COMMON_BUFFER_SIZE;
  534. staticEDs = HcResources->CommonBufferVa + sizeof(HCCA_BLOCK);
  535. staticEDsPhys = HcResources->CommonBufferPhys + sizeof(HCCA_BLOCK);
  536. mpStatus = OHCI_InitializeSchedule(DeviceData,
  537. staticEDs,
  538. staticEDsPhys,
  539. endCommonBuffer);
  540. }
  541. if (mpStatus == USBMP_STATUS_SUCCESS) {
  542. // got resources and schedule
  543. // init the controller
  544. mpStatus = OHCI_InitializeHardware(DeviceData);
  545. }
  546. if (mpStatus == USBMP_STATUS_SUCCESS) {
  547. HC_CONTROL control;
  548. // When the HC is in the operational state, HccaPad1 should be set to
  549. // zero every time the HC updates HccaFrameNumer. Preset HccaPad1 to
  550. // zero before entering the operational state. OHCI_CheckController()
  551. // should always find a zero value in HccaPad1 when the HC is in the
  552. // operational state.
  553. //
  554. DeviceData->HcHCCA->HccaPad1 = 0;
  555. // activate the controller
  556. control.ul = READ_REGISTER_ULONG(&hc->HcControl.ul);
  557. control.HostControllerFunctionalState = HcHCFS_USBOperational;
  558. // enable control and bulk interrupt and iso we only disable
  559. // them if we need to remove ED or if the controller
  560. // is idle.
  561. control.ControlListEnable = 1;
  562. control.BulkListEnable = 1;
  563. control.PeriodicListEnable = 1;
  564. control.IsochronousEnable = 1;
  565. WRITE_REGISTER_ULONG(&hc->HcControl.ul, control.ul);
  566. // enable power for the root hub
  567. // since messing with the 'operatinal state' messes
  568. // up the root hub we the do the global power set here
  569. WRITE_REGISTER_ULONG(&hc->HcRhStatus, HcRhS_SetGlobalPower);
  570. } else {
  571. DEBUG_BREAK(DeviceData);
  572. }
  573. return mpStatus;
  574. }
  575. VOID
  576. USBMPFN
  577. OHCI_DisableInterrupts(
  578. PDEVICE_DATA DeviceData
  579. )
  580. /*++
  581. Routine Description:
  582. Arguments:
  583. Return Value:
  584. --*/
  585. {
  586. PHC_OPERATIONAL_REGISTER hc = NULL;
  587. // set up or device data structure
  588. hc = DeviceData->HC;
  589. WRITE_REGISTER_ULONG(&hc->HcInterruptDisable,
  590. HcInt_MasterInterruptEnable);
  591. }
  592. VOID
  593. USBMPFN
  594. OHCI_FlushInterrupts(
  595. PDEVICE_DATA DeviceData
  596. )
  597. /*++
  598. Routine Description:
  599. Arguments:
  600. Return Value:
  601. --*/
  602. {
  603. //nop
  604. }
  605. VOID
  606. USBMPFN
  607. OHCI_EnableInterrupts(
  608. PDEVICE_DATA DeviceData
  609. )
  610. /*++
  611. Routine Description:
  612. Arguments:
  613. Return Value:
  614. --*/
  615. {
  616. PHC_OPERATIONAL_REGISTER hc = NULL;
  617. // set up or device data structure
  618. hc = DeviceData->HC;
  619. // activate the controllers interrupt
  620. WRITE_REGISTER_ULONG(&hc->HcInterruptEnable,
  621. HcInt_MasterInterruptEnable);
  622. }
  623. VOID
  624. OHCI_InsertEndpointInSchedule(
  625. PDEVICE_DATA DeviceData,
  626. PENDPOINT_DATA EndpointData
  627. )
  628. /*++
  629. Routine Description:
  630. Insert an endpoint into the h/w schedule
  631. Arguments:
  632. --*/
  633. {
  634. PHC_STATIC_ED_DATA staticEd;
  635. PHCD_ENDPOINT_DESCRIPTOR ed;
  636. staticEd = EndpointData->StaticEd;
  637. ed = EndpointData->HcdEd;
  638. //
  639. // Link endpoint descriptor into HCD tracking queue
  640. //
  641. // each static ED stucture conatins a list of real
  642. // EDs (that are for transfers)
  643. //
  644. // the HW list is linear with :
  645. // TransferHwED->TransferHwED->0
  646. if (IsListEmpty(&staticEd->TransferEdList)) {
  647. //
  648. // list is currently empty,
  649. // link it to the head of the hw queue
  650. //
  651. InsertHeadList(&staticEd->TransferEdList, &ed->SwLink.List);
  652. if (staticEd->EdFlags & EDFLAG_REGISTER) {
  653. // control and bulk EDs are linked thru a hw register
  654. // in the hc
  655. //
  656. // the HW list is linear with :
  657. // TransferHwED->TransferHwED->0
  658. //
  659. // update the hardware register that points to the list head
  660. LOGENTRY(DeviceData, G, '_IN1', 0, ed, staticEd);
  661. // next points to static head
  662. ed->HwED.NextED = READ_REGISTER_ULONG(staticEd->PhysicalHead);
  663. // new head is this ed
  664. WRITE_REGISTER_ULONG(staticEd->PhysicalHead, ed->PhysicalAddress);
  665. } else {
  666. // for interrupt we have two cases
  667. //
  668. // case 1:
  669. // 32ms interrupt, PhysicalHead is the address of the entry
  670. // in the HCCA that points to the first 32 ms list
  671. // (ie &HCCA[n] == physicalHead),
  672. // so we end up with:
  673. // HCCA[n]->TransferHwED->TransferHwED->StaticEd(32)->
  674. //
  675. // case 2:
  676. // not 32ms interrupt, PhysicaHead is the address of the
  677. // NextED entry in the static HwED for the list list,
  678. // (ie &HwED->nextEd == physicalHead)
  679. // so we end up with
  680. // StaticEd->TransferHwED->TransferHwED->NextStaticED
  681. //
  682. LOGENTRY(DeviceData, G, '_IN2', staticEd->PhysicalHead,
  683. ed, staticEd);
  684. // tail points to old list head HW ed head
  685. ed->HwED.NextED = *staticEd->PhysicalHead;
  686. // new head is this ed
  687. *staticEd->PhysicalHead = ed->PhysicalAddress;
  688. }
  689. } else {
  690. PHCD_ENDPOINT_DESCRIPTOR tailEd;
  691. //
  692. // Something already on the list,
  693. // Link ED into tail of transferEd list
  694. //
  695. tailEd = CONTAINING_RECORD(staticEd->TransferEdList.Blink,
  696. HCD_ENDPOINT_DESCRIPTOR,
  697. SwLink);
  698. LOGENTRY(DeviceData, G, '_Led', 0, tailEd, staticEd);
  699. //LOGENTRY(G, 'INT1', list, ed, 0);
  700. InsertTailList(&staticEd->TransferEdList, &ed->SwLink.List);
  701. ed->HwED.NextED = 0;
  702. tailEd->HwED.NextED = ed->PhysicalAddress;
  703. }
  704. }
  705. VOID
  706. OHCI_RemoveEndpointFromSchedule(
  707. PDEVICE_DATA DeviceData,
  708. PENDPOINT_DATA EndpointData
  709. )
  710. /*++
  711. Routine Description:
  712. Remove an endpoint from the h/w schedule
  713. Arguments:
  714. --*/
  715. {
  716. PHC_STATIC_ED_DATA staticEd;
  717. PHCD_ENDPOINT_DESCRIPTOR ed, previousEd;
  718. staticEd = EndpointData->StaticEd;
  719. ed = EndpointData->HcdEd;
  720. OHCI_ASSERT_ED(DeviceData, ed);
  721. LOGENTRY(DeviceData, G, '_Red', EndpointData, staticEd, 0);
  722. // Unlink the ED from the physical ED list
  723. // two cases:
  724. if (&staticEd->TransferEdList == ed->SwLink.List.Blink) {
  725. // case 1, we are at the head of the list
  726. // make the next guy the head
  727. LOGENTRY(DeviceData, G, '_yHD', EndpointData, 0, 0);
  728. if (ed->EdFlags & EDFLAG_REGISTER) {
  729. WRITE_REGISTER_ULONG(staticEd->PhysicalHead, ed->HwED.NextED);
  730. } else {
  731. *staticEd->PhysicalHead = ed->HwED.NextED;
  732. }
  733. } else {
  734. // case 2 we are not at the head
  735. // use the sw link to get the previus ed
  736. previousEd =
  737. CONTAINING_RECORD(ed->SwLink.List.Blink,
  738. HCD_ENDPOINT_DESCRIPTOR,
  739. SwLink);
  740. LOGENTRY(DeviceData, G, '_nHD', EndpointData, previousEd, 0);
  741. OHCI_ASSERT_ED(DeviceData, previousEd);
  742. previousEd->HwED.NextED = ed->HwED.NextED;
  743. }
  744. // remove ourselves from the software list
  745. RemoveEntryList(&ed->SwLink.List);
  746. // on no list
  747. EndpointData->StaticEd = NULL;
  748. }
  749. PHCD_ENDPOINT_DESCRIPTOR
  750. OHCI_InitializeED(
  751. PDEVICE_DATA DeviceData,
  752. PENDPOINT_DATA EndpointData,
  753. PHCD_ENDPOINT_DESCRIPTOR Ed,
  754. PHCD_TRANSFER_DESCRIPTOR DummyTd,
  755. HW_32BIT_PHYSICAL_ADDRESS HwPhysAddress
  756. )
  757. /*++
  758. Routine Description:
  759. Initialize an ED for inserting in to the
  760. schedule
  761. returns a ptr to the ED passed in
  762. Arguments:
  763. --*/
  764. {
  765. RtlZeroMemory(Ed, sizeof(*Ed));
  766. Ed->PhysicalAddress = HwPhysAddress;
  767. ENDPOINT_DATA_PTR(Ed->EndpointData) = EndpointData;
  768. Ed->Sig = SIG_HCD_ED;
  769. // init the hw descriptor
  770. Ed->HwED.FunctionAddress = EndpointData->Parameters.DeviceAddress;
  771. Ed->HwED.EndpointNumber = EndpointData->Parameters.EndpointAddress;
  772. if (EndpointData->Parameters.TransferType == Control) {
  773. Ed->HwED.Direction = HcEDDirection_Defer;
  774. } else if (EndpointData->Parameters.TransferDirection == In) {
  775. Ed->HwED.Direction = HcEDDirection_In;
  776. } else {
  777. Ed->HwED.Direction = HcEDDirection_Out;
  778. }
  779. Ed->HwED.sKip = 1;
  780. if (EndpointData->Parameters.DeviceSpeed == LowSpeed) {
  781. Ed->HwED.LowSpeed = 1;
  782. }
  783. if (EndpointData->Parameters.TransferType == Isochronous) {
  784. Ed->HwED.Isochronous = 1;
  785. }
  786. Ed->HwED.MaxPacket = EndpointData->Parameters.MaxPacketSize;
  787. // set head tail ptr to point to the dummy TD
  788. Ed->HwED.TailP = Ed->HwED.HeadP = DummyTd->PhysicalAddress;
  789. SET_FLAG(DummyTd->Flags, TD_FLAG_BUSY);
  790. EndpointData->HcdHeadP = EndpointData->HcdTailP = DummyTd;
  791. return Ed;
  792. }
  793. PHCD_TRANSFER_DESCRIPTOR
  794. OHCI_InitializeTD(
  795. PDEVICE_DATA DeviceData,
  796. PENDPOINT_DATA EndpointData,
  797. PHCD_TRANSFER_DESCRIPTOR Td,
  798. HW_32BIT_PHYSICAL_ADDRESS HwPhysAddress
  799. )
  800. /*++
  801. Routine Description:
  802. Initialize an ED for insertin in to the
  803. schedule
  804. returns a ptr to the ED passed in
  805. Arguments:
  806. --*/
  807. {
  808. RtlZeroMemory(Td, sizeof(*Td));
  809. Td->PhysicalAddress = HwPhysAddress;
  810. ENDPOINT_DATA_PTR(Td->EndpointData) = EndpointData;
  811. Td->Flags = 0;
  812. Td->Sig = SIG_HCD_TD;
  813. TRANSFER_CONTEXT_PTR(Td->TransferContext) = FREE_TD_CONTEXT;
  814. return Td;
  815. }
  816. USB_MINIPORT_STATUS
  817. OHCI_OpenEndpoint(
  818. PDEVICE_DATA DeviceData,
  819. PENDPOINT_PARAMETERS EndpointParameters,
  820. PENDPOINT_DATA EndpointData
  821. )
  822. /*++
  823. Routine Description:
  824. Arguments:
  825. Return Value:
  826. --*/
  827. {
  828. USB_MINIPORT_STATUS mpStatus;
  829. EndpointData->Sig = SIG_EP_DATA;
  830. // save a copy of the parameters
  831. EndpointData->Parameters = *EndpointParameters;
  832. EndpointData->Flags = 0;
  833. EndpointData->PendingTransfers = 0;
  834. InitializeListHead(&EndpointData->DoneTdList);
  835. switch (EndpointParameters->TransferType) {
  836. case Control:
  837. mpStatus = OHCI_OpenControlEndpoint(
  838. DeviceData,
  839. EndpointParameters,
  840. EndpointData);
  841. break;
  842. case Interrupt:
  843. mpStatus = OHCI_OpenInterruptEndpoint(
  844. DeviceData,
  845. EndpointParameters,
  846. EndpointData);
  847. break;
  848. case Bulk:
  849. mpStatus = OHCI_OpenBulkEndpoint(
  850. DeviceData,
  851. EndpointParameters,
  852. EndpointData);
  853. break;
  854. case Isochronous:
  855. mpStatus = OHCI_OpenIsoEndpoint(
  856. DeviceData,
  857. EndpointParameters,
  858. EndpointData);
  859. break;
  860. default:
  861. mpStatus = USBMP_STATUS_NOT_SUPPORTED;
  862. }
  863. return mpStatus;
  864. }
  865. USB_MINIPORT_STATUS
  866. OHCI_PokeEndpoint(
  867. PDEVICE_DATA DeviceData,
  868. PENDPOINT_PARAMETERS EndpointParameters,
  869. PENDPOINT_DATA EndpointData
  870. )
  871. /*++
  872. Routine Description:
  873. Arguments:
  874. Return Value:
  875. --*/
  876. {
  877. PHCD_ENDPOINT_DESCRIPTOR ed;
  878. ULONG oldBandwidth;
  879. LOGENTRY(DeviceData, G, '_Pok', EndpointData,
  880. EndpointParameters, 0);
  881. ed = EndpointData->HcdEd;
  882. oldBandwidth = EndpointData->Parameters.Bandwidth;
  883. EndpointData->Parameters = *EndpointParameters;
  884. ed->HwED.FunctionAddress =
  885. EndpointData->Parameters.DeviceAddress;
  886. ed->HwED.MaxPacket =
  887. EndpointData->Parameters.MaxPacketSize;
  888. // adjust bw if necessary
  889. if (EndpointData->Parameters.TransferType == Isochronous ||
  890. EndpointData->Parameters.TransferType == Interrupt) {
  891. // subtract the old bandwidth
  892. EndpointData->StaticEd->AllocatedBandwidth -=
  893. oldBandwidth;
  894. // add on new bw
  895. EndpointData->StaticEd->AllocatedBandwidth +=
  896. EndpointData->Parameters.Bandwidth;
  897. }
  898. return USBMP_STATUS_SUCCESS;
  899. }
  900. VOID
  901. OHCI_QueryEndpointRequirements(
  902. PDEVICE_DATA DeviceData,
  903. PENDPOINT_PARAMETERS EndpointParameters,
  904. PENDPOINT_REQUIREMENTS EndpointRequirements
  905. )
  906. /*++
  907. Routine Description:
  908. compute how much common buffer we will need
  909. for this endpoint
  910. Arguments:
  911. Return Value:
  912. --*/
  913. {
  914. switch (EndpointParameters->TransferType) {
  915. case Control:
  916. EndpointRequirements->MinCommonBufferBytes =
  917. sizeof(HCD_ENDPOINT_DESCRIPTOR) +
  918. TDS_PER_CONTROL_ENDPOINT*sizeof(HCD_TRANSFER_DESCRIPTOR);
  919. EndpointRequirements->MaximumTransferSize =
  920. MAX_CONTROL_TRANSFER_SIZE;
  921. break;
  922. case Interrupt:
  923. EndpointRequirements->MinCommonBufferBytes =
  924. sizeof(HCD_ENDPOINT_DESCRIPTOR) +
  925. TDS_PER_INTERRUPT_ENDPOINT*sizeof(HCD_TRANSFER_DESCRIPTOR);
  926. #ifdef TEST_SPLIT
  927. EndpointRequirements->MaximumTransferSize =
  928. EndpointParameters->MaxPacketSize;
  929. #else
  930. EndpointRequirements->MaximumTransferSize =
  931. MAX_INTERRUPT_TRANSFER_SIZE;
  932. #endif
  933. break;
  934. case Bulk:
  935. EndpointRequirements->MinCommonBufferBytes =
  936. sizeof(HCD_ENDPOINT_DESCRIPTOR) +
  937. TDS_PER_BULK_ENDPOINT*sizeof(HCD_TRANSFER_DESCRIPTOR);
  938. #ifdef TEST_SPLIT
  939. EndpointRequirements->MaximumTransferSize = 4096;
  940. #else
  941. EndpointRequirements->MaximumTransferSize =
  942. MAX_BULK_TRANSFER_SIZE;
  943. #endif
  944. break;
  945. case Isochronous:
  946. // BUGBUG NOTE
  947. // the 1.1 USBDI caped requests at 255 packets per urb
  948. EndpointRequirements->MinCommonBufferBytes =
  949. sizeof(HCD_ENDPOINT_DESCRIPTOR) +
  950. TDS_PER_ISO_ENDPOINT*sizeof(HCD_TRANSFER_DESCRIPTOR);
  951. EndpointRequirements->MaximumTransferSize =
  952. MAX_ISO_TRANSFER_SIZE;
  953. break;
  954. default:
  955. TEST_TRAP();
  956. }
  957. }
  958. VOID
  959. OHCI_CloseEndpoint(
  960. PDEVICE_DATA DeviceData,
  961. PENDPOINT_DATA EndpointData
  962. )
  963. /*++
  964. Routine Description:
  965. Arguments:
  966. Return Value:
  967. --*/
  968. {
  969. // nothing to do here
  970. }
  971. VOID
  972. OHCI_PollEndpoint(
  973. PDEVICE_DATA DeviceData,
  974. PENDPOINT_DATA EndpointData
  975. )
  976. /*++
  977. Routine Description:
  978. Arguments:
  979. Return Value:
  980. --*/
  981. {
  982. switch(EndpointData->Parameters.TransferType) {
  983. case Control:
  984. case Interrupt:
  985. case Bulk:
  986. OHCI_PollAsyncEndpoint(DeviceData, EndpointData);
  987. break;
  988. case Isochronous:
  989. OHCI_PollIsoEndpoint(DeviceData, EndpointData);
  990. break;
  991. }
  992. }
  993. VOID
  994. OHCI_PollController(
  995. PDEVICE_DATA DeviceData
  996. )
  997. /*++
  998. Routine Description:
  999. Arguments:
  1000. Return Value:
  1001. --*/
  1002. {
  1003. BOOLEAN hcOk = TRUE;
  1004. PHC_OPERATIONAL_REGISTER hc;
  1005. ULONG irqStatus;
  1006. hc = DeviceData->HC;
  1007. if (TEST_FLAG(DeviceData->Flags, HMP_FLAG_SUSPENDED)) {
  1008. ULONG ps;
  1009. ULONG p;
  1010. // indicates polling while controller is
  1011. // suspended but in D0
  1012. //
  1013. // should invalidate the root hub only if changes
  1014. // are detected on the root ports.
  1015. //
  1016. // check all the ports
  1017. //
  1018. for (p=0; p< DeviceData->NumberOfPorts; p++) {
  1019. ps = READ_REGISTER_ULONG(&hc->HcRhPortStatus[p]);
  1020. if (ps & HcRhPS_ConnectStatusChange) {
  1021. //TEST_TRAP();
  1022. LOGENTRY(DeviceData, G, '_rPS', DeviceData, 0, 0);
  1023. USBPORT_INVALIDATE_ROOTHUB(DeviceData);
  1024. break;
  1025. }
  1026. }
  1027. return;
  1028. }
  1029. #if 0
  1030. // see if the controller is still operating
  1031. fn = DeviceData->HcHCCA->HccaFrameNumber;
  1032. if (DeviceData->LastFn && DeviceData->LastFn == fn) {
  1033. hcOk = FALSE;
  1034. }
  1035. if (hcOK) {
  1036. DeviceData->LastFn = fn;
  1037. } else {
  1038. OHCI_KdPrint((DeviceData, 0, "Controller has crashed\n");
  1039. // bugbug, signal USBPORT to attempt recovery
  1040. TEST_TRAP();
  1041. }
  1042. #endif
  1043. }
  1044. VOID
  1045. OHCI_AbortTransfer(
  1046. PDEVICE_DATA DeviceData,
  1047. PENDPOINT_DATA EndpointData,
  1048. PTRANSFER_CONTEXT AbortTransferContext,
  1049. PULONG BytesTransferred
  1050. )
  1051. /*++
  1052. Routine Description:
  1053. Called when a transfer needs to be removed
  1054. from the schedule.
  1055. This process is vertually identical regardless
  1056. of transfer type
  1057. Arguments:
  1058. Return Value:
  1059. --*/
  1060. {
  1061. PHCD_TRANSFER_DESCRIPTOR td, currentTd, tmpTd;
  1062. PHCD_ENDPOINT_DESCRIPTOR ed;
  1063. ULONG i;
  1064. BOOLEAN found = FALSE;
  1065. BOOLEAN iso = FALSE; // assume its async
  1066. if (EndpointData->Parameters.TransferType == Isochronous) {
  1067. iso = TRUE;
  1068. }
  1069. ed = EndpointData->HcdEd;
  1070. //
  1071. // The endpoint should have the skip bit set
  1072. // ie 'paused'
  1073. //
  1074. OHCI_ASSERT(DeviceData, ed->HwED.sKip == 1);
  1075. LOGENTRY(DeviceData, G, '_abr', ed, AbortTransferContext,
  1076. EndpointData);
  1077. // one less pending transfer
  1078. EndpointData->PendingTransfers--;
  1079. // our mission now is to remove all TDs associated with
  1080. // this transfer
  1081. // get the 'currentTD'
  1082. currentTd = (PHCD_TRANSFER_DESCRIPTOR)
  1083. USBPORT_PHYSICAL_TO_VIRTUAL(ed->HwED.HeadP & ~HcEDHeadP_FLAGS,
  1084. DeviceData,
  1085. EndpointData);
  1086. // we have three possible cases to deal with:
  1087. // case 1: the transfer is current, headp points to a TD
  1088. // associated with this transfer
  1089. // case 2: transfer is already done, we just need to free
  1090. // the TDs
  1091. // case 3: transfer is not processed, we need to link
  1092. // the current transfer to the next.
  1093. if (TRANSFER_CONTEXT_PTR(currentTd->TransferContext)
  1094. == AbortTransferContext) {
  1095. LOGENTRY(DeviceData, G, '_aCU', currentTd,
  1096. 0, 0);
  1097. // case 1: transfer is current
  1098. found = TRUE;
  1099. // set Headp to next transfer and update sw pointers in ED
  1100. tmpTd = AbortTransferContext->NextXferTd;
  1101. // preserve the data toggle for whatever the transfer
  1102. ed->HwED.HeadP = tmpTd->PhysicalAddress |
  1103. (ed->HwED.HeadP & HcEDHeadP_CARRY);
  1104. EndpointData->HcdHeadP = tmpTd;
  1105. // loop thru all TDs and free the ones for this tarnsfer
  1106. for (i=0; i<EndpointData->TdCount; i++) {
  1107. tmpTd = &EndpointData->TdList->Td[i];
  1108. if (TRANSFER_CONTEXT_PTR(tmpTd->TransferContext)
  1109. == AbortTransferContext) {
  1110. if (iso) {
  1111. OHCI_ProcessDoneIsoTd(DeviceData,
  1112. tmpTd,
  1113. FALSE);
  1114. } else {
  1115. OHCI_ProcessDoneAsyncTd(DeviceData,
  1116. tmpTd,
  1117. FALSE);
  1118. }
  1119. }
  1120. }
  1121. } else {
  1122. // not current, walk the the list of TDs from the
  1123. // last known HeadP to the current TD if we find it
  1124. // it is already done (case 2).
  1125. // Issue to investigate: What if we find some TDs which belong to
  1126. // this transfer but we stop walking the TD list when we hit currentTd
  1127. // and there are still TDs queued which belong to this transfer? If
  1128. // they stay stuck on the HW and the transfer is freed that would be
  1129. // bad.
  1130. td = EndpointData->HcdHeadP;
  1131. while (td != currentTd) {
  1132. PTRANSFER_CONTEXT transfer;
  1133. transfer = TRANSFER_CONTEXT_PTR(td->TransferContext);
  1134. ASSERT_TRANSFER(DeviceData, transfer);
  1135. if (transfer == AbortTransferContext) {
  1136. // case 2 the transfer TDs have already
  1137. // been comlpleted by the hardware
  1138. found = TRUE;
  1139. LOGENTRY(DeviceData, G, '_aDN', currentTd,
  1140. td, 0);
  1141. // free this TD
  1142. tmpTd = td;
  1143. td = TRANSFER_DESCRIPTOR_PTR(td->NextHcdTD);
  1144. // if this TD was the head we need to bump the
  1145. // headp
  1146. if (tmpTd == EndpointData->HcdHeadP) {
  1147. EndpointData->HcdHeadP = td;
  1148. }
  1149. if (iso) {
  1150. OHCI_ProcessDoneIsoTd(DeviceData,
  1151. tmpTd,
  1152. FALSE);
  1153. } else {
  1154. OHCI_ProcessDoneAsyncTd(DeviceData,
  1155. tmpTd,
  1156. FALSE);
  1157. }
  1158. } else {
  1159. // we walk the SW links
  1160. td = TRANSFER_DESCRIPTOR_PTR(td->NextHcdTD);
  1161. }
  1162. }
  1163. }
  1164. if (!found) {
  1165. PHCD_TRANSFER_DESCRIPTOR firstTd, lastTd;
  1166. PTRANSFER_CONTEXT prevTransfer;
  1167. // case 3 the transfer is not current and not done.
  1168. // 1. we need to find it.
  1169. // 2. unlink it from the prevoius transfer
  1170. // 3. free the TDs
  1171. // 4. link prev transfer to the next
  1172. td = EndpointData->HcdHeadP;
  1173. firstTd = NULL;
  1174. LOGENTRY(DeviceData, G, '_abP', EndpointData->HcdHeadP,
  1175. EndpointData->HcdTailP, currentTd);
  1176. // start at the current HeadP and find the first
  1177. // td for this transfer
  1178. lastTd = td;
  1179. while (td != EndpointData->HcdTailP) {
  1180. PTRANSFER_CONTEXT transfer;
  1181. transfer = TRANSFER_CONTEXT_PTR(td->TransferContext);
  1182. ASSERT_TRANSFER(DeviceData, transfer);
  1183. if (transfer == AbortTransferContext) {
  1184. // found it
  1185. LOGENTRY(DeviceData, G, '_fnT', transfer,
  1186. td, 0);
  1187. firstTd = td;
  1188. break;
  1189. } else {
  1190. lastTd = td;
  1191. td = TRANSFER_DESCRIPTOR_PTR(td->NextHcdTD);
  1192. }
  1193. }
  1194. OHCI_ASSERT(DeviceData, firstTd != NULL);
  1195. // found the first TD, walk to the HcdTailP or the
  1196. // next transfer and free these TDs
  1197. td = firstTd;
  1198. while (td != EndpointData->HcdTailP) {
  1199. tmpTd = td;
  1200. td = TRANSFER_DESCRIPTOR_PTR(td->NextHcdTD);
  1201. if (iso) {
  1202. OHCI_ProcessDoneIsoTd(DeviceData,
  1203. tmpTd,
  1204. FALSE);
  1205. } else {
  1206. OHCI_ProcessDoneAsyncTd(DeviceData,
  1207. tmpTd,
  1208. FALSE);
  1209. }
  1210. if (TRANSFER_CONTEXT_PTR(td->TransferContext) !=
  1211. AbortTransferContext) {
  1212. break;
  1213. }
  1214. }
  1215. LOGENTRY(DeviceData, G, '_NnT', 0, td, 0);
  1216. // td should now point to the next Transfer (or the
  1217. // tail)
  1218. OHCI_ASSERT(DeviceData,
  1219. TRANSFER_CONTEXT_PTR(td->TransferContext) !=
  1220. AbortTransferContext);
  1221. // BUGBUG toggle?
  1222. // link last TD of the prev transfer to this TD
  1223. //
  1224. prevTransfer = TRANSFER_CONTEXT_PTR(lastTd->TransferContext);
  1225. prevTransfer->NextXferTd = td;
  1226. TRANSFER_DESCRIPTOR_PTR(lastTd->NextHcdTD) = td;
  1227. lastTd->HwTD.NextTD = td->PhysicalAddress;
  1228. }
  1229. *BytesTransferred = AbortTransferContext->BytesTransferred;
  1230. }
  1231. USB_MINIPORT_STATUS
  1232. OHCI_SubmitIsoTransfer(
  1233. PDEVICE_DATA DeviceData,
  1234. PENDPOINT_DATA EndpointData,
  1235. PTRANSFER_PARAMETERS TransferParameters,
  1236. PTRANSFER_CONTEXT TransferContext,
  1237. PMINIPORT_ISO_TRANSFER IsoTransfer
  1238. )
  1239. {
  1240. USB_MINIPORT_STATUS mpStatus;
  1241. // init the context
  1242. RtlZeroMemory(TransferContext, sizeof(*TransferContext));
  1243. TransferContext->Sig = SIG_OHCI_TRANSFER;
  1244. TransferContext->UsbdStatus = USBD_STATUS_SUCCESS;
  1245. TransferContext->EndpointData = EndpointData;
  1246. TransferContext->TransferParameters = TransferParameters;
  1247. OHCI_ASSERT(DeviceData,
  1248. EndpointData->Parameters.TransferType == Isochronous);
  1249. mpStatus =
  1250. OHCI_IsoTransfer(DeviceData,
  1251. EndpointData,
  1252. TransferParameters,
  1253. TransferContext,
  1254. IsoTransfer);
  1255. return mpStatus;
  1256. }
  1257. USB_MINIPORT_STATUS
  1258. OHCI_SubmitTransfer(
  1259. PDEVICE_DATA DeviceData,
  1260. PENDPOINT_DATA EndpointData,
  1261. PTRANSFER_PARAMETERS TransferParameters,
  1262. PTRANSFER_CONTEXT TransferContext,
  1263. PTRANSFER_SG_LIST TransferSGList
  1264. )
  1265. {
  1266. USB_MINIPORT_STATUS mpStatus;
  1267. // init the context
  1268. RtlZeroMemory(TransferContext, sizeof(*TransferContext));
  1269. TransferContext->Sig = SIG_OHCI_TRANSFER;
  1270. TransferContext->UsbdStatus = USBD_STATUS_SUCCESS;
  1271. TransferContext->EndpointData = EndpointData;
  1272. TransferContext->TransferParameters = TransferParameters;
  1273. switch (EndpointData->Parameters.TransferType) {
  1274. case Control:
  1275. mpStatus =
  1276. OHCI_ControlTransfer(DeviceData,
  1277. EndpointData,
  1278. TransferParameters,
  1279. TransferContext,
  1280. TransferSGList);
  1281. break;
  1282. case Interrupt:
  1283. case Bulk:
  1284. mpStatus =
  1285. OHCI_BulkOrInterruptTransfer(DeviceData,
  1286. EndpointData,
  1287. TransferParameters,
  1288. TransferContext,
  1289. TransferSGList);
  1290. break;
  1291. default:
  1292. TEST_TRAP();
  1293. }
  1294. return mpStatus;
  1295. }
  1296. PHCD_TRANSFER_DESCRIPTOR
  1297. OHCI_AllocTd(
  1298. PDEVICE_DATA DeviceData,
  1299. PENDPOINT_DATA EndpointData
  1300. )
  1301. /*++
  1302. Routine Description:
  1303. Allocate a TD, it is OK to fail
  1304. Arguments:
  1305. Return Value:
  1306. --*/
  1307. {
  1308. ULONG i;
  1309. PHCD_TRANSFER_DESCRIPTOR td;
  1310. for (i=0; i<EndpointData->TdCount; i++) {
  1311. td = &EndpointData->TdList->Td[i];
  1312. if (!(td->Flags & TD_FLAG_BUSY)) {
  1313. SET_FLAG(td->Flags, TD_FLAG_BUSY);
  1314. LOGENTRY(DeviceData, G, '_aTD', td, 0, 0);
  1315. OHCI_ASSERT(DeviceData, td->DoneLink.Flink == NULL &&
  1316. td->DoneLink.Blink == NULL);
  1317. return td;
  1318. }
  1319. }
  1320. // if we don't have enough TDs the caller has to handle this case.
  1321. // generally we make sure we have enough before we ever call this
  1322. // function so the callers just assert that the return is not
  1323. // USB_BAD_PTR
  1324. return USB_BAD_PTR;
  1325. }
  1326. ULONG
  1327. OHCI_FreeTds(
  1328. PDEVICE_DATA DeviceData,
  1329. PENDPOINT_DATA EndpointData
  1330. )
  1331. /*++
  1332. Routine Description:
  1333. return the number of free TDs
  1334. Arguments:
  1335. Return Value:
  1336. --*/
  1337. {
  1338. ULONG i;
  1339. PHCD_TRANSFER_DESCRIPTOR td;
  1340. ULONG n=0;
  1341. for (i=0; i<EndpointData->TdCount; i++) {
  1342. td = &EndpointData->TdList->Td[i];
  1343. if (!(td->Flags & TD_FLAG_BUSY)) {
  1344. n++;
  1345. }
  1346. }
  1347. return n;
  1348. }
  1349. VOID
  1350. OHCI_EnableList(
  1351. PDEVICE_DATA DeviceData,
  1352. PENDPOINT_DATA EndpointData
  1353. )
  1354. /*++
  1355. Routine Description:
  1356. Arguments:
  1357. Return Value:
  1358. --*/
  1359. {
  1360. PHC_OPERATIONAL_REGISTER hc;
  1361. ULONG listFilled = 0;
  1362. ULONG temp;
  1363. hc = DeviceData->HC;
  1364. temp = READ_REGISTER_ULONG(&hc->HcControlHeadED);
  1365. if (temp) {
  1366. SET_FLAG(listFilled, HcCmd_ControlListFilled);
  1367. }
  1368. temp = READ_REGISTER_ULONG (&hc->HcBulkHeadED);
  1369. if (temp) {
  1370. SET_FLAG(listFilled, HcCmd_BulkListFilled);
  1371. }
  1372. if (EndpointData->Parameters.TransferType == Bulk) {
  1373. SET_FLAG(listFilled, HcCmd_BulkListFilled);
  1374. } else if (EndpointData->Parameters.TransferType == Control) {
  1375. SET_FLAG(listFilled, HcCmd_ControlListFilled);
  1376. }
  1377. WRITE_REGISTER_ULONG(&hc->HcCommandStatus.ul,
  1378. listFilled);
  1379. LOGENTRY(DeviceData, G, '_enL', listFilled, EndpointData, 0);
  1380. }
  1381. VOID
  1382. OHCI_SetEndpointStatus(
  1383. PDEVICE_DATA DeviceData,
  1384. PENDPOINT_DATA EndpointData,
  1385. MP_ENDPOINT_STATUS Status
  1386. )
  1387. /*++
  1388. Routine Description:
  1389. Arguments:
  1390. Return Value:
  1391. --*/
  1392. {
  1393. PHCD_ENDPOINT_DESCRIPTOR ed;
  1394. PHC_OPERATIONAL_REGISTER hc;
  1395. ed = EndpointData->HcdEd;
  1396. switch(Status) {
  1397. case ENDPOINT_STATUS_RUN:
  1398. // clear halt bit
  1399. ed->HwED.HeadP &= ~HcEDHeadP_HALT;
  1400. OHCI_EnableList(DeviceData, EndpointData);
  1401. break;
  1402. case ENDPOINT_STATUS_HALT:
  1403. TEST_TRAP();
  1404. break;
  1405. }
  1406. }
  1407. MP_ENDPOINT_STATUS
  1408. OHCI_GetEndpointStatus(
  1409. PDEVICE_DATA DeviceData,
  1410. PENDPOINT_DATA EndpointData
  1411. )
  1412. /*++
  1413. Routine Description:
  1414. Arguments:
  1415. Return Value:
  1416. --*/
  1417. {
  1418. PHCD_ENDPOINT_DESCRIPTOR ed;
  1419. PHC_OPERATIONAL_REGISTER hc;
  1420. MP_ENDPOINT_STATUS status = ENDPOINT_STATUS_RUN;
  1421. ed = EndpointData->HcdEd;
  1422. if ((ed->HwED.HeadP & HcEDHeadP_HALT) &&
  1423. !TEST_FLAG(ed->EdFlags, EDFLAG_NOHALT)) {
  1424. status = ENDPOINT_STATUS_HALT;
  1425. }
  1426. return status;
  1427. }
  1428. VOID
  1429. OHCI_SetEndpointState(
  1430. PDEVICE_DATA DeviceData,
  1431. PENDPOINT_DATA EndpointData,
  1432. MP_ENDPOINT_STATE State
  1433. )
  1434. /*++
  1435. Routine Description:
  1436. Arguments:
  1437. Return Value:
  1438. --*/
  1439. {
  1440. PHCD_ENDPOINT_DESCRIPTOR ed;
  1441. PHC_OPERATIONAL_REGISTER hc;
  1442. ed = EndpointData->HcdEd;
  1443. switch(State) {
  1444. case ENDPOINT_ACTIVE:
  1445. // clear the skip bit
  1446. ed->HwED.sKip = 0;
  1447. // if its bulk or control set the
  1448. // 'list filled' bits
  1449. OHCI_EnableList(DeviceData, EndpointData);
  1450. break;
  1451. case ENDPOINT_PAUSE:
  1452. ed->HwED.sKip = 1;
  1453. break;
  1454. case ENDPOINT_REMOVE:
  1455. SET_FLAG(ed->EdFlags, EDFLAG_REMOVED);
  1456. ed->HwED.sKip = 1;
  1457. // free the bw
  1458. EndpointData->StaticEd->AllocatedBandwidth -=
  1459. EndpointData->Parameters.Bandwidth;
  1460. OHCI_RemoveEndpointFromSchedule(DeviceData,
  1461. EndpointData);
  1462. break;
  1463. default:
  1464. TEST_TRAP();
  1465. }
  1466. }
  1467. VOID
  1468. OHCI_SetEndpointDataToggle(
  1469. PDEVICE_DATA DeviceData,
  1470. PENDPOINT_DATA EndpointData,
  1471. ULONG Toggle
  1472. )
  1473. /*++
  1474. Routine Description:
  1475. Arguments:
  1476. Toggle is 0 or 1
  1477. Return Value:
  1478. --*/
  1479. {
  1480. PHCD_ENDPOINT_DESCRIPTOR ed;
  1481. ed = EndpointData->HcdEd;
  1482. if (Toggle == 0) {
  1483. ed->HwED.HeadP &= ~HcEDHeadP_CARRY;
  1484. } else {
  1485. ed->HwED.HeadP |= HcEDHeadP_CARRY;
  1486. }
  1487. // we should get here unless we are paused or halted or
  1488. // we have no tranfsers
  1489. OHCI_ASSERT(DeviceData, (ed->HwED.sKip == 1) ||
  1490. (ed->HwED.HeadP & HcEDHeadP_HALT) ||
  1491. ((ed->HwED.HeadP & ~HcEDHeadP_FLAGS) == ed->HwED.TailP));
  1492. LOGENTRY(DeviceData, G, '_stg', EndpointData, 0, Toggle);
  1493. }
  1494. MP_ENDPOINT_STATE
  1495. OHCI_GetEndpointState(
  1496. PDEVICE_DATA DeviceData,
  1497. PENDPOINT_DATA EndpointData
  1498. )
  1499. /*++
  1500. Routine Description:
  1501. Arguments:
  1502. Return Value:
  1503. --*/
  1504. {
  1505. PHCD_ENDPOINT_DESCRIPTOR ed;
  1506. MP_ENDPOINT_STATE state = ENDPOINT_ACTIVE;
  1507. ed = EndpointData->HcdEd;
  1508. if (TEST_FLAG(ed->EdFlags, EDFLAG_REMOVED)) {
  1509. state = ENDPOINT_REMOVE;
  1510. goto OHCI_GetEndpointState_Done;
  1511. }
  1512. if (ed->HwED.sKip == 1) {
  1513. state = ENDPOINT_PAUSE;
  1514. goto OHCI_GetEndpointState_Done;
  1515. }
  1516. OHCI_GetEndpointState_Done:
  1517. LOGENTRY(DeviceData, G, '_eps', EndpointData, 0, state);
  1518. return state;
  1519. }
  1520. #if 0
  1521. VOID
  1522. USBMPFN
  1523. OHCI_SendGoatPacket(
  1524. PDEVICE_DATA DeviceData,
  1525. PUCHAR WorkspaceVirtualAddress,
  1526. HW_32BIT_PHYSICAL_ADDRESS WorkspacePhysicalAddress
  1527. COMPLETION ROUTINE
  1528. )
  1529. /*++
  1530. Routine Description:
  1531. Transmit the 'magic' iso packet.
  1532. This is a fire and forget API so
  1533. Arguments:
  1534. Return Value:
  1535. --*/
  1536. {
  1537. PHC_OPERATIONAL_REGISTER hc;
  1538. PHW_TRANSFER_DESCRIPTOR hwTD;
  1539. // hang a special ISO td of the static is ED
  1540. pch = WorkspaceVirtualAddress;
  1541. phys = WorkspacePhysicalAddress;
  1542. hwTD = pch;
  1543. hwTDPhys = phys;
  1544. pch += xxx;
  1545. phys += xxx
  1546. goatData = pch;
  1547. goatDataPhys = phys;
  1548. pch += sizeof(USB_GOAT_DATA);
  1549. phys += sizeof(USB_GOAT_DATA);
  1550. // initialize the goat packet
  1551. strcpy(goatData, USB_GOAT_DATA,
  1552. hwTD->NextTD = 0;
  1553. hwTD->CBP = goatDataPhys;
  1554. hwTD->BE = dataPhys+sizeof(USB_GOAT_DATA)-1;
  1555. hwTD->ConditionCode = HcCC_NotAccessed;
  1556. hwTD->ErrorCount = 0;
  1557. hwTD->IntDelay = HcTDIntDelay_0ms;
  1558. hwTD->ShortXferOk = 0;
  1559. hwTD->Isochrinous = 1;
  1560. hwTD->FrameCount = 0;
  1561. hwTD->StartFrameNumber = xxx;
  1562. // hang the TD on the static ISO ED
  1563. // clear the skip bit
  1564. }
  1565. #endif
  1566. USB_MINIPORT_STATUS
  1567. USBMPFN
  1568. OHCI_StartSendOnePacket(
  1569. PDEVICE_DATA DeviceData,
  1570. PMP_PACKET_PARAMETERS PacketParameters,
  1571. PUCHAR PacketData,
  1572. PULONG PacketLength,
  1573. PUCHAR WorkspaceVirtualAddress,
  1574. HW_32BIT_PHYSICAL_ADDRESS WorkspacePhysicalAddress,
  1575. ULONG WorkSpaceLength,
  1576. USBD_STATUS *UsbdStatus
  1577. )
  1578. /*++
  1579. Routine Description:
  1580. insert structures to transmit a single packet -- this is for debug
  1581. tool purposes only so we can be a little creative here.
  1582. Arguments:
  1583. Return Value:
  1584. --*/
  1585. {
  1586. PHC_OPERATIONAL_REGISTER hc;
  1587. PUCHAR pch;
  1588. PHW_ENDPOINT_DESCRIPTOR hwED;
  1589. ULONG hwEDPhys, phys;
  1590. PHW_TRANSFER_DESCRIPTOR hwTD, hwDummyTD;
  1591. ULONG hwTDPhys, hwDummyTDPhys, dataPhys;
  1592. PUCHAR data;
  1593. PHC_STATIC_ED_DATA staticControlEd;
  1594. ULONG i;
  1595. PSS_PACKET_CONTEXT context;
  1596. staticControlEd = &DeviceData->StaticEDList[ED_CONTROL];
  1597. hc = DeviceData->HC;
  1598. // allocate an ED & TD from the scratch space and initialize it
  1599. phys = WorkspacePhysicalAddress;
  1600. pch = WorkspaceVirtualAddress;
  1601. LOGENTRY(DeviceData, G, '_ssS', phys, 0, pch);
  1602. context = (PSS_PACKET_CONTEXT) pch;
  1603. pch += sizeof(SS_PACKET_CONTEXT);
  1604. phys += sizeof(SS_PACKET_CONTEXT);
  1605. // carve out an ED
  1606. hwEDPhys = phys;
  1607. hwED = (PHW_ENDPOINT_DESCRIPTOR) pch;
  1608. pch += sizeof(HW_ENDPOINT_DESCRIPTOR);
  1609. phys += sizeof(HW_ENDPOINT_DESCRIPTOR);
  1610. // carve out a TD
  1611. hwTDPhys = phys;
  1612. hwTD = (PHW_TRANSFER_DESCRIPTOR) pch;
  1613. pch += sizeof(HW_TRANSFER_DESCRIPTOR);
  1614. phys += sizeof(HW_TRANSFER_DESCRIPTOR);
  1615. // carve out a dummy TD
  1616. hwDummyTDPhys = phys;
  1617. hwDummyTD = (PHW_TRANSFER_DESCRIPTOR) pch;
  1618. pch += sizeof(HW_TRANSFER_DESCRIPTOR);
  1619. phys += sizeof(HW_TRANSFER_DESCRIPTOR);
  1620. // use the rest for data
  1621. LOGENTRY(DeviceData, G, '_ssD', PacketData, *PacketLength, 0);
  1622. dataPhys = phys;
  1623. data = pch;
  1624. RtlCopyMemory(data, PacketData, *PacketLength);
  1625. pch+=*PacketLength;
  1626. phys+=*PacketLength;
  1627. // init the hw ed descriptor
  1628. hwED->NextED = 0;
  1629. hwED->FunctionAddress = PacketParameters->DeviceAddress;
  1630. hwED->EndpointNumber = PacketParameters->EndpointAddress;
  1631. hwED->sKip = 0;
  1632. hwED->Direction = HcEDDirection_Defer;
  1633. switch (PacketParameters->Speed) {
  1634. case ss_Low:
  1635. hwED->LowSpeed = 1;
  1636. break;
  1637. default:
  1638. hwED->LowSpeed = 0;
  1639. }
  1640. hwED->MaxPacket = PacketParameters->MaximumPacketSize;
  1641. hwED->HeadP = hwTDPhys;
  1642. hwED->TailP = hwDummyTDPhys;
  1643. // init the TD for this packet
  1644. hwTD->NextTD = hwDummyTDPhys;
  1645. hwTD->Asy.ConditionCode = HcCC_NotAccessed;
  1646. hwTD->Asy.ErrorCount = 0;
  1647. hwTD->Asy.IntDelay = HcTDIntDelay_0ms;
  1648. hwTD->Asy.ShortXferOk = 1;
  1649. if (0 == *PacketLength) {
  1650. hwTD->CBP = 0;
  1651. hwTD->BE = 0;
  1652. }
  1653. else {
  1654. hwTD->CBP = dataPhys;
  1655. hwTD->BE = dataPhys+*PacketLength-1;
  1656. }
  1657. // init the dummy TD
  1658. hwDummyTD->NextTD = 0;
  1659. hwDummyTD->CBP = 0xFFFFFFFF;
  1660. LOGENTRY(DeviceData, G, '_ss2', hwTD, context, hwED);
  1661. LOGENTRY(DeviceData, G, '_ss3', dataPhys, data, *PacketLength);
  1662. switch(PacketParameters->Type) {
  1663. case ss_Setup:
  1664. LOGENTRY(DeviceData, G, '_sSU', 0, 0, 0);
  1665. hwED->Direction = HcEDDirection_Defer;
  1666. hwED->Isochronous = 0;
  1667. hwTD->Asy.Direction = HcTDDirection_Setup;
  1668. hwTD->Asy.Isochronous = 0;
  1669. break;
  1670. case ss_In:
  1671. LOGENTRY(DeviceData, G, '_ssI', 0, 0, 0);
  1672. hwED->Direction = HcEDDirection_Defer;
  1673. hwED->Isochronous = 0;
  1674. hwTD->Asy.Direction = HcTDDirection_In;
  1675. hwTD->Asy.Isochronous = 0;
  1676. break;
  1677. case ss_Out:
  1678. LOGENTRY(DeviceData, G, '_ssO', 0, 0, 0);
  1679. hwED->Direction = HcEDDirection_Defer;
  1680. hwED->Isochronous = 0;
  1681. hwTD->Asy.Direction = HcTDDirection_Out;
  1682. hwTD->Asy.Isochronous = 0;
  1683. break;
  1684. case ss_Iso_In:
  1685. break;
  1686. case ss_Iso_Out:
  1687. break;
  1688. }
  1689. switch(PacketParameters->Toggle) {
  1690. case ss_Toggle0:
  1691. hwTD->Asy.Toggle = HcTDToggle_Data0;
  1692. break;
  1693. case ss_Toggle1:
  1694. hwTD->Asy.Toggle = HcTDToggle_Data1;
  1695. break;
  1696. }
  1697. //TEST_TRAP();
  1698. //
  1699. // Replace the control ED in the list with the ED just created.
  1700. // Save the old value of both the control and bulk lists so
  1701. // they can be replaced when this transfer is complete.
  1702. //
  1703. // NOTE: This will interrupt normal bus operation for at least one ms
  1704. context->PhysHold = READ_REGISTER_ULONG(staticControlEd->PhysicalHead);
  1705. HW_DATA_PTR(context->Data) = data;
  1706. HW_TRANSFER_DESCRIPTOR_PTR(context->Td) = hwTD;
  1707. WRITE_REGISTER_ULONG(staticControlEd->PhysicalHead, hwEDPhys);
  1708. //
  1709. // Enable the control list and disable the bulk list. Disabling the
  1710. // bulk list temporarily will allow the single step transaction to
  1711. // complete without interfering with bulk data. In this manner, the
  1712. // bulk data INs and OUTs can be sent without interfering with bulk
  1713. // devices currently on the bus.
  1714. //
  1715. // NOTE: I think attempting to use this feature without first disabling
  1716. // the root hub could lead to some problems.
  1717. //
  1718. WRITE_REGISTER_ULONG(&hc->HcCommandStatus.ul, HcCmd_ControlListFilled);
  1719. return USBMP_STATUS_SUCCESS;
  1720. }
  1721. USB_MINIPORT_STATUS
  1722. USBMPFN
  1723. OHCI_EndSendOnePacket(
  1724. PDEVICE_DATA DeviceData,
  1725. PMP_PACKET_PARAMETERS PacketParameters,
  1726. PUCHAR PacketData,
  1727. PULONG PacketLength,
  1728. PUCHAR WorkspaceVirtualAddress,
  1729. HW_32BIT_PHYSICAL_ADDRESS WorkspacePhysicalAddress,
  1730. ULONG WorkSpaceLength,
  1731. USBD_STATUS *UsbdStatus
  1732. )
  1733. /*++
  1734. Routine Description:
  1735. Arguments:
  1736. Return Value:
  1737. --*/
  1738. {
  1739. PHC_OPERATIONAL_REGISTER hc;
  1740. PUCHAR pch;
  1741. PSS_PACKET_CONTEXT context;
  1742. PHC_STATIC_ED_DATA staticControlEd;
  1743. PHC_STATIC_ED_DATA staticBulkEd;
  1744. ULONG currentBulkEd;
  1745. PHW_TRANSFER_DESCRIPTOR hwTd;
  1746. PUCHAR data;
  1747. ULONG listFilled;
  1748. staticControlEd = &DeviceData->StaticEDList[ED_CONTROL];
  1749. staticBulkEd = &DeviceData->StaticEDList[ED_BULK];
  1750. hc = DeviceData->HC;
  1751. context = (PSS_PACKET_CONTEXT) WorkspaceVirtualAddress;
  1752. hwTd = HW_TRANSFER_DESCRIPTOR_PTR(context->Td);
  1753. data = HW_DATA_PTR(context->Data);
  1754. LOGENTRY(DeviceData, G, '_ssE', hwTd, 0, 0);
  1755. //TEST_TRAP();
  1756. // compute bytes transferred
  1757. if (hwTd->CBP) {
  1758. // we never have pagebreaks in the single step TD
  1759. *PacketLength = *PacketLength - ((hwTd->BE & OHCI_PAGE_SIZE_MASK) -
  1760. (hwTd->CBP & OHCI_PAGE_SIZE_MASK)+1);
  1761. }
  1762. // return any errors
  1763. if (hwTd->Asy.ConditionCode == HcCC_NoError) {
  1764. *UsbdStatus = USBD_STATUS_SUCCESS;
  1765. } else {
  1766. *UsbdStatus =
  1767. (hwTd->Asy.ConditionCode | 0xC0000000);
  1768. }
  1769. LOGENTRY(DeviceData, G, '_ssX', hwTd, *PacketLength, 0);
  1770. RtlCopyMemory(PacketData,
  1771. data,
  1772. *PacketLength);
  1773. //
  1774. // Restore the previous control structure and enable the control and
  1775. // bulk lists if they are non-NULL (ie. point to valid EDs.)
  1776. //
  1777. listFilled = 0;
  1778. WRITE_REGISTER_ULONG(staticControlEd->PhysicalHead, context->PhysHold);
  1779. if (context->PhysHold) {
  1780. listFilled |= HcCmd_ControlListFilled;
  1781. }
  1782. currentBulkEd = READ_REGISTER_ULONG(staticBulkEd->PhysicalHead);
  1783. if (currentBulkEd) {
  1784. listFilled |= HcCmd_BulkListFilled;
  1785. }
  1786. WRITE_REGISTER_ULONG(&hc->HcCommandStatus.ul, listFilled);
  1787. return USBMP_STATUS_SUCCESS;
  1788. }
  1789. VOID
  1790. OHCI_SuspendController(
  1791. PDEVICE_DATA DeviceData
  1792. )
  1793. {
  1794. PHC_OPERATIONAL_REGISTER hc;
  1795. HC_CONTROL control;
  1796. hc = DeviceData->HC;
  1797. // mask off interrupts that are not appropriate
  1798. WRITE_REGISTER_ULONG(&hc->HcInterruptDisable, 0xFFFFffff);
  1799. // flush any rogue status
  1800. WRITE_REGISTER_ULONG(&hc->HcInterruptStatus, 0xFFFFffff);
  1801. // put the controller in 'suspend'
  1802. control.ul = READ_REGISTER_ULONG(&hc->HcControl.ul);
  1803. control.HostControllerFunctionalState = HcHCFS_USBSuspend;
  1804. control.RemoteWakeupEnable = 1;
  1805. WRITE_REGISTER_ULONG(&hc->HcControl.ul, control.ul);
  1806. // enable the resume interrupt
  1807. WRITE_REGISTER_ULONG(&hc->HcInterruptEnable,
  1808. HcInt_MasterInterruptEnable |
  1809. HcInt_RootHubStatusChange |
  1810. HcInt_ResumeDetected |
  1811. HcInt_UnrecoverableError);
  1812. SET_FLAG(DeviceData->Flags, HMP_FLAG_SUSPENDED);
  1813. }
  1814. USB_MINIPORT_STATUS
  1815. OHCI_ResumeController(
  1816. PDEVICE_DATA DeviceData
  1817. )
  1818. /*++
  1819. Routine Description:
  1820. reverse what was done in 'suspend'
  1821. Arguments:
  1822. Return Value:
  1823. None
  1824. --*/
  1825. {
  1826. PHC_OPERATIONAL_REGISTER hc;
  1827. HC_CONTROL control;
  1828. hc = DeviceData->HC;
  1829. CLEAR_FLAG(DeviceData->Flags, HMP_FLAG_SUSPENDED);
  1830. // is some cases the BIOS trashes the state of the controller,
  1831. // even though we enter suspend.
  1832. // This is usually platform specific and indicates a broken BIOS
  1833. control.ul = READ_REGISTER_ULONG(&hc->HcControl.ul);
  1834. if (control.HostControllerFunctionalState == HcHCFS_USBReset) {
  1835. return USBMP_STATUS_HARDWARE_FAILURE;
  1836. } else {
  1837. // When the HC is in the operational state, HccaPad1 should be set to
  1838. // zero every time the HC updates HccaFrameNumer. Preset HccaPad1 to
  1839. // zero before entering the operational state. OHCI_CheckController()
  1840. // should always find a zero value in HccaPad1 when the HC is in the
  1841. // operational state.
  1842. //
  1843. DeviceData->HcHCCA->HccaPad1 = 0;
  1844. // put the controller in 'operational' state
  1845. control.ul = READ_REGISTER_ULONG(&hc->HcControl.ul);
  1846. control.HostControllerFunctionalState = HcHCFS_USBOperational;
  1847. WRITE_REGISTER_ULONG(&hc->HcControl.ul, control.ul);
  1848. }
  1849. // re-enable interrupts
  1850. WRITE_REGISTER_ULONG(&hc->HcInterruptEnable,
  1851. HcInt_OwnershipChange |
  1852. HcInt_SchedulingOverrun |
  1853. HcInt_WritebackDoneHead |
  1854. HcInt_FrameNumberOverflow |
  1855. HcInt_UnrecoverableError);
  1856. WRITE_REGISTER_ULONG(&hc->HcControl.ul, control.ul);
  1857. return USBMP_STATUS_SUCCESS;
  1858. }
  1859. VOID
  1860. OHCI_Unload(
  1861. PDRIVER_OBJECT DriverObject
  1862. )
  1863. /*++
  1864. Routine Description:
  1865. Arguments:
  1866. DriverObject - pointer to a driver object
  1867. Return Value:
  1868. None
  1869. --*/
  1870. {
  1871. // provide an unload routine
  1872. // we do this just to test the port driver
  1873. }
  1874. BOOLEAN
  1875. OHCI_HardwarePresent(
  1876. PDEVICE_DATA DeviceData,
  1877. BOOLEAN Notify
  1878. )
  1879. {
  1880. ULONG tmp;
  1881. PHC_OPERATIONAL_REGISTER hc;
  1882. hc = DeviceData->HC;
  1883. tmp = READ_REGISTER_ULONG(&hc->HcCommandStatus.ul);
  1884. if (tmp == 0xffffffff) {
  1885. if (Notify) {
  1886. USBPORT_INVALIDATE_CONTROLLER(DeviceData, UsbMpControllerRemoved);
  1887. }
  1888. return FALSE;
  1889. }
  1890. return TRUE;
  1891. }
  1892. VOID
  1893. OHCI_CheckController(
  1894. PDEVICE_DATA DeviceData
  1895. )
  1896. {
  1897. PHC_OPERATIONAL_REGISTER hc;
  1898. ULONG currentDeadmanFrame;
  1899. ULONG lastDeadmanFrame;
  1900. ULONG frameDelta;
  1901. hc = DeviceData->HC;
  1902. // First make sure it looks like the hardware is still present. (This
  1903. // will call USBPORT_INVALIDATE_CONTROLLER() if it looks like the hardware
  1904. // is no longer present).
  1905. //
  1906. if (!OHCI_HardwarePresent(DeviceData, TRUE)) {
  1907. return;
  1908. }
  1909. // Don't check any further if the controller is not currently in the
  1910. // operational state.
  1911. //
  1912. if ((READ_REGISTER_ULONG(&hc->HcControl.ul) & HcCtrl_HCFS_MASK) !=
  1913. HcCtrl_HCFS_USBOperational) {
  1914. return;
  1915. }
  1916. // Don't check any further if we already checked once this frame (or in
  1917. // the last few frames).
  1918. //
  1919. currentDeadmanFrame = READ_REGISTER_ULONG(&hc->HcFmNumber);
  1920. lastDeadmanFrame = DeviceData->LastDeadmanFrame;
  1921. frameDelta = (currentDeadmanFrame - lastDeadmanFrame) & HcFmNumber_MASK;
  1922. // Might HcFmNumber erroneously read back as zero under some conditions
  1923. // on some chipsets? Don't check any further if HcFmNumber is zero,
  1924. // just check later next time around.
  1925. //
  1926. if (currentDeadmanFrame && (frameDelta >= 5)) {
  1927. DeviceData->LastDeadmanFrame = currentDeadmanFrame;
  1928. switch (DeviceData->HcHCCA->HccaPad1)
  1929. {
  1930. case 0:
  1931. //
  1932. // When the HC updates HccaFrameNumber, it is supposed
  1933. // to set HccaPad1 to zero, so this is the expected case.
  1934. // Here we set HccaPad1 to a non-zero value to try to
  1935. // detect situations when the HC is no longer functioning
  1936. // correctly and accessing and updating host memory.
  1937. //
  1938. DeviceData->HcHCCA->HccaPad1 = 0xBAD1;
  1939. break;
  1940. case 0xBAD1:
  1941. //
  1942. // Apparently the HC has not updated the HCCA since the
  1943. // last time the DPC ran. This is probably not good.
  1944. //
  1945. DeviceData->HcHCCA->HccaPad1 = 0xBAD2;
  1946. LOGENTRY(DeviceData, G, '_BD2', DeviceData,
  1947. lastDeadmanFrame,
  1948. currentDeadmanFrame);
  1949. LOGENTRY(DeviceData, G, '_bd2', DeviceData,
  1950. DeviceData->HcHCCA->HccaFrameNumber,
  1951. frameDelta);
  1952. break;
  1953. case 0xBAD2:
  1954. //
  1955. // Apparently the HC has not updated the HCCA since the
  1956. // last two times the DPC ran. This looks even worse.
  1957. // Assume the HC has become wedged.
  1958. //
  1959. DeviceData->HcHCCA->HccaPad1 = 0xBAD3;
  1960. LOGENTRY(DeviceData, G, '_BD3', DeviceData,
  1961. lastDeadmanFrame,
  1962. currentDeadmanFrame);
  1963. LOGENTRY(DeviceData, G, '_bd3', DeviceData,
  1964. DeviceData->HcHCCA->HccaFrameNumber,
  1965. frameDelta);
  1966. OHCI_KdPrint((DeviceData, 0,
  1967. "*** Warning: OHCI HC %08X appears to be wedged!\n",
  1968. DeviceData));
  1969. // Tell USBPORT to please reset the controller.
  1970. //
  1971. USBPORT_INVALIDATE_CONTROLLER(DeviceData,
  1972. UsbMpControllerNeedsHwReset);
  1973. break;
  1974. case 0xBAD3:
  1975. break;
  1976. default:
  1977. // Should not hit this case.
  1978. TEST_TRAP();
  1979. break;
  1980. }
  1981. }
  1982. }
  1983. VOID
  1984. OHCI_ResetController(
  1985. PDEVICE_DATA DeviceData
  1986. )
  1987. /*++
  1988. Attempt to resurrect the HC after we have determined that it is dead.
  1989. --*/
  1990. {
  1991. PHC_OPERATIONAL_REGISTER HC;
  1992. ULONG HccaFrameNumber;
  1993. ULONG HcControl;
  1994. ULONG HcHCCA;
  1995. ULONG HcControlHeadED;
  1996. ULONG HcBulkHeadED;
  1997. ULONG HcFmInterval;
  1998. ULONG HcPeriodicStart;
  1999. ULONG HcLSThreshold;
  2000. HC_RH_DESCRIPTOR_A descrA;
  2001. ULONG port;
  2002. LOGENTRY(DeviceData, G, '_RHC', 0, 0, 0);
  2003. //
  2004. // Get the pointer to the HC Operational Registers
  2005. //
  2006. HC = DeviceData->HC;
  2007. //
  2008. // Save the last FrameNumber from the HCCA from when the HC froze
  2009. //
  2010. HccaFrameNumber = DeviceData->HcHCCA->HccaFrameNumber;
  2011. //
  2012. // Save current HC operational register values
  2013. //
  2014. // offset 0x04, save HcControl
  2015. //
  2016. HcControl = READ_REGISTER_ULONG(&HC->HcControl.ul);
  2017. // offset 0x18, save HcHCCA
  2018. //
  2019. HcHCCA = READ_REGISTER_ULONG(&HC->HcHCCA);
  2020. // offset 0x20, save HcControlHeadED
  2021. //
  2022. HcControlHeadED = READ_REGISTER_ULONG(&HC->HcControlHeadED);
  2023. // offset 0x28, save HcBulkHeadED
  2024. //
  2025. HcBulkHeadED = READ_REGISTER_ULONG(&HC->HcBulkHeadED);
  2026. // offset 0x34, save HcFmInterval
  2027. //
  2028. HcFmInterval = READ_REGISTER_ULONG(&HC->HcFmInterval.ul);
  2029. // offset 0x40, save HcPeriodicStart
  2030. //
  2031. HcPeriodicStart = READ_REGISTER_ULONG(&HC->HcPeriodicStart);
  2032. // offset 0x44, save HcLSThreshold
  2033. //
  2034. HcLSThreshold = READ_REGISTER_ULONG(&HC->HcLSThreshold);
  2035. //
  2036. // Reset the host controller
  2037. //
  2038. WRITE_REGISTER_ULONG(&HC->HcCommandStatus.ul, HcCmd_HostControllerReset);
  2039. KeStallExecutionProcessor(10);
  2040. //
  2041. // Restore / reinitialize HC operational register values
  2042. //
  2043. // offset 0x08, HcCommandStatus is set to zero on reset
  2044. // offset 0x0C, HcInterruptStatus is set to zero on reset
  2045. // offset 0x10, HcInterruptEnable is set to zero on reset
  2046. // offset 0x14, HcInterruptDisable is set to zero on reset
  2047. // offset 0x18, restore HcHCCA
  2048. //
  2049. WRITE_REGISTER_ULONG(&HC->HcHCCA, HcHCCA);
  2050. // offset 0x1C, HcPeriodCurrentED is set to zero on reset
  2051. // offset 0x20, restore HcControlHeadED
  2052. //
  2053. WRITE_REGISTER_ULONG(&HC->HcControlHeadED, HcControlHeadED);
  2054. // offset 0x24, HcControlCurrentED is set to zero on reset
  2055. // offset 0x28, restore HcBulkHeadED
  2056. //
  2057. WRITE_REGISTER_ULONG(&HC->HcBulkHeadED, HcBulkHeadED);
  2058. // offset 0x2C, HcBulkCurrentED is set to zero on reset
  2059. // offset 0x30, HcDoneHead is set to zero on reset
  2060. // It appears that writes to HcFmInterval don't stick unless the HC
  2061. // is in the operational state. Set the HC into the operational
  2062. // state at this point, but don't enable any list processing yet
  2063. // by setting any of the BLE, CLE, IE, or PLE bits.
  2064. //
  2065. WRITE_REGISTER_ULONG(&HC->HcControl.ul, HcCtrl_HCFS_USBOperational);
  2066. // offset 0x34, restore HcFmInterval
  2067. //
  2068. WRITE_REGISTER_ULONG(&HC->HcFmInterval.ul,
  2069. HcFmInterval | HcFmI_FRAME_INTERVAL_TOGGLE);
  2070. // offset 0x38, HcFmRemaining is set to zero on reset
  2071. // offset 0x3C, restore HcFmNumber
  2072. //
  2073. WRITE_REGISTER_ULONG(&HC->HcFmNumber, HccaFrameNumber);
  2074. // offset 0x40, restore HcPeriodicStart
  2075. //
  2076. WRITE_REGISTER_ULONG(&HC->HcPeriodicStart, HcPeriodicStart);
  2077. // offset 0x44, restore HcLSThreshold
  2078. //
  2079. WRITE_REGISTER_ULONG(&HC->HcLSThreshold, HcLSThreshold);
  2080. // Power on downstream ports
  2081. //
  2082. WRITE_REGISTER_ULONG(&HC->HcRhStatus,
  2083. HcRhS_SetGlobalPower | HcRhS_SetRemoteWakeupEnable);
  2084. descrA.ul = OHCI_ReadRhDescriptorA(DeviceData);
  2085. OHCI_ASSERT(DeviceData, (descrA.ul) && (!(descrA.ul & HcDescA_RESERVED)));
  2086. for (port = 0; port < descrA.s.NumberDownstreamPorts; port++)
  2087. {
  2088. WRITE_REGISTER_ULONG(&HC->HcRhPortStatus[port], HcRhPS_SetPortPower);
  2089. }
  2090. // offset 0x04, restore HcControl
  2091. //
  2092. HcControl &= ~(HcCtrl_HCFS_MASK);
  2093. HcControl |= HcCtrl_HCFS_USBOperational;
  2094. WRITE_REGISTER_ULONG(&HC->HcControl.ul, HcControl);
  2095. // offset 0x10, restore HcInterruptEnable (just turn everything on!)
  2096. //
  2097. WRITE_REGISTER_ULONG(&HC->HcInterruptEnable,
  2098. HcInt_MasterInterruptEnable | // 0x80000000
  2099. HcInt_OwnershipChange | // 0x40000000
  2100. HcInt_RootHubStatusChange | // 0x00000040
  2101. HcInt_FrameNumberOverflow | // 0x00000020
  2102. HcInt_UnrecoverableError | // 0x00000010
  2103. HcInt_ResumeDetected | // 0x00000008
  2104. HcInt_StartOfFrame | // 0x00000004
  2105. HcInt_WritebackDoneHead | // 0x00000002
  2106. HcInt_SchedulingOverrun // 0x00000001
  2107. );
  2108. }