ref: 561346d07f176356e9841891e5213672c0a33878
parent: 7cf8369411a3b9348f862bccaa4147b9aaf38e67
author: aiju <devnull@localhost>
date: Sat Jan 11 22:40:42 EST 2020
cyclone v kernel: fpga support, fix CONFADDR
--- a/sys/src/9/cycv/cycv
+++ b/sys/src/9/cycv/cycv
@@ -2,7 +2,7 @@
root
cons
swap
-# arch
+ arch
uart
mnt
srv
@@ -24,6 +24,7 @@
segment
link
+ dma
ethercycv
ethermedium
loopbackmedium
--- a/sys/src/9/cycv/dat.h
+++ b/sys/src/9/cycv/dat.h
@@ -13,6 +13,7 @@
typedef struct PMMU PMMU;
typedef struct Ureg Ureg;
typedef struct ISAConf ISAConf;
+typedef struct DMAC DMAC;
typedef uvlong Tval;
#pragma incomplete Ureg
@@ -202,3 +203,7 @@
#define mpcore ((ulong*)MPCORE_BASE)
#define resetmgr ((ulong*)RESETMGR_BASE)
#define sysmgr ((ulong*)SYSMGR_BASE)
+
+/*dmacopy*/
+#define SRC_INC (1<<0)
+#define DST_INC (1<<14)
--- a/sys/src/9/cycv/devarch.c
+++ b/sys/src/9/cycv/devarch.c
@@ -7,11 +7,44 @@
#include "ureg.h"
#include "../port/error.h"
+#define fpga ((ulong*) FPGAMGR_BASE)
+
+enum { Timeout = 3000 };
+
enum {
+ FPGASTAT,
+ FPGACTRL,
+ FPGAINTEN = 0x830/4,
+ FPGAINTTYPE = 0x838/4,
+ FPGAINTPOL = 0x83C/4,
+ FPGAINTSTATUS = 0x840/4,
+ FPGAEOI = 0x84C/4,
+ FPGAPINS = 0x850/4,
+};
+
+enum {
+ /*FPGACTRL*/
+ HPSCONFIG = 1<<0,
+ NCONFIGPULL = 1<<2,
+ AXICFGEN = 1<<8,
+ /*FPGAPINS*/
+ NSTATUS = 1<<0,
+ CONF_DONE = 1<<1,
+ INIT_DONE = 1<<2,
+ CRC_ERROR = 1<<3,
+ CVP_CONF_DONE = 1<<4,
+ PR_READY = 1<<5,
+ PR_ERROR = 1<<6,
+ PR_DONE = 1<<7,
+ NCONFIG_PIN = 1<<8,
+ NSTATUS_PIN = 1<<9,
+ CONF_DONE_PIN = 1<<10,
+ FPGA_POWER_ON = 1<<11
+};
+
+enum {
Qdir = 0,
- Qtemp,
- Qpl,
- Qfbctl,
+ Qfpga,
Qbase,
Qmax = 16,
@@ -19,288 +52,149 @@
static Dirtab archdir[Qmax] = {
".", { Qdir, 0, QTDIR }, 0, 0555,
- "temp", { Qtemp, 0}, 0, 0440,
- "pl", { Qpl, 0 }, 0, 0660,
- "fbctl", { Qfbctl, 0 }, 0, 0660,
+ "fpga", { Qfpga, 0 }, 0, 0660,
};
static int narchdir = Qbase;
-static int temp = -128;
-static ulong *devc;
-static int dmadone;
-enum { PLBUFSIZ = 8192 };
-static uchar *plbuf;
-static Rendez plinitr, pldoner, pldmar;
-static QLock plrlock, plwlock;
-static Ref plwopen;
-static Physseg *axi;
+static Ref fpgawopen;
+enum { FPGABUFSIZ = 65536 };
+static uchar *fpgabuf;
+static int fpgabufp;
+static int fpgaok;
-enum {
- DEVCTRL = 0,
- DEVISTS = 0xc/4,
- DEVMASK,
- DEVSTS,
- DMASRC = 0x18/4,
- DMADST,
- DMASRCL,
- DMADSTL,
- XADCCFG = 0x100/4,
- XADCSTS,
- XADCMASK,
- XADCMSTS,
- XADCCMD,
- XADCREAD,
- XADCMCTL,
-
- FPGA0_CLK_CTRL = 0x170/4,
-};
-
-enum {
- PROG = 1<<30,
- DONE = 1<<2,
- INITPE = 1<<1,
- INIT = 1<<4,
- DMADONE = 1<<13,
-};
-
-static void
-scram(void)
+static Rendez fpgarend;
+static u32int fpgawaitset, fpgawaitclr;
+static int
+donewaiting(void *)
{
- splhi();
- slcr[0x100/4] |= 1<<4;
- slcr[0x104/4] |= 1<<4;
- slcr[0x108/4] |= 1<<4;
- slcr[DEVCTRL] &= ~PROG;
- slcr[0x244/4] = 1<<4|1<<5;
-}
-
-static void
-xadcirq(Ureg *, void *)
-{
- int v;
- static int al, notfirst;
+ u32int s;
- while((devc[XADCMSTS] & 1<<8) == 0){
- v = ((u16int)devc[XADCREAD]) >> 4;
- if(v == 0){
- if(notfirst)
- print("temperature sensor reads 0, shouldn't happen\n");
- break;
- }
- notfirst = 1;
- temp = v * 5040 / 4096 - 2732;
- if(temp >= 800){
- if(al == 0)
- print("temperature exceeds 80 deg C\n");
- al = 1;
- }
- if(temp <= 750)
- al = 0;
- if(temp >= 900){
- print("chip temperature exceeds 90 deg C, shutting down");
- scram();
- }
- }
- devc[XADCSTS] = -1;
+ s = fpga[FPGAPINS];
+ return (s & fpgawaitset | ~s & fpgawaitclr) != 0;
+
}
-
static void
-xadctimer(void)
+fpgairq(Ureg *, void *)
{
- devc[XADCCMD] = 1<<26 | 0<<16;
+ fpga[FPGAEOI] = -1;
+ if(donewaiting(nil))
+ wakeup(&fpgarend);
}
-
-static void
-xadcinit(void)
-{
- int i;
- int x;
-
- devc = vmap(DEVC_BASE, 0x11C);
- devc[XADCMCTL] |= 1<<4;
- devc[XADCMCTL] &= ~(1<<4);
- devc[XADCCMD] = 0x08030000;
- for(i = 0; i < 15; i++)
- devc[XADCCMD] = 0;
- while((devc[XADCMSTS] & 1<<10) == 0)
- ;
- while((devc[XADCMSTS] & 1<<8) == 0){
- x = devc[XADCREAD];
- USED(x);
- }
- devc[XADCCFG] = 0x80001114;
- devc[XADCMASK] = ~(1<<8);
- devc[XADCSTS] = -1;
- intrenable(XADCIRQ, xadcirq, nil, LEVEL, "xadc");
- addclock0link(xadctimer, XADCINTERVAL);
-}
-
static int
-isplinit(void *)
+fpgawait(u32int set, u32int clr, int timeout)
{
- return devc[DEVSTS] & INIT;
-}
+ int s;
-static int
-ispldone(void *)
-{
- return devc[DEVISTS] & DONE;
+ fpgawaitset = set;
+ fpgawaitclr = clr;
+ if(donewaiting(nil)) return 0;
+ s = spllo();
+ fpga[FPGAINTEN] = 0;
+ fpga[FPGAEOI] = -1;
+ fpga[FPGAINTPOL] = set;
+ fpga[FPGAINTEN] = set | clr;
+ tsleep(&fpgarend, donewaiting, nil, timeout);
+ fpga[FPGAINTEN] = 0;
+ fpga[FPGAEOI] = -1;
+ splx(s);
+ return donewaiting(nil) ? 0 : -1;
}
-static int
-isdmadone(void *)
-{
- return dmadone;
-}
-
static void
-plirq(Ureg *, void *)
+fpgaconf(void)
{
- ulong fl;
+ int msel;
+ enum { PORFAST = 1, AES = 2, AESMAYBE = 4, COMP = 8, FPP32 = 16 };
+ static uchar mseltab[16][3] = {
+ [0] {0, 1, PORFAST},
+ [4] {0, 1, 0},
+ [1] {0, 2, PORFAST|AES},
+ [5] {0, 2, AES},
+ [2] {0, 3, COMP|AESMAYBE|PORFAST},
+ [6] {0, 3, COMP|AESMAYBE},
+ [8] {1, 1, PORFAST|FPP32},
+ [12] {1, 1, FPP32},
+ [9] {1, 2, AES|FPP32|PORFAST},
+ [13] {1, 2, AES|FPP32},
+ [10] {1, 4, COMP|AESMAYBE|PORFAST|FPP32},
+ [14] {1, 4, COMP|AESMAYBE|FPP32}
+ };
- fl = devc[DEVISTS];
- if((fl & INITPE) != 0)
- wakeup(&plinitr);
- if((fl & DONE) != 0){
- slcr[0x900/4] = 0xf;
- slcr[0x240/4] = 0;
- devc[DEVMASK] |= DONE;
- axi->attr &= ~SG_FAULT;
- wakeup(&pldoner);
+ if((fpga[FPGAPINS] & FPGA_POWER_ON) == 0)
+ error("FPGA powered off");
+ msel = fpga[FPGASTAT] >> 3 & 0x1f;
+ if(msel >= 16 || mseltab[msel][1] == 0){
+ print("MSEL set to invalid setting %#.2x\n", msel);
+ error("MSEL set to invalid setting");
}
- if((fl & DMADONE) != 0){
- dmadone++;
- wakeup(&pldmar);
- }
- devc[DEVISTS] = fl;
+ fpga[FPGACTRL] = fpga[FPGACTRL] & ~0x3ff
+ | mseltab[msel][0] << 9 /* cfgwdth */
+ | mseltab[msel][1]-1 << 6 /* cdratio */
+ | NCONFIGPULL | HPSCONFIG;
+ if(fpgawait(0, NSTATUS, Timeout) < 0 || fpgawait(0, CONF_DONE, Timeout) < 0)
+ error("FPGA won't enter reset phase");
+ fpga[FPGACTRL] &= ~NCONFIGPULL;
+ if(fpgawait(NSTATUS, 0, Timeout) < 0)
+ error("FPGA won't enter configuration phase");
+ fpga[FPGACTRL] |= AXICFGEN;
}
static void
-plinit(void)
+fpgawrite(uchar *a, int n)
{
- Physseg seg;
+ int m;
- memset(&seg, 0, sizeof seg);
- seg.attr = SG_PHYSICAL | SG_DEVICE | SG_NOEXEC | SG_FAULT;
- seg.name = "axi";
- seg.pa = 0x40000000;
- seg.size = 0x8000000;
- axi = addphysseg(&seg);
-
- devc[DEVCTRL] &= ~(PROG|1<<25);
- devc[DEVCTRL] |= 3<<26|PROG;
- devc[DEVISTS] = -1;
- devc[DEVMASK] = ~(DONE|INITPE|DMADONE);
- intrenable(DEVCIRQ, plirq, nil, LEVEL, "pl");
-
- slcr[FPGA0_CLK_CTRL] = 1<<20 | 10<<8;
-}
-
-static void
-plconf(void)
-{
- axi->attr |= SG_FAULT;
- procflushpseg(axi);
- flushmmu();
-
- slcr[0x240/4] = 0xf;
- slcr[0x900/4] = 0xa;
- devc[DEVISTS] = DONE|INITPE|DMADONE;
- devc[DEVCTRL] |= PROG;
- devc[DEVCTRL] &= ~PROG;
- devc[DEVMASK] &= ~DONE;
- devc[DEVCTRL] |= PROG;
-
- while(waserror())
- ;
- sleep(&plinitr, isplinit, nil);
- poperror();
-}
-
-static long
-plwrite(uintptr pa, long n)
-{
- dmadone = 0;
- coherence();
- devc[DMASRC] = pa;
- devc[DMADST] = -1;
- devc[DMASRCL] = n>>2;
- devc[DMADSTL] = 0;
-
- while(waserror())
- ;
- sleep(&pldmar, isdmadone, nil);
- poperror();
-
- return n;
-}
-
-static long
-plcopy(uchar *d, long n)
-{
- long ret;
- ulong nn;
- uintptr pa;
-
- if((n & 3) != 0 || n <= 0)
- error(Eshort);
-
- eqlock(&plwlock);
if(waserror()){
- qunlock(&plwlock);
+ fpgaok = 0;
nexterror();
}
-
- ret = n;
- pa = PADDR(plbuf);
- while(n > 0){
- if(n > PLBUFSIZ)
- nn = PLBUFSIZ;
- else
- nn = n;
- memmove(plbuf, d, nn);
- cleandse(plbuf, plbuf + nn);
- clean2pa(pa, pa + nn);
- n -= plwrite(pa, nn);
+ if((fpga[FPGAPINS] & NSTATUS) == 0)
+ error("FPGA reports configuration error");
+ fpgaok = 1;
+ while(fpgabufp + n >= FPGABUFSIZ){
+ m = FPGABUFSIZ - fpgabufp;
+ memmove(&fpgabuf[fpgabufp], a, m);
+ cleandse(fpgabuf, fpgabuf + FPGABUFSIZ);
+ dmacopy((void *) FPGAMGRDATA, fpgabuf, FPGABUFSIZ, SRC_INC);
+ a += m;
+ n -= m;
+ fpgabufp = 0;
}
-
- qunlock(&plwlock);
+ memmove(&fpgabuf[fpgabufp], a, n);
+ fpgabufp += n;
poperror();
-
- return ret;
}
-void
-archinit(void)
+static void
+fpgafinish(void)
{
- slcr[2] = 0xDF0D;
- xadcinit();
- plinit();
+ if(!fpgaok) return;
+ while((fpgabufp & 3) != 0)
+ fpgabuf[fpgabufp++] = 0;
+ cleandse(fpgabuf, fpgabuf + fpgabufp);
+ dmacopy((void *) FPGAMGRDATA, fpgabuf, fpgabufp, SRC_INC);
+ fpga[FPGACTRL] &= ~AXICFGEN;
+ if(fpgawait(CONF_DONE, NSTATUS, Timeout) < 0){
+ print("FPGA stuck in configuration phase -- truncated file?\n");
+ return;
+ }
+ if((fpga[FPGAPINS] & NSTATUS) == 0){
+ print("FPGA reports configuration error\n");
+ return;
+ }
+ if(fpgawait(INIT_DONE, 0, Timeout) < 0){
+ print("FPGA stuck in initialization phase\n");
+ return;
+ }
+ fpga[FPGACTRL] &= ~HPSCONFIG;
}
static long
-archread(Chan *c, void *a, long n, vlong offset)
+archread(Chan *c, void *a, long n, vlong)
{
- char buf[64];
-
switch((ulong)c->qid.path){
case Qdir:
return devdirread(c, a, n, archdir, narchdir, devgen);
- case Qtemp:
- snprint(buf, sizeof(buf), "%d.%d\n", temp/10, temp%10);
- return readstr(offset, a, n, buf);
- case Qpl:
- eqlock(&plrlock);
- if(waserror()){
- qunlock(&plrlock);
- nexterror();
- }
- sleep(&pldoner, ispldone, nil);
- qunlock(&plrlock);
- poperror();
- return 0;
- case Qfbctl:
- return fbctlread(c, a, n, offset);
default:
error(Egreg);
return -1;
@@ -308,13 +202,12 @@
}
static long
-archwrite(Chan *c, void *a, long n, vlong offset)
+archwrite(Chan *c, void *a, long n, vlong)
{
switch((ulong)c->qid.path){
- case Qpl:
- return plcopy(a, n);
- case Qfbctl:
- return fbctlwrite(c, a, n, offset);
+ case Qfpga:
+ fpgawrite(a, n);
+ return n;
default:
error(Egreg);
return -1;
@@ -337,14 +230,16 @@
archopen(Chan* c, int omode)
{
devopen(c, omode, archdir, narchdir, devgen);
- if((ulong)c->qid.path == Qpl && (c->mode == OWRITE || c->mode == ORDWR)){
- if(incref(&plwopen) != 1){
+ if((ulong)c->qid.path == Qfpga && (c->mode == OWRITE || c->mode == ORDWR)){
+ if(incref(&fpgawopen) != 1){
c->flag &= ~COPEN;
- decref(&plwopen);
+ decref(&fpgawopen);
error(Einuse);
}
- plbuf = smalloc(PLBUFSIZ);
- plconf();
+ fpgaok = 0;
+ fpgaconf();
+ fpgabuf = xspanalloc(FPGABUFSIZ, 64, 0);
+ fpgabufp = 0;
}
return c;
}
@@ -353,13 +248,23 @@
archclose(Chan* c)
{
if((c->flag & COPEN) != 0)
- if((ulong)c->qid.path == Qpl && (c->mode == OWRITE || c->mode == ORDWR)){
- free(plbuf);
- plbuf = nil;
- decref(&plwopen);
+ if((ulong)c->qid.path == Qfpga && (c->mode == OWRITE || c->mode == ORDWR)){
+ fpgafinish();
+ //xfree(fpgabuf);
+ fpgabuf = nil;
+ decref(&fpgawopen);
}
}
+static void
+archreset(void)
+{
+ fpga[FPGAINTEN] = 0;
+ fpga[FPGAEOI] = -1;
+ fpga[FPGAINTTYPE] = -1;
+ intrenable(FPGAMGRIRQ, fpgairq, nil, LEVEL, "fpgamgr");
+}
+
static Chan*
archattach(char* spec)
{
@@ -370,7 +275,7 @@
'P',
"arch",
- devreset,
+ archreset,
devinit,
devshutdown,
archattach,
--- /dev/null
+++ b/sys/src/9/cycv/dma.c
@@ -1,0 +1,265 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "ureg.h"
+#include "../port/error.h"
+
+#define dmar ((ulong*)DMAS_BASE)
+
+enum {
+ DSR = 0x000,
+ DPC = 0x004/4,
+ INTEN = 0x20 / 4,
+ INT_EVENT_RIS = 0x024 / 4,
+ INTMIS = 0x028 / 4,
+ INTCLR = 0x02C / 4,
+ FSRD = 0x030 / 4,
+ FSRC = 0x034 / 4,
+ FTRD = 0x038 / 4,
+ DBGSTATUS = 0xD00 / 4,
+ DBGCMD = 0xD04 / 4,
+ DBGINST0 = 0xD08 / 4,
+ DBGINST1 = 0xD0C / 4,
+ CR0 = 0xE00 / 4,
+ CR1, CR2, CR3, CR4, CRD,
+ WD = 0xE80 / 4,
+};
+enum {
+ DMAStopped,
+ DMAExecuting,
+ DMACacheMiss,
+ DMAUpdatingPC,
+ DMAWaitingForEvent,
+ DMAAtBarrier,
+ DMAWaitingForPeripheral = 7,
+ DMAKilling,
+ DMACompleting,
+ DMAFaultingCompleting=14,
+ DMAFaulting,
+};
+#define FTR(n) dmar[(0x40/4 + (n))]
+#define CSR(n) dmar[(0x100/4 + (n)*2)]
+#define CPC(n) dmar[(0x104/4 + (n)*2)]
+#define SAR(n) dmar[(0x400/4 + (n)*8)]
+#define DAR(n) dmar[(0x404/4 + (n)*8)]
+#define CCR(n) dmar[(0x408/4 + (n)*8)]
+#define LC0(n) dmar[(0x40C/4 + (n)*8)]
+#define LC1(n) dmar[(0x410/4 + (n)*8)]
+
+#define DST_BURST(n) (((n)-1&0xf)<<18)
+#define DST_BEAT_1 (0)
+#define DST_BEAT_2 (1<<15)
+#define DST_BEAT_4 (2<<15)
+#define DST_BEAT_8 (3<<15)
+#define DST_BEAT_16 (4<<15)
+#define SRC_BURST(n) (((n)-1&0xf)<<4)
+#define SRC_BEAT_1 (0)
+#define SRC_BEAT_2 (1<<1)
+#define SRC_BEAT_4 (2<<1)
+#define SRC_BEAT_8 (3<<1)
+#define SRC_BEAT_16 (4<<1)
+
+#define dmaMOV_SARn 0x00bc
+#define dmaMOV_CCRn 0x01bc
+#define dmaMOV_DARn 0x02bc
+#define dmaLP0(n) (((n)-1&0xff)<<8|0x20)
+#define dmaLP1(n) (((n)-1&0xff)<<8|0x22)
+#define dmaLPEND0(n) (((n)&0xff)<<8|0x38)
+#define dmaLPEND1(n) (((n)&0xff)<<8|0x3c)
+#define dmaLD 0x04
+#define dmaST 0x08
+#define dmaSEV(n) (((n)&31)<<11|0x34)
+#define dmaEND 0x00
+#define dmaWMB 0x13
+
+static QLock dmalock;
+static Rendez dmarend;
+static int finished;
+static ulong code[64];
+
+static int
+isfinished(void *)
+{
+ return finished;
+}
+static void
+dmairq(Ureg *, void *)
+{
+ dmar[INTCLR] = -1;
+ finished = 1;
+ wakeup(&dmarend);
+}
+
+static void
+compactify(ulong *lp)
+{
+ uchar *p, *q;
+
+ q = p = (uchar *) lp;
+ for(;;){
+ switch(*p){
+ case 0xbc:
+ q[0] = p[0];
+ q[1] = p[1];
+ q[2] = p[4];
+ q[3] = p[5];
+ q[4] = p[6];
+ q[5] = p[7];
+ q += 6; p += 8;
+ break;
+ case 0x20: case 0x22: case 0x38: case 0x3c: case 0x34:
+ q[0] = p[0];
+ q[1] = p[1];
+ q += 2; p += 4;
+ break;
+ case 0x04: case 0x08: case 0x13:
+ q[0] = p[0];
+ q++; p += 4;
+ break;
+ case 0x00:
+ q[0] = 0;
+ return;
+ default:
+ panic("DMA: unknown opcode %.2x", *p);
+ }
+ }
+}
+
+#define BURST(n) *p++ = dmaMOV_CCRn, *p++ = DST_BEAT_4 | SRC_BEAT_4 | SRC_BURST(n) | DST_BURST(n) | attr
+
+void
+dmacopy(void *dst, void *src, ulong n, int attr)
+{
+ ulong *p;
+
+ assert((n & 3) == 0 && ((uintptr)src & 3) == 0 && ((uintptr)dst & 3) == 0);
+ while(n > (1<<22)){
+ dmacopy(dst, src, 1<<22, attr);
+ if((attr & SRC_INC) != 0) src = (uchar*)src + (1<<22);
+ if((attr & DST_INC) != 0) dst = (uchar*)dst + (1<<22);
+ }
+ if(n == 0) return;
+ qlock(&dmalock);
+ p = code;
+ *p++ = dmaMOV_SARn; *p++ = PADDR(src);
+ *p++ = dmaMOV_DARn; *p++ = PADDR(dst);
+ if((n >> 6) >= 1){
+ BURST(16);
+ if((n>>14) >= 1){
+ if((n>>14) > 1) *p++ = dmaLP0(n >> 14);
+ *p++ = dmaLP1(256);
+ *p++ = dmaLD;
+ *p++ = dmaST;
+ *p++ = dmaLPEND1(2);
+ if((n>>14) > 1) *p++ = dmaLPEND0(6);
+ n &= (1<<14)-1;
+ }
+ if((n >> 6) >= 1){
+ if((n>>6) > 1) *p++ = dmaLP0(n >> 6);
+ *p++ = dmaLD;
+ *p++ = dmaST;
+ if((n>>6) > 1) *p++ = dmaLPEND0(2);
+ n &= 63;
+ }
+ }
+ if(n >= 4){
+ BURST(n>>2);
+ *p++ = dmaLD;
+ *p++ = dmaST;
+ }
+ *p++ = dmaWMB;
+ *p++ = dmaSEV(0);
+ *p = dmaEND;
+ compactify(code);
+ if((CSR(0) & 0xf) != DMAStopped){
+ while((dmar[DBGSTATUS] & 1) != 0)
+ tsleep(&up->sleep, return0, nil, 1);
+ dmar[DBGINST0] = 0x1 << 16 | 1;
+ dmar[DBGCMD] = 0;
+ while((dmar[DBGSTATUS] & 1) != 0)
+ tsleep(&up->sleep, return0, nil, 1);
+ while((CSR(0) & 0xf) != DMAStopped)
+ tsleep(&up->sleep, return0, nil, 1);
+ }
+ cleandse(code, code + nelem(code));
+ while((dmar[DBGSTATUS] & 1) != 0)
+ tsleep(&up->sleep, return0, nil, 1);
+ dmar[DBGINST0] = 0xa0 << 16;
+ dmar[DBGINST1] = PADDR(code);
+ finished = 0;
+ dmar[DBGCMD] = 0;
+ while(!finished)
+ sleep(&dmarend, isfinished, nil);
+ qunlock(&dmalock);
+}
+
+
+static void
+dmaabort(Ureg *, void *)
+{
+ int i;
+
+ if((dmar[FSRD] & 1) != 0){
+ iprint("dma: manager fault: ");
+ if((dmar[FTRD] & 1<<30) != 0)
+ iprint("debug instruction, ");
+ if((dmar[FTRD] & 1<<16) != 0)
+ iprint("instruction fetch error, ");
+ if((dmar[FTRD] & 1<<5) != 0)
+ iprint("event security violation, ");
+ if((dmar[FTRD] & 1<<4) != 0)
+ iprint("DMAGO security violation, ");
+ if((dmar[FTRD] & 1<<1) != 0)
+ iprint("operand invalid, ");
+ if((dmar[FTRD] & 1<<0) != 0)
+ iprint("undefined instruction, ");
+ iprint("\n");
+ }
+ for(i = 0; i < 8; i++){
+ if((dmar[FSRC] & 1<<i) == 0)
+ continue;
+ iprint("dma: channel %d fault\n", i);
+ iprint("code = %.8p, PC = %.8ulx\n", code, CPC(i));
+ iprint("CCRn = %.8ulx, CSRn = %.8ulx\n", CCR(i), CSR(i));
+ iprint("LC0 = %.2ulx, LC1 = %.2ulx\n", LC0(i), LC1(i));
+ if((FTR(i) & 1<<31) != 0)
+ iprint("insufficient resources, ");
+ if((FTR(i) & 1<<30) != 0)
+ iprint("debug instruction, ");
+ if((FTR(i) & 1<<18) != 0)
+ iprint("read error, ");
+ if((FTR(i) & 1<<17) != 0)
+ iprint("write error, ");
+ if((FTR(i) & 1<<16) != 0)
+ iprint("instruction fetch error, ");
+ if((FTR(i) & 1<<13) != 0)
+ iprint("FIFO underflow, ");
+ if((FTR(i) & 1<<12) != 0)
+ iprint("FIFO error, ");
+ if((FTR(i) & 1<<7) != 0)
+ iprint("CCRn security violation, ");
+ if((FTR(i) & 1<<6) != 0)
+ iprint("peripheral security violation, ");
+ if((FTR(i) & 1<<5) != 0)
+ iprint("event security violation, ");
+ if((FTR(i) & 1<<4) != 0)
+ iprint("DMAGO security violation, ");
+ if((FTR(i) & 1<<1) != 0)
+ iprint("operand invalid, ");
+ if((FTR(i) & 1<<0) != 0)
+ iprint("undefined instruction, ");
+ iprint("\n");
+ }
+ panic("DMA fault");
+}
+
+void
+dmalink(void)
+{
+ dmar[INTEN] = 1;
+ intrenable(DMAIRQ0, dmairq, nil, LEVEL, "dma");
+ intrenable(DMAABORTIRQ, dmaabort, nil, LEVEL, "dma_abort");
+}
--- a/sys/src/9/cycv/ethercycv.c
+++ b/sys/src/9/cycv/ethercycv.c
@@ -199,8 +199,6 @@
r = &c->rxr[4 * c->rxconsi];
if((r[0] >> 31) != 0)
break;
- if((r[0] & 1<<15) != 0)
- iprint("eth: error frame\n");
if((r[0] & (3<<8)) != (3<<8))
iprint("eth: lilu dallas multidescriptor\n");
bp = c->rxs[c->rxconsi];
@@ -404,6 +402,38 @@
}
}
+static long
+ethifstat(Ether *edev, void *a, long n, ulong offset)
+{
+ static char *names[] = {
+ "txoctetcount_gb", "txframecount_gb", "txbroadcastframes_g", "txmulticastframes_g",
+ "tx64octets_gb", "tx65to127octets_gb", "tx128to255octets_gb", "tx256to511octets_gb",
+ "tx512to1023octets_gb", "tx1024tomaxoctets_gb", "txunicastframes_gb", "txmulticastframes_gb",
+ "txbroadcastframes_gb", "txunderflowerror", "txsinglecol_g", "txmulticol_g",
+ "txdeferred", "txlatecol", "txexesscol", "txcarriererr",
+ "txoctetcnt", "txframecount_g", "txexcessdef", "txpauseframes",
+ "txvlanframes_g", "txoversize_g", "rxframecount_gb", "rxoctetcount_gb",
+ "rxoctetcount_g", "rxbroadcastframes_g", "rxmulticastframes_g", "rxcrcerror",
+ "rxalignmenterror", "rxrunterror", "rxjabbererror", "rxundersize_g",
+ "rxoversize_g", "rx64octets_gb", "rx65to127octets_gb", "rx128to255octets_gb",
+ "rx256to511octets_gb", "rx512to1023octets_gb", "rx1024tomaxoctets_gb", "rxunicastframes_g",
+ "rxlengtherror", "rxoutofrangetype", "rxpauseframes", "rxfifooverflow",
+ "rxvlanframes_gb", "rxwatchdogerror", "rxrcverror", "rxctrlframes_g",
+ };
+ int i;
+ char *buf, *p, *e;
+ Ctlr *c;
+
+ p = buf = smalloc(READSTR);
+ e = p + READSTR;
+ c = edev->ctlr;
+ for(i = 0; i < nelem(names); i++)
+ p = seprint(p, e, "%s: %lud\n", names[i], c->r[0x114/4 + i]);
+ n = readstr(offset, a, n, buf);
+ free(buf);
+ return n;
+}
+
static int
etherpnp(Ether *edev)
{
@@ -425,6 +455,7 @@
edev->mbps = 1000;
edev->promiscuous = ethprom;
edev->multicast = ethmcast;
+ edev->ifstat = ethifstat;
if(ethinit(edev) < 0){
edev->ctlr = nil;
--- a/sys/src/9/cycv/fns.h
+++ b/sys/src/9/cycv/fns.h
@@ -76,3 +76,4 @@
void screeninit(void);
int isaconfig(char*, int, ISAConf*);
void cputhex(u32int);
+void dmacopy(void *, void *, ulong, int);
--- a/sys/src/9/cycv/io.h
+++ b/sys/src/9/cycv/io.h
@@ -5,7 +5,10 @@
#define EMAC1_BASE 0xFF702000
#define RESETMGR_BASE 0xFFD05000
#define SYSMGR_BASE 0xFFD08000
+#define FPGAMGR_BASE 0xFF706000
+#define FPGAMGRDATA 0xFFB90000
#define OCRAM 0xFFFF0000
+#define DMAS_BASE 0xFFE01000
/*RESETMGR*/
#define PERMODRST (0x14/4)
@@ -17,6 +20,9 @@
#define TIMERIRQ 29
#define UART0IRQ 194
#define EMAC1IRQ 152
+#define FPGAMGRIRQ 207
+#define DMAIRQ0 136
+#define DMAABORTIRQ 144
#define LEVEL 0
#define EDGE 1
--- a/sys/src/9/cycv/l.s
+++ b/sys/src/9/cycv/l.s
@@ -37,7 +37,7 @@
_clrstart:
MOVW.P R0, 4(R1)
CMP.S R1, R2
- BGE _clrstart
+ BGT _clrstart
/* clean BSS */
MOVW $edata-KZERO(SB), R1
@@ -45,7 +45,7 @@
_clrbss:
MOVW.P R0, 4(R1)
CMP.S R1, R2
- BGE _clrbss
+ BGT _clrbss
PUTC('a')