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

View file

@ -5,9 +5,6 @@
#define MiB 1048576u /* Mebi 0x0000000000100000 */
#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 MAX(a, b) ((a) > (b)? (a): (b))
@ -36,7 +33,7 @@
*/
#define BY2PG (4*KiB) /* bytes per page */
#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 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
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
fpi.$O fpiarm.$O fpimem.$O: fpi.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);
pa -= o;
size += o;
size = ROUNDUP(size, BY2PG);
size = PGROUND(size);
va = kseg0|pa;
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 "../port/error.h"
#include "../port/netif.h"
#include "etherif.h"
#include "../port/etherif.h"
#define DEBUG (0)
#define debug if(DEBUG)print
@ -1654,12 +1653,13 @@ ether->irq = 2; /* arrrrrgh */
*/
ether->attach = attach;
ether->transmit = transmit;
ether->interrupt = interrupt;
ether->ifstat = ifstat;
ether->arg = ether;
ether->promiscuous = promiscuous;
intrenable(ether->irq, interrupt, ether, ether->tbdf, ether->name);
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
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
$AS initcode

View file

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

View file

@ -240,6 +240,8 @@ struct ISAConf {
char *opt[NISAOPT];
};
#define BUSUNKNOWN -1
#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;
iunlock(&alloclck);
ruplen = ROUNDUP(len, sizeof(ulong));
ruplen = ROUND(len, sizeof(ulong));
assert(to != from);
cp = regs->chan + chan;

View file

@ -18,8 +18,7 @@
#include "io.h"
#include "../port/error.h"
#include "../port/netif.h"
#include "etherif.h"
#include "../port/etherif.h"
/* currently using kprocs is a lot slower than not (87 s. to boot vs 60) */
#undef USE_KPROCS
@ -943,7 +942,6 @@ smcpnp(Ether* edev)
*/
edev->attach = smcattach;
edev->transmit = smctransmitcall;
edev->interrupt = smcinterrupt;
edev->ifstat = smcifstat;
/* edev->ctl = smcctl; /* no ctl msgs supported */
@ -951,6 +949,9 @@ smcpnp(Ether* edev)
edev->promiscuous = smcpromiscuous;
edev->multicast = smcmulticast;
edev->shutdown = smcshutdown;
intrenable(edev->irq, smcinterrupt, edev, 0, edev->name);
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 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 MAX(a, b) ((a) > (b)? (a): (b))
@ -36,7 +33,7 @@
*/
#define BY2PG (4*KiB) /* bytes per page */
#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 MAXMACH 1 /* max # cpus system can run */
@ -71,7 +68,7 @@
#define UZERO 0 /* user segment */
#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. */
#define USTKTOP 0x20000000 /* user segment end +1 */
#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 \
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
ecc.$O flashbeagle.$O flashigep.$O: ../port/nandecc.h io.h
fpi.$O fpiarm.$O fpimem.$O: fpi.h

View file

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

View file

@ -257,7 +257,7 @@ configdispc(void)
(sp->vsw-1);
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);
coherence();

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -18,10 +18,9 @@
#include "io.h"
#include "../port/error.h"
#include "../port/netif.h"
#include "../port/etherif.h"
#define malign(n) xspanalloc((n), 32, 0)
#include "etherif.h"
#include "etherga620fw.h"
enum {
@ -1260,7 +1259,6 @@ ga620pnp(Ether* edev)
*/
edev->attach = ga620attach;
edev->transmit = ga620transmit;
edev->interrupt = ga620interrupt;
edev->ifstat = ga620ifstat;
edev->ctl = ga620ctl;
@ -1269,6 +1267,8 @@ ga620pnp(Ether* edev)
edev->multicast = ga620multicast;
edev->shutdown = ga620shutdown;
intrenable(edev->irq, ga620interrupt, edev, edev->tbdf, edev->name);
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 "../port/error.h"
#include "../port/netif.h"
#include "../port/etherif.h"
#include "etherif.h"
#include "ethermii.h"
enum {
@ -2020,7 +2020,6 @@ igbepnp(Ether* edev)
*/
edev->attach = igbeattach;
edev->transmit = igbetransmit;
edev->interrupt = igbeinterrupt;
edev->ifstat = igbeifstat;
edev->ctl = igbectl;
@ -2029,6 +2028,8 @@ igbepnp(Ether* edev)
edev->shutdown = igbeshutdown;
edev->multicast = igbemulticast;
intrenable(edev->irq, igbeinterrupt, edev, edev->tbdf, edev->name);
return 0;
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -100,7 +100,7 @@ install:V: $p$CONF
<../port/portmkfile
<|../port/mkbootrules $CONF
$ETHER: etherif.h ../port/netif.h
$ETHER: ../port/etherif.h ../port/netif.h
$AUDIO: ../port/audioif.h
ether8003.$O ether8390.$O: ether8390.h
etheryuk.$O: yukdump.h
@ -122,11 +122,9 @@ usbehci.$O usbehcipc.$O: usbehci.h
trap.$O: /sys/include/tos.h
uartaxp.$O: uartaxp.i
etherm10g.$O: etherm10g2k.i etherm10g4k.i
etheriwl.$O: wifi.h
etherwpi.$O: wifi.h
etherrt2860.$O: wifi.h
wifi.$O: wifi.h etherif.h ../port/netif.h /sys/include/libsec.h
wifi.$O: ../ip/ip.h ../ip/ipv6.h
etheriwl.$O: ../port/wifi.h
etherwpi.$O: ../port/wifi.h
etherrt2860.$O: ../port/wifi.h
init.h:D: ../port/initcode.c init9.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);
return;
}
if(tbdf != BUSUNKNOWN && (irq == 0xff || irq == 0)){
print("intrenable: got unassigned irq %d, tbdf 0x%uX for %s\n",
irq, tbdf, name);
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)
panic("intrenable: out of memory");
v->isintr = 1;
@ -83,6 +90,8 @@ intrdisable(int irq, void (*f)(Ureg *, void *), void *a, int tbdf, char *name)
Vctl **pv, *v;
int vno;
if(irq == 2)
irq = 9;
if(arch->intrvecno == nil || (tbdf != BUSUNKNOWN && (irq == 0xff || irq == 0))){
/*
* on APIC machine, irq is pretty meaningless

View file

@ -272,16 +272,6 @@ reset(Hci *hp)
ehcilinkage(hp);
hp->shutdown = shutdown;
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);
return 0;

View file

@ -2608,14 +2608,6 @@ reset(Hci *hp)
hp->shutdown = shutdown;
hp->debug = usbdebug;
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);
return 0;

View file

@ -2345,14 +2345,6 @@ reset(Hci *hp)
hp->shutdown = shutdown;
hp->debug = setdebug;
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);
return 0;

View file

@ -25,7 +25,8 @@
#include "io.h"
#include "../port/error.h"
#include "../port/netif.h"
#include "etherif.h"
#include "../port/etherif.h"
#include "wavelan.h"
enum
@ -1234,7 +1235,6 @@ wavelanreset(Ether* ether, Ctlr *ctlr)
ether->mbps = 10;
ether->attach = w_attach;
ether->detach = w_detach;
ether->interrupt = w_interrupt;
ether->transmit = w_transmit;
ether->ifstat = w_ifstat;
ether->ctl = w_ctl;
@ -1244,6 +1244,8 @@ wavelanreset(Ether* ether, Ctlr *ctlr)
ether->scanbs = w_scanbs;
ether->arg = ether;
intrenable(ether->irq, w_interrupt, ether, ether->tbdf, ether->name);
DEBUG("#l%d: irq %d port %lx type %s",
ether->ctlrno, ether->irq, ether->port, ether->type);
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
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
REPCH=`{echo $PCHEADERS | sed 's/\.h//g; s/ /|/g'}
@ -100,7 +100,7 @@ REPCC=`{../port/mkfilelist ../pc}
l.$O apbootstrap.$O: mem.h
$ETHER: etherif.h ../port/netif.h
$ETHER: ../port/etherif.h ../port/netif.h
$AUDIO: ../port/audioif.h
ether8003.$O ether8390.$O: ether8390.h
etheryuk.$O: yukdump.h
@ -122,11 +122,9 @@ usbehci.$O usbehcipc.$O: usbehci.h
trap.$O: /sys/include/tos.h
ethermii.$O: ethermii.h
etheriwl.$O: wifi.h
etherwpi.$O: wifi.h
etherrt2860.$O: wifi.h
wifi.$O: wifi.h etherif.h ../port/netif.h /sys/include/libsec.h
wifi.$O: ../ip/ip.h ../ip/ipv6.h
etheriwl.$O: ../port/wifi.h
etherwpi.$O: ../port/wifi.h
etherrt2860.$O: ../port/wifi.h
init.h:D: ../port/initcode.c ../pc/init9.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;
}
/*
* 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)
panic("intrenable: out of memory");
v->isintr = 1;
@ -83,6 +92,8 @@ intrdisable(int irq, void (*f)(Ureg *, void *), void *a, int tbdf, char *name)
Vctl **pv, *v;
int vno;
if(irq == 2)
irq = 9;
if(arch->intrvecno == nil || (tbdf != BUSUNKNOWN && (irq == 0xff || irq == 0))){
/*
* on APIC machine, irq is pretty meaningless

View file

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

View file

@ -8,8 +8,9 @@
#include "ureg.h"
#include "../port/error.h"
#include "../port/netif.h"
#include "../port/etherif.h"
#include "etherif.h"
extern int eipfmt(Fmt*);
static Ether *etherxx[MaxEther];
@ -348,7 +349,6 @@ 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){
@ -356,8 +356,9 @@ etherprobe(int cardno, int ctlrno)
return nil;
}
memset(ether, 0, sizeof(Ether));
ether->ctlrno = ctlrno;
ether->tbdf = BUSUNKNOWN;
ether->irq = -1;
ether->ctlrno = ctlrno;
ether->mbps = 10;
ether->minmtu = ETHERMINTU;
ether->maxmtu = ETHERMAXTU;
@ -384,38 +385,15 @@ etherprobe(int cardno, int ctlrno)
free(ether);
return nil;
}
snprint(ether->name, sizeof(ether->name), "ether%d", ctlrno);
if(cards[cardno].reset(ether) < 0){
free(ether);
return nil;
}
/*
* 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)
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);
print("#l%d: %s: %dMbps port 0x%luX irq %d ea %E\n",
ctlrno, cards[cardno].type,
ether->mbps, ether->port, ether->irq, ether->ea);
/* compute log10(ether->mbps) into 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)
bsz /= 2;
netifinit(ether, name, Ntypes, bsz);
netifinit(ether, 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);
panic("etherreset %s: can't allocate output queue of %ld bytes", ether->name, bsz);
ether->alen = Eaddrlen;
memmove(ether->addr, ether->ea, Eaddrlen);
memset(ether->bcast, 0xFF, Eaddrlen);
@ -449,6 +428,8 @@ etherreset(void)
Ether *ether;
int cardno, ctlrno;
fmtinstall('E', eipfmt);
for(ctlrno = 0; ctlrno < MaxEther; ctlrno++){
if((ether = etherprobe(-1, ctlrno)) == nil)
continue;

View file

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

View file

@ -101,3 +101,6 @@ devaoe.$O sdaoe.$O: /sys/include/fis.h
sysproc.$O: /sys/include/a.out.h
syscallfmt.$O: /sys/src/libc/9syscall/sys.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 "../port/error.h"
#include "../port/netif.h"
#include "etherif.h"
#include "wifi.h"
#include "../port/etherif.h"
#include "../port/wifi.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 "../port/error.h"
#include "../port/netif.h"
#include "../port/etherif.h"
#include "etherif.h"
#include "../ppc/ethermii.h"
#define DBG 1
@ -719,7 +719,6 @@ reset(Ether* ether)
ether->mbps = 100; /* TO DO: could be 10mbps */
ether->attach = attach;
ether->transmit = transmit;
ether->interrupt = interrupt;
ether->ifstat = ifstat;
ether->arg = ether;
@ -736,6 +735,8 @@ reset(Ether* ether)
return -1;
}
intrenable(ether->irq, interrupt, ether, ether->name);
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 "../port/error.h"
#include "../port/netif.h"
#include "msaturn.h"
#include "../port/etherif.h"
#include "etherif.h"
#include "msaturn.h"
enum{
Etcr = Saturn + 0x0c00,
@ -209,7 +209,6 @@ reset(Ether* ether)
ether->ctlr = ctlr;
ether->transmit = transmit;
ether->interrupt = interrupt;
ether->irq = Vecether;
ether->arg = ether;
memmove(ether->ea, (ushort*)Emacaddr0, Eaddrlen);
@ -218,6 +217,9 @@ reset(Ether* ether)
*eimr = Ei_rxdone|Ei_txretry|Ei_txdone;
iprint("reset: ercr %.4uX\n", *ercr);
intrenable(ether->irq, interrupt, ether, ether->name);
return 0;
}

View file

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

View file

@ -13,6 +13,7 @@ typedef struct PMMU PMMU;
typedef struct Softtlb Softtlb;
typedef struct Ureg Ureg;
typedef struct Proc Proc;
typedef struct ISAConf ISAConf;
typedef uvlong Tval;
#define MAXSYSARG 5 /* for mount(fd, afd, mpt, flag, arg) */
@ -70,6 +71,16 @@ struct Conf
int keyboard;
};
struct ISAConf
{
char *type;
ulong port;
int irq;
int nopt;
char *opt[1];
};
#define BUSUNKNOWN -1
/*
* 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 "io.h"
#include "../port/netif.h"
#include "etherif.h"
#include "../port/etherif.h"
typedef struct Hio Hio;
typedef struct Desc Desc;
@ -451,19 +451,21 @@ pnp(Ether *edev)
edev->ctlr = &ct;
edev->port = HPC3_ETHER;
edev->irq = IRQENET;
edev->irqlevel = hpc3irqlevel(edev->irq);
edev->ctlr = &ct;
edev->promiscuous = promiscuous;
edev->multicast = multicast;
edev->interrupt = interrupt;
edev->attach = attach;
edev->arg = edev;
edev->mbps = 10;
edev->link = 1;
if(init(edev) < 0){
edev->ctlr = nil;
return -1;
}
intrenable(hpc3irqlevel(edev->irq), interrupt, edev);
return 0;
}

View file

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

View file

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

View file

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

View file

@ -12,7 +12,7 @@
#include "arm.h"
#include "../port/netif.h"
#include "etherif.h"
#include "../port/etherif.h"
#include "../port/flashif.h"
#include "../port/usb.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 "../port/error.h"
#include "../port/netif.h"
#include "../port/etherif.h"
#include "etherif.h"
#include "ethermii.h"
typedef struct Ctlr Ctlr;
@ -1655,7 +1655,6 @@ rtl8169pnp(Ether* edev)
edev->attach = rtl8169attach;
edev->transmit = rtl8169transmit;
edev->interrupt = rtl8169interrupt;
edev->ifstat = rtl8169ifstat;
edev->arg = edev;
@ -1666,6 +1665,9 @@ rtl8169pnp(Ether* edev)
ilock(&ctlr->reglock);
rtl8169link(edev);
iunlock(&ctlr->reglock);
intrenable(edev->irq, rtl8169interrupt, edev, 0, edev->name);
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 "../port/error.h"
#include "../port/netif.h"
#include "../port/etherif.h"
#include "etherif.h"
#include "ethermii.h"
int

View file

@ -5,9 +5,6 @@
#define MiB 1048576u /* Mebi 0x0000000000100000 */
#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 MAX(a, b) ((a) > (b)? (a): (b))
@ -36,7 +33,7 @@
*/
#define BY2PG (4*KiB) /* bytes per page */
#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))
/* max # of cpus system can run. tegra2 cpu ids are two bits wide. */
@ -85,7 +82,6 @@
#define UZERO 0 /* user segment */
#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 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 \
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
ecc.$O flashtegra.$O flashigep.$O: ../port/nandecc.h io.h
fpi.$O fpiarm.$O fpimem.$O: fpi.h

View file

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

View file

@ -10,7 +10,7 @@
#include "io.h"
#include "../port/error.h"
#include "../port/netif.h"
#include "etherif.h"
#include "../port/etherif.h"
#define LOG(a)
@ -478,12 +478,14 @@ pnp(Ether* ether)
ether->transmit = etherxentransmit;
ether->irq = -1;
ether->tbdf = BUSUNKNOWN;
ether->interrupt = etherxenintr;
ether->ifstat = ifstat;
ether->ctl = etherxenctl;
ether->promiscuous = nil;
ether->multicast = etherxenmulticast;
ether->arg = ether;
intrenable(ether->irq, etherxenintr, ether, ether->tbdf, ether->name);
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/
# 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)\.h:R: '../pc/\1.h'
@ -132,7 +132,7 @@ ptclbsum386.$O: ../pc/ptclbsum386.s
$AS $AFLAGS ../pc/ptclbsum386.s
# we inherited these.. revisit.
$ETHER: etherif.h ../port/netif.h
$ETHER: ../port/etherif.h ../port/netif.h
$SDEV: ../port/sd.h
main.$O: init.h reboot.h
trap.$O: /sys/include/tos.h

View file

@ -20,7 +20,7 @@ dev
xenstore
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

View file

@ -161,10 +161,11 @@ struct Mach
struct ISAConf
{
int dummy;
char *type;
ulong port;
int irq;
char *type;
ulong port;
int irq;
int nopt;
char *opt[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 "io.h"
#include "../port/netif.h"
#include "etherif.h"
#include "../port/etherif.h"
#define Rbsz ROUNDUP(sizeof(Etherpkt)+16, 64)
@ -409,9 +409,7 @@ etherpnp(Ether *edev)
edev->port = ETH0_BASE;
ct.r = vmap(edev->port, BY2PG);
edev->irq = ETH0IRQ;
edev->irqlevel = LEVEL;
edev->ctlr = &ct;
edev->interrupt = ethirq;
edev->transmit = ethtx;
edev->attach = ethattach;
edev->promiscuous = ethprom;
@ -423,6 +421,8 @@ etherpnp(Ether *edev)
edev->ctlr = nil;
return -1;
}
intrenable(edev->irq, ethirq, edev, LEVEL, edev->name);
return 0;
}

View file

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