]> git.lizzy.rs Git - plan9front.git/blobdiff - sys/src/9/pc/ether79c970.c
kernel: cleanup the software mouse cursor mess
[plan9front.git] / sys / src / 9 / pc / ether79c970.c
index 5e682847d46317a32755afc78e9f969420a62db6..d9e17e0b45688f2442a46d4887f7637ee6e5fec6 100644 (file)
@@ -12,8 +12,7 @@
 #include "io.h"
 #include "../port/error.h"
 #include "../port/netif.h"
-
-#include "etherif.h"
+#include "../port/etherif.h"
 
 enum {
        Lognrdre        = 6,
@@ -83,9 +82,10 @@ struct Dre {                 /* descriptor ring entry */
        ulong   addr;
        ulong   md1;                    /* status|bcnt */
        ulong   md2;                    /* rcc|rpc|mcnt */
-       Block*  bp;
+       ulong   aux;
 };
 
+
 enum {                                 /* md1 */
        Enp             = 0x01000000,   /* end of packet */
        Stp             = 0x02000000,   /* start of packet */
@@ -120,9 +120,11 @@ struct Ctlr {
        int     init;                   /* initialisation in progress */
        Iblock  iblock;
 
+       Block** rb;
        Dre*    rdr;                    /* receive descriptor ring */
        int     rdrx;
 
+       Block** tb;
        Dre*    tdr;                    /* transmit descriptor ring */
        int     tdrh;                   /* host index into tdr */
        int     tdri;                   /* interface index into tdr */
@@ -204,7 +206,7 @@ ifstat(Ether* ether, void* a, long n, ulong offset)
        if(n == 0)
                return 0;
 
-       p = malloc(READSTR);
+       p = smalloc(READSTR);
        len = snprint(p, READSTR, "Rxbuff: %ld\n", ctlr->rxbuff);
        len += snprint(p+len, READSTR-len, "Crc: %ld\n", ctlr->crc);
        len += snprint(p+len, READSTR-len, "Oflo: %ld\n", ctlr->oflo);
@@ -227,7 +229,9 @@ ifstat(Ether* ether, void* a, long n, ulong offset)
 static void
 ringinit(Ctlr* ctlr)
 {
+       Block *bp;
        Dre *dre;
+       int i;
 
        /*
         * Initialise the receive and transmit buffer rings.
@@ -235,19 +239,26 @@ ringinit(Ctlr* ctlr)
         *
         * This routine is protected by ctlr->init.
         */
+       if(ctlr->rb == nil)
+               ctlr->rb = malloc(Nrdre*sizeof(Block*));
        if(ctlr->rdr == 0){
                ctlr->rdr = xspanalloc(Nrdre*sizeof(Dre), 0x10, 0);
-               for(dre = ctlr->rdr; dre < &ctlr->rdr[Nrdre]; dre++){
-                       dre->bp = iallocb(Rbsize);
-                       if(dre->bp == nil)
-                               panic("can't allocate ethernet receive ring\n");
-                       dre->addr = PADDR(dre->bp->rp);
+               for(i=0; i<Nrdre; i++){
+                       bp = iallocb(Rbsize);
+                       if(bp == nil)
+                               panic("can't allocate ethernet receive ring");
+                       ctlr->rb[i] = bp;
+                       dre = &ctlr->rdr[i];
+                       dre->addr = PADDR(bp->rp);
                        dre->md2 = 0;
                        dre->md1 = Own|(-Rbsize & 0xFFFF);
+                       dre->aux = 0;
                }
        }
        ctlr->rdrx = 0;
 
+       if(ctlr->tb == nil)
+               ctlr->tb = malloc(Ntdre*sizeof(Block*));
        if(ctlr->tdr == 0)
                ctlr->tdr = xspanalloc(Ntdre*sizeof(Dre), 0x10, 0);
        memset(ctlr->tdr, 0, Ntdre*sizeof(Dre));
@@ -287,7 +298,7 @@ promiscuous(void* arg, int on)
 
        ctlr->iow(ctlr, Rap, 15);
        x = ctlr->ior(ctlr, Rdp) & ~Prom;
-       if(on)
+       if(on || ether->nmaddr > 0)
                x |= Prom;
        ctlr->iow(ctlr, Rdp, x);
        ctlr->iow(ctlr, Rap, 0);
@@ -303,7 +314,8 @@ promiscuous(void* arg, int on)
 static void
 multicast(void* arg, uchar*, int)
 {
-       promiscuous(arg, 1);
+       Ether *ether = arg;
+       promiscuous(arg, ether->prom);
 }
 
 static void
@@ -312,6 +324,7 @@ txstart(Ether* ether)
        Ctlr *ctlr;
        Block *bp;
        Dre *dre;
+       int i;
 
        ctlr = ether->ctlr;
 
@@ -330,8 +343,11 @@ txstart(Ether* ether)
                 * There's no need to pad to ETHERMINTU
                 * here as ApadXmt is set in CSR4.
                 */
-               dre = &ctlr->tdr[ctlr->tdrh];
-               dre->bp = bp;
+               i = ctlr->tdrh;
+               if(ctlr->tb[i] != nil)
+                       break;
+               dre = &ctlr->tdr[i];
+               ctlr->tb[i] = bp;
                dre->addr = PADDR(bp->rp);
                dre->md2 = 0;
                dre->md1 = Own|Stp|Enp|(-BLEN(bp) & 0xFFFF);
@@ -357,9 +373,9 @@ interrupt(Ureg*, void* arg)
 {
        Ctlr *ctlr;
        Ether *ether;
-       int csr0, len;
+       int csr0, len, i;
        Dre *dre;
-       Block *bp;
+       Block *bp, *bb;
 
        ether = arg;
        ctlr = ether->ctlr;
@@ -388,7 +404,9 @@ intrloop:
         * until a descriptor is encountered still owned by the chip.
         */
        if(csr0 & Rint){
-               dre = &ctlr->rdr[ctlr->rdrx];
+               ilock(ctlr);
+               i = ctlr->rdrx;
+               dre = &ctlr->rdr[i];
                while(!(dre->md1 & Own)){
                        if(dre->md1 & RxErr){
                                if(dre->md1 & RxBuff)
@@ -401,10 +419,13 @@ intrloop:
                                        ctlr->fram++;
                        }
                        else if(bp = iallocb(Rbsize)){
-                               len = (dre->md2 & 0x0FFF)-4;
-                               dre->bp->wp = dre->bp->rp+len;
-                               etheriq(ether, dre->bp, 1);
-                               dre->bp = bp;
+                               bb = ctlr->rb[i];
+                               ctlr->rb[i] = bp;
+                               if(bb != nil){
+                                       len = (dre->md2 & 0x0FFF)-4;
+                                       bb->wp = bb->rp+len;
+                                       etheriq(ether, bb);
+                               }
                                dre->addr = PADDR(bp->rp);
                        }
 
@@ -415,18 +436,20 @@ intrloop:
                        dre->md2 = 0;
                        dre->md1 = Own|(-Rbsize & 0xFFFF);
 
-                       ctlr->rdrx = NEXT(ctlr->rdrx, Nrdre);
-                       dre = &ctlr->rdr[ctlr->rdrx];
+                       i = ctlr->rdrx = NEXT(ctlr->rdrx, Nrdre);
+                       dre = &ctlr->rdr[i];
                }
+               iunlock(ctlr);
        }
 
        /*
         * Transmitter interrupt: wakeup anyone waiting for a free descriptor.
         */
        if(csr0 & Tint){
-               lock(ctlr);
+               ilock(ctlr);
                while(ctlr->ntq){
-                       dre = &ctlr->tdr[ctlr->tdri];
+                       i = ctlr->tdri;
+                       dre = &ctlr->tdr[i];
                        if(dre->md1 & Own)
                                break;
        
@@ -443,14 +466,17 @@ intrloop:
                                        ctlr->txbuff++;
                                ether->oerrs++;
                        }
-       
-                       freeb(dre->bp);
+                       bp = ctlr->tb[i];
+                       if(bp != nil){
+                               ctlr->tb[i] = nil;
+                               freeb(bp);
+                       }
        
                        ctlr->ntq--;
                        ctlr->tdri = NEXT(ctlr->tdri, Ntdre);
                }
                txstart(ether);
-               unlock(ctlr);
+               iunlock(ctlr);
        }
        goto intrloop;
 }
@@ -470,6 +496,11 @@ amd79c970pci(void)
                        continue;
                }
                ctlr = malloc(sizeof(Ctlr));
+               if(ctlr == nil){
+                       print("amd79c970: can't allocate memory\n");
+                       iofree(port);
+                       continue;
+               }
                ctlr->port = p->mem[0].bar & ~0x01;
                ctlr->pcidev = p;
 
@@ -513,9 +544,10 @@ reset(Ether* ether)
        ether->port = ctlr->port;
        ether->irq = ctlr->pcidev->intl;
        ether->tbdf = ctlr->pcidev->tbdf;
-       pcisetbme(ctlr->pcidev);
        ilock(ctlr);
        ctlr->init = 1;
+       pcienable(ctlr->pcidev);
+       pcisetbme(ctlr->pcidev);
 
        io32r(ctlr, Sreset);
        io16r(ctlr, Sreset);
@@ -540,7 +572,10 @@ reset(Ether* ether)
        switch(x&0xFFFFFFF){
        case 0x2420003: /* PCnet/PCI 79C970 */
        case 0x2621003: /* PCnet/PCI II 79C970A */
+               ether->mbps = 10;
+               break;
        case 0x2625003: /* PCnet-FAST III 79C973 */
+               ether->mbps = 100;
                break;
        default:
                print("#l%d: unknown PCnet card version 0x%.7ux\n",
@@ -583,6 +618,15 @@ reset(Ether* ether)
                ether->ea[5] = x>>8;
        }
 
+       /* VMware */
+       x = ether->ea[0]<<16 | ether->ea[1]<<8 | ether->ea[2];
+       switch(x){
+       case 0x0569:
+       case 0x0C29:
+       case 0x5056:
+               ether->mbps = 1000;
+       }
+
        /*
         * Start to fill in the initialisation block
         * (must be DWORD aligned).
@@ -628,7 +672,6 @@ reset(Ether* ether)
         */
        ether->attach = attach;
        ether->transmit = transmit;
-       ether->interrupt = interrupt;
        ether->ifstat = ifstat;
 
        ether->arg = ether;
@@ -636,6 +679,8 @@ reset(Ether* ether)
        ether->multicast = multicast;
 //     ether->shutdown = shutdown;
 
+       intrenable(ether->irq, interrupt, ether, ether->tbdf, ether->name);
+
        return 0;
 }