cyclone v kernel: fpga support, fix CONFADDR
parent
7cf8369411
commit
561346d07f
|
@ -2,7 +2,7 @@ dev
|
||||||
root
|
root
|
||||||
cons
|
cons
|
||||||
swap
|
swap
|
||||||
# arch
|
arch
|
||||||
uart
|
uart
|
||||||
mnt
|
mnt
|
||||||
srv
|
srv
|
||||||
|
@ -24,6 +24,7 @@ dev
|
||||||
segment
|
segment
|
||||||
|
|
||||||
link
|
link
|
||||||
|
dma
|
||||||
ethercycv
|
ethercycv
|
||||||
ethermedium
|
ethermedium
|
||||||
loopbackmedium
|
loopbackmedium
|
||||||
|
|
|
@ -13,6 +13,7 @@ typedef struct Proc Proc;
|
||||||
typedef struct PMMU PMMU;
|
typedef struct PMMU PMMU;
|
||||||
typedef struct Ureg Ureg;
|
typedef struct Ureg Ureg;
|
||||||
typedef struct ISAConf ISAConf;
|
typedef struct ISAConf ISAConf;
|
||||||
|
typedef struct DMAC DMAC;
|
||||||
typedef uvlong Tval;
|
typedef uvlong Tval;
|
||||||
|
|
||||||
#pragma incomplete Ureg
|
#pragma incomplete Ureg
|
||||||
|
@ -202,3 +203,7 @@ struct DevConf
|
||||||
#define mpcore ((ulong*)MPCORE_BASE)
|
#define mpcore ((ulong*)MPCORE_BASE)
|
||||||
#define resetmgr ((ulong*)RESETMGR_BASE)
|
#define resetmgr ((ulong*)RESETMGR_BASE)
|
||||||
#define sysmgr ((ulong*)SYSMGR_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 "ureg.h"
|
||||||
#include "../port/error.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 {
|
enum {
|
||||||
Qdir = 0,
|
Qdir = 0,
|
||||||
Qtemp,
|
Qfpga,
|
||||||
Qpl,
|
|
||||||
Qfbctl,
|
|
||||||
Qbase,
|
Qbase,
|
||||||
|
|
||||||
Qmax = 16,
|
Qmax = 16,
|
||||||
|
@ -19,288 +52,149 @@ enum {
|
||||||
|
|
||||||
static Dirtab archdir[Qmax] = {
|
static Dirtab archdir[Qmax] = {
|
||||||
".", { Qdir, 0, QTDIR }, 0, 0555,
|
".", { Qdir, 0, QTDIR }, 0, 0555,
|
||||||
"temp", { Qtemp, 0}, 0, 0440,
|
"fpga", { Qfpga, 0 }, 0, 0660,
|
||||||
"pl", { Qpl, 0 }, 0, 0660,
|
|
||||||
"fbctl", { Qfbctl, 0 }, 0, 0660,
|
|
||||||
};
|
};
|
||||||
static int narchdir = Qbase;
|
static int narchdir = Qbase;
|
||||||
|
|
||||||
static int temp = -128;
|
static Ref fpgawopen;
|
||||||
static ulong *devc;
|
enum { FPGABUFSIZ = 65536 };
|
||||||
static int dmadone;
|
static uchar *fpgabuf;
|
||||||
enum { PLBUFSIZ = 8192 };
|
static int fpgabufp;
|
||||||
static uchar *plbuf;
|
static int fpgaok;
|
||||||
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 Rendez fpgarend;
|
||||||
|
static u32int fpgawaitset, fpgawaitclr;
|
||||||
static int
|
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
|
static int
|
||||||
ispldone(void *)
|
fpgawait(u32int set, u32int clr, int timeout)
|
||||||
{
|
{
|
||||||
return devc[DEVISTS] & DONE;
|
int s;
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
fpgawaitset = set;
|
||||||
isdmadone(void *)
|
fpgawaitclr = clr;
|
||||||
{
|
if(donewaiting(nil)) return 0;
|
||||||
return dmadone;
|
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
|
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((fpga[FPGAPINS] & FPGA_POWER_ON) == 0)
|
||||||
if((fl & INITPE) != 0)
|
error("FPGA powered off");
|
||||||
wakeup(&plinitr);
|
msel = fpga[FPGASTAT] >> 3 & 0x1f;
|
||||||
if((fl & DONE) != 0){
|
if(msel >= 16 || mseltab[msel][1] == 0){
|
||||||
slcr[0x900/4] = 0xf;
|
print("MSEL set to invalid setting %#.2x\n", msel);
|
||||||
slcr[0x240/4] = 0;
|
error("MSEL set to invalid setting");
|
||||||
devc[DEVMASK] |= DONE;
|
|
||||||
axi->attr &= ~SG_FAULT;
|
|
||||||
wakeup(&pldoner);
|
|
||||||
}
|
}
|
||||||
if((fl & DMADONE) != 0){
|
fpga[FPGACTRL] = fpga[FPGACTRL] & ~0x3ff
|
||||||
dmadone++;
|
| mseltab[msel][0] << 9 /* cfgwdth */
|
||||||
wakeup(&pldmar);
|
| mseltab[msel][1]-1 << 6 /* cdratio */
|
||||||
}
|
| NCONFIGPULL | HPSCONFIG;
|
||||||
devc[DEVISTS] = fl;
|
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
|
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()){
|
if(waserror()){
|
||||||
qunlock(&plwlock);
|
fpgaok = 0;
|
||||||
nexterror();
|
nexterror();
|
||||||
}
|
}
|
||||||
|
if((fpga[FPGAPINS] & NSTATUS) == 0)
|
||||||
ret = n;
|
error("FPGA reports configuration error");
|
||||||
pa = PADDR(plbuf);
|
fpgaok = 1;
|
||||||
while(n > 0){
|
while(fpgabufp + n >= FPGABUFSIZ){
|
||||||
if(n > PLBUFSIZ)
|
m = FPGABUFSIZ - fpgabufp;
|
||||||
nn = PLBUFSIZ;
|
memmove(&fpgabuf[fpgabufp], a, m);
|
||||||
else
|
cleandse(fpgabuf, fpgabuf + FPGABUFSIZ);
|
||||||
nn = n;
|
dmacopy((void *) FPGAMGRDATA, fpgabuf, FPGABUFSIZ, SRC_INC);
|
||||||
memmove(plbuf, d, nn);
|
a += m;
|
||||||
cleandse(plbuf, plbuf + nn);
|
n -= m;
|
||||||
clean2pa(pa, pa + nn);
|
fpgabufp = 0;
|
||||||
n -= plwrite(pa, nn);
|
|
||||||
}
|
}
|
||||||
|
memmove(&fpgabuf[fpgabufp], a, n);
|
||||||
qunlock(&plwlock);
|
fpgabufp += n;
|
||||||
poperror();
|
poperror();
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
archinit(void)
|
fpgafinish(void)
|
||||||
{
|
{
|
||||||
slcr[2] = 0xDF0D;
|
if(!fpgaok) return;
|
||||||
xadcinit();
|
while((fpgabufp & 3) != 0)
|
||||||
plinit();
|
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
|
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){
|
switch((ulong)c->qid.path){
|
||||||
case Qdir:
|
case Qdir:
|
||||||
return devdirread(c, a, n, archdir, narchdir, devgen);
|
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:
|
default:
|
||||||
error(Egreg);
|
error(Egreg);
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -308,13 +202,12 @@ archread(Chan *c, void *a, long n, vlong offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
static long
|
static long
|
||||||
archwrite(Chan *c, void *a, long n, vlong offset)
|
archwrite(Chan *c, void *a, long n, vlong)
|
||||||
{
|
{
|
||||||
switch((ulong)c->qid.path){
|
switch((ulong)c->qid.path){
|
||||||
case Qpl:
|
case Qfpga:
|
||||||
return plcopy(a, n);
|
fpgawrite(a, n);
|
||||||
case Qfbctl:
|
return n;
|
||||||
return fbctlwrite(c, a, n, offset);
|
|
||||||
default:
|
default:
|
||||||
error(Egreg);
|
error(Egreg);
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -337,14 +230,16 @@ static Chan*
|
||||||
archopen(Chan* c, int omode)
|
archopen(Chan* c, int omode)
|
||||||
{
|
{
|
||||||
devopen(c, omode, archdir, narchdir, devgen);
|
devopen(c, omode, archdir, narchdir, devgen);
|
||||||
if((ulong)c->qid.path == Qpl && (c->mode == OWRITE || c->mode == ORDWR)){
|
if((ulong)c->qid.path == Qfpga && (c->mode == OWRITE || c->mode == ORDWR)){
|
||||||
if(incref(&plwopen) != 1){
|
if(incref(&fpgawopen) != 1){
|
||||||
c->flag &= ~COPEN;
|
c->flag &= ~COPEN;
|
||||||
decref(&plwopen);
|
decref(&fpgawopen);
|
||||||
error(Einuse);
|
error(Einuse);
|
||||||
}
|
}
|
||||||
plbuf = smalloc(PLBUFSIZ);
|
fpgaok = 0;
|
||||||
plconf();
|
fpgaconf();
|
||||||
|
fpgabuf = xspanalloc(FPGABUFSIZ, 64, 0);
|
||||||
|
fpgabufp = 0;
|
||||||
}
|
}
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
@ -353,13 +248,23 @@ static void
|
||||||
archclose(Chan* c)
|
archclose(Chan* c)
|
||||||
{
|
{
|
||||||
if((c->flag & COPEN) != 0)
|
if((c->flag & COPEN) != 0)
|
||||||
if((ulong)c->qid.path == Qpl && (c->mode == OWRITE || c->mode == ORDWR)){
|
if((ulong)c->qid.path == Qfpga && (c->mode == OWRITE || c->mode == ORDWR)){
|
||||||
free(plbuf);
|
fpgafinish();
|
||||||
plbuf = nil;
|
//xfree(fpgabuf);
|
||||||
decref(&plwopen);
|
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*
|
static Chan*
|
||||||
archattach(char* spec)
|
archattach(char* spec)
|
||||||
{
|
{
|
||||||
|
@ -370,7 +275,7 @@ Dev archdevtab = {
|
||||||
'P',
|
'P',
|
||||||
"arch",
|
"arch",
|
||||||
|
|
||||||
devreset,
|
archreset,
|
||||||
devinit,
|
devinit,
|
||||||
devshutdown,
|
devshutdown,
|
||||||
archattach,
|
archattach,
|
||||||
|
|
|
@ -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];
|
r = &c->rxr[4 * c->rxconsi];
|
||||||
if((r[0] >> 31) != 0)
|
if((r[0] >> 31) != 0)
|
||||||
break;
|
break;
|
||||||
if((r[0] & 1<<15) != 0)
|
|
||||||
iprint("eth: error frame\n");
|
|
||||||
if((r[0] & (3<<8)) != (3<<8))
|
if((r[0] & (3<<8)) != (3<<8))
|
||||||
iprint("eth: lilu dallas multidescriptor\n");
|
iprint("eth: lilu dallas multidescriptor\n");
|
||||||
bp = c->rxs[c->rxconsi];
|
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
|
static int
|
||||||
etherpnp(Ether *edev)
|
etherpnp(Ether *edev)
|
||||||
{
|
{
|
||||||
|
@ -425,6 +455,7 @@ etherpnp(Ether *edev)
|
||||||
edev->mbps = 1000;
|
edev->mbps = 1000;
|
||||||
edev->promiscuous = ethprom;
|
edev->promiscuous = ethprom;
|
||||||
edev->multicast = ethmcast;
|
edev->multicast = ethmcast;
|
||||||
|
edev->ifstat = ethifstat;
|
||||||
|
|
||||||
if(ethinit(edev) < 0){
|
if(ethinit(edev) < 0){
|
||||||
edev->ctlr = nil;
|
edev->ctlr = nil;
|
||||||
|
|
|
@ -76,3 +76,4 @@ uintptr palookur(void *);
|
||||||
void screeninit(void);
|
void screeninit(void);
|
||||||
int isaconfig(char*, int, ISAConf*);
|
int isaconfig(char*, int, ISAConf*);
|
||||||
void cputhex(u32int);
|
void cputhex(u32int);
|
||||||
|
void dmacopy(void *, void *, ulong, int);
|
||||||
|
|
|
@ -5,7 +5,10 @@
|
||||||
#define EMAC1_BASE 0xFF702000
|
#define EMAC1_BASE 0xFF702000
|
||||||
#define RESETMGR_BASE 0xFFD05000
|
#define RESETMGR_BASE 0xFFD05000
|
||||||
#define SYSMGR_BASE 0xFFD08000
|
#define SYSMGR_BASE 0xFFD08000
|
||||||
|
#define FPGAMGR_BASE 0xFF706000
|
||||||
|
#define FPGAMGRDATA 0xFFB90000
|
||||||
#define OCRAM 0xFFFF0000
|
#define OCRAM 0xFFFF0000
|
||||||
|
#define DMAS_BASE 0xFFE01000
|
||||||
|
|
||||||
/*RESETMGR*/
|
/*RESETMGR*/
|
||||||
#define PERMODRST (0x14/4)
|
#define PERMODRST (0x14/4)
|
||||||
|
@ -17,6 +20,9 @@
|
||||||
#define TIMERIRQ 29
|
#define TIMERIRQ 29
|
||||||
#define UART0IRQ 194
|
#define UART0IRQ 194
|
||||||
#define EMAC1IRQ 152
|
#define EMAC1IRQ 152
|
||||||
|
#define FPGAMGRIRQ 207
|
||||||
|
#define DMAIRQ0 136
|
||||||
|
#define DMAABORTIRQ 144
|
||||||
|
|
||||||
#define LEVEL 0
|
#define LEVEL 0
|
||||||
#define EDGE 1
|
#define EDGE 1
|
||||||
|
|
|
@ -37,7 +37,7 @@ TEXT _start0(SB), $-4
|
||||||
_clrstart:
|
_clrstart:
|
||||||
MOVW.P R0, 4(R1)
|
MOVW.P R0, 4(R1)
|
||||||
CMP.S R1, R2
|
CMP.S R1, R2
|
||||||
BGE _clrstart
|
BGT _clrstart
|
||||||
|
|
||||||
/* clean BSS */
|
/* clean BSS */
|
||||||
MOVW $edata-KZERO(SB), R1
|
MOVW $edata-KZERO(SB), R1
|
||||||
|
@ -45,7 +45,7 @@ _clrstart:
|
||||||
_clrbss:
|
_clrbss:
|
||||||
MOVW.P R0, 4(R1)
|
MOVW.P R0, 4(R1)
|
||||||
CMP.S R1, R2
|
CMP.S R1, R2
|
||||||
BGE _clrbss
|
BGT _clrbss
|
||||||
|
|
||||||
PUTC('a')
|
PUTC('a')
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue