Revision e8ee3c72
b/hw/usb-uhci.c | ||
---|---|---|
265 | 265 |
static UHCIAsync *uhci_async_find_td(UHCIState *s, uint32_t addr, uint32_t token) |
266 | 266 |
{ |
267 | 267 |
UHCIAsync *async = s->async_pending; |
268 |
UHCIAsync *match = NULL; |
|
269 |
int count = 0; |
|
270 |
|
|
271 |
/* |
|
272 |
* We're looking for the best match here. ie both td addr and token. |
|
273 |
* Otherwise we return last good match. ie just token. |
|
274 |
* It's ok to match just token because it identifies the transaction |
|
275 |
* rather well, token includes: device addr, endpoint, size, etc. |
|
276 |
* |
|
277 |
* Also since we queue async transactions in reverse order by returning |
|
278 |
* last good match we restores the order. |
|
279 |
* |
|
280 |
* It's expected that we wont have a ton of outstanding transactions. |
|
281 |
* If we ever do we'd want to optimize this algorithm. |
|
282 |
*/ |
|
268 | 283 |
|
269 | 284 |
while (async) { |
270 |
if (async->td == addr) { |
|
271 |
if (async->token == token) |
|
272 |
return async; |
|
273 |
|
|
274 |
/* |
|
275 |
* TD was reused for a different transfer. |
|
276 |
* Invalidate the original one asap. |
|
277 |
*/ |
|
278 |
if (async->valid > 0) { |
|
279 |
async->valid = 0; |
|
280 |
dprintf("husb: bad reuse. td 0x%x\n", async->td); |
|
285 |
if (async->token == token) { |
|
286 |
/* Good match */ |
|
287 |
match = async; |
|
288 |
|
|
289 |
if (async->td == addr) { |
|
290 |
/* Best match */ |
|
291 |
break; |
|
281 | 292 |
} |
282 | 293 |
} |
283 | 294 |
|
284 | 295 |
async = async->next; |
296 |
count++; |
|
285 | 297 |
} |
286 |
return NULL; |
|
298 |
|
|
299 |
if (count > 64) |
|
300 |
fprintf(stderr, "uhci: warning lots of async transactions\n"); |
|
301 |
|
|
302 |
return match; |
|
287 | 303 |
} |
288 | 304 |
|
289 | 305 |
static void uhci_attach(USBPort *port1, USBDevice *dev); |
Also available in: Unified diff