]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/pc/ether83815.c
merge
[plan9front.git] / sys / src / 9 / pc / ether83815.c
1 /*
2  * National Semiconductor DP83815
3  *
4  * Supports only internal PHY and has been tested on:
5  *      Netgear FA311TX (using Netgear DS108 10/100 hub)
6  *      SiS 900 within SiS 630
7  * To do:
8  *      check Ethernet address;
9  *      test autonegotiation on 10 Mbit, and 100 Mbit full duplex;
10  *      external PHY via MII (should be common code for MII);
11  *      thresholds;
12  *      ring sizing;
13  *      physical link changes/disconnect;
14  *      push initialisation back to attach.
15  *
16  * C H Forsyth, forsyth@vitanuova.com, 18th June 2001.
17  */
18
19 #include "u.h"
20 #include "../port/lib.h"
21 #include "mem.h"
22 #include "dat.h"
23 #include "fns.h"
24 #include "io.h"
25 #include "../port/error.h"
26 #include "../port/netif.h"
27
28 #include "etherif.h"
29
30 #define DEBUG           0
31 #define debug           if(DEBUG)print
32
33 enum {
34         Nrde            = 64,
35         Ntde            = 64,
36 };
37
38 #define Rbsz            ROUNDUP(sizeof(Etherpkt)+4, 4)
39
40 typedef struct Des {
41         ulong   next;
42         int     cmdsts;
43         ulong   addr;
44         Block*  bp;
45 } Des;
46
47 enum {  /* cmdsts */
48         Own     = 1<<31,        /* set by data producer to hand to consumer */
49         More    = 1<<30,        /* more of packet in next descriptor */
50         Intr    = 1<<29,        /* interrupt when device is done with it */
51         Supcrc  = 1<<28,        /* suppress crc on transmit */
52         Inccrc  = 1<<28,        /* crc included on receive (always) */
53         Ok      = 1<<27,        /* packet ok */
54         Size    = 0xFFF,        /* packet size in bytes */
55
56         /* transmit */
57         Txa     = 1<<26,        /* transmission aborted */
58         Tfu     = 1<<25,        /* transmit fifo underrun */
59         Crs     = 1<<24,        /* carrier sense lost */
60         Td      = 1<<23,        /* transmission deferred */
61         Ed      = 1<<22,        /* excessive deferral */
62         Owc     = 1<<21,        /* out of window collision */
63         Ec      = 1<<20,        /* excessive collisions */
64         /* 19-16 collision count */
65
66         /* receive */
67         Rxa     = 1<<26,        /* receive aborted (same as Rxo) */
68         Rxo     = 1<<25,        /* receive overrun */
69         Dest    = 3<<23,        /* destination class */
70           Drej= 0<<23,          /* packet was rejected */
71           Duni= 1<<23,          /* unicast */
72           Dmulti=       2<<23,          /* multicast */
73           Dbroad=       3<<23,          /* broadcast */
74         Long = 1<<22,           /* too long packet received */
75         Runt =  1<<21,          /* packet less than 64 bytes */
76         Ise =   1<<20,          /* invalid symbol */
77         Crce =  1<<19,          /* invalid crc */
78         Fae =   1<<18,          /* frame alignment error */
79         Lbp =   1<<17,          /* loopback packet */
80         Col =   1<<16,          /* collision during receive */
81 };
82
83 enum {                          /* PCI vendor & device IDs */
84         Nat83815        = (0x0020<<16)|0x100B,
85         SiS =   0x1039,
86         SiS900 =        (0x0900<<16)|SiS,
87         SiS7016 =       (0x7016<<16)|SiS,
88
89         SiS630bridge    = 0x0008,
90
91         /* SiS 900 PCI revision codes */
92         SiSrev630s =    0x81,
93         SiSrev630e =    0x82,
94         SiSrev630ea1 =  0x83,
95         SiSrev635 =     0x90,
96
97         SiSeenodeaddr = 8,              /* short addr of SiS eeprom mac addr */
98         SiS630eenodeaddr =      9,      /* likewise for the 630 */
99         Nseenodeaddr =  6,              /* " for NS eeprom */
100         Nat83815avng =  0x403,
101         Nat83816avng =  0x505,          /* 83816 acts like submodel of 83815 */
102                                         /* using reg. 0x58 to disambiguate. */
103 };
104
105 typedef struct Ctlr Ctlr;
106 typedef struct Ctlr {
107         int     port;
108         Pcidev* pcidev;
109         Ctlr*   next;
110         int     active;
111         int     id;                     /* (pcidev->did<<16)|pcidev->vid */
112
113         ushort  srom[0xB+1];
114         uchar   sromea[Eaddrlen];       /* MAC address */
115
116         uchar   fd;                     /* option or auto negotiation */
117
118         int     mbps;
119
120         Lock    lock;
121
122         Des*    rdr;                    /* receive descriptor ring */
123         int     nrdr;                   /* size of rdr */
124         int     rdrx;                   /* index into rdr */
125
126         Lock    tlock;
127         Des*    tdr;                    /* transmit descriptor ring */
128         int     ntdr;                   /* size of tdr */
129         int     tdrh;                   /* host index into tdr */
130         int     tdri;                   /* interface index into tdr */
131         int     ntq;                    /* descriptors active */
132         int     ntqmax;
133
134         ulong   rxa;                    /* receive statistics */
135         ulong   rxo;
136         ulong   rlong;
137         ulong   runt;
138         ulong   ise;
139         ulong   crce;
140         ulong   fae;
141         ulong   lbp;
142         ulong   col;
143         ulong   rxsovr;
144         ulong   rxorn;
145
146         ulong   txa;                    /* transmit statistics */
147         ulong   tfu;
148         ulong   crs;
149         ulong   td;
150         ulong   ed;
151         ulong   owc;
152         ulong   ec;
153         ulong   txurn;
154
155         ulong   dperr;                  /* system errors */
156         ulong   rmabt;
157         ulong   rtabt;
158         ulong   sserr;
159         ulong   rxsover;
160
161         ulong   version;                /* silicon version; register 0x58h */
162 } Ctlr;
163
164 static Ctlr* ctlrhead;
165 static Ctlr* ctlrtail;
166
167 enum {
168         /* registers (could memory map) */
169         Rcr=    0x00,           /* command register */
170           Rld=          1<<10,  /* reload */
171           Rst=          1<<8,
172           Rxr=          1<<5,   /* receiver reset */
173           Txr=          1<<4,   /* transmitter reset */
174           Rxd=          1<<3,   /* receiver disable */
175           Rxe=          1<<2,   /* receiver enable */
176           Txd=          1<<1,   /* transmitter disable */
177           Txe=          1<<0,   /* transmitter enable */
178         Rcfg=   0x04,           /* configuration */
179           Lnksts=       1<<31,  /* link good */
180           Speed100=     1<<30,  /* 100 Mb/s link */
181           Fdup=         1<<29,  /* full duplex */
182           Pol=          1<<28,  /* polarity reversal (10baseT) */
183           Aneg_dn=      1<<27,  /* autonegotiation done */
184           Pint_acen=    1<<17,  /* PHY interrupt auto clear enable */
185           Pause_adv=    1<<16,  /* advertise pause during auto neg */
186           Paneg_ena=    1<<13,  /* auto negotiation enable */
187           Paneg_all=    7<<13,  /* auto negotiation enable 10/100 half & full */
188           Ext_phy=      1<<12,  /* enable MII for external PHY */
189           Phy_rst=      1<<10,  /* reset internal PHY */
190           Phy_dis=      1<<9,   /* disable internal PHY (eg, low power) */
191           Req_alg=      1<<7,   /* PCI bus request: set means less aggressive */
192           Sb=           1<<6,   /* single slot back-off not random */
193           Pow=          1<<5,   /* out of window timer selection */
194           Exd=          1<<4,   /* disable excessive deferral timer */
195           Pesel=        1<<3,   /* parity error algorithm selection */
196           Brom_dis=     1<<2,   /* disable boot rom interface */
197           Bem=          1<<0,   /* big-endian mode */
198         Rmear=  0x08,           /* eeprom access */
199           Mdc=          1<<6,   /* MII mangement check */
200           Mddir=        1<<5,   /* MII management direction */
201           Mdio=         1<<4,   /* MII mangement data */
202           Eesel=        1<<3,   /* EEPROM chip select */
203           Eeclk=        1<<2,   /* EEPROM clock */
204           Eedo=         1<<1,   /* EEPROM data out (from chip) */
205           Eedi=         1<<0,   /* EEPROM data in (to chip) */
206         Rptscr= 0x0C,           /* pci test control */
207         Risr=   0x10,           /* interrupt status */
208           Txrcmp=       1<<25,  /* transmit reset complete */
209           Rxrcmp=       1<<24,  /* receiver reset complete */
210           Dperr=        1<<23,  /* detected parity error */
211           Sserr=        1<<22,  /* signalled system error */
212           Rmabt=        1<<21,  /* received master abort */
213           Rtabt=        1<<20,  /* received target abort */
214           Rxsovr=       1<<16,  /* RX status FIFO overrun */
215           Hiberr=       1<<15,  /* high bits error set (OR of 25-16) */
216           Phy=          1<<14,  /* PHY interrupt */
217           Pme=          1<<13,  /* power management event (wake online) */
218           Swi=          1<<12,  /* software interrupt */
219           Mib=          1<<11,  /* MIB service */
220           Txurn=        1<<10,  /* TX underrun */
221           Txidle=       1<<9,   /* TX idle */
222           Txerr=        1<<8,   /* TX packet error */
223           Txdesc=       1<<7,   /* TX descriptor (with Intr bit done) */
224           Txok=         1<<6,   /* TX ok */
225           Rxorn=        1<<5,   /* RX overrun */
226           Rxidle=       1<<4,   /* RX idle */
227           Rxearly=      1<<3,   /* RX early threshold */
228           Rxerr=        1<<2,   /* RX packet error */
229           Rxdesc=       1<<1,   /* RX descriptor (with Intr bit done) */
230           Rxok=         1<<0,   /* RX ok */
231         Rimr=   0x14,           /* interrupt mask */
232         Rier=   0x18,           /* interrupt enable */
233           Ie=           1<<0,   /* interrupt enable */
234         Rtxdp=  0x20,           /* transmit descriptor pointer */
235         Rtxcfg= 0x24,           /* transmit configuration */
236           Csi=          1<<31,  /* carrier sense ignore (needed for full duplex) */
237           Hbi=          1<<30,  /* heartbeat ignore (needed for full duplex) */
238           Atp=          1<<28,  /* automatic padding of runt packets */
239           Mxdma=        7<<20,  /* maximum dma transfer field */
240           Mxdma32=      4<<20,  /* 4x32-bit words (32 bytes) */
241           Mxdma64=      5<<20,  /* 8x32-bit words (64 bytes) */
242           Flth=         0x3F<<8,/* Tx fill threshold, units of 32 bytes (must be > Mxdma) */
243           Drth=         0x3F<<0,/* Tx drain threshold (units of 32 bytes) */
244           Flth128=      4<<8,   /* fill at 128 bytes */
245           Drth512=      16<<0,  /* drain at 512 bytes */
246         Rrxdp=  0x30,           /* receive descriptor pointer */
247         Rrxcfg= 0x34,           /* receive configuration */
248           Atx=          1<<28,  /* accept transmit packets (needed for full duplex) */
249           Rdrth=        0x1F<<1,/* Rx drain threshold (units of 32 bytes) */
250           Rdrth64=      2<<1,   /* drain at 64 bytes */
251         Rccsr=  0x3C,           /* CLKRUN control/status */
252           Pmests=       1<<15,  /* PME status */
253         Rwcsr=  0x40,           /* wake on lan control/status */
254         Rpcr=   0x44,           /* pause control/status */
255         Rrfcr=  0x48,           /* receive filter/match control */
256           Rfen=         1<<31,  /* receive filter enable */
257           Aab=          1<<30,  /* accept all broadcast */
258           Aam=          1<<29,  /* accept all multicast */
259           Aau=          1<<28,  /* accept all unicast */
260           Apm=          1<<27,  /* accept on perfect match */
261           Apat=         0xF<<23,/* accept on pattern match */
262           Aarp=         1<<22,  /* accept ARP */
263           Mhen=         1<<21,  /* multicast hash enable */
264           Uhen=         1<<20,  /* unicast hash enable */
265           Ulm=          1<<19,  /* U/L bit mask */
266                                 /* bits 0-9 are rfaddr */
267         Rrfdr=  0x4C,           /* receive filter/match data */
268         Rbrar=  0x50,           /* boot rom address */
269         Rbrdr=  0x54,           /* boot rom data */
270         Rsrr=   0x58,           /* silicon revision */
271         Rmibc=  0x5C,           /* MIB control */
272                                 /* 60-78 MIB data */
273
274         /* PHY registers */
275         Rbmcr=  0x80,           /* basic mode configuration */
276           Reset=        1<<15,
277           Sel100=       1<<13,  /* select 100Mb/sec if no auto neg */
278           Anena=        1<<12,  /* auto negotiation enable */
279           Anrestart=    1<<9,   /* restart auto negotiation */
280           Selfdx=       1<<8,   /* select full duplex if no auto neg */
281         Rbmsr=  0x84,           /* basic mode status */
282           Ancomp=       1<<5,   /* autonegotiation complete */
283         Rphyidr1= 0x88,
284         Rphyidr2= 0x8C,
285         Ranar=  0x90,           /* autonegotiation advertisement */
286         Ranlpar= 0x94,          /* autonegotiation link partner ability */
287         Raner=  0x98,           /* autonegotiation expansion */
288         Rannptr= 0x9C,          /* autonegotiation next page TX */
289         Rphysts= 0xC0,          /* PHY status */
290         Rmicr=  0xC4,           /* MII control */
291           Inten=        1<<1,   /* PHY interrupt enable */
292         Rmisr=  0xC8,           /* MII status */
293         Rfcscr= 0xD0,           /* false carrier sense counter */
294         Rrecr=  0xD4,           /* receive error counter */
295         Rpcsr=  0xD8,           /* 100Mb config/status */
296         Rphycr= 0xE4,           /* PHY control */
297         Rtbscr= 0xE8,           /* 10BaseT status/control */
298 };
299
300 /*
301  * eeprom addresses
302  *      7 to 9 (16 bit words): mac address, shifted and reversed
303  */
304
305 #define csr32r(c, r)    (inl((c)->port+(r)))
306 #define csr32w(c, r, l) (outl((c)->port+(r), (ulong)(l)))
307 #define csr16r(c, r)    (ins((c)->port+(r)))
308 #define csr16w(c, r, l) (outs((c)->port+(r), (ulong)(l)))
309
310 static void
311 dumpcregs(Ctlr *ctlr)
312 {
313         int i;
314
315         for(i=0; i<=0x5C; i+=4)
316                 print("%2.2ux %8.8lux\n", i, csr32r(ctlr, i));
317 }
318
319 static void
320 promiscuous(void* arg, int on)
321 {
322         Ctlr *ctlr;
323         ulong w;
324
325         ctlr = ((Ether*)arg)->ctlr;
326         ilock(&ctlr->lock);
327         w = csr32r(ctlr, Rrfcr);
328         if(on != ((w&Aau)!=0)){
329                 csr32w(ctlr, Rrfcr, w & ~Rfen);
330                 csr32w(ctlr, Rrfcr, Rfen | (w ^ Aau));
331         }
332         iunlock(&ctlr->lock);
333 }
334
335 static void
336 attach(Ether* ether)
337 {
338         Ctlr *ctlr;
339
340         ctlr = ether->ctlr;
341         ilock(&ctlr->lock);
342         if(0)
343                 dumpcregs(ctlr);
344         csr32w(ctlr, Rcr, Rxe);
345         iunlock(&ctlr->lock);
346 }
347
348 static long
349 ifstat(Ether* ether, void* a, long n, ulong offset)
350 {
351         Ctlr *ctlr;
352         char *buf, *p;
353         int i, l, len;
354
355         ctlr = ether->ctlr;
356
357         ether->crcs = ctlr->crce;
358         ether->frames = ctlr->runt+ctlr->ise+ctlr->rlong+ctlr->fae;
359         ether->buffs = ctlr->rxorn+ctlr->tfu;
360         ether->overflows = ctlr->rxsovr;
361
362         if(n == 0)
363                 return 0;
364
365         p = smalloc(READSTR);
366         l = snprint(p, READSTR, "Rxa: %lud\n", ctlr->rxa);
367         l += snprint(p+l, READSTR-l, "Rxo: %lud\n", ctlr->rxo);
368         l += snprint(p+l, READSTR-l, "Rlong: %lud\n", ctlr->rlong);
369         l += snprint(p+l, READSTR-l, "Runt: %lud\n", ctlr->runt);
370         l += snprint(p+l, READSTR-l, "Ise: %lud\n", ctlr->ise);
371         l += snprint(p+l, READSTR-l, "Fae: %lud\n", ctlr->fae);
372         l += snprint(p+l, READSTR-l, "Lbp: %lud\n", ctlr->lbp);
373         l += snprint(p+l, READSTR-l, "Tfu: %lud\n", ctlr->tfu);
374         l += snprint(p+l, READSTR-l, "Txa: %lud\n", ctlr->txa);
375         l += snprint(p+l, READSTR-l, "CRC Error: %lud\n", ctlr->crce);
376         l += snprint(p+l, READSTR-l, "Collision Seen: %lud\n", ctlr->col);
377         l += snprint(p+l, READSTR-l, "Frame Too Long: %lud\n", ctlr->rlong);
378         l += snprint(p+l, READSTR-l, "Runt Frame: %lud\n", ctlr->runt);
379         l += snprint(p+l, READSTR-l, "Rx Underflow Error: %lud\n", ctlr->rxorn);
380         l += snprint(p+l, READSTR-l, "Tx Underrun: %lud\n", ctlr->txurn);
381         l += snprint(p+l, READSTR-l, "Excessive Collisions: %lud\n", ctlr->ec);
382         l += snprint(p+l, READSTR-l, "Late Collision: %lud\n", ctlr->owc);
383         l += snprint(p+l, READSTR-l, "Loss of Carrier: %lud\n", ctlr->crs);
384         l += snprint(p+l, READSTR-l, "Parity: %lud\n", ctlr->dperr);
385         l += snprint(p+l, READSTR-l, "Aborts: %lud\n", ctlr->rmabt+ctlr->rtabt);
386         l += snprint(p+l, READSTR-l, "RX Status overrun: %lud\n", ctlr->rxsover);
387         snprint(p+l, READSTR-l, "ntqmax: %d\n", ctlr->ntqmax);
388         ctlr->ntqmax = 0;
389         buf = a;
390         len = readstr(offset, buf, n, p);
391         if(offset > l)
392                 offset -= l;
393         else
394                 offset = 0;
395         buf += len;
396         n -= len;
397
398         l = snprint(p, READSTR, "srom:");
399         for(i = 0; i < nelem(ctlr->srom); i++){
400                 if(i && ((i & 0x0F) == 0))
401                         l += snprint(p+l, READSTR-l, "\n     ");
402                 l += snprint(p+l, READSTR-l, " %4.4uX", ctlr->srom[i]);
403         }
404
405         snprint(p+l, READSTR-l, "\n");
406         len += readstr(offset, buf, n, p);
407         free(p);
408
409         return len;
410 }
411
412 static void
413 txstart(Ether* ether)
414 {
415         Ctlr *ctlr;
416         Block *bp;
417         Des *des;
418         int started;
419
420         ctlr = ether->ctlr;
421         started = 0;
422         while(ctlr->ntq < ctlr->ntdr-1){
423                 bp = qget(ether->oq);
424                 if(bp == nil)
425                         break;
426                 des = &ctlr->tdr[ctlr->tdrh];
427                 des->bp = bp;
428                 des->addr = PADDR(bp->rp);
429                 ctlr->ntq++;
430                 coherence();
431                 des->cmdsts = Own | BLEN(bp);
432                 ctlr->tdrh = NEXT(ctlr->tdrh, ctlr->ntdr);
433                 started = 1;
434         }
435         if(started){
436                 coherence();
437                 csr32w(ctlr, Rcr, Txe); /* prompt */
438         }
439
440         if(ctlr->ntq > ctlr->ntqmax)
441                 ctlr->ntqmax = ctlr->ntq;
442 }
443
444 static void
445 transmit(Ether* ether)
446 {
447         Ctlr *ctlr;
448
449         ctlr = ether->ctlr;
450         ilock(&ctlr->tlock);
451         txstart(ether);
452         iunlock(&ctlr->tlock);
453 }
454
455 static void
456 txrxcfg(Ctlr *ctlr, int txdrth)
457 {
458         ulong rx, tx;
459
460         rx = csr32r(ctlr, Rrxcfg);
461         tx = csr32r(ctlr, Rtxcfg);
462         if(ctlr->fd){
463                 rx |= Atx;
464                 tx |= Csi | Hbi;
465         }else{
466                 rx &= ~Atx;
467                 tx &= ~(Csi | Hbi);
468         }
469         tx &= ~(Mxdma|Drth|Flth);
470         tx |= Mxdma64 | Flth128 | txdrth;
471         csr32w(ctlr, Rtxcfg, tx);
472         rx &= ~(Mxdma|Rdrth);
473         rx |= Mxdma64 | Rdrth64;
474         csr32w(ctlr, Rrxcfg, rx);
475 }
476
477 static void
478 interrupt(Ureg*, void* arg)
479 {
480         int len, status, cmdsts, n;
481         Ctlr *ctlr;
482         Ether *ether;
483         Des *des;
484         Block *bp;
485
486         ether = arg;
487         ctlr = ether->ctlr;
488
489         while((status = csr32r(ctlr, Risr)) != 0){
490
491                 status &= ~(Pme|Mib);
492
493                 if(status & Hiberr){
494                         if(status & Rxsovr)
495                                 ctlr->rxsover++;
496                         if(status & Sserr)
497                                 ctlr->sserr++;
498                         if(status & Dperr)
499                                 ctlr->dperr++;
500                         if(status & Rmabt)
501                                 ctlr->rmabt++;
502                         if(status & Rtabt)
503                                 ctlr->rtabt++;
504                         status &= ~(Hiberr|Txrcmp|Rxrcmp|Rxsovr|Dperr|Sserr|Rmabt|Rtabt);
505                 }
506
507                 /* update link state */
508                 if(status&Phy){
509                         status &= ~Phy;
510                         csr32r(ctlr, Rcfg);
511                         n = csr32r(ctlr, Rcfg);
512 //                      iprint("83815 phy %x %x\n", n, n&Lnksts);
513                         ether->link = (n&Lnksts) != 0;
514                 }
515
516                 /*
517                  * Received packets.
518                  */
519                 if(status & (Rxdesc|Rxok|Rxerr|Rxearly|Rxorn)){
520                         des = &ctlr->rdr[ctlr->rdrx];
521                         while((cmdsts = des->cmdsts) & Own){
522                                 if((cmdsts&Ok) == 0){
523                                         if(cmdsts & Rxa)
524                                                 ctlr->rxa++;
525                                         if(cmdsts & Rxo)
526                                                 ctlr->rxo++;
527                                         if(cmdsts & Long)
528                                                 ctlr->rlong++;
529                                         if(cmdsts & Runt)
530                                                 ctlr->runt++;
531                                         if(cmdsts & Ise)
532                                                 ctlr->ise++;
533                                         if(cmdsts & Crce)
534                                                 ctlr->crce++;
535                                         if(cmdsts & Fae)
536                                                 ctlr->fae++;
537                                         if(cmdsts & Lbp)
538                                                 ctlr->lbp++;
539                                         if(cmdsts & Col)
540                                                 ctlr->col++;
541                                 }
542                                 else if(bp = iallocb(Rbsz)){
543                                         len = (cmdsts&Size)-4;
544                                         if(len <= 0){
545                                                 debug("ns83815: packet len %d <=0\n", len);
546                                                 freeb(des->bp);
547                                         }else{
548                                                 des->bp->wp = des->bp->rp+len;
549                                                 etheriq(ether, des->bp, 1);
550                                         }
551                                         des->bp = bp;
552                                         des->addr = PADDR(bp->rp);
553                                         coherence();
554                                 }else{
555                                         debug("ns83815: interrupt: iallocb for input buffer failed\n");
556                                         des->bp->next = 0;
557                                 }
558
559                                 des->cmdsts = Rbsz;
560                                 coherence();
561
562                                 ctlr->rdrx = NEXT(ctlr->rdrx, ctlr->nrdr);
563                                 des = &ctlr->rdr[ctlr->rdrx];
564                         }
565                         status &= ~(Rxdesc|Rxok|Rxerr|Rxearly|Rxorn);
566                 }
567
568                 /*
569                  * Check the transmit side:
570                  *      check for Transmit Underflow and Adjust
571                  *      the threshold upwards;
572                  *      free any transmitted buffers and try to
573                  *      top-up the ring.
574                  */
575                 if(status & Txurn){
576                         ctlr->txurn++;
577                         ilock(&ctlr->lock);
578                         /* change threshold */
579                         iunlock(&ctlr->lock);
580                         status &= ~(Txurn);
581                 }
582
583                 ilock(&ctlr->tlock);
584                 while(ctlr->ntq){
585                         des = &ctlr->tdr[ctlr->tdri];
586                         cmdsts = des->cmdsts;
587                         if(cmdsts & Own)
588                                 break;
589
590                         if((cmdsts & Ok) == 0){
591                                 if(cmdsts & Txa)
592                                         ctlr->txa++;
593                                 if(cmdsts & Tfu)
594                                         ctlr->tfu++;
595                                 if(cmdsts & Td)
596                                         ctlr->td++;
597                                 if(cmdsts & Ed)
598                                         ctlr->ed++;
599                                 if(cmdsts & Owc)
600                                         ctlr->owc++;
601                                 if(cmdsts & Ec)
602                                         ctlr->ec++;
603                                 ether->oerrs++;
604                         }
605
606                         freeb(des->bp);
607                         des->bp = nil;
608                         des->cmdsts = 0;
609
610                         ctlr->ntq--;
611                         ctlr->tdri = NEXT(ctlr->tdri, ctlr->ntdr);
612                 }
613                 txstart(ether);
614                 iunlock(&ctlr->tlock);
615
616                 status &= ~(Txurn|Txidle|Txerr|Txdesc|Txok);
617
618                 /*
619                  * Anything left not catered for?
620                  */
621                 if(status)
622                         print("#l%d: status %8.8uX\n", ether->ctlrno, status);
623         }
624 }
625
626 static void
627 ctlrinit(Ether* ether)
628 {
629         Ctlr *ctlr;
630         Des *des, *last;
631
632         ctlr = ether->ctlr;
633
634         /*
635          * Allocate suitable aligned descriptors
636          * for the transmit and receive rings;
637          * initialise the receive ring;
638          * initialise the transmit ring;
639          * unmask interrupts and start the transmit side.
640          */
641         des = xspanalloc((ctlr->nrdr+ctlr->ntdr)*sizeof(Des), 32, 0);
642         ctlr->tdr = des;
643         ctlr->rdr = des+ctlr->ntdr;
644
645         last = nil;
646         for(des = ctlr->rdr; des < &ctlr->rdr[ctlr->nrdr]; des++){
647                 des->bp = iallocb(Rbsz);
648                 if(des->bp == nil)
649                         panic("ether83815: can't allocate receive buffer");
650                 des->cmdsts = Rbsz;
651                 des->addr = PADDR(des->bp->rp);
652                 if(last != nil)
653                         last->next = PADDR(des);
654                 last = des;
655         }
656         ctlr->rdr[ctlr->nrdr-1].next = PADDR(ctlr->rdr);
657         ctlr->rdrx = 0;
658         csr32w(ctlr, Rrxdp, PADDR(ctlr->rdr));
659
660         last = nil;
661         for(des = ctlr->tdr; des < &ctlr->tdr[ctlr->ntdr]; des++){
662                 des->cmdsts = 0;
663                 des->bp = nil;
664                 des->addr = ~0;
665                 if(last != nil)
666                         last->next = PADDR(des);
667                 last = des;
668         }
669         ctlr->tdr[ctlr->ntdr-1].next = PADDR(ctlr->tdr);
670         ctlr->tdrh = 0;
671         ctlr->tdri = 0;
672         csr32w(ctlr, Rtxdp, PADDR(ctlr->tdr));
673
674         txrxcfg(ctlr, Drth512);
675
676         csr32w(ctlr, Rimr, Dperr|Sserr|Rmabt|Rtabt|Rxsovr|Hiberr|Txurn|Txerr|
677                 Txdesc|Txok|Rxorn|Rxerr|Rxdesc|Rxok);   /* Phy|Pme|Mib */
678         csr32w(ctlr, Rmicr, Inten);     /* enable phy interrupts */
679         csr32r(ctlr, Risr);             /* clear status */
680         csr32w(ctlr, Rier, Ie);
681 }
682
683 static void
684 eeclk(Ctlr *ctlr, int clk)
685 {
686         csr32w(ctlr, Rmear, Eesel | clk);
687         microdelay(2);
688 }
689
690 static void
691 eeidle(Ctlr *ctlr)
692 {
693         int i;
694
695         eeclk(ctlr, 0);
696         eeclk(ctlr, Eeclk);
697         for(i=0; i<25; i++){
698                 eeclk(ctlr, 0);
699                 eeclk(ctlr, Eeclk);
700         }
701         eeclk(ctlr, 0);
702         csr32w(ctlr, Rmear, 0);
703         microdelay(2);
704 }
705
706 static ushort
707 eegetw(Ctlr *ctlr, int a)
708 {
709         int d, i, w;
710
711         eeidle(ctlr);
712         eeclk(ctlr, 0);
713         eeclk(ctlr, Eeclk);
714         d = 0x180 | a;
715         for(i=0x400; i; i>>=1){
716                 if(d & i)
717                         csr32w(ctlr, Rmear, Eesel|Eedi);
718                 else
719                         csr32w(ctlr, Rmear, Eesel);
720                 eeclk(ctlr, Eeclk);
721                 eeclk(ctlr, 0);
722                 microdelay(2);
723         }
724         w = 0;
725         for(i=0x8000; i; i >>= 1){
726                 eeclk(ctlr, Eeclk);
727                 if(csr32r(ctlr, Rmear) & Eedo)
728                         w |= i;
729                 microdelay(2);
730                 eeclk(ctlr, 0);
731         }
732         eeidle(ctlr);
733         return w;
734 }
735
736 static int
737 resetctlr(Ctlr *ctlr)
738 {
739         int i;
740
741         /*
742          * Soft-reset the controller
743          */
744         csr32w(ctlr, Rcr, Rst);
745         for(i=0;; i++){
746                 if(i > 100){
747                         print("ns83815: soft reset did not complete\n");
748                         return -1;
749                 }
750                 microdelay(250);
751                 if((csr32r(ctlr, Rcr) & Rst) == 0)
752                         break;
753                 delay(1);
754         }
755         return 0;
756 }
757
758 static void
759 shutdown(Ether* ether)
760 {
761         Ctlr *ctlr = ether->ctlr;
762
763 print("ether83815 shutting down\n");
764         csr32w(ctlr, Rcr, Rxd|Txd);     /* disable transceiver */
765         resetctlr(ctlr);
766 }
767
768 static int
769 softreset(Ctlr* ctlr, int resetphys)
770 {
771         int i, w;
772
773         /*
774          * Soft-reset the controller
775          */
776         resetctlr(ctlr);
777         if(ctlr->id != Nat83815)
778                 return 0;
779         csr32w(ctlr, Rccsr, Pmests);
780         csr32w(ctlr, Rccsr, 0);
781         csr32w(ctlr, Rcfg, csr32r(ctlr, Rcfg) | Pint_acen);
782         ctlr->version = csr32r(ctlr, Rsrr);
783         if(resetphys){
784                 /*
785                  * Soft-reset the PHY
786                  */
787                 csr32w(ctlr, Rbmcr, Reset);
788                 for(i=0;; i++){
789                         if(i > 100){
790                                 print("ns83815: PHY soft reset time out\n");
791                                 return -1;
792                         }
793                         if((csr32r(ctlr, Rbmcr) & Reset) == 0)
794                                 break;
795                         delay(1);
796                 }
797         }
798
799         /*
800          * Initialisation values, in sequence (see 4.4 Recommended Registers Configuration)
801          */
802         csr16w(ctlr, 0xCC, 0x0001);     /* PGSEL */
803         csr16w(ctlr, 0xE4, 0x189C);     /* PMCCSR */
804         csr16w(ctlr, 0xFC, 0x0000);     /* TSTDAT */
805         csr16w(ctlr, 0xF4, 0x5040);     /* DSPCFG */
806         csr16w(ctlr, 0xF8, 0x008C);     /* SDCFG */
807
808         /*
809          * Auto negotiate
810          */
811         csr16r(ctlr, Rbmsr);            /* clear latched bits */
812         debug("anar: %4.4ux\n", csr16r(ctlr, Ranar));
813         csr16w(ctlr, Rbmcr, Anena);
814         if(csr16r(ctlr, Ranar) == 0 || (csr32r(ctlr, Rcfg) & Aneg_dn) == 0){
815                 csr16w(ctlr, Rbmcr, Anena|Anrestart);
816                 for(i=0;; i++){
817                         if(i > 3000){
818                                 print("ns83815: auto neg timed out\n");
819                                 return -1;
820                         }
821                         if((w = csr16r(ctlr, Rbmsr)) & Ancomp)
822                                 break;
823                         delay(1);
824                 }
825                 debug("%d ms\n", i);
826                 w &= 0xFFFF;
827                 debug("bmsr: %4.4ux\n", w);
828                 USED(w);
829         }
830         debug("anar: %4.4ux\n", csr16r(ctlr, Ranar));
831         debug("anlpar: %4.4ux\n", csr16r(ctlr, Ranlpar));
832         debug("aner: %4.4ux\n", csr16r(ctlr, Raner));
833         debug("physts: %4.4ux\n", csr16r(ctlr, Rphysts));
834         debug("tbscr: %4.4ux\n", csr16r(ctlr, Rtbscr));
835         return 0;
836 }
837
838 static int
839 media(Ether* ether)
840 {
841         Ctlr* ctlr;
842         ulong cfg;
843
844         ctlr = ether->ctlr;
845         cfg = csr32r(ctlr, Rcfg);
846         ctlr->fd = (cfg & Fdup) != 0;
847         ether->link = (cfg&Lnksts) != 0;
848         return (cfg&(Lnksts|Speed100)) == Lnksts? 10: 100;
849 }
850
851 static char* mediatable[9] = {
852         "10BASE-T",                             /* TP */
853         "10BASE-2",                             /* BNC */
854         "10BASE-5",                             /* AUI */
855         "100BASE-TX",
856         "10BASE-TFD",
857         "100BASE-TXFD",
858         "100BASE-T4",
859         "100BASE-FX",
860         "100BASE-FXFD",
861 };
862
863 static int
864 is630(ulong id, Pcidev *p)
865 {
866         if(id == SiS900)
867                 switch (p->rid) {
868                 case SiSrev630s:
869                 case SiSrev630e:
870                 case SiSrev630ea1:
871                         return 1;
872                 }
873         return 0;
874 }
875
876 enum {
877         MagicReg = 0x48,
878         MagicRegSz = 1,
879         Magicrden = 0x40,       /* read enable, apparently */
880         Paddr=          0x70,   /* address port */
881         Pdata=          0x71,   /* data port */
882 };
883
884 /* rcmos() originally from LANL's SiS 900 driver's rcmos() */
885 static int
886 sisrdcmos(Ctlr *ctlr)
887 {
888         int i;
889         unsigned reg;
890         ulong port;
891         Pcidev *p;
892
893         debug("ns83815: SiS 630 rev. %ux reading mac address from cmos\n", ctlr->pcidev->rid);
894         p = pcimatch(nil, SiS, SiS630bridge);
895         if(p == nil) {
896                 print("ns83815: no SiS 630 rev. %ux bridge for mac addr\n",
897                         ctlr->pcidev->rid);
898                 return 0;
899         }
900         port = p->mem[0].bar & ~0x01;
901         debug("ns83815: SiS 630 rev. %ux reading mac addr from cmos via bridge at port 0x%lux\n", ctlr->pcidev->rid, port);
902
903         reg = pcicfgr8(p, MagicReg);
904         pcicfgw8(p, MagicReg, reg|Magicrden);
905
906         for (i = 0; i < Eaddrlen; i++) {
907                 outb(port+Paddr, SiS630eenodeaddr + i);
908                 ctlr->sromea[i] = inb(port+Pdata);
909         }
910
911         pcicfgw8(p, MagicReg, reg & ~Magicrden);
912         return 1;
913 }
914
915 /*
916  * If this is a SiS 630E chipset with an embedded SiS 900 controller,
917  * we have to read the MAC address from the APC CMOS RAM. - sez freebsd.
918  * However, CMOS *is* NVRAM normally.  See devrtc.c:440, memory.c:88.
919  */
920 static void
921 sissrom(Ctlr *ctlr)
922 {
923         union {
924                 uchar   eaddr[Eaddrlen];
925                 ushort  alignment;
926         } ee;
927         int i, off = SiSeenodeaddr, cnt = sizeof ee.eaddr / sizeof(short);
928         ushort *shp = (ushort *)ee.eaddr;
929
930         if(ctlr->id == SiS900 && ctlr->pcidev->rid == SiSrev635) {
931                 csr32w(ctlr, Rcr, csr32r(ctlr, Rcr) | Rld);
932                 csr32w(ctlr, Rcr, csr32r(ctlr, Rcr) & ~Rld);
933                 csr32w(ctlr, Rrfcr, csr32r(ctlr, Rrfcr) & ~Rfen);
934
935                 csr32w(ctlr, Rrfcr, 0);
936                 *shp++ = csr32r(ctlr, Rrfdr);
937                 csr32w(ctlr, Rrfcr, 1<<16);
938                 *shp++ = csr32r(ctlr, Rrfdr);
939                 csr32w(ctlr, Rrfcr, 1<<17);
940                 *shp = csr32r(ctlr, Rrfdr);
941
942                 csr32w(ctlr, Rrfcr, csr32r(ctlr, Rrfcr) | Rfen);
943                 memmove(ctlr->sromea, ee.eaddr, sizeof ctlr->sromea);
944         } else if(!is630(ctlr->id, ctlr->pcidev) || !sisrdcmos(ctlr)) {
945                 for (i = 0; i < cnt; i++)
946                         *shp++ = eegetw(ctlr, off++);
947                 memmove(ctlr->sromea, ee.eaddr, sizeof ctlr->sromea);
948         }
949 }
950
951 ushort
952 søkrisee(Ctlr *c, int n)
953 {
954         int i;
955         uint cmd;
956         ushort r;
957
958         csr32w(c, Rmear, Eesel);
959
960         cmd = 0x180|n;
961         for(i = 10; i >= 0; i--){
962                 n = 1<<3;
963                 if(cmd&(1<<i))
964                         n |= 1;
965                 csr32w(c, Rmear, n);
966                 csr32r(c, Rmear);
967                 csr32w(c, Rmear, n|4);
968                 csr32r(c, Rmear);
969         }
970
971         csr32w(c, Rmear, 1<<3);
972         csr32r(c, Rmear);
973
974         r = 0;
975         for(i = 0; i < 16; i++){
976                 csr32w(c, Rmear, 1<<3 | 1<<2);
977                 csr32r(c, Rmear);
978                 if(csr32r(c, Rmear) & 2)
979                         r |= 1<<i;
980                 csr32w(c, Rmear, 1<<3);
981                 csr32r(c, Rmear);
982         }
983
984         csr32w(c, Rmear, 1<<3);
985         csr32w(c, Rmear, 0);
986
987         return r;
988 }
989
990 static void
991 nsnormalea(Ctlr *ctlr)
992 {
993         int i, j;
994
995         /*
996          * the MAC address is reversed, straddling word boundaries
997          */
998         j = Nseenodeaddr*16 + 15;
999         for(i = 0; i < 48; i++){
1000                 ctlr->sromea[i>>3] |= ((ctlr->srom[j>>4] >> (15-(j&0xF))) & 1) << (i&7);
1001                 j++;
1002         }
1003 }
1004
1005 static void
1006 ns403ea(Ctlr *ctlr)
1007 {
1008         int i;
1009         ushort s, t;
1010
1011         s = ctlr->srom[6];
1012         for(i = 0; i < 3; i++){
1013                 t = ctlr->srom[i+7];
1014                 ctlr->sromea[i*2]   = t<<1 | s>>15;
1015                 ctlr->sromea[i*2+1] = t>>7;
1016                 s = t;
1017         }
1018 }
1019
1020 static void
1021 nssrom(Ctlr* ctlr)
1022 {
1023         int i, ns403;
1024         ulong vers;
1025         ushort (*ee)(Ctlr*, int);
1026
1027         vers = ctlr->version;
1028         ns403 = vers == Nat83815avng || vers == Nat83816avng;
1029         if(ns403){
1030                 ee = søkrisee;
1031                 print("soekris %lx\n", vers);
1032         }else
1033                 ee = eegetw;
1034
1035         for(i = 0; i < nelem(ctlr->srom); i++)
1036                 ctlr->srom[i] = ee(ctlr, i);
1037
1038         if(ns403)
1039                 ns403ea(ctlr);
1040         else
1041                 nsnormalea(ctlr);
1042 }
1043
1044 static void
1045 srom(Ctlr* ctlr)
1046 {
1047         memset(ctlr->sromea, 0, sizeof(ctlr->sromea));
1048         switch (ctlr->id) {
1049         case SiS900:
1050         case SiS7016:
1051                 sissrom(ctlr);
1052                 break;
1053         case Nat83815:
1054                 nssrom(ctlr);
1055                 break;
1056         default:
1057                 print("ns83815: srom: unknown id 0x%ux\n", ctlr->id);
1058                 break;
1059         }
1060 }
1061
1062 static void
1063 scanpci83815(void)
1064 {
1065         Ctlr *ctlr;
1066         Pcidev *p;
1067         ulong id;
1068
1069         p = nil;
1070         while(p = pcimatch(p, 0, 0)){
1071                 if(p->ccrb != Pcibcnet || p->ccru != 0)
1072                         continue;
1073                 id = (p->did<<16)|p->vid;
1074                 switch(id){
1075                 default:
1076                         continue;
1077
1078                 case Nat83815:
1079                         break;
1080                 case SiS900:
1081                         break;
1082                 }
1083
1084                 /*
1085                  * bar[0] is the I/O port register address and
1086                  * bar[1] is the memory-mapped register address.
1087                  */
1088                 ctlr = malloc(sizeof(Ctlr));
1089                 if(ctlr == nil){
1090                         print("ns83815: can't allocate memory\n");
1091                         continue;
1092                 }
1093                 ctlr->port = p->mem[0].bar & ~0x01;
1094                 ctlr->pcidev = p;
1095                 ctlr->id = id;
1096
1097                 if(ioalloc(ctlr->port, p->mem[0].size, 0, "ns83815") < 0){
1098                         print("ns83815: port 0x%uX in use\n", ctlr->port);
1099                         free(ctlr);
1100                         continue;
1101                 }
1102
1103                 if(softreset(ctlr, 0) == -1){
1104                         free(ctlr);
1105                         continue;
1106                 }
1107                 srom(ctlr);
1108
1109                 if(ctlrhead != nil)
1110                         ctlrtail->next = ctlr;
1111                 else
1112                         ctlrhead = ctlr;
1113                 ctlrtail = ctlr;
1114         }
1115 }
1116
1117 /* multicast already on, don't need to do anything */
1118 static void
1119 multicast(void*, uchar*, int)
1120 {
1121 }
1122
1123 static int
1124 reset(Ether* ether)
1125 {
1126         Ctlr *ctlr;
1127         int i, x;
1128         ulong ctladdr;
1129         uchar ea[Eaddrlen];
1130         static int scandone;
1131
1132         if(scandone == 0){
1133                 scanpci83815();
1134                 scandone = 1;
1135         }
1136
1137         /*
1138          * Any adapter matches if no ether->port is supplied,
1139          * otherwise the ports must match.
1140          */
1141         for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){
1142                 if(ctlr->active)
1143                         continue;
1144                 if(ether->port == 0 || ether->port == ctlr->port){
1145                         ctlr->active = 1;
1146                         break;
1147                 }
1148         }
1149         if(ctlr == nil)
1150                 return -1;
1151
1152         ether->ctlr = ctlr;
1153         ether->port = ctlr->port;
1154         ether->irq = ctlr->pcidev->intl;
1155         ether->tbdf = ctlr->pcidev->tbdf;
1156
1157         /*
1158          * Check if the adapter's station address is to be overridden.
1159          * If not, read it from the EEPROM and set in ether->ea prior to
1160          * loading the station address in the hardware.
1161          */
1162         memset(ea, 0, Eaddrlen);
1163         if(memcmp(ea, ether->ea, Eaddrlen) == 0)
1164                 memmove(ether->ea, ctlr->sromea, Eaddrlen);
1165         for(i=0; i<Eaddrlen; i+=2){
1166                 x = ether->ea[i] | (ether->ea[i+1]<<8);
1167                 ctladdr = (ctlr->id == Nat83815? i: i<<15);
1168                 csr32w(ctlr, Rrfcr, ctladdr);
1169                 csr32w(ctlr, Rrfdr, x);
1170         }
1171         csr32w(ctlr, Rrfcr, Rfen|Apm|Aab|Aam);
1172
1173         ether->mbps = media(ether);
1174
1175         /*
1176          * Look for a medium override in case there's no autonegotiation
1177          * the autonegotiation fails.
1178          */
1179
1180         for(i = 0; i < ether->nopt; i++){
1181                 if(cistrcmp(ether->opt[i], "FD") == 0){
1182                         ctlr->fd = 1;
1183                         continue;
1184                 }
1185                 for(x = 0; x < nelem(mediatable); x++){
1186                         debug("compare <%s> <%s>\n", mediatable[x],
1187                                 ether->opt[i]);
1188                         if(cistrcmp(mediatable[x], ether->opt[i]) == 0){
1189                                 if(x != 4 && x >= 3)
1190                                         ether->mbps = 100;
1191                                 else
1192                                         ether->mbps = 10;
1193                                 switch(x){
1194                                 default:
1195                                         ctlr->fd = 0;
1196                                         break;
1197
1198                                 case 0x04:              /* 10BASE-TFD */
1199                                 case 0x05:              /* 100BASE-TXFD */
1200                                 case 0x08:              /* 100BASE-FXFD */
1201                                         ctlr->fd = 1;
1202                                         break;
1203                                 }
1204                                 break;
1205                         }
1206                 }
1207         }
1208
1209         /*
1210          * Initialise descriptor rings, ethernet address.
1211          */
1212         ctlr->nrdr = Nrde;
1213         ctlr->ntdr = Ntde;
1214         pcisetbme(ctlr->pcidev);
1215         ctlrinit(ether);
1216
1217         /*
1218          * Linkage to the generic ethernet driver.
1219          */
1220         ether->attach = attach;
1221         ether->transmit = transmit;
1222         ether->interrupt = interrupt;
1223         ether->ifstat = ifstat;
1224
1225         ether->arg = ether;
1226         ether->promiscuous = promiscuous;
1227         ether->multicast = multicast;
1228         ether->shutdown = shutdown;
1229         return 0;
1230 }
1231
1232 void
1233 ether83815link(void)
1234 {
1235         addethercard("83815",  reset);
1236 }