kernel: move devether and wifi to port/

the only architecture dependence of devether was enabling interrupts,
which is now done at the end of the driver's reset() function now.

the wifi stack and dummy ethersink also go to port/.

do the IRQ2->IRQ9 hack for pc kernels in intrenabale(), so not
every caller of intrenable() has to be aware of it.
This commit is contained in:
cinap_lenrek 2018-02-11 18:08:03 +01:00
parent debb786fea
commit d6e0e9c402
96 changed files with 237 additions and 3945 deletions

View file

@ -11,7 +11,7 @@
#include "io.h" #include "io.h"
#include "../port/netif.h" #include "../port/netif.h"
#include "etherif.h" #include "../port/etherif.h"
#include "../port/flashif.h" #include "../port/flashif.h"
#include "arm.h" #include "arm.h"
@ -395,17 +395,6 @@ archkwlink(void)
{ {
} }
int
archether(unsigned ctlno, Ether *ether)
{
if(ctlno >= 2)
return -1;
ether->type = "88e1116";
ether->port = ctlno;
// ether->mbps = 1000;
return 1;
}
/* LED/USB gpios */ /* LED/USB gpios */
enum { enum {
/* /*

View file

@ -1,502 +0,0 @@
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/error.h"
#include "../port/netif.h"
#include "etherif.h"
extern int archether(unsigned ctlno, Ether *ether);
static Ether *etherxx[MaxEther];
Chan*
etherattach(char* spec)
{
int ctlrno;
char *p;
Chan *chan;
ctlrno = 0;
if(spec && *spec){
ctlrno = strtoul(spec, &p, 0);
if((ctlrno == 0 && p == spec) || *p != 0)
error(Ebadarg);
if(ctlrno < 0 || ctlrno >= MaxEther)
error(Ebadarg);
}
if(etherxx[ctlrno] == 0)
error(Enodev);
chan = devattach('l', spec);
if(waserror()){
chanfree(chan);
nexterror();
}
chan->dev = ctlrno;
if(etherxx[ctlrno]->attach)
etherxx[ctlrno]->attach(etherxx[ctlrno]);
poperror();
return chan;
}
static Walkqid*
etherwalk(Chan* chan, Chan* nchan, char** name, int nname)
{
return netifwalk(etherxx[chan->dev], chan, nchan, name, nname);
}
static int
etherstat(Chan* chan, uchar* dp, int n)
{
return netifstat(etherxx[chan->dev], chan, dp, n);
}
static Chan*
etheropen(Chan* chan, int omode)
{
return netifopen(etherxx[chan->dev], chan, omode);
}
static Chan*
ethercreate(Chan*, char*, int, ulong)
{
error(Eperm);
return 0;
}
static void
etherclose(Chan* chan)
{
netifclose(etherxx[chan->dev], chan);
}
static long
etherread(Chan* chan, void* buf, long n, vlong off)
{
Ether *ether;
ulong offset = off;
ether = etherxx[chan->dev];
if((chan->qid.type & QTDIR) == 0 && ether->ifstat){
/*
* With some controllers it is necessary to reach
* into the chip to extract statistics.
*/
if(NETTYPE(chan->qid.path) == Nifstatqid)
return ether->ifstat(ether, buf, n, offset);
else if(NETTYPE(chan->qid.path) == Nstatqid)
ether->ifstat(ether, buf, 0, offset);
}
return netifread(ether, chan, buf, n, offset);
}
static Block*
etherbread(Chan* chan, long n, ulong offset)
{
return netifbread(etherxx[chan->dev], chan, n, offset);
}
static int
etherwstat(Chan* chan, uchar* dp, int n)
{
return netifwstat(etherxx[chan->dev], chan, dp, n);
}
static void
etherrtrace(Netfile* f, Etherpkt* pkt, int len)
{
int i, n;
Block *bp;
if(qwindow(f->in) <= 0)
return;
if(len > 58)
n = 58;
else
n = len;
bp = iallocb(64);
if(bp == nil)
return;
memmove(bp->wp, pkt->d, n);
i = TK2MS(MACHP(0)->ticks);
bp->wp[58] = len>>8;
bp->wp[59] = len;
bp->wp[60] = i>>24;
bp->wp[61] = i>>16;
bp->wp[62] = i>>8;
bp->wp[63] = i;
bp->wp += 64;
qpass(f->in, bp);
}
Block*
etheriq(Ether* ether, Block* bp, int fromwire)
{
Etherpkt *pkt;
ushort type;
int len, multi, tome, fromme;
Netfile **ep, *f, **fp, *fx;
Block *xbp;
ether->inpackets++;
pkt = (Etherpkt*)bp->rp;
len = BLEN(bp);
type = (pkt->type[0]<<8)|pkt->type[1];
fx = 0;
ep = &ether->f[Ntypes];
multi = pkt->d[0] & 1;
/* check for valid multicast addresses */
if(multi && memcmp(pkt->d, ether->bcast, sizeof(pkt->d)) != 0 && ether->prom == 0){
if(!activemulti(ether, pkt->d, sizeof(pkt->d))){
if(fromwire){
freeb(bp);
bp = 0;
}
return bp;
}
}
/* is it for me? */
tome = memcmp(pkt->d, ether->ea, sizeof(pkt->d)) == 0;
fromme = memcmp(pkt->s, ether->ea, sizeof(pkt->s)) == 0;
/*
* Multiplex the packet to all the connections which want it.
* If the packet is not to be used subsequently (fromwire != 0),
* attempt to simply pass it into one of the connections, thereby
* saving a copy of the data (usual case hopefully).
*/
for(fp = ether->f; fp < ep; fp++){
if(f = *fp)
if(f->type == type || f->type < 0)
if(tome || multi || f->prom){
/* Don't want to hear loopback or bridged packets */
if(f->bridge && (tome || !fromwire && !fromme))
continue;
if(!f->headersonly){
if(fromwire && fx == 0)
fx = f;
else if(xbp = iallocb(len)){
memmove(xbp->wp, pkt, len);
xbp->wp += len;
if(qpass(f->in, xbp) < 0)
ether->soverflows++;
}
else
ether->soverflows++;
}
else
etherrtrace(f, pkt, len);
}
}
if(fx){
if(qpass(fx->in, bp) < 0)
ether->soverflows++;
return 0;
}
if(fromwire){
freeb(bp);
return 0;
}
return bp;
}
static int
etheroq(Ether* ether, Block* bp)
{
int len, loopback;
Etherpkt *pkt;
ether->outpackets++;
/*
* Check if the packet has to be placed back onto the input queue,
* i.e. if it's a loopback or broadcast packet or the interface is
* in promiscuous mode.
* If it's a loopback packet indicate to etheriq that the data isn't
* needed and return, etheriq will pass-on or free the block.
* To enable bridging to work, only packets that were originated
* by this interface are fed back.
*/
pkt = (Etherpkt*)bp->rp;
len = BLEN(bp);
loopback = memcmp(pkt->d, ether->ea, sizeof(pkt->d)) == 0;
if(loopback || memcmp(pkt->d, ether->bcast, sizeof(pkt->d)) == 0 || ether->prom)
if(etheriq(ether, bp, loopback) == 0)
return len;
qbwrite(ether->oq, bp);
if(ether->transmit != nil)
ether->transmit(ether);
return len;
}
static long
etherwrite(Chan* chan, void* buf, long n, vlong)
{
Ether *ether;
Block *bp;
int nn, onoff;
Cmdbuf *cb;
ether = etherxx[chan->dev];
if(NETTYPE(chan->qid.path) != Ndataqid) {
nn = netifwrite(ether, chan, buf, n);
if(nn >= 0)
return nn;
cb = parsecmd(buf, n);
if(strcmp(cb->f[0], "nonblocking") == 0){
if(cb->nf <= 1)
onoff = 1;
else
onoff = atoi(cb->f[1]);
qnoblock(ether->oq, onoff);
free(cb);
return n;
}
free(cb);
if(ether->ctl!=nil)
return ether->ctl(ether,buf,n);
error(Ebadctl);
}
if(n > ether->maxmtu)
error(Etoobig);
if(n < ether->minmtu)
error(Etoosmall);
bp = allocb(n);
if(waserror()){
freeb(bp);
nexterror();
}
memmove(bp->rp, buf, n);
if(!ether->f[NETID(chan->qid.path)]->bridge)
memmove(bp->rp+Eaddrlen, ether->ea, Eaddrlen);
poperror();
bp->wp += n;
return etheroq(ether, bp);
}
static long
etherbwrite(Chan* chan, Block* bp, ulong)
{
Ether *ether;
long n;
n = BLEN(bp);
if(NETTYPE(chan->qid.path) != Ndataqid){
if(waserror()) {
freeb(bp);
nexterror();
}
n = etherwrite(chan, bp->rp, n, 0);
poperror();
freeb(bp);
return n;
}
ether = etherxx[chan->dev];
if(n > ether->maxmtu){
freeb(bp);
error(Etoobig);
}
if(n < ether->minmtu){
freeb(bp);
error(Etoosmall);
}
return etheroq(ether, bp);
}
static struct {
char* type;
int (*reset)(Ether*);
} cards[MaxEther+1];
void
addethercard(char* t, int (*r)(Ether*))
{
static int ncard;
if(ncard == MaxEther)
panic("too many ether cards");
cards[ncard].type = t;
cards[ncard].reset = r;
ncard++;
}
static void
etherreset(void)
{
Ether *ether;
int i, n, ctlrno;
char name[KNAMELEN], buf[128];
for(ether = 0, ctlrno = 0; ctlrno < MaxEther; ctlrno++){
if(ether == 0)
ether = malloc(sizeof(Ether));
memset(ether, 0, sizeof(Ether));
ether->ctlrno = ctlrno;
ether->mbps = 10;
ether->minmtu = ETHERMINTU;
ether->maxmtu = ETHERMAXTU;
if(archether(ctlrno, ether) <= 0)
continue;
for(n = 0; cards[n].type; n++){
if(cistrcmp(cards[n].type, ether->type))
continue;
for(i = 0; i < ether->nopt; i++){
if(cistrncmp(ether->opt[i], "ea=", 3) == 0){
if(parseether(ether->ea, &ether->opt[i][3]) == -1)
memset(ether->ea, 0, Eaddrlen);
}else if(cistrcmp(ether->opt[i], "fullduplex") == 0 ||
cistrcmp(ether->opt[i], "10BASE-TFD") == 0)
ether->fullduplex = 1;
else if(cistrcmp(ether->opt[i], "100BASE-TXFD") == 0)
ether->mbps = 100;
}
if(cards[n].reset(ether))
break;
snprint(name, sizeof(name), "ether%d", ctlrno);
if(ether->interrupt != nil)
intrenable(Irqlo, ether->irq, ether->interrupt,
ether, name);
i = snprint(buf, sizeof buf,
"#l%d: %s: %dMbps port %#lux irq %d",
ctlrno, ether->type, ether->mbps, ether->port,
ether->irq);
if(ether->mem)
i += snprint(buf+i, sizeof buf - i,
" addr %#lux", PADDR(ether->mem));
if(ether->size)
i += snprint(buf+i, sizeof buf - i,
" size %#luX", ether->size);
i += snprint(buf+i, sizeof buf - i,
": %2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux",
ether->ea[0], ether->ea[1], ether->ea[2],
ether->ea[3], ether->ea[4], ether->ea[5]);
snprint(buf+i, sizeof buf - i, "\n");
print("%s", buf);
if(ether->mbps >= 1000)
netifinit(ether, name, Ntypes, 4*1024*1024);
else if(ether->mbps >= 100)
netifinit(ether, name, Ntypes, 1024*1024);
else
netifinit(ether, name, Ntypes, 65*1024);
if(ether->oq == 0)
ether->oq = qopen(ether->limit, Qmsg, 0, 0);
if(ether->oq == 0)
panic("etherreset %s", name);
ether->alen = Eaddrlen;
memmove(ether->addr, ether->ea, Eaddrlen);
memset(ether->bcast, 0xFF, Eaddrlen);
etherxx[ctlrno] = ether;
ether = 0;
break;
}
}
if(ether)
free(ether);
}
static void
ethershutdown(void)
{
Ether *ether;
int i;
for(i = 0; i < MaxEther; i++){
ether = etherxx[i];
if(ether == nil)
continue;
if(ether->shutdown == nil) {
print("#l%d: no shutdown function\n", i);
continue;
}
(*ether->shutdown)(ether);
}
}
#define POLY 0xedb88320
/* really slow 32 bit crc for ethers */
ulong
ethercrc(uchar *p, int len)
{
int i, j;
ulong crc, b;
crc = 0xffffffff;
for(i = 0; i < len; i++){
b = *p++;
for(j = 0; j < 8; j++){
crc = (crc>>1) ^ (((crc^b) & 1) ? POLY : 0);
b >>= 1;
}
}
return crc;
}
void
dumpoq(Queue *oq)
{
if (oq == nil)
print("no outq! ");
else if (qisclosed(oq))
print("outq closed ");
else if (qfull(oq))
print("outq full ");
else
print("outq %d ", qlen(oq));
}
void
dumpnetif(Netif *netif)
{
print("netif %s ", netif->name);
print("limit %d mbps %d link %d ",
netif->limit, netif->mbps, netif->link);
print("inpkts %lld outpkts %lld errs %d\n",
netif->inpackets, netif->outpackets,
netif->crcs + netif->oerrs + netif->frames + netif->overflows +
netif->buffs + netif->soverflows);
}
Dev etherdevtab = {
'l',
"ether",
etherreset,
devinit,
ethershutdown,
etherattach,
etherwalk,
etherstat,
etheropen,
ethercreate,
etherclose,
etherread,
etherbread,
etherwrite,
etherbwrite,
devremove,
etherwstat,
};

View file

@ -16,8 +16,8 @@
#include "io.h" #include "io.h"
#include "../port/error.h" #include "../port/error.h"
#include "../port/netif.h" #include "../port/netif.h"
#include "../port/etherif.h"
#include "etherif.h"
#include "ethermii.h" #include "ethermii.h"
#include "../ip/ip.h" #include "../ip/ip.h"
@ -144,6 +144,9 @@ struct Ctlr {
Mii *mii; Mii *mii;
int port; int port;
int linkchg; /* link status changed? */
uvlong starttime; /* last activity time */
/* stats */ /* stats */
ulong intrs; ulong intrs;
ulong newintrs; ulong newintrs;
@ -579,14 +582,16 @@ dump(uchar *bp, long max)
static void static void
etheractive(Ether *ether) etheractive(Ether *ether)
{ {
ether->starttime = TK2MS(MACHP(0)->ticks)/1000; Ctlr *ctlr = ether->ctlr;
ctlr->starttime = TK2MS(MACHP(0)->ticks)/1000;
} }
static void static void
ethercheck(Ether *ether) ethercheck(Ether *ether)
{ {
if (ether->starttime != 0 && Ctlr *ctlr = ether->ctlr;
TK2MS(MACHP(0)->ticks)/1000 - ether->starttime > Etherstuck) { if (ctlr->starttime != 0 &&
TK2MS(MACHP(0)->ticks)/1000 - ctlr->starttime > Etherstuck) {
etheractive(ether); etheractive(ether);
if (ether->ctlrno == 0) /* only complain about main ether */ if (ether->ctlrno == 0) /* only complain about main ether */
iprint("#l%d: ethernet stuck\n", ether->ctlrno); iprint("#l%d: ethernet stuck\n", ether->ctlrno);
@ -833,7 +838,7 @@ interrupt(Ureg*, void *arg)
*/ */
if(irqe & IEphystschg) { if(irqe & IEphystschg) {
ether->link = (reg->ps0 & PS0linkup) != 0; ether->link = (reg->ps0 & PS0linkup) != 0;
ether->linkchg = 1; ctlr->linkchg = 1;
} }
if(irqe & IEtxerrq(Qno)) if(irqe & IEtxerrq(Qno))
ether->oerrs++; ether->oerrs++;
@ -858,10 +863,10 @@ interrupt(Ureg*, void *arg)
irq &= ~(Irxerr | Irxerrq(Qno)); irq &= ~(Irxerr | Irxerrq(Qno));
} }
if(ether->linkchg && (reg->ps1 & PS1an_done)) { if(ctlr->linkchg && (reg->ps1 & PS1an_done)) {
handled++; handled++;
ether->link = (reg->ps0 & PS0linkup) != 0; ether->link = (reg->ps0 & PS0linkup) != 0;
ether->linkchg = 0; ctlr->linkchg = 0;
} }
ctlr->newintrs++; ctlr->newintrs++;
@ -1652,7 +1657,6 @@ ifstat(Ether *ether, void *a, long n, ulong off)
p = seprint(p, e, "transmitted broadcast frames: %lud\n", ctlr->txbcastpkt); p = seprint(p, e, "transmitted broadcast frames: %lud\n", ctlr->txbcastpkt);
p = seprint(p, e, "transmitted multicast frames: %lud\n", ctlr->txmcastpkt); p = seprint(p, e, "transmitted multicast frames: %lud\n", ctlr->txmcastpkt);
p = seprint(p, e, "transmit frames dropped by collision: %lud\n", ctlr->txcollpktdrop); p = seprint(p, e, "transmit frames dropped by collision: %lud\n", ctlr->txcollpktdrop);
p = seprint(p, e, "misaligned buffers: %lud\n", ether->pktsmisaligned);
p = seprint(p, e, "bad mac control frames: %lud\n", ctlr->badmacctlpkts); p = seprint(p, e, "bad mac control frames: %lud\n", ctlr->badmacctlpkts);
p = seprint(p, e, "transmitted flow control messages: %lud\n", ctlr->txflctl); p = seprint(p, e, "transmitted flow control messages: %lud\n", ctlr->txflctl);
@ -1689,7 +1693,7 @@ reset(Ether *ether)
ether->irq = IRQ0gbe1sum; ether->irq = IRQ0gbe1sum;
break; break;
default: default:
panic("ether1116: bad ether ctlr #%d", ether->ctlrno); return -1;
} }
ctlr->reg = (Gbereg*)soc.ether[ether->ctlrno]; ctlr->reg = (Gbereg*)soc.ether[ether->ctlrno];
@ -1728,7 +1732,6 @@ iprint("ether1116: reset: zero ether->ea\n");
ether->attach = attach; ether->attach = attach;
ether->transmit = transmit; ether->transmit = transmit;
ether->interrupt = interrupt;
ether->ifstat = ifstat; ether->ifstat = ifstat;
ether->shutdown = shutdown; ether->shutdown = shutdown;
ether->ctl = ctl; ether->ctl = ctl;
@ -1736,6 +1739,9 @@ iprint("ether1116: reset: zero ether->ea\n");
ether->arg = ether; ether->arg = ether;
ether->promiscuous = promiscuous; ether->promiscuous = promiscuous;
ether->multicast = multicast; ether->multicast = multicast;
intrenable(Irqlo, ether->irq, interrupt, ether, ether->name);
return 0; return 0;
} }

View file

@ -1,55 +0,0 @@
enum
{
MaxEther = 2,
Ntypes = 8,
};
typedef struct Ether Ether;
struct Ether {
RWlock; /* TO DO */
ISAConf; /* hardware info */
int ctlrno;
int minmtu;
int maxmtu;
uchar ea[Eaddrlen];
void *address;
int tbusy;
void (*attach)(Ether*); /* filled in by reset routine */
void (*closed)(Ether*);
void (*detach)(Ether*);
void (*transmit)(Ether*);
void (*interrupt)(Ureg*, void*);
long (*ifstat)(Ether*, void*, long, ulong);
long (*ctl)(Ether*, void*, long); /* custom ctl messages */
void (*power)(Ether*, int); /* power on/off */
void (*shutdown)(Ether*); /* shutdown hardware before reboot */
void *ctlr;
int pcmslot; /* PCMCIA */
int fullduplex; /* non-zero if full duplex */
int linkchg; /* link status changed? */
uvlong starttime; /* last activity time */
Queue* oq;
/* statistics */
ulong interrupts;
ulong dmarxintr;
ulong dmatxintr;
ulong promisc;
ulong pktsdropped;
ulong pktsmisaligned;
ulong resets; /* after initialisation */
ulong bcasts; /* broadcast pkts rcv'd */
ulong mcasts; /* multicast pkts rcv'd */
Netif;
};
extern Block* etheriq(Ether*, Block*, int);
extern void addethercard(char*, int(*)(Ether*));
extern ulong ethercrc(uchar*, int);
extern int parseether(uchar*, char*);
#define NEXT(x, l) (((x)+1)%(l))
#define PREV(x, l) (((x) == 0) ? (l)-1: (x)-1)

View file

@ -6,8 +6,8 @@
#include "io.h" #include "io.h"
#include "../port/error.h" #include "../port/error.h"
#include "../port/netif.h" #include "../port/netif.h"
#include "../port/etherif.h"
#include "etherif.h"
#include "ethermii.h" #include "ethermii.h"
int int

View file

@ -5,9 +5,6 @@
#define MiB 1048576u /* Mebi 0x0000000000100000 */ #define MiB 1048576u /* Mebi 0x0000000000100000 */
#define GiB 1073741824u /* Gibi 000000000040000000 */ #define GiB 1073741824u /* Gibi 000000000040000000 */
#define HOWMANY(x, y) (((x)+((y)-1))/(y))
#define ROUNDUP(x, y) (HOWMANY((x), (y))*(y)) /* ceiling */
#define ROUNDDN(x, y) (((x)/(y))*(y)) /* floor */
#define MIN(a, b) ((a) < (b)? (a): (b)) #define MIN(a, b) ((a) < (b)? (a): (b))
#define MAX(a, b) ((a) > (b)? (a): (b)) #define MAX(a, b) ((a) > (b)? (a): (b))
@ -36,7 +33,7 @@
*/ */
#define BY2PG (4*KiB) /* bytes per page */ #define BY2PG (4*KiB) /* bytes per page */
#define PGSHIFT 12 /* log(BY2PG) */ #define PGSHIFT 12 /* log(BY2PG) */
#define PGROUND(s) ROUNDUP(s, BY2PG) #define PGROUND(s) ROUND(s, BY2PG)
#define ROUND(s, sz) (((s)+(sz-1))&~(sz-1)) #define ROUND(s, sz) (((s)+(sz-1))&~(sz-1))
#define MAXMACH 1 /* max # cpus system can run */ #define MAXMACH 1 /* max # cpus system can run */

View file

@ -124,7 +124,7 @@ arch.$O clock.$O fpiarm.$O main.$O mmu.$O screen.$O sdscsi.$O syscall.$O \
trap.$O: /$objtype/include/ureg.h trap.$O: /$objtype/include/ureg.h
archkw.$O devether.$O ether1116.$O ethermii.$O: \ archkw.$O devether.$O ether1116.$O ethermii.$O: \
etherif.h ethermii.h ../port/netif.h ethermii.h ../port/etherif.h ../port/netif.h
archkw.$O devflash.$O flashkw.$O: ../port/flashif.h archkw.$O devflash.$O flashkw.$O: ../port/flashif.h
fpi.$O fpiarm.$O fpimem.$O: fpi.h fpi.$O fpiarm.$O fpimem.$O: fpi.h
l.$O lexception.$O lproc.$O mmu.$O: arm.s arm.h mem.h l.$O lexception.$O lproc.$O mmu.$O: arm.s arm.h mem.h

View file

@ -465,7 +465,7 @@ vmap(uintptr pa, usize size)
o = pa & (BY2PG-1); o = pa & (BY2PG-1);
pa -= o; pa -= o;
size += o; size += o;
size = ROUNDUP(size, BY2PG); size = PGROUND(size);
va = kseg0|pa; va = kseg0|pa;
pae = mmukmap(va, pa, size); pae = mmukmap(va, pa, size);

View file

@ -1,447 +0,0 @@
#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"
#include "../port/netif.h"
#include "etherif.h"
static Ether *etherxx[MaxEther];
Chan*
etherattach(char* spec)
{
ulong ctlrno;
char *p;
Chan *chan;
ctlrno = 0;
if(spec && *spec){
ctlrno = strtoul(spec, &p, 0);
if((ctlrno == 0 && p == spec) || *p || (ctlrno >= MaxEther))
error(Ebadarg);
}
if(etherxx[ctlrno] == 0)
error(Enodev);
chan = devattach('l', spec);
chan->dev = ctlrno;
if(etherxx[ctlrno]->attach)
etherxx[ctlrno]->attach(etherxx[ctlrno]);
return chan;
}
static Walkqid*
etherwalk(Chan* chan, Chan* nchan, char** name, int nname)
{
return netifwalk(etherxx[chan->dev], chan, nchan, name, nname);
}
static int
etherstat(Chan* chan, uchar* dp, int n)
{
return netifstat(etherxx[chan->dev], chan, dp, n);
}
static Chan*
etheropen(Chan* chan, int omode)
{
return netifopen(etherxx[chan->dev], chan, omode);
}
static Chan*
ethercreate(Chan*, char*, int, ulong)
{
error(Eperm);
return 0;
}
static void
etherclose(Chan* chan)
{
netifclose(etherxx[chan->dev], chan);
}
static long
etherread(Chan* chan, void* buf, long n, vlong off)
{
Ether *ether;
ulong offset = off;
ether = etherxx[chan->dev];
if((chan->qid.type & QTDIR) == 0 && ether->ifstat){
/*
* With some controllers it is necessary to reach
* into the chip to extract statistics.
*/
if(NETTYPE(chan->qid.path) == Nifstatqid)
return ether->ifstat(ether, buf, n, offset);
else if(NETTYPE(chan->qid.path) == Nstatqid)
ether->ifstat(ether, buf, 0, offset);
}
return netifread(ether, chan, buf, n, offset);
}
static Block*
etherbread(Chan* chan, long n, ulong offset)
{
return netifbread(etherxx[chan->dev], chan, n, offset);
}
static int
etherwstat(Chan* chan, uchar* dp, int n)
{
return netifwstat(etherxx[chan->dev], chan, dp, n);
}
static void
etherrtrace(Netfile* f, Etherpkt* pkt, int len)
{
int i, n;
Block *bp;
if(qwindow(f->in) <= 0)
return;
if(len > 58)
n = 58;
else
n = len;
bp = iallocb(64);
if(bp == nil)
return;
memmove(bp->wp, pkt->d, n);
i = TK2MS(MACHP(0)->ticks);
bp->wp[58] = len>>8;
bp->wp[59] = len;
bp->wp[60] = i>>24;
bp->wp[61] = i>>16;
bp->wp[62] = i>>8;
bp->wp[63] = i;
bp->wp += 64;
qpass(f->in, bp);
}
Block*
etheriq(Ether* ether, Block* bp, int fromwire)
{
Etherpkt *pkt;
ushort type;
int len, multi, tome, fromme;
Netfile **ep, *f, **fp, *fx;
Block *xbp;
ether->inpackets++;
pkt = (Etherpkt*)bp->rp;
len = BLEN(bp);
type = (pkt->type[0]<<8)|pkt->type[1];
fx = 0;
ep = &ether->f[Ntypes];
multi = pkt->d[0] & 1;
/* check for valid multicast addresses */
if(multi && memcmp(pkt->d, ether->bcast, sizeof(pkt->d)) && ether->prom == 0){
if(!activemulti(ether, pkt->d, sizeof(pkt->d))){
if(fromwire){
freeb(bp);
bp = 0;
}
return bp;
}
}
/* is it for me? */
tome = memcmp(pkt->d, ether->ea, sizeof(pkt->d)) == 0;
fromme = memcmp(pkt->s, ether->ea, sizeof(pkt->s)) == 0;
/*
* Multiplex the packet to all the connections which want it.
* If the packet is not to be used subsequently (fromwire != 0),
* attempt to simply pass it into one of the connections, thereby
* saving a copy of the data (usual case hopefully).
*/
for(fp = ether->f; fp < ep; fp++){
if(f = *fp)
if(f->type == type || f->type < 0)
if(tome || multi || f->prom){
/* Don't want to hear loopback or bridged packets */
if(f->bridge && (tome || !fromwire && !fromme))
continue;
if(!f->headersonly){
if(fromwire && fx == 0)
fx = f;
else if(xbp = iallocb(len)){
memmove(xbp->wp, pkt, len);
xbp->wp += len;
qpass(f->in, xbp);
}
else
ether->soverflows++;
}
else
etherrtrace(f, pkt, len);
}
}
if(fx){
if(qpass(fx->in, bp) < 0)
ether->soverflows++;
return 0;
}
if(fromwire){
freeb(bp);
return 0;
}
return bp;
}
static int
etheroq(Ether* ether, Block* bp)
{
int len, loopback;
Etherpkt *pkt;
ether->outpackets++;
/*
* Check if the packet has to be placed back onto the input queue,
* i.e. if it's a loopback or broadcast packet or the interface is
* in promiscuous mode.
* If it's a loopback packet indicate to etheriq that the data isn't
* needed and return, etheriq will pass-on or free the block.
* To enable bridging to work, only packets that were originated
* by this interface are fed back.
*/
pkt = (Etherpkt*)bp->rp;
len = BLEN(bp);
loopback = memcmp(pkt->d, ether->ea, sizeof(pkt->d)) == 0;
if(loopback || memcmp(pkt->d, ether->bcast, sizeof(pkt->d)) == 0 || ether->prom)
if(etheriq(ether, bp, loopback) == 0)
return len;
qbwrite(ether->oq, bp);
if(ether->transmit != nil)
ether->transmit(ether);
return len;
}
static long
etherwrite(Chan* chan, void* buf, long n, vlong)
{
Ether *ether;
Block *bp;
int nn;
ether = etherxx[chan->dev];
if(NETTYPE(chan->qid.path) != Ndataqid) {
nn = netifwrite(ether, chan, buf, n);
if(nn >= 0)
return nn;
if(n == sizeof("nonblocking")-1 && strncmp((char*)buf, "nonblocking", n) == 0){
qnoblock(ether->oq, 1);
return n;
}
if(ether->ctl!=nil)
return ether->ctl(ether,buf,n);
error(Ebadctl);
}
if(n > ether->maxmtu)
error(Etoobig);
if(n < ether->minmtu)
error(Etoosmall);
bp = allocb(n);
if(waserror()){
freeb(bp);
nexterror();
}
memmove(bp->rp, buf, n);
if(!ether->f[NETID(chan->qid.path)]->bridge)
memmove(bp->rp+Eaddrlen, ether->ea, Eaddrlen);
poperror();
bp->wp += n;
return etheroq(ether, bp);
}
static long
etherbwrite(Chan* chan, Block* bp, ulong)
{
Ether *ether;
long n;
n = BLEN(bp);
if(NETTYPE(chan->qid.path) != Ndataqid){
if(waserror()) {
freeb(bp);
nexterror();
}
n = etherwrite(chan, bp->rp, n, 0);
poperror();
freeb(bp);
return n;
}
ether = etherxx[chan->dev];
if(n > ether->maxmtu){
freeb(bp);
error(Etoobig);
}
if(n < ether->minmtu){
freeb(bp);
error(Etoosmall);
}
return etheroq(ether, bp);
}
static struct {
char* type;
int (*reset)(Ether*);
} cards[MaxEther+1];
void
addethercard(char* t, int (*r)(Ether*))
{
static int ncard;
if(ncard == MaxEther)
panic("too many ether cards");
cards[ncard].type = t;
cards[ncard].reset = r;
ncard++;
}
static void
etherreset(void)
{
Ether *ether;
int i, n, ctlrno;
char name[32], buf[128];
for(ether = 0, ctlrno = 0; ctlrno < MaxEther; ctlrno++){
if(ether == 0)
ether = malloc(sizeof(Ether));
memset(ether, 0, sizeof(Ether));
ether->ctlrno = ctlrno;
ether->tbdf = BUSUNKNOWN;
ether->mbps = 10;
ether->minmtu = ETHERMINTU;
ether->maxmtu = ETHERMAXTU;
if(isaconfig("ether", ctlrno, ether) == 0)
continue;
for(n = 0; cards[n].type; n++){
if(cistrcmp(cards[n].type, ether->type))
continue;
for(i = 0; i < ether->nopt; i++){
if(strncmp(ether->opt[i], "ea=", 3))
continue;
if(parseether(ether->ea, &ether->opt[i][3]) == -1)
memset(ether->ea, 0, Eaddrlen);
}
if(cards[n].reset(ether))
break;
/*
* IRQ2 doesn't really exist, it's used to gang the interrupt
* controllers together. A device set to IRQ2 will appear on
* the second interrupt controller as IRQ9.
*/
if(ether->irq == 2 && BUSTYPE(ether->tbdf) != BusPCI)
ether->irq = 9;
snprint(name, sizeof(name), "ether%d", ctlrno);
/*
* If ether->irq is <0, it is a hack to indicate no interrupt
* used by ethersink.
*/
if(ether->irq >= 0)
intrenable(ether->irq, ether->interrupt, ether, ether->tbdf, name);
i = sprint(buf, "#l%d: %s: %dMbps port 0x%luX irq %d",
ctlrno, ether->type, ether->mbps, ether->port, ether->irq);
if(ether->mem)
i += sprint(buf+i, " addr 0x%luX", PADDR(ether->mem));
if(ether->size)
i += sprint(buf+i, " size 0x%luX", ether->size);
i += sprint(buf+i, ": %2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux",
ether->ea[0], ether->ea[1], ether->ea[2],
ether->ea[3], ether->ea[4], ether->ea[5]);
sprint(buf+i, "\n");
print(buf);
if(ether->mbps >= 100){
netifinit(ether, name, Ntypes, 256*1024);
if(ether->oq == 0)
ether->oq = qopen(256*1024, Qmsg, 0, 0);
}
else{
netifinit(ether, name, Ntypes, 65*1024);
if(ether->oq == 0)
ether->oq = qopen(65*1024, Qmsg, 0, 0);
}
if(ether->oq == 0)
panic("etherreset %s", name);
ether->alen = Eaddrlen;
memmove(ether->addr, ether->ea, Eaddrlen);
memset(ether->bcast, 0xFF, Eaddrlen);
etherxx[ctlrno] = ether;
ether = 0;
break;
}
}
if(ether)
free(ether);
}
#define POLY 0xedb88320
/* really slow 32 bit crc for ethers */
ulong
ethercrc(uchar *p, int len)
{
int i, j;
ulong crc, b;
crc = 0xffffffff;
for(i = 0; i < len; i++){
b = *p++;
for(j = 0; j < 8; j++){
crc = (crc>>1) ^ (((crc^b) & 1) ? POLY : 0);
b >>= 1;
}
}
return crc;
}
Dev etherdevtab = {
'l',
"ether",
etherreset,
devinit,
devshutdown,
etherattach,
etherwalk,
etherstat,
etheropen,
ethercreate,
etherclose,
etherread,
etherbread,
etherwrite,
etherbwrite,
devremove,
etherwstat,
};

View file

@ -16,8 +16,7 @@
#include "io.h" #include "io.h"
#include "../port/error.h" #include "../port/error.h"
#include "../port/netif.h" #include "../port/netif.h"
#include "../port/etherif.h"
#include "etherif.h"
#define DEBUG (0) #define DEBUG (0)
#define debug if(DEBUG)print #define debug if(DEBUG)print
@ -1654,12 +1653,13 @@ ether->irq = 2; /* arrrrrgh */
*/ */
ether->attach = attach; ether->attach = attach;
ether->transmit = transmit; ether->transmit = transmit;
ether->interrupt = interrupt;
ether->ifstat = ifstat; ether->ifstat = ifstat;
ether->arg = ether; ether->arg = ether;
ether->promiscuous = promiscuous; ether->promiscuous = promiscuous;
intrenable(ether->irq, interrupt, ether, ether->tbdf, ether->name);
return 0; return 0;
} }

View file

@ -1,35 +0,0 @@
enum {
MaxEther = 24,
Ntypes = 8,
};
typedef struct Ether Ether;
struct Ether {
ISAConf; /* hardware info */
int ctlrno;
int tbdf; /* type+busno+devno+funcno */
int minmtu;
int maxmtu;
uchar ea[Eaddrlen];
void (*attach)(Ether*); /* filled in by reset routine */
void (*transmit)(Ether*);
void (*interrupt)(Ureg*, void*);
long (*ifstat)(Ether*, void*, long, ulong);
long (*ctl)(Ether*, void*, long); /* custom ctl messages */
void *ctlr;
Queue* oq;
Netif;
};
extern Block* etheriq(Ether*, Block*, int);
extern void addethercard(char*, int(*)(Ether*));
extern ulong ethercrc(uchar*, int);
#define NEXT(x, l) (((x)+1)%(l))
#define PREV(x, l) (((x) == 0) ? (l)-1: (x)-1)
#define HOWMANY(x, y) (((x)+((y)-1))/(y))
#define ROUNDUP(x, y) (HOWMANY((x), (y))*(y))

View file

@ -82,7 +82,7 @@ devether.$O: /$objtype/include/ureg.h
main.$O: /$objtype/include/ureg.h errstr.h init.h main.$O: /$objtype/include/ureg.h errstr.h init.h
trap.$O: /$objtype/include/ureg.h trap.$O: /$objtype/include/ureg.h
$ETHER: etherif.h ../port/netif.h $ETHER: ../port/etherif.h ../port/netif.h
init.h: initcode /sys/src/libc/9syscall/sys.h init.h: initcode /sys/src/libc/9syscall/sys.h
$AS initcode $AS initcode

View file

@ -15,7 +15,7 @@
#include "arm.h" #include "arm.h"
#include "../port/netif.h" #include "../port/netif.h"
#include "etherif.h" #include "../port/etherif.h"
#include "../port/flashif.h" #include "../port/flashif.h"
#include "../port/usb.h" #include "../port/usb.h"
#include "../port/portusbehci.h" #include "../port/portusbehci.h"

View file

@ -240,6 +240,8 @@ struct ISAConf {
char *opt[NISAOPT]; char *opt[NISAOPT];
}; };
#define BUSUNKNOWN -1
#define MACHP(n) (machaddr[n]) #define MACHP(n) (machaddr[n])
/* /*

View file

@ -1,504 +0,0 @@
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/error.h"
#include "../port/netif.h"
#include "etherif.h"
extern int archether(unsigned ctlno, Ether *ether);
static Ether *etherxx[MaxEther];
Chan*
etherattach(char* spec)
{
int ctlrno;
char *p;
Chan *chan;
ctlrno = 0;
if(spec && *spec){
ctlrno = strtoul(spec, &p, 0);
if((ctlrno == 0 && p == spec) || *p != 0)
error(Ebadarg);
if(ctlrno < 0 || ctlrno >= MaxEther)
error(Ebadarg);
}
if(etherxx[ctlrno] == 0)
error(Enodev);
chan = devattach('l', spec);
if(waserror()){
chanfree(chan);
nexterror();
}
chan->dev = ctlrno;
if(etherxx[ctlrno]->attach)
etherxx[ctlrno]->attach(etherxx[ctlrno]);
poperror();
return chan;
}
static Walkqid*
etherwalk(Chan* chan, Chan* nchan, char** name, int nname)
{
return netifwalk(etherxx[chan->dev], chan, nchan, name, nname);
}
static int
etherstat(Chan* chan, uchar* dp, int n)
{
return netifstat(etherxx[chan->dev], chan, dp, n);
}
static Chan*
etheropen(Chan* chan, int omode)
{
return netifopen(etherxx[chan->dev], chan, omode);
}
static Chan*
ethercreate(Chan*, char*, int, ulong)
{
error(Eperm);
return 0;
}
static void
etherclose(Chan* chan)
{
netifclose(etherxx[chan->dev], chan);
}
static long
etherread(Chan* chan, void* buf, long n, vlong off)
{
Ether *ether;
ulong offset = off;
ether = etherxx[chan->dev];
if((chan->qid.type & QTDIR) == 0 && ether->ifstat){
/*
* With some controllers it is necessary to reach
* into the chip to extract statistics.
*/
if(NETTYPE(chan->qid.path) == Nifstatqid)
return ether->ifstat(ether, buf, n, offset);
else if(NETTYPE(chan->qid.path) == Nstatqid)
ether->ifstat(ether, buf, 0, offset);
}
return netifread(ether, chan, buf, n, offset);
}
static Block*
etherbread(Chan* chan, long n, ulong offset)
{
return netifbread(etherxx[chan->dev], chan, n, offset);
}
static int
etherwstat(Chan* chan, uchar* dp, int n)
{
return netifwstat(etherxx[chan->dev], chan, dp, n);
}
static void
etherrtrace(Netfile* f, Etherpkt* pkt, int len)
{
int i, n;
Block *bp;
if(qwindow(f->in) <= 0)
return;
if(len > 58)
n = 58;
else
n = len;
bp = iallocb(64);
if(bp == nil)
return;
memmove(bp->wp, pkt->d, n);
i = TK2MS(MACHP(0)->ticks);
bp->wp[58] = len>>8;
bp->wp[59] = len;
bp->wp[60] = i>>24;
bp->wp[61] = i>>16;
bp->wp[62] = i>>8;
bp->wp[63] = i;
bp->wp += 64;
qpass(f->in, bp);
}
Block*
etheriq(Ether* ether, Block* bp, int fromwire)
{
Etherpkt *pkt;
ushort type;
int len, multi, tome, fromme;
Netfile **ep, *f, **fp, *fx;
Block *xbp;
ether->inpackets++;
pkt = (Etherpkt*)bp->rp;
len = BLEN(bp);
type = (pkt->type[0]<<8)|pkt->type[1];
fx = 0;
ep = &ether->f[Ntypes];
multi = pkt->d[0] & 1;
/* check for valid multicast addresses */
if(multi && memcmp(pkt->d, ether->bcast, sizeof(pkt->d)) != 0 &&
ether->prom == 0){
if(!activemulti(ether, pkt->d, sizeof(pkt->d))){
if(fromwire){
freeb(bp);
bp = 0;
}
return bp;
}
}
/* is it for me? */
tome = memcmp(pkt->d, ether->ea, sizeof(pkt->d)) == 0;
fromme = memcmp(pkt->s, ether->ea, sizeof(pkt->s)) == 0;
/*
* Multiplex the packet to all the connections which want it.
* If the packet is not to be used subsequently (fromwire != 0),
* attempt to simply pass it into one of the connections, thereby
* saving a copy of the data (usual case hopefully).
*/
for(fp = ether->f; fp < ep; fp++){
if((f = *fp) != nil && (f->type == type || f->type < 0) &&
(tome || multi || f->prom)){
/* Don't want to hear loopback or bridged packets */
if(f->bridge && (tome || !fromwire && !fromme))
continue;
if(!f->headersonly){
if(fromwire && fx == 0)
fx = f;
else if(xbp = iallocb(len)){
memmove(xbp->wp, pkt, len);
xbp->wp += len;
if(qpass(f->in, xbp) < 0)
ether->soverflows++;
}
else
ether->soverflows++;
}
else
etherrtrace(f, pkt, len);
}
}
if(fx){
if(qpass(fx->in, bp) < 0)
ether->soverflows++;
return 0;
}
if(fromwire){
freeb(bp);
return 0;
}
return bp;
}
static int
etheroq(Ether* ether, Block* bp)
{
int len, loopback;
Etherpkt *pkt;
ether->outpackets++;
/*
* Check if the packet has to be placed back onto the input queue,
* i.e. if it's a loopback or broadcast packet or the interface is
* in promiscuous mode.
* If it's a loopback packet indicate to etheriq that the data isn't
* needed and return, etheriq will pass-on or free the block.
* To enable bridging to work, only packets that were originated
* by this interface are fed back.
*/
pkt = (Etherpkt*)bp->rp;
len = BLEN(bp);
loopback = memcmp(pkt->d, ether->ea, sizeof(pkt->d)) == 0;
if(loopback || memcmp(pkt->d, ether->bcast, sizeof(pkt->d)) == 0 || ether->prom)
if(etheriq(ether, bp, loopback) == 0)
return len;
qbwrite(ether->oq, bp);
if(ether->transmit != nil)
ether->transmit(ether);
return len;
}
static long
etherwrite(Chan* chan, void* buf, long n, vlong)
{
Ether *ether;
Block *bp;
int nn, onoff;
Cmdbuf *cb;
ether = etherxx[chan->dev];
if(NETTYPE(chan->qid.path) != Ndataqid) {
nn = netifwrite(ether, chan, buf, n);
if(nn >= 0)
return nn;
cb = parsecmd(buf, n);
if(cb->f[0] && strcmp(cb->f[0], "nonblocking") == 0){
if(cb->nf <= 1)
onoff = 1;
else
onoff = atoi(cb->f[1]);
qnoblock(ether->oq, onoff);
free(cb);
return n;
}
free(cb);
if(ether->ctl!=nil)
return ether->ctl(ether,buf,n);
error(Ebadctl);
}
if(n > ether->maxmtu)
error(Etoobig);
if(n < ether->minmtu)
error(Etoosmall);
bp = allocb(n);
if(waserror()){
freeb(bp);
nexterror();
}
memmove(bp->rp, buf, n);
if(!ether->f[NETID(chan->qid.path)]->bridge)
memmove(bp->rp+Eaddrlen, ether->ea, Eaddrlen);
poperror();
bp->wp += n;
return etheroq(ether, bp);
}
static long
etherbwrite(Chan* chan, Block* bp, ulong)
{
Ether *ether;
long n;
n = BLEN(bp);
if(NETTYPE(chan->qid.path) != Ndataqid){
if(waserror()) {
freeb(bp);
nexterror();
}
n = etherwrite(chan, bp->rp, n, 0);
poperror();
freeb(bp);
return n;
}
ether = etherxx[chan->dev];
if(n > ether->maxmtu){
freeb(bp);
error(Etoobig);
}
if(n < ether->minmtu){
freeb(bp);
error(Etoosmall);
}
return etheroq(ether, bp);
}
static struct {
char* type;
int (*reset)(Ether*);
} cards[MaxEther+1];
void
addethercard(char* t, int (*r)(Ether*))
{
static int ncard;
if(ncard == MaxEther)
panic("too many ether cards");
cards[ncard].type = t;
cards[ncard].reset = r;
ncard++;
}
static void
etherreset(void)
{
Ether *ether;
int i, n, ctlrno;
char name[KNAMELEN], buf[128];
for(ether = 0, ctlrno = 0; ctlrno < MaxEther; ctlrno++){
if(ether == 0)
ether = malloc(sizeof(Ether));
memset(ether, 0, sizeof(Ether));
ether->ctlrno = ctlrno;
ether->mbps = 10;
ether->minmtu = ETHERMINTU;
ether->maxmtu = ETHERMAXTU;
if(archether(ctlrno, ether) <= 0)
continue;
if(isaconfig("ether", ctlrno, ether) == 0){
// free(ether);
// return nil;
continue;
}
for(n = 0; cards[n].type; n++){
if(cistrcmp(cards[n].type, ether->type))
continue;
for(i = 0; i < ether->nopt; i++)
if(cistrncmp(ether->opt[i], "ea=", 3) == 0){
if(parseether(ether->ea,
&ether->opt[i][3]) == -1)
memset(ether->ea, 0, Eaddrlen);
} else if(cistrcmp(ether->opt[i],
"100BASE-TXFD") == 0)
ether->mbps = 100;
if(cards[n].reset(ether))
break;
snprint(name, sizeof(name), "ether%d", ctlrno);
if(ether->interrupt != nil && ether->irq >= 0)
intrenable(ether->irq, ether->interrupt,
ether, 0, name);
i = snprint(buf, sizeof buf,
"#l%d: %s: %dMbps port %#lux irq %d",
ctlrno, ether->type, ether->mbps, ether->port,
ether->irq);
if(ether->mem)
i += snprint(buf+i, sizeof buf - i,
" addr %#lux", PADDR(ether->mem));
if(ether->size)
i += snprint(buf+i, sizeof buf - i,
" size %#luX", ether->size);
i += snprint(buf+i, sizeof buf - i,
": %2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux",
ether->ea[0], ether->ea[1], ether->ea[2],
ether->ea[3], ether->ea[4], ether->ea[5]);
snprint(buf+i, sizeof buf - i, "\n");
iprint("%s", buf); /* it may be too early for print */
if(ether->mbps >= 1000)
netifinit(ether, name, Ntypes, 4*1024*1024);
else if(ether->mbps >= 100)
netifinit(ether, name, Ntypes, 1024*1024);
else
netifinit(ether, name, Ntypes, 65*1024);
if(ether->oq == 0)
ether->oq = qopen(ether->limit, Qmsg, 0, 0);
if(ether->oq == 0)
panic("etherreset %s", name);
ether->alen = Eaddrlen;
memmove(ether->addr, ether->ea, Eaddrlen);
memset(ether->bcast, 0xFF, Eaddrlen);
etherxx[ctlrno] = ether;
ether = 0;
break;
}
}
if(ether)
free(ether);
}
static void
ethershutdown(void)
{
Ether *ether;
int i;
for(i = 0; i < MaxEther; i++){
ether = etherxx[i];
if(ether == nil)
continue;
if(ether->shutdown == nil) {
print("#l%d: no shutdown function\n", i);
continue;
}
(*ether->shutdown)(ether);
}
}
#define POLY 0xedb88320
/* really slow 32 bit crc for ethers */
ulong
ethercrc(uchar *p, int len)
{
int i, j;
ulong crc, b;
crc = 0xffffffff;
for(i = 0; i < len; i++){
b = *p++;
for(j = 0; j < 8; j++){
crc = (crc>>1) ^ (((crc^b) & 1) ? POLY : 0);
b >>= 1;
}
}
return crc;
}
void
dumpoq(Queue *oq)
{
if (oq == nil)
print("no outq! ");
else if (qisclosed(oq))
print("outq closed ");
else if (qfull(oq))
print("outq full ");
else
print("outq %d ", qlen(oq));
}
void
dumpnetif(Netif *netif)
{
print("netif %s ", netif->name);
print("limit %d mbps %d link %d ",
netif->limit, netif->mbps, netif->link);
print("inpkts %lld outpkts %lld errs %d\n",
netif->inpackets, netif->outpackets,
netif->crcs + netif->oerrs + netif->frames + netif->overflows +
netif->buffs + netif->soverflows);
}
Dev etherdevtab = {
'l',
"ether",
etherreset,
devinit,
ethershutdown,
etherattach,
etherwalk,
etherstat,
etheropen,
ethercreate,
etherclose,
etherread,
etherbread,
etherwrite,
etherbwrite,
devremove,
etherwstat,
};

View file

@ -235,7 +235,7 @@ dmastart(void *to, int tmode, void *from, int fmode, uint len, Rendez *rend,
*done = 0; *done = 0;
iunlock(&alloclck); iunlock(&alloclck);
ruplen = ROUNDUP(len, sizeof(ulong)); ruplen = ROUND(len, sizeof(ulong));
assert(to != from); assert(to != from);
cp = regs->chan + chan; cp = regs->chan + chan;

View file

@ -18,8 +18,7 @@
#include "io.h" #include "io.h"
#include "../port/error.h" #include "../port/error.h"
#include "../port/netif.h" #include "../port/netif.h"
#include "../port/etherif.h"
#include "etherif.h"
/* currently using kprocs is a lot slower than not (87 s. to boot vs 60) */ /* currently using kprocs is a lot slower than not (87 s. to boot vs 60) */
#undef USE_KPROCS #undef USE_KPROCS
@ -943,7 +942,6 @@ smcpnp(Ether* edev)
*/ */
edev->attach = smcattach; edev->attach = smcattach;
edev->transmit = smctransmitcall; edev->transmit = smctransmitcall;
edev->interrupt = smcinterrupt;
edev->ifstat = smcifstat; edev->ifstat = smcifstat;
/* edev->ctl = smcctl; /* no ctl msgs supported */ /* edev->ctl = smcctl; /* no ctl msgs supported */
@ -951,6 +949,9 @@ smcpnp(Ether* edev)
edev->promiscuous = smcpromiscuous; edev->promiscuous = smcpromiscuous;
edev->multicast = smcmulticast; edev->multicast = smcmulticast;
edev->shutdown = smcshutdown; edev->shutdown = smcshutdown;
intrenable(edev->irq, smcinterrupt, edev, 0, edev->name);
return 0; return 0;
} }

View file

@ -1,41 +0,0 @@
enum
{
MaxEther = 4,
Ntypes = 8,
};
typedef struct Ether Ether;
struct Ether {
RWlock;
ISAConf; /* hardware info */
int ctlrno;
int minmtu;
int maxmtu;
Netif;
void (*attach)(Ether*); /* filled in by reset routine */
void (*detach)(Ether*);
void (*transmit)(Ether*);
void (*interrupt)(Ureg*, void*);
long (*ifstat)(Ether*, void*, long, ulong);
long (*ctl)(Ether*, void*, long); /* custom ctl messages */
void (*power)(Ether*, int); /* power on/off */
void (*shutdown)(Ether*); /* shutdown hardware before reboot */
void* ctlr;
uchar ea[Eaddrlen];
void* address;
int irq;
Queue* oq;
};
extern Block* etheriq(Ether*, Block*, int);
extern void addethercard(char*, int(*)(Ether*));
extern ulong ethercrc(uchar*, int);
extern int parseether(uchar*, char*);
#define NEXT(x, l) (((x)+1)%(l))
#define PREV(x, l) (((x) == 0) ? (l)-1: (x)-1)

View file

@ -5,9 +5,6 @@
#define MiB 1048576u /* Mebi 0x0000000000100000 */ #define MiB 1048576u /* Mebi 0x0000000000100000 */
#define GiB 1073741824u /* Gibi 000000000040000000 */ #define GiB 1073741824u /* Gibi 000000000040000000 */
#define HOWMANY(x, y) (((x)+((y)-1))/(y))
#define ROUNDUP(x, y) (HOWMANY((x), (y))*(y)) /* ceiling */
#define ROUNDDN(x, y) (((x)/(y))*(y)) /* floor */
#define MIN(a, b) ((a) < (b)? (a): (b)) #define MIN(a, b) ((a) < (b)? (a): (b))
#define MAX(a, b) ((a) > (b)? (a): (b)) #define MAX(a, b) ((a) > (b)? (a): (b))
@ -36,7 +33,7 @@
*/ */
#define BY2PG (4*KiB) /* bytes per page */ #define BY2PG (4*KiB) /* bytes per page */
#define PGSHIFT 12 /* log(BY2PG) */ #define PGSHIFT 12 /* log(BY2PG) */
#define PGROUND(s) ROUNDUP(s, BY2PG) #define PGROUND(s) ROUND(s, BY2PG)
#define ROUND(s, sz) (((s)+(sz-1))&~(sz-1)) #define ROUND(s, sz) (((s)+(sz-1))&~(sz-1))
#define MAXMACH 1 /* max # cpus system can run */ #define MAXMACH 1 /* max # cpus system can run */
@ -71,7 +68,7 @@
#define UZERO 0 /* user segment */ #define UZERO 0 /* user segment */
#define UTZERO (UZERO+BY2PG) /* user text start */ #define UTZERO (UZERO+BY2PG) /* user text start */
#define UTROUND(t) ROUNDUP((t), BY2PG)
/* moved USTKTOP down to 512MB to keep MMIO space out of user space. */ /* moved USTKTOP down to 512MB to keep MMIO space out of user space. */
#define USTKTOP 0x20000000 /* user segment end +1 */ #define USTKTOP 0x20000000 /* user segment end +1 */
#define USTKSIZE (8*1024*1024) /* user stack size */ #define USTKSIZE (8*1024*1024) /* user stack size */

View file

@ -101,7 +101,7 @@ CFLAGS= -I. -I../port $CFLAGS # hack to compile private sysproc.c (e.g.)
arch.$O clock.$O fpiarm.$O main.$O mmu.$O screen.$O sdscsi.$O syscall.$O \ arch.$O clock.$O fpiarm.$O main.$O mmu.$O screen.$O sdscsi.$O syscall.$O \
trap.$O: /$objtype/include/ureg.h trap.$O: /$objtype/include/ureg.h
archomap.$O devether.$0 ether9221.$O: etherif.h ../port/netif.h archomap.$O devether.$0 ether9221.$O: ../port/etherif.h ../port/netif.h
archomap.$O devflash.$O flashbeagle.$O flashigep.$O: ../port/flashif.h archomap.$O devflash.$O flashbeagle.$O flashigep.$O: ../port/flashif.h
ecc.$O flashbeagle.$O flashigep.$O: ../port/nandecc.h io.h ecc.$O flashbeagle.$O flashigep.$O: ../port/nandecc.h io.h
fpi.$O fpiarm.$O fpimem.$O: fpi.h fpi.$O fpiarm.$O fpimem.$O: fpi.h

View file

@ -439,7 +439,7 @@ vmap(uintptr pa, usize size)
o = pa & (BY2PG-1); o = pa & (BY2PG-1);
pa -= o; pa -= o;
size += o; size += o;
size = ROUNDUP(size, BY2PG); size = PGROUND(size);
va = kseg0|pa; va = kseg0|pa;
pae = mmukmap(va, pa, size); pae = mmukmap(va, pa, size);

View file

@ -257,7 +257,7 @@ configdispc(void)
(sp->vsw-1); (sp->vsw-1);
dispc->pol_req = Ipc | Ihs | Ivs | Acb; dispc->pol_req = Ipc | Ihs | Ivs | Acb;
dispc->divisor = 1 << 16 | HOWMANY(432000, sp->pixelclock); dispc->divisor = 1 << 16 | ((432000+sp->pixelclock-1)/sp->pixelclock);
dispc->lcdsize = (sp->ht - 1) << 16 | (sp->wid - 1); dispc->lcdsize = (sp->ht - 1) << 16 | (sp->wid - 1);
coherence(); coherence();

View file

@ -6,8 +6,8 @@
#include "io.h" #include "io.h"
#include "../port/error.h" #include "../port/error.h"
#include "../port/netif.h" #include "../port/netif.h"
#include "../port/etherif.h"
#include "etherif.h"
#include "ether8390.h" #include "ether8390.h"
/* /*

View file

@ -16,8 +16,7 @@
#include "io.h" #include "io.h"
#include "../port/error.h" #include "../port/error.h"
#include "../port/netif.h" #include "../port/netif.h"
#include "../port/etherif.h"
#include "etherif.h"
#define DEBUG (0) #define DEBUG (0)
#define debug if(DEBUG)print #define debug if(DEBUG)print
@ -1818,7 +1817,6 @@ reset(Ether* ether)
*/ */
ether->attach = attach; ether->attach = attach;
ether->transmit = transmit; ether->transmit = transmit;
ether->interrupt = interrupt;
ether->ifstat = ifstat; ether->ifstat = ifstat;
ether->arg = ether; ether->arg = ether;
@ -1826,6 +1824,8 @@ reset(Ether* ether)
ether->multicast = multicast; ether->multicast = multicast;
ether->promiscuous = promiscuous; ether->promiscuous = promiscuous;
intrenable(ether->irq, interrupt, ether, ether->tbdf, ether->name);
return 0; return 0;
} }

View file

@ -11,8 +11,7 @@
#include "io.h" #include "io.h"
#include "../port/error.h" #include "../port/error.h"
#include "../port/netif.h" #include "../port/netif.h"
#include "../port/etherif.h"
#include "etherif.h"
enum { /* all windows */ enum { /* all windows */
CommandR = 0x000E, CommandR = 0x000E,

View file

@ -12,8 +12,7 @@
#include "io.h" #include "io.h"
#include "../port/error.h" #include "../port/error.h"
#include "../port/netif.h" #include "../port/netif.h"
#include "../port/etherif.h"
#include "etherif.h"
enum { enum {
Lognrdre = 6, Lognrdre = 6,
@ -672,7 +671,6 @@ reset(Ether* ether)
*/ */
ether->attach = attach; ether->attach = attach;
ether->transmit = transmit; ether->transmit = transmit;
ether->interrupt = interrupt;
ether->ifstat = ifstat; ether->ifstat = ifstat;
ether->arg = ether; ether->arg = ether;
@ -680,6 +678,8 @@ reset(Ether* ether)
ether->multicast = multicast; ether->multicast = multicast;
// ether->shutdown = shutdown; // ether->shutdown = shutdown;
intrenable(ether->irq, interrupt, ether, ether->tbdf, ether->name);
return 0; return 0;
} }

View file

@ -6,8 +6,8 @@
#include "io.h" #include "io.h"
#include "../port/error.h" #include "../port/error.h"
#include "../port/netif.h" #include "../port/netif.h"
#include "../port/etherif.h"
#include "etherif.h"
#include "ether8390.h" #include "ether8390.h"
/* /*

View file

@ -11,8 +11,7 @@
#include "io.h" #include "io.h"
#include "../port/error.h" #include "../port/error.h"
#include "../port/netif.h" #include "../port/netif.h"
#include "../port/etherif.h"
#include "etherif.h"
enum { /* registers */ enum { /* registers */
Idr0 = 0x0000, /* MAC address */ Idr0 = 0x0000, /* MAC address */
@ -817,7 +816,6 @@ rtl8139pnp(Ether* edev)
edev->attach = rtl8139attach; edev->attach = rtl8139attach;
edev->transmit = rtl8139transmit; edev->transmit = rtl8139transmit;
edev->interrupt = rtl8139interrupt;
edev->ifstat = rtl8139ifstat; edev->ifstat = rtl8139ifstat;
edev->arg = edev; edev->arg = edev;
@ -825,6 +823,8 @@ rtl8139pnp(Ether* edev)
edev->multicast = rtl8139multicast; edev->multicast = rtl8139multicast;
// edev->shutdown = rtl8139shutdown; // edev->shutdown = rtl8139shutdown;
intrenable(edev->irq, rtl8139interrupt, edev, edev->tbdf, edev->name);
/* /*
* This should be much more dynamic but will do for now. * This should be much more dynamic but will do for now.
*/ */

View file

@ -15,8 +15,8 @@
#include "io.h" #include "io.h"
#include "../port/error.h" #include "../port/error.h"
#include "../port/netif.h" #include "../port/netif.h"
#include "../port/etherif.h"
#include "etherif.h"
#include "ethermii.h" #include "ethermii.h"
enum { /* registers */ enum { /* registers */
@ -1207,7 +1207,6 @@ rtl8169pnp(Ether* edev)
edev->attach = rtl8169attach; edev->attach = rtl8169attach;
edev->transmit = rtl8169transmit; edev->transmit = rtl8169transmit;
edev->interrupt = rtl8169interrupt;
edev->ifstat = rtl8169ifstat; edev->ifstat = rtl8169ifstat;
edev->arg = edev; edev->arg = edev;
@ -1216,6 +1215,8 @@ rtl8169pnp(Ether* edev)
rtl8169link(edev); rtl8169link(edev);
intrenable(edev->irq, rtl8169interrupt, edev, edev->tbdf, edev->name);
return 0; return 0;
} }

View file

@ -18,8 +18,7 @@
#include "io.h" #include "io.h"
#include "../port/error.h" #include "../port/error.h"
#include "../port/netif.h" #include "../port/netif.h"
#include "../port/etherif.h"
#include "etherif.h"
enum { enum {
Ctrl = 0x00000000, /* Device Control */ Ctrl = 0x00000000, /* Device Control */

View file

@ -16,8 +16,7 @@
#include "io.h" #include "io.h"
#include "../port/error.h" #include "../port/error.h"
#include "../port/netif.h" #include "../port/netif.h"
#include "../port/etherif.h"
#include "etherif.h"
enum { enum {
Nrfd = 64, /* receive frame area */ Nrfd = 64, /* receive frame area */
@ -1332,7 +1331,6 @@ reset(Ether* ether)
*/ */
ether->attach = attach; ether->attach = attach;
ether->transmit = transmit; ether->transmit = transmit;
ether->interrupt = interrupt;
ether->ifstat = ifstat; ether->ifstat = ifstat;
ether->shutdown = shutdown; ether->shutdown = shutdown;
@ -1340,6 +1338,8 @@ reset(Ether* ether)
ether->multicast = multicast; ether->multicast = multicast;
ether->arg = ether; ether->arg = ether;
intrenable(ether->irq, interrupt, ether, ether->tbdf, ether->name);
return 0; return 0;
} }

View file

@ -11,8 +11,7 @@
#include "io.h" #include "io.h"
#include "../port/error.h" #include "../port/error.h"
#include "../port/netif.h" #include "../port/netif.h"
#include "../port/etherif.h"
#include "etherif.h"
/* /*
* note: the 82575, 82576 and 82580 are operated using registers aliased * note: the 82575, 82576 and 82580 are operated using registers aliased
@ -2105,7 +2104,6 @@ pnp(Ether *edev, int type)
*/ */
edev->attach = i82563attach; edev->attach = i82563attach;
// edev->transmit = i82563transmit; // edev->transmit = i82563transmit;
edev->interrupt = i82563interrupt;
edev->ifstat = i82563ifstat; edev->ifstat = i82563ifstat;
edev->ctl = i82563ctl; edev->ctl = i82563ctl;
@ -2114,6 +2112,8 @@ pnp(Ether *edev, int type)
edev->shutdown = i82563shutdown; edev->shutdown = i82563shutdown;
edev->multicast = i82563multicast; edev->multicast = i82563multicast;
intrenable(edev->irq, i82563interrupt, edev, edev->tbdf, edev->name);
return 0; return 0;
} }

View file

@ -10,7 +10,7 @@
#include "io.h" #include "io.h"
#include "../port/error.h" #include "../port/error.h"
#include "../port/netif.h" #include "../port/netif.h"
#include "etherif.h" #include "../port/etherif.h"
/* /*
* // comments note conflicts with 82563-style drivers, * // comments note conflicts with 82563-style drivers,
@ -953,12 +953,13 @@ pnp(Ether *e)
e->attach = attach; e->attach = attach;
e->ctl = ctl; e->ctl = ctl;
e->ifstat = ifstat; e->ifstat = ifstat;
e->interrupt = interrupt;
e->multicast = multicast; e->multicast = multicast;
e->promiscuous = promiscuous; e->promiscuous = promiscuous;
e->shutdown = shutdown; e->shutdown = shutdown;
e->transmit = transmit; e->transmit = transmit;
intrenable(e->irq, interrupt, e, e->tbdf, e->name);
return 0; return 0;
} }

View file

@ -24,8 +24,7 @@
#include "io.h" #include "io.h"
#include "../port/error.h" #include "../port/error.h"
#include "../port/netif.h" #include "../port/netif.h"
#include "../port/etherif.h"
#include "etherif.h"
#define DEBUG 0 #define DEBUG 0
#define debug if(DEBUG)print #define debug if(DEBUG)print
@ -1219,13 +1218,15 @@ reset(Ether* ether)
*/ */
ether->attach = attach; ether->attach = attach;
ether->transmit = transmit; ether->transmit = transmit;
ether->interrupt = interrupt;
ether->ifstat = ifstat; ether->ifstat = ifstat;
ether->arg = ether; ether->arg = ether;
ether->promiscuous = promiscuous; ether->promiscuous = promiscuous;
ether->multicast = multicast; ether->multicast = multicast;
ether->shutdown = shutdown; ether->shutdown = shutdown;
intrenable(ether->irq, interrupt, ether, ether->tbdf, ether->name);
return 0; return 0;
} }

View file

@ -10,8 +10,8 @@
#include "io.h" #include "io.h"
#include "../port/error.h" #include "../port/error.h"
#include "../port/netif.h" #include "../port/netif.h"
#include "../port/etherif.h"
#include "etherif.h"
#include "ether8390.h" #include "ether8390.h"
enum { /* NIC core registers */ enum { /* NIC core registers */
@ -801,12 +801,13 @@ dp8390reset(Ether* ether)
*/ */
ether->attach = attach; ether->attach = attach;
ether->transmit = transmit; ether->transmit = transmit;
ether->interrupt = interrupt;
ether->ifstat = 0; ether->ifstat = 0;
ether->promiscuous = promiscuous; ether->promiscuous = promiscuous;
ether->multicast = multicast; ether->multicast = multicast;
ether->arg = ether; ether->arg = ether;
intrenable(ether->irq, interrupt, ether, ether->tbdf, ether->name);
return 0; return 0;
} }

View file

@ -15,8 +15,7 @@
#include "io.h" #include "io.h"
#include "../port/error.h" #include "../port/error.h"
#include "../port/netif.h" #include "../port/netif.h"
#include "../port/etherif.h"
#include "etherif.h"
#define Rbsz ROUNDUP(sizeof(Etherpkt)+4, 4) #define Rbsz ROUNDUP(sizeof(Etherpkt)+4, 4)
@ -873,7 +872,6 @@ again:
edev->port = ctlr->port; edev->port = ctlr->port;
edev->irq = ctlr->pdev->intl; edev->irq = ctlr->pdev->intl;
edev->tbdf = ctlr->pdev->tbdf; edev->tbdf = ctlr->pdev->tbdf;
edev->interrupt = bcminterrupt;
edev->transmit = bcmtransmit; edev->transmit = bcmtransmit;
edev->multicast = bcmmulticast; edev->multicast = bcmmulticast;
edev->promiscuous = bcmpromiscuous; edev->promiscuous = bcmpromiscuous;
@ -884,6 +882,9 @@ again:
edev->ctlr = nil; edev->ctlr = nil;
goto again; goto again;
} }
intrenable(edev->irq, bcminterrupt, edev, edev->tbdf, edev->name);
return 0; return 0;
} }

View file

@ -12,8 +12,8 @@
#include "io.h" #include "io.h"
#include "../port/error.h" #include "../port/error.h"
#include "../port/netif.h" #include "../port/netif.h"
#include "../port/etherif.h"
#include "etherif.h"
#include "ethermii.h" #include "ethermii.h"
enum { /* Registers */ enum { /* Registers */
@ -1232,7 +1232,6 @@ dp83820pnp(Ether* edev)
edev->attach = dp83820attach; edev->attach = dp83820attach;
edev->transmit = dp83820transmit; edev->transmit = dp83820transmit;
edev->interrupt = dp83820interrupt;
edev->ifstat = dp83820ifstat; edev->ifstat = dp83820ifstat;
edev->arg = edev; edev->arg = edev;
@ -1240,6 +1239,8 @@ dp83820pnp(Ether* edev)
edev->multicast = dp83820multicast; edev->multicast = dp83820multicast;
edev->shutdown = dp83820shutdown; edev->shutdown = dp83820shutdown;
intrenable(edev->irq, dp83820interrupt, edev, edev->tbdf, edev->name);
return 0; return 0;
} }

View file

@ -9,8 +9,8 @@
#include "io.h" #include "io.h"
#include "../port/error.h" #include "../port/error.h"
#include "../port/netif.h" #include "../port/netif.h"
#include "../port/etherif.h"
#include "etherif.h"
#include "ether8390.h" #include "ether8390.h"
enum { enum {

View file

@ -16,8 +16,7 @@
#include "io.h" #include "io.h"
#include "../port/error.h" #include "../port/error.h"
#include "../port/netif.h" #include "../port/netif.h"
#include "../port/etherif.h"
#include "etherif.h"
#define XCVRDEBUG if(0)print #define XCVRDEBUG if(0)print
@ -2124,7 +2123,6 @@ etherelnk3reset(Ether* ether)
*/ */
ether->attach = attach; ether->attach = attach;
ether->transmit = transmit; ether->transmit = transmit;
ether->interrupt = interrupt;
ether->ifstat = ifstat; ether->ifstat = ifstat;
ether->promiscuous = promiscuous; ether->promiscuous = promiscuous;
@ -2132,6 +2130,8 @@ etherelnk3reset(Ether* ether)
ether->shutdown = shutdown; ether->shutdown = shutdown;
ether->arg = ether; ether->arg = ether;
intrenable(ether->irq, interrupt, ether, ether->tbdf, ether->name);
return 0; return 0;
} }

View file

@ -18,10 +18,9 @@
#include "io.h" #include "io.h"
#include "../port/error.h" #include "../port/error.h"
#include "../port/netif.h" #include "../port/netif.h"
#include "../port/etherif.h"
#define malign(n) xspanalloc((n), 32, 0) #define malign(n) xspanalloc((n), 32, 0)
#include "etherif.h"
#include "etherga620fw.h" #include "etherga620fw.h"
enum { enum {
@ -1260,7 +1259,6 @@ ga620pnp(Ether* edev)
*/ */
edev->attach = ga620attach; edev->attach = ga620attach;
edev->transmit = ga620transmit; edev->transmit = ga620transmit;
edev->interrupt = ga620interrupt;
edev->ifstat = ga620ifstat; edev->ifstat = ga620ifstat;
edev->ctl = ga620ctl; edev->ctl = ga620ctl;
@ -1269,6 +1267,8 @@ ga620pnp(Ether* edev)
edev->multicast = ga620multicast; edev->multicast = ga620multicast;
edev->shutdown = ga620shutdown; edev->shutdown = ga620shutdown;
intrenable(edev->irq, ga620interrupt, edev, edev->tbdf, edev->name);
return 0; return 0;
} }

View file

@ -1,39 +0,0 @@
enum {
MaxEther = 64,
Ntypes = 8,
};
typedef struct Ether Ether;
struct Ether {
ISAConf; /* hardware info */
int ctlrno;
int tbdf; /* type+busno+devno+funcno */
int minmtu;
int maxmtu;
uchar ea[Eaddrlen];
void (*attach)(Ether*); /* filled in by reset routine */
void (*detach)(Ether*);
void (*transmit)(Ether*);
void (*interrupt)(Ureg*, void*);
long (*ifstat)(Ether*, void*, long, ulong);
long (*ctl)(Ether*, void*, long); /* custom ctl messages */
void (*power)(Ether*, int); /* power on/off */
void (*shutdown)(Ether*); /* shutdown hardware before reboot */
void *ctlr;
Queue* oq;
Netif;
};
extern Block* etheriq(Ether*, Block*, int);
extern void addethercard(char*, int(*)(Ether*));
extern ulong ethercrc(uchar*, int);
extern int parseether(uchar*, char*);
#define NEXT(x, l) (((x)+1)%(l))
#define PREV(x, l) (((x) == 0) ? (l)-1: (x)-1)
#define HOWMANY(x, y) (((x)+((y)-1))/(y))
#define ROUNDUP(x, y) (HOWMANY((x), (y))*(y))

View file

@ -24,8 +24,8 @@
#include "io.h" #include "io.h"
#include "../port/error.h" #include "../port/error.h"
#include "../port/netif.h" #include "../port/netif.h"
#include "../port/etherif.h"
#include "etherif.h"
#include "ethermii.h" #include "ethermii.h"
enum { enum {
@ -2020,7 +2020,6 @@ igbepnp(Ether* edev)
*/ */
edev->attach = igbeattach; edev->attach = igbeattach;
edev->transmit = igbetransmit; edev->transmit = igbetransmit;
edev->interrupt = igbeinterrupt;
edev->ifstat = igbeifstat; edev->ifstat = igbeifstat;
edev->ctl = igbectl; edev->ctl = igbectl;
@ -2029,6 +2028,8 @@ igbepnp(Ether* edev)
edev->shutdown = igbeshutdown; edev->shutdown = igbeshutdown;
edev->multicast = igbemulticast; edev->multicast = igbemulticast;
intrenable(edev->irq, igbeinterrupt, edev, edev->tbdf, edev->name);
return 0; return 0;
} }

View file

@ -14,9 +14,8 @@
#include "io.h" #include "io.h"
#include "../port/error.h" #include "../port/error.h"
#include "../port/netif.h" #include "../port/netif.h"
#include "../port/etherif.h"
#include "etherif.h" #include "../port/wifi.h"
#include "wifi.h"
enum { enum {
MaxQueue = 24*1024, /* total buffer is 2*MaxQueue: 48k at 22Mbit ≅ 20ms */ MaxQueue = 24*1024, /* total buffer is 2*MaxQueue: 48k at 22Mbit ≅ 20ms */
@ -2534,7 +2533,6 @@ again:
edev->irq = ctlr->pdev->intl; edev->irq = ctlr->pdev->intl;
edev->tbdf = ctlr->pdev->tbdf; edev->tbdf = ctlr->pdev->tbdf;
edev->arg = edev; edev->arg = edev;
edev->interrupt = iwlinterrupt;
edev->attach = iwlattach; edev->attach = iwlattach;
edev->ifstat = iwlifstat; edev->ifstat = iwlifstat;
edev->ctl = iwlctl; edev->ctl = iwlctl;
@ -2547,6 +2545,8 @@ again:
edev->ctlr = nil; edev->ctlr = nil;
goto again; goto again;
} }
intrenable(edev->irq, iwlinterrupt, edev, edev->tbdf, edev->name);
return 0; return 0;
} }

View file

@ -14,8 +14,7 @@
#include "io.h" #include "io.h"
#include "../port/error.h" #include "../port/error.h"
#include "../port/netif.h" #include "../port/netif.h"
#include "../port/etherif.h"
#include "../pc/etherif.h"
#ifndef KiB #ifndef KiB
#define KiB 1024u /* Kibi 0x0000000000000400 */ #define KiB 1024u /* Kibi 0x0000000000000400 */

View file

@ -6,8 +6,8 @@
#include "io.h" #include "io.h"
#include "../port/error.h" #include "../port/error.h"
#include "../port/netif.h" #include "../port/netif.h"
#include "../port/etherif.h"
#include "etherif.h"
#include "ethermii.h" #include "ethermii.h"
int int

View file

@ -14,9 +14,8 @@
#include "io.h" #include "io.h"
#include "../port/error.h" #include "../port/error.h"
#include "../port/netif.h" #include "../port/netif.h"
#include "../port/etherif.h"
#include "etherif.h" #include "../port/wifi.h"
#include "wifi.h"
/* for consistency */ /* for consistency */
typedef signed char s8int; typedef signed char s8int;
@ -3544,7 +3543,6 @@ again:
edev->irq = ctlr->pdev->intl; edev->irq = ctlr->pdev->intl;
edev->tbdf = ctlr->pdev->tbdf; edev->tbdf = ctlr->pdev->tbdf;
edev->arg = edev; edev->arg = edev;
edev->interrupt = rt2860interrupt;
edev->attach = rt2860attach; edev->attach = rt2860attach;
edev->ifstat = rt2860ifstat; edev->ifstat = rt2860ifstat;
edev->ctl = rt2860ctl; edev->ctl = rt2860ctl;
@ -3556,6 +3554,9 @@ again:
edev->ctlr = nil; edev->ctlr = nil;
goto again; goto again;
} }
intrenable(edev->irq, rt2860interrupt, edev, edev->tbdf, edev->name);
return 0; return 0;
} }

View file

@ -10,7 +10,7 @@
#include "io.h" #include "io.h"
#include "../port/error.h" #include "../port/error.h"
#include "../port/netif.h" #include "../port/netif.h"
#include "etherif.h" #include "../port/etherif.h"
enum { enum {
IoSize = 0x10, /* port pool size */ IoSize = 0x10, /* port pool size */
@ -766,12 +766,15 @@ reset(Ether* ether)
ether->attach = attach; ether->attach = attach;
ether->transmit = transmit; ether->transmit = transmit;
ether->interrupt = interrupt;
ether->ifstat = ifstat; ether->ifstat = ifstat;
ether->promiscuous = promiscuous; ether->promiscuous = promiscuous;
ether->multicast = multicast; ether->multicast = multicast;
ether->arg = ether; ether->arg = ether;
iunlock(ctlr); iunlock(ctlr);
intrenable(ether->irq, interrupt, ether, ether->tbdf, ether->name);
return 0; return 0;
} }

View file

@ -29,8 +29,8 @@
#include "io.h" #include "io.h"
#include "../port/error.h" #include "../port/error.h"
#include "../port/netif.h" #include "../port/netif.h"
#include "../port/etherif.h"
#include "etherif.h"
#include "ethermii.h" #include "ethermii.h"
#define DEBUG #define DEBUG
@ -1137,14 +1137,15 @@ vgbepnp(Ether* edev)
memmove(edev->ea, ctlr->ea, Eaddrlen); memmove(edev->ea, ctlr->ea, Eaddrlen);
edev->attach = vgbeattach; edev->attach = vgbeattach;
edev->transmit = vgbetransmit; edev->transmit = vgbetransmit;
edev->interrupt = vgbeinterrupt;
edev->ifstat = vgbeifstat; edev->ifstat = vgbeifstat;
// edev->promiscuous = vgbepromiscuous; // edev->promiscuous = vgbepromiscuous;
edev->multicast = vgbemulticast; edev->multicast = vgbemulticast;
// edev->shutdown = vgbeshutdown; // edev->shutdown = vgbeshutdown;
edev->ctl = vgbectl; edev->ctl = vgbectl;
edev->arg = edev; edev->arg = edev;
intrenable(edev->irq, vgbeinterrupt, edev, edev->tbdf, edev->name);
return 0; return 0;
} }

View file

@ -6,7 +6,7 @@
#include "io.h" #include "io.h"
#include "../port/error.h" #include "../port/error.h"
#include "../port/netif.h" #include "../port/netif.h"
#include "etherif.h" #include "../port/etherif.h"
/* /*
* virtio ethernet driver * virtio ethernet driver
@ -661,7 +661,6 @@ reset(Ether* edev)
edev->attach = attach; edev->attach = attach;
edev->shutdown = shutdown; edev->shutdown = shutdown;
edev->interrupt = interrupt;
edev->ifstat = ifstat; edev->ifstat = ifstat;
if((ctlr->feat & (Fctrlvq|Fctrlrx)) == (Fctrlvq|Fctrlrx)){ if((ctlr->feat & (Fctrlvq|Fctrlrx)) == (Fctrlvq|Fctrlrx)){
@ -669,6 +668,8 @@ reset(Ether* edev)
edev->promiscuous = promiscuous; edev->promiscuous = promiscuous;
} }
intrenable(edev->irq, interrupt, edev, edev->tbdf, edev->name);
return 0; return 0;
} }

View file

@ -17,8 +17,8 @@
#include "io.h" #include "io.h"
#include "../port/error.h" #include "../port/error.h"
#include "../port/netif.h" #include "../port/netif.h"
#include "../port/etherif.h"
#include "etherif.h"
#include "ethermii.h" #include "ethermii.h"
enum { enum {
@ -1032,7 +1032,6 @@ vt6102pnp(Ether* edev)
*/ */
edev->attach = vt6102attach; edev->attach = vt6102attach;
edev->transmit = vt6102transmit; edev->transmit = vt6102transmit;
edev->interrupt = vt6102interrupt;
edev->ifstat = vt6102ifstat; edev->ifstat = vt6102ifstat;
edev->ctl = nil; edev->ctl = nil;
@ -1040,6 +1039,8 @@ vt6102pnp(Ether* edev)
edev->promiscuous = vt6102promiscuous; edev->promiscuous = vt6102promiscuous;
edev->multicast = vt6102multicast; edev->multicast = vt6102multicast;
intrenable(edev->irq, vt6102interrupt, edev, edev->tbdf, edev->name);
return 0; return 0;
} }

View file

@ -20,8 +20,8 @@
#include "io.h" #include "io.h"
#include "../port/error.h" #include "../port/error.h"
#include "../port/netif.h" #include "../port/netif.h"
#include "../port/etherif.h"
#include "etherif.h"
#include "ethermii.h" #include "ethermii.h"
enum { enum {
@ -1200,7 +1200,6 @@ vt6105Mpnp(Ether* edev)
*/ */
edev->attach = vt6105Mattach; edev->attach = vt6105Mattach;
edev->transmit = vt6105Mtransmit; edev->transmit = vt6105Mtransmit;
edev->interrupt = vt6105Minterrupt;
edev->ifstat = vt6105Mifstat; edev->ifstat = vt6105Mifstat;
edev->ctl = nil; edev->ctl = nil;
@ -1210,6 +1209,8 @@ vt6105Mpnp(Ether* edev)
edev->maxmtu = ETHERMAXTU+Bslop; edev->maxmtu = ETHERMAXTU+Bslop;
intrenable(edev->irq, vt6105Minterrupt, edev, edev->tbdf, edev->name);
return 0; return 0;
} }

View file

@ -8,7 +8,7 @@
#include "io.h" #include "io.h"
#include "../port/error.h" #include "../port/error.h"
#include "../port/netif.h" #include "../port/netif.h"
#include "etherif.h" #include "../port/etherif.h"
#include "wavelan.h" #include "wavelan.h"

View file

@ -6,9 +6,8 @@
#include "io.h" #include "io.h"
#include "../port/error.h" #include "../port/error.h"
#include "../port/netif.h" #include "../port/netif.h"
#include "../port/etherif.h"
#include "etherif.h" #include "../port/wifi.h"
#include "wifi.h"
enum { enum {
MaxQueue = 24*1024, /* total buffer is 2*MaxQueue: 48k at 22Mbit ≅ 20ms */ MaxQueue = 24*1024, /* total buffer is 2*MaxQueue: 48k at 22Mbit ≅ 20ms */
@ -1846,7 +1845,6 @@ again:
edev->irq = ctlr->pdev->intl; edev->irq = ctlr->pdev->intl;
edev->tbdf = ctlr->pdev->tbdf; edev->tbdf = ctlr->pdev->tbdf;
edev->arg = edev; edev->arg = edev;
edev->interrupt = wpiinterrupt;
edev->attach = wpiattach; edev->attach = wpiattach;
edev->ifstat = wpiifstat; edev->ifstat = wpiifstat;
edev->ctl = wpictl; edev->ctl = wpictl;
@ -1860,6 +1858,8 @@ again:
goto again; goto again;
} }
intrenable(edev->irq, wpiinterrupt, edev, edev->tbdf, edev->name);
return 0; return 0;
} }

View file

@ -10,7 +10,7 @@
#include "io.h" #include "io.h"
#include "../port/error.h" #include "../port/error.h"
#include "../port/netif.h" #include "../port/netif.h"
#include "etherif.h" #include "../port/etherif.h"
#define Pciwaddrh(x) 0 #define Pciwaddrh(x) 0
#define Pciwaddrl(x) PCIWADDR(x) #define Pciwaddrl(x) PCIWADDR(x)
@ -2247,12 +2247,13 @@ pnp(Ether *e)
e->attach = attach; e->attach = attach;
e->ctl = ctl; e->ctl = ctl;
e->ifstat = ifstat; e->ifstat = ifstat;
e->interrupt = interrupt;
e->multicast = multicast; e->multicast = multicast;
e->promiscuous = promiscuous; e->promiscuous = promiscuous;
e->shutdown = shutdown; e->shutdown = shutdown;
e->transmit = nil; e->transmit = nil;
intrenable(e->irq, interrupt, e, e->tbdf, e->name);
return 0; return 0;
} }

View file

@ -100,7 +100,7 @@ install:V: $p$CONF
<../port/portmkfile <../port/portmkfile
<|../port/mkbootrules $CONF <|../port/mkbootrules $CONF
$ETHER: etherif.h ../port/netif.h $ETHER: ../port/etherif.h ../port/netif.h
$AUDIO: ../port/audioif.h $AUDIO: ../port/audioif.h
ether8003.$O ether8390.$O: ether8390.h ether8003.$O ether8390.$O: ether8390.h
etheryuk.$O: yukdump.h etheryuk.$O: yukdump.h
@ -122,11 +122,9 @@ usbehci.$O usbehcipc.$O: usbehci.h
trap.$O: /sys/include/tos.h trap.$O: /sys/include/tos.h
uartaxp.$O: uartaxp.i uartaxp.$O: uartaxp.i
etherm10g.$O: etherm10g2k.i etherm10g4k.i etherm10g.$O: etherm10g2k.i etherm10g4k.i
etheriwl.$O: wifi.h etheriwl.$O: ../port/wifi.h
etherwpi.$O: wifi.h etherwpi.$O: ../port/wifi.h
etherrt2860.$O: wifi.h etherrt2860.$O: ../port/wifi.h
wifi.$O: wifi.h etherif.h ../port/netif.h /sys/include/libsec.h
wifi.$O: ../ip/ip.h ../ip/ipv6.h
init.h:D: ../port/initcode.c init9.c init.h:D: ../port/initcode.c init9.c
$CC ../port/initcode.c $CC ../port/initcode.c

View file

@ -40,13 +40,20 @@ intrenable(int irq, void (*f)(Ureg*, void*), void* a, int tbdf, char *name)
irq, tbdf, name); irq, tbdf, name);
return; return;
} }
if(tbdf != BUSUNKNOWN && (irq == 0xff || irq == 0)){ if(tbdf != BUSUNKNOWN && (irq == 0xff || irq == 0)){
print("intrenable: got unassigned irq %d, tbdf 0x%uX for %s\n", print("intrenable: got unassigned irq %d, tbdf 0x%uX for %s\n",
irq, tbdf, name); irq, tbdf, name);
irq = -1; irq = -1;
} }
/*
* IRQ2 doesn't really exist, it's used to gang the interrupt
* controllers together. A device set to IRQ2 will appear on
* the second interrupt controller as IRQ9.
*/
if(irq == 2)
irq = 9;
if((v = xalloc(sizeof(Vctl))) == nil) if((v = xalloc(sizeof(Vctl))) == nil)
panic("intrenable: out of memory"); panic("intrenable: out of memory");
v->isintr = 1; v->isintr = 1;
@ -83,6 +90,8 @@ intrdisable(int irq, void (*f)(Ureg *, void *), void *a, int tbdf, char *name)
Vctl **pv, *v; Vctl **pv, *v;
int vno; int vno;
if(irq == 2)
irq = 9;
if(arch->intrvecno == nil || (tbdf != BUSUNKNOWN && (irq == 0xff || irq == 0))){ if(arch->intrvecno == nil || (tbdf != BUSUNKNOWN && (irq == 0xff || irq == 0))){
/* /*
* on APIC machine, irq is pretty meaningless * on APIC machine, irq is pretty meaningless

View file

@ -272,16 +272,6 @@ reset(Hci *hp)
ehcilinkage(hp); ehcilinkage(hp);
hp->shutdown = shutdown; hp->shutdown = shutdown;
hp->debug = setdebug; hp->debug = setdebug;
if(hp->interrupt == nil)
return 0;
/*
* IRQ2 doesn't really exist, it's used to gang the interrupt
* controllers together. A device set to IRQ2 will appear on
* the second interrupt controller as IRQ9.
*/
if(hp->irq == 2)
hp->irq = 9;
intrenable(hp->irq, hp->interrupt, hp, hp->tbdf, hp->type); intrenable(hp->irq, hp->interrupt, hp, hp->tbdf, hp->type);
return 0; return 0;

View file

@ -2608,14 +2608,6 @@ reset(Hci *hp)
hp->shutdown = shutdown; hp->shutdown = shutdown;
hp->debug = usbdebug; hp->debug = usbdebug;
hp->type = "ohci"; hp->type = "ohci";
/*
* IRQ2 doesn't really exist, it's used to gang the interrupt
* controllers together. A device set to IRQ2 will appear on
* the second interrupt controller as IRQ9.
*/
if(hp->irq == 2)
hp->irq = 9;
intrenable(hp->irq, hp->interrupt, hp, hp->tbdf, hp->type); intrenable(hp->irq, hp->interrupt, hp, hp->tbdf, hp->type);
return 0; return 0;

View file

@ -2345,14 +2345,6 @@ reset(Hci *hp)
hp->shutdown = shutdown; hp->shutdown = shutdown;
hp->debug = setdebug; hp->debug = setdebug;
hp->type = "uhci"; hp->type = "uhci";
/*
* IRQ2 doesn't really exist, it's used to gang the interrupt
* controllers together. A device set to IRQ2 will appear on
* the second interrupt controller as IRQ9.
*/
if(hp->irq == 2)
hp->irq = 9;
intrenable(hp->irq, hp->interrupt, hp, hp->tbdf, hp->type); intrenable(hp->irq, hp->interrupt, hp, hp->tbdf, hp->type);
return 0; return 0;

View file

@ -25,7 +25,8 @@
#include "io.h" #include "io.h"
#include "../port/error.h" #include "../port/error.h"
#include "../port/netif.h" #include "../port/netif.h"
#include "etherif.h" #include "../port/etherif.h"
#include "wavelan.h" #include "wavelan.h"
enum enum
@ -1234,7 +1235,6 @@ wavelanreset(Ether* ether, Ctlr *ctlr)
ether->mbps = 10; ether->mbps = 10;
ether->attach = w_attach; ether->attach = w_attach;
ether->detach = w_detach; ether->detach = w_detach;
ether->interrupt = w_interrupt;
ether->transmit = w_transmit; ether->transmit = w_transmit;
ether->ifstat = w_ifstat; ether->ifstat = w_ifstat;
ether->ctl = w_ctl; ether->ctl = w_ctl;
@ -1244,6 +1244,8 @@ wavelanreset(Ether* ether, Ctlr *ctlr)
ether->scanbs = w_scanbs; ether->scanbs = w_scanbs;
ether->arg = ether; ether->arg = ether;
intrenable(ether->irq, w_interrupt, ether, ether->tbdf, ether->name);
DEBUG("#l%d: irq %d port %lx type %s", DEBUG("#l%d: irq %d port %lx type %s",
ether->ctlrno, ether->irq, ether->port, ether->type); ether->ctlrno, ether->irq, ether->port, ether->type);
DEBUG(" %2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux\n", DEBUG(" %2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux\n",

View file

@ -83,7 +83,7 @@ install:V: $p$CONF
# copies generated by the rule below # copies generated by the rule below
PCHEADERS=wifi.h usbehci.h screen.h etherif.h ethermii.h mp.h io.h ahci.h \ PCHEADERS=usbehci.h screen.h ethermii.h mp.h io.h ahci.h \
yukdump.h yukdump.h
REPCH=`{echo $PCHEADERS | sed 's/\.h//g; s/ /|/g'} REPCH=`{echo $PCHEADERS | sed 's/\.h//g; s/ /|/g'}
@ -100,7 +100,7 @@ REPCC=`{../port/mkfilelist ../pc}
l.$O apbootstrap.$O: mem.h l.$O apbootstrap.$O: mem.h
$ETHER: etherif.h ../port/netif.h $ETHER: ../port/etherif.h ../port/netif.h
$AUDIO: ../port/audioif.h $AUDIO: ../port/audioif.h
ether8003.$O ether8390.$O: ether8390.h ether8003.$O ether8390.$O: ether8390.h
etheryuk.$O: yukdump.h etheryuk.$O: yukdump.h
@ -122,11 +122,9 @@ usbehci.$O usbehcipc.$O: usbehci.h
trap.$O: /sys/include/tos.h trap.$O: /sys/include/tos.h
ethermii.$O: ethermii.h ethermii.$O: ethermii.h
etheriwl.$O: wifi.h etheriwl.$O: ../port/wifi.h
etherwpi.$O: wifi.h etherwpi.$O: ../port/wifi.h
etherrt2860.$O: wifi.h etherrt2860.$O: ../port/wifi.h
wifi.$O: wifi.h etherif.h ../port/netif.h /sys/include/libsec.h
wifi.$O: ../ip/ip.h ../ip/ipv6.h
init.h:D: ../port/initcode.c ../pc/init9.c init.h:D: ../port/initcode.c ../pc/init9.c
$CC ../port/initcode.c $CC ../port/initcode.c

View file

@ -47,6 +47,15 @@ intrenable(int irq, void (*f)(Ureg*, void*), void* a, int tbdf, char *name)
irq = -1; irq = -1;
} }
/*
* IRQ2 doesn't really exist, it's used to gang the interrupt
* controllers together. A device set to IRQ2 will appear on
* the second interrupt controller as IRQ9.
*/
if(irq == 2)
irq = 9;
if((v = xalloc(sizeof(Vctl))) == nil) if((v = xalloc(sizeof(Vctl))) == nil)
panic("intrenable: out of memory"); panic("intrenable: out of memory");
v->isintr = 1; v->isintr = 1;
@ -83,6 +92,8 @@ intrdisable(int irq, void (*f)(Ureg *, void *), void *a, int tbdf, char *name)
Vctl **pv, *v; Vctl **pv, *v;
int vno; int vno;
if(irq == 2)
irq = 9;
if(arch->intrvecno == nil || (tbdf != BUSUNKNOWN && (irq == 0xff || irq == 0))){ if(arch->intrvecno == nil || (tbdf != BUSUNKNOWN && (irq == 0xff || irq == 0))){
/* /*
* on APIC machine, irq is pretty meaningless * on APIC machine, irq is pretty meaningless

View file

@ -12,7 +12,7 @@
#include "ureg.h" #include "ureg.h"
#include "../port/error.h" #include "../port/error.h"
#include "../port/netif.h" #include "../port/netif.h"
#include "etherif.h" #include "../port/etherif.h"
#include "../ip/ip.h" #include "../ip/ip.h"
#include "../port/aoe.h" #include "../port/aoe.h"
#include <fis.h> #include <fis.h>

View file

@ -8,8 +8,9 @@
#include "ureg.h" #include "ureg.h"
#include "../port/error.h" #include "../port/error.h"
#include "../port/netif.h" #include "../port/netif.h"
#include "../port/etherif.h"
#include "etherif.h" extern int eipfmt(Fmt*);
static Ether *etherxx[MaxEther]; static Ether *etherxx[MaxEther];
@ -348,7 +349,6 @@ etherprobe(int cardno, int ctlrno)
int i, lg; int i, lg;
ulong mb, bsz; ulong mb, bsz;
Ether *ether; Ether *ether;
char buf[128], name[32];
ether = malloc(sizeof(Ether)); ether = malloc(sizeof(Ether));
if(ether == nil){ if(ether == nil){
@ -356,8 +356,9 @@ etherprobe(int cardno, int ctlrno)
return nil; return nil;
} }
memset(ether, 0, sizeof(Ether)); memset(ether, 0, sizeof(Ether));
ether->ctlrno = ctlrno;
ether->tbdf = BUSUNKNOWN; ether->tbdf = BUSUNKNOWN;
ether->irq = -1;
ether->ctlrno = ctlrno;
ether->mbps = 10; ether->mbps = 10;
ether->minmtu = ETHERMINTU; ether->minmtu = ETHERMINTU;
ether->maxmtu = ETHERMAXTU; ether->maxmtu = ETHERMAXTU;
@ -384,38 +385,15 @@ etherprobe(int cardno, int ctlrno)
free(ether); free(ether);
return nil; return nil;
} }
snprint(ether->name, sizeof(ether->name), "ether%d", ctlrno);
if(cards[cardno].reset(ether) < 0){ if(cards[cardno].reset(ether) < 0){
free(ether); free(ether);
return nil; return nil;
} }
/* print("#l%d: %s: %dMbps port 0x%luX irq %d ea %E\n",
* IRQ2 doesn't really exist, it's used to gang the interrupt ctlrno, cards[cardno].type,
* controllers together. A device set to IRQ2 will appear on ether->mbps, ether->port, ether->irq, ether->ea);
* the second interrupt controller as IRQ9.
*/
if(ether->irq == 2)
ether->irq = 9;
snprint(name, sizeof(name), "ether%d", ctlrno);
/*
* If ether->irq is <0, it is a hack to indicate no interrupt
* used by ethersink.
*/
if(ether->irq >= 0)
intrenable(ether->irq, ether->interrupt, ether, ether->tbdf, name);
i = sprint(buf, "#l%d: %s: %dMbps port 0x%luX irq %d",
ctlrno, cards[cardno].type, ether->mbps, ether->port, ether->irq);
if(ether->mem)
i += sprint(buf+i, " addr 0x%luX", ether->mem);
if(ether->size)
i += sprint(buf+i, " size 0x%luX", ether->size);
i += sprint(buf+i, ": %2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux",
ether->ea[0], ether->ea[1], ether->ea[2],
ether->ea[3], ether->ea[4], ether->ea[5]);
sprint(buf+i, "\n");
print(buf);
/* compute log10(ether->mbps) into lg */ /* compute log10(ether->mbps) into lg */
for(lg = 0, mb = ether->mbps; mb >= 10; lg++) for(lg = 0, mb = ether->mbps; mb >= 10; lg++)
@ -429,13 +407,14 @@ etherprobe(int cardno, int ctlrno)
while (bsz > mainmem->maxsize / 8 && bsz > 128*1024) while (bsz > mainmem->maxsize / 8 && bsz > 128*1024)
bsz /= 2; bsz /= 2;
netifinit(ether, name, Ntypes, bsz); netifinit(ether, ether->name, Ntypes, bsz);
if(ether->oq == nil) { if(ether->oq == nil) {
ether->oq = qopen(bsz, Qmsg, 0, 0); ether->oq = qopen(bsz, Qmsg, 0, 0);
ether->limit = bsz; ether->limit = bsz;
} }
if(ether->oq == nil) if(ether->oq == nil)
panic("etherreset %s: can't allocate output queue of %ld bytes", name, bsz); panic("etherreset %s: can't allocate output queue of %ld bytes", ether->name, bsz);
ether->alen = Eaddrlen; ether->alen = Eaddrlen;
memmove(ether->addr, ether->ea, Eaddrlen); memmove(ether->addr, ether->ea, Eaddrlen);
memset(ether->bcast, 0xFF, Eaddrlen); memset(ether->bcast, 0xFF, Eaddrlen);
@ -449,6 +428,8 @@ etherreset(void)
Ether *ether; Ether *ether;
int cardno, ctlrno; int cardno, ctlrno;
fmtinstall('E', eipfmt);
for(ctlrno = 0; ctlrno < MaxEther; ctlrno++){ for(ctlrno = 0; ctlrno < MaxEther; ctlrno++){
if((ether = etherprobe(-1, ctlrno)) == nil) if((ether = etherprobe(-1, ctlrno)) == nil)
continue; continue;

View file

@ -10,7 +10,7 @@
#include "io.h" #include "io.h"
#include "../port/error.h" #include "../port/error.h"
#include "../port/netif.h" #include "../port/netif.h"
#include "etherif.h" #include "../port/etherif.h"
static long static long
ctl(Ether *ether, void *buf, long n) ctl(Ether *ether, void *buf, long n)
@ -40,16 +40,11 @@ nop(Ether*)
static int static int
reset(Ether* ether) reset(Ether* ether)
{ {
uchar ea[Eaddrlen];
if(ether->type==nil) if(ether->type==nil)
return -1; return -1;
memset(ea, 0, sizeof ea);
ether->mbps = 1000; ether->mbps = 1000;
ether->attach = nop; ether->attach = nop;
ether->transmit = nop; ether->transmit = nop;
ether->irq = -1;
ether->interrupt = nil;
ether->ifstat = nil; ether->ifstat = nil;
ether->ctl = ctl; ether->ctl = ctl;
ether->promiscuous = nil; ether->promiscuous = nil;

View file

@ -101,3 +101,6 @@ devaoe.$O sdaoe.$O: /sys/include/fis.h
sysproc.$O: /sys/include/a.out.h sysproc.$O: /sys/include/a.out.h
syscallfmt.$O: /sys/src/libc/9syscall/sys.h syscallfmt.$O: /sys/src/libc/9syscall/sys.h
devusb.$O: ../port/usb.h devusb.$O: ../port/usb.h
devether.$O: ../port/etherif.h ../port/netif.h
wifi.$O: ../port/etherif.h ../port/netif.h ../port/wifi.h /sys/include/libsec.h
wifi.$O: ../ip/ip.h ../ip/ipv6.h

View file

@ -7,9 +7,8 @@
#include "ureg.h" #include "ureg.h"
#include "../port/error.h" #include "../port/error.h"
#include "../port/netif.h" #include "../port/netif.h"
#include "../port/etherif.h"
#include "etherif.h" #include "../port/wifi.h"
#include "wifi.h"
#include <libsec.h> #include <libsec.h>

View file

@ -1,446 +0,0 @@
#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"
#include "../port/netif.h"
#include "etherif.h"
static Ether *etherxx[MaxEther];
extern uchar etheraddr[];
Chan*
etherattach(char* spec)
{
ulong ctlrno;
char *p;
Chan *chan;
ctlrno = 0;
if(spec && *spec){
ctlrno = strtoul(spec, &p, 0);
if((ctlrno == 0 && p == spec) || *p || (ctlrno >= MaxEther))
error(Ebadarg);
}
if(etherxx[ctlrno] == 0)
error(Enodev);
chan = devattach('l', spec);
chan->dev = ctlrno;
if(etherxx[ctlrno]->attach)
etherxx[ctlrno]->attach(etherxx[ctlrno]);
return chan;
}
static Walkqid*
etherwalk(Chan* chan, Chan* nchan, char** name, int nname)
{
return netifwalk(etherxx[chan->dev], chan, nchan, name, nname);
}
static int
etherstat(Chan* chan, uchar* dp, int n)
{
return netifstat(etherxx[chan->dev], chan, dp, n);
}
static Chan*
etheropen(Chan* chan, int omode)
{
return netifopen(etherxx[chan->dev], chan, omode);
}
static Chan*
ethercreate(Chan*, char*, int, ulong)
{
error(Eperm);
return 0;
}
static void
etherclose(Chan* chan)
{
netifclose(etherxx[chan->dev], chan);
}
static long
etherread(Chan* chan, void* buf, long n, vlong off)
{
Ether *ether;
ulong offset = off;
ether = etherxx[chan->dev];
if((chan->qid.type & QTDIR) == 0 && ether->ifstat){
/*
* With some controllers it is necessary to reach
* into the chip to extract statistics.
*/
if(NETTYPE(chan->qid.path) == Nifstatqid)
return ether->ifstat(ether, buf, n, offset);
else if(NETTYPE(chan->qid.path) == Nstatqid)
ether->ifstat(ether, buf, 0, offset);
}
return netifread(ether, chan, buf, n, offset);
}
static Block*
etherbread(Chan* chan, long n, ulong offset)
{
return netifbread(etherxx[chan->dev], chan, n, offset);
}
static int
etherwstat(Chan* chan, uchar* dp, int n)
{
return netifwstat(etherxx[chan->dev], chan, dp, n);
}
static void
etherrtrace(Netfile* f, Etherpkt* pkt, int len)
{
int i, n;
Block *bp;
if(qwindow(f->in) <= 0)
return;
if(len > 58)
n = 58;
else
n = len;
bp = iallocb(64);
if(bp == nil)
return;
memmove(bp->wp, pkt->d, n);
i = TK2MS(MACHP(0)->ticks);
bp->wp[58] = len>>8;
bp->wp[59] = len;
bp->wp[60] = i>>24;
bp->wp[61] = i>>16;
bp->wp[62] = i>>8;
bp->wp[63] = i;
bp->wp += 64;
qpass(f->in, bp);
}
Block*
etheriq(Ether* ether, Block* bp, int fromwire)
{
Etherpkt *pkt;
ushort type;
int len, multi, tome, fromme;
Netfile **ep, *f, **fp, *fx;
Block *xbp;
ether->inpackets++;
pkt = (Etherpkt*)bp->rp;
len = BLEN(bp);
type = (pkt->type[0]<<8)|pkt->type[1];
fx = 0;
ep = &ether->f[Ntypes];
multi = pkt->d[0] & 1;
/* check for valid multicast addresses */
if(multi && memcmp(pkt->d, ether->bcast, sizeof(pkt->d)) && ether->prom == 0){
if(!activemulti(ether, pkt->d, sizeof(pkt->d))){
if(fromwire){
freeb(bp);
bp = 0;
}
return bp;
}
}
/* is it for me? */
tome = memcmp(pkt->d, ether->ea, sizeof(pkt->d)) == 0;
fromme = memcmp(pkt->s, ether->ea, sizeof(pkt->s)) == 0;
/*
* Multiplex the packet to all the connections which want it.
* If the packet is not to be used subsequently (fromwire != 0),
* attempt to simply pass it into one of the connections, thereby
* saving a copy of the data (usual case hopefully).
*/
for(fp = ether->f; fp < ep; fp++){
if(f = *fp)
if(f->type == type || f->type < 0)
if(tome || multi || f->prom){
/* Don't want to hear loopback or bridged packets */
if(f->bridge && (tome || !fromwire && !fromme))
continue;
if(!f->headersonly){
if(fromwire && fx == 0)
fx = f;
else if(xbp = iallocb(len)){
memmove(xbp->wp, pkt, len);
xbp->wp += len;
qpass(f->in, xbp);
}
else
ether->soverflows++;
}
else
etherrtrace(f, pkt, len);
}
}
if(fx){
if(qpass(fx->in, bp) < 0)
ether->soverflows++;
return 0;
}
if(fromwire){
freeb(bp);
return 0;
}
return bp;
}
static int
etheroq(Ether* ether, Block* bp)
{
int len, loopback;
Etherpkt *pkt;
ether->outpackets++;
/*
* Check if the packet has to be placed back onto the input queue,
* i.e. if it's a loopback or broadcast packet or the interface is
* in promiscuous mode.
* If it's a loopback packet indicate to etheriq that the data isn't
* needed and return, etheriq will pass-on or free the block.
* To enable bridging to work, only packets that were originated
* by this interface are fed back.
*/
pkt = (Etherpkt*)bp->rp;
len = BLEN(bp);
loopback = memcmp(pkt->d, ether->ea, sizeof(pkt->d)) == 0;
if(loopback || memcmp(pkt->d, ether->bcast, sizeof(pkt->d)) == 0 || ether->prom)
if(etheriq(ether, bp, loopback) == 0)
return len;
qbwrite(ether->oq, bp);
if(ether->transmit != nil)
ether->transmit(ether);
return len;
}
static long
etherwrite(Chan* chan, void* buf, long n, vlong)
{
Ether *ether;
Block *bp;
int nn;
ether = etherxx[chan->dev];
if(NETTYPE(chan->qid.path) != Ndataqid) {
nn = netifwrite(ether, chan, buf, n);
if(nn >= 0)
return nn;
if(n == sizeof("nonblocking")-1 && strncmp((char*)buf, "nonblocking", n) == 0){
qnoblock(ether->oq, 1);
return n;
}
if(ether->ctl!=nil)
return ether->ctl(ether,buf,n);
error(Ebadctl);
}
if(n > ether->maxmtu)
error(Etoobig);
if(n < ether->minmtu)
error(Etoosmall);
bp = allocb(n);
if(waserror()){
freeb(bp);
nexterror();
}
memmove(bp->rp, buf, n);
if(!ether->f[NETID(chan->qid.path)]->bridge)
memmove(bp->rp+Eaddrlen, ether->ea, Eaddrlen);
poperror();
bp->wp += n;
return etheroq(ether, bp);
}
static long
etherbwrite(Chan* chan, Block* bp, ulong)
{
Ether *ether;
long n;
n = BLEN(bp);
if(NETTYPE(chan->qid.path) != Ndataqid){
if(waserror()) {
freeb(bp);
nexterror();
}
n = etherwrite(chan, bp->rp, n, 0);
poperror();
freeb(bp);
return n;
}
ether = etherxx[chan->dev];
if(n > ether->maxmtu){
freeb(bp);
error(Etoobig);
}
if(n < ether->minmtu){
freeb(bp);
error(Etoosmall);
}
return etheroq(ether, bp);
}
static struct {
char* type;
int (*reset)(Ether*);
} cards[MaxEther+1];
void
addethercard(char* t, int (*r)(Ether*))
{
static int ncard;
if(ncard == MaxEther)
panic("too many ether cards");
cards[ncard].type = t;
cards[ncard].reset = r;
ncard++;
}
static void
etherreset(void)
{
Ether *ether;
int i, n, ctlrno;
char name[32], buf[128];
for(ether = 0, ctlrno = 0; ctlrno < MaxEther; ctlrno++){
if(ether == 0)
ether = malloc(sizeof(Ether));
memset(ether, 0, sizeof(Ether));
ether->ctlrno = ctlrno;
ether->tbdf = BUSUNKNOWN;
ether->mbps = 10;
ether->minmtu = ETHERMINTU;
ether->maxmtu = ETHERMAXTU;
if(isaconfig("ether", ctlrno, ether) == 0)
continue;
for(n = 0; cards[n].type; n++){
if(cistrcmp(cards[n].type, ether->type))
continue;
memmove(ether->ea, etheraddr, 6);
for(i = 0; i < ether->nopt; i++){
if(strncmp(ether->opt[i], "ea=", 3))
continue;
if(parseether(ether->ea, &ether->opt[i][3]) == -1)
memset(ether->ea, 0, Eaddrlen);
}
if(cards[n].reset(ether))
break;
/*
* IRQ2 doesn't really exist, it's used to gang the interrupt
* controllers together. A device set to IRQ2 will appear on
* the second interrupt controller as IRQ9.
*/
if(ether->irq == 2 && BUSTYPE(ether->tbdf) != BusPCI)
ether->irq = 9;
snprint(name, sizeof(name), "ether%d", ctlrno);
/*
* If ether->irq is <0, it is a hack to indicate no interrupt
* used by ethersink.
*/
if(ether->irq >= 0)
intrenable(ether->irq, ether->interrupt, ether, name);
i = sprint(buf, "#l%d: %s: %dMbps port 0x%luX irq %d",
ctlrno, ether->type, ether->mbps, ether->port, ether->irq);
if(ether->mem)
i += sprint(buf+i, " addr 0x%luX", PADDR(ether->mem));
if(ether->size)
i += sprint(buf+i, " size 0x%luX", ether->size);
i += sprint(buf+i, ": %2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux",
ether->ea[0], ether->ea[1], ether->ea[2],
ether->ea[3], ether->ea[4], ether->ea[5]);
sprint(buf+i, "\n");
print(buf);
if(ether->mbps >= 100){
netifinit(ether, name, Ntypes, 256*1024);
if(ether->oq == 0)
ether->oq = qopen(256*1024, Qmsg, 0, 0);
}
else{
netifinit(ether, name, Ntypes, 65*1024);
if(ether->oq == 0)
ether->oq = qopen(65*1024, Qmsg, 0, 0);
}
if(ether->oq == 0)
panic("etherreset %s", name);
ether->alen = Eaddrlen;
memmove(ether->addr, ether->ea, Eaddrlen);
memset(ether->bcast, 0xFF, Eaddrlen);
etherxx[ctlrno] = ether;
ether = 0;
break;
}
}
if(ether)
free(ether);
}
#define POLY 0xedb88320
/* really slow 32 bit crc for ethers */
ulong
ethercrc(uchar *p, int len)
{
int i, j;
ulong crc, b;
crc = 0xffffffff;
for(i = 0; i < len; i++){
b = *p++;
for(j = 0; j < 8; j++){
crc = (crc>>1) ^ (((crc^b) & 1) ? POLY : 0);
b >>= 1;
}
}
return crc;
}
Dev etherdevtab = {
'l',
"ether",
etherreset,
devinit,
devshutdown,
etherattach,
etherwalk,
etherstat,
etheropen,
ethercreate,
etherclose,
etherread,
etherbread,
etherwrite,
etherbwrite,
devremove,
etherwstat,
};

View file

@ -11,8 +11,8 @@
#include "imm.h" #include "imm.h"
#include "../port/error.h" #include "../port/error.h"
#include "../port/netif.h" #include "../port/netif.h"
#include "../port/etherif.h"
#include "etherif.h"
#include "../ppc/ethermii.h" #include "../ppc/ethermii.h"
#define DBG 1 #define DBG 1
@ -719,7 +719,6 @@ reset(Ether* ether)
ether->mbps = 100; /* TO DO: could be 10mbps */ ether->mbps = 100; /* TO DO: could be 10mbps */
ether->attach = attach; ether->attach = attach;
ether->transmit = transmit; ether->transmit = transmit;
ether->interrupt = interrupt;
ether->ifstat = ifstat; ether->ifstat = ifstat;
ether->arg = ether; ether->arg = ether;
@ -736,6 +735,8 @@ reset(Ether* ether)
return -1; return -1;
} }
intrenable(ether->irq, interrupt, ether, ether->name);
return 0; return 0;
} }

View file

@ -1,35 +0,0 @@
enum {
MaxEther = 24,
Ntypes = 8,
};
typedef struct Ether Ether;
struct Ether {
ISAConf; /* hardware info */
int ctlrno;
int tbdf; /* type+busno+devno+funcno */
int minmtu;
int maxmtu;
uchar ea[Eaddrlen];
void (*attach)(Ether*); /* filled in by reset routine */
void (*transmit)(Ether*);
void (*interrupt)(Ureg*, void*);
long (*ifstat)(Ether*, void*, long, ulong);
long (*ctl)(Ether*, void*, long); /* custom ctl messages */
void *ctlr;
Queue* oq;
Netif;
};
extern Block* etheriq(Ether*, Block*, int);
extern void addethercard(char*, int(*)(Ether*));
extern ulong ethercrc(uchar*, int);
#define NEXT(x, l) (((x)+1)%(l))
#define PREV(x, l) (((x) == 0) ? (l)-1: (x)-1)
#define HOWMANY(x, y) (((x)+((y)-1))/(y))
#define ROUNDUP(x, y) (HOWMANY((x), (y))*(y))

View file

@ -6,9 +6,9 @@
#include "io.h" #include "io.h"
#include "../port/error.h" #include "../port/error.h"
#include "../port/netif.h" #include "../port/netif.h"
#include "msaturn.h" #include "../port/etherif.h"
#include "etherif.h" #include "msaturn.h"
enum{ enum{
Etcr = Saturn + 0x0c00, Etcr = Saturn + 0x0c00,
@ -209,7 +209,6 @@ reset(Ether* ether)
ether->ctlr = ctlr; ether->ctlr = ctlr;
ether->transmit = transmit; ether->transmit = transmit;
ether->interrupt = interrupt;
ether->irq = Vecether; ether->irq = Vecether;
ether->arg = ether; ether->arg = ether;
memmove(ether->ea, (ushort*)Emacaddr0, Eaddrlen); memmove(ether->ea, (ushort*)Emacaddr0, Eaddrlen);
@ -218,6 +217,9 @@ reset(Ether* ether)
*eimr = Ei_rxdone|Ei_txretry|Ei_txdone; *eimr = Ei_rxdone|Ei_txretry|Ei_txdone;
iprint("reset: ercr %.4uX\n", *ercr); iprint("reset: ercr %.4uX\n", *ercr);
intrenable(ether->irq, interrupt, ether, ether->name);
return 0; return 0;
} }

View file

@ -52,7 +52,6 @@ OBJ=\
HFILES=\ HFILES=\
dat.h\ dat.h\
errstr.h\ errstr.h\
etherif.h\
fns.h\ fns.h\
init.h\ init.h\
io.h\ io.h\
@ -94,7 +93,7 @@ clock.$O devether.$O main.$O trap.$O: /$objtype/include/ureg.h
%.$O: $HFILES %.$O: $HFILES
$ETHER: etherif.h ../port/netif.h $ETHER: ../port/etherif.h ../port/netif.h
init.h: ../port/initcode.c init9.s init.h: ../port/initcode.c init9.s
$CC ../port/initcode.c $CC ../port/initcode.c

View file

@ -13,6 +13,7 @@ typedef struct PMMU PMMU;
typedef struct Softtlb Softtlb; typedef struct Softtlb Softtlb;
typedef struct Ureg Ureg; typedef struct Ureg Ureg;
typedef struct Proc Proc; typedef struct Proc Proc;
typedef struct ISAConf ISAConf;
typedef uvlong Tval; typedef uvlong Tval;
#define MAXSYSARG 5 /* for mount(fd, afd, mpt, flag, arg) */ #define MAXSYSARG 5 /* for mount(fd, afd, mpt, flag, arg) */
@ -70,6 +71,16 @@ struct Conf
int keyboard; int keyboard;
}; };
struct ISAConf
{
char *type;
ulong port;
int irq;
int nopt;
char *opt[1];
};
#define BUSUNKNOWN -1
/* /*
* floating point registers * floating point registers
*/ */

View file

@ -1,489 +0,0 @@
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "pool.h"
#include "ureg.h"
#include "../port/error.h"
#include "../port/netif.h"
#include "etherif.h"
static Ether *etherxx[MaxEther];
Chan*
etherattach(char* spec)
{
ulong ctlrno;
char *p;
Chan *chan;
ctlrno = 0;
if(spec && *spec){
ctlrno = strtoul(spec, &p, 0);
if((ctlrno == 0 && p == spec) || *p || (ctlrno >= MaxEther))
error(Ebadarg);
}
if(etherxx[ctlrno] == 0)
error(Enodev);
chan = devattach('l', spec);
if(waserror()){
chanfree(chan);
nexterror();
}
chan->dev = ctlrno;
if(etherxx[ctlrno]->attach)
etherxx[ctlrno]->attach(etherxx[ctlrno]);
poperror();
return chan;
}
static Walkqid*
etherwalk(Chan* chan, Chan* nchan, char** name, int nname)
{
return netifwalk(etherxx[chan->dev], chan, nchan, name, nname);
}
static int
etherstat(Chan* chan, uchar* dp, int n)
{
return netifstat(etherxx[chan->dev], chan, dp, n);
}
static Chan*
etheropen(Chan* chan, int omode)
{
return netifopen(etherxx[chan->dev], chan, omode);
}
static Chan*
ethercreate(Chan*, char*, int, ulong)
{
error(Eperm);
return 0;
}
static void
etherclose(Chan* chan)
{
netifclose(etherxx[chan->dev], chan);
}
static long
etherread(Chan* chan, void* buf, long n, vlong off)
{
Ether *ether;
ulong offset = off;
ether = etherxx[chan->dev];
if((chan->qid.type & QTDIR) == 0 && ether->ifstat){
/*
* With some controllers it is necessary to reach
* into the chip to extract statistics.
*/
if(NETTYPE(chan->qid.path) == Nifstatqid)
return ether->ifstat(ether, buf, n, offset);
else if(NETTYPE(chan->qid.path) == Nstatqid)
ether->ifstat(ether, buf, 0, offset);
}
return netifread(ether, chan, buf, n, offset);
}
static Block*
etherbread(Chan* chan, long n, ulong offset)
{
return netifbread(etherxx[chan->dev], chan, n, offset);
}
static int
etherwstat(Chan* chan, uchar* dp, int n)
{
return netifwstat(etherxx[chan->dev], chan, dp, n);
}
static void
etherrtrace(Netfile* f, Etherpkt* pkt, int len)
{
int i, n;
Block *bp;
if(qwindow(f->in) <= 0)
return;
if(len > 58)
n = 58;
else
n = len;
bp = iallocb(64);
if(bp == nil)
return;
memmove(bp->wp, pkt->d, n);
i = TK2MS(MACHP(0)->ticks);
bp->wp[58] = len>>8;
bp->wp[59] = len;
bp->wp[60] = i>>24;
bp->wp[61] = i>>16;
bp->wp[62] = i>>8;
bp->wp[63] = i;
bp->wp += 64;
qpass(f->in, bp);
}
Block*
etheriq(Ether* ether, Block* bp, int fromwire)
{
Etherpkt *pkt;
ushort type;
int len, multi, tome, fromme;
Netfile **ep, *f, **fp, *fx;
Block *xbp;
ether->inpackets++;
pkt = (Etherpkt*)bp->rp;
len = BLEN(bp);
type = (pkt->type[0]<<8)|pkt->type[1];
fx = 0;
ep = &ether->f[Ntypes];
multi = pkt->d[0] & 1;
/* check for valid multicast addresses */
if(multi && memcmp(pkt->d, ether->bcast, sizeof(pkt->d)) != 0 && ether->prom == 0){
if(!activemulti(ether, pkt->d, sizeof(pkt->d))){
if(fromwire){
freeb(bp);
bp = 0;
}
return bp;
}
}
/* is it for me? */
tome = memcmp(pkt->d, ether->ea, sizeof(pkt->d)) == 0;
fromme = memcmp(pkt->s, ether->ea, sizeof(pkt->s)) == 0;
/*
* Multiplex the packet to all the connections which want it.
* If the packet is not to be used subsequently (fromwire != 0),
* attempt to simply pass it into one of the connections, thereby
* saving a copy of the data (usual case hopefully).
*/
for(fp = ether->f; fp < ep; fp++){
if(f = *fp)
if(f->type == type || f->type < 0)
if(tome || multi || f->prom){
/* Don't want to hear loopback or bridged packets */
if(f->bridge && (tome || !fromwire && !fromme))
continue;
if(!f->headersonly){
if(fromwire && fx == 0)
fx = f;
else if(xbp = iallocb(len)){
memmove(xbp->wp, pkt, len);
xbp->wp += len;
if(qpass(f->in, xbp) < 0) {
// print("soverflow for f->in\n");
ether->soverflows++;
}
}
else {
// print("soverflow iallocb\n");
ether->soverflows++;
}
}
else
etherrtrace(f, pkt, len);
}
}
if(fx){
if(qpass(fx->in, bp) < 0) {
// print("soverflow for fx->in\n");
ether->soverflows++;
}
return 0;
}
if(fromwire){
freeb(bp);
return 0;
}
return bp;
}
static int
etheroq(Ether* ether, Block* bp)
{
int len, loopback;
Etherpkt *pkt;
ether->outpackets++;
/*
* Check if the packet has to be placed back onto the input queue,
* i.e. if it's a loopback or broadcast packet or the interface is
* in promiscuous mode.
* If it's a loopback packet indicate to etheriq that the data isn't
* needed and return, etheriq will pass-on or free the block.
* To enable bridging to work, only packets that were originated
* by this interface are fed back.
*/
pkt = (Etherpkt*)bp->rp;
len = BLEN(bp);
loopback = memcmp(pkt->d, ether->ea, sizeof(pkt->d)) == 0;
if(loopback || memcmp(pkt->d, ether->bcast, sizeof(pkt->d)) == 0 || ether->prom)
if(etheriq(ether, bp, loopback) == 0)
return len;
qbwrite(ether->oq, bp);
if(ether->transmit != nil)
ether->transmit(ether);
return len;
}
static long
etherwrite(Chan* chan, void* buf, long n, vlong)
{
Ether *ether;
Block *bp;
int nn, onoff;
Cmdbuf *cb;
ether = etherxx[chan->dev];
if(NETTYPE(chan->qid.path) != Ndataqid) {
nn = netifwrite(ether, chan, buf, n);
if(nn >= 0)
return nn;
cb = parsecmd(buf, n);
if(cb->f[0] && strcmp(cb->f[0], "nonblocking") == 0){
if(cb->nf <= 1)
onoff = 1;
else
onoff = atoi(cb->f[1]);
qnoblock(ether->oq, onoff);
free(cb);
return n;
}
free(cb);
if(ether->ctl!=nil)
return ether->ctl(ether,buf,n);
error(Ebadctl);
}
if(n > ether->maxmtu)
error(Etoobig);
if(n < ether->minmtu)
error(Etoosmall);
bp = allocb(n);
if(waserror()){
freeb(bp);
nexterror();
}
memmove(bp->rp, buf, n);
if(!ether->f[NETID(chan->qid.path)]->bridge)
memmove(bp->rp+Eaddrlen, ether->ea, Eaddrlen);
poperror();
bp->wp += n;
return etheroq(ether, bp);
}
static long
etherbwrite(Chan* chan, Block* bp, ulong)
{
Ether *ether;
long n;
n = BLEN(bp);
if(NETTYPE(chan->qid.path) != Ndataqid){
if(waserror()) {
freeb(bp);
nexterror();
}
n = etherwrite(chan, bp->rp, n, 0);
poperror();
freeb(bp);
return n;
}
ether = etherxx[chan->dev];
if(n > ether->maxmtu){
freeb(bp);
error(Etoobig);
}
if(n < ether->minmtu){
freeb(bp);
error(Etoosmall);
}
return etheroq(ether, bp);
}
static struct {
char* type;
int (*reset)(Ether*);
} cards[MaxEther+1];
void
addethercard(char* t, int (*r)(Ether*))
{
static int ncard;
if(ncard == MaxEther)
panic("too many ether cards");
cards[ncard].type = t;
cards[ncard].reset = r;
ncard++;
}
static Ether*
etherprobe(int cardno, int ctlrno)
{
int i, lg;
ulong mb, bsz;
Ether *ether;
char buf[128], name[32];
ether = malloc(sizeof(Ether));
if(ether == nil){
print("etherprobe: no memory for Ether\n");
return nil;
}
memset(ether, 0, sizeof(Ether));
ether->ctlrno = ctlrno;
ether->mbps = 10;
ether->minmtu = ETHERMINTU;
ether->maxmtu = ETHERMAXTU;
if(cardno >= MaxEther || cards[cardno].type == nil){
free(ether);
return nil;
}
if(cards[cardno].reset(ether) < 0){
free(ether);
return nil;
}
snprint(name, sizeof(name), "ether%d", ctlrno);
intrenable(ether->irqlevel, ether->interrupt, ether);
i = sprint(buf, "#l%d: %s: %dMbps port 0x%luX irq %d",
ctlrno, cards[cardno].type, ether->mbps, ether->port, ether->irq);
i += sprint(buf+i, ": %2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux",
ether->ea[0], ether->ea[1], ether->ea[2],
ether->ea[3], ether->ea[4], ether->ea[5]);
sprint(buf+i, "\n");
print(buf);
/* compute log10(ether->mbps) into lg */
for(lg = 0, mb = ether->mbps; mb >= 10; lg++)
mb /= 10;
if (lg > 0)
lg--;
if (lg > 14) /* 2^(14+17) = 2³¹ */
lg = 14;
/* allocate larger output queues for higher-speed interfaces */
bsz = 1UL << (lg + 17); /* 2¹⁷ = 128K, bsz = 2ⁿ × 128K */
while (bsz > mainmem->maxsize / 8 && bsz > 128*1024)
bsz /= 2;
netifinit(ether, name, Ntypes, bsz);
if(ether->oq == nil) {
ether->oq = qopen(bsz, Qmsg, 0, 0);
ether->limit = bsz;
}
if(ether->oq == nil)
panic("etherreset %s: can't allocate output queue of %ld bytes", name, bsz);
ether->alen = Eaddrlen;
memmove(ether->addr, ether->ea, Eaddrlen);
memset(ether->bcast, 0xFF, Eaddrlen);
return ether;
}
static void
etherreset(void)
{
Ether *ether;
int cardno, ctlrno;
cardno = ctlrno = 0;
while(cards[cardno].type != nil && ctlrno < MaxEther){
if(etherxx[ctlrno] != nil){
ctlrno++;
continue;
}
if((ether = etherprobe(cardno, ctlrno)) == nil){
cardno++;
continue;
}
etherxx[ctlrno] = ether;
ctlrno++;
}
}
static void
ethershutdown(void)
{
Ether *ether;
int i;
for(i = 0; i < MaxEther; i++){
ether = etherxx[i];
if(ether == nil)
continue;
if(ether->shutdown == nil) {
print("#l%d: no shutdown function\n", i);
continue;
}
(*ether->shutdown)(ether);
}
}
#define POLY 0xedb88320
/* really slow 32 bit crc for ethers */
ulong
ethercrc(uchar *p, int len)
{
int i, j;
ulong crc, b;
crc = 0xffffffff;
for(i = 0; i < len; i++){
b = *p++;
for(j = 0; j < 8; j++){
crc = (crc>>1) ^ (((crc^b) & 1) ? POLY : 0);
b >>= 1;
}
}
return crc;
}
Dev etherdevtab = {
'l',
"ether",
etherreset,
devinit,
ethershutdown,
etherattach,
etherwalk,
etherstat,
etheropen,
ethercreate,
etherclose,
etherread,
etherbread,
etherwrite,
etherbwrite,
devremove,
etherwstat,
};

View file

@ -1,40 +0,0 @@
enum {
MaxEther = 1,
Ntypes = 8,
};
typedef struct Ether Ether;
struct Ether {
int ctlrno;
int minmtu;
int maxmtu;
uchar ea[Eaddrlen];
int irq, irqlevel;
uintptr port;
void (*attach)(Ether*); /* filled in by reset routine */
void (*detach)(Ether*);
void (*transmit)(Ether*);
void (*interrupt)(Ureg*, void*);
long (*ifstat)(Ether*, void*, long, ulong);
long (*ctl)(Ether*, void*, long); /* custom ctl messages */
void (*power)(Ether*, int); /* power on/off */
void (*shutdown)(Ether*); /* shutdown hardware before reboot */
void *ctlr;
Queue* oq;
Netif;
};
extern Block* etheriq(Ether*, Block*, int);
extern void addethercard(char*, int(*)(Ether*));
extern ulong ethercrc(uchar*, int);
extern int parseether(uchar*, char*);
#define NEXT(x, l) (((x)+1)%(l))
#define PREV(x, l) (((x) == 0) ? (l)-1: (x)-1)
#define HOWMANY(x, y) (((x)+((y)-1))/(y))
#define ROUNDUP(x, y) (HOWMANY((x), (y))*(y))

View file

@ -5,7 +5,7 @@
#include "fns.h" #include "fns.h"
#include "io.h" #include "io.h"
#include "../port/netif.h" #include "../port/netif.h"
#include "etherif.h" #include "../port/etherif.h"
typedef struct Hio Hio; typedef struct Hio Hio;
typedef struct Desc Desc; typedef struct Desc Desc;
@ -451,19 +451,21 @@ pnp(Ether *edev)
edev->ctlr = &ct; edev->ctlr = &ct;
edev->port = HPC3_ETHER; edev->port = HPC3_ETHER;
edev->irq = IRQENET; edev->irq = IRQENET;
edev->irqlevel = hpc3irqlevel(edev->irq);
edev->ctlr = &ct; edev->ctlr = &ct;
edev->promiscuous = promiscuous; edev->promiscuous = promiscuous;
edev->multicast = multicast; edev->multicast = multicast;
edev->interrupt = interrupt;
edev->attach = attach; edev->attach = attach;
edev->arg = edev; edev->arg = edev;
edev->mbps = 10; edev->mbps = 10;
edev->link = 1; edev->link = 1;
if(init(edev) < 0){ if(init(edev) < 0){
edev->ctlr = nil; edev->ctlr = nil;
return -1; return -1;
} }
intrenable(hpc3irqlevel(edev->irq), interrupt, edev);
return 0; return 0;
} }

View file

@ -22,6 +22,7 @@ ulong getrandom(void);
int gettlbp(ulong, ulong*); int gettlbp(ulong, ulong*);
ulong gettlbvirt(int); ulong gettlbvirt(int);
int hpc3irqlevel(int); int hpc3irqlevel(int);
int isaconfig(char*, int, ISAConf*);
void icflush(void *, ulong); void icflush(void *, ulong);
void idlehands(void); void idlehands(void);
void introff(int); void introff(int);

View file

@ -10,8 +10,8 @@ dev
env env
pipe pipe
dup dup
ether netif ether netif
ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium inferno ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium inferno
ssl ssl
tls tls
cap cap

View file

@ -502,3 +502,9 @@ setupwatchpts(Proc *, Watchpt *, int n)
if(n > 0) if(n > 0)
error("no watchpoints"); error("no watchpoints");
} }
int
isaconfig(char *, int, ISAConf*)
{
return 0;
}

View file

@ -12,7 +12,7 @@
#include "arm.h" #include "arm.h"
#include "../port/netif.h" #include "../port/netif.h"
#include "etherif.h" #include "../port/etherif.h"
#include "../port/flashif.h" #include "../port/flashif.h"
#include "../port/usb.h" #include "../port/usb.h"
#include "../port/portusbehci.h" #include "../port/portusbehci.h"

View file

@ -1,502 +0,0 @@
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/error.h"
#include "../port/netif.h"
#include "etherif.h"
static Ether *etherxx[MaxEther];
Chan*
etherattach(char* spec)
{
int ctlrno;
char *p;
Chan *chan;
ctlrno = 0;
if(spec && *spec){
ctlrno = strtoul(spec, &p, 0);
if((ctlrno == 0 && p == spec) || *p != 0)
error(Ebadarg);
if(ctlrno < 0 || ctlrno >= MaxEther)
error(Ebadarg);
}
if(etherxx[ctlrno] == 0)
error(Enodev);
chan = devattach('l', spec);
if(waserror()){
chanfree(chan);
nexterror();
}
chan->dev = ctlrno;
if(etherxx[ctlrno]->attach)
etherxx[ctlrno]->attach(etherxx[ctlrno]);
poperror();
return chan;
}
static Walkqid*
etherwalk(Chan* chan, Chan* nchan, char** name, int nname)
{
return netifwalk(etherxx[chan->dev], chan, nchan, name, nname);
}
static int
etherstat(Chan* chan, uchar* dp, int n)
{
return netifstat(etherxx[chan->dev], chan, dp, n);
}
static Chan*
etheropen(Chan* chan, int omode)
{
return netifopen(etherxx[chan->dev], chan, omode);
}
static Chan*
ethercreate(Chan*, char*, int, ulong)
{
error(Eperm);
return 0;
}
static void
etherclose(Chan* chan)
{
netifclose(etherxx[chan->dev], chan);
}
static long
etherread(Chan* chan, void* buf, long n, vlong off)
{
Ether *ether;
ulong offset = off;
ether = etherxx[chan->dev];
if((chan->qid.type & QTDIR) == 0 && ether->ifstat){
/*
* With some controllers it is necessary to reach
* into the chip to extract statistics.
*/
if(NETTYPE(chan->qid.path) == Nifstatqid)
return ether->ifstat(ether, buf, n, offset);
else if(NETTYPE(chan->qid.path) == Nstatqid)
ether->ifstat(ether, buf, 0, offset);
}
return netifread(ether, chan, buf, n, offset);
}
static Block*
etherbread(Chan* chan, long n, ulong offset)
{
return netifbread(etherxx[chan->dev], chan, n, offset);
}
static int
etherwstat(Chan* chan, uchar* dp, int n)
{
return netifwstat(etherxx[chan->dev], chan, dp, n);
}
static void
etherrtrace(Netfile* f, Etherpkt* pkt, int len)
{
int i, n;
Block *bp;
if(qwindow(f->in) <= 0)
return;
if(len > 58)
n = 58;
else
n = len;
bp = iallocb(64);
if(bp == nil)
return;
memmove(bp->wp, pkt->d, n);
i = TK2MS(MACHP(0)->ticks);
bp->wp[58] = len>>8;
bp->wp[59] = len;
bp->wp[60] = i>>24;
bp->wp[61] = i>>16;
bp->wp[62] = i>>8;
bp->wp[63] = i;
bp->wp += 64;
qpass(f->in, bp);
}
Block*
etheriq(Ether* ether, Block* bp, int fromwire)
{
Etherpkt *pkt;
ushort type;
int len, multi, tome, fromme;
Netfile **ep, *f, **fp, *fx;
Block *xbp;
ether->inpackets++;
pkt = (Etherpkt*)bp->rp;
len = BLEN(bp);
type = (pkt->type[0]<<8)|pkt->type[1];
fx = 0;
ep = &ether->f[Ntypes];
multi = pkt->d[0] & 1;
/* check for valid multicast addresses */
if(multi && memcmp(pkt->d, ether->bcast, sizeof(pkt->d)) != 0 &&
ether->prom == 0){
if(!activemulti(ether, pkt->d, sizeof(pkt->d))){
if(fromwire){
freeb(bp);
bp = 0;
}
return bp;
}
}
/* is it for me? */
tome = memcmp(pkt->d, ether->ea, sizeof(pkt->d)) == 0;
fromme = memcmp(pkt->s, ether->ea, sizeof(pkt->s)) == 0;
/*
* Multiplex the packet to all the connections which want it.
* If the packet is not to be used subsequently (fromwire != 0),
* attempt to simply pass it into one of the connections, thereby
* saving a copy of the data (usual case hopefully).
*/
for(fp = ether->f; fp < ep; fp++){
if((f = *fp) != nil && (f->type == type || f->type < 0) &&
(tome || multi || f->prom)){
/* Don't want to hear loopback or bridged packets */
if(f->bridge && (tome || !fromwire && !fromme))
continue;
if(!f->headersonly){
if(fromwire && fx == 0)
fx = f;
else if(xbp = iallocb(len)){
memmove(xbp->wp, pkt, len);
xbp->wp += len;
if(qpass(f->in, xbp) < 0)
ether->soverflows++;
}
else
ether->soverflows++;
}
else
etherrtrace(f, pkt, len);
}
}
if(fx){
if(qpass(fx->in, bp) < 0)
ether->soverflows++;
return 0;
}
if(fromwire){
freeb(bp);
return 0;
}
return bp;
}
static int
etheroq(Ether* ether, Block* bp)
{
int len, loopback;
Etherpkt *pkt;
ether->outpackets++;
/*
* Check if the packet has to be placed back onto the input queue,
* i.e. if it's a loopback or broadcast packet or the interface is
* in promiscuous mode.
* If it's a loopback packet indicate to etheriq that the data isn't
* needed and return, etheriq will pass-on or free the block.
* To enable bridging to work, only packets that were originated
* by this interface are fed back.
*/
pkt = (Etherpkt*)bp->rp;
len = BLEN(bp);
loopback = memcmp(pkt->d, ether->ea, sizeof(pkt->d)) == 0;
if(loopback || memcmp(pkt->d, ether->bcast, sizeof(pkt->d)) == 0 || ether->prom)
if(etheriq(ether, bp, loopback) == 0)
return len;
qbwrite(ether->oq, bp);
if(ether->transmit != nil)
ether->transmit(ether);
return len;
}
static long
etherwrite(Chan* chan, void* buf, long n, vlong)
{
Ether *ether;
Block *bp;
int nn, onoff;
Cmdbuf *cb;
ether = etherxx[chan->dev];
if(NETTYPE(chan->qid.path) != Ndataqid) {
nn = netifwrite(ether, chan, buf, n);
if(nn >= 0)
return nn;
cb = parsecmd(buf, n);
if(cb->f[0] && strcmp(cb->f[0], "nonblocking") == 0){
if(cb->nf <= 1)
onoff = 1;
else
onoff = atoi(cb->f[1]);
qnoblock(ether->oq, onoff);
free(cb);
return n;
}
free(cb);
if(ether->ctl!=nil)
return ether->ctl(ether,buf,n);
error(Ebadctl);
}
if(n > ether->maxmtu)
error(Etoobig);
if(n < ether->minmtu)
error(Etoosmall);
bp = allocb(n);
if(waserror()){
freeb(bp);
nexterror();
}
memmove(bp->rp, buf, n);
if(!ether->f[NETID(chan->qid.path)]->bridge)
memmove(bp->rp+Eaddrlen, ether->ea, Eaddrlen);
poperror();
bp->wp += n;
return etheroq(ether, bp);
}
static long
etherbwrite(Chan* chan, Block* bp, ulong)
{
Ether *ether;
long n;
n = BLEN(bp);
if(NETTYPE(chan->qid.path) != Ndataqid){
if(waserror()) {
freeb(bp);
nexterror();
}
n = etherwrite(chan, bp->rp, n, 0);
poperror();
freeb(bp);
return n;
}
ether = etherxx[chan->dev];
if(n > ether->maxmtu){
freeb(bp);
error(Etoobig);
}
if(n < ether->minmtu){
freeb(bp);
error(Etoosmall);
}
return etheroq(ether, bp);
}
static struct {
char* type;
int (*reset)(Ether*);
} cards[MaxEther+1];
void
addethercard(char* t, int (*r)(Ether*))
{
static int ncard;
if(ncard == MaxEther)
panic("too many ether cards");
cards[ncard].type = t;
cards[ncard].reset = r;
ncard++;
}
static void
etherreset(void)
{
Ether *ether;
int i, n, ctlrno;
char name[KNAMELEN], buf[128];
for(ether = 0, ctlrno = 0; ctlrno < MaxEther; ctlrno++){
if(ether == 0)
ether = malloc(sizeof(Ether));
memset(ether, 0, sizeof(Ether));
ether->ctlrno = ctlrno;
ether->mbps = 10;
ether->minmtu = ETHERMINTU;
ether->maxmtu = ETHERMAXTU;
if(archether(ctlrno, ether) <= 0)
continue;
if(isaconfig("ether", ctlrno, ether) == 0){
// free(ether);
// return nil;
continue;
}
for(n = 0; cards[n].type; n++){
if(cistrcmp(cards[n].type, ether->type))
continue;
for(i = 0; i < ether->nopt; i++)
if(cistrncmp(ether->opt[i], "ea=", 3) == 0){
if(parseether(ether->ea,
&ether->opt[i][3]) == -1)
memset(ether->ea, 0, Eaddrlen);
} else if(cistrcmp(ether->opt[i],
"100BASE-TXFD") == 0)
ether->mbps = 100;
if(cards[n].reset(ether))
break;
snprint(name, sizeof(name), "ether%d", ctlrno);
if(ether->interrupt != nil && ether->irq >= 0)
intrenable(ether->irq, ether->interrupt,
ether, 0, name);
i = snprint(buf, sizeof buf,
"#l%d: %s: %dMbps port %#lux irq %d",
ctlrno, ether->type, ether->mbps, ether->port,
ether->irq);
if(ether->mem)
i += snprint(buf+i, sizeof buf - i,
" addr %#lux", PADDR(ether->mem));
if(ether->size)
i += snprint(buf+i, sizeof buf - i,
" size %#luX", ether->size);
i += snprint(buf+i, sizeof buf - i,
": %2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux",
ether->ea[0], ether->ea[1], ether->ea[2],
ether->ea[3], ether->ea[4], ether->ea[5]);
snprint(buf+i, sizeof buf - i, "\n");
iprint("%s", buf); /* it may be too early for print */
if(ether->mbps >= 1000)
netifinit(ether, name, Ntypes, 4*1024*1024);
else if(ether->mbps >= 100)
netifinit(ether, name, Ntypes, 1024*1024);
else
netifinit(ether, name, Ntypes, 65*1024);
if(ether->oq == 0)
ether->oq = qopen(ether->limit, Qmsg, 0, 0);
if(ether->oq == 0)
panic("etherreset %s", name);
ether->alen = Eaddrlen;
memmove(ether->addr, ether->ea, Eaddrlen);
memset(ether->bcast, 0xFF, Eaddrlen);
etherxx[ctlrno] = ether;
ether = 0;
break;
}
}
if(ether)
free(ether);
}
static void
ethershutdown(void)
{
Ether *ether;
int i;
for(i = 0; i < MaxEther; i++){
ether = etherxx[i];
if(ether == nil)
continue;
if(ether->shutdown == nil) {
print("#l%d: no shutdown function\n", i);
continue;
}
(*ether->shutdown)(ether);
}
}
#define POLY 0xedb88320
/* really slow 32 bit crc for ethers */
ulong
ethercrc(uchar *p, int len)
{
int i, j;
ulong crc, b;
crc = 0xffffffff;
for(i = 0; i < len; i++){
b = *p++;
for(j = 0; j < 8; j++){
crc = (crc>>1) ^ (((crc^b) & 1) ? POLY : 0);
b >>= 1;
}
}
return crc;
}
void
dumpoq(Queue *oq)
{
if (oq == nil)
print("no outq! ");
else if (qisclosed(oq))
print("outq closed ");
else if (qfull(oq))
print("outq full ");
else
print("outq %d ", qlen(oq));
}
void
dumpnetif(Netif *netif)
{
print("netif %s ", netif->name);
print("limit %d mbps %d link %d ",
netif->limit, netif->mbps, netif->link);
print("inpkts %lld outpkts %lld errs %d\n",
netif->inpackets, netif->outpackets,
netif->crcs + netif->oerrs + netif->frames + netif->overflows +
netif->buffs + netif->soverflows);
}
Dev etherdevtab = {
'l',
"ether",
etherreset,
devinit,
ethershutdown,
etherattach,
etherwalk,
etherstat,
etheropen,
ethercreate,
etherclose,
etherread,
etherbread,
etherwrite,
etherbwrite,
devremove,
etherwstat,
};

View file

@ -15,8 +15,8 @@
#include "io.h" #include "io.h"
#include "../port/error.h" #include "../port/error.h"
#include "../port/netif.h" #include "../port/netif.h"
#include "../port/etherif.h"
#include "etherif.h"
#include "ethermii.h" #include "ethermii.h"
typedef struct Ctlr Ctlr; typedef struct Ctlr Ctlr;
@ -1655,7 +1655,6 @@ rtl8169pnp(Ether* edev)
edev->attach = rtl8169attach; edev->attach = rtl8169attach;
edev->transmit = rtl8169transmit; edev->transmit = rtl8169transmit;
edev->interrupt = rtl8169interrupt;
edev->ifstat = rtl8169ifstat; edev->ifstat = rtl8169ifstat;
edev->arg = edev; edev->arg = edev;
@ -1666,6 +1665,9 @@ rtl8169pnp(Ether* edev)
ilock(&ctlr->reglock); ilock(&ctlr->reglock);
rtl8169link(edev); rtl8169link(edev);
iunlock(&ctlr->reglock); iunlock(&ctlr->reglock);
intrenable(edev->irq, rtl8169interrupt, edev, 0, edev->name);
return 0; return 0;
} }

View file

@ -1,42 +0,0 @@
enum
{
MaxEther = 4,
Ntypes = 8,
};
typedef struct Ether Ether;
struct Ether {
RWlock;
ISAConf; /* hardware info */
int ctlrno;
ulong tbdf;
int minmtu;
int maxmtu;
Netif;
void (*attach)(Ether*); /* filled in by reset routine */
void (*detach)(Ether*);
void (*transmit)(Ether*);
void (*interrupt)(Ureg*, void*);
long (*ifstat)(Ether*, void*, long, ulong);
long (*ctl)(Ether*, void*, long); /* custom ctl messages */
void (*power)(Ether*, int); /* power on/off */
void (*shutdown)(Ether*); /* shutdown hardware before reboot */
void* ctlr;
uchar ea[Eaddrlen];
void* address;
int irq;
Queue* oq;
};
extern Block* etheriq(Ether*, Block*, int);
extern void addethercard(char*, int(*)(Ether*));
extern ulong ethercrc(uchar*, int);
extern int parseether(uchar*, char*);
#define NEXT(x, l) (((x)+1)%(l))
#define PREV(x, l) (((x) == 0) ? (l)-1: (x)-1)

View file

@ -6,8 +6,8 @@
#include "io.h" #include "io.h"
#include "../port/error.h" #include "../port/error.h"
#include "../port/netif.h" #include "../port/netif.h"
#include "../port/etherif.h"
#include "etherif.h"
#include "ethermii.h" #include "ethermii.h"
int int

View file

@ -5,9 +5,6 @@
#define MiB 1048576u /* Mebi 0x0000000000100000 */ #define MiB 1048576u /* Mebi 0x0000000000100000 */
#define GiB 1073741824u /* Gibi 000000000040000000 */ #define GiB 1073741824u /* Gibi 000000000040000000 */
#define HOWMANY(x, y) (((x)+((y)-1))/(y))
#define ROUNDUP(x, y) (HOWMANY((x), (y))*(y)) /* ceiling */
#define ROUNDDN(x, y) (((x)/(y))*(y)) /* floor */
#define MIN(a, b) ((a) < (b)? (a): (b)) #define MIN(a, b) ((a) < (b)? (a): (b))
#define MAX(a, b) ((a) > (b)? (a): (b)) #define MAX(a, b) ((a) > (b)? (a): (b))
@ -36,7 +33,7 @@
*/ */
#define BY2PG (4*KiB) /* bytes per page */ #define BY2PG (4*KiB) /* bytes per page */
#define PGSHIFT 12 /* log(BY2PG) */ #define PGSHIFT 12 /* log(BY2PG) */
#define PGROUND(s) ROUNDUP(s, BY2PG) #define PGROUND(s) ROUND(s, BY2PG)
#define ROUND(s, sz) (((s)+(sz-1))&~(sz-1)) #define ROUND(s, sz) (((s)+(sz-1))&~(sz-1))
/* max # of cpus system can run. tegra2 cpu ids are two bits wide. */ /* max # of cpus system can run. tegra2 cpu ids are two bits wide. */
@ -85,7 +82,6 @@
#define UZERO 0 /* user segment */ #define UZERO 0 /* user segment */
#define UTZERO (UZERO+BY2PG) /* user text start */ #define UTZERO (UZERO+BY2PG) /* user text start */
#define UTROUND(t) ROUNDUP((t), BY2PG)
/* /*
* moved USTKTOP down to 1GB to keep MMIO space out of user space. * moved USTKTOP down to 1GB to keep MMIO space out of user space.
* moved it down another MB to utterly avoid KADDR(stack_base) mapping * moved it down another MB to utterly avoid KADDR(stack_base) mapping

View file

@ -117,7 +117,7 @@ CFLAGS= -I. -I../port $CFLAGS # hack to compile private sysproc.c (e.g.)
arch.$O clock.$O fpiarm.$O main.$O mmu.$O screen.$O sdscsi.$O syscall.$O \ arch.$O clock.$O fpiarm.$O main.$O mmu.$O screen.$O sdscsi.$O syscall.$O \
trap.$O: /$objtype/include/ureg.h trap.$O: /$objtype/include/ureg.h
archtegra.$O devether.$0 ether9221.$O: etherif.h ../port/netif.h archtegra.$O devether.$0 ether9221.$O: ../port/etherif.h ../port/netif.h
archtegra.$O devflash.$O flashtegra.$O flashigep.$O: ../port/flashif.h archtegra.$O devflash.$O flashtegra.$O flashigep.$O: ../port/flashif.h
ecc.$O flashtegra.$O flashigep.$O: ../port/nandecc.h io.h ecc.$O flashtegra.$O flashigep.$O: ../port/nandecc.h io.h
fpi.$O fpiarm.$O fpimem.$O: fpi.h fpi.$O fpiarm.$O fpimem.$O: fpi.h

View file

@ -693,7 +693,7 @@ vmap(uintptr pa, usize size)
o = pa & (BY2PG-1); o = pa & (BY2PG-1);
pa -= o; pa -= o;
size += o; size += o;
size = ROUNDUP(size, BY2PG); size = PGROUND(size);
va = kseg0|pa; va = kseg0|pa;
pae = mmukmap(va, pa, size); pae = mmukmap(va, pa, size);

View file

@ -10,7 +10,7 @@
#include "io.h" #include "io.h"
#include "../port/error.h" #include "../port/error.h"
#include "../port/netif.h" #include "../port/netif.h"
#include "etherif.h" #include "../port/etherif.h"
#define LOG(a) #define LOG(a)
@ -478,12 +478,14 @@ pnp(Ether* ether)
ether->transmit = etherxentransmit; ether->transmit = etherxentransmit;
ether->irq = -1; ether->irq = -1;
ether->tbdf = BUSUNKNOWN; ether->tbdf = BUSUNKNOWN;
ether->interrupt = etherxenintr;
ether->ifstat = ifstat; ether->ifstat = ifstat;
ether->ctl = etherxenctl; ether->ctl = etherxenctl;
ether->promiscuous = nil; ether->promiscuous = nil;
ether->multicast = etherxenmulticast; ether->multicast = etherxenmulticast;
ether->arg = ether; ether->arg = ether;
intrenable(ether->irq, etherxenintr, ether, ether->tbdf, ether->name);
return 0; return 0;
} }

View file

@ -114,7 +114,7 @@ install:V: $p$CONF $p$CONF.gz
# import lookout / /n/lookout && cp $p$CONF $p$CONF.gz /n/lookout/$objtype/ # import lookout / /n/lookout && cp $p$CONF $p$CONF.gz /n/lookout/$objtype/
# copies generated by the rule below # copies generated by the rule below
PCHEADERS=uncached.h etherif.h ethermii.h mp.h io.h PCHEADERS=uncached.h ethermii.h mp.h io.h
REPCH=`{echo $PCHEADERS | sed 's/\.h//g; s/ /|/g'} REPCH=`{echo $PCHEADERS | sed 's/\.h//g; s/ /|/g'}
^($REPCH)\.h:R: '../pc/\1.h' ^($REPCH)\.h:R: '../pc/\1.h'
@ -132,7 +132,7 @@ ptclbsum386.$O: ../pc/ptclbsum386.s
$AS $AFLAGS ../pc/ptclbsum386.s $AS $AFLAGS ../pc/ptclbsum386.s
# we inherited these.. revisit. # we inherited these.. revisit.
$ETHER: etherif.h ../port/netif.h $ETHER: ../port/etherif.h ../port/netif.h
$SDEV: ../port/sd.h $SDEV: ../port/sd.h
main.$O: init.h reboot.h main.$O: init.h reboot.h
trap.$O: /sys/include/tos.h trap.$O: /sys/include/tos.h

View file

@ -20,7 +20,7 @@ dev
xenstore xenstore
ether netif ether netif
ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium ptclbsum386 inferno ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium ptclbsum386 inferno
sd sd

View file

@ -161,10 +161,11 @@ struct Mach
struct ISAConf struct ISAConf
{ {
int dummy; char *type;
char *type; ulong port;
ulong port; int irq;
int irq; int nopt;
char *opt[1];
}; };
#define BUSUNKNOWN -1 #define BUSUNKNOWN -1

View file

@ -1,489 +0,0 @@
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "pool.h"
#include "ureg.h"
#include "../port/error.h"
#include "../port/netif.h"
#include "etherif.h"
static Ether *etherxx[MaxEther];
Chan*
etherattach(char* spec)
{
ulong ctlrno;
char *p;
Chan *chan;
ctlrno = 0;
if(spec && *spec){
ctlrno = strtoul(spec, &p, 0);
if((ctlrno == 0 && p == spec) || *p || (ctlrno >= MaxEther))
error(Ebadarg);
}
if(etherxx[ctlrno] == 0)
error(Enodev);
chan = devattach('l', spec);
if(waserror()){
chanfree(chan);
nexterror();
}
chan->dev = ctlrno;
if(etherxx[ctlrno]->attach)
etherxx[ctlrno]->attach(etherxx[ctlrno]);
poperror();
return chan;
}
static Walkqid*
etherwalk(Chan* chan, Chan* nchan, char** name, int nname)
{
return netifwalk(etherxx[chan->dev], chan, nchan, name, nname);
}
static int
etherstat(Chan* chan, uchar* dp, int n)
{
return netifstat(etherxx[chan->dev], chan, dp, n);
}
static Chan*
etheropen(Chan* chan, int omode)
{
return netifopen(etherxx[chan->dev], chan, omode);
}
static Chan*
ethercreate(Chan*, char*, int, ulong)
{
error(Eperm);
return 0;
}
static void
etherclose(Chan* chan)
{
netifclose(etherxx[chan->dev], chan);
}
static long
etherread(Chan* chan, void* buf, long n, vlong off)
{
Ether *ether;
ulong offset = off;
ether = etherxx[chan->dev];
if((chan->qid.type & QTDIR) == 0 && ether->ifstat){
/*
* With some controllers it is necessary to reach
* into the chip to extract statistics.
*/
if(NETTYPE(chan->qid.path) == Nifstatqid)
return ether->ifstat(ether, buf, n, offset);
else if(NETTYPE(chan->qid.path) == Nstatqid)
ether->ifstat(ether, buf, 0, offset);
}
return netifread(ether, chan, buf, n, offset);
}
static Block*
etherbread(Chan* chan, long n, ulong offset)
{
return netifbread(etherxx[chan->dev], chan, n, offset);
}
static int
etherwstat(Chan* chan, uchar* dp, int n)
{
return netifwstat(etherxx[chan->dev], chan, dp, n);
}
static void
etherrtrace(Netfile* f, Etherpkt* pkt, int len)
{
int i, n;
Block *bp;
if(qwindow(f->in) <= 0)
return;
if(len > 58)
n = 58;
else
n = len;
bp = iallocb(64);
if(bp == nil)
return;
memmove(bp->wp, pkt->d, n);
i = TK2MS(MACHP(0)->ticks);
bp->wp[58] = len>>8;
bp->wp[59] = len;
bp->wp[60] = i>>24;
bp->wp[61] = i>>16;
bp->wp[62] = i>>8;
bp->wp[63] = i;
bp->wp += 64;
qpass(f->in, bp);
}
Block*
etheriq(Ether* ether, Block* bp, int fromwire)
{
Etherpkt *pkt;
ushort type;
int len, multi, tome, fromme;
Netfile **ep, *f, **fp, *fx;
Block *xbp;
ether->inpackets++;
pkt = (Etherpkt*)bp->rp;
len = BLEN(bp);
type = (pkt->type[0]<<8)|pkt->type[1];
fx = 0;
ep = &ether->f[Ntypes];
multi = pkt->d[0] & 1;
/* check for valid multicast addresses */
if(multi && memcmp(pkt->d, ether->bcast, sizeof(pkt->d)) != 0 && ether->prom == 0){
if(!activemulti(ether, pkt->d, sizeof(pkt->d))){
if(fromwire){
freeb(bp);
bp = 0;
}
return bp;
}
}
/* is it for me? */
tome = memcmp(pkt->d, ether->ea, sizeof(pkt->d)) == 0;
fromme = memcmp(pkt->s, ether->ea, sizeof(pkt->s)) == 0;
/*
* Multiplex the packet to all the connections which want it.
* If the packet is not to be used subsequently (fromwire != 0),
* attempt to simply pass it into one of the connections, thereby
* saving a copy of the data (usual case hopefully).
*/
for(fp = ether->f; fp < ep; fp++){
if(f = *fp)
if(f->type == type || f->type < 0)
if(tome || multi || f->prom){
/* Don't want to hear loopback or bridged packets */
if(f->bridge && (tome || !fromwire && !fromme))
continue;
if(!f->headersonly){
if(fromwire && fx == 0)
fx = f;
else if(xbp = iallocb(len)){
memmove(xbp->wp, pkt, len);
xbp->wp += len;
if(qpass(f->in, xbp) < 0) {
// print("soverflow for f->in\n");
ether->soverflows++;
}
}
else {
// print("soverflow iallocb\n");
ether->soverflows++;
}
}
else
etherrtrace(f, pkt, len);
}
}
if(fx){
if(qpass(fx->in, bp) < 0) {
// print("soverflow for fx->in\n");
ether->soverflows++;
}
return 0;
}
if(fromwire){
freeb(bp);
return 0;
}
return bp;
}
static int
etheroq(Ether* ether, Block* bp)
{
int len, loopback;
Etherpkt *pkt;
ether->outpackets++;
/*
* Check if the packet has to be placed back onto the input queue,
* i.e. if it's a loopback or broadcast packet or the interface is
* in promiscuous mode.
* If it's a loopback packet indicate to etheriq that the data isn't
* needed and return, etheriq will pass-on or free the block.
* To enable bridging to work, only packets that were originated
* by this interface are fed back.
*/
pkt = (Etherpkt*)bp->rp;
len = BLEN(bp);
loopback = memcmp(pkt->d, ether->ea, sizeof(pkt->d)) == 0;
if(loopback || memcmp(pkt->d, ether->bcast, sizeof(pkt->d)) == 0 || ether->prom)
if(etheriq(ether, bp, loopback) == 0)
return len;
qbwrite(ether->oq, bp);
if(ether->transmit != nil)
ether->transmit(ether);
return len;
}
static long
etherwrite(Chan* chan, void* buf, long n, vlong)
{
Ether *ether;
Block *bp;
int nn, onoff;
Cmdbuf *cb;
ether = etherxx[chan->dev];
if(NETTYPE(chan->qid.path) != Ndataqid) {
nn = netifwrite(ether, chan, buf, n);
if(nn >= 0)
return nn;
cb = parsecmd(buf, n);
if(cb->f[0] && strcmp(cb->f[0], "nonblocking") == 0){
if(cb->nf <= 1)
onoff = 1;
else
onoff = atoi(cb->f[1]);
qnoblock(ether->oq, onoff);
free(cb);
return n;
}
free(cb);
if(ether->ctl!=nil)
return ether->ctl(ether,buf,n);
error(Ebadctl);
}
if(n > ether->maxmtu)
error(Etoobig);
if(n < ether->minmtu)
error(Etoosmall);
bp = allocb(n);
if(waserror()){
freeb(bp);
nexterror();
}
memmove(bp->rp, buf, n);
if(!ether->f[NETID(chan->qid.path)]->bridge)
memmove(bp->rp+Eaddrlen, ether->ea, Eaddrlen);
poperror();
bp->wp += n;
return etheroq(ether, bp);
}
static long
etherbwrite(Chan* chan, Block* bp, ulong)
{
Ether *ether;
long n;
n = BLEN(bp);
if(NETTYPE(chan->qid.path) != Ndataqid){
if(waserror()) {
freeb(bp);
nexterror();
}
n = etherwrite(chan, bp->rp, n, 0);
poperror();
freeb(bp);
return n;
}
ether = etherxx[chan->dev];
if(n > ether->maxmtu){
freeb(bp);
error(Etoobig);
}
if(n < ether->minmtu){
freeb(bp);
error(Etoosmall);
}
return etheroq(ether, bp);
}
static struct {
char* type;
int (*reset)(Ether*);
} cards[MaxEther+1];
void
addethercard(char* t, int (*r)(Ether*))
{
static int ncard;
if(ncard == MaxEther)
panic("too many ether cards");
cards[ncard].type = t;
cards[ncard].reset = r;
ncard++;
}
static Ether*
etherprobe(int cardno, int ctlrno)
{
int i, lg;
ulong mb, bsz;
Ether *ether;
char buf[128], name[32];
ether = malloc(sizeof(Ether));
if(ether == nil){
print("etherprobe: no memory for Ether\n");
return nil;
}
memset(ether, 0, sizeof(Ether));
ether->ctlrno = ctlrno;
ether->mbps = 10;
ether->minmtu = ETHERMINTU;
ether->maxmtu = ETHERMAXTU;
if(cardno >= MaxEther || cards[cardno].type == nil){
free(ether);
return nil;
}
if(cards[cardno].reset(ether) < 0){
free(ether);
return nil;
}
snprint(name, sizeof(name), "ether%d", ctlrno);
intrenable(ether->irq, ether->interrupt, ether, ether->irqlevel, name);
i = sprint(buf, "#l%d: %s: %dMbps port 0x%luX irq %d",
ctlrno, cards[cardno].type, ether->mbps, ether->port, ether->irq);
i += sprint(buf+i, ": %2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux",
ether->ea[0], ether->ea[1], ether->ea[2],
ether->ea[3], ether->ea[4], ether->ea[5]);
sprint(buf+i, "\n");
print(buf);
/* compute log10(ether->mbps) into lg */
for(lg = 0, mb = ether->mbps; mb >= 10; lg++)
mb /= 10;
if (lg > 0)
lg--;
if (lg > 14) /* 2^(14+17) = 2³¹ */
lg = 14;
/* allocate larger output queues for higher-speed interfaces */
bsz = 1UL << (lg + 17); /* 2¹⁷ = 128K, bsz = 2ⁿ × 128K */
while (bsz > mainmem->maxsize / 8 && bsz > 128*1024)
bsz /= 2;
netifinit(ether, name, Ntypes, bsz);
if(ether->oq == nil) {
ether->oq = qopen(bsz, Qmsg, 0, 0);
ether->limit = bsz;
}
if(ether->oq == nil)
panic("etherreset %s: can't allocate output queue of %ld bytes", name, bsz);
ether->alen = Eaddrlen;
memmove(ether->addr, ether->ea, Eaddrlen);
memset(ether->bcast, 0xFF, Eaddrlen);
return ether;
}
static void
etherreset(void)
{
Ether *ether;
int cardno, ctlrno;
cardno = ctlrno = 0;
while(cards[cardno].type != nil && ctlrno < MaxEther){
if(etherxx[ctlrno] != nil){
ctlrno++;
continue;
}
if((ether = etherprobe(cardno, ctlrno)) == nil){
cardno++;
continue;
}
etherxx[ctlrno] = ether;
ctlrno++;
}
}
static void
ethershutdown(void)
{
Ether *ether;
int i;
for(i = 0; i < MaxEther; i++){
ether = etherxx[i];
if(ether == nil)
continue;
if(ether->shutdown == nil) {
print("#l%d: no shutdown function\n", i);
continue;
}
(*ether->shutdown)(ether);
}
}
#define POLY 0xedb88320
/* really slow 32 bit crc for ethers */
ulong
ethercrc(uchar *p, int len)
{
int i, j;
ulong crc, b;
crc = 0xffffffff;
for(i = 0; i < len; i++){
b = *p++;
for(j = 0; j < 8; j++){
crc = (crc>>1) ^ (((crc^b) & 1) ? POLY : 0);
b >>= 1;
}
}
return crc;
}
Dev etherdevtab = {
'l',
"ether",
etherreset,
devinit,
ethershutdown,
etherattach,
etherwalk,
etherstat,
etheropen,
ethercreate,
etherclose,
etherread,
etherbread,
etherwrite,
etherbwrite,
devremove,
etherwstat,
};

View file

@ -1,40 +0,0 @@
enum {
MaxEther = 1,
Ntypes = 8,
};
typedef struct Ether Ether;
struct Ether {
int ctlrno;
int minmtu;
int maxmtu;
uchar ea[Eaddrlen];
int irq, irqlevel;
uintptr port;
void (*attach)(Ether*); /* filled in by reset routine */
void (*detach)(Ether*);
void (*transmit)(Ether*);
void (*interrupt)(Ureg*, void*);
long (*ifstat)(Ether*, void*, long, ulong);
long (*ctl)(Ether*, void*, long); /* custom ctl messages */
void (*power)(Ether*, int); /* power on/off */
void (*shutdown)(Ether*); /* shutdown hardware before reboot */
void *ctlr;
Queue* oq;
Netif;
};
extern Block* etheriq(Ether*, Block*, int);
extern void addethercard(char*, int(*)(Ether*));
extern ulong ethercrc(uchar*, int);
extern int parseether(uchar*, char*);
#define NEXT(x, l) (((x)+1)%(l))
#define PREV(x, l) (((x) == 0) ? (l)-1: (x)-1)
#define HOWMANY(x, y) (((x)+((y)-1))/(y))
#define ROUNDUP(x, y) (HOWMANY((x), (y))*(y))

View file

@ -5,7 +5,7 @@
#include "fns.h" #include "fns.h"
#include "io.h" #include "io.h"
#include "../port/netif.h" #include "../port/netif.h"
#include "etherif.h" #include "../port/etherif.h"
#define Rbsz ROUNDUP(sizeof(Etherpkt)+16, 64) #define Rbsz ROUNDUP(sizeof(Etherpkt)+16, 64)
@ -409,9 +409,7 @@ etherpnp(Ether *edev)
edev->port = ETH0_BASE; edev->port = ETH0_BASE;
ct.r = vmap(edev->port, BY2PG); ct.r = vmap(edev->port, BY2PG);
edev->irq = ETH0IRQ; edev->irq = ETH0IRQ;
edev->irqlevel = LEVEL;
edev->ctlr = &ct; edev->ctlr = &ct;
edev->interrupt = ethirq;
edev->transmit = ethtx; edev->transmit = ethtx;
edev->attach = ethattach; edev->attach = ethattach;
edev->promiscuous = ethprom; edev->promiscuous = ethprom;
@ -423,6 +421,8 @@ etherpnp(Ether *edev)
edev->ctlr = nil; edev->ctlr = nil;
return -1; return -1;
} }
intrenable(edev->irq, ethirq, edev, LEVEL, edev->name);
return 0; return 0;
} }

View file

@ -306,7 +306,7 @@ getconf(char *n)
int int
isaconfig(char *, int, ISAConf*) isaconfig(char *, int, ISAConf*)
{ {
return 1; return 0;
} }
void void