2 * myricom 10g-pcie-8a 10 Gb ethernet driver
3 * © 2007 erik quanstrom, coraid
5 * the card is big endian.
6 * we use uvlong rather than uintptr to hold addresses so that
7 * we don't get "warning: stupid shift" on 32-bit architectures.
10 #include "../port/lib.h"
15 #include "../port/error.h"
16 #include "../port/netif.h"
17 #include "../port/etherif.h"
20 #define KiB 1024u /* Kibi 0x0000000000000400 */
21 #define MiB 1048576u /* Mebi 0x0000000000100000 */
24 #define dprint(...) if(debug) print(__VA_ARGS__)
25 #define pcicapdbg(...)
26 #define malign(n) mallocalign((n), 4*KiB, 0, 0)
28 #include "etherm10g2k.i"
29 #include "etherm10g4k.i"
32 static char Etimeout[] = "timeout";
42 Cmdoff = 0xf80000, /* command port offset */
43 Fwsubmt = 0xfc0000, /* firmware submission command port offset */
44 Rdmaoff = 0xfc01c0, /* rdma command port offset */
52 CSintrqdma, /* issue these before Cetherup */
53 CSbigsz, /* in bytes bigsize = 2^n */
65 Cetherup, /* above parameters + mtu/mac addr must be set first. */
68 CSmtu, /* below may be issued live */
69 CGcoaloff, /* in µs */
70 CSstatsrate, /* in µs */
80 Cdmatest, /* address in d[0-1], d[2]=length */
89 CSstatsdma2, /* adds (unused) multicast stats */
123 Send *lanai; /* tx ring (cksum+len in lanai memory) */
124 Send *host; /* tx ring (data in our memory) */
126 // uchar *wcfifo; /* what the heck is a w/c fifo? */
127 int size; /* of buffers in the z8's memory */
129 uint n; /* rxslots */
130 uint m; /* mask; rxslots must be a power of two */
131 uint i; /* number of segments (not frames) queued */
132 uint cnt; /* number of segments sent by the card */
141 uint size; /* buffer size of each block */
142 uint n; /* n free buffers */
146 static Bpool smpool = { .size = 128, };
147 static Bpool bgpool = { .size = Maxmtu, };
150 Bpool *pool; /* free buffers */
151 ulong *lanai; /* rx ring; we have no permanent host shadow */
152 Block **host; /* called "info" in myricom driver */
153 // uchar *wcfifo; /* cmd submission fifo */
155 uint n; /* rxslots */
157 uint cnt; /* number of buffers allocated (lifetime) */
161 /* dma mapped. unix network byte order. */
192 typedef struct Ctlr Ctlr;
193 typedef struct Ctlr {
201 int id; /* do we need this? */
213 ulong serial; /* unit serial number */
216 Cmd *cmd; /* address of command return */
217 uvlong cprt; /* bus address of command */
219 uvlong boot; /* boot address */
239 PciCapPMG = 0x01, /* power management */
241 PciCapVPD = 0x03, /* vital product data */
242 PciCapSID = 0x04, /* slot id */
244 PciCapCHS = 0x06, /* compact pci hot swap */
246 PciCapHTC = 0x08, /* hypertransport irq conf */
247 PciCapVND = 0x09, /* vendor specific information */
248 PciCapHSW = 0x0C, /* hot swap */
261 AercCCR = 0x18, /* control register */
267 PcieMRD = 0x7000, /* maximum read size */
271 pcicap(Pcidev *p, int cap)
275 pcicapdbg("pcicap: %x:%d\n", p->vid, p->did);
276 off = 0x34; /* 0x14 for cardbus */
278 pcicapdbg("\t" "loop %x\n", off);
279 off = pcicfgr8(p, off);
280 pcicapdbg("\t" "pcicfgr8 %x\n", off);
284 c = pcicfgr8(p, off);
285 pcicapdbg("\t" "pcicfgr8 %x\n", c);
296 * this function doesn't work because pcicgr32 doesn't have access
297 * to the pcie extended configuration space.
300 pciecap(Pcidev *p, int cap)
305 while(((i = pcicfgr32(p, off)) & 0xffff) != cap){
307 print("m10g: pciecap offset = %ud", off);
308 if(off < 0x100 || off >= 4*KiB - 1)
311 print("m10g: pciecap found = %ud", off);
321 off = pcicap(p, PciCapPCIe);
325 pcicfgw16(p, off, (pcicfgr16(p, off) & ~PcieMRD) | 5<<12);
333 int i, off, lanes, ecrc;
336 /* check the number of configured lanes. */
337 off = pcicap(p, PciCapPCIe);
341 cap = pcicfgr16(p, off);
342 lanes = (cap>>4) & 0x3f;
344 /* check AERC register. we need it on. */
345 off = pciecap(p, PcieAERC);
346 print("; offset %d returned\n", off);
350 cap = pcicfgr32(p, off);
351 print("m10g: %lud cap\n", cap);
353 ecrc = (cap>>4) & 0xf;
354 /* if we don't like the aerc, kick it here. */
356 print("m10g: %d lanes; ecrc=%d; ", lanes, ecrc);
357 if(s = getconf("myriforce")){
359 if(i != 4*KiB || i != 2*KiB)
361 print("fw = %d [forced]\n", i);
365 print("fw = 4096 [lanes]\n");
367 print("fw = 4096 [ecrc set]\n");
369 print("fw = 4096 [default]\n");
376 int i, j, k, l, bits;
379 dprint("m10g eprom:\n");
382 for(i = 0; s[i] && i < Epromsz; i++){
384 dprint("\t%s\n", s+i);
385 if(strncmp(s+i, "MAC=", 4) == 0 && l == 4+12+5){
388 for(k = 0; k < 6; k++)
389 c->ra[k] = strtoul(s+j+3*k, 0, 16);
390 }else if(strncmp(s+i, "SN=", 3) == 0){
392 c->serial = strtoul(s+i+3, 0, 10);
450 prepcmd(ulong *cmd, int i)
453 cmd[i] = pbit32(cmd[i]);
457 * the command looks like this (int 32bit integers)
461 * pad (used for dma testing)
464 * 40 byte = 5 int pad.
468 cmd(Ctlr *c, int type, uvlong data)
476 memset(buf, 0, sizeof buf);
480 buf[4] = c->cprt >> 32;
484 memmove(c->ram + Cmdoff, buf, sizeof buf);
488 for(i = 0; i < 15; i++){
489 if(cmd->i[1] != Noconf){
497 tsleep(&up->sleep, return0, 0, 1);
500 iprint("m10g: cmd timeout [%ux %ux] cmd=%d\n",
501 cmd->i[0], cmd->i[1], type);
503 return ~0; /* silence! */
507 maccmd(Ctlr *c, int type, uchar *m)
515 memset(buf, 0, sizeof buf);
517 buf[1] = m[0]<<24 | m[1]<<16 | m[2]<<8 | m[3];
518 buf[2] = m[4]<< 8 | m[5];
519 buf[4] = c->cprt >> 32;
523 memmove(c->ram + Cmdoff, buf, sizeof buf);
527 for(i = 0; i < 15; i++){
528 if(cmd->i[1] != Noconf){
536 tsleep(&up->sleep, return0, 0, 1);
539 iprint("m10g: maccmd timeout [%ux %ux] cmd=%d\n",
540 cmd->i[0], cmd->i[1], type);
542 return ~0; /* silence! */
545 /* remove this garbage after testing */
552 dmatestcmd(Ctlr *c, int type, uvlong addr, int len)
556 memset(buf, 0, sizeof buf);
557 memset(c->cmd, Noconf, sizeof *c->cmd);
562 buf[4] = c->cprt >> 32;
566 memmove(c->ram + Cmdoff, buf, sizeof buf);
570 for(i = 0; i < 15; i++){
571 if(c->cmd->i[1] != Noconf){
572 i = gbit32(c->cmd->c);
578 tsleep(&up->sleep, return0, 0, 5);
581 return ~0; /* silence! */
585 rdmacmd(Ctlr *c, int on)
589 memset(buf, 0, sizeof buf);
592 buf[0] = c->cprt >> 32;
595 buf[3] = c->cprt >> 32;
599 memmove(c->ram + Rdmaoff, buf, sizeof buf);
603 for(i = 0; i < 20; i++){
604 if(c->cmd->i[0] == Noconf){
606 return gbit32(c->cmd->c);
608 tsleep(&up->sleep, return0, 0, 1);
611 iprint("m10g: rdmacmd timeout\n");
612 return ~0; /* silence! */
616 loadfw(Ctlr *c, int *align)
621 if((*align = whichfw(c->pcidev)) == 4*KiB){
629 s = (ulong*)(c->ram + Fwoffset);
630 for(i = 0; i < sz / 4; i++)
642 if((sz = loadfw(c, &align)) == 0)
644 dprint("bootfw %d bytes ... ", sz);
647 memset(buf, 0, sizeof buf);
650 buf[0] = c->cprt >> 32; /* upper dma target address */
651 buf[1] = c->cprt; /* lower */
652 buf[2] = Noconf; /* writeback */
653 buf[3] = Fwoffset + 8,
659 memmove(c->ram + Fwsubmt, buf, sizeof buf);
661 for(i = 0; i < 20; i++){
662 if(cmd->i[0] == Noconf)
666 dprint("[%lux %lux]", gbit32(cmd->c), gbit32(cmd->c+4));
668 print("m10g: cannot load fw\n");
677 kickthebaby(Pcidev *p, Ctlr *c)
679 /* don't kick the baby! */
682 pcicfgw8(p, 0x10 + c->boot, 0x3);
683 pcicfgw32(p, 0x18 + c->boot, 0xfffffff0);
684 code = pcicfgr32(p, 0x14 + c->boot);
686 dprint("reboot status = %lux\n", code);
687 if(code != 0xfffffff0)
731 off = gbit32(c->ram+0x3c);
732 dprint("firmware %lux\n", off);
733 if((off&3) || off + sizeof *h > c->ramsz){
734 print("!m10g: bad firmware %lux\n", off);
737 h = (Fwhdr*)(c->ram + off);
738 type = gbit32(h->type);
739 dprint("\t" "type %s\n", fwtype(type));
740 dprint("\t" "vers %s\n", h->version);
741 dprint("\t" "ramsz %lux\n", gbit32(h->ramsz));
743 print("!m10g: bad card type %s\n", fwtype(type));
747 return bootfw(c) || rdmacmd(c, 0);
751 reset(Ether *e, Ctlr *c)
756 print("m10g: reset error\n");
764 cmd(c, CSintrqsz, c->done.n * sizeof *c->done.entry);
765 cmd(c, CSintrqdma, c->done.busaddr);
766 c->irqack = (ulong*)(c->ram + cmd(c, CGirqackoff, 0));
767 /* required only if we're not doing msi? */
768 c->irqdeass = (ulong*)(c->ram + cmd(c, CGirqdeassoff, 0));
769 /* this is the driver default, why fiddle with this? */
770 c->coal = (ulong*)(c->ram + cmd(c, CGcoaloff, 0));
771 *c->coal = pbit32(25);
773 dprint("dma stats:\n");
776 i = dmatestcmd(c, DMAread, c->done.busaddr, sz);
777 print("m10g: read %lud MB/s;", ((i>>16)*sz*2) / (i&0xffff));
778 i = dmatestcmd(c, DMAwrite, c->done.busaddr, sz);
779 print(" write %lud MB/s;", ((i>>16)*sz*2) / (i&0xffff));
780 i = dmatestcmd(c, DMAwrite|DMAread, c->done.busaddr, sz);
781 print(" r/w %lud MB/s\n", ((i>>16)*sz*2*2) / (i&0xffff));
782 memset(c->done.entry, 0, c->done.n * sizeof *c->done.entry);
784 maccmd(c, CSmac, c->ra);
785 // cmd(c, Cnopromisc, 0);
786 cmd(c, Cenablefc, 0);
788 cmd(c, CSmtu, e->maxmtu);
789 dprint("CSmtu %d...\n", e->maxmtu);
798 /* free up all the Block*s, too */
809 setmem(Pcidev *p, Ctlr *c)
817 c->ramsz = 2*MiB - (2*48*KiB + 32*KiB) - 0x100;
818 if(c->ramsz > p->mem[0].size)
821 raddr = p->mem[0].bar & ~0x0F;
822 mem = vmap(raddr, p->mem[0].size);
824 print("m10g: can't map %8.8lux\n", p->mem[0].bar);
827 dprint("%llux <- vmap(mem[0].size = %ux)\n", raddr, p->mem[0].size);
830 c->cmd = malign(sizeof *c->cmd);
831 c->cprt = PCIWADDR(c->cmd);
836 i = d->n * sizeof *d->entry;
837 d->entry = malign(i);
838 memset(d->entry, 0, i);
839 d->busaddr = PCIWADDR(d->entry);
841 c->stats = malign(sizeof *c->stats);
842 memset(c->stats, 0, sizeof *c->stats);
843 c->statsprt = PCIWADDR(c->stats);
845 memmove(c->eprom, c->ram + c->ramsz - Epromsz, Epromsz-2);
846 return setpcie(p) || parseeprom(c);
850 whichrx(Ctlr *c, int sz)
852 if(sz <= smpool.size)
863 if((bp = rx->pool->head) != nil){
864 rx->pool->head = bp->next;
873 rbfree(Block *b, Bpool *p)
875 b->rp = b->wp = (uchar*)PGROUND((uintptr)b->base);
876 b->flag &= ~(Bipck | Budpck | Btcpck | Bpktck);
901 ulong buf[16], i, idx, e;
908 memset(buf, 0, sizeof buf);
909 e = (rx->i - rx->cnt) & ~7;
911 while(p->n >= 8 && e){
912 idx = rx->cnt & rx->m;
913 for(i = 0; i < 8; i++){
915 buf[i*2] = pbit32((uvlong)PCIWADDR(b->wp) >> 32);
916 buf[i*2+1] = pbit32(PCIWADDR(b->wp));
920 memmove(rx->lanai + 2*idx, buf, sizeof buf);
926 print("m10g: should panic? pool->n = %d", p->n);
931 * if (c->mtrr >= 0) {
932 * c->tx.wcfifo = c->ram+0x200000;
933 * c->sm.wcfifo = c->ram+0x300000;
934 * c->bg.wcfifo = c->ram+0x340000;
943 for(i = 0; j > (1 << i); i++)
961 open0(Ether *e, Ctlr *c)
966 entries = cmd(c, CGsendrgsz, 0) / sizeof *c->tx.lanai;
967 c->tx.lanai = (Send*)(c->ram + cmd(c, CGsendoff, 0));
968 c->tx.host = emalign(entries * sizeof *c->tx.host);
969 c->tx.bring = emalign(entries * sizeof *c->tx.bring);
973 entries = cmd(c, CGrxrgsz, 0)/8;
974 c->sm.pool = &smpool;
975 cmd(c, CSsmallsz, c->sm.pool->size);
976 c->sm.lanai = (ulong*)(c->ram + cmd(c, CGsmallrxoff, 0));
979 c->sm.host = emalign(entries * sizeof *c->sm.host);
981 c->bg.pool = &bgpool;
982 c->bg.pool->size = nextpow(2 + e->maxmtu); /* 2-byte alignment pad */
983 cmd(c, CSbigsz, c->bg.pool->size);
984 c->bg.lanai = (ulong*)(c->ram + cmd(c, CGbigrxoff, 0));
987 c->bg.host = emalign(entries * sizeof *c->bg.host);
989 sz = c->sm.pool->size + BY2PG;
990 for(i = 0; i < c->sm.n; i++){
991 if((b = allocb(sz)) == 0)
996 sz = c->bg.pool->size + BY2PG;
997 for(i = 0; i < c->bg.n; i++){
998 if((b = allocb(sz)) == 0)
1004 cmd(c, CSstatsdma, c->statsprt);
1008 cmd(c, Cetherup, 0);
1025 sp = (Slotparts *)(s + i);
1032 l = gbit16((uchar*)&l);
1033 //dprint("nextb: i=%d l=%d\n", d->i, l);
1035 if(rx->i >= rx->cnt){
1036 iprint("m10g: overrun\n");
1043 iprint("m10g: error rx to no block. memory is hosed.\n");
1048 b->flag |= Bipck|Btcpck|Budpck;
1052 b->lim = b->wp; /* lie like a dog. */
1067 sp = (Slotparts *)(s + (d->i & d->m));
1070 c->irqack[0] = pbit32(3);
1088 sleep(&c->rxrendez, rxcansleep, c);
1089 while(b = nextblock(c))
1095 txcleanup(Tx *tx, ulong n)
1105 * if tx->cnt == tx->i, yet tx->npkt == n-1, we just
1106 * caught ourselves and myricom card updating.
1109 j = tx->cnt & tx->m;
1110 if(b = tx->bring[j]){
1112 tx->nbytes += BLEN(b);
1117 if(tx->cnt == tx->i)
1120 iprint("m10g: tx ovrun: %lud %lud\n", n, tx->npkt);
1132 if(c->tx.cnt != c->tx.i && c->tx.npkt != gbit32(c->stats->txcnt))
1150 sleep(&c->txrendez, txcansleep, c);
1151 txcleanup(tx, gbit32(c->stats->txcnt));
1156 submittx(Tx *tx, int n)
1165 for(i = n-1; i >= 0; i--)
1166 memmove(l+(i + i0 & m), h+(i + i0 & m), sizeof *h);
1172 nsegments(Block *b, int segsz)
1174 uintptr bus, end, slen, len;
1177 bus = PCIWADDR(b->rp);
1179 for(len = BLEN(b); len; len -= slen){
1180 end = bus + segsz & ~(segsz-1);
1191 m10gtransmit(Ether *e)
1194 ulong i, cnt, rdma, nseg, count, end, bus, len, segsz;
1198 Send *s, *s0, *s0m8;
1207 s = tx->host + (tx->i & tx->m);
1209 s0 = tx->host + (cnt & tx->m);
1210 s0m8 = tx->host + ((cnt - 8) & tx->m);
1212 for(; s >= s0 || s < s0m8; i += nseg){
1213 if((b = qget(e->oq)) == nil)
1215 flags = SFfirst|SFnotso;
1216 if((len = BLEN(b)) < 1520)
1218 rdma = nseg = nsegments(b, segsz);
1219 bus = PCIWADDR(b->rp);
1220 for(; len; len -= slen){
1221 end = (bus + segsz) & ~(segsz-1);
1225 s->low = pbit32(bus);
1226 s->len = pbit16(slen);
1231 if(++s == tx->host + tx->n)
1237 tx->bring[(i + nseg - 1) & tx->m] = b;
1239 submittx(tx, count);
1242 s0 = tx->host + (cnt & tx->m);
1243 s0m8 = tx->host + ((cnt - 8) & tx->m);
1250 checkstats(Ether *e, Ctlr *c, Stats *s)
1257 i = gbit32(s->linkstat);
1258 if(c->linkstat != i){
1261 dprint("m10g: link up\n");
1263 dprint("m10g: link down\n");
1265 i = gbit32(s->nrdma);
1267 dprint("m10g: rdma timeout %ld\n", i);
1277 for(i = 0; i < 1024*1024; i++){
1278 if(c->stats->valid == 0)
1285 m10ginterrupt(Ureg *, void *v)
1293 if(c->state != Runed || c->stats->valid == 0) /* not ready for us? */
1296 if(c->stats->valid & 1)
1297 wakeup(&c->rxrendez);
1298 if(gbit32(c->stats->txcnt) != c->tx.npkt)
1299 wakeup(&c->txrendez);
1303 c->stats->valid = 0;
1305 checkstats(e, c, c->stats);
1306 c->irqack[1] = pbit32(3);
1310 m10gattach(Ether *e)
1315 dprint("m10gattach\n");
1319 if(c->state != Detached){
1324 c->state = Detached;
1329 c->state = Attached;
1333 snprint(name, sizeof name, "#l%drxproc", e->ctlrno);
1334 kproc(name, m10rx, e);
1335 snprint(name, sizeof name, "#l%dtxproc", e->ctlrno);
1336 kproc(name, txproc, e);
1346 dprint("m10gdetach\n");
1348 vunmap(c->ram, c->pcidev->mem[0].size);
1359 for(; b; b = b->next)
1365 m10gifstat(Ether *e, void *v, long n, ulong off)
1372 p = smalloc(READSTR);
1373 /* no point in locking this because this is done via dma. */
1374 memmove(&s, c->stats, sizeof s);
1376 "txcnt = %lud\n" "linkstat = %lud\n" "dlink = %lud\n"
1377 "derror = %lud\n" "drunt = %lud\n" "doverrun = %lud\n"
1378 "dnosm = %lud\n" "dnobg = %lud\n" "nrdma = %lud\n"
1379 "txstopped = %ud\n" "down = %ud\n" "updated = %ud\n"
1381 "tx pkt = %lud\n" "tx bytes = %lld\n"
1382 "tx cnt = %ud\n" "tx n = %ud\n" "tx i = %ud\n"
1383 "sm cnt = %ud\n" "sm i = %ud\n" "sm n = %ud\n"
1385 "bg cnt = %ud\n" "bg i = %ud\n" "bg n = %ud\n"
1387 "segsz = %lud\n" "coal = %lud\n",
1388 gbit32(s.txcnt), gbit32(s.linkstat), gbit32(s.dlink),
1389 gbit32(s.derror), gbit32(s.drunt), gbit32(s.doverrun),
1390 gbit32(s.dnosm), gbit32(s.dnobg), gbit32(s.nrdma),
1391 s.txstopped, s.down, s.updated, s.valid,
1392 c->tx.npkt, c->tx.nbytes,
1393 c->tx.cnt, c->tx.n, c->tx.i,
1394 c->sm.cnt, c->sm.i, c->sm.pool->n, lstcount(c->sm.pool->head),
1395 c->bg.cnt, c->bg.i, c->bg.pool->n, lstcount(c->bg.pool->head),
1396 c->tx.segsz, gbit32((uchar*)c->coal));
1398 n = readstr(off, v, n, p);
1411 // buf = malloc(n=250);
1415 // snprint(buf, n, "oq\n");
1416 // qsummary(e->oq, buf+3, n-3-1);
1417 // iprint("%s", buf);
1419 // if(e->f) for(i = 0; e->f[i]; i++){
1420 // j = snprint(buf, n, "f%d %d\n", i, e->f[i]->type);
1421 // qsummary(e->f[i]->in, buf+j, n-j-1);
1422 // print("%s", buf);
1438 for(i = 0; i < d->n; i++) {
1439 sp = (Slotparts *)(s + i);
1441 iprint("s[%d] = %d\n", i, sp->len);
1454 static Cmdtab ctab[] = {
1455 CMdebug, "debug", 2,
1457 CMwakeup, "wakeup", 1,
1458 CMtxwakeup, "txwakeup", 1,
1459 // CMqsummary, "q", 1,
1460 CMrxring, "rxring", 1,
1464 m10gctl(Ether *e, void *v, long n)
1470 dprint("m10gctl\n");
1479 t = lookupcmd(c, ctab, nelem(ctab));
1482 debug = (strcmp(c->f[1], "on") == 0);
1486 if(i < 0 || i > 1000)
1488 *((Ctlr*)e->ctlr)->coal = pbit32(i);
1491 wakeup(&((Ctlr*)e->ctlr)->rxrendez); /* you're kidding, right? */
1494 wakeup(&((Ctlr*)e->ctlr)->txrendez); /* you're kidding, right? */
1511 m10gshutdown(Ether *e)
1513 dprint("m10gshutdown\n");
1514 m10gdetach(e->ctlr);
1518 m10gpromiscuous(void *v, int on)
1523 dprint("m10gpromiscuous\n");
1532 static int mcctab[] = { CSleavemc, CSjoinmc };
1533 static char *mcntab[] = { "leave", "join" };
1536 m10gmulticast(void *v, uchar *ea, int on)
1541 dprint("m10gmulticast\n");
1543 if((i = maccmd(e->ctlr, mcctab[on], ea)) != 0)
1544 print("m10g: can't %s %E: %d\n", mcntab[on], ea, i);
1554 for(p = 0; p = pcimatch(p, Vmyricom, 0); ){
1558 case 0x9: /* 8a with msi-x fw */
1561 case 0xc: /* 2-8b2 */
1565 print("etherm10g: unknown myricom did %#ux\n", p->did);
1568 c = malloc(sizeof *c);
1570 print("etherm10g: can't allocate memory\n");
1575 c->id = p->did<<16 | p->vid;
1576 c->boot = pcicap(p, PciCapVND);
1577 // kickthebaby(p, c);
1579 if(setmem(p, c) == -1){
1580 print("m10g: setmem failed\n");
1601 for(c = ctlrs; c != nil; c = c->next)
1604 else if(e->port == 0 || e->port == c->port)
1612 e->irq = c->pcidev->intl;
1613 e->tbdf = c->pcidev->tbdf;
1615 memmove(e->ea, c->ra, Eaddrlen);
1617 e->attach = m10gattach;
1618 e->transmit = m10gtransmit;
1619 e->interrupt = m10ginterrupt;
1620 e->ifstat = m10gifstat;
1622 // e->power = m10gpower;
1623 e->shutdown = m10gshutdown;
1626 e->promiscuous = m10gpromiscuous;
1627 e->multicast = m10gmulticast;
1635 addethercard("m10g", m10gpnp);