diff options
| author | cinap_lenrek <cinap_lenrek@gmx.de> | 2013-04-12 22:14:32 +0200 |
|---|---|---|
| committer | cinap_lenrek <cinap_lenrek@gmx.de> | 2013-04-12 22:14:32 +0200 |
| commit | 800670da4e504b0e2d25dcaddb6164bcc3d7fbe5 (patch) | |
| tree | 2afa67d1dd795344ef0ccc93d6b948192db87ca0 | |
| parent | 1e31b342cd913bb702bd12debd8e0d44bf1d221c (diff) | |
| download | plan9front-800670da4e504b0e2d25dcaddb6164bcc3d7fbe5.tar.xz | |
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.
| -rw-r--r-- | sys/src/9/port/usbehci.c | 34 |
1 files changed, 20 insertions, 14 deletions
diff --git a/sys/src/9/port/usbehci.c b/sys/src/9/port/usbehci.c index 6d1b6d2bd..207b93d44 100644 --- a/sys/src/9/port/usbehci.c +++ b/sys/src/9/port/usbehci.c @@ -2150,14 +2150,17 @@ epgettd(Qio *io, int flags, void *a, int count, int maxpkt) if(count <= Align - sizeof(Td)){ td->data = td->sbuff; td->buff = nil; - }else - td->data = td->buff = smalloc(Tdmaxpkt); + } else if(count <= 0x4000){ + td->buff = td->data = smalloc(count); + } else { + td->buff = smalloc(count + 0x1000); + td->data = (uchar*)ROUND((uintptr)td->buff, 0x1000); + } pa = PADDR(td->data); for(i = 0; i < nelem(td->buffer); i++){ td->buffer[i] = pa; - if(i > 0) - td->buffer[i] &= ~0xFFF; + pa &= ~0xFFF; pa += 0x1000; } td->ndata = count; @@ -2435,10 +2438,14 @@ epio(Ep *ep, Qio *io, void *a, long count, int mustlock) io->toggle = td->csw & Tddata1; coherence(); } - tot += td->ndata; - if(c != nil && (td->csw & Tdtok) == Tdtokin && td->ndata > 0){ - memmove(c, td->data, td->ndata); - c += td->ndata; + if((n = td->ndata) > 0 && tot < count){ + if((tot + n) > count) + n = count - tot; + if(c != nil && (td->csw & Tdtok) == Tdtokin){ + memmove(c, td->data, n); + c += n; + } + tot += n; } } ntd = td->next; @@ -2455,8 +2462,6 @@ epio(Ep *ep, Qio *io, void *a, long count, int mustlock) return 0; /* that's our convention */ if(err != nil) error(err); - if(tot < 0) - error(Eio); return tot; } @@ -2725,10 +2730,11 @@ isohsinit(Ep *ep, Isoio *iso) td = itdalloc(); td->data = iso->data + i * 8 * iso->maxsize; pa = PADDR(td->data) & ~0xFFF; - for(p = 0; p < 8; p++) - td->buffer[i] = pa + p * 0x1000; - td->buffer[0] = PADDR(iso->data) & ~0xFFF | - ep->nb << Itdepshift | ep->dev->nb << Itddevshift; + for(p = 0; p < nelem(td->buffer); p++){ + td->buffer[p] = pa; + pa += 0x1000; + } + td->buffer[0] |= ep->nb << Itdepshift | ep->dev->nb << Itddevshift; if(ep->mode == OREAD) td->buffer[1] |= Itdin; else |
