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