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:
parent
debb786fea
commit
d6e0e9c402
|
@ -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 {
|
||||
/*
|
||||
|
|
|
@ -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 = ðer->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, ðer->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,
|
||||
};
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 = ðer->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, ðer->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,
|
||||
};
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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))
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -240,6 +240,8 @@ struct ISAConf {
|
|||
char *opt[NISAOPT];
|
||||
};
|
||||
|
||||
#define BUSUNKNOWN -1
|
||||
|
||||
#define MACHP(n) (machaddr[n])
|
||||
|
||||
/*
|
||||
|
|
|
@ -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 = ðer->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,
|
||||
ðer->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,
|
||||
};
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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"
|
||||
|
||||
/*
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
||||
/*
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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))
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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;
|
|
@ -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;
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
@ -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 = ðer->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, ðer->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,
|
||||
};
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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))
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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 = ðer->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,
|
||||
};
|
|
@ -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))
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -502,3 +502,9 @@ setupwatchpts(Proc *, Watchpt *, int n)
|
|||
if(n > 0)
|
||||
error("no watchpoints");
|
||||
}
|
||||
|
||||
int
|
||||
isaconfig(char *, int, ISAConf*)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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 = ðer->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,
|
||||
ðer->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,
|
||||
};
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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 = ðer->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,
|
||||
};
|
|
@ -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))
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -306,7 +306,7 @@ getconf(char *n)
|
|||
int
|
||||
isaconfig(char *, int, ISAConf*)
|
||||
{
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
Loading…
Reference in a new issue