Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2433 lines
72 KiB

  1. // scheduling algorithm for split periodic
  2. /*
  3. * Allocate_time_for_endpoint - adds a new endpoint to the periodic budget tracking list
  4. * Dealloate_time_for_endpoint - removes an endpoint from the budget
  5. *
  6. * Each of these routines return a list of other (previously allocated) endpoints that have had
  7. * their allocation changed due to the (de)allocation of an endpoint.
  8. *
  9. */
  10. /***************** Design notes *********************
  11. *
  12. * Split transactions require three allocations (and/or budgets).
  13. * 1) the classic bus must count the byte times required in each classic frame.
  14. * This is what a classic bus already normally does.
  15. * 2) a microframe patterned frame budget must be computed for each classic frame.
  16. * This is used to determine what microframes require split transactions.
  17. * 3) the high speed bus must count the byte times required in each HS microframe.
  18. * This is the HS equivalent of what is done for a (classic) bus, i.e same
  19. * general allocation algorithm, just at HS and for microframes (vs. frames).
  20. *
  21. * A frame budget must be maintained for currently configured endpoints.
  22. * A frame budget consists of a (continuous repeating) sequence of frames.
  23. * Each frame consists of the endpoints that are allocated time for that frame.
  24. * Each frame contains the microframe patterns for each configured endpoint for
  25. * split transaction endpoints. A microframe pattern consists of the microframes in a
  26. * frame that contain start-splits (SS) or complete-splits (CS) for an endpoint.
  27. *
  28. * The frame budget is maintained separately from any HC schedule of transactions for endpoints.
  29. * The two must be coherent with each other, but the budget is essentially a pattern to be used
  30. * to construct an HC transaction schedule as clients request data transfer. When a new endpoint
  31. * is allocated, it can change the pattern of previously existing (allocated) endpoints. This
  32. * requires that the corresponding HC schedule be reconciled at some point in time. Precisely how
  33. * the two are reconciled is not dealt with in this algorithm. However, some ideas are captured
  34. * later in these comments.
  35. *
  36. * The microframe patterns budgeted must match the order in which transactions are
  37. * processed on the bus by the host controller and its driver. This makes the
  38. * scheduling software interdependent with the host controller and its driver.
  39. *
  40. * There are several requirements between the computed frame budget and the order in which the
  41. * HC visits transactions:
  42. * 1) (EHCI req): a large isoch transaction (> about 570 bytes?) must be first in the
  43. * frame to avoid having more than 1 microframe with an SS and CS
  44. * This is in lieu of having to sort the transactions into decreasing size through the frame.
  45. * 2) (core spec req): the order of CSs in a microframe for a set of endpoints must be
  46. * identical to the order of SSs used to start the classic transactions
  47. * 3) (implementation requirement due to EHCI and core spec TT rules): the order of endpoints
  48. * for isoch OUTs longer than 188 bytes (e.g. ones with more than one SS) must match the
  49. * budgeted order so that multiple SSs are sequenced correctly across microframes for multiple
  50. * endpoints.
  51. *
  52. * Example, assume endpoint A and B
  53. * are isoch OUT, with A budgeted before B and B requires 2 microframes of SS. A must
  54. * be processed before B so that the SS sequence is:
  55. * microframe N: A-SS1, B-SS1
  56. * microframe N+1: B-SS2
  57. *
  58. * if instead the processing order were allowed to be B and then A this would result in:
  59. *
  60. * microframe N: B-SS1, A-SS1
  61. * microframe N+1: B-SS2
  62. *
  63. * this would result in the TT seeing B-SS1, A-SS1, B-SS2. This is not a valid order for
  64. * long isoch OUT for B. The TT will treat B (initially) as incomplete (due to the A SS) and ignore
  65. * B-SS2.
  66. * 4) (implementation requirement due to EHCI and core spec TT rules): The order of endpoints for
  67. * isoch INs longer than 188 bytes must match the budgeted order (similar to above for OUTs).
  68. * 5) (core spec) Only 2^N periods are allowed.
  69. * 6) Classic (split) budget is based on best case times (specified by core spec), i.e. no bit stuffing.
  70. * However, high speed budgets are based on worst case times, i.e. including bit stuffing.
  71. * 7) (EHCI req) Interrupt endpoints must be ordered in the frame from largest period to smallest period.
  72. * 8) (core spec and EHCI req) Interrupt endpoints have different numbers of CSs. Ones near the end of
  73. * a frame have 2, while others have 3. EHCI requires that late endpoints DON'T have 3, so all
  74. * endpoints can't be treated as having three (to try and allow unordered endpoints in a frame).
  75. * It also might appear that early endpoints could be unordered, while later ones are ordered.
  76. * However, as endpoints are allocated, a previously "undordered" endpoint would then need to
  77. * become "ordered". This seems to be a really hard transition, therefore all interrupt
  78. * endpoints are required to be ordered in a frame.
  79. *
  80. * This scheduling algorithm depends on the HC transaction processing sequence:
  81. * 1) Interrupt endpoints are executed in decreasing period order (e.g. period 16 endpoint
  82. * is executed before a period 8 endpoint). Endpoints with the same period are
  83. * executed in budget order.
  84. * 2) Interrupt endpoints are executed after all isochronous endpoints.
  85. * 3) Isochronous OUT endpoints longer than 188 bytes are executed in budget order.
  86. * 4) Isochronous IN periodic endpoints are executed in budget order. (must be so to ensure
  87. * that CSs for endpoints occur in correct order, e.g. for different lengths)
  88. * Note: this could be relaxed if more CSs were budgeted.
  89. * 5) If there is a large isoch, it is first in the frame.
  90. *
  91. * When transactions are enqueued in the framelist HC data structures, the order
  92. * of the transactions must be the same as that budgeted. This is so that when an endpoint
  93. * is allocated (inserted), the budget computation accurately determines the other affected endpoints.
  94. * The HC is required to process SSs and CSs for a set of endpoints for the same TT in the same order.
  95. * The act of creating the frame list ensures that this order is preserved (without
  96. * requiring any particular order to be explicitly created.
  97. * The physical framelist order from time to time can be different for interrupt endpoints,
  98. * but the TT is not sensitive to order.
  99. *
  100. * This algorithm computes budget order as determined in the routine OK_to_insert (below).
  101. *
  102. * Simplifying scheduling and HC assumptions:
  103. * a) The maximum allocation allowed is reduced by 30 (from 1157 to 1127 FS byte times)
  104. * FS byte times to eliminate needing to deal with an end of frame wrap case
  105. * that would require a TD back pointer.
  106. * b) Isoch IN transactions/endpoints longer than 1023-188-30 FS byte times are artifically
  107. * processed (inserted) at the beginning of a frame. This eliminates another
  108. * end of frame wrap case. Actually this is reduced to 1/2 a frame, since there can only be
  109. * one "large" transaction in a frame.
  110. * c) It is highly desirable to have the least impact on other endpoints due to an allocation.
  111. *
  112. * The isoch portion of the frame budget is maintained such that the frame time is "compacted".
  113. * I.e., there are no "holes" in the allocated frame time.
  114. *
  115. * In contrast, the interrupt portion of the frame budget has "holes" in the allocated frame time.
  116. * This is because the HC visits endpoints in the schedule in increasing period order, and we
  117. * must have the same SS/CS masks for all frames the endpoint is in, while a compacted budget
  118. * would require decreasing period order.
  119. *
  120. * The SS and CS masks used are only computed when the endpoint is configured.
  121. * This eliminates requiring different microframe patterns for different frames.
  122. * This also means that based on the presence of transactions for configured endpoints,
  123. * there can be "holes" in the periodic portion of the classic frame. These holes can be
  124. * reclaimed and used for control and bulk classic transactions.
  125. *
  126. * Endpoints have a single "SS/CS microframe within frame" pattern for all frames
  127. * in which they have transfers. This pattern is computed once when the endpoint is
  128. * configured. It is also recomputed whenever other endpoints in the same frame have their
  129. * allocation time changed due to some other newly allocated endpoint.
  130. *
  131. * The budget frame list for FS/LS devices behind a TT, must be bound/tracked to/by
  132. * that TT. A normal FS/LS frame bus time is maintained in addition to
  133. * the more detailed microframe pattern information.
  134. * Once the microframe pattern is determined, an HS allocation must be made of the
  135. * HS HC budget. This HS allocation is done on a microframe basis for each SS/CS
  136. * that is required to support the classic device (and its TT). The time for each
  137. * SS (and any data per microframe) is allocated in the appropriate microframe(s).
  138. * The time for each CS is allocated in the appropriate microframe(s).
  139. *
  140. * The data requirements (vs. overhead) for all classic IN endpoints for each TT should be tracked
  141. * for each HS microframe. The time for the data portion should never exceed 188 bytes
  142. * (inc. bitstuffing overhead) for CSs for all devices of a TT in a HS microframe. SSs always
  143. * allocate the required time. For CSs, the first classic device must allocate data time in
  144. * all microframes for all splits. However, once the time in a HS microframe for a TT reaches
  145. * 188 data bytes, no more time needs to be allocated from the HS budget for data. This is
  146. * because that is the most data that a classic bus can ever require. It may take more split
  147. * transactions to move that data, but the amount of data can't increase. The additional splits
  148. * just deal with the classic bus operation variation.
  149. *
  150. * The bus times for each period in the frame list must be updated for an endpoint. I.e.
  151. * multiple frame entries will need to be adjusted for periods smaller than the budgeting
  152. * window (i.e. MAXFRAMES). A tree structure is used to link slower period endpoints from different
  153. * frames to the same endpoint of a faster period (similar to the periodic Qhead HC structure.
  154. * There is a tree for isoch endpoints and a separate tree for interrupt endpoints.
  155. * The endpoints lists rooted in each budget frame starts with a dummy SOF endpoint to make link
  156. * traversal easier (i.e. avoids an empty list case).
  157. *
  158. * All bus times are kept in byte time units (either HS or FS). LS bus times are tracked
  159. * as appropriately scaled FS byte times.
  160. *
  161. * A general comment about processing flow in allocate and deallocate. There are three processing
  162. * concepts. All frames that an endpoint is allcoated within, must be visited to do the endpoint
  163. * specific processing. However, other frames must also be visited to deal with the movement of
  164. * their budget times due to the changed endpoint. Therefore all frames are always visited for
  165. * an allocation change. As the frame list is walked, the "frame_bias" ranges over:
  166. * (- ep->start_frame) + MAXFRAMES - 1 ... (- ep->start_frame)
  167. * (frames are visited in reverse order)
  168. * But only in frames that are multiples of the endpoint's period are changes
  169. * made. This causes some of the code "tracking" complexity.
  170. *
  171. * Comments about reconciling HC schedule and changed frame budgets:
  172. * When an isoch endpoint's microframe pattern is recomputed, currently pending transaction
  173. * requests are not manipulated. But the new pattern does affect future transactions.
  174. * (Since the FS/LS device is expecting its transactions anywhere in the frame, the
  175. * microframe "jitter" that results is not relevant.)
  176. *
  177. * However, when an interrupt endpoint is inserted/removed in/from the middle of a frame, the
  178. * other endpoints (with pending/active transactions) affected must have their
  179. * transactions updated. For interrupt endpoints, the split transaction masks are
  180. * in the queue head. To change the interrupt masks:
  181. * 1. the endpoint QH must be made inactive
  182. * 2. the driver must wait for >= 1 frame time to ensure that the HC is not processing the QH
  183. * 3. the split masks are changed
  184. * 4. if the TD did an SS and didn't do a CS in the frame, the endpoint is halted to recover
  185. * (a nasty race condition, but hopefully rare)
  186. * 5. the QH is made active.
  187. *
  188. * To change isoch masks, the current pending/active TDs can be changed in place.
  189. * Existing error mechanisms can handle any race conditions with the HC.
  190. *
  191. * There may be a corner condition in that the budget information shouldn't be used
  192. * (solely) to find transactions in the current schedule. If a client requests transactions
  193. * according to one budget and then the budget changes, and then the client wants to abort
  194. * the old transactions, I think the stack would normally use the budget to determine where
  195. * the transactions are in the schedule, but now the budget may identify "other"
  196. * microframes as having the transaction(s). Coder beware!
  197. *
  198. * Classic HC allocation uses the microframe_info, microframe[0] to count the bandwidth allocation.
  199. *
  200. * History:
  201. *
  202. * 10-3-2000, JIG: fixed incorrect starting time and shift calculations for first interrupt and only large isoch
  203. * 10-4-2000, JIG: moved max allocation into TT and HC structs,
  204. * added inputfile ability to set TT/HC allocation_limit, TT/HC thinktime, and HC speed
  205. * made dump_budget not dump split info for classic HC
  206. * fixed duplicate thinktime addition in calc_bus_time for HS/FS nonsplit allocations
  207. *
  208. ****************************************************/
  209. #include "common.h"
  210. #if 0
  211. int min (int a, int b)
  212. {
  213. return (int) ((a<=b) ? a : b);
  214. }
  215. int max (int a, int b)
  216. {
  217. return (int) ((a>=b) ? a : b);
  218. }
  219. #endif
  220. /**
  221. error
  222. **/
  223. error(char *s)
  224. {
  225. // take some action for error, but
  226. // don't return to caller
  227. //printf("error called: %s.\n", s);
  228. DBGPRINT(("error called: %s.\n", s));
  229. // exit(1);
  230. }
  231. /*******
  232. Add_bitstuff
  233. *******/
  234. unsigned Add_bitstuff(
  235. unsigned bus_time)
  236. {
  237. // Bit stuffing is 16.6666% extra.
  238. // But we'll calculate bitstuffing as 16% extra with an add of a 4bit
  239. // shift (i.e. value + value/16) to avoid floats.
  240. return (bus_time + (bus_time>>4));
  241. }
  242. /*******
  243. Allocate_check
  244. *******/
  245. int Allocate_check(
  246. unsigned *used,
  247. unsigned newval,
  248. unsigned limit)
  249. {
  250. int ok = 1;
  251. unsigned t;
  252. // check if this new allocation fits in the currently used amout below the limit.
  253. //
  254. t = *used + newval;
  255. // do allocation even if over limit. This will be fixed/deallocated after the frame is finished.
  256. *used = t;
  257. if ( t > limit)
  258. {
  259. //printf("Allocation of %d+%d out of %d\n", *used, newval, limit);
  260. DBGPRINT(("Allocation of %d+%d out of %d\n", (*used-newval), newval, limit));
  261. error("Allocation check failed");
  262. ok = 0;
  263. }
  264. return ok;
  265. }
  266. /*******
  267. OK_to_Insert
  268. *******/
  269. int OK_to_insert(
  270. PEndpoint curr,
  271. PEndpoint newep
  272. )
  273. {
  274. // Determine if this current endpoint in the budget frame endpoint list is the one before
  275. // which the new endpoint should be inserted.
  276. // DON'T call this routine if there is already a large isoch ep in this frame and this is a
  277. // large isoch ep!!
  278. // Called in a loop for each endpoint while walking the budget frame endpoint list in linkage order.
  279. // on exit when returns 1: curr points to the endpoint before which the new endpoint should be inserted.
  280. int insertion_OK = 0;
  281. /*
  282. There are separate endpoint budget "trees" for isoch and interrupt. A budget tree has the same
  283. organization as the EHCI interrupt qhead tree. This allows a single endpoint data structure to
  284. represent the allocation requirements in all frames allocated to the endpoint.
  285. Order of insertion in a budget frame list of endpoints is as follows for each list.
  286. Isoch:
  287. 1. Endpoints in period order, largest period to smallest period
  288. (required to maintain endpoint linkages easily in a "Tree")
  289. (HC will actually enqueue isoch xacts in smallest period to largest period order)
  290. 1a. within the same period
  291. newer endpoints are at the front of the sublist, older are at the end
  292. (Since isoch are visited by the HC in reverse order, this results in new
  293. endpoints being added after older endpoints, thereby having least impact on existing
  294. frame traffic)
  295. 2. An endpoint larger than LARGEXACT bytes (only ever one possible per frame) is held separated
  296. from normal list
  297. (avoids having a long isoch that requires 2 uframes with SS and CS)
  298. Note that the endpoint could have a period different than 1
  299. Interrupt:
  300. 1. Endpoints in period order, largest period to smallest period
  301. (required to maintain endpoint linkages easily in a "Tree")
  302. 1.2 within same period, newer endpoints are at the end of the sublist, older are at the front
  303. Corresponding required (for this algorithm) order of transactions in HC frame list is:
  304. 1. First, an isoch endpoint larger than LARGEXACT bytes (only ever one possible per frame)
  305. (avoids having a long isoch that requires 2 uframes with SS and CS)
  306. Note that the endpoint could have a period different than 1
  307. 2. Isoch endpoint ITDs in INCREASING period order
  308. ***** (NOTE: THIS IS opposite AS IN THE BUDGET LIST!!!!) *****
  309. 2a. within the same period, oldest allocated eps are first, newest allocated are last
  310. 3. interrupts endpoint Qheads in decreasing period order (in "tree" of qheads)
  311. 3a. within the same period, oldest allocated (in time) eps are first, newest allocated are last
  312. */
  313. if (newep->calc_bus_time < LARGEXACT) // only really possible for isoch
  314. {
  315. if (curr) // some endpoints already allocated
  316. {
  317. // This is the correct insertion point if the new ep has a period longer/larger
  318. // than the current ep (so put it before the current ep)
  319. // check if this is the correct period order
  320. if ( ((curr->actual_period < newep->actual_period) && newep->ep_type == interrupt) ||
  321. ((curr->actual_period <= newep->actual_period) && newep->ep_type == isoch))
  322. {
  323. insertion_OK = 1;
  324. } else
  325. if (curr == newep) // we are at the current endpoint (due to inserting during a previous frame)
  326. insertion_OK = 1;
  327. } else
  328. insertion_OK = 1; // if first endpoint, always "insert" at head
  329. } //else large xact, so this routine shouldn't be called since the large is held separately
  330. // This routine won't be called if there is already a large in this frame.
  331. return insertion_OK;
  332. }
  333. /*******
  334. Compute_last_isoch_time
  335. ********/
  336. int Compute_last_isoch_time(
  337. PEndpoint ep,
  338. int frame
  339. )
  340. {
  341. int t;
  342. PEndpoint p;
  343. p = ep->mytt->frame_budget[frame].isoch_ehead; // dummy SOF
  344. p = p->next_ep; // potential real isoch, could be large isoch or other isoch
  345. if (p)
  346. {
  347. // There is an isoch, so use its start time (since it is the last isoch on the bus.
  348. t = p->start_time + p->calc_bus_time;
  349. } else // There aren't other, nonlarge isoch transactions in the frame
  350. {
  351. // If there is a large isoch, use that
  352. if (ep->mytt->frame_budget[frame].allocated_large)
  353. {
  354. p = ep->mytt->frame_budget[frame].allocated_large;
  355. t = p->start_time + p->calc_bus_time;
  356. } else
  357. // no isoch transactions
  358. t = FS_SOF;
  359. }
  360. return t;
  361. }
  362. /*******
  363. Compute_ep_start_time
  364. ********/
  365. int Compute_ep_start_time(
  366. PEndpoint curr_ep,
  367. PEndpoint ep,
  368. PEndpoint last_ep,
  369. int frame
  370. )
  371. {
  372. int t;
  373. PEndpoint p;
  374. // Given that there is a dummy SOF endpoint at the beginning of each list (always), there
  375. // is always a valid last_ep. If the end of list is reached, curr_ep will be zero.
  376. // For isoch endpoints, the "next" ep on the list is the previous start time endpoint
  377. // For interrupt endpoint, the previous ep is the previous start time endpoint.
  378. // For interrupt endpoint, if this is the interrupt endpoint at the beginning of the int list
  379. // (after some isoch), the start time is the end of the isoch.
  380. if (curr_ep) // we will do an insertion in the middle of the list
  381. {
  382. if (ep->ep_type == isoch)
  383. {
  384. t = curr_ep->start_time + curr_ep->calc_bus_time;
  385. } else // interrupt
  386. {
  387. if (last_ep == ep->mytt->frame_budget[frame].int_ehead) // new first interrupt ep
  388. {
  389. t = Compute_last_isoch_time(ep, frame);
  390. } else
  391. t = last_ep->start_time + last_ep->calc_bus_time;
  392. }
  393. } else // empty list or have run off end of budget list
  394. {
  395. if (ep->ep_type == isoch)
  396. {
  397. if (ep->mytt->frame_budget[frame].allocated_large)
  398. {
  399. p = ep->mytt->frame_budget[frame].allocated_large;
  400. t = p->start_time + p->calc_bus_time;
  401. } else
  402. t = FS_SOF;
  403. } else // interrupt
  404. {
  405. if (last_ep != ep->mytt->frame_budget[frame].int_ehead) // is the last ep not the dummy SOF?
  406. {
  407. // non empty list, ran off end of interrupt list,
  408. // this is the last transaction in the frame
  409. t = last_ep->start_time + last_ep->calc_bus_time;
  410. } else // was empty interrupt list
  411. t = Compute_last_isoch_time(ep, frame);
  412. }
  413. } // end if for first endpoint on list
  414. return t;
  415. }
  416. /*******
  417. Compute_nonsplit_overhead
  418. ********/
  419. int Compute_nonsplit_overhead(
  420. PEndpoint ep)
  421. {
  422. PHC hc;
  423. hc = ep->mytt->myHC;
  424. if (ep->speed == HSSPEED)
  425. {
  426. if (ep->direction == OUTDIR)
  427. {
  428. if (ep->ep_type == isoch)
  429. {
  430. return HS_TOKEN_SAME_OVERHEAD + HS_DATA_SAME_OVERHEAD + hc->thinktime;
  431. } else // interrupt
  432. {
  433. return HS_TOKEN_SAME_OVERHEAD + HS_DATA_SAME_OVERHEAD +
  434. HS_HANDSHAKE_OVERHEAD + hc->thinktime;
  435. }
  436. } else
  437. { // IN
  438. if (ep->ep_type == isoch)
  439. {
  440. return HS_TOKEN_TURN_OVERHEAD + HS_DATA_TURN_OVERHEAD + hc->thinktime;
  441. } else // interrupt
  442. {
  443. return HS_TOKEN_TURN_OVERHEAD + HS_DATA_TURN_OVERHEAD +
  444. HS_HANDSHAKE_OVERHEAD + hc->thinktime;
  445. }
  446. } // end of IN overhead calculations
  447. } else if (ep->speed == FSSPEED)
  448. {
  449. if (ep->ep_type == isoch)
  450. {
  451. return FS_ISOCH_OVERHEAD + hc->thinktime;
  452. } else // interrupt
  453. {
  454. return FS_INT_OVERHEAD + hc->thinktime;
  455. }
  456. } else // LS
  457. {
  458. return LS_INT_OVERHEAD + hc->thinktime;
  459. }
  460. }
  461. /*******
  462. Compute_HS_Overheads
  463. ********/
  464. Compute_HS_Overheads(
  465. PEndpoint ep,
  466. int *HS_SS,
  467. int *HS_CS)
  468. {
  469. PHC hc;
  470. hc = ep->mytt->myHC;
  471. if (ep->direction == OUTDIR)
  472. {
  473. if (ep->ep_type == isoch)
  474. {
  475. *HS_SS = HS_SPLIT_SAME_OVERHEAD + HS_DATA_SAME_OVERHEAD + hc->thinktime;
  476. *HS_CS = 0;
  477. } else // interrupt
  478. {
  479. *HS_SS = HS_SPLIT_SAME_OVERHEAD + HS_DATA_SAME_OVERHEAD + hc->thinktime;
  480. *HS_CS = HS_SPLIT_TURN_OVERHEAD + HS_HANDSHAKE_OVERHEAD + hc->thinktime;
  481. }
  482. } else
  483. { // IN
  484. if (ep->ep_type == isoch)
  485. {
  486. *HS_SS = HS_SPLIT_SAME_OVERHEAD + hc->thinktime;
  487. *HS_CS = HS_SPLIT_TURN_OVERHEAD + HS_DATA_TURN_OVERHEAD + hc->thinktime;
  488. } else // interrupt
  489. {
  490. *HS_SS = HS_SPLIT_SAME_OVERHEAD + hc->thinktime;
  491. *HS_CS = HS_SPLIT_TURN_OVERHEAD + HS_DATA_TURN_OVERHEAD + hc->thinktime;
  492. }
  493. } // end of IN overhead calculations
  494. }
  495. /*******
  496. Deallocate_HS
  497. ********/
  498. Deallocate_HS(
  499. PEndpoint ep,
  500. int frame_bias)
  501. {
  502. // 1. Calculate last microframe for a nominal complete split
  503. // 2. Calculate HS overheads
  504. // 3. Deallocate HS split overhead time
  505. // 4. Deallocate separate HS data bus time
  506. unsigned i, t, f, HS_SSoverhead, HS_CSoverhead, lastcs, min_used;
  507. int m;
  508. PHC hc;
  509. hc = ep->mytt->myHC;
  510. //***
  511. //*** 1. Calculate last microframe for a nominal complete split
  512. //***
  513. // determine last microframe for complete split (isoch in particular)
  514. //lastcs = floor( (ep->start_time + ep->calc_bus_time) / (float) FS_BYTES_PER_MICROFRAME) + 1;
  515. lastcs = ( (ep->start_time + ep->calc_bus_time) / FS_BYTES_PER_MICROFRAME) + 1;
  516. //***
  517. //*** 2. Calculate HS overheads
  518. //***
  519. Compute_HS_Overheads(ep, &HS_SSoverhead, &HS_CSoverhead);
  520. //***
  521. //*** 3. Deallocate HS split overhead time for this frame
  522. //***
  523. // Deallocate HS time for SS and CS overhead, but treat data differently
  524. // Deallocate HS start split bus time
  525. m = ep->start_microframe;
  526. f = ep->start_frame + frame_bias;
  527. if (m == -1)
  528. {
  529. m = 7;
  530. if (f == 0)
  531. f = MAXFRAMES - 1;
  532. else
  533. f--;
  534. }
  535. for (i=0;i < ep->num_starts; i++)
  536. {
  537. hc->HS_microframe_info[f][m].time_used -= HS_SSoverhead;
  538. ep->mytt->num_starts[f][m]--;
  539. m++;
  540. if (m > 7) {
  541. m = 0;
  542. f = (f + 1) % MAXFRAMES;
  543. }
  544. }
  545. // Deallocate HS complete split bus time
  546. if (ep->num_completes > 0)
  547. {
  548. m = ep->start_microframe + ep->num_starts + 1;
  549. f = ep->start_frame + frame_bias;
  550. for (i = 0; i < ep->num_completes; i++)
  551. {
  552. hc->HS_microframe_info[f][m].time_used -= HS_CSoverhead;
  553. m++;
  554. if (m > 7) {
  555. m = 0;
  556. f = (f + 1) % MAXFRAMES;
  557. }
  558. }
  559. }
  560. //***
  561. //*** 4. Deallocate separate HS data bus time
  562. //***
  563. // Deallocate HS data part of split bus time
  564. if (ep->direction) // OUT
  565. {
  566. // Deallocate full portion of data time in each microframe for OUTs
  567. m = ep->start_microframe;
  568. f = ep->start_frame + frame_bias;
  569. if (m == -1)
  570. {
  571. m = 7;
  572. if (f == 0)
  573. f = MAXFRAMES - 1;
  574. else
  575. f--;
  576. }
  577. for (i=0; i < ep->num_starts; i++) {
  578. min_used = min(
  579. FS_BYTES_PER_MICROFRAME,
  580. Add_bitstuff(ep->max_packet) - FS_BYTES_PER_MICROFRAME * i);
  581. hc->HS_microframe_info[f][m].time_used -= min_used;
  582. m++;
  583. if (m > 7) {
  584. m = 0;
  585. f = (f + 1) % MAXFRAMES;
  586. }
  587. }
  588. } else // IN
  589. {
  590. // Only deallocate at most 188 bytes for all devices behind a TT in
  591. // each microframe.
  592. if (ep->num_completes > 0)
  593. {
  594. m = ep->start_microframe + ep->num_starts + 1;
  595. f = ep->start_frame + frame_bias;
  596. for (i=0; i < ep->num_completes; i++)
  597. {
  598. // update total HS bandwith due to devices behind this tt
  599. // This is used to determine when to deallocate HS bus time.
  600. ep->mytt->HS_split_data_time[f][m] -=
  601. min(Add_bitstuff(ep->max_packet), FS_BYTES_PER_MICROFRAME);
  602. // calculate remaining bytes this endpoint contributes
  603. // to 188 byte limit per microframe and (possible) HS deallocation.
  604. if (ep->mytt->HS_split_data_time[f][m] < FS_BYTES_PER_MICROFRAME)
  605. {
  606. // find adjustment to HS allocation for data
  607. t = min(
  608. //
  609. FS_BYTES_PER_MICROFRAME - ep->mytt->HS_split_data_time[f][m],
  610. Add_bitstuff(ep->max_packet));
  611. hc->HS_microframe_info[f][m].time_used -= t;
  612. }
  613. m++;
  614. if (m > 7) {
  615. m = 0;
  616. f = (f + 1) % MAXFRAMES;
  617. }
  618. }
  619. }
  620. }
  621. }
  622. /*******
  623. Allocate_HS
  624. ********/
  625. int Allocate_HS(
  626. PEndpoint ep,
  627. int frame_bias)
  628. {
  629. // 1. Calculate start microframe
  630. // 2. Calculate last microframe for a nominal complete split
  631. // 3. Calculate number of SSs, CSs and HS overheads
  632. // 4. Allocate HS split overhead time
  633. // 5. Allocate separate HS data bus time
  634. unsigned i, t, f, HS_SSoverhead, HS_CSoverhead, lastcs, min_used;
  635. int m, retv;
  636. PHC hc;
  637. retv = 1;
  638. hc = ep->mytt->myHC;
  639. //***
  640. //*** 1. Calculate start microframe
  641. //***
  642. if (frame_bias == 0)
  643. // only update endpoint for first frame since other frames will simply
  644. // reference this endpoint (which has already had its information computed)
  645. //ep->start_microframe = floor(ep->start_time / (float) FS_BYTES_PER_MICROFRAME) - 1;
  646. ep->start_microframe = (ep->start_time / FS_BYTES_PER_MICROFRAME) - 1;
  647. //***
  648. //*** 2. Calculate last microframe for a nominal complete split
  649. //***
  650. // determine last microframe for complete split (isoch in particular)
  651. //lastcs = floor( (ep->start_time + ep->calc_bus_time) / (float) FS_BYTES_PER_MICROFRAME) + 1;
  652. lastcs = ( (ep->start_time + ep->calc_bus_time) / FS_BYTES_PER_MICROFRAME) + 1;
  653. //***
  654. //*** 3. Calculate number of SSs, CSs and HS overheads
  655. //***
  656. Compute_HS_Overheads(ep, &HS_SSoverhead, &HS_CSoverhead);
  657. // determine number of splits (starts and completes)
  658. if (ep->direction == OUTDIR)
  659. {
  660. if (ep->ep_type == isoch)
  661. {
  662. if (frame_bias == 0) {
  663. ep->num_starts = (ep->max_packet / FS_BYTES_PER_MICROFRAME) + 1;
  664. ep->num_completes = 0;
  665. }
  666. } else // interrupt
  667. {
  668. if (frame_bias == 0) {
  669. ep->num_starts = 1;
  670. ep->num_completes = 2;
  671. if (ep->start_microframe + 1 < 6)
  672. ep->num_completes++;
  673. }
  674. }
  675. } else
  676. { // IN
  677. if (ep->ep_type == isoch)
  678. {
  679. if (frame_bias == 0) {
  680. ep->num_starts = 1;
  681. ep->num_completes = lastcs - (ep->start_microframe + 1);
  682. if (lastcs <= 6)
  683. {
  684. if ((ep->start_microframe + 1) == 0)
  685. ep->num_completes++;
  686. else
  687. ep->num_completes += 2; // this can cause one CS to be in the next frame
  688. }
  689. else if (lastcs == 7)
  690. {
  691. if ((ep->start_microframe + 1) != 0)
  692. ep->num_completes++; // only one more CS if late in the frame.
  693. }
  694. }
  695. } else // interrupt
  696. {
  697. if (frame_bias == 0) {
  698. ep->num_starts = 1;
  699. ep->num_completes = 2;
  700. if (ep->start_microframe + 1 < 6)
  701. ep->num_completes++;
  702. }
  703. }
  704. } // end of IN
  705. //***
  706. //*** 4. Allocate HS split overhead time for this frame
  707. //***
  708. // check avail time for HS splits
  709. // allocate HS time for SS and CS overhead, but treat data differently
  710. // allocate HS start split bus time
  711. m = ep->start_microframe;
  712. f = ep->start_frame + frame_bias;
  713. if (m == -1)
  714. {
  715. m = 7;
  716. if (f == 0)
  717. f = MAXFRAMES - 1;
  718. else
  719. f--;
  720. }
  721. for (i=0;i < ep->num_starts; i++)
  722. {
  723. // go ahead and do the allocations even if the checks fail. This will be deallocated after the
  724. // frame is finished.
  725. if (!Allocate_check(
  726. &hc->HS_microframe_info[f][m].time_used,
  727. HS_SSoverhead,
  728. HS_MAX_PERIODIC_ALLOCATION))
  729. retv = 0;
  730. // Check for >16 SS in a microframe to one TT? Maybe not needed in practice.
  731. if (ep->mytt->num_starts[f][m] + 1 > 16) {
  732. error("too many SSs in microframe");
  733. retv = 0;
  734. }
  735. ep->mytt->num_starts[f][m]++;
  736. m++;
  737. if (m > 7) {
  738. m = 0;
  739. f = (f + 1) % MAXFRAMES;
  740. }
  741. }
  742. // allocate HS complete split bus time
  743. if (ep->num_completes > 0)
  744. {
  745. m = ep->start_microframe + ep->num_starts + 1;
  746. f = ep->start_frame + frame_bias;
  747. for (i = 0; i < ep->num_completes; i++)
  748. {
  749. if (!Allocate_check(
  750. &hc->HS_microframe_info[f][m].time_used,
  751. HS_CSoverhead,
  752. HS_MAX_PERIODIC_ALLOCATION))
  753. retv = 0;
  754. m++;
  755. if (m > 7) {
  756. m = 0;
  757. f = (f + 1) % MAXFRAMES;
  758. }
  759. }
  760. }
  761. //***
  762. //*** 5. Allocate separate HS data bus time
  763. //***
  764. // allocate HS data part of split bus time
  765. if (ep->direction) // OUT
  766. {
  767. // allocate full portion of data time in each microframe for OUTs
  768. m = ep->start_microframe;
  769. f = ep->start_frame + frame_bias;
  770. if (m == -1)
  771. {
  772. m = 7;
  773. if (f == 0)
  774. f = MAXFRAMES - 1;
  775. else
  776. f--;
  777. }
  778. for (i=0; i < ep->num_starts; i++) {
  779. min_used = min(
  780. FS_BYTES_PER_MICROFRAME,
  781. Add_bitstuff(ep->max_packet) - FS_BYTES_PER_MICROFRAME * i);
  782. if (! Allocate_check(
  783. &hc->HS_microframe_info[f][m].time_used,
  784. min_used,
  785. HS_MAX_PERIODIC_ALLOCATION))
  786. retv = 0;
  787. m++;
  788. if (m > 7) {
  789. m = 0;
  790. f = (f + 1) % MAXFRAMES;
  791. }
  792. }
  793. } else // IN
  794. {
  795. // Only allocate at most 188 bytes for all devices behind a TT in
  796. // each microframe.
  797. if (ep->num_completes > 0)
  798. {
  799. m = ep->start_microframe + ep->num_starts + 1;
  800. f = ep->start_frame + frame_bias;
  801. for (i=0; i < ep->num_completes; i++)
  802. {
  803. //calculate remaining bytes this endpoint contributes
  804. // to 188 byte limit per microframe and new (possible) HS allocation.
  805. if (ep->mytt->HS_split_data_time[f][m] < FS_BYTES_PER_MICROFRAME)
  806. {
  807. // find minimum required new contribution of this device:
  808. // either remaining bytes of maximum for TT or the bus time the
  809. // device can contribute
  810. t = min(
  811. // find maximum remaining bytes in this microframe for this tt.
  812. // Don't let it go to negative, which it could when device bus time
  813. // is greater than bytes per microframe (188)
  814. max(
  815. FS_BYTES_PER_MICROFRAME -
  816. ep->mytt->HS_split_data_time[f][m],
  817. 0),
  818. Add_bitstuff(ep->max_packet));
  819. if (! Allocate_check(
  820. &hc->HS_microframe_info[f][m].time_used,
  821. t,
  822. HS_MAX_PERIODIC_ALLOCATION))
  823. retv = 0;
  824. }
  825. // update total HS bandwith due to devices behind this tt
  826. // This is used in remove device to determine when to deallocate HS
  827. // bus time.
  828. ep->mytt->HS_split_data_time[f][m] +=
  829. min(Add_bitstuff(ep->max_packet), FS_BYTES_PER_MICROFRAME);
  830. m++;
  831. if (m > 7) {
  832. m = 0;
  833. f = (f + 1) % MAXFRAMES;
  834. }
  835. }
  836. }
  837. }
  838. return retv;
  839. }
  840. /*******
  841. Move_ep
  842. ********/
  843. int Move_ep(
  844. PEndpoint curr_ep,
  845. int shift_time,
  846. PEndpoint changed_ep_list[],
  847. int *changed_eps,
  848. int max_changed_eps,
  849. int *err)
  850. {
  851. int i, f;
  852. *err = 1;
  853. // Adjust endpoint allocation, if we haven't already done so.
  854. // This endpoint is adjusted to its new time.
  855. // For interrupt endpoints that are being moved due to deallocation, an endpoint can be moved more than once.
  856. // This can happen when recomputing the adjustment in some previous frame didn't allow the full movement to take place
  857. // because some later frame hadn't yet been recomputed (so it was inconsistent). The later move brings it closer to
  858. // consistency.
  859. // check if we already have this endpoint from some previous frame
  860. // for (i = 0; i < *changed_eps; i++)
  861. for (i = 0; changed_ep_list[i] != 0; i++)
  862. //if ((changed_ep_list[i] == curr_ep) && (curr_ep->moved_this_req))
  863. if (changed_ep_list[i] == curr_ep)
  864. break;
  865. // if ((i >= *changed_eps) || // haven't seen this endpoint before
  866. // ((i < *changed_eps) && !curr_ep->moved_this_req) || // have seen this endpoint this pass
  867. if ((changed_ep_list[i] == 0) || // haven't seen this endpoint before
  868. ((changed_ep_list[i] != 0) && !curr_ep->moved_this_req) || // have seen this endpoint this pass
  869. ((curr_ep->ep_type == interrupt) && (shift_time < 0)) )
  870. { // Update NEW changed endpoint
  871. // newly moved endpoints must have their HS bus time deallocated in all period frames in the budget window
  872. // (since the start_time can't be changed without affecting all frames the endpoint is in)
  873. // then their start_time can be changed and the bus time reallocated for all period frames in the budget window
  874. for (f=0; (f + curr_ep->start_frame) < MAXFRAMES; f += curr_ep->actual_period)
  875. Deallocate_HS(curr_ep, f);
  876. curr_ep->start_time += shift_time;
  877. if ((curr_ep->start_time + curr_ep->calc_bus_time) > FS_MAX_PERIODIC_ALLOCATION)
  878. {
  879. error("end of new xact too late");
  880. *err = 0;
  881. }
  882. curr_ep->moved_this_req = 1;
  883. if (changed_ep_list[i] == 0)
  884. {
  885. // don't overrun bounds of array if too small
  886. if (i < max_changed_eps)
  887. {
  888. changed_ep_list[i] = curr_ep;
  889. changed_ep_list[i + 1] = 0; // zero terminated list
  890. } else
  891. {
  892. error("too many changed eps");
  893. *err = 0;
  894. // will be fixed after the frame is finished
  895. }
  896. } // already have this endpoint on the change list
  897. for (f=0; (f + curr_ep->start_frame) < MAXFRAMES; f += curr_ep->actual_period)
  898. if (! Allocate_HS(curr_ep, f))
  899. *err = 0;
  900. return 1;
  901. } else
  902. return 0;
  903. }
  904. /*******
  905. Common_frames
  906. ********/
  907. int Common_frames(PEndpoint a, PEndpoint b)
  908. {
  909. PEndpoint maxep, minep;
  910. /* Determine if the two endpoints are present in the same frames based on their
  911. * start_frame and actual_period.
  912. */
  913. if ((a->actual_period == 1) || (b->actual_period == 1))
  914. return 1;
  915. if (a->actual_period >= b->actual_period)
  916. {
  917. maxep = a;
  918. minep = b;
  919. }
  920. else
  921. {
  922. maxep = b;
  923. minep = a;
  924. }
  925. if ((maxep->start_frame % minep->actual_period) == minep->start_frame)
  926. return 1;
  927. else
  928. return 0;
  929. }
  930. /*******
  931. Deallocate_endpoint_budget
  932. ********/
  933. int Deallocate_endpoint_budget(
  934. PEndpoint ep, // endpoint that needs to be removed (bus time deallocated)
  935. PEndpoint changed_ep_list[], // pointer to array to set (on return) with list of
  936. // changed endpoints
  937. int *max_changed_eps, // input: maximum size of (returned) list
  938. // on return: number of changed endpoints
  939. int partial_frames) // number of partial frames that have been allocated
  940. // Normally MAXFRAMES, but this function is also used to unwind partial
  941. // allocations.
  942. {
  943. /*
  944. 1. For each frame that endpoint is in:
  945. 2. Deallocate HS bus time for this endpoint
  946. 3. Deallocate classic bus time
  947. 4. Find where endpoint is
  948. 5. Unlink this endpoint
  949. 6. For isoch:
  950. 7. Compute gap
  951. 8. For previous (larger/eq period) endpoint in this frame list
  952. 9. move endpoint its new earlier position in the frame
  953. (skipping same period endpoints that have already been moved)
  954. 10. Setup to move interrupt endpoints
  955. 11. For interrupt:
  956. 12. For next (smaller/eq period) endpoint in this frame list
  957. 13. Compute gap
  958. 14. if ep is same period as gap, move it earlier
  959. 15. else "ep has faster period"
  960. 16. check for gap in "sibling" dependent frames of ep
  961. 17. if gap in all, move ep earlier
  962. 18. if moved, do next ep
  963. */
  964. int frame_bias, shift_time, changed_eps, moved, move_status;
  965. unsigned frame_cnt, gap_start, gap_end, i, j, siblings, gap_period;
  966. PEndpoint curr_ep, last_ep, p, head, gap_ep;
  967. // check that this endpoint is already allocated
  968. if (! ep->calc_bus_time)
  969. {
  970. error("endpoint not allocated");
  971. return 0;
  972. }
  973. // handle nonsplit HS deallocation
  974. if ((ep->speed == HSSPEED) && (ep->mytt->myHC->speed == HSSPEED))
  975. {
  976. for (i = (ep->start_frame*MICROFRAMES_PER_FRAME) + ep->start_microframe;
  977. i < MAXFRAMES*MICROFRAMES_PER_FRAME;
  978. i += ep->actual_period)
  979. {
  980. ep->mytt->myHC->HS_microframe_info[i/MICROFRAMES_PER_FRAME][
  981. i % MICROFRAMES_PER_FRAME].time_used -= ep->calc_bus_time;
  982. }
  983. ep->calc_bus_time = 0;
  984. return 1;
  985. } else // split and nonsplit FS/LS deallocation
  986. {
  987. if ((ep->speed != HSSPEED) && (ep->mytt->myHC->speed != HSSPEED))
  988. {
  989. // do classic (nonsplit) deallocation for classic HC
  990. for (i = ep->start_frame; i < MAXFRAMES; i += ep->actual_period)
  991. ep->mytt->myHC->HS_microframe_info[i][0].time_used -= ep->calc_bus_time;
  992. ep->calc_bus_time = 0;
  993. return 1;
  994. }
  995. }
  996. changed_eps = 0;
  997. while (changed_ep_list[changed_eps]) // reset indicators of endpoints changed this pass.
  998. {
  999. changed_ep_list[changed_eps]->moved_this_req = 0;
  1000. changed_eps++;
  1001. }
  1002. // this allows appending changed endpoints onto the current change list.
  1003. frame_bias = ep->start_frame;
  1004. frame_bias = (- frame_bias) + (partial_frames - 1);
  1005. for (frame_cnt=partial_frames; frame_cnt > 0; frame_cnt--)
  1006. {
  1007. //***
  1008. //*** 2. Deallocate HS bus time
  1009. //***
  1010. // Only do deallocation handling for frames this endpoint is located in
  1011. if ((frame_bias % ep->actual_period) == 0)
  1012. {
  1013. Deallocate_HS(ep, frame_bias);
  1014. //***
  1015. //*** 3. Deallocate classic bus time
  1016. //***
  1017. ep->mytt->frame_budget[ep->start_frame + frame_bias].time_used -= ep->calc_bus_time;
  1018. }
  1019. //***
  1020. //*** 4. Find where endpoint is
  1021. //***
  1022. // endpoint may not be in a particular frame since we process all frames, and the endpoint
  1023. // can have a period greater than 1. We process all frames, since the allocated times in a
  1024. // frame can be affected by endpoint allocations in other frames.
  1025. if (ep->ep_type == isoch)
  1026. {
  1027. last_ep = ep->mytt->frame_budget[ep->start_frame + frame_bias].isoch_ehead;
  1028. curr_ep = last_ep->next_ep; // get past SOF endpoint
  1029. } else
  1030. {
  1031. last_ep = ep->mytt->frame_budget[ep->start_frame + frame_bias].int_ehead;
  1032. curr_ep = last_ep->next_ep; // get past dummy SOF endpoint
  1033. }
  1034. // if this is not a large transaction, then search for it.
  1035. if (ep->calc_bus_time <= LARGEXACT)
  1036. {
  1037. // walk endpoint list for this frame to find where to insert new endpoint
  1038. while (curr_ep)
  1039. {
  1040. if (OK_to_insert(curr_ep, ep))
  1041. break;
  1042. last_ep = curr_ep;
  1043. curr_ep = curr_ep->next_ep;
  1044. }
  1045. // The isoch search will stop at the beginning of the same period sublist. The endpoint to be removed
  1046. // could be further in the sublist, we need to check for that if the ep to be removed isn't the first
  1047. // on the list. However, if it turns out that the ep isn't in the list, we can't lose the initial
  1048. // location
  1049. if ((ep->ep_type == isoch) && curr_ep)
  1050. {
  1051. p = last_ep;
  1052. while ((curr_ep->actual_period == ep->actual_period) && (curr_ep != ep))
  1053. {
  1054. last_ep = curr_ep;
  1055. curr_ep = curr_ep->next_ep;
  1056. if (curr_ep == 0)
  1057. {
  1058. // didn't find endpoint in list, so restore pointers back to initial location
  1059. last_ep = p;
  1060. curr_ep = last_ep->next_ep;
  1061. break;
  1062. }
  1063. }
  1064. }
  1065. } else // large transaction, so just get to the end of the isoch list to set up curr_ep and last_ep
  1066. {
  1067. while (curr_ep)
  1068. {
  1069. last_ep = curr_ep;
  1070. curr_ep = curr_ep->next_ep;
  1071. }
  1072. // now set up curr_ep to point to the large endpoint, but leave last_ep pointing to the end of the isoch list
  1073. curr_ep = ep;
  1074. }
  1075. //***
  1076. //*** 5. Unlink endpoint
  1077. //***
  1078. // only unlink if the endpoint is in this frame
  1079. if ((frame_bias % ep->actual_period) == 0)
  1080. {
  1081. if (ep->calc_bus_time <= LARGEXACT)
  1082. {
  1083. // if ((curr_ep == 0) && ((frame_bias % ep->actual_period) == 0))
  1084. if (curr_ep != 0)
  1085. {
  1086. last_ep->next_ep = curr_ep->next_ep;
  1087. curr_ep = curr_ep->next_ep;
  1088. }
  1089. } else
  1090. ep->mytt->frame_budget[ep->start_frame + frame_bias].allocated_large = 0;
  1091. } // processing of frames this endpoint is in
  1092. gap_ep = ep;
  1093. gap_period = gap_ep->actual_period;
  1094. //***
  1095. //*** 6. For isoch
  1096. //***
  1097. if (ep->ep_type == isoch)
  1098. {
  1099. // For isoch, when we find the deallocated endpoint in a frame, all isoch endpoints after it must
  1100. // be compacted (moved earlier). Since the isoch portion of the frame is kept in increasing period
  1101. // order and is compacted, a deallocation results in a recompacted budget.
  1102. //***
  1103. //*** 7. Compute gap
  1104. //***
  1105. head = ep->mytt->frame_budget[ep->start_frame + frame_bias].isoch_ehead;
  1106. gap_start = ep->start_time;
  1107. gap_end = gap_start + ep->calc_bus_time;
  1108. // If the deallocated endpoint is the large one and not period 1, we must check for siblings before
  1109. // compacting, since large allocations in other frames can prevent a compaction
  1110. if ((ep->calc_bus_time > LARGEXACT) && (ep->actual_period != 1))
  1111. {
  1112. for (i = 0; i < ep->actual_period; i++)
  1113. {
  1114. if (i != ep->start_frame)
  1115. {
  1116. p = ep->mytt->frame_budget[i].allocated_large;
  1117. if (p)
  1118. if (p->start_time + p->calc_bus_time - 1 > gap_start)
  1119. {
  1120. gap_start = p->start_time + p->calc_bus_time;
  1121. if (gap_end - gap_start <= 0)
  1122. break;
  1123. }
  1124. }
  1125. }
  1126. }
  1127. //***
  1128. //*** 8. For previous (larger/eq period) endpoint in this frame list
  1129. //***
  1130. if (gap_end - gap_start > 0)
  1131. {
  1132. // if large isoch is the one deallocated, update gap period based on the period of the last isoch
  1133. // in this frame
  1134. if ((ep->calc_bus_time > LARGEXACT) && (last_ep->actual_period < gap_period))
  1135. gap_period = last_ep->actual_period;
  1136. while (last_ep != head)
  1137. {
  1138. // The isoch list is "backwards", so curr_ep is earlier in the frame and last_ep is later.
  1139. // Compute the gap accordingly.
  1140. // curr_ep and last_ep are normally valid endpoints, but there are some corner conditions:
  1141. // a) curr_ep can be null when the ep isn't found, but we won't be here if that's true.
  1142. // b) last_ep can be dummy_sof when ep is newest, slowest period endpoint, but that will be
  1143. // handled as part of the interrupt ep handling initial conditions (and we won't get here)
  1144. //***
  1145. //*** 9. move endpoint its new earlier position in the frame
  1146. //*** (skipping same period endpoints that have already been moved)
  1147. //***
  1148. shift_time = gap_end - gap_start;
  1149. if (shift_time > 0)
  1150. {
  1151. moved = Move_ep(
  1152. last_ep,
  1153. - shift_time,
  1154. changed_ep_list,
  1155. &changed_eps,
  1156. *max_changed_eps,
  1157. &move_status);
  1158. if (! move_status)
  1159. error("deallocation move failure!!"); //<<few things can go wrong here, but num eps could >>
  1160. if (! moved)
  1161. break; // since we have found the part of the frame tree that has already been moved
  1162. // previous frames.
  1163. }
  1164. // rewalk isoch list until we get to "previous" endpoint in list/frame.
  1165. // This will be a little nasty since the isoch tree is linked in the opposite order that we
  1166. // really need to walk the frame to "compact". Simply re-walk the isoch tree for this frame
  1167. // from the head until we get to the previous. This is mostly ok since the isoch tree is
  1168. // extremely likely to be normally very short so the processing hit of rewalking the list will
  1169. // normally be small.
  1170. p = last_ep;
  1171. last_ep = ep->mytt->frame_budget[ep->start_frame + frame_bias].isoch_ehead;
  1172. curr_ep = last_ep->next_ep; // get past dummy SOF endpoint
  1173. // This test always terminates since we can't run off the end of the list due to the entry
  1174. // condition of the last_ep not being the (dummy) head.
  1175. while (curr_ep != p)
  1176. {
  1177. last_ep = curr_ep;
  1178. curr_ep = curr_ep->next_ep;
  1179. }
  1180. } // end of isoch endpoints in frame
  1181. } // end of shift handling
  1182. //***
  1183. //*** 10. Setup to move interrupt endpoints
  1184. //***
  1185. last_ep = ep->mytt->frame_budget[ep->start_frame + frame_bias].int_ehead;
  1186. curr_ep = last_ep->next_ep; // get past dummy SOF endpoint
  1187. // if there is an isoch endpoint, use the last one as the last_ep for interrupt budget
  1188. // processing to allow correct computation of the previous transaction end time.
  1189. // if there is a non-large isoch endpoint, use it other if there is a large isoch use that
  1190. // otherwise, leave the dummy sof interrupt endpoint as last
  1191. if (ep->mytt->frame_budget[ep->start_frame + frame_bias].isoch_ehead->next_ep)
  1192. last_ep = ep->mytt->frame_budget[ep->start_frame + frame_bias].isoch_ehead->next_ep;
  1193. else if (ep->mytt->frame_budget[ep->start_frame + frame_bias].allocated_large)
  1194. last_ep = ep->mytt->frame_budget[ep->start_frame + frame_bias].allocated_large;
  1195. } // end isoch
  1196. //***
  1197. //*** 11. For interrupt
  1198. //***
  1199. // The interrupt frame budget can have "holes" of unallocated time in a frame. These holes
  1200. // can be caused by some endpoint in one frame forcing an endpoint in another frame to be later
  1201. // in the frame to avoid collisions. In order to compact after a deallocation, we have to ensure
  1202. // that the gap exists in all frames of an endpoint that is a candidate to move.
  1203. // An endpoint that has an end time that is greater than ep's start time (but less than the
  1204. // end time) advances the gap start time to the (previous) endpoint's end time.
  1205. // An endpoint that has a start time that is less than the ep's end time (but greater than the
  1206. // start time) reduces the end time to the (later) endpoint's start time.
  1207. //
  1208. // If the gap end time is greater than the gap start time, we have to move affected endpoints by that
  1209. // amount. Otherwise, no endpoints are affected by the removal in this frame.
  1210. // if this is the first interrupt on the endpoint list, fixup the last_ep pointer for the gap computation
  1211. if ((ep->ep_type == interrupt) && (last_ep == ep->mytt->frame_budget[ep->start_frame + frame_bias].int_ehead))
  1212. {
  1213. if (ep->mytt->frame_budget[ep->start_frame + frame_bias].isoch_ehead->next_ep)
  1214. last_ep = ep->mytt->frame_budget[ep->start_frame + frame_bias].isoch_ehead->next_ep;
  1215. else if (ep->mytt->frame_budget[ep->start_frame + frame_bias].allocated_large)
  1216. last_ep = ep->mytt->frame_budget[ep->start_frame + frame_bias].allocated_large;
  1217. }
  1218. //***
  1219. //*** 12. For next (smaller/eq period) endpoint in this frame list
  1220. //***
  1221. while (curr_ep)
  1222. {
  1223. //***
  1224. //*** 13. Compute gap
  1225. //***
  1226. gap_start = last_ep->start_time + last_ep->calc_bus_time;
  1227. gap_end = curr_ep->start_time;
  1228. moved = 0;
  1229. //***
  1230. //*** 14. if ep is same or larger period than gap, move it earlier
  1231. //***
  1232. if ((gap_period <= curr_ep->actual_period) && (gap_ep->start_frame == curr_ep->start_frame))
  1233. {
  1234. shift_time = gap_end - gap_start;
  1235. if (shift_time > 0)
  1236. {
  1237. moved = Move_ep(
  1238. curr_ep,
  1239. - shift_time,
  1240. changed_ep_list,
  1241. &changed_eps,
  1242. *max_changed_eps,
  1243. &move_status);
  1244. if (! move_status)
  1245. error("deallocate move failure 2"); // <<few things, but num eps could fail here>>
  1246. }
  1247. } else // move candidate has a smaller interrupt period or has a different start_frame
  1248. {
  1249. //***
  1250. //*** 15. else "ep has faster period or different start_frame"
  1251. //***
  1252. //***
  1253. //*** 16. check for gap in "sibling" dependent frames of ep
  1254. //***
  1255. // siblings are the other frames that the curr_ep is dependent upon. E.g. if curr period
  1256. // is 1 and gap_period is 8, there are 7 other frames that need to be checked for a gap
  1257. if (Common_frames(curr_ep, ep))
  1258. siblings = (gap_period / curr_ep->actual_period);
  1259. else // move candidate is not in frames occupied by deleted endpoint
  1260. siblings = MAXFRAMES / curr_ep->actual_period;
  1261. j = curr_ep->start_frame;
  1262. for (i = 0; i < siblings; i++)
  1263. {
  1264. // find curr_ep in new sibling frame to check gap
  1265. // We only look in frames that we know the curr_ep is in.
  1266. // We can look in frames that aren't affected by the deleted ep, but don't optimize for now.
  1267. // skip the gap start frame since we already know it has a gap
  1268. if (j != gap_ep->start_frame) {
  1269. last_ep = ep->mytt->frame_budget[j].int_ehead;
  1270. p = last_ep->next_ep;
  1271. // fixup last_ep if this is the first interrupt ep in the frame after some isoch.
  1272. if (ep->mytt->frame_budget[j].isoch_ehead->next_ep)
  1273. last_ep = ep->mytt->frame_budget[j].isoch_ehead->next_ep;
  1274. else if (ep->mytt->frame_budget[j].allocated_large)
  1275. last_ep = ep->mytt->frame_budget[j].allocated_large;
  1276. while (p && (p != curr_ep))
  1277. {
  1278. last_ep = p;
  1279. p = p->next_ep;
  1280. }
  1281. if (last_ep->start_time + last_ep->calc_bus_time - 1 > gap_start)
  1282. {
  1283. gap_start = last_ep->start_time + last_ep->calc_bus_time;
  1284. if (gap_end - gap_start <= 0)
  1285. break;
  1286. }
  1287. }
  1288. j += curr_ep->actual_period;
  1289. }
  1290. //***
  1291. //*** 17. if gap in all, move ep earlier
  1292. //***
  1293. shift_time = gap_end - gap_start;
  1294. if (shift_time > 0)
  1295. {
  1296. moved = Move_ep(
  1297. curr_ep,
  1298. - shift_time,
  1299. changed_ep_list,
  1300. &changed_eps,
  1301. *max_changed_eps,
  1302. &move_status);
  1303. if (! move_status)
  1304. error("deallocate move failure 3"); // << few things, but num eps could fail here>>
  1305. }
  1306. } // end of faster period interrupt endpoint move candidate
  1307. //***
  1308. //*** 18. if moved, do next ep
  1309. //***
  1310. if (!moved)
  1311. break;
  1312. gap_ep = curr_ep;
  1313. if (gap_period > curr_ep->actual_period)
  1314. gap_period = curr_ep->actual_period;
  1315. last_ep = curr_ep;
  1316. curr_ep = curr_ep->next_ep;
  1317. } // end interrupt endpoints in frame
  1318. frame_bias--;
  1319. } // end for all frames
  1320. ep->calc_bus_time = 0;
  1321. return 1;
  1322. }
  1323. /*******
  1324. Allocate_time_for_endpoint
  1325. ********/
  1326. int Allocate_time_for_endpoint(
  1327. PEndpoint ep, // endpoint that needs to be configured (bus time allocated)
  1328. PEndpoint changed_ep_list[], // pointer to array to set (on return) with list of
  1329. // changed endpoints
  1330. int *max_changed_eps // input: maximum size of (returned) list
  1331. // on return: number of changed endpoints
  1332. )
  1333. {
  1334. int shift_time, frame_bias, moved, retv, move_status;
  1335. unsigned t, overhead, changed_eps, i, min_used, latest_start, frame_cnt;
  1336. PEndpoint curr_ep, last_ep, p;
  1337. changed_eps = 0;
  1338. retv = 1;
  1339. // OVERVIEW of algorithm steps:
  1340. // 1. Determine starting frame # for period
  1341. // 2. Calculate classic time required
  1342. // 3. For all period frames, find the latest starting time so we can check the classic allocation later
  1343. // 4. Process each frame data structure for endpoint period in budget window
  1344. // 5. Now check allocation for each frame using shift adjustment based on latest start time
  1345. // 6a. Now move isoch endpoints, insert new isoch and then move interrupt endpoints
  1346. // 6b. Now insert new interrupt and move rest of interrupt endpoints
  1347. // 7. Allocate HS bus time
  1348. // 8. Allocate classic bus time
  1349. //***
  1350. //*** 1. Determine starting frame # for period
  1351. //***
  1352. // Also remember the maximum frame time allocation since it will be used to pass the allocation check.
  1353. // Find starting frame number for reasonable balance of all classic frames
  1354. ep->start_frame = 0;
  1355. ep->start_microframe = 0;
  1356. ep->num_completes = 0;
  1357. ep->num_starts = 0;
  1358. // check that this endpoint isn't already allocated
  1359. if (ep->calc_bus_time)
  1360. {
  1361. error("endpoint already allocated");
  1362. return 0;
  1363. }
  1364. // handle nonsplit HS allocation
  1365. // if ((ep->speed == HSSPEED) && (ep->mytt->myHC->speed == HSSPEED)) {
  1366. if (ep->speed == HSSPEED) {
  1367. min_used = ep->mytt->myHC->HS_microframe_info[0][0].time_used;
  1368. if (ep->period > MAXFRAMES*MICROFRAMES_PER_FRAME)
  1369. ep->actual_period = MAXFRAMES*MICROFRAMES_PER_FRAME;
  1370. else
  1371. ep->actual_period = ep->period;
  1372. // Look at all candidate frames for this period to find the one with min
  1373. // allocated bus time.
  1374. //
  1375. for (i=1; i < ep->actual_period; i++)
  1376. {
  1377. if (ep->mytt->myHC->HS_microframe_info[i/MICROFRAMES_PER_FRAME][i % MICROFRAMES_PER_FRAME].time_used < min_used)
  1378. {
  1379. min_used = ep->mytt->myHC->HS_microframe_info[i/MICROFRAMES_PER_FRAME][i % MICROFRAMES_PER_FRAME].time_used;
  1380. ep->start_frame = i/MICROFRAMES_PER_FRAME;
  1381. ep->start_microframe = i % MICROFRAMES_PER_FRAME;
  1382. }
  1383. }
  1384. // compute and allocate HS bandwidth
  1385. ep->calc_bus_time = Compute_nonsplit_overhead(ep) + Add_bitstuff(ep->max_packet);
  1386. for (i = (ep->start_frame*MICROFRAMES_PER_FRAME) + ep->start_microframe;
  1387. i < MAXFRAMES*MICROFRAMES_PER_FRAME;
  1388. i += ep->actual_period)
  1389. {
  1390. if (! Allocate_check(
  1391. &(ep->mytt->myHC->HS_microframe_info[i/MICROFRAMES_PER_FRAME][
  1392. i % MICROFRAMES_PER_FRAME].time_used),
  1393. ep->calc_bus_time,
  1394. HS_MAX_PERIODIC_ALLOCATION))
  1395. retv = 0;
  1396. }
  1397. if (! retv) // if allocation failed, deallocate
  1398. {
  1399. for (i = (ep->start_frame*MICROFRAMES_PER_FRAME) + ep->start_microframe;
  1400. i < MAXFRAMES*MICROFRAMES_PER_FRAME;
  1401. i += ep->actual_period)
  1402. {
  1403. ep->mytt->myHC->HS_microframe_info[i/MICROFRAMES_PER_FRAME][
  1404. i % MICROFRAMES_PER_FRAME].time_used -= ep->calc_bus_time;
  1405. }
  1406. }
  1407. return retv;
  1408. } else {
  1409. // split or nonsplit FS/LS speed allocation
  1410. // classic allocation
  1411. if ((ep->speed != HSSPEED) && (ep->mytt->myHC->speed != HSSPEED)) {
  1412. min_used = ep->mytt->myHC->HS_microframe_info[0][0].time_used;
  1413. if (ep->period > MAXFRAMES)
  1414. ep->actual_period = MAXFRAMES;
  1415. else
  1416. ep->actual_period = ep->period;
  1417. // Look at all candidate frames for this period to find the one with min
  1418. // allocated bus time.
  1419. //
  1420. for (i=1; i < ep->actual_period ; i++)
  1421. {
  1422. if (ep->mytt->myHC->HS_microframe_info[i][0].time_used < min_used)
  1423. {
  1424. min_used = ep->mytt->myHC->HS_microframe_info[i][0].time_used;
  1425. ep->start_frame = i;
  1426. }
  1427. }
  1428. // compute and allocate FS/LS bandwidth
  1429. ep->calc_bus_time = Compute_nonsplit_overhead(ep) +
  1430. Add_bitstuff((ep->speed?1:8) * ep->max_packet);
  1431. for (i = ep->start_frame; i < MAXFRAMES; i += ep->actual_period) {
  1432. t = ep->mytt->myHC->HS_microframe_info[i][0].time_used; // can't take address of bitfield (below)
  1433. if (! Allocate_check( &t, ep->calc_bus_time, FS_MAX_PERIODIC_ALLOCATION))
  1434. retv = 0;
  1435. ep->mytt->myHC->HS_microframe_info[i][0].time_used = t;
  1436. }
  1437. if (! retv) {
  1438. for (i = ep->start_frame; i < MAXFRAMES; i += ep->actual_period)
  1439. ep->mytt->myHC->HS_microframe_info[i][0].time_used -= ep->calc_bus_time;
  1440. }
  1441. return retv;
  1442. } else {
  1443. // split allocation
  1444. min_used = ep->mytt->frame_budget[0].time_used;
  1445. if (ep->period > MAXFRAMES)
  1446. ep->actual_period = MAXFRAMES;
  1447. else
  1448. ep->actual_period = ep->period;
  1449. // Look at all candidate frames for this period to find the one with min
  1450. // allocated bus time.
  1451. //
  1452. for (i=1; i < ep->actual_period ; i++) {
  1453. if (ep->mytt->frame_budget[i].time_used < min_used) {
  1454. min_used = ep->mytt->frame_budget[i].time_used;
  1455. ep->start_frame = i;
  1456. }
  1457. }
  1458. }
  1459. }
  1460. // above handles all speeds, the rest of this code is for split transaction processing
  1461. // There could be multiple frames with a minimum already allocated bus time.
  1462. // If there is a frame where this ep would be added at the end of the frame,
  1463. // we can avoid doing an insert (which requires other endpoints to be adjusted).
  1464. // Currently we don't look for that optimization. It would involve checking the
  1465. // frame endpoint list to see if the new endpoint would be the last and if not
  1466. // going back to see if there is another candidate frame and trying again (until
  1467. // there are no more candidate frames). We could also keep track of the candidate
  1468. // frame that had the least affect on other endpoints (for the case where there
  1469. // is a frame that makes the new endpoint closest to last).
  1470. // <<attempt later maybe>>??
  1471. //***
  1472. //*** 2. Calculate classic time required
  1473. //***
  1474. // Calculate classic overhead
  1475. if (ep->ep_type == isoch)
  1476. {
  1477. if (ep->speed == FSSPEED)
  1478. overhead = FS_ISOCH_OVERHEAD + ep->mytt->think_time;
  1479. else
  1480. {
  1481. error("low speed isoch illegal"); // illegal, LS isoch
  1482. return 0;
  1483. }
  1484. } else
  1485. { // interrupt
  1486. if (ep->speed == FSSPEED)
  1487. overhead = FS_INT_OVERHEAD + ep->mytt->think_time;
  1488. else
  1489. overhead = LS_INT_OVERHEAD + ep->mytt->think_time;
  1490. }
  1491. // Classic bus time, NOT including bitstuffing overhead (in FS byte times) since we do best case budget
  1492. ep->calc_bus_time = ep->max_packet * (ep->speed?1:8) + overhead;
  1493. //***
  1494. //*** 3. For all period frames, find the latest starting time so we can check the classic allocation later.
  1495. //***
  1496. // Checking the classic allocation takes two passes through the frame/endpoint lists.
  1497. // Or else we would have to remember the last/curr ep pointers for each period frame and loop back
  1498. // through that list the second time. (<<Future optimization?>>)
  1499. // To find the start time to use for the new endpoint: for each frame, find the insertion point and use
  1500. // the "previous" endpoint in the FRAME. Use the previous endpoint end time as a possible start time
  1501. // for this new endpoint. Use the end time instead of the insertion point start time since there can
  1502. // before endpoints and we want to allocate as contiguously as possible. Using this time, find the latest
  1503. // start be unallocated time time across all frames (this keeps the early part of the frame as allocated as
  1504. // possible to avoid having to worry about fragmentation of time (and even more complexity).
  1505. //
  1506. // Once the final start time is known, then for each frame, check the allocation required in each frame.
  1507. // The total frame allocation is actually the time of the ending of the last transaction in the frame.
  1508. // It is possible that a new allocation can fit in an unallocated "gap" between two other allocated
  1509. // endpoints of slower periods. The new allocation is therefore any shift required of later endpoints in
  1510. // the frame.
  1511. //
  1512. // The shift is computed as:
  1513. // shift = (final_start_time + new.calc_bus_time) - curr.start_time
  1514. // If shift is positive, later endpoints must be moved by the shift amount, otherwise later endpoints
  1515. // (and the frame allocation) aren't affected.
  1516. latest_start = FS_SOF + HUB_FS_ADJ; // initial start time must be after the SOF transaction
  1517. // find latest start
  1518. for (i=0; ep->start_frame + i < MAXFRAMES; i += ep->actual_period)
  1519. {
  1520. if (ep->ep_type == isoch)
  1521. {
  1522. last_ep = ep->mytt->frame_budget[ep->start_frame + i].isoch_ehead;
  1523. curr_ep = last_ep->next_ep; // get past SOF endpoint
  1524. } else
  1525. {
  1526. last_ep = ep->mytt->frame_budget[ep->start_frame + i].int_ehead;
  1527. curr_ep = last_ep->next_ep; // get past dummy SOF endpoint
  1528. }
  1529. // if this frame has a large transaction endpoint, make sure we don't allocate another one
  1530. if (ep->mytt->frame_budget[ep->start_frame + i].allocated_large)
  1531. {
  1532. if (ep->calc_bus_time >= LARGEXACT)
  1533. {
  1534. error("too many large xacts"); // only one large transaction allowed in a frame.
  1535. return 0;
  1536. }
  1537. }
  1538. while (curr_ep) // walk endpoint list for this frame to find where to insert new endpoint
  1539. {
  1540. // Note: the actual insertion will be done later
  1541. //
  1542. if (OK_to_insert(curr_ep, ep))
  1543. {
  1544. break;
  1545. }
  1546. last_ep = curr_ep;
  1547. curr_ep = curr_ep->next_ep;
  1548. }
  1549. t = Compute_ep_start_time(curr_ep, ep, last_ep, ep->start_frame + i);
  1550. // update latest start time as required
  1551. if (t > latest_start)
  1552. latest_start = t;
  1553. } // end of for loop looking for latest start time
  1554. // Set the start time for the new endpoint
  1555. ep->start_time = latest_start;
  1556. if ((ep->start_time + ep->calc_bus_time) > FS_MAX_PERIODIC_ALLOCATION)
  1557. {
  1558. // error("start time %d past end of frame", ep->start_time + ep->calc_bus_time);
  1559. ep->calc_bus_time = 0;
  1560. return 0;
  1561. }
  1562. //***
  1563. //*** 4. Process each frame data structure for endpoint period in budget window
  1564. //***
  1565. changed_eps = 0; // Track number of endpoints that will need to be updated.
  1566. while (changed_ep_list[changed_eps]) // reset indicators of endpoints changed this pass.
  1567. {
  1568. changed_ep_list[changed_eps]->moved_this_req = 0;
  1569. changed_eps++;
  1570. }
  1571. // this allows appending changed endpoints onto the current change list.
  1572. // We have to check the allocation of this new endpoint in each frame. We also have to move any
  1573. // later endpoints in the frame to their new start times (and adjust their SS/CS allocations as
  1574. // appropriate).
  1575. //
  1576. // Doing this is tricky since:
  1577. // A. The actual isoch portion of the frame is organized in reverse order in the budget list
  1578. // B. If a large isoch transaction exists in this frame, it is first in the frame
  1579. //
  1580. // For a new isoch ep:
  1581. // We have to find the shift for this endpoint.
  1582. // We have to move isoch endpoints up to (but not including) the isoch insertion point endpoint
  1583. // We also have to move all interrupt endpoints (to the end of the list and frame) after we
  1584. // finish the isoch endpoints.
  1585. //
  1586. // For a new interrupt ep:
  1587. // skip to the insertion point without doing anything
  1588. // then move the start times of the rest of the interrupt endpoints until the end of the list (and frame)
  1589. //
  1590. // Allocate time in each frame of the endpoint period in the budgeting window.
  1591. //
  1592. // Since the interrupt frame budget is ordered with decreasing period (with holes in the budget),
  1593. // we must process all frames in the budget window to correctly move any smaller period interrupt
  1594. // endpoints that are affected by this new enpoint, even though the new endpoint is only added in
  1595. // its period frames
  1596. frame_bias = ep->start_frame;
  1597. frame_bias = - frame_bias;
  1598. for (frame_cnt=0; frame_cnt < MAXFRAMES; frame_cnt++)
  1599. {
  1600. //***
  1601. //*** 5. Now check allocation for each frame using shift adjustment based on latest start time
  1602. //***
  1603. if (ep->ep_type == isoch)
  1604. {
  1605. last_ep = ep->mytt->frame_budget[ep->start_frame + frame_bias].isoch_ehead;
  1606. curr_ep = last_ep->next_ep; // get past dummy SOF endpoint
  1607. p = last_ep; // save the starting point so we can start over after finding the shift time
  1608. // walk endpoint list for this frame to find where to insert new endpoint
  1609. while (curr_ep)
  1610. {
  1611. // Note: the actual insertion will be done later, this just does the allocation check
  1612. //
  1613. if (OK_to_insert(curr_ep, ep))
  1614. break;
  1615. last_ep = curr_ep;
  1616. curr_ep = curr_ep->next_ep;
  1617. }
  1618. // shift = (final_start_time + new.calc_bus_time) - curr.start_time
  1619. // for isoch the last_ep is the endpoint before which the new one is inserted, i.e. it is "curr"
  1620. if (last_ep != ep->mytt->frame_budget[ep->start_frame + frame_bias].isoch_ehead)
  1621. // This is somewhere in the "middle" of the list
  1622. shift_time = (latest_start + ep->calc_bus_time) - last_ep->start_time;
  1623. else
  1624. {
  1625. if (curr_ep)
  1626. {
  1627. // There is only one endpoint on the list, so must use 1st (non dummy SOF) int endpoint as
  1628. // next ep in frame (if there is one)
  1629. if (ep->mytt->frame_budget[ep->start_frame + frame_bias].int_ehead->next_ep)
  1630. shift_time = (latest_start + ep->calc_bus_time) -
  1631. ep->mytt->frame_budget[ep->start_frame + frame_bias].int_ehead->next_ep->start_time;
  1632. else // no int endpoints
  1633. shift_time = 0;
  1634. } else
  1635. // There are no endpoints on the isoch list
  1636. shift_time = ep->calc_bus_time;
  1637. }
  1638. //
  1639. // Check classic allocation
  1640. //
  1641. // check that if new ep is at end of frame, it will fit in the frame
  1642. //if ((ep->start_time + ep->calc_bus_time) > FS_MAX_PERIODIC_ALLOCATION)
  1643. //{
  1644. // error("new xact too late in frame");
  1645. // Deallocate_endpoint_budget(ep, changed_ep_list, max_changed_eps, frame_cnt);
  1646. // return 0;
  1647. //}
  1648. // check classic allocation with adjusted start time before proceeding
  1649. if (shift_time > 0)
  1650. {
  1651. // worst frame test to stop remaining processing as early as possible.
  1652. t = ep->mytt->frame_budget[ep->start_frame + frame_bias].time_used;
  1653. if ( ! Allocate_check(&t, shift_time, FS_MAX_PERIODIC_ALLOCATION))
  1654. {
  1655. Deallocate_endpoint_budget(ep, changed_ep_list, max_changed_eps, frame_cnt);
  1656. return 0;
  1657. }
  1658. }
  1659. //***
  1660. //*** 6a. Now move isoch endpoints, insert new isoch and then move interrupt endpoints
  1661. //***
  1662. last_ep = p;
  1663. curr_ep = last_ep->next_ep;
  1664. // Walk endpoint list for this frame to find where to insert new isoch endpoint.
  1665. // This time we move later isoch endpoints in frame (early endpoints on budget list)
  1666. while (curr_ep)
  1667. {
  1668. if (! OK_to_insert(curr_ep, ep))
  1669. {
  1670. if (shift_time > 0) {
  1671. moved = Move_ep(
  1672. curr_ep,
  1673. shift_time,
  1674. changed_ep_list,
  1675. &changed_eps,
  1676. *max_changed_eps,
  1677. &move_status);
  1678. if (! move_status)
  1679. retv = 0;
  1680. if (! moved) // already have visited the endpoints from here on in this frame
  1681. break;
  1682. }
  1683. } else // insert new endpoint here
  1684. break;
  1685. last_ep = curr_ep;
  1686. curr_ep = curr_ep->next_ep;
  1687. }
  1688. // Don't insert endpoint if its already been inserted and processed due to a previous endpoint
  1689. //
  1690. if (curr_ep != ep) {
  1691. if ((frame_bias % ep->actual_period) == 0)
  1692. // Only allocate new endpoint in its period frames
  1693. {
  1694. // insert new endpoint
  1695. if (ep->calc_bus_time >= LARGEXACT)
  1696. {
  1697. // save the large ep pointer
  1698. ep->mytt->frame_budget[ep->start_frame + frame_bias].allocated_large = ep;
  1699. // we don't link the large onto any other endpoints
  1700. } else
  1701. { // not large, so link the endpoint onto the list
  1702. if (frame_bias == 0)
  1703. ep->next_ep = curr_ep;
  1704. last_ep->next_ep = ep;
  1705. }
  1706. }
  1707. // now move all interrupt endpoints
  1708. // find end of last isoch ep and check if it is after start of first interrupt, if so, interrupt
  1709. // eps must be shifted
  1710. p = ep->mytt->frame_budget[ep->start_frame + frame_bias].isoch_ehead; // sof
  1711. if (p->next_ep)
  1712. p = p->next_ep; // last actual isoch , could be null when no isoch allocated in this frame
  1713. else
  1714. if (ep->mytt->frame_budget[ep->start_frame + frame_bias].allocated_large)
  1715. p = ep->mytt->frame_budget[ep->start_frame + frame_bias].allocated_large;
  1716. last_ep = ep->mytt->frame_budget[ep->start_frame + frame_bias].int_ehead;
  1717. curr_ep = last_ep->next_ep; // get past dummy SOF endpoint
  1718. if (curr_ep) { // only move interrupt endpoints that are there
  1719. if ((p->start_time + p->calc_bus_time) > curr_ep->start_time) {
  1720. // Compute the shift time for all following interrupt endpoints ONCE. Then
  1721. // apply it to all endpoints. This ensures that any gaps between endpoints are
  1722. // preserved without compression.
  1723. shift_time = p->start_time + p->calc_bus_time - curr_ep->start_time;
  1724. while (curr_ep)
  1725. {
  1726. // Note: this doesn't do any insertion, just adjusts start times of interrupt eps
  1727. // we haven't seen yet
  1728. // << this can exit once it finds an ep we have already seen>>
  1729. moved = Move_ep(
  1730. curr_ep,
  1731. shift_time,
  1732. changed_ep_list,
  1733. &changed_eps,
  1734. *max_changed_eps,
  1735. &move_status);
  1736. if (! move_status)
  1737. retv = 0;
  1738. if (! moved)
  1739. break;
  1740. last_ep = curr_ep;
  1741. curr_ep = curr_ep->next_ep;
  1742. }
  1743. }
  1744. }
  1745. }
  1746. } else // interrupt
  1747. {
  1748. last_ep = ep->mytt->frame_budget[ep->start_frame + frame_bias].int_ehead;
  1749. curr_ep = last_ep->next_ep; // get past dummy SOF endpoint
  1750. // walk endpoint list for this frame to find where to insert new endpoint
  1751. while (curr_ep)
  1752. {
  1753. // Note: the actual insertion will be done later, this just does the allocation check
  1754. //
  1755. if (OK_to_insert(curr_ep, ep))
  1756. break;
  1757. last_ep = curr_ep;
  1758. curr_ep = curr_ep->next_ep;
  1759. }
  1760. // shift = (final_start_time + new.calc_bus_time) - curr.start_time
  1761. if (curr_ep)
  1762. shift_time = (latest_start + ep->calc_bus_time) - curr_ep->start_time;
  1763. else
  1764. shift_time = ep->calc_bus_time;
  1765. // only change endpoints in frame if the new interrupt endpoint is in this frame
  1766. if ((frame_bias % ep->actual_period) == 0)
  1767. {
  1768. shift_time = 0;
  1769. }
  1770. //
  1771. // Check classic allocation
  1772. //
  1773. // check classic allocation with adjusted start time before proceeding
  1774. if (shift_time > 0)
  1775. {
  1776. // worst frame test to stop remaining processing as early as possible.
  1777. t = ep->mytt->frame_budget[ep->start_frame + frame_bias].time_used;
  1778. if ( ! Allocate_check(&t, shift_time, FS_MAX_PERIODIC_ALLOCATION))
  1779. retv = 0;
  1780. }
  1781. //***
  1782. //*** 6b. Now insert new interrupt endpoint and move rest of interrupt endpoints
  1783. //***
  1784. // insert new endpoint
  1785. if (curr_ep != ep) {
  1786. if ((frame_bias % ep->actual_period) == 0) {
  1787. // Only allocate new endpoint in its period frames
  1788. if (frame_bias == 0)
  1789. ep->next_ep = curr_ep;
  1790. last_ep->next_ep = ep;
  1791. last_ep = ep;
  1792. }
  1793. if (shift_time > 0) {
  1794. while (curr_ep)
  1795. {
  1796. // Move the rest of the interrupt endpoints
  1797. //
  1798. moved = Move_ep(
  1799. curr_ep,
  1800. shift_time,
  1801. changed_ep_list,
  1802. &changed_eps,
  1803. *max_changed_eps,
  1804. &move_status);
  1805. if (! move_status)
  1806. retv = 0;
  1807. if (! moved)
  1808. break;
  1809. last_ep = curr_ep;
  1810. curr_ep = curr_ep->next_ep;
  1811. }
  1812. }
  1813. }
  1814. } // end of interrupt insertion handling
  1815. //***
  1816. //*** 7. Allocate HS bus time for endpoint
  1817. //***
  1818. if (frame_bias % ep->actual_period == 0) // Only allocate new endpoint in its period frames
  1819. {
  1820. if (! Allocate_HS(ep, frame_bias))
  1821. retv = 0;
  1822. //***
  1823. //*** 8. Allocate classic bus time
  1824. //***
  1825. ep->mytt->frame_budget[ep->start_frame + frame_bias].time_used += ep->calc_bus_time;
  1826. }
  1827. if (!retv)
  1828. {
  1829. // some error in this frame, so do partial deallocation and exit
  1830. Deallocate_endpoint_budget(ep, changed_ep_list, max_changed_eps, frame_cnt + 1);
  1831. return 0;
  1832. }
  1833. frame_bias++;
  1834. } // end of "for each frame in budget window"
  1835. return retv;
  1836. }
  1837. /*******
  1838. Deallocate_time_for_endpoint
  1839. ********/
  1840. void
  1841. Deallocate_time_for_endpoint(
  1842. PEndpoint ep, // endpoint that needs to be removed (bus time deallocated)
  1843. PEndpoint changed_ep_list[], // pointer to array to set (on return) with list of
  1844. // changed endpoints
  1845. int *max_changed_eps // input: maximum size of (returned) list
  1846. // on return: number of changed endpoints
  1847. )
  1848. {
  1849. // Deallocate all frames of information
  1850. Deallocate_endpoint_budget(ep, changed_ep_list,max_changed_eps, MAXFRAMES);
  1851. }
  1852. /*******
  1853. Set_endpoint()
  1854. ********/
  1855. Set_endpoint(
  1856. PEndpoint ep,
  1857. eptype t,
  1858. unsigned d,
  1859. unsigned s,
  1860. unsigned p,
  1861. unsigned m,
  1862. TT *thistt
  1863. )
  1864. {
  1865. ep->ep_type = t;
  1866. ep->direction = d;
  1867. ep->speed = s;
  1868. ep->period = p;
  1869. ep->max_packet = m;
  1870. ep->mytt = thistt;
  1871. ep->calc_bus_time = 0;
  1872. ep->start_frame = 0;
  1873. ep->start_microframe = 0;
  1874. ep->start_time = 0;
  1875. ep->num_starts = 0;
  1876. ep->num_completes = 0;
  1877. ep->actual_period = 0;
  1878. ep->next_ep = 0;
  1879. ep->saved_period = 0;
  1880. ep->promoted_this_time = 0;
  1881. ep->id = 0; // not needed for real budgeter
  1882. }
  1883. void
  1884. init_hc(PHC myHC)
  1885. {
  1886. int i,j;
  1887. PEndpoint ep;
  1888. // allocate at TT to test with
  1889. //myHC.tthead = (PTT) malloc(sizeof(TT));
  1890. myHC->thinktime = HS_HC_THINK_TIME;
  1891. myHC->allocation_limit = HS_MAX_PERIODIC_ALLOCATION;
  1892. myHC->speed = HSSPEED;
  1893. for (i=0; i<MAXFRAMES; i++)
  1894. {
  1895. for (j=0; j < MICROFRAMES_PER_FRAME; j++)
  1896. {
  1897. myHC->HS_microframe_info[i][j].time_used = 0;
  1898. }
  1899. }
  1900. }
  1901. void
  1902. init_tt(PHC myHC, PTT myTT)
  1903. {
  1904. int i,j;
  1905. PEndpoint ep;
  1906. myTT->think_time = 1;
  1907. myTT->myHC = myHC;
  1908. myTT->allocation_limit = FS_MAX_PERIODIC_ALLOCATION;
  1909. for (i=0; i<MAXFRAMES; i++)
  1910. {
  1911. myTT->frame_budget[i].time_used = FS_SOF + HUB_FS_ADJ;
  1912. myTT->frame_budget[i].allocated_large = 0;
  1913. for (j=0; j < MICROFRAMES_PER_FRAME; j++)
  1914. {
  1915. myTT->HS_split_data_time[i][j] = 0;
  1916. myTT->num_starts[i][j] = 0;
  1917. }
  1918. ep = &myTT->isoch_head[i];
  1919. myTT->frame_budget[i].isoch_ehead = ep;
  1920. // SOF at the beginning of each frame
  1921. Set_endpoint(ep, isoch, OUTDIR, FSSPEED, MAXFRAMES, 0, myTT);
  1922. ep->calc_bus_time = FS_SOF + HUB_FS_ADJ;
  1923. ep->actual_period = MAXFRAMES;
  1924. ep->start_microframe = -1;
  1925. ep->start_frame = i;
  1926. ep = &myTT->int_head[i];
  1927. myTT->frame_budget[i].int_ehead = ep;
  1928. // dummy SOF at the beginning of each int frame budget list
  1929. Set_endpoint(ep, interrupt, OUTDIR, FSSPEED, MAXFRAMES, 0, myTT);
  1930. ep->calc_bus_time = FS_SOF + HUB_FS_ADJ;
  1931. ep->actual_period = MAXFRAMES;
  1932. ep->start_microframe = -1;
  1933. ep->start_frame = i;
  1934. }
  1935. }