This commit is contained in:
cinap_lenrek 2011-11-05 11:06:58 +01:00
commit 875e89b8fa
14 changed files with 409 additions and 71 deletions

View file

@ -21,6 +21,8 @@
#define PsrDfiq 0x00000040 /* disable FIQ interrupts */
#define PsrDirq 0x00000080 /* disable IRQ interrupts */
#define PsrOK 0xF80F0000 /* user processes may touch these */
#define PsrV 0x10000000 /* overflow */
#define PsrC 0x20000000 /* carry/borrow/extend */
#define PsrZ 0x40000000 /* zero */

View file

@ -65,7 +65,7 @@ perfticks(void)
}
void
clocktick(Ureg* ureg)
clocktick(Ureg* ureg, void *)
{
timerintr(ureg, 0);
}
@ -74,7 +74,7 @@ void
localclockinit(void)
{
local[2] = 0xFF06;
intenable(29, clocktick);
intenable(29, clocktick, nil);
timerset(0);
}

View file

@ -8,6 +8,7 @@ typedef struct PMMU PMMU;
typedef struct Confmem Confmem;
typedef struct Conf Conf;
typedef struct Proc Proc;
typedef struct ISAConf ISAConf;
typedef uvlong Tval;
typedef void KMap;
#define VA(k) ((uintptr)(k))
@ -142,3 +143,9 @@ extern uintptr kseg0;
#define AOUT_MAGIC (E_MAGIC)
#define NCOLOR 1
struct ISAConf
{
char *type;
ulong port, irq;
};

View file

@ -33,7 +33,9 @@ void touser(Ureg*);
void links(void);
void globalclockinit(void);
void localclockinit(void);
void intenable(int, void(*)(Ureg*));
void setled(int, int);
void intenable(int, void(*)(Ureg*, void *), void *);
void uartinit(void);
void irqroute(int, void(*)(Ureg*));
void irqroute(int, void(*)(Ureg*, void *), void *);
void gpioinit(void);
void setgpio(int, int);
void gpiomode(int, int);

View file

@ -51,7 +51,7 @@ uartloop:
EWAVE('n')
MRC CpSC, 0, R1, C(CpCONTROL), C(0), CpMainctl
ORR $(CpCmmu|CpChv|CpCsw), R1
ORR $(CpCmmu|CpChv|CpCsw|CpCicache), R1
MCR CpSC, 0, R1, C(CpCONTROL), C(0), CpMainctl
EWAVE(' ')
@ -59,7 +59,7 @@ uartloop:
BL _jumphi(SB)
EWAVE('9')
MOVW $setR12(SB), R12
MOVW $KTZERO, R13

View file

@ -147,12 +147,15 @@ userinit(void)
void
main()
{
extern int ehcidebug;
wave('f');
memset(edata, 0, end - edata);
wave('r');
machinit();
wave('o');
mmuinit();
gpioinit();
wave('m');
trapinit();
uartinit();
@ -166,8 +169,9 @@ main()
swapinit();
initseg();
quotefmtinstall();
chandevreset();
ehcidebug = 1;
links();
chandevreset();
userinit();
schedinit();
}

View file

@ -37,6 +37,7 @@
#define MAXSYSARG 7
#define MAXMACH 2
#define BI2BY 8
#define BY2WD 4
#define BY2V 8
#define BY2PG 4096

View file

@ -19,6 +19,7 @@ PORT=\
dev.$O\
edf.$O\
fault.$O\
gpio.$O\
mul64fract.$O\
rebootcmd.$O\
page.$O\

View file

@ -9,7 +9,6 @@
char iopages[NIOPAGES / 8];
Lock iopagelock;
uchar *periph;
ulong *ledgpio;
static int
isfree(int i)
@ -95,19 +94,10 @@ vunmap(void *virt, ulong length)
flushtlb();
}
void
setled(int n, int s)
{
ulong *r;
r = &ledgpio[0x190/4];
r[s != 0] = (1 << (7 + n));
}
void
markidle(int n)
{
setled(m->machno, !n);
setgpio(7 + m->machno, !n);
}
void
@ -126,7 +116,6 @@ mmuinit(void)
l2 += L2SIZ;
}
uart = vmap((ulong) uart, BY2PG);
ledgpio = vmap(0x4A310000, BY2PG);
periph = vmap(0x48240000, 2 * BY2PG);
memset(l1, 0, sizeof(ulong) * (IZERO / MiB));
l1[4095] = PRIVL2 | Coarse;
@ -137,9 +126,6 @@ mmuinit(void)
pl2[241] = FIRSTMACH | L2AP(Krw) | Small | Cached | Buffered;
flushtlb();
m = (Mach *) MACHADDR;
ledgpio[0x134/4] &= ~((1<<8)|(1<<7));
setled(0, 1);
setled(1, 1);
}
void

View file

@ -22,35 +22,34 @@ dev
# flash
# ether netif
# ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium ptclbsum inferno
ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium ptclbsum inferno
# draw screen
# dss
# mouse
uart
# usb
usb
link
# archoma
# ethermedium
ethermedium
# flashigep
# loopbackmedium
# netdevmedium
netdevmedium
## avoid tickling errata 3.1.1.183
## usbohci
# usbehci usbehciomap
# usbohci
usbehci usbehciomap
ip
# tcp
# udp
# ipifc
# icmp
# icmp6
# ipmux
# gre
# esp
tcp
udp
ipifc
icmp
icmp6
ipmux
gre
esp
misc
# rdb

View file

@ -12,7 +12,8 @@
extern uchar *periph;
ulong *intc, *intd;
void (*irqhandler[MAXMACH][256])(Ureg*);
void (*irqhandler[MAXMACH][256])(Ureg *, void *);
void *irqaux[MAXMACH][256];
static char *trapname[] = {
"reset", /* wtf */
@ -20,7 +21,6 @@ static char *trapname[] = {
"supervisor call",
"prefetch abort",
"data abort",
"unknown trap",
"IRQ",
"FIQ",
};
@ -52,24 +52,28 @@ trapinit(void)
}
void
intenable(int i, void (*fn)(Ureg *))
intenable(int i, void (*fn)(Ureg *, void *), void *aux)
{
intd[0x40 + (i / 32)] = 1 << (i % 32);
irqhandler[m->machno][i] = fn;
irqaux[m->machno][i] = aux;
}
void
irqroute(int i, void (*fn)(Ureg *))
irqroute(int i, void (*fn)(Ureg *, void *), void *aux)
{
ulong x, y, z;
intenable(32 + i, fn);
if(irqhandler[m->machno][i] != nil){
print("irqroute: irq already used: i=%d pc=%#p newfn=%#p oldfn=%#p\n", i, getcallerpc(&i), fn, irqhandler[m->machno][i]);
return;
}
intenable(32 + i, fn, aux);
x = intd[0x208 + i/4];
y = 0xFF << ((i%4) * 8);
z = 1 << (m->machno + (i%4) * 8);
x = (x & ~y) | z;
intd[0x208 + i/4] = x;
// intd[0x200/4 + (i+32)/32] = 1 << (i % 32);
}
void
@ -128,12 +132,139 @@ updatetos(void)
tos->pid = up->pid;
}
int
notify(Ureg *ureg)
{
int l;
ulong s, sp;
Note *n;
if(up->procctl)
procctl(up);
if(up->nnote == 0)
return 0;
s = spllo();
qlock(&up->debug);
up->notepending = 0;
n = &up->note[0];
if(strncmp(n->msg, "sys:", 4) == 0){
l = strlen(n->msg);
if(l > ERRMAX-15)
l = ERRMAX-15;
sprint(n->msg + l, " pc=0x%.8lux", ureg->pc);
}
if(n->flag != NUser && (up->notified || up->notify == 0)){
if(n->flag == NDebug)
pprint("suicide: %s\n", n->msg);
qunlock(&up->debug);
pexit(n->msg, n->flag != NDebug);
}
if(up->notified){
qunlock(&up->debug);
splhi();
return 0;
}
if(!up->notify){
qunlock(&up->debug);
pexit(n->msg, n->flag != NDebug);
}
sp = ureg->sp;
sp -= 256 + sizeof(Ureg);
if(!okaddr((ulong)up->notify, 1, 0)
|| !okaddr(sp - ERRMAX - 4 * BY2WD, sizeof(Ureg) + ERRMAX + 4 * BY2WD, 1)){
qunlock(&up->debug);
pprint("suicide: bad address in notify\n");
pexit("Suicide", 0);
}
memmove((void *) sp, ureg, sizeof(Ureg));
((void**)sp)[-1] = up->ureg;
up->ureg = (void *) sp;
sp -= BY2WD + ERRMAX;
memmove((void *) sp, up->note[0].msg, ERRMAX);
sp -= 3 * BY2WD;
((ulong*)sp)[2] = sp + 3 * BY2WD;
((Ureg**)sp)[1] = up->ureg;
((ulong*)sp)[0] = 0;
memset(ureg, 0, sizeof *ureg);
ureg->psr = PsrMusr;
ureg->sp = sp;
ureg->pc = (ulong) up->notify;
up->notified = 1;
up->nnote--;
memmove(&up->lastnote, &up->note[0], sizeof(Note));
memmove(&up->note[0], &up->note[1], up->nnote * sizeof(Note));
qunlock(&up->debug);
splx(s);
return 1;
}
void
noted(Ureg *ureg, ulong arg0)
{
Ureg *nureg;
ulong oureg, sp;
qlock(&up->debug);
if(arg0 != NRSTR && !up->notified){
qunlock(&up->debug);
pprint("call to noted() when not notified\n");
pexit("Suicide", 0);
}
up->notified = 0;
nureg = up->ureg;
oureg = (ulong) nureg;
if(!okaddr((ulong) oureg - BY2WD, BY2WD + sizeof(Ureg), 0)){
qunlock(&up->debug);
pprint("bad ureg in noted or call to noted when not notified\n");
pexit("Suicide", 0);
}
nureg->psr = nureg->psr & PsrOK | ureg->psr & ~PsrOK;
memmove(ureg, nureg, sizeof(Ureg));
if(!okaddr(nureg->pc, 1, 0) && !okaddr(nureg->sp, BY2WD, 0)
&& (arg0 == NCONT || arg0 == NRSTR || arg0 == NSAVE)){
qunlock(&up->debug);
pprint("suicide: trap in noted\n");
pexit("Suicide", 0);
}
switch(arg0){
case NCONT:
case NRSTR:
up->ureg = (Ureg *) (*(ulong *)(oureg - BY2WD));
qunlock(&up->debug);
break;
case NSAVE:
qunlock(&up->debug);
sp = oureg - 4 * BY2WD - ERRMAX;
splhi();
ureg->sp = sp;
((ulong *) sp)[1] = oureg;
((ulong *) sp)[0] = 0;
break;
default:
pprint("unknown noted arg 0x%lux\n", arg0);
up->lastnote.flag = NDebug;
/* fallthrough */
case NDFLT:
qunlock(&up->debug);
if(up->lastnote.flag == NDebug)
pprint("suicide: %s\n", up->lastnote.msg);
pexit(up->lastnote.msg, up->lastnote.flag != NDebug);
}
}
void
trap(Ureg *ureg)
{
int user, intn, x;
char buf[ERRMAX];
user = (ureg->psr & PsrMask) == PsrMusr;
if(user){
fillureguser(ureg);
@ -149,10 +280,13 @@ trap(Ureg *ureg)
x = intc[3];
intn = x & 0x3FF;
if(irqhandler[m->machno][intn] != nil)
irqhandler[m->machno][intn](ureg);
irqhandler[m->machno][intn](ureg, irqaux[m->machno][intn]);
else
print("unexpected interrupt %d\n", intn);
intc[4] = x;
if(intn != 29)
preempted();
splhi();
if(up && up->delaysched && (intn == 29)){
sched();
splhi();
@ -170,6 +304,8 @@ trap(Ureg *ureg)
}
}
if(user){
if(up->procctl || up->nnote)
notify(ureg);
updatetos();
up->dbgreg = nil;
}
@ -193,7 +329,6 @@ syscall(Ureg *ureg)
}
scall = ureg->r0;
up->scallnr = scall;
// print("%s\n", sysctab[scall]);
spllo();
sp = ureg->sp;
@ -224,8 +359,16 @@ syscall(Ureg *ureg)
procctl(up);
splx(s);
}
up->insyscall = 0;
up->psstate = nil;
if(scall == NOTED)
noted(ureg, *(ulong *)(sp + BY2WD));
if(scall != RFORK && (up->procctl || up->nnote)){
splhi();
notify(ureg);
}
splhi();
if(up->delaysched){
sched();

View file

@ -24,20 +24,23 @@ omappnp(void)
static void
omapkick(Uart *u)
{
int x;
x = splhi();
while((uart[17] & 1) == 0){
if(u->op >= u->oe)
if(uartstageoutput(u) == 0)
if(uartstageoutput(u) == 0){
uart[1] &= ~(1<<1);
break;
}
uart[0] = *u->op++;
}
if(u->op < u->oe || qlen(u->oq))
uart[1] |= (1<<1);
else
uart[1] &= ~(1<<1);
}
splx(x);
}
void
omapinterrupt(Ureg *)
omapinterrupt(Ureg *, void *)
{
ulong st;
@ -45,6 +48,12 @@ omapinterrupt(Ureg *)
if((st & 1) != 0)
return;
switch((st >> 1) & 0x1F){
case 0:
case 16:
puart.cts = (uart[6] & (1<<4)) != 0;
puart.dsr = (uart[6] & (1<<5)) != 0;
puart.dcd = (uart[6] & (1<<7)) != 0;
break;
case 1:
uartkick(&puart);
break;
@ -54,23 +63,164 @@ omapinterrupt(Ureg *)
uartrecv(&puart, uart[0]);
break;
default:
print("unknown UART interrupt %d\n", (st>>1) & 0x1F);
print("unknown UART interrupt %uld\n", (st>>1) & 0x1F);
uartkick(&puart);
}
}
static void
omapenable(Uart *, int ie)
omapenable(Uart *u, int ie)
{
while(uart[5] & (1<<6))
;
if(ie){
irqroute(74, omapinterrupt);
irqroute(74, omapinterrupt, u);
uart[1] = (1<<0);
// uart[0x10] |= (1<<3);
}
}
static void
omapdisable(Uart *)
{
uart[1] = 0;
}
static void
omapdobreak(Uart *, int ms)
{
if(ms <= 0)
ms = 200;
uart[3] |= (1<<6);
tsleep(&up->sleep, return0, 0, ms);
uart[3] &= ~(1<<6);
}
static int
omapbaud(Uart *u, int baud)
{
int val;
if(baud <= 0)
return -1;
val = (48000000 / 16) / baud;
uart[3] |= (1<<7);
uart[0] = val & 0xFF;
uart[1] = (val >> 8) & 0xFF;
uart[3] &= ~(1<<7);
u->baud = baud;
return 0;
}
static int
omapbits(Uart *u, int bits)
{
if(bits < 5 || bits > 8)
return -1;
uart[3] = (uart[3] & ~3) | (bits - 5);
u->bits = bits;
return 0;
}
static int
omapstop(Uart *u, int stop)
{
if(stop < 1 || stop > 2)
return -1;
uart[3] &= ~4;
if(stop == 2)
uart[3] |= 4;
u->stop = stop;
return 0;
}
static int
omapparity(Uart *u, int parity)
{
uart[3] &= ~0x38;
switch(parity){
case 'n':
break;
case 'o':
uart[3] |= (1<<3);
case 'e':
uart[3] |= (1<<3) | (1<<4);
break;
default:
return -1;
}
u->parity = parity;
return 0;
}
static void
omapmodemctl(Uart *u, int on)
{
if(on){
u->modem = 1;
u->cts = (uart[6] & (1<<4)) != 0;
uart[1] |= (1<<6);
}else{
u->modem = 0;
u->cts = 1;
}
}
static void
omaprts(Uart *, int i)
{
uart[4] = (uart[4] & ~2) | (i << 1);
}
static void
omapdtr(Uart *, int i)
{
uart[4] = (uart[4] & ~1) | i;
}
static long
omapstatus(Uart* u, void* buf, long n, long offset)
{
char *p;
ulong msr;
msr = uart[6];
p = malloc(READSTR);
snprint(p, READSTR,
"b%d c%d d%d e%d l%d m%d p%c r%d s%d\n"
"dev(%d) type(%d) framing(%d) overruns(%d) "
"berr(%d) serr(%d)%s%s%s%s\n",
u->baud,
u->hup_dcd,
u->dsr,
u->hup_dsr,
u->bits,
u->modem,
u->parity,
(uart[3] & 2) != 0,
u->stop,
u->dev,
u->type,
u->ferr,
u->oerr,
u->berr,
u->serr,
(msr & (1<<4)) ? " cts": "",
(msr & (1<<5)) ? " dsr": "",
(msr & (1<<7)) ? " dcd": "",
(msr & (1<<6)) ? " ri": ""
);
n = readstr(offset, buf, n, p);
free(p);
return n;
}
static int
omapgetc(Uart *)
{
@ -87,19 +237,22 @@ omapputc(Uart *, int c)
uart[0] = c;
}
static void
omaprts(Uart *, int)
{
}
PhysUart omapphysuart = {
.name = "omap4430 uart",
.pnp = omappnp,
.getc = omapgetc,
.putc = omapputc,
.enable = omapenable,
.disable = omapdisable,
.kick = omapkick,
.rts = omaprts,
.parity = omapparity,
.baud = omapbaud,
.bits = omapbits,
.stop = omapstop,
.modemctl = omapmodemctl,
.dtr = omapdtr,
.status = omapstatus,
};
void

View file

@ -425,7 +425,7 @@ bcminterrupt(Ureg*, void *arg)
iunlock(&ctlr->imlock);
}
static void
static int
bcminit(Ether *edev)
{
ulong i, j;
@ -436,7 +436,12 @@ bcminit(Ether *edev)
/* initialization procedure according to the datasheet */
csr32(ctlr, MiscHostCtl) |= MaskPCIInt | ClearIntA;
csr32(ctlr, SwArbitration) |= SwArbitSet1;
while((csr32(ctlr, SwArbitration) & SwArbitWon1) == 0);
for(i = 0; i < 10000 && (csr32(ctlr, SwArbitration) & SwArbitWon1) == 0; i++)
microdelay(100);
if(i == 10000){
iprint("bcm: arbiter failed to respond\n");
return -1;
}
csr32(ctlr, MemArbiterMode) |= Enable;
csr32(ctlr, MiscHostCtl) |= IndirectAccessEnable | EnablePCIStateRegister | EnableClockControlRegister;
csr32(ctlr, MemoryWindow) = 0;
@ -452,7 +457,12 @@ bcminit(Ether *edev)
csr32(ctlr, ModeControl) |= ByteWordSwap;
csr32(ctlr, MACMode) = (csr32(ctlr, MACMode) & MACPortMask) | MACPortGMII;
microdelay(40000);
while(mem32(ctlr, 0xB50) != 0xB49A89AB);
for(i = 0; i < 100000 && mem32(ctlr, 0xB50) != 0xB49A89AB; i++)
microdelay(100);
if(i == 100000){
iprint("bcm: chip failed to reset\n");
return -1;
}
csr32(ctlr, TLPControl) |= (1<<25) | (1<<29);
memset(ctlr->status, 0, 20);
csr32(ctlr, DMARWControl) = (csr32(ctlr, DMARWControl) & DMAWatermarkMask) | DMAWatermarkValue;
@ -462,10 +472,20 @@ bcminit(Ether *edev)
csr32(ctlr, MBUFHighWatermark) = 0x60;
csr32(ctlr, LowWatermarkMaximum) = (csr32(ctlr, LowWatermarkMaximum) & LowWatermarkMaxMask) | LowWatermarkMaxValue;
csr32(ctlr, BufferManMode) |= Enable | Attn;
while((csr32(ctlr, BufferManMode) & Enable) == 0);
for(i = 0; i < 100 && (csr32(ctlr, BufferManMode) & Enable) == 0; i++)
microdelay(100);
if(i == 100){
iprint("bcm: buffer manager failed to start\n");
return -1;
}
csr32(ctlr, FTQReset) = -1;
csr32(ctlr, FTQReset) = 0;
while(csr32(ctlr, FTQReset));
for(i = 0; i < 1000 && csr32(ctlr, FTQReset) != 0; i++)
microdelay(100);
if(i == 1000){
iprint("bcm: ftq failed to reset\n");
return -1;
}
csr32(ctlr, ReceiveBDHostAddr) = 0;
csr32(ctlr, ReceiveBDHostAddr + 4) = PADDR(ctlr->recvprod);
csr32(ctlr, ReceiveBDFlags) = RecvProdRingLen << 16;
@ -503,7 +523,12 @@ bcminit(Ether *edev)
csr32(ctlr, SendInitiatorMask) = 0xFFFFFF;
csr32(ctlr, SendInitiatorConfiguration) |= SendStats;
csr32(ctlr, HostCoalescingMode) = 0;
while(csr32(ctlr, HostCoalescingMode) != 0);
for(i = 0; i < 200 && csr32(ctlr, HostCoalescingMode) != 0; i++)
microdelay(100);
if(i == 200){
iprint("bcm: host coalescing engine failed to stop\n");
return -1;
}
csr32(ctlr, HostCoalescingRecvTicks) = 150;
csr32(ctlr, HostCoalescingSendTicks) = 150;
csr32(ctlr, RecvMaxCoalescedFrames) = 10;
@ -539,7 +564,12 @@ bcminit(Ether *edev)
csr32(ctlr, MIMode) = 0xC0000;
microdelay(40);
miiw(ctlr, PhyControl, 1<<15);
while(miir(ctlr, PhyControl) & (1<<15));
for(i = 0; i < 1000 && miir(ctlr, PhyControl) & (1<<15); i++)
microdelay(100);
if(i == 1000){
iprint("bcm: PHY failed to reset\n");
return -1;
}
miiw(ctlr, PhyAuxControl, 2);
miir(ctlr, PhyIntStatus);
miir(ctlr, PhyIntStatus);
@ -554,6 +584,7 @@ bcminit(Ether *edev)
csr32(ctlr, ReceiveRulesConfiguration) = 1 << 3;
csr32(ctlr, MSIMode) |= Enable;
csr32(ctlr, MiscHostCtl) &= ~(MaskPCIInt | ClearIntA);
return 0;
}
static void
@ -637,6 +668,7 @@ bcmpnp(Ether* edev)
{
Ctlr *ctlr;
again:
if(bcmhead == nil)
bcmpci();
@ -664,7 +696,10 @@ bcmpnp(Ether* edev)
edev->arg = edev;
edev->mbps = 1000;
bcminit(edev);
if(bcminit(edev) < 0){
edev->ctlr = nil;
goto again;
}
return 0;
}

View file

@ -77,6 +77,11 @@ asmb(void)
curtext = P;
switch(HEADTYPE) {
case 0:
if(debug['P']){
OFFSET = rnd(textsize, INITRND);
seek(cout, OFFSET, 0);
break;
}
case 1:
case 2:
case 5: