shithub: riscv

Download patch

ref: 995379e388e4cd202f683a00e99749c7f21a225d
parent: 6b2d1f0186f2e38a3b0cd6a19b5980dccb045c3c
author: cinap_lenrek <[email protected]>
date: Fri Feb 13 22:00:31 EST 2015

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.

--- a/sys/src/9/kw/fns.h
+++ b/sys/src/9/kw/fns.h
@@ -110,7 +110,7 @@
 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*);
--- a/sys/src/9/kw/mkfile
+++ b/sys/src/9/kw/mkfile
@@ -132,7 +132,7 @@
 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
--- a/sys/src/9/kw/mmu.c
+++ b/sys/src/9/kw/mmu.c
@@ -261,7 +261,7 @@
 	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)
--- a/sys/src/9/kw/ucalloc.c
+++ b/sys/src/9/kw/ucalloc.c
@@ -127,7 +127,7 @@
 }
 
 void*
-ucallocalign(usize size, int align, int span)
+ucallocalign(usize size, int align, usize span)
 {
 	assert(size < ucpool.minarena-128);
 
--- a/sys/src/9/kw/uncached.h
+++ /dev/null
@@ -1,36 +1,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);
-}
--- a/sys/src/9/kw/usbehci.h
+++ b/sys/src/9/kw/usbehci.h
@@ -172,6 +172,11 @@
 	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 */
--- a/sys/src/9/kw/usbehcikw.c
+++ b/sys/src/9/kw/usbehcikw.c
@@ -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)
@@ -330,6 +329,10 @@
 	ddprint("ehci: routing %s, %sport power ctl, %d ports\n",
 		capio->parms & 0x40 ? "explicit" : "automatic",
 		capio->parms & 0x10 ? "" : "no ", hp->nports);
+
+	ctlr->tdalloc = ucallocalign;
+	ctlr->dmaalloc = ucalloc;
+	ctlr->dmafree = ucfree;
 
 	ehcireset(ctlr);
 	ehcimeminit(ctlr);
--- a/sys/src/9/omap/mkfile
+++ b/sys/src/9/omap/mkfile
@@ -111,7 +111,7 @@
 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
--- a/sys/src/9/omap/uncached.h
+++ /dev/null
@@ -1,36 +1,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);
-}
--- a/sys/src/9/omap/usbehci.h
+++ b/sys/src/9/omap/usbehci.h
@@ -39,6 +39,11 @@
 	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 */
--- a/sys/src/9/omap/usbehciomap.c
+++ b/sys/src/9/omap/usbehciomap.c
@@ -178,6 +178,10 @@
 		capio->parms & 0x40 ? "explicit" : "automatic",
 		capio->parms & 0x10 ? "" : "no ", hp->nports);
 
+	ctlr->tdalloc = ucallocalign;
+	ctlr->dmaalloc = ucalloc;
+	cltr->dmafree = ucfree;
+
 	ehcireset(ctlr);
 	ehcimeminit(ctlr);
 
--- a/sys/src/9/pc/uncached.h
+++ /dev/null
@@ -1,4 +1,0 @@
-/*
- * On the PC, processor accesses, memory caches and DMA are all
- * coherent, so we don't need to use uncached memory.
- */
--- a/sys/src/9/pc/usbehci.h
+++ b/sys/src/9/pc/usbehci.h
@@ -174,6 +174,11 @@
 	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 */
--- a/sys/src/9/pc64/mkfile
+++ b/sys/src/9/pc64/mkfile
@@ -83,7 +83,7 @@
 
 
 # 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 @@
 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
--- a/sys/src/9/port/usbehci.c
+++ b/sys/src/9/port/usbehci.c
@@ -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,7 +398,7 @@
 }
 
 static void*
-edalloc(void)
+edalloc(Ctlr *ctlr)
 {
 	Ed *ed, *pool;
 	int i;
@@ -406,7 +405,7 @@
 
 	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 @@
  */
 
 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 @@
 	Qh *qh;
 	int ttype;
 
-	qh = edalloc();
+	qh = edalloc(ctlr);
 	qh->nlink = Lterm;
 	qh->alink = Lterm;
 	qh->csw = Tdhalt;
@@ -777,7 +777,7 @@
 
 	while((td = qh->tds) != nil){
 		qh->tds = td->next;
-		tdfree(td);
+		tdfree(ctlr, td);
 	}
 
 	edfree(qh);
@@ -1236,7 +1236,7 @@
 }
 
 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 @@
 	 */
 	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 @@
 }
 
 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 @@
 			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 @@
 
 		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 @@
 				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 @@
 			coherence();
 		}
 		if(tdu->ndata == 0){
-			itdinit(iso, tdu);
+			itdinit(ctlr, iso, tdu);
 			iso->tdu = tdu->next;
 		}
 	}
@@ -1921,6 +1926,8 @@
 				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 @@
 			coherence();
 		}
 		if(stdu->ndata == 0){
-			sitdinit(iso, stdu);
+			sitdinit(ctlr, iso, stdu);
 			iso->stdu = stdu->next;
 		}
 	}
@@ -2024,7 +2031,7 @@
 				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 @@
 				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 @@
 }
 
 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 @@
 
 	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 @@
 		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 @@
 		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 @@
 		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 @@
 				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 @@
 			}
 		}
 		ntd = td->next;
-		tdfree(td);
+		tdfree(ctlr, td);
 	}
 	if(mustlock){
 		qunlock(io);
@@ -2679,12 +2690,14 @@
 	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 @@
 
 		iso->sitdps[frno] = td;
 		coherence();
-		sitdinit(iso, td);
+		sitdinit(ctlr, iso, td);
 		if(ltd != nil)
 			ltd->next = td;
 		ltd = td;
@@ -2727,16 +2740,18 @@
 	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 @@
 		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 @@
 	 */
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 
 	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);
--- a/sys/src/9/zynq/mkfile
+++ b/sys/src/9/zynq/mkfile
@@ -86,5 +86,5 @@
 	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
--- a/sys/src/9/zynq/uncached.h
+++ /dev/null
@@ -1,27 +1,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);
-}
--- a/sys/src/9/zynq/usbehci.h
+++ b/sys/src/9/zynq/usbehci.h
@@ -84,16 +84,30 @@
 
 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
@@ -112,6 +126,11 @@
 	int	active;		/* in use or not */
 	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) */
--- a/sys/src/9/zynq/usbehcizynq.c
+++ b/sys/src/9/zynq/usbehcizynq.c
@@ -61,6 +61,47 @@
 	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 @@
 	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 @@
 void
 usbehcilink(void)
 {
-	ehcidebug = 2;
+//	ehcidebug = 2;
 	addhcitype("ehci", reset);
 }
--- a/sys/src/9/zynq/zynq
+++ b/sys/src/9/zynq/zynq
@@ -26,7 +26,7 @@
 	etherzynq
 	ethermedium
 	loopbackmedium
-#	usbehci usbehcizynq
+	usbehci usbehcizynq
 
 misc
 	uartzynq