usbehci: initial support for usb on zynq, remove uncached.h
the following hooks have been added to the ehci Ctlr structore to handle cache coherency (on arm): void* (*tdalloc)(ulong,int,ulong); void* (*dmaalloc)(ulong); void (*dmafree)(void*); void (*dmaflush)(int,void*,ulong); tdalloc() is used to allocate descriptors and the periodic frame schedule array. on arm, this needs to return uncached memory. tdalloc()ed memory is never freed. dmaalloc()/dmafree() is used for io buffers. this can return cached memory when when hardware maintains cache coherency (pc) or dmaflush() is provided to flush/invalidate the cache (zynq), otherwise needs to return uncached memory. dmaflush() is used to flush/invalidate the cache. the first argument tells us if we need to flush (non zero) or invalidate (zero). uncached.h is gone now. this change makes the handling explicit.
This commit is contained in:
parent
6b2d1f0186
commit
995379e388
20 changed files with 178 additions and 172 deletions
|
@ -110,7 +110,7 @@ uintptr mmukmap(uintptr, uintptr, usize);
|
|||
uintptr mmukunmap(uintptr, uintptr, usize);
|
||||
extern void* mmuuncache(void*, usize);
|
||||
extern void* ucalloc(usize);
|
||||
extern void* ucallocalign(usize size, int align, int span);
|
||||
extern void* ucallocalign(usize size, int align, usize span);
|
||||
extern Block* ucallocb(int);
|
||||
extern void ucfree(void*);
|
||||
extern void ucfreeb(Block*);
|
||||
|
|
|
@ -132,7 +132,7 @@ l.$O lexception.$O lproc.$O mmu.$O: arm.s arm.h mem.h
|
|||
main.$O: errstr.h init.h reboot.h
|
||||
mouse.$O: screen.h
|
||||
devusb.$O: ../port/usb.h
|
||||
usbehci.$O usbohci.$O usbuhci.$O: ../port/usb.h usbehci.h uncached.h
|
||||
usbehci.$O usbohci.$O usbuhci.$O: ../port/usb.h usbehci.h
|
||||
|
||||
init.h:D: ../port/initcode.c init9.s
|
||||
$CC ../port/initcode.c
|
||||
|
|
|
@ -261,7 +261,7 @@ mmurelease(Proc* proc)
|
|||
for(page = proc->mmul2cache; page != nil; page = next){
|
||||
next = page->next;
|
||||
if(--page->ref)
|
||||
panic("mmurelease: page->ref %d", page->ref);
|
||||
panic("mmurelease: page->ref %lud", page->ref);
|
||||
pagechainhead(page);
|
||||
}
|
||||
if(proc->mmul2cache && palloc.r.p)
|
||||
|
|
|
@ -127,7 +127,7 @@ ucalloc(usize size)
|
|||
}
|
||||
|
||||
void*
|
||||
ucallocalign(usize size, int align, int span)
|
||||
ucallocalign(usize size, int align, usize span)
|
||||
{
|
||||
assert(size < ucpool.minarena-128);
|
||||
|
||||
|
|
|
@ -1,36 +0,0 @@
|
|||
/*
|
||||
* running the l2 cache as write-back and using cached memory for
|
||||
* usb data structures yields spurious errors such as
|
||||
*
|
||||
* qhintr: td 0x60ee3d80 csw 0x8824a error 0x48 transaction error
|
||||
*
|
||||
* from usbehci. so, at least for now, we will use uncached memory until
|
||||
* we sort out the write-back problems.
|
||||
*/
|
||||
#define free ucfree
|
||||
#define malloc myucalloc
|
||||
#define mallocz ucallocz
|
||||
#define smalloc myucalloc
|
||||
#define xspanalloc ucallocalign
|
||||
|
||||
#define allocb ucallocb
|
||||
#define iallocb uciallocb
|
||||
#define freeb ucfreeb
|
||||
|
||||
static void *
|
||||
ucallocz(uint n, int)
|
||||
{
|
||||
char *p = ucalloc(n);
|
||||
|
||||
if (p)
|
||||
memset(p, 0, n);
|
||||
else
|
||||
panic("ucalloc: out of memory");
|
||||
return p;
|
||||
}
|
||||
|
||||
static void *
|
||||
myucalloc(uint n)
|
||||
{
|
||||
return ucallocz(n, 1);
|
||||
}
|
|
@ -172,6 +172,11 @@ struct Ctlr
|
|||
Ecapio* capio; /* Capability i/o regs */
|
||||
Eopio* opio; /* Operational i/o regs */
|
||||
|
||||
void* (*tdalloc)(ulong,int,ulong);
|
||||
void* (*dmaalloc)(ulong);
|
||||
void (*dmafree)(void*);
|
||||
void (*dmaflush)(int,void*,ulong len);
|
||||
|
||||
int nframes; /* 1024, 512, or 256 frames in the list */
|
||||
ulong* frames; /* periodic frame list (hw) */
|
||||
Qh* qhs; /* async Qh circular list for bulk/ctl */
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
#include "../port/error.h"
|
||||
#include "../port/usb.h"
|
||||
#include "usbehci.h"
|
||||
//#include "uncached.h"
|
||||
|
||||
#define WINTARG(ctl) (((ctl) >> 4) & 017)
|
||||
#define WINATTR(ctl) (((ctl) >> 8) & 0377)
|
||||
|
@ -331,6 +330,10 @@ reset(Hci *hp)
|
|||
capio->parms & 0x40 ? "explicit" : "automatic",
|
||||
capio->parms & 0x10 ? "" : "no ", hp->nports);
|
||||
|
||||
ctlr->tdalloc = ucallocalign;
|
||||
ctlr->dmaalloc = ucalloc;
|
||||
ctlr->dmafree = ucfree;
|
||||
|
||||
ehcireset(ctlr);
|
||||
ehcimeminit(ctlr);
|
||||
|
||||
|
|
|
@ -111,7 +111,7 @@ l.$O rebootcode.$O: cache.v7.s
|
|||
main.$O: errstr.h init.h reboot.h
|
||||
devdss.$O devmouse.$O mouse.$O screen.$O: screen.h
|
||||
devusb.$O: ../port/usb.h
|
||||
usbehci.$O usbohci.$O usbuhci.$O: ../port/usb.h usbehci.h uncached.h
|
||||
usbehci.$O usbohci.$O usbuhci.$O: ../port/usb.h usbehci.h
|
||||
|
||||
init.h:D: ../port/initcode.c init9.s
|
||||
$CC ../port/initcode.c
|
||||
|
|
|
@ -1,36 +0,0 @@
|
|||
/*
|
||||
* running the l2 cache as write-back and using cached memory for
|
||||
* usb data structures yields spurious errors such as
|
||||
*
|
||||
* qhintr: td 0x60ee3d80 csw 0x8824a error 0x48 transaction error
|
||||
*
|
||||
* from usbehci. so, at least for now, we will use uncached memory until
|
||||
* we sort out the write-back problems.
|
||||
*/
|
||||
#define free ucfree
|
||||
#define malloc myucalloc
|
||||
#define mallocz ucallocz
|
||||
#define smalloc myucalloc
|
||||
#define xspanalloc ucallocalign
|
||||
|
||||
#define allocb ucallocb
|
||||
#define iallocb uciallocb
|
||||
#define freeb ucfreeb
|
||||
|
||||
static void *
|
||||
ucallocz(uint n, int)
|
||||
{
|
||||
char *p = ucalloc(n);
|
||||
|
||||
if (p)
|
||||
memset(p, 0, n);
|
||||
else
|
||||
panic("ucalloc: out of memory");
|
||||
return p;
|
||||
}
|
||||
|
||||
static void *
|
||||
myucalloc(uint n)
|
||||
{
|
||||
return ucallocz(n, 1);
|
||||
}
|
|
@ -39,6 +39,11 @@ struct Ctlr
|
|||
Ecapio* capio; /* Capability i/o regs */
|
||||
Eopio* opio; /* Operational i/o regs */
|
||||
|
||||
void* (*tdalloc)(ulong,int,ulong);
|
||||
void* (*dmaalloc)(ulong);
|
||||
void (*dmafree)(void*);
|
||||
void (*dmaflush)(int,void*,ulong len);
|
||||
|
||||
int nframes; /* 1024, 512, or 256 frames in the list */
|
||||
ulong* frames; /* periodic frame list (hw) */
|
||||
Qh* qhs; /* async Qh circular list for bulk/ctl */
|
||||
|
|
|
@ -178,6 +178,10 @@ reset(Hci *hp)
|
|||
capio->parms & 0x40 ? "explicit" : "automatic",
|
||||
capio->parms & 0x10 ? "" : "no ", hp->nports);
|
||||
|
||||
ctlr->tdalloc = ucallocalign;
|
||||
ctlr->dmaalloc = ucalloc;
|
||||
cltr->dmafree = ucfree;
|
||||
|
||||
ehcireset(ctlr);
|
||||
ehcimeminit(ctlr);
|
||||
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
/*
|
||||
* On the PC, processor accesses, memory caches and DMA are all
|
||||
* coherent, so we don't need to use uncached memory.
|
||||
*/
|
|
@ -174,6 +174,11 @@ struct Ctlr
|
|||
Ecapio* capio; /* Capability i/o regs */
|
||||
Eopio* opio; /* Operational i/o regs */
|
||||
|
||||
void* (*tdalloc)(ulong,int,ulong);
|
||||
void* (*dmaalloc)(ulong);
|
||||
void (*dmafree)(void*);
|
||||
void (*dmaflush)(int,void*,ulong len);
|
||||
|
||||
int nframes; /* 1024, 512, or 256 frames in the list */
|
||||
ulong* frames; /* periodic frame list (hw) */
|
||||
Qh* qhs; /* async Qh circular list for bulk/ctl */
|
||||
|
|
|
@ -83,7 +83,7 @@ install:V: $p$CONF
|
|||
|
||||
|
||||
# copies generated by the rule below
|
||||
PCHEADERS=wifi.h uncached.h usbehci.h screen.h etherif.h ethermii.h mp.h io.h ahci.h
|
||||
PCHEADERS=wifi.h usbehci.h screen.h etherif.h ethermii.h mp.h io.h ahci.h
|
||||
|
||||
REPCH=`{echo $PCHEADERS | sed 's/\.h//g; s/ /|/g'}
|
||||
^($REPCH)\.h:R: '../pc/\1.h'
|
||||
|
@ -117,7 +117,7 @@ devaoe.$O sdaoe.$O: ../port/aoe.h
|
|||
main.$O: init.h reboot.h
|
||||
|
||||
devusb.$O usbuhci.$O usbohci.$O usbehci.$O: ../port/usb.h
|
||||
usbehci.$O: usbehci.h uncached.h
|
||||
usbehci.$O: usbehci.h
|
||||
trap.$O: /sys/include/tos.h
|
||||
ethermii.$O: ethermii.h
|
||||
etheriwl.$O: wifi.h
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
#include "../port/error.h"
|
||||
#include "../port/usb.h"
|
||||
#include "usbehci.h"
|
||||
#include "uncached.h"
|
||||
|
||||
#define diprint if(ehcidebug || iso->debug)print
|
||||
#define ddiprint if(ehcidebug>1 || iso->debug>1)print
|
||||
|
@ -399,14 +398,14 @@ ehcirun(Ctlr *ctlr, int on)
|
|||
}
|
||||
|
||||
static void*
|
||||
edalloc(void)
|
||||
edalloc(Ctlr *ctlr)
|
||||
{
|
||||
Ed *ed, *pool;
|
||||
int i;
|
||||
|
||||
lock(&edpool);
|
||||
if(edpool.free == nil){
|
||||
pool = xspanalloc(Incr*sizeof(Ed), Align, 0);
|
||||
pool = (*ctlr->tdalloc)(Incr*sizeof(Ed), Align, 0);
|
||||
if(pool == nil)
|
||||
panic("edalloc");
|
||||
for(i=Incr; --i>=0;){
|
||||
|
@ -448,53 +447,54 @@ edfree(void *a)
|
|||
*/
|
||||
|
||||
static Itd*
|
||||
itdalloc(void)
|
||||
itdalloc(Ctlr *ctlr)
|
||||
{
|
||||
Itd *td;
|
||||
|
||||
td = edalloc();
|
||||
td = edalloc(ctlr);
|
||||
td->link = Lterm;
|
||||
return td;
|
||||
}
|
||||
|
||||
static void
|
||||
itdfree(Itd *td)
|
||||
itdfree(Ctlr*, Itd *td)
|
||||
{
|
||||
edfree(td);
|
||||
}
|
||||
|
||||
static Sitd*
|
||||
sitdalloc(void)
|
||||
sitdalloc(Ctlr *ctlr)
|
||||
{
|
||||
Sitd *td;
|
||||
|
||||
td = edalloc();
|
||||
td = edalloc(ctlr);
|
||||
td->link = td->blink = Lterm;
|
||||
return td;
|
||||
}
|
||||
|
||||
static void
|
||||
sitdfree(Sitd *td)
|
||||
sitdfree(Ctlr*, Sitd *td)
|
||||
{
|
||||
edfree(td);
|
||||
}
|
||||
|
||||
static Td*
|
||||
tdalloc(void)
|
||||
tdalloc(Ctlr *ctlr)
|
||||
{
|
||||
Td *td;
|
||||
|
||||
td = edalloc();
|
||||
td = edalloc(ctlr);
|
||||
td->nlink = td->alink = Lterm;
|
||||
return td;
|
||||
}
|
||||
|
||||
static void
|
||||
tdfree(Td *td)
|
||||
tdfree(Ctlr *ctlr, Td *td)
|
||||
{
|
||||
if(td == nil)
|
||||
return;
|
||||
free(td->buff);
|
||||
if(td->buff != nil)
|
||||
(*ctlr->dmafree)(td->buff);
|
||||
edfree(td);
|
||||
}
|
||||
|
||||
|
@ -661,7 +661,7 @@ qhalloc(Ctlr *ctlr, Ep *ep, Qio *io, char* tag)
|
|||
Qh *qh;
|
||||
int ttype;
|
||||
|
||||
qh = edalloc();
|
||||
qh = edalloc(ctlr);
|
||||
qh->nlink = Lterm;
|
||||
qh->alink = Lterm;
|
||||
qh->csw = Tdhalt;
|
||||
|
@ -777,7 +777,7 @@ qhfree(Ctlr *ctlr, Qh *qh)
|
|||
|
||||
while((td = qh->tds) != nil){
|
||||
qh->tds = td->next;
|
||||
tdfree(td);
|
||||
tdfree(ctlr, td);
|
||||
}
|
||||
|
||||
edfree(qh);
|
||||
|
@ -1236,7 +1236,7 @@ isocanwrite(void *a)
|
|||
}
|
||||
|
||||
static void
|
||||
itdinit(Isoio *iso, Itd *td)
|
||||
itdinit(Ctlr *ctlr, Isoio *iso, Itd *td)
|
||||
{
|
||||
int p, t;
|
||||
ulong pa, tsize, size;
|
||||
|
@ -1248,6 +1248,8 @@ itdinit(Isoio *iso, Itd *td)
|
|||
*/
|
||||
p = 0;
|
||||
size = td->ndata = td->mdata;
|
||||
if(ctlr->dmaflush != nil)
|
||||
(*ctlr->dmaflush)(1, td->data, size);
|
||||
pa = PADDR(td->data);
|
||||
for(t = 0; size > 0 && t < 8; t++){
|
||||
tsize = size;
|
||||
|
@ -1265,8 +1267,10 @@ itdinit(Isoio *iso, Itd *td)
|
|||
}
|
||||
|
||||
static void
|
||||
sitdinit(Isoio *iso, Sitd *td)
|
||||
sitdinit(Ctlr *ctlr, Isoio *iso, Sitd *td)
|
||||
{
|
||||
if(ctlr->dmaflush != nil)
|
||||
(*ctlr->dmaflush)(1, td->data, td->mdata);
|
||||
td->ndata = td->mdata & Stdlenmask;
|
||||
td->buffer[0] = PADDR(td->data);
|
||||
td->buffer[1] = (td->buffer[0] & ~0xFFF) + 0x1000;
|
||||
|
@ -1379,7 +1383,7 @@ isohsinterrupt(Ctlr *ctlr, Isoio *iso)
|
|||
tdi->ndata = 0;
|
||||
if(tdi->next == iso->tdu || tdi->next->next == iso->tdu){
|
||||
memset(iso->tdu->data, 0, iso->tdu->mdata);
|
||||
itdinit(iso, iso->tdu);
|
||||
itdinit(ctlr, iso, iso->tdu);
|
||||
iso->tdu = iso->tdu->next;
|
||||
iso->nleft = 0;
|
||||
}
|
||||
|
@ -1444,8 +1448,7 @@ isofsinterrupt(Ctlr *ctlr, Isoio *iso)
|
|||
|
||||
if(stdi->next == iso->stdu || stdi->next->next == iso->stdu){
|
||||
memset(iso->stdu->data, 0, iso->stdu->mdata);
|
||||
coherence();
|
||||
sitdinit(iso, iso->stdu);
|
||||
sitdinit(ctlr, iso, iso->stdu);
|
||||
iso->stdu = iso->stdu->next;
|
||||
iso->nleft = 0;
|
||||
}
|
||||
|
@ -1883,6 +1886,8 @@ episohscpy(Ctlr *ctlr, Ep *ep, Isoio* iso, uchar *b, long count)
|
|||
ep->dev->nb, ep->nb);
|
||||
else{
|
||||
iunlock(ctlr); /* We could page fault here */
|
||||
if(ctlr->dmaflush != nil)
|
||||
(*ctlr->dmaflush)(0, tdu->data, tdu->mdata);
|
||||
memmove(b+tot, tdu->data, nr);
|
||||
ilock(ctlr);
|
||||
if(iso->tdu != tdu)
|
||||
|
@ -1893,7 +1898,7 @@ episohscpy(Ctlr *ctlr, Ep *ep, Isoio* iso, uchar *b, long count)
|
|||
coherence();
|
||||
}
|
||||
if(tdu->ndata == 0){
|
||||
itdinit(iso, tdu);
|
||||
itdinit(ctlr, iso, tdu);
|
||||
iso->tdu = tdu->next;
|
||||
}
|
||||
}
|
||||
|
@ -1921,6 +1926,8 @@ episofscpy(Ctlr *ctlr, Ep *ep, Isoio* iso, uchar *b, long count)
|
|||
ep->dev->nb, ep->nb);
|
||||
else{
|
||||
iunlock(ctlr); /* We could page fault here */
|
||||
if(ctlr->dmaflush != nil)
|
||||
(*ctlr->dmaflush)(0, stdu->data, stdu->mdata);
|
||||
memmove(b+tot, stdu->data, nr);
|
||||
ilock(ctlr);
|
||||
if(iso->stdu != stdu)
|
||||
|
@ -1932,7 +1939,7 @@ episofscpy(Ctlr *ctlr, Ep *ep, Isoio* iso, uchar *b, long count)
|
|||
coherence();
|
||||
}
|
||||
if(stdu->ndata == 0){
|
||||
sitdinit(iso, stdu);
|
||||
sitdinit(ctlr, iso, stdu);
|
||||
iso->stdu = stdu->next;
|
||||
}
|
||||
}
|
||||
|
@ -2024,7 +2031,7 @@ putsamples(Ctlr *ctlr, Isoio *iso, uchar *b, long count)
|
|||
continue;
|
||||
iso->nleft += n;
|
||||
if(iso->nleft == tdu->mdata){
|
||||
itdinit(iso, tdu);
|
||||
itdinit(ctlr, iso, tdu);
|
||||
iso->tdu = tdu->next;
|
||||
iso->nleft = 0;
|
||||
}
|
||||
|
@ -2039,7 +2046,7 @@ putsamples(Ctlr *ctlr, Isoio *iso, uchar *b, long count)
|
|||
continue;
|
||||
iso->nleft += n;
|
||||
if(iso->nleft == stdu->mdata){
|
||||
sitdinit(iso, stdu);
|
||||
sitdinit(ctlr, iso, stdu);
|
||||
iso->stdu = stdu->next;
|
||||
iso->nleft = 0;
|
||||
}
|
||||
|
@ -2137,7 +2144,7 @@ nexttoggle(int toggle, int count, int maxpkt)
|
|||
}
|
||||
|
||||
static Td*
|
||||
epgettd(Qio *io, int flags, void *a, int count, int maxpkt)
|
||||
epgettd(Ctlr *ctlr, Qio *io, int flags, void *a, int count, int maxpkt)
|
||||
{
|
||||
Td *td;
|
||||
ulong pa;
|
||||
|
@ -2145,7 +2152,7 @@ epgettd(Qio *io, int flags, void *a, int count, int maxpkt)
|
|||
|
||||
if(count > Tdmaxpkt)
|
||||
panic("ehci: epgettd: too many bytes");
|
||||
td = tdalloc();
|
||||
td = tdalloc(ctlr);
|
||||
td->csw = flags | io->toggle | io->tok | count << Tdlenshift |
|
||||
Tderr2 | Tderr1;
|
||||
coherence();
|
||||
|
@ -2159,12 +2166,16 @@ epgettd(Qio *io, int flags, void *a, int count, int maxpkt)
|
|||
td->data = td->sbuff;
|
||||
td->buff = nil;
|
||||
} else if(count <= 0x4000){
|
||||
td->buff = td->data = smalloc(count);
|
||||
td->buff = td->data = (*ctlr->dmaalloc)(count);
|
||||
} else {
|
||||
td->buff = smalloc(count + 0x1000);
|
||||
td->buff = (*ctlr->dmaalloc)(count+0x1000);
|
||||
td->data = (uchar*)ROUND((uintptr)td->buff, 0x1000);
|
||||
}
|
||||
|
||||
if(a != nil && count > 0){
|
||||
memmove(td->data, a, count);
|
||||
if(ctlr->dmaflush != nil && td->buff != nil)
|
||||
(*ctlr->dmaflush)(1, td->data, count);
|
||||
}
|
||||
pa = PADDR(td->data);
|
||||
for(i = 0; i < nelem(td->buffer); i++){
|
||||
td->buffer[i] = pa;
|
||||
|
@ -2172,8 +2183,6 @@ epgettd(Qio *io, int flags, void *a, int count, int maxpkt)
|
|||
pa += 0x1000;
|
||||
}
|
||||
td->ndata = count;
|
||||
if(a != nil && count > 0)
|
||||
memmove(td->data, a, count);
|
||||
coherence();
|
||||
io->toggle = nexttoggle(io->toggle, count, maxpkt);
|
||||
coherence();
|
||||
|
@ -2386,9 +2395,9 @@ epio(Ep *ep, Qio *io, void *a, long count, int mustlock)
|
|||
if(count-tot < n)
|
||||
n = count-tot;
|
||||
if(c != nil && io->tok != Tdtokin)
|
||||
td = epgettd(io, Tdactive, c+tot, n, ep->maxpkt);
|
||||
td = epgettd(ctlr, io, Tdactive, c+tot, n, ep->maxpkt);
|
||||
else
|
||||
td = epgettd(io, Tdactive, nil, n, ep->maxpkt);
|
||||
td = epgettd(ctlr, io, Tdactive, nil, n, ep->maxpkt);
|
||||
if(td0 == nil)
|
||||
td0 = td;
|
||||
else
|
||||
|
@ -2452,6 +2461,8 @@ epio(Ep *ep, Qio *io, void *a, long count, int mustlock)
|
|||
if((tot + n) > count)
|
||||
n = count - tot;
|
||||
if(c != nil && (td->csw & Tdtok) == Tdtokin){
|
||||
if(ctlr->dmaflush != nil && td->buff != nil)
|
||||
(*ctlr->dmaflush)(0, td->data, n);
|
||||
memmove(c, td->data, n);
|
||||
c += n;
|
||||
}
|
||||
|
@ -2459,7 +2470,7 @@ epio(Ep *ep, Qio *io, void *a, long count, int mustlock)
|
|||
}
|
||||
}
|
||||
ntd = td->next;
|
||||
tdfree(td);
|
||||
tdfree(ctlr, td);
|
||||
}
|
||||
if(mustlock){
|
||||
qunlock(io);
|
||||
|
@ -2679,12 +2690,14 @@ isofsinit(Ep *ep, Isoio *iso)
|
|||
Sitd *td, *ltd;
|
||||
int i;
|
||||
ulong frno;
|
||||
Ctlr *ctlr;
|
||||
|
||||
ctlr = ep->hp->aux;
|
||||
left = 0;
|
||||
ltd = nil;
|
||||
frno = iso->td0frno;
|
||||
for(i = 0; i < iso->nframes; i++){
|
||||
td = sitdalloc();
|
||||
td = sitdalloc(ctlr);
|
||||
td->data = iso->data + i * ep->maxpkt;
|
||||
td->epc = ep->dev->port << Stdportshift;
|
||||
td->epc |= ep->dev->hub << Stdhubshift;
|
||||
|
@ -2710,7 +2723,7 @@ isofsinit(Ep *ep, Isoio *iso)
|
|||
|
||||
iso->sitdps[frno] = td;
|
||||
coherence();
|
||||
sitdinit(iso, td);
|
||||
sitdinit(ctlr, iso, td);
|
||||
if(ltd != nil)
|
||||
ltd->next = td;
|
||||
ltd = td;
|
||||
|
@ -2727,16 +2740,18 @@ isohsinit(Ep *ep, Isoio *iso)
|
|||
long left;
|
||||
ulong frno, i, pa;
|
||||
Itd *ltd, *td;
|
||||
Ctlr *ctlr;
|
||||
|
||||
iso->hs = 1;
|
||||
ival = 1;
|
||||
if(ep->pollival > 8)
|
||||
ival = ep->pollival/8;
|
||||
ctlr = ep->hp->aux;
|
||||
left = 0;
|
||||
ltd = nil;
|
||||
frno = iso->td0frno;
|
||||
for(i = 0; i < iso->nframes; i++){
|
||||
td = itdalloc();
|
||||
td = itdalloc(ctlr);
|
||||
td->data = iso->data + i * 8 * iso->maxsize;
|
||||
pa = PADDR(td->data) & ~0xFFF;
|
||||
for(p = 0; p < nelem(td->buffer); p++){
|
||||
|
@ -2761,7 +2776,7 @@ isohsinit(Ep *ep, Isoio *iso)
|
|||
coherence();
|
||||
iso->itdps[frno] = td;
|
||||
coherence();
|
||||
itdinit(iso, td);
|
||||
itdinit(ctlr, iso, td);
|
||||
if(ltd != nil)
|
||||
ltd->next = td;
|
||||
ltd = td;
|
||||
|
@ -2826,8 +2841,8 @@ isoopen(Ctlr *ctlr, Ep *ep)
|
|||
*/
|
||||
assert(ep->maxpkt > 0 && ep->ntds > 0 && ep->ntds < 4);
|
||||
assert(ep->maxpkt <= 1024);
|
||||
iso->tdps = smalloc(sizeof(uintptr) * Nisoframes);
|
||||
iso->data = smalloc(iso->nframes * tpf * ep->ntds * ep->maxpkt);
|
||||
iso->tdps = smalloc(sizeof(void*) * Nisoframes);
|
||||
iso->data = (*ctlr->dmaalloc)(iso->nframes * tpf * ep->ntds * ep->maxpkt);
|
||||
iso->td0frno = TRUNC(ctlr->opio->frno + 10, Nisoframes);
|
||||
/* read: now; write: 1s ahead */
|
||||
|
||||
|
@ -3067,9 +3082,9 @@ cancelisoio(Ctlr *ctlr, Isoio *iso, int pollival, ulong load)
|
|||
frno = iso->td0frno;
|
||||
for(i = 0; i < iso->nframes; i++){
|
||||
if(iso->hs != 0)
|
||||
itdfree(iso->itdps[frno]);
|
||||
itdfree(ctlr, iso->itdps[frno]);
|
||||
else
|
||||
sitdfree(iso->sitdps[frno]);
|
||||
sitdfree(ctlr, iso->sitdps[frno]);
|
||||
iso->tdps[frno] = nil;
|
||||
frno = TRUNC(frno+pollival, Nisoframes);
|
||||
}
|
||||
|
@ -3165,7 +3180,7 @@ mkqhtree(Ctlr *ctlr)
|
|||
if(qt->bw == nil || tree == nil)
|
||||
panic("ehci: mkqhtree: no memory");
|
||||
for(i = 0; i < n; i++){
|
||||
tree[i] = qh = edalloc();
|
||||
tree[i] = qh = edalloc(ctlr);
|
||||
if(qh == nil)
|
||||
panic("ehci: mkqhtree: no memory");
|
||||
qh->nlink = qh->alink = qh->link = Lterm;
|
||||
|
@ -3208,10 +3223,17 @@ ehcimeminit(Ctlr *ctlr)
|
|||
int i, frsize;
|
||||
Eopio *opio;
|
||||
|
||||
if(ctlr->tdalloc == nil)
|
||||
ctlr->tdalloc = xspanalloc;
|
||||
if(ctlr->dmaalloc == nil)
|
||||
ctlr->dmaalloc = smalloc;
|
||||
if(ctlr->dmafree == nil)
|
||||
ctlr->dmafree = free;
|
||||
|
||||
opio = ctlr->opio;
|
||||
frsize = ctlr->nframes * sizeof(ulong);
|
||||
assert((frsize & 0xFFF) == 0); /* must be 4k aligned */
|
||||
ctlr->frames = xspanalloc(frsize, frsize, 0);
|
||||
ctlr->frames = (*ctlr->tdalloc)(frsize, frsize, 0);
|
||||
if(ctlr->frames == nil)
|
||||
panic("ehci reset: no memory");
|
||||
|
||||
|
@ -3223,7 +3245,7 @@ ehcimeminit(Ctlr *ctlr)
|
|||
|
||||
qhalloc(ctlr, nil, nil, nil); /* init async list */
|
||||
mkqhtree(ctlr); /* init sync list */
|
||||
edfree(edalloc()); /* try to get some ones pre-allocated */
|
||||
edfree(edalloc(ctlr)); /* try to get some ones pre-allocated */
|
||||
|
||||
dprint("ehci %#p flb %#lux frno %#lux\n",
|
||||
ctlr->capio, opio->frbase, opio->frno);
|
||||
|
|
|
@ -86,5 +86,5 @@ install:V: $p$CONF
|
|||
for(i in $EXTRACOPIES)
|
||||
import $i / /n/$i && cp $p$CONF $p$CONF.gz /n/$i/$objtype/
|
||||
|
||||
devusb.$O usbehci.$O usbehcizynq.$O: ../port/usb.h uncached.h
|
||||
devusb.$O usbehci.$O usbehcizynq.$O: ../port/usb.h
|
||||
usbehci.$O usbehcizynq.$O: usbehci.h
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
#define free ucfree
|
||||
#define malloc myucalloc
|
||||
#define mallocz ucallocz
|
||||
#define smalloc myucalloc
|
||||
#define xspanalloc ucallocalign
|
||||
|
||||
#define allocb ucallocb
|
||||
#define iallocb uciallocb
|
||||
#define freeb ucfreeb
|
||||
|
||||
static void *
|
||||
ucallocz(uint n, int)
|
||||
{
|
||||
char *p = ucalloc(n);
|
||||
|
||||
if (p)
|
||||
memset(p, 0, n);
|
||||
else
|
||||
panic("ucalloc: out of memory");
|
||||
return p;
|
||||
}
|
||||
|
||||
static void *
|
||||
myucalloc(uint n)
|
||||
{
|
||||
return ucallocz(n, 1);
|
||||
}
|
|
@ -84,16 +84,30 @@ typedef struct Qtree Qtree;
|
|||
|
||||
struct Eopio
|
||||
{
|
||||
ulong cmd;
|
||||
ulong sts;
|
||||
ulong intr;
|
||||
ulong frno;
|
||||
ulong dummy1[2];
|
||||
ulong frbase;
|
||||
ulong link;
|
||||
ulong dummy2[9];
|
||||
ulong config;
|
||||
ulong portsc[1];
|
||||
/*140*/ ulong cmd;
|
||||
/*144*/ ulong sts;
|
||||
/*148*/ ulong intr;
|
||||
/*14c*/ ulong frno;
|
||||
|
||||
/*150*/ ulong reserved1;
|
||||
|
||||
/*154*/ ulong frbase;
|
||||
/*158*/ ulong link;
|
||||
|
||||
/*15c*/ ulong _ttctrl;
|
||||
/*160*/ ulong _burstsize;
|
||||
/*164*/ ulong _txfilltuning;
|
||||
/*168*/ ulong _txttfilltuning;
|
||||
/*16c*/ ulong _ic_usb;
|
||||
/*170*/ ulong _ulpi_viewport;
|
||||
|
||||
/*174*/ ulong reserved2;
|
||||
|
||||
/*178*/ ulong _endptnak;
|
||||
/*17c*/ ulong _endptnaken;
|
||||
|
||||
/*180*/ ulong config;
|
||||
/*184*/ ulong portsc[1];
|
||||
};
|
||||
|
||||
struct Poll
|
||||
|
@ -113,6 +127,11 @@ struct Ctlr
|
|||
void* capio; /* base address for debug info */
|
||||
Eopio* opio; /* Operational i/o regs */
|
||||
|
||||
void* (*tdalloc)(ulong,int,ulong);
|
||||
void* (*dmaalloc)(ulong);
|
||||
void (*dmafree)(void*);
|
||||
void (*dmaflush)(int,void*,ulong len);
|
||||
|
||||
int nframes; /* 1024, 512, or 256 frames in the list */
|
||||
ulong* frames; /* periodic frame list (hw) */
|
||||
Qh* qhs; /* async Qh circular list for bulk/ctl */
|
||||
|
|
|
@ -61,6 +61,47 @@ ehcireset(Ctlr *ctlr)
|
|||
iunlock(ctlr);
|
||||
}
|
||||
|
||||
enum {
|
||||
Cls = 64,
|
||||
};
|
||||
|
||||
/* descriptors need to be allocated in uncached memory */
|
||||
static void*
|
||||
tdalloc(ulong size, int, ulong)
|
||||
{
|
||||
return ucalloc(size);
|
||||
}
|
||||
|
||||
static void*
|
||||
dmaalloc(ulong len)
|
||||
{
|
||||
return mallocalign(ROUND(len, Cls), Cls, 0, 0);
|
||||
}
|
||||
static void
|
||||
dmafree(void *data)
|
||||
{
|
||||
free(data);
|
||||
}
|
||||
|
||||
static void
|
||||
dmaflush(int clean, void *data, ulong len)
|
||||
{
|
||||
uintptr va, pa;
|
||||
|
||||
va = (uintptr)data & ~(Cls-1);
|
||||
pa = PADDR(va);
|
||||
len = ROUND(len, Cls);
|
||||
if(clean){
|
||||
/* flush cache before write */
|
||||
cleandse((uchar*)va, (uchar*)va+len);
|
||||
clean2pa(pa, pa+len);
|
||||
} else {
|
||||
/* invalidate cache before read */
|
||||
invaldse((uchar*)va, (uchar*)va+len);
|
||||
inval2pa(pa, pa+len);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
reset(Hci *hp)
|
||||
{
|
||||
|
@ -84,12 +125,17 @@ reset(Hci *hp)
|
|||
ctlr->opio = (Eopio *) ((uchar *) ctlr->r + 0x140);
|
||||
ctlr->capio = (void *) ctlr->base;
|
||||
hp->nports = 1;
|
||||
ctlr->r[USBMODE] |= USBHOST;
|
||||
|
||||
|
||||
ctlr->tdalloc = tdalloc;
|
||||
ctlr->dmaalloc = dmaalloc;
|
||||
ctlr->dmafree = dmafree;
|
||||
ctlr->dmaflush = dmaflush;
|
||||
|
||||
ehcireset(ctlr);
|
||||
ctlr->r[USBMODE] |= USBHOST;
|
||||
ctlr->r[ULPI] = 1<<30 | 1<<29 | 0x0B << 16 | 3<<5;
|
||||
ehcimeminit(ctlr);
|
||||
ehcilinkage(hp);
|
||||
ctlr->r[ULPI] = 1<<30 | 1<<29 | 0x0B << 16 | 3<<5;
|
||||
if(hp->interrupt != nil)
|
||||
intrenable(hp->irq, hp->interrupt, hp, LEVEL, hp->type);
|
||||
return 0;
|
||||
|
@ -98,6 +144,6 @@ reset(Hci *hp)
|
|||
void
|
||||
usbehcilink(void)
|
||||
{
|
||||
ehcidebug = 2;
|
||||
// ehcidebug = 2;
|
||||
addhcitype("ehci", reset);
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ link
|
|||
etherzynq
|
||||
ethermedium
|
||||
loopbackmedium
|
||||
# usbehci usbehcizynq
|
||||
usbehci usbehcizynq
|
||||
|
||||
misc
|
||||
uartzynq
|
||||
|
|
Loading…
Reference in a new issue