usbehci: align page td buffer for >16K transfers, fix isohsinit()
from ehci spec: The buffer pointer list in the qTD is long enough to support a maximum transfer size of 20K bytes. This case occurs when all five buffer pointers are used and the first offset is zero. A qTD handles a 16Kbyte buffer with any starting buffer alignment.
This commit is contained in:
parent
1e31b342cd
commit
800670da4e
1 changed files with 20 additions and 14 deletions
|
@ -2150,14 +2150,17 @@ epgettd(Qio *io, int flags, void *a, int count, int maxpkt)
|
||||||
if(count <= Align - sizeof(Td)){
|
if(count <= Align - sizeof(Td)){
|
||||||
td->data = td->sbuff;
|
td->data = td->sbuff;
|
||||||
td->buff = nil;
|
td->buff = nil;
|
||||||
}else
|
} else if(count <= 0x4000){
|
||||||
td->data = td->buff = smalloc(Tdmaxpkt);
|
td->buff = td->data = smalloc(count);
|
||||||
|
} else {
|
||||||
|
td->buff = smalloc(count + 0x1000);
|
||||||
|
td->data = (uchar*)ROUND((uintptr)td->buff, 0x1000);
|
||||||
|
}
|
||||||
|
|
||||||
pa = PADDR(td->data);
|
pa = PADDR(td->data);
|
||||||
for(i = 0; i < nelem(td->buffer); i++){
|
for(i = 0; i < nelem(td->buffer); i++){
|
||||||
td->buffer[i] = pa;
|
td->buffer[i] = pa;
|
||||||
if(i > 0)
|
pa &= ~0xFFF;
|
||||||
td->buffer[i] &= ~0xFFF;
|
|
||||||
pa += 0x1000;
|
pa += 0x1000;
|
||||||
}
|
}
|
||||||
td->ndata = count;
|
td->ndata = count;
|
||||||
|
@ -2435,10 +2438,14 @@ epio(Ep *ep, Qio *io, void *a, long count, int mustlock)
|
||||||
io->toggle = td->csw & Tddata1;
|
io->toggle = td->csw & Tddata1;
|
||||||
coherence();
|
coherence();
|
||||||
}
|
}
|
||||||
tot += td->ndata;
|
if((n = td->ndata) > 0 && tot < count){
|
||||||
if(c != nil && (td->csw & Tdtok) == Tdtokin && td->ndata > 0){
|
if((tot + n) > count)
|
||||||
memmove(c, td->data, td->ndata);
|
n = count - tot;
|
||||||
c += td->ndata;
|
if(c != nil && (td->csw & Tdtok) == Tdtokin){
|
||||||
|
memmove(c, td->data, n);
|
||||||
|
c += n;
|
||||||
|
}
|
||||||
|
tot += n;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ntd = td->next;
|
ntd = td->next;
|
||||||
|
@ -2455,8 +2462,6 @@ epio(Ep *ep, Qio *io, void *a, long count, int mustlock)
|
||||||
return 0; /* that's our convention */
|
return 0; /* that's our convention */
|
||||||
if(err != nil)
|
if(err != nil)
|
||||||
error(err);
|
error(err);
|
||||||
if(tot < 0)
|
|
||||||
error(Eio);
|
|
||||||
return tot;
|
return tot;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2725,10 +2730,11 @@ isohsinit(Ep *ep, Isoio *iso)
|
||||||
td = itdalloc();
|
td = itdalloc();
|
||||||
td->data = iso->data + i * 8 * iso->maxsize;
|
td->data = iso->data + i * 8 * iso->maxsize;
|
||||||
pa = PADDR(td->data) & ~0xFFF;
|
pa = PADDR(td->data) & ~0xFFF;
|
||||||
for(p = 0; p < 8; p++)
|
for(p = 0; p < nelem(td->buffer); p++){
|
||||||
td->buffer[i] = pa + p * 0x1000;
|
td->buffer[p] = pa;
|
||||||
td->buffer[0] = PADDR(iso->data) & ~0xFFF |
|
pa += 0x1000;
|
||||||
ep->nb << Itdepshift | ep->dev->nb << Itddevshift;
|
}
|
||||||
|
td->buffer[0] |= ep->nb << Itdepshift | ep->dev->nb << Itddevshift;
|
||||||
if(ep->mode == OREAD)
|
if(ep->mode == OREAD)
|
||||||
td->buffer[1] |= Itdin;
|
td->buffer[1] |= Itdin;
|
||||||
else
|
else
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue