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.

787 lines
25 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. usb2.c
  5. Abstract:
  6. functions for processing usb 2.0 specific requests
  7. Environment:
  8. kernel mode only
  9. Notes:
  10. Revision History:
  11. 6-20-99 : created
  12. --*/
  13. #include "common.h"
  14. #ifdef ALLOC_PRAGMA
  15. #endif
  16. // taken from budgeter code
  17. #define LARGEXACT (579)
  18. #define USBPORT_MAX_REBALANCE 30
  19. VOID
  20. USBPORT_Rebalance(
  21. PDEVICE_OBJECT FdoDeviceObject,
  22. PLIST_ENTRY ReblanceListHead
  23. )
  24. /*++
  25. Routine Description:
  26. The rebalnce list contains all the endpoints that were effected
  27. by budgeting this new USB2 endpoint. We must re-schedule each of
  28. them.
  29. This process occurs during configuration of the device which is
  30. serialized so we don't need to protect the list.
  31. --*/
  32. {
  33. PLIST_ENTRY listEntry;
  34. PHCD_ENDPOINT endpoint;
  35. LONG startHframe;
  36. ULONG scheduleOffset;
  37. UCHAR sMask, cMask, period;
  38. ULONG bandwidth;
  39. PDEVICE_EXTENSION devExt;
  40. LIST_ENTRY interruptChangeList;
  41. LIST_ENTRY periodPromotionList;
  42. LIST_ENTRY isoChangeList;
  43. GET_DEVICE_EXT(devExt, FdoDeviceObject);
  44. ASSERT_FDOEXT(devExt);
  45. InitializeListHead(&interruptChangeList);
  46. InitializeListHead(&periodPromotionList);
  47. InitializeListHead(&isoChangeList);
  48. // bugbug
  49. // can the insertion of the new endpiont occurr after the modification
  50. // of the rebalnced endpoints?
  51. // bugbug, this list must be sorted such that the changes occurr
  52. // in the proper sequnence.
  53. // ???
  54. // <------chnages must travel this direction
  55. // iso--interrupt
  56. LOGENTRY(NULL, FdoDeviceObject, LOG_XFERS,
  57. '2RB>', 0, 0, 0);
  58. while (!IsListEmpty(ReblanceListHead)) {
  59. listEntry = RemoveHeadList(ReblanceListHead);
  60. endpoint = (PHCD_ENDPOINT) CONTAINING_RECORD(
  61. listEntry,
  62. struct _HCD_ENDPOINT,
  63. RebalanceLink);
  64. ASSERT_ENDPOINT(endpoint);
  65. endpoint->RebalanceLink.Flink = NULL;
  66. endpoint->RebalanceLink.Blink = NULL;
  67. sMask = USB2LIB_GetSMASK(endpoint->Usb2LibEpContext);
  68. cMask = USB2LIB_GetCMASK(endpoint->Usb2LibEpContext);
  69. bandwidth = USB2LIB_GetAllocedBusTime(endpoint->Usb2LibEpContext) * 8;
  70. scheduleOffset = USB2LIB_GetScheduleOffset(endpoint->Usb2LibEpContext);
  71. period = USB2LIB_GetNewPeriod(endpoint->Usb2LibEpContext);
  72. USBPORT_KdPrint((1,"'[RB-old] %x sMask = x%x cMask = x%x\n", endpoint,
  73. endpoint->Parameters.InterruptScheduleMask,
  74. endpoint->Parameters.SplitCompletionMask));
  75. USBPORT_KdPrint((1,"'[RB-old] Period x%x Offset x%x\n",
  76. endpoint->Parameters.Period,
  77. endpoint->Parameters.ScheduleOffset));
  78. USBPORT_KdPrint((1,"'[RB-new] %x sMask = x%x cMask = x%x\n",
  79. endpoint, sMask, cMask));
  80. USBPORT_KdPrint((1,"'[RB-new] Period x%x Offset x%x\n",
  81. period, scheduleOffset));
  82. switch (endpoint->Parameters.TransferType) {
  83. case Interrupt:
  84. if (sMask == endpoint->Parameters.InterruptScheduleMask &&
  85. cMask == endpoint->Parameters.SplitCompletionMask &&
  86. scheduleOffset == endpoint->Parameters.ScheduleOffset &&
  87. period == endpoint->Parameters.Period) {
  88. USBPORT_KdPrint((1,"'[RB] no changes\n"));
  89. USBPORT_ASSERT(bandwidth == endpoint->Parameters.Bandwidth);
  90. } else if (period != endpoint->Parameters.Period ||
  91. scheduleOffset != endpoint->Parameters.ScheduleOffset) {
  92. USBPORT_KdPrint((1,"'[RB] period changes\n"));
  93. InsertTailList(&periodPromotionList,
  94. &endpoint->RebalanceLink);
  95. } else {
  96. USBPORT_KdPrint((1,"'[RB] interrupt changes\n"));
  97. InsertTailList(&interruptChangeList,
  98. &endpoint->RebalanceLink);
  99. }
  100. break;
  101. case Isochronous:
  102. if (sMask == endpoint->Parameters.InterruptScheduleMask &&
  103. cMask == endpoint->Parameters.SplitCompletionMask &&
  104. scheduleOffset == endpoint->Parameters.ScheduleOffset &&
  105. period == endpoint->Parameters.Period) {
  106. USBPORT_KdPrint((1,"'[RB] iso no changes\n"));
  107. USBPORT_ASSERT(bandwidth == endpoint->Parameters.Bandwidth);
  108. } else if (period != endpoint->Parameters.Period ||
  109. scheduleOffset != endpoint->Parameters.ScheduleOffset) {
  110. // currently not handled
  111. USBPORT_KdPrint((1,"'[RB] iso period changes\n"));
  112. TEST_TRAP();
  113. } else {
  114. USBPORT_KdPrint((1,"'[RB] iso changes\n"));
  115. InsertTailList(&isoChangeList,
  116. &endpoint->RebalanceLink);
  117. }
  118. break;
  119. }
  120. }
  121. // now do the period promotions
  122. // BUGBUG lump period and interrupt together
  123. USBPORT_KdPrint((1,"'[RB] period\n"));
  124. USBPORT_RebalanceEndpoint(FdoDeviceObject,
  125. &periodPromotionList);
  126. USBPORT_KdPrint((1,"'[RB] interrupt\n"));
  127. USBPORT_RebalanceEndpoint(FdoDeviceObject,
  128. &interruptChangeList);
  129. // now rebalance the iso endpoints
  130. USBPORT_KdPrint((1,"'[RB] iso\n"));
  131. USBPORT_RebalanceEndpoint(FdoDeviceObject,
  132. &isoChangeList);
  133. LOGENTRY(NULL, FdoDeviceObject, LOG_XFERS,
  134. '2RB<', 0, 0, 0);
  135. }
  136. VOID
  137. USBPORT_RebalanceEndpoint(
  138. PDEVICE_OBJECT FdoDeviceObject,
  139. PLIST_ENTRY EndpointList
  140. )
  141. /*++
  142. Routine Description:
  143. Computes the best schedule parameters for a USB2 endpoint.
  144. --*/
  145. {
  146. PLIST_ENTRY listEntry;
  147. PHCD_ENDPOINT endpoint;
  148. ULONG scheduleOffset;
  149. UCHAR sMask, cMask, period;
  150. ULONG bandwidth, n, i, bt;
  151. PDEVICE_EXTENSION devExt;
  152. PHCD_ENDPOINT nextEndpoint;
  153. GET_DEVICE_EXT(devExt, FdoDeviceObject);
  154. ASSERT_FDOEXT(devExt);
  155. while (!IsListEmpty(EndpointList)) {
  156. listEntry = RemoveHeadList(EndpointList);
  157. endpoint = (PHCD_ENDPOINT) CONTAINING_RECORD(
  158. listEntry,
  159. struct _HCD_ENDPOINT,
  160. RebalanceLink);
  161. LOGENTRY(NULL, FdoDeviceObject, LOG_XFERS,
  162. 'rbe+', endpoint, 0, 0);
  163. ASSERT_ENDPOINT(endpoint);
  164. endpoint->RebalanceLink.Flink = NULL;
  165. endpoint->RebalanceLink.Blink = NULL;
  166. ACQUIRE_ENDPOINT_LOCK(endpoint, FdoDeviceObject, 'Lex+');
  167. // notify the miniport of the changed parameters
  168. sMask = USB2LIB_GetSMASK(endpoint->Usb2LibEpContext);
  169. cMask = USB2LIB_GetCMASK(endpoint->Usb2LibEpContext);
  170. scheduleOffset = USB2LIB_GetScheduleOffset(endpoint->Usb2LibEpContext);
  171. period = USB2LIB_GetNewPeriod(endpoint->Usb2LibEpContext);
  172. bt = USB2LIB_GetAllocedBusTime(endpoint->Usb2LibEpContext);
  173. bandwidth = bt * 8;
  174. nextEndpoint = USB2LIB_GetNextEndpoint(endpoint->Usb2LibEpContext);
  175. #if DBG
  176. if (nextEndpoint) {
  177. ASSERT_ENDPOINT(nextEndpoint);
  178. }
  179. #endif
  180. USBPORT_KdPrint((1,"'[RB - %x] \n", endpoint));
  181. USBPORT_ASSERT(bandwidth == endpoint->Parameters.Bandwidth);
  182. endpoint->Parameters.InterruptScheduleMask = sMask;
  183. endpoint->Parameters.SplitCompletionMask = cMask;
  184. if (endpoint->Parameters.Period != period) {
  185. // adjust bandwidth tracked for this endpoint
  186. n = USBPORT_MAX_INTEP_POLLING_INTERVAL/endpoint->Parameters.Period;
  187. for (i=0; i<n; i++) {
  188. USBPORT_ASSERT(n*endpoint->Parameters.ScheduleOffset+i < USBPORT_MAX_INTEP_POLLING_INTERVAL);
  189. endpoint->Tt->BandwidthTable[n*endpoint->Parameters.ScheduleOffset+i] +=
  190. endpoint->Parameters.Bandwidth;
  191. }
  192. if (bt >= LARGEXACT) {
  193. SET_FLAG(endpoint->Flags, EPFLAG_FATISO);
  194. } else {
  195. CLEAR_FLAG(endpoint->Flags, EPFLAG_FATISO);
  196. }
  197. // track new parameters resulting from period change
  198. endpoint->Parameters.Period = period;
  199. endpoint->Parameters.ScheduleOffset = scheduleOffset;
  200. endpoint->Parameters.Bandwidth = bandwidth;
  201. endpoint->Parameters.Ordinal =
  202. USBPORT_SelectOrdinal(FdoDeviceObject, endpoint);
  203. // new allocation
  204. n = USBPORT_MAX_INTEP_POLLING_INTERVAL/period;
  205. for (i=0; i<n; i++) {
  206. USBPORT_ASSERT(n*scheduleOffset+i < USBPORT_MAX_INTEP_POLLING_INTERVAL);
  207. endpoint->Tt->BandwidthTable[n*scheduleOffset+i] +=
  208. bandwidth;
  209. }
  210. }
  211. MP_RebalanceEndpoint(devExt, endpoint);
  212. RELEASE_ENDPOINT_LOCK(endpoint, FdoDeviceObject, 'Lex-');
  213. }
  214. }
  215. BOOLEAN
  216. USBPORT_AllocateBandwidthUSB20(
  217. PDEVICE_OBJECT FdoDeviceObject,
  218. PHCD_ENDPOINT Endpoint
  219. )
  220. /*++
  221. Routine Description:
  222. Computes the best schedule parameters for a USB2 endpoint.
  223. --*/
  224. {
  225. PDEVICE_EXTENSION devExt;
  226. USB2LIB_BUDGET_PARAMETERS budget;
  227. BOOLEAN alloced;
  228. LONG startHframe;
  229. ULONG scheduleOffset, bt;
  230. UCHAR sMask, cMask, period;
  231. PREBALANCE_LIST rebalanceList;
  232. ULONG rebalanceListEntries;
  233. ULONG bytes;
  234. LIST_ENTRY endpointList;
  235. PVOID ttContext;
  236. PTRANSACTION_TRANSLATOR translator = NULL;
  237. PHCD_ENDPOINT nextEndpoint;
  238. PAGED_CODE();
  239. GET_DEVICE_EXT(devExt, FdoDeviceObject);
  240. ASSERT_FDOEXT(devExt);
  241. ASSERT_ENDPOINT(Endpoint);
  242. InitializeListHead(&endpointList);
  243. Endpoint->Parameters.ScheduleOffset = 0;
  244. LOGENTRY(NULL, FdoDeviceObject, LOG_XFERS,
  245. 'a2BW', Endpoint, 0, 0);
  246. // bulk and control are not tracked
  247. if (Endpoint->Parameters.TransferType == Bulk ||
  248. Endpoint->Parameters.TransferType == Control ||
  249. TEST_FLAG(Endpoint->Flags, EPFLAG_ROOTHUB)) {
  250. Endpoint->Parameters.ScheduleOffset = 0;
  251. return TRUE;
  252. }
  253. if (Endpoint->Parameters.TransferType == Interrupt ||
  254. Endpoint->Parameters.TransferType == Isochronous) {
  255. USBPORT_KdPrint((1,"'ALLOCBW (EP) %x >>>>>>>>>>>>\n", Endpoint));
  256. // period has been normalized to a value <=
  257. // USBPORT_MAX_INTEP_POLLING_INTERVAL in either mf of frames
  258. // call the engine to compute appropriate split masks
  259. // for this interrupt endpoint
  260. //
  261. USBPORT_KdPrint((1,"'(alloc) ep = %x\n", Endpoint));
  262. // set budget input parameters
  263. if (Endpoint->Parameters.TransferType == Interrupt) {
  264. budget.TransferType = Budget_Interrupt;
  265. budget.Period = Endpoint->Parameters.Period;
  266. } else {
  267. budget.TransferType = Budget_Iso;
  268. budget.Period = 1;
  269. }
  270. budget.MaxPacket = Endpoint->Parameters.MaxPacketSize;
  271. if (Endpoint->Parameters.TransferDirection == In) {
  272. budget.Direction = Budget_In;
  273. } else {
  274. budget.Direction = Budget_Out;
  275. }
  276. switch (Endpoint->Parameters.DeviceSpeed) {
  277. case HighSpeed:
  278. budget.Speed = Budget_HighSpeed;
  279. break;
  280. case LowSpeed:
  281. budget.Speed = Budget_LowSpeed;
  282. break;
  283. case FullSpeed:
  284. budget.Speed = Budget_FullSpeed;
  285. break;
  286. }
  287. bytes = sizeof(PVOID) * USBPORT_MAX_REBALANCE;
  288. ALLOC_POOL_Z(rebalanceList,
  289. NonPagedPool,
  290. bytes);
  291. // high speed endpoints will have no Tt context
  292. ttContext = NULL;
  293. if (Endpoint->Tt != NULL) {
  294. ASSERT_TT(Endpoint->Tt);
  295. translator = Endpoint->Tt;
  296. ttContext = &Endpoint->Tt->Usb2LibTtContext[0];
  297. }
  298. if (rebalanceList != NULL) {
  299. rebalanceListEntries = USBPORT_MAX_REBALANCE;
  300. alloced = USB2LIB_AllocUsb2BusTime(
  301. devExt->Fdo.Usb2LibHcContext,
  302. ttContext,
  303. Endpoint->Usb2LibEpContext,
  304. &budget,
  305. Endpoint, // context
  306. rebalanceList,
  307. &rebalanceListEntries);
  308. } else {
  309. alloced = FALSE;
  310. rebalanceListEntries = 0;
  311. }
  312. USBPORT_KdPrint((1,"'(alloc %d) rebalance count = %d\n",
  313. alloced, rebalanceListEntries));
  314. if (rebalanceListEntries > 0) {
  315. PHCD_ENDPOINT rebalanceEndpoint;
  316. ULONG i;
  317. // convert the rebalance entries to endpoints
  318. for (i=0; i< rebalanceListEntries; i++) {
  319. rebalanceEndpoint = rebalanceList->RebalanceContext[i];
  320. USBPORT_KdPrint((1,"'(alloc) rebalance Endpoint = %x \n",
  321. rebalanceList->RebalanceContext[i]));
  322. USBPORT_ASSERT(rebalanceEndpoint->RebalanceLink.Flink == NULL);
  323. USBPORT_ASSERT(rebalanceEndpoint->RebalanceLink.Blink == NULL);
  324. InsertTailList(&endpointList,
  325. &rebalanceEndpoint->RebalanceLink);
  326. }
  327. }
  328. if (rebalanceList != NULL) {
  329. FREE_POOL(FdoDeviceObject, rebalanceList);
  330. }
  331. if (alloced == TRUE) {
  332. ULONG n, bandwidth;
  333. ULONG i;
  334. // compute parameters for the miniport
  335. startHframe = USB2LIB_GetStartMicroFrame(Endpoint->Usb2LibEpContext);
  336. scheduleOffset = USB2LIB_GetScheduleOffset(Endpoint->Usb2LibEpContext);
  337. period = USB2LIB_GetNewPeriod(Endpoint->Usb2LibEpContext);
  338. sMask = USB2LIB_GetSMASK(Endpoint->Usb2LibEpContext);
  339. cMask = USB2LIB_GetCMASK(Endpoint->Usb2LibEpContext);
  340. // bw in bit times
  341. bt = USB2LIB_GetAllocedBusTime(Endpoint->Usb2LibEpContext);
  342. bandwidth = bt*8;
  343. nextEndpoint = USB2LIB_GetNextEndpoint(Endpoint->Usb2LibEpContext);
  344. #if DBG
  345. if (nextEndpoint) {
  346. ASSERT_ENDPOINT(nextEndpoint);
  347. }
  348. #endif
  349. // update the bw table in the TT
  350. if (translator == NULL) {
  351. n = USBPORT_MAX_INTEP_POLLING_INTERVAL/period;
  352. for (i=0; i<n; i++) {
  353. USBPORT_ASSERT(n*scheduleOffset+i < USBPORT_MAX_INTEP_POLLING_INTERVAL);
  354. USBPORT_ASSERT(devExt->Fdo.BandwidthTable[n*scheduleOffset+i] >= bandwidth);
  355. devExt->Fdo.BandwidthTable[n*scheduleOffset+i] -= bandwidth;
  356. }
  357. } else {
  358. // tt allocation, track the bw
  359. n = USBPORT_MAX_INTEP_POLLING_INTERVAL/period;
  360. for (i=0; i<n; i++) {
  361. USBPORT_ASSERT(n*scheduleOffset+i < USBPORT_MAX_INTEP_POLLING_INTERVAL);
  362. USBPORT_ASSERT(translator->BandwidthTable[n*scheduleOffset+i] >= bandwidth);
  363. translator->BandwidthTable[n*scheduleOffset+i] -= bandwidth;
  364. }
  365. }
  366. Endpoint->Parameters.Period = period;
  367. Endpoint->Parameters.ScheduleOffset = scheduleOffset;
  368. Endpoint->Parameters.InterruptScheduleMask = sMask;
  369. Endpoint->Parameters.SplitCompletionMask = cMask;
  370. Endpoint->Parameters.Bandwidth = bandwidth;
  371. if (bt >= LARGEXACT) {
  372. SET_FLAG(Endpoint->Flags, EPFLAG_FATISO);
  373. }
  374. USBPORT_KdPrint((1,"'[NEW] %x sMask = x%x cMask = x%x hFrame x%x\n",
  375. Endpoint, sMask, cMask, startHframe));
  376. USBPORT_KdPrint((1,"'[NEW] Period x%x Offset x%x bw = %d\n",
  377. period, scheduleOffset, bandwidth));
  378. USBPORT_KdPrint((1,"'[NEW] BudgetNextEp x%x \n", nextEndpoint));
  379. } else {
  380. USBPORT_KdPrint((1,"'[NEW] alloc failed\n"));
  381. }
  382. USBPORT_KdPrint((1,"'ALLOCBW (EP) <<<<<<<<<<<<<<<<<\n"));
  383. }
  384. LOGENTRY(NULL, FdoDeviceObject, LOG_XFERS,
  385. 'a2RB', 0, 0, alloced);
  386. USBPORT_KdPrint((1,"'REBLANCE (EP) >>>>>>>>>>>>>>>>>>>>\n"));
  387. // process the rebalanced endpoints
  388. USBPORT_Rebalance(FdoDeviceObject,
  389. &endpointList);
  390. USBPORT_KdPrint((1,"'REBLANCE (EP) <<<<<<<<<<<<<<<<<<<<<\n"));
  391. if (translator != NULL) {
  392. // adjust the global bandwidth tracked for this tt
  393. ULONG bandwidth, i;
  394. // release old bandwidth
  395. bandwidth = translator->MaxAllocedBw;
  396. for (i=0; i<USBPORT_MAX_INTEP_POLLING_INTERVAL; i++) {
  397. devExt->Fdo.BandwidthTable[i] += bandwidth;
  398. }
  399. USBPORT_UpdateAllocatedBwTt(translator);
  400. // alloc new
  401. bandwidth = translator->MaxAllocedBw;
  402. for (i=0; i<USBPORT_MAX_INTEP_POLLING_INTERVAL; i++) {
  403. devExt->Fdo.BandwidthTable[i] -= bandwidth;
  404. }
  405. }
  406. return alloced;
  407. }
  408. VOID
  409. USBPORT_FreeBandwidthUSB20(
  410. PDEVICE_OBJECT FdoDeviceObject,
  411. PHCD_ENDPOINT Endpoint
  412. )
  413. /*++
  414. Routine Description:
  415. Frees the bw reserved for a give endpoint
  416. Arguments:
  417. Return Value:
  418. FALSE if no bandwidth availble
  419. --*/
  420. {
  421. PDEVICE_EXTENSION devExt;
  422. ULONG period, bandwidth, sheduleOffset, i, n;
  423. PREBALANCE_LIST rebalanceList;
  424. ULONG rebalanceListEntries;
  425. ULONG bytes;
  426. LIST_ENTRY endpointList;
  427. PVOID ttContext;
  428. PTRANSACTION_TRANSLATOR translator = NULL;
  429. ULONG scheduleOffset;
  430. PAGED_CODE();
  431. GET_DEVICE_EXT(devExt, FdoDeviceObject);
  432. ASSERT_FDOEXT(devExt);
  433. ASSERT_ENDPOINT(Endpoint);
  434. period = Endpoint->Parameters.Period;
  435. scheduleOffset = Endpoint->Parameters.ScheduleOffset;
  436. bandwidth = Endpoint->Parameters.Bandwidth;
  437. InitializeListHead(&endpointList);
  438. if (Endpoint->Parameters.TransferType == Bulk ||
  439. Endpoint->Parameters.TransferType == Control ||
  440. TEST_FLAG(Endpoint->Flags, EPFLAG_ROOTHUB)) {
  441. // these come out of our standard 10%
  442. return;
  443. }
  444. USBPORT_KdPrint((1,"'(free) Endpoint = %x\n", Endpoint));
  445. bytes = sizeof(PVOID) * USBPORT_MAX_REBALANCE;
  446. // This must succeed, if we can't get memory for the
  447. // rebalance list we cannot reorganize the schedule
  448. // as a result of the device leaving. This means the
  449. // whole schedule is busted and the bus will not function
  450. // at all after this occurs.
  451. //
  452. ALLOC_POOL_Z(rebalanceList,
  453. NonPagedPool,
  454. bytes);
  455. if (rebalanceList == NULL) {
  456. // if this fails we have no choice but to leave
  457. // the schedule hoplessly you-know-what'ed up.
  458. return;
  459. }
  460. rebalanceListEntries = USBPORT_MAX_REBALANCE;
  461. // high speed endpoints will have no Tt context
  462. ttContext = NULL;
  463. if (Endpoint->Tt != NULL) {
  464. ASSERT_TT(Endpoint->Tt);
  465. translator = Endpoint->Tt;
  466. ttContext = &Endpoint->Tt->Usb2LibTtContext[0];
  467. }
  468. if (translator == NULL) {
  469. // allocate 2.0 bus time
  470. n = USBPORT_MAX_INTEP_POLLING_INTERVAL/period;
  471. for (i=0; i<n; i++) {
  472. USBPORT_ASSERT(n*scheduleOffset+i < USBPORT_MAX_INTEP_POLLING_INTERVAL);
  473. devExt->Fdo.BandwidthTable[n*scheduleOffset+i] += bandwidth;
  474. }
  475. } else {
  476. // tt allocation, track the bw on the tt
  477. n = USBPORT_MAX_INTEP_POLLING_INTERVAL/period;
  478. for (i=0; i<n; i++) {
  479. USBPORT_ASSERT(n*scheduleOffset+i < USBPORT_MAX_INTEP_POLLING_INTERVAL);
  480. translator->BandwidthTable[n*scheduleOffset+i] += bandwidth;
  481. }
  482. }
  483. USB2LIB_FreeUsb2BusTime(
  484. devExt->Fdo.Usb2LibHcContext,
  485. ttContext,
  486. Endpoint->Usb2LibEpContext,
  487. rebalanceList,
  488. &rebalanceListEntries);
  489. USBPORT_KdPrint((1,"'[FREE] %x sMask = x%x cMask = x%x\n",
  490. Endpoint,
  491. Endpoint->Parameters.InterruptScheduleMask,
  492. Endpoint->Parameters.SplitCompletionMask));
  493. USBPORT_KdPrint((1,"'[FREE] Period x%x Offset x%x bw %d\n",
  494. Endpoint->Parameters.Period,
  495. Endpoint->Parameters.ScheduleOffset,
  496. Endpoint->Parameters.Bandwidth));
  497. USBPORT_KdPrint((1,"'rebalance count = %d\n",
  498. rebalanceListEntries));
  499. if (rebalanceListEntries > 0) {
  500. PHCD_ENDPOINT rebalanceEndpoint;
  501. ULONG rbIdx;
  502. // convert the rebalance entries to endpoints
  503. for (rbIdx=0; rbIdx< rebalanceListEntries; rbIdx++) {
  504. rebalanceEndpoint = rebalanceList->RebalanceContext[rbIdx];
  505. USBPORT_KdPrint((1,"'(free) rebalance Endpoint = %x\n",
  506. rebalanceList->RebalanceContext[rbIdx]));
  507. if (rebalanceEndpoint != Endpoint) {
  508. USBPORT_ASSERT(rebalanceEndpoint->RebalanceLink.Flink == NULL);
  509. USBPORT_ASSERT(rebalanceEndpoint->RebalanceLink.Blink == NULL);
  510. InsertTailList(&endpointList,
  511. &rebalanceEndpoint->RebalanceLink);
  512. }
  513. }
  514. }
  515. if (rebalanceList != NULL) {
  516. FREE_POOL(FdoDeviceObject, rebalanceList);
  517. }
  518. // process the rebalanced endpoints
  519. USBPORT_Rebalance(FdoDeviceObject,
  520. &endpointList);
  521. if (translator != NULL) {
  522. // adjust the global bandwidth tracked for this tt
  523. // release old bandwidth
  524. bandwidth = translator->MaxAllocedBw;
  525. for (i=0; i<USBPORT_MAX_INTEP_POLLING_INTERVAL; i++) {
  526. devExt->Fdo.BandwidthTable[i] += bandwidth;
  527. }
  528. USBPORT_UpdateAllocatedBwTt(translator);
  529. // alloc new
  530. bandwidth = translator->MaxAllocedBw;
  531. for (i=0; i<USBPORT_MAX_INTEP_POLLING_INTERVAL; i++) {
  532. devExt->Fdo.BandwidthTable[i] -= bandwidth;
  533. }
  534. }
  535. return;
  536. }
  537. /*
  538. Endpoint Ordinal
  539. An endpoint ordinal is a schedule attribute of the endpoint.
  540. The ordinal set is unique for each endpoint type,period,offset,speed
  541. combination. The ordinal is used to indicate the relative
  542. order the endpoints should be visited by the host controller
  543. hardware.
  544. Interrupt Ordinals
  545. These are unique to each node in the interrupt schedule, we maintain
  546. a table similar to the miniport interrupt tree:
  547. // the array looks like this, values indicate period:
  548. // 1, 2, 2, 4, 4, 4, 4, 8,
  549. // 8, 8, 8, 8, 8, 8, 8,16,
  550. // 16,16,16,16,16,16,16,16,
  551. // 16,16,16,16,16,16,16,32,
  552. // 32,32,32,32,32,32,32,32,
  553. // 32,32,32,32,32,32,32,32,
  554. // 32,32,32,32,32,32,32,32,
  555. // 32,32,32,32,32,32,32,
  556. */
  557. ULONG
  558. USBPORT_SelectOrdinal(
  559. PDEVICE_OBJECT FdoDeviceObject,
  560. PHCD_ENDPOINT Endpoint
  561. )
  562. /*++
  563. Routine Description:
  564. Frees the bw reserved for a give endpoint
  565. Arguments:
  566. Return Value:
  567. FALSE if no bandwidth availble
  568. --*/
  569. {
  570. PDEVICE_EXTENSION devExt;
  571. ULONG ordinal;
  572. static o = 0;
  573. GET_DEVICE_EXT(devExt, FdoDeviceObject);
  574. ASSERT_FDOEXT(devExt);
  575. if (!USBPORT_IS_USB20(devExt)) {
  576. return 0;
  577. }
  578. switch (Endpoint->Parameters.TransferType) {
  579. case Bulk:
  580. case Control:
  581. ordinal = 0;
  582. break;
  583. case Interrupt:
  584. // BUGBUG
  585. ordinal = o++;
  586. break;
  587. case Isochronous:
  588. if (TEST_FLAG(Endpoint->Flags, EPFLAG_FATISO)) {
  589. ordinal = 0;
  590. } else {
  591. ordinal = 1;
  592. }
  593. break;
  594. }
  595. return ordinal;
  596. }