@@ 7,6 7,7 @@
* output
* deal with stalling and restarting output on input overflow
* fix magic ring constants
+ * rewrite per SMC doc
*/
#include "u.h"
#include "../port/lib.h"
@@ 79,7 80,8 @@ enum {
struct Ring {
uchar status;
uchar next;
- ushort len;
+ uchar len0;
+ uchar len1;
uchar data[BUFsize-4];
};
@@ 101,14 103,17 @@ struct Pktype {
struct Ctlr {
QLock;
+ Ring *ring;
Rendez rr; /* rendezvous for an input buffer */
+ Queue rq;
uchar bnry;
uchar curr;
uchar ovw;
- Queue rq;
+ Etherpkt *xpkt;
QLock xl;
Rendez xr;
+ uchar xbusy;
int iobase; /* I/O base address */
@@ 132,6 137,14 @@ struct Ctlr {
};
static Ctlr ctlr[Nctlr];
+static int
+isxfree(void *arg)
+{
+ Ctlr *cp = arg;
+
+ return cp->xbusy == 0 && cp->ovw == 0;
+}
+
static void
etheroput(Queue *q, Block *bp)
{
@@ 184,22 197,20 @@ etheroput(Queue *q, Block *bp)
}
}
-panic("etheroput\n");
-#ifdef notdef
/*
* only one transmitter at a time
*/
- qlock(&c->xl);
+ qlock(&cp->xl);
if(waserror()){
- qunlock(&c->xl);
+ qunlock(&cp->xl);
nexterror();
}
/*
- * Wait till we get an output buffer
+ * Wait till we get an output buffer
*/
- sleep(&c->xr, isobuf, c);
- p = enet.xn;
+ sleep(&cp->xr, isxfree, cp);
+ p = cp->xpkt;
/*
* copy message into buffer
@@ 216,38 227,29 @@ panic("etheroput\n");
}
/*
- * pad the packet (zero the pad)
+ * pad the packet (zero the pad)
*/
if(len < ETHERMINTU){
memset(((char*)p)+len, 0, ETHERMINTU-len);
len = ETHERMINTU;
}
- enet.xn->len = len;
/*
- * give packet a local address
+ * give packet a local address
*/
- memmove(p->s, enet.ea, sizeof(enet.ea));
+ memmove(p->s, cp->ea, sizeof(cp->ea));
/*
- * give to Chip
+ * start the transmission
*/
- splhi(); /* sync with interrupt routine */
- enet.xn->owner = Chip;
- if(enet.xmting == 0)
- ethersend(enet.xn);
- spllo();
+ outb(cp->iobase+Tbcr0, len & 0xFF);
+ outb(cp->iobase+Tbcr1, (len>>8) & 0xFF);
+ outb(cp->iobase+Cr, 0x26); /* Page0|TXP|STA */
+ cp->xbusy = 1;
- /*
- * send
- */
- enet.xn = XSUCC(enet.xn);
freeb(bp);
- qunlock(&enet.xl);
+ qunlock(&cp->xl);
poperror();
-
- enet.outpackets++;
-#endif
}
/*
@@ 370,7 372,8 @@ intr(Ureg *ur)
if(isr & Ptx)
cp->outpackets++;
if(isr & (Txe|Ptx)){
- panic("tx intr\n");
+ cp->xbusy = 0;
+ wakeup(&cp->xr);
}
/*
* the receive ring is full.
@@ 422,6 425,7 @@ init(Ctlr *cp)
outb(cp->iobase+Tcr, 0x20); /* LB0 */
outb(cp->iobase+Bnry, 6);
cp->bnry = 6;
+ cp->ring = (Ring*)(KZERO|RAMbase);
outb(cp->iobase+Pstart, 6); /* 6*256 */
outb(cp->iobase+Pstop, 32); /* 8*1024/256 */
outb(cp->iobase+Isr, 0xFF);
@@ 435,6 439,7 @@ init(Ctlr *cp)
outb(cp->iobase+Cr, 0x22); /* Page0, RD2|STA */
outb(cp->iobase+Tpsr, 0);
+ cp->xpkt = (Etherpkt*)(KZERO|RAMbase);
}
void
@@ 556,14 561,13 @@ etherkproc(void *arg)
/*
* process any received packets
*/
- bnry = inb(cp->iobase+Bnry);
- while(bnry != cp->curr){
- rp = &((Ring*)RAMbase)[bnry];
-printpkt(bnry, rp->len, (Etherpkt*)rp->data);
+ cp->bnry = inb(cp->iobase+Bnry);
+ while(cp->bnry != cp->curr){
+ rp = &cp->ring[cp->bnry];
cp->inpackets++;
- etherup(cp, (Etherpkt*)rp->data, rp->len-4);
- bnry = rp->next;
- outb(cp->iobase+Bnry, bnry);
+ etherup(cp, (Etherpkt*)rp->data, ((rp->len1<<8)+rp->len0)-4);
+ cp->bnry = rp->next;
+ outb(cp->iobase+Bnry, cp->bnry);
}
/*
* if we idled input because of overflow,
@@ 572,6 576,7 @@ printpkt(bnry, rp->len, (Etherpkt*)rp->data);
if(cp->ovw){
cp->ovw = 0;
outb(cp->iobase+Tcr, 0);
+ wakeup(&cp->xr);
}
}
}
@@ 498,11 498,13 @@ syscall(Ureg *aur)
ulong r1;
Ureg *ur;
char *msg;
+ Proc *p;
m->syscall++;
- u->p->insyscall = 1;
+ p = u->p;
+ p->insyscall = 1;
ur = aur;
- u->p->pc = ur->pc; /* BUG */
+ p->pc = ur->pc; /* BUG */
u->dbgreg = aur;
ur->cause = 15<<2; /* for debugging: system call is undef 15;
/*
@@ 510,9 512,9 @@ syscall(Ureg *aur)
* guarantee anything about registers, we can
* smash them. but we must save fpstatus.
*/
- if(u->p->fpstate == FPactive) {
+ if(p->fpstate == FPactive) {
u->fpsave.fpstatus = fcr31();
- u->p->fpstate = FPinit;
+ p->fpstate = FPinit;
ur->status &= ~CU1;
}
spllo();
@@ 526,7 528,7 @@ syscall(Ureg *aur)
pprint("bad sys call number %d pc %lux\n", r1, ((Ureg*)UREGADDR)->pc);
msg = "sys: bad sys call";
Bad:
- postnote(u->p, 1, msg, NDebug);
+ postnote(p, 1, msg, NDebug);
error(Ebadarg);
}
if(sp & (BY2WD-1)){
@@ 534,24 536,20 @@ syscall(Ureg *aur)
msg = "sys: odd stack";
goto Bad;
}
- if(((ulong*)ur->pc)[-2] == 0x23bdfffc){ /* old calling convention: look for ADD $-4, SP */
- pprint("old system call linkage; recompile\n");
- sp += BY2WD;
- }
if(sp<(USTKTOP-BY2PG) || sp>(USTKTOP-(1+MAXSYSARG)*BY2WD))
validaddr(sp, (1+MAXSYSARG)*BY2WD, 0);
- u->p->psstate = sysctab[r1];
+ p->psstate = sysctab[r1];
ret = (*systab[r1])((ulong*)(sp+BY2WD));
}
ur->pc += 4;
u->nerrlab = 0;
- u->p->psstate = 0;
- u->p->insyscall = 0;
+ p->psstate = 0;
+ p->insyscall = 0;
if(r1 == NOTED) /* ugly hack */
noted(&aur, *(ulong*)(sp+BY2WD)); /* doesn't return */
splhi();
- if(r1!=FORK && (u->p->procctl || u->nnote)){
+ if(r1!=FORK && (u->nnote || p->procctl)){
u->svr1 = ret;
if(notify(ur))
return ur->r1;