cyclone v kernel: fpga support, fix CONFADDR
This commit is contained in:
parent
7cf8369411
commit
561346d07f
8 changed files with 483 additions and 269 deletions
|
@ -2,7 +2,7 @@ dev
|
|||
root
|
||||
cons
|
||||
swap
|
||||
# arch
|
||||
arch
|
||||
uart
|
||||
mnt
|
||||
srv
|
||||
|
@ -24,6 +24,7 @@ dev
|
|||
segment
|
||||
|
||||
link
|
||||
dma
|
||||
ethercycv
|
||||
ethermedium
|
||||
loopbackmedium
|
||||
|
|
|
@ -13,6 +13,7 @@ typedef struct Proc Proc;
|
|||
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 @@ struct DevConf
|
|||
#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)
|
||||
|
|
|
@ -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 @@ enum {
|
|||
|
||||
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;
|
||||
|
||||
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)
|
||||
{
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static void
|
||||
xadctimer(void)
|
||||
{
|
||||
devc[XADCCMD] = 1<<26 | 0<<16;
|
||||
}
|
||||
|
||||
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 Ref fpgawopen;
|
||||
enum { FPGABUFSIZ = 65536 };
|
||||
static uchar *fpgabuf;
|
||||
static int fpgabufp;
|
||||
static int fpgaok;
|
||||
|
||||
static Rendez fpgarend;
|
||||
static u32int fpgawaitset, fpgawaitclr;
|
||||
static int
|
||||
isplinit(void *)
|
||||
donewaiting(void *)
|
||||
{
|
||||
return devc[DEVSTS] & INIT;
|
||||
u32int s;
|
||||
|
||||
s = fpga[FPGAPINS];
|
||||
return (s & fpgawaitset | ~s & fpgawaitclr) != 0;
|
||||
|
||||
}
|
||||
static void
|
||||
fpgairq(Ureg *, void *)
|
||||
{
|
||||
fpga[FPGAEOI] = -1;
|
||||
if(donewaiting(nil))
|
||||
wakeup(&fpgarend);
|
||||
}
|
||||
|
||||
static int
|
||||
ispldone(void *)
|
||||
fpgawait(u32int set, u32int clr, int timeout)
|
||||
{
|
||||
return devc[DEVISTS] & DONE;
|
||||
}
|
||||
int s;
|
||||
|
||||
static int
|
||||
isdmadone(void *)
|
||||
{
|
||||
return dmadone;
|
||||
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 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 @@ archread(Chan *c, void *a, long n, vlong offset)
|
|||
}
|
||||
|
||||
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 @@ static Chan*
|
|||
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 @@ static void
|
|||
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 @@ Dev archdevtab = {
|
|||
'P',
|
||||
"arch",
|
||||
|
||||
devreset,
|
||||
archreset,
|
||||
devinit,
|
||||
devshutdown,
|
||||
archattach,
|
||||
|
|
265
sys/src/9/cycv/dma.c
Normal file
265
sys/src/9/cycv/dma.c
Normal file
|
@ -0,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");
|
||||
}
|
|
@ -199,8 +199,6 @@ ethrx(Ether *edev)
|
|||
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 @@ ethmcast(void *arg, uchar *ea, int on)
|
|||
}
|
||||
}
|
||||
|
||||
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 @@ etherpnp(Ether *edev)
|
|||
edev->mbps = 1000;
|
||||
edev->promiscuous = ethprom;
|
||||
edev->multicast = ethmcast;
|
||||
edev->ifstat = ethifstat;
|
||||
|
||||
if(ethinit(edev) < 0){
|
||||
edev->ctlr = nil;
|
||||
|
|
|
@ -76,3 +76,4 @@ uintptr palookur(void *);
|
|||
void screeninit(void);
|
||||
int isaconfig(char*, int, ISAConf*);
|
||||
void cputhex(u32int);
|
||||
void dmacopy(void *, void *, ulong, int);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -37,7 +37,7 @@ TEXT _start0(SB), $-4
|
|||
_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 @@ _clrstart:
|
|||
_clrbss:
|
||||
MOVW.P R0, 4(R1)
|
||||
CMP.S R1, R2
|
||||
BGE _clrbss
|
||||
BGT _clrbss
|
||||
|
||||
PUTC('a')
|
||||
|
||||
|
|
Loading…
Reference in a new issue