]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/cs/if_cs.c
Use __FBSDID().
[FreeBSD/FreeBSD.git] / sys / dev / cs / if_cs.c
1 /*
2  * Copyright (c) 1997,1998 Maxim Bolotin and Oleg Sharoiko.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice unmodified, this list of conditions, and the following
10  *    disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  */
28
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
31
32 /*
33  *
34  * Device driver for Crystal Semiconductor CS8920 based ethernet
35  *   adapters. By Maxim Bolotin and Oleg Sharoiko, 27-April-1997
36  */
37
38 /*
39 #define  CS_DEBUG 
40  */
41
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/malloc.h>
45 #include <sys/mbuf.h>
46 #include <sys/socket.h>
47 #include <sys/sockio.h>
48 #include <sys/kernel.h>
49 #include <sys/sysctl.h>
50 #include <sys/syslog.h>
51
52 #include <sys/module.h>
53 #include <sys/bus.h>
54 #include <machine/bus.h>
55 #include <sys/rman.h>
56 #include <machine/resource.h>
57
58 #include <net/if.h>
59 #include <net/if_arp.h>
60 #include <net/if_media.h>
61 #include <net/ethernet.h>
62 #include <net/bpf.h>
63
64 #include <dev/cs/if_csvar.h>
65 #include <dev/cs/if_csreg.h>
66
67 #ifdef  CS_USE_64K_DMA
68 #define CS_DMA_BUFFER_SIZE 65536
69 #else
70 #define CS_DMA_BUFFER_SIZE 16384
71 #endif
72
73 static int      cs_recv_delay = 570;
74 SYSCTL_INT(_machdep, OID_AUTO, cs_recv_delay, CTLFLAG_RW, &cs_recv_delay, 0, "");
75
76 static void     cs_init         (void *);
77 static int      cs_ioctl        (struct ifnet *, u_long, caddr_t);
78 static void     cs_start        (struct ifnet *);
79 static void     cs_stop         (struct cs_softc *);
80 static void     cs_reset        (struct cs_softc *);
81 static void     cs_watchdog     (struct ifnet *);
82
83 static int      cs_mediachange  (struct ifnet *);
84 static void     cs_mediastatus  (struct ifnet *, struct ifmediareq *);
85 static int      cs_mediaset     (struct cs_softc *, int);
86
87 static void     cs_write_mbufs(struct cs_softc*, struct mbuf*);
88 static void     cs_xmit_buf(struct cs_softc*);
89 static int      cs_get_packet(struct cs_softc*);
90 static void     cs_setmode(struct cs_softc*);
91
92 static int      get_eeprom_data(struct cs_softc *sc, int, int, int *);
93 static int      get_eeprom_cksum(int, int, int *);
94 static int      wait_eeprom_ready( struct cs_softc *);
95 static void     control_dc_dc( struct cs_softc *, int );
96 static int      send_test_pkt( struct cs_softc * );
97 static int      enable_tp(struct cs_softc *);
98 static int      enable_aui(struct cs_softc *);
99 static int      enable_bnc(struct cs_softc *);
100 static int      cs_duplex_auto(struct cs_softc *);
101
102 devclass_t cs_devclass;
103
104 static int
105 get_eeprom_data( struct cs_softc *sc, int off, int len, int *buffer)
106 {
107         int i;
108
109 #ifdef CS_DEBUG
110         printf(CS_NAME":EEPROM data from %x for %x:\n", off,len);
111 #endif
112
113         for (i=0;i<len;i++) {
114                 if (wait_eeprom_ready(sc) < 0) return -1;
115                 /* Send command to EEPROM to read */
116                 cs_writereg(sc, PP_EECMD, (off + i) | EEPROM_READ_CMD);
117                 if (wait_eeprom_ready(sc)<0)
118                         return (-1);
119                 buffer[i] = cs_readreg(sc, PP_EEData);
120
121 #ifdef CS_DEBUG
122                 printf("%02x %02x ",(unsigned char)buffer[i],
123                                         (unsigned char)buffer[i+1]);
124 #endif
125         }
126
127 #ifdef CS_DEBUG
128         printf("\n");
129 #endif
130         return (0);
131 }
132
133 static int
134 get_eeprom_cksum(int off, int len, int *buffer)
135 {
136         int i,cksum=0;
137
138         for (i=0;i<len;i++)
139                 cksum+=buffer[i];
140         cksum &= 0xffff;
141         if (cksum==0)
142                 return 0;
143         return -1;
144 }
145
146 static int
147 wait_eeprom_ready(struct cs_softc *sc)
148 {
149         DELAY ( 30000 );        /* XXX should we do some checks here ? */
150         return 0;
151 }
152
153 static void
154 control_dc_dc(struct cs_softc *sc, int on_not_off)
155 {
156         unsigned int self_control = HCB1_ENBL;
157
158         if (((sc->adapter_cnf & A_CNF_DC_DC_POLARITY)!=0) ^ on_not_off)
159                 self_control |= HCB1;
160         else
161                 self_control &= ~HCB1;
162         cs_writereg(sc, PP_SelfCTL, self_control);
163
164         DELAY( 500000 );
165 }
166
167
168 static int
169 cs_duplex_auto(struct cs_softc *sc)
170 {
171         int i, error=0;
172         
173         cs_writereg(sc, PP_AutoNegCTL,
174             RE_NEG_NOW | ALLOW_FDX | AUTO_NEG_ENABLE);
175         for (i=0; cs_readreg(sc, PP_AutoNegST) & AUTO_NEG_BUSY; i++) {
176                 if (i > 40000) {
177                         if_printf(&sc->arpcom.ac_if,
178                                 "full/half duplex auto negotiation timeout\n");
179                         error = ETIMEDOUT;
180                         break;
181                 }
182                 DELAY(1000);
183         }
184         DELAY( 1000000 );
185         return error;
186 }
187
188 static int
189 enable_tp(struct cs_softc *sc)
190 {
191
192         cs_writereg(sc, PP_LineCTL, sc->line_ctl & ~AUI_ONLY);
193         control_dc_dc(sc, 0);
194         DELAY( 150000 );
195
196         if ((cs_readreg(sc, PP_LineST) & LINK_OK)==0) {
197                 if_printf(&sc->arpcom.ac_if, "failed to enable TP\n");
198                 return EINVAL;
199         }
200
201         return 0;
202 }
203
204 /*
205  * XXX This was rewritten from Linux driver without any tests.
206  */             
207 static int
208 send_test_pkt(struct cs_softc *sc)
209 {
210         char test_packet[] = { 0,0,0,0,0,0, 0,0,0,0,0,0,
211                                 0, 46,  /* A 46 in network order */
212                                 0, 0,   /* DSAP=0 & SSAP=0 fields */
213                                 0xf3, 0 /* Control (Test Req + P bit set) */ };
214         int i;
215         u_char ether_address_backup[ETHER_ADDR_LEN];
216
217         for (i = 0; i < ETHER_ADDR_LEN; i++) {
218                 ether_address_backup[i] = sc->arpcom.ac_enaddr[i];
219         }
220
221         cs_writereg(sc, PP_LineCTL, cs_readreg(sc, PP_LineCTL) | SERIAL_TX_ON);
222         bcopy(test_packet, sc->arpcom.ac_enaddr, ETHER_ADDR_LEN);
223         bcopy(test_packet+ETHER_ADDR_LEN, 
224             sc->arpcom.ac_enaddr, ETHER_ADDR_LEN);
225         cs_outw(sc, TX_CMD_PORT, sc->send_cmd);
226         cs_outw(sc, TX_LEN_PORT, sizeof(test_packet));
227
228         /* Wait for chip to allocate memory */
229         DELAY(50000);
230         if (!(cs_readreg(sc, PP_BusST) & READY_FOR_TX_NOW)) {
231                 for (i = 0; i < ETHER_ADDR_LEN; i++) {
232                         sc->arpcom.ac_enaddr[i] = ether_address_backup[i];
233                 }
234                 return 0;
235         }
236
237         outsw(sc->nic_addr + TX_FRAME_PORT, test_packet, sizeof(test_packet));
238
239         DELAY(30000);
240
241         if ((cs_readreg(sc, PP_TxEvent) & TX_SEND_OK_BITS) == TX_OK) {
242                 for (i = 0; i < ETHER_ADDR_LEN; i++) {
243                         sc->arpcom.ac_enaddr[i] = ether_address_backup[i];
244                 }
245                 return 1;
246         }
247         for (i = 0; i < ETHER_ADDR_LEN; i++) {
248                 sc->arpcom.ac_enaddr[i] = ether_address_backup[i];
249         }
250         return 0;
251 }
252
253 /*
254  * XXX This was rewritten from Linux driver without any tests.
255  */
256 static int
257 enable_aui(struct cs_softc *sc)
258 {
259
260         control_dc_dc(sc, 0);
261         cs_writereg(sc, PP_LineCTL,
262             (sc->line_ctl & ~AUTO_AUI_10BASET) | AUI_ONLY);
263
264         if (!send_test_pkt(sc)) {
265                 if_printf(&sc->arpcom.ac_if, "failed to enable AUI\n");
266                 return EINVAL;
267         }
268         return 0;
269 }
270
271 /*
272  * XXX This was rewritten from Linux driver without any tests.
273  */             
274 static int
275 enable_bnc(struct cs_softc *sc)
276 {
277
278         control_dc_dc(sc, 1);
279         cs_writereg(sc, PP_LineCTL,
280             (sc->line_ctl & ~AUTO_AUI_10BASET) | AUI_ONLY);
281
282         if (!send_test_pkt(sc)) {
283                 if_printf(&sc->arpcom.ac_if, "failed to enable BNC\n");
284                 return EINVAL;
285         }
286         return 0;
287 }
288
289 int
290 cs_cs89x0_probe(device_t dev)
291 {
292         int i;
293         int error;
294         u_long irq, junk;
295         struct cs_softc *sc = device_get_softc(dev);
296         unsigned rev_type = 0;
297         u_int16_t id;
298         char chip_revision;
299         int eeprom_buff[CHKSUM_LEN];
300         int chip_type, pp_isaint, pp_isadma;
301
302         error = cs_alloc_port(dev, 0, CS_89x0_IO_PORTS);
303         if (error)
304                 return (error);
305
306         sc->nic_addr = rman_get_start(sc->port_res);
307
308         if ((cs_inw(sc, ADD_PORT) & ADD_MASK) != ADD_SIG) {
309                 /* Chip not detected. Let's try to reset it */
310                 if (bootverbose)
311                         device_printf(dev, "trying to reset the chip.\n");
312                 cs_outw(sc, ADD_PORT, PP_SelfCTL);
313                 i = cs_inw(sc, DATA_PORT);
314                 cs_outw(sc, ADD_PORT, PP_SelfCTL);
315                 cs_outw(sc, DATA_PORT, i | POWER_ON_RESET);
316                 if ((cs_inw(sc, ADD_PORT) & ADD_MASK) != ADD_SIG)
317                         return (ENXIO);
318         }
319
320         for (i = 0; i < 10000; i++) {
321                 id = cs_readreg(sc, PP_ChipID);
322                 if (id == CHIP_EISA_ID_SIG)
323                         break;
324         }
325         if (i == 10000)
326                 return (ENXIO);
327
328         rev_type = cs_readreg(sc, PRODUCT_ID_ADD);
329         chip_type = rev_type & ~REVISON_BITS;
330         chip_revision = ((rev_type & REVISON_BITS) >> 8) + 'A';
331
332         sc->chip_type = chip_type;
333
334         if(chip_type==CS8900) {
335                 pp_isaint = PP_CS8900_ISAINT;
336                 pp_isadma = PP_CS8900_ISADMA;
337                 sc->send_cmd = TX_CS8900_AFTER_ALL;
338         } else {
339                 pp_isaint = PP_CS8920_ISAINT;
340                 pp_isadma = PP_CS8920_ISADMA;
341                 sc->send_cmd = TX_CS8920_AFTER_ALL;
342         }
343
344         /*
345          * Clear some fields so that fail of EEPROM will left them clean
346          */
347         sc->auto_neg_cnf = 0;
348         sc->adapter_cnf  = 0;
349         sc->isa_config   = 0;
350         
351         /*
352          * If no interrupt specified (or "?"), use what the board tells us.
353          */
354         error = bus_get_resource(dev, SYS_RES_IRQ, 0, &irq, &junk);
355
356         /*
357          * Get data from EEPROM
358          */
359         if((cs_readreg(sc, PP_SelfST) & EEPROM_PRESENT) == 0) {
360                 device_printf(dev, "No EEPROM, assuming defaults.\n");
361         } else {
362                 if (get_eeprom_data(sc,START_EEPROM_DATA,CHKSUM_LEN, eeprom_buff)<0) {
363                         device_printf(dev, "EEPROM read failed, "
364                                 "assuming defaults.\n");
365                 } else {
366                         if (get_eeprom_cksum(START_EEPROM_DATA,CHKSUM_LEN, eeprom_buff)<0) {
367                                 device_printf(dev, "EEPROM cheksum bad, "
368                                         "assuming defaults.\n");
369                         } else {
370                                 sc->auto_neg_cnf =
371                                         eeprom_buff[AUTO_NEG_CNF_OFFSET/2];
372                                 sc->adapter_cnf =
373                                         eeprom_buff[ADAPTER_CNF_OFFSET/2];
374                                 sc->isa_config =
375                                         eeprom_buff[ISA_CNF_OFFSET/2];
376
377                                 for (i=0; i<ETHER_ADDR_LEN/2; i++) {
378                                         sc->arpcom.ac_enaddr[i*2]=
379                                                 eeprom_buff[i];
380                                         sc->arpcom.ac_enaddr[i*2+1]=
381                                                 eeprom_buff[i] >> 8;
382                                 }
383
384                                 /*
385                                  * If no interrupt specified (or "?"),
386                                  * use what the board tells us.
387                                  */
388                                 if (error) {
389                                         irq = sc->isa_config & INT_NO_MASK;
390                                         if (chip_type==CS8900) {
391                                                 switch(irq) {
392                                                  case 0:
393                                                         irq=10;
394                                                         error=0;
395                                                         break;
396                                                  case 1:
397                                                         irq=11;
398                                                         error=0;
399                                                         break;
400                                                  case 2:
401                                                         irq=12;
402                                                         error=0;
403                                                         break;
404                                                  case 3:
405                                                         irq=5;
406                                                         error=0;
407                                                         break;
408                                                  default:
409                                                         device_printf(dev, "invalid irq in EEPROM.\n");
410                                                         error=EINVAL;
411                                                 }
412                                         } else {
413                                                 if (irq>CS8920_NO_INTS) {
414                                                         device_printf(dev, "invalid irq in EEPROM.\n");
415                                                         error=EINVAL;
416                                                 } else {
417                                                         error=0;
418                                                 }
419                                         }
420
421                                         if (!error)
422                                                 bus_set_resource(dev, SYS_RES_IRQ, 0,
423                                                                 irq, 1);
424                                 }
425                         }
426                 }
427         }
428
429         if (!error) {
430                 if (chip_type == CS8900) {
431                         switch(irq) {
432                                 case  5:
433                                         irq = 3;
434                                         break;
435                                 case 10:
436                                         irq = 0;
437                                         break;
438                                 case 11:
439                                         irq = 1;
440                                         break;
441                                 case 12:
442                                         irq = 2;
443                                         break;
444                                 default:
445                                         error=EINVAL;
446                         }
447                 } else {
448                         if (irq > CS8920_NO_INTS) {
449                                 error = EINVAL;
450                         }
451                 }
452         }
453
454         if (!error) {
455                 cs_writereg(sc, pp_isaint, irq);
456         } else {
457                 device_printf(dev, "Unknown or invalid irq\n");
458                 return (ENXIO);
459         }
460         
461         /*
462          * Temporary disabled
463          *
464         if (drq>0)
465                 cs_writereg(sc, pp_isadma, drq);
466         else {
467                 device_printf(dev, "incorrect drq\n",);
468                 return 0;
469         }
470         */
471
472         if (bootverbose)
473                  device_printf(dev, "CS89%c0%s rev %c media%s%s%s\n",
474                         chip_type==CS8900 ? '0' : '2',
475                         chip_type==CS8920M ? "M" : "",
476                         chip_revision,
477                         (sc->adapter_cnf & A_CNF_10B_T) ? " TP"  : "",
478                         (sc->adapter_cnf & A_CNF_AUI)   ? " AUI" : "",
479                         (sc->adapter_cnf & A_CNF_10B_2) ? " BNC" : "");
480
481         if ((sc->adapter_cnf & A_CNF_EXTND_10B_2) &&
482             (sc->adapter_cnf & A_CNF_LOW_RX_SQUELCH))
483                 sc->line_ctl = LOW_RX_SQUELCH;
484         else
485                 sc->line_ctl = 0;
486
487         
488         return 0;
489 }
490
491 /*
492  * Allocate a port resource with the given resource id.
493  */
494 int cs_alloc_port(device_t dev, int rid, int size)
495 {
496         struct cs_softc *sc = device_get_softc(dev);
497         struct resource *res;
498
499         res = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
500                                  0ul, ~0ul, size, RF_ACTIVE);
501         if (res) {
502                 sc->port_rid = rid;
503                 sc->port_res = res;
504                 sc->port_used = size;
505                 return (0);
506         } else {
507                 return (ENOENT);
508         }
509 }
510
511 /*
512  * Allocate a memory resource with the given resource id.
513  */
514 int cs_alloc_memory(device_t dev, int rid, int size)
515 {
516         struct cs_softc *sc = device_get_softc(dev);
517         struct resource *res;
518
519         res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid,
520                                  0ul, ~0ul, size, RF_ACTIVE);
521         if (res) {
522                 sc->mem_rid = rid;
523                 sc->mem_res = res;
524                 sc->mem_used = size;
525                 return (0);
526         } else {
527                 return (ENOENT);
528         }
529 }
530
531 /*
532  * Allocate an irq resource with the given resource id.
533  */
534 int cs_alloc_irq(device_t dev, int rid, int flags)
535 {
536         struct cs_softc *sc = device_get_softc(dev);
537         struct resource *res;
538
539         res = bus_alloc_resource(dev, SYS_RES_IRQ, &rid,
540                                  0ul, ~0ul, 1, (RF_ACTIVE | flags));
541         if (res) {
542                 sc->irq_rid = rid;
543                 sc->irq_res = res;
544                 return (0);
545         } else {
546                 return (ENOENT);
547         }
548 }
549
550 /*
551  * Release all resources
552  */
553 void cs_release_resources(device_t dev)
554 {
555         struct cs_softc *sc = device_get_softc(dev);
556
557         if (sc->port_res) {
558                 bus_release_resource(dev, SYS_RES_IOPORT,
559                                      sc->port_rid, sc->port_res);
560                 sc->port_res = 0;
561         }
562         if (sc->mem_res) {
563                 bus_release_resource(dev, SYS_RES_MEMORY,
564                                      sc->mem_rid, sc->mem_res);
565                 sc->mem_res = 0;
566         }
567         if (sc->irq_res) {
568                 bus_release_resource(dev, SYS_RES_IRQ,
569                                      sc->irq_rid, sc->irq_res);
570                 sc->irq_res = 0;
571         }
572 }
573
574 /*
575  * Install the interface into kernel networking data structures
576  */
577 int
578 cs_attach(struct cs_softc *sc, int unit, int flags)
579 {
580         int media=0;
581         struct ifnet *ifp = &(sc->arpcom.ac_if);
582
583         cs_stop( sc );
584
585         if (!ifp->if_name) {
586                 ifp->if_softc=sc;
587                 ifp->if_unit=unit;
588                 ifp->if_name="cs";
589                 ifp->if_output=ether_output;
590                 ifp->if_start=cs_start;
591                 ifp->if_ioctl=cs_ioctl;
592                 ifp->if_watchdog=cs_watchdog;
593                 ifp->if_init=cs_init;
594                 ifp->if_snd.ifq_maxlen= IFQ_MAXLEN;
595                 /*
596                  *  MIB DATA
597                  */
598                 /*
599                 ifp->if_linkmib=&sc->mibdata;
600                 ifp->if_linkmiblen=sizeof sc->mibdata;
601                 */
602
603                 ifp->if_flags=(IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST );
604
605                 /*
606                  * this code still in progress (DMA support)
607                  *
608
609                 sc->recv_ring=malloc(CS_DMA_BUFFER_SIZE<<1, M_DEVBUF, M_NOWAIT);
610                 if (sc->recv_ring == NULL) {
611                         log(LOG_ERR,CS_NAME
612                         "%d: Couldn't allocate memory for NIC\n", unit);
613                         return(0);
614                 }
615                 if ((sc->recv_ring-(sc->recv_ring & 0x1FFFF))
616                     < (128*1024-CS_DMA_BUFFER_SIZE))
617                     sc->recv_ring+=16*1024;
618
619                 */
620
621                 sc->buffer=malloc(ETHER_MAX_LEN-ETHER_CRC_LEN,M_DEVBUF,M_NOWAIT);
622                 if (sc->buffer == NULL) {
623                         if_printf(ifp, "Couldn't allocate memory for NIC\n");
624                         return(0);
625                 }
626
627                 /*
628                  * Initialize the media structures.
629                  */
630                 ifmedia_init(&sc->media, 0, cs_mediachange, cs_mediastatus);
631
632                 if (sc->adapter_cnf & A_CNF_10B_T) {
633                         ifmedia_add(&sc->media, IFM_ETHER|IFM_10_T, 0, NULL);
634                         if (sc->chip_type != CS8900) {
635                                 ifmedia_add(&sc->media,
636                                         IFM_ETHER|IFM_10_T|IFM_FDX, 0, NULL);
637                                 ifmedia_add(&sc->media,
638                                         IFM_ETHER|IFM_10_T|IFM_HDX, 0, NULL);
639                         }
640                 } 
641
642                 if (sc->adapter_cnf & A_CNF_10B_2)
643                         ifmedia_add(&sc->media, IFM_ETHER|IFM_10_2, 0, NULL);
644
645                 if (sc->adapter_cnf & A_CNF_AUI)
646                         ifmedia_add(&sc->media, IFM_ETHER|IFM_10_5, 0, NULL);
647
648                 if (sc->adapter_cnf & A_CNF_MEDIA)
649                         ifmedia_add(&sc->media, IFM_ETHER|IFM_AUTO, 0, NULL);
650
651                 /* Set default media from EEPROM */
652                 switch (sc->adapter_cnf & A_CNF_MEDIA_TYPE) {
653                 case A_CNF_MEDIA_AUTO:  media = IFM_ETHER|IFM_AUTO; break;
654                 case A_CNF_MEDIA_10B_T: media = IFM_ETHER|IFM_10_T; break;
655                 case A_CNF_MEDIA_10B_2: media = IFM_ETHER|IFM_10_2; break;
656                 case A_CNF_MEDIA_AUI:   media = IFM_ETHER|IFM_10_5; break;
657                 default: if_printf(ifp, "adapter has no media\n");
658                 }
659                 ifmedia_set(&sc->media, media);
660                 cs_mediaset(sc, media);
661
662                 ether_ifattach(ifp, sc->arpcom.ac_enaddr);
663         }
664
665         if (bootverbose)
666                 if_printf(ifp, "ethernet address %6D\n",
667                        sc->arpcom.ac_enaddr, ":");
668
669         return (0);
670 }
671
672 /*
673  * Initialize the board
674  */
675 static void
676 cs_init(void *xsc)
677 {
678         struct cs_softc *sc=(struct cs_softc *)xsc;
679         struct ifnet *ifp = &sc->arpcom.ac_if;
680         int i, s, rx_cfg;
681
682         /* address not known */
683         if (TAILQ_EMPTY(&ifp->if_addrhead)) /* unlikely? XXX */
684                 return;
685
686         /*
687          * reset whatchdog timer
688          */
689         ifp->if_timer=0;
690         sc->buf_len = 0;
691         
692         s=splimp();
693
694         /*
695          * Hardware initialization of cs
696          */
697
698         /* Enable receiver and transmitter */
699         cs_writereg(sc, PP_LineCTL,
700                 cs_readreg(sc, PP_LineCTL) | SERIAL_RX_ON | SERIAL_TX_ON);
701
702         /* Configure the receiver mode */
703         cs_setmode(sc);
704
705         /*
706          * This defines what type of frames will cause interrupts
707          * Bad frames should generate interrupts so that the driver
708          * could track statistics of discarded packets
709          */
710         rx_cfg = RX_OK_ENBL | RX_CRC_ERROR_ENBL | RX_RUNT_ENBL |
711                  RX_EXTRA_DATA_ENBL;
712         if (sc->isa_config & STREAM_TRANSFER)
713                 rx_cfg |= RX_STREAM_ENBL;
714         cs_writereg(sc, PP_RxCFG, rx_cfg);
715         cs_writereg(sc, PP_TxCFG, TX_LOST_CRS_ENBL |
716                     TX_SQE_ERROR_ENBL | TX_OK_ENBL | TX_LATE_COL_ENBL |
717                     TX_JBR_ENBL | TX_ANY_COL_ENBL | TX_16_COL_ENBL);
718         cs_writereg(sc, PP_BufCFG, READY_FOR_TX_ENBL |
719                     RX_MISS_COUNT_OVRFLOW_ENBL | TX_COL_COUNT_OVRFLOW_ENBL |
720                     TX_UNDERRUN_ENBL /*| RX_DMA_ENBL*/);
721
722         /* Write MAC address into IA filter */
723         for (i=0; i<ETHER_ADDR_LEN/2; i++)
724                 cs_writereg(sc, PP_IA + i * 2,
725                     sc->arpcom.ac_enaddr[i * 2] |
726                     (sc->arpcom.ac_enaddr[i * 2 + 1] << 8) );
727
728         /*
729          * Now enable everything
730          */
731 /*
732 #ifdef  CS_USE_64K_DMA
733         cs_writereg(sc, PP_BusCTL, ENABLE_IRQ | RX_DMA_SIZE_64K);
734 #else
735         cs_writereg(sc, PP_BusCTL, ENABLE_IRQ);
736 #endif
737 */
738         cs_writereg(sc, PP_BusCTL, ENABLE_IRQ);
739         
740         /*
741          * Set running and clear output active flags
742          */
743         sc->arpcom.ac_if.if_flags |= IFF_RUNNING;
744         sc->arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
745
746         /*
747          * Start sending process
748          */
749         cs_start(ifp);
750
751         (void) splx(s);
752 }
753
754 /*
755  * Get the packet from the board and send it to the upper layer.
756  */
757 static int
758 cs_get_packet(struct cs_softc *sc)
759 {
760         struct ifnet *ifp = &(sc->arpcom.ac_if);
761         int iobase = sc->nic_addr, status, length;
762         struct ether_header *eh;
763         struct mbuf *m;
764
765 #ifdef CS_DEBUG
766         int i;
767 #endif
768
769         status = cs_inw(sc, RX_FRAME_PORT);
770         length = cs_inw(sc, RX_FRAME_PORT);
771
772 #ifdef CS_DEBUG
773         if_printf(ifp, "rcvd: stat %x, len %d\n",
774                 status, length);
775 #endif
776
777         if (!(status & RX_OK)) {
778 #ifdef CS_DEBUG
779                 if_printf(ifp, "bad pkt stat %x\n", status);
780 #endif
781                 ifp->if_ierrors++;
782                 return -1;
783         }
784
785         MGETHDR(m, M_DONTWAIT, MT_DATA);
786         if (m==NULL)
787                 return -1;
788
789         if (length > MHLEN) {
790                 MCLGET(m, M_DONTWAIT);
791                 if (!(m->m_flags & M_EXT)) {
792                         m_freem(m);
793                         return -1;
794                 }
795         }
796
797         /* Initialize packet's header info */
798         m->m_pkthdr.rcvif = ifp;
799         m->m_pkthdr.len = length;
800         m->m_len = length;
801
802         /* Get the data */
803         insw(iobase + RX_FRAME_PORT, m->m_data, (length+1)>>1);
804
805         eh = mtod(m, struct ether_header *);
806
807 #ifdef CS_DEBUG
808         for (i=0;i<length;i++)
809              printf(" %02x",(unsigned char)*((char *)(m->m_data+i)));
810         printf( "\n" );
811 #endif
812
813         if (status & (RX_IA | RX_BROADCAST) || 
814             (ifp->if_flags & IFF_MULTICAST && status & RX_HASHED)) {
815                 /* Feed the packet to the upper layer */
816                 (*ifp->if_input)(ifp, m);
817
818                 ifp->if_ipackets++;
819
820                 if (length==ETHER_MAX_LEN-ETHER_CRC_LEN)
821                         DELAY( cs_recv_delay );
822         } else {
823                 m_freem(m);
824         }
825
826         return 0;
827 }
828
829 /*
830  * Handle interrupts
831  */
832 void
833 csintr(void *arg)
834 {
835         struct cs_softc *sc = (struct cs_softc*) arg;
836         struct ifnet *ifp = &(sc->arpcom.ac_if);
837         int status;
838
839 #ifdef CS_DEBUG
840         if_printf(ifp, "Interrupt.\n");
841 #endif
842
843         while ((status=cs_inw(sc, ISQ_PORT))) {
844
845 #ifdef CS_DEBUG
846                 if_printf(ifp, "from ISQ: %04x\n", status);
847 #endif
848
849                 switch (status & ISQ_EVENT_MASK) {
850                 case ISQ_RECEIVER_EVENT:
851                         cs_get_packet(sc);
852                         break;
853
854                 case ISQ_TRANSMITTER_EVENT:
855                         if (status & TX_OK)
856                                 ifp->if_opackets++;
857                         else
858                                 ifp->if_oerrors++;
859                         ifp->if_flags &= ~IFF_OACTIVE;
860                         ifp->if_timer = 0;
861                         break;
862
863                 case ISQ_BUFFER_EVENT:
864                         if (status & READY_FOR_TX) {
865                                 ifp->if_flags &= ~IFF_OACTIVE;
866                                 ifp->if_timer = 0;
867                         }
868
869                         if (status & TX_UNDERRUN) {
870                                 ifp->if_flags &= ~IFF_OACTIVE;
871                                 ifp->if_timer = 0;
872                                 ifp->if_oerrors++;
873                         }
874                         break;
875
876                 case ISQ_RX_MISS_EVENT:
877                         ifp->if_ierrors+=(status>>6);
878                         break;
879
880                 case ISQ_TX_COL_EVENT:
881                         ifp->if_collisions+=(status>>6);
882                         break;
883                 }
884         }
885
886         if (!(ifp->if_flags & IFF_OACTIVE)) {
887                 cs_start(ifp);
888         }
889 }
890
891 /*
892  * Save the data in buffer
893  */
894
895 static void
896 cs_write_mbufs( struct cs_softc *sc, struct mbuf *m )
897 {
898         int len;
899         struct mbuf *mp;
900         unsigned char *data, *buf;
901
902         for (mp=m, buf=sc->buffer, sc->buf_len=0; mp != NULL; mp=mp->m_next) {
903                 len = mp->m_len;
904
905                 /*
906                  * Ignore empty parts
907                  */
908                 if (!len)
909                 continue;
910
911                 /*
912                  * Find actual data address
913                  */
914                 data = mtod(mp, caddr_t);
915
916                 bcopy((caddr_t) data, (caddr_t) buf, len);
917                 buf += len;
918                 sc->buf_len += len;
919         }
920 }
921
922
923 static void
924 cs_xmit_buf( struct cs_softc *sc )
925 {
926         outsw(sc->nic_addr+TX_FRAME_PORT, sc->buffer, (sc->buf_len+1)>>1);
927         sc->buf_len = 0;
928 }
929
930 static void
931 cs_start(struct ifnet *ifp)
932 {
933         int s, length;
934         struct mbuf *m, *mp;
935         struct cs_softc *sc = ifp->if_softc;
936
937         s = splimp();
938
939         for (;;) {
940                 if (sc->buf_len)
941                         length = sc->buf_len;
942                 else {
943                         IF_DEQUEUE( &ifp->if_snd, m );
944
945                         if (m==NULL) {
946                                 (void) splx(s);
947                                 return;
948                         }
949
950                         for (length=0, mp=m; mp != NULL; mp=mp->m_next)
951                                 length += mp->m_len;
952
953                         /* Skip zero-length packets */
954                         if (length == 0) {
955                                 m_freem(m);
956                                 continue;
957                         }
958
959                         cs_write_mbufs(sc, m);
960
961                         BPF_MTAP(ifp, m);
962
963                         m_freem(m);
964                 }
965
966                 /*
967                  * Issue a SEND command
968                  */
969                 cs_outw(sc, TX_CMD_PORT, sc->send_cmd);
970                 cs_outw(sc, TX_LEN_PORT, length );
971
972                 /*
973                  * If there's no free space in the buffer then leave
974                  * this packet for the next time: indicate output active
975                  * and return.
976                  */
977                 if (!(cs_readreg(sc, PP_BusST) & READY_FOR_TX_NOW)) {
978                         ifp->if_timer = sc->buf_len;
979                         (void) splx(s);
980                         ifp->if_flags |= IFF_OACTIVE;
981                         return;
982                 }
983
984                 cs_xmit_buf(sc);
985
986                 /*
987                  * Set the watchdog timer in case we never hear
988                  * from board again. (I don't know about correct
989                  * value for this timeout)
990                  */
991                 ifp->if_timer = length;
992
993                 (void) splx(s);
994                 ifp->if_flags |= IFF_OACTIVE;
995                 return;
996         }
997 }
998
999 /*
1000  * Stop everything on the interface
1001  */
1002 static void
1003 cs_stop(struct cs_softc *sc)
1004 {
1005         int s = splimp();
1006
1007         cs_writereg(sc, PP_RxCFG, 0);
1008         cs_writereg(sc, PP_TxCFG, 0);
1009         cs_writereg(sc, PP_BufCFG, 0);
1010         cs_writereg(sc, PP_BusCTL, 0);
1011
1012         sc->arpcom.ac_if.if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
1013         sc->arpcom.ac_if.if_timer = 0;
1014
1015         (void) splx(s);
1016 }
1017
1018 /*
1019  * Reset the interface
1020  */
1021 static void
1022 cs_reset(struct cs_softc *sc)
1023 {
1024         cs_stop(sc);
1025         cs_init(sc);
1026 }
1027
1028 static void
1029 cs_setmode(struct cs_softc *sc)
1030 {
1031         struct ifnet *ifp = &(sc->arpcom.ac_if);
1032         int rx_ctl;
1033
1034         /* Stop the receiver while changing filters */
1035         cs_writereg(sc, PP_LineCTL, cs_readreg(sc, PP_LineCTL) & ~SERIAL_RX_ON);
1036
1037         if (ifp->if_flags & IFF_PROMISC) {
1038                 /* Turn on promiscuous mode. */
1039                 rx_ctl = RX_OK_ACCEPT | RX_PROM_ACCEPT;
1040         } else {
1041                 if (ifp->if_flags & IFF_MULTICAST) {
1042                         /* Allow receiving frames with multicast addresses */
1043                         rx_ctl = RX_IA_ACCEPT | RX_BROADCAST_ACCEPT |
1044                                  RX_OK_ACCEPT | RX_MULTCAST_ACCEPT;
1045                         /*
1046                          * Here the reconfiguration of chip's multicast
1047                          * filters should be done but I've no idea about
1048                          * hash transformation in this chip. If you can
1049                          * add this code or describe me the transformation
1050                          * I'd be very glad.
1051                          */
1052                 } else {
1053                         /*
1054                          * Receive only good frames addressed for us and
1055                          * good broadcasts.
1056                          */
1057                         rx_ctl = RX_IA_ACCEPT | RX_BROADCAST_ACCEPT |
1058                                  RX_OK_ACCEPT;
1059                 }
1060         }
1061
1062         /* Set up the filter */
1063         cs_writereg(sc, PP_RxCTL, RX_DEF_ACCEPT | rx_ctl);
1064
1065         /* Turn on receiver */
1066         cs_writereg(sc, PP_LineCTL, cs_readreg(sc, PP_LineCTL) | SERIAL_RX_ON);
1067 }
1068
1069 static int
1070 cs_ioctl(register struct ifnet *ifp, u_long command, caddr_t data)
1071 {
1072         struct cs_softc *sc=ifp->if_softc;
1073         struct ifreq *ifr = (struct ifreq *)data;
1074         int s,error=0;
1075
1076 #ifdef CS_DEBUG
1077         if_printf(ifp, "ioctl(%lx)\n", command);
1078 #endif
1079
1080         s=splimp();
1081
1082         switch (command) {
1083         case SIOCSIFFLAGS:
1084                 /*
1085                  * Switch interface state between "running" and
1086                  * "stopped", reflecting the UP flag.
1087                  */
1088                 if (sc->arpcom.ac_if.if_flags & IFF_UP) {
1089                         if ((sc->arpcom.ac_if.if_flags & IFF_RUNNING)==0) {
1090                                 cs_init(sc);
1091                         }
1092                 } else {
1093                         if ((sc->arpcom.ac_if.if_flags & IFF_RUNNING)!=0) {
1094                                 cs_stop(sc);
1095                         }
1096                 }
1097                 /*
1098                  * Promiscuous and/or multicast flags may have changed,
1099                  * so reprogram the multicast filter and/or receive mode.
1100                  *
1101                  * See note about multicasts in cs_setmode
1102                  */
1103                 cs_setmode(sc);
1104                 break;
1105
1106         case SIOCADDMULTI:
1107         case SIOCDELMULTI:
1108             /*
1109              * Multicast list has changed; set the hardware filter
1110              * accordingly.
1111              *
1112              * See note about multicasts in cs_setmode
1113              */
1114             cs_setmode(sc);
1115             error = 0;
1116             break;
1117
1118         case SIOCSIFMEDIA:
1119         case SIOCGIFMEDIA:
1120                 error = ifmedia_ioctl(ifp, ifr, &sc->media, command);
1121                 break;
1122
1123         default:
1124                 ether_ioctl(ifp, command, data);
1125                 break;
1126         }
1127
1128         (void) splx(s);
1129         return error;
1130 }
1131
1132 /*
1133  * Device timeout/watchdog routine. Entered if the device neglects to
1134  * generate an interrupt after a transmit has been started on it.
1135  */
1136 static void
1137 cs_watchdog(struct ifnet *ifp)
1138 {
1139         struct cs_softc *sc = ifp->if_softc;
1140
1141         ifp->if_oerrors++;
1142         log(LOG_ERR, CS_NAME"%d: device timeout\n", ifp->if_unit);
1143
1144         /* Reset the interface */
1145         if (ifp->if_flags & IFF_UP)
1146                 cs_reset(sc);
1147         else
1148                 cs_stop(sc);
1149 }
1150
1151 static int
1152 cs_mediachange(struct ifnet *ifp)
1153 {
1154         struct cs_softc *sc = ifp->if_softc;
1155         struct ifmedia *ifm = &sc->media;
1156
1157         if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER)
1158                 return EINVAL;
1159
1160         return cs_mediaset(sc, ifm->ifm_media);
1161 }
1162
1163 static void
1164 cs_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr)
1165 {
1166         int line_status;
1167         struct cs_softc *sc = ifp->if_softc;
1168
1169         ifmr->ifm_active = IFM_ETHER;
1170         line_status = cs_readreg(sc, PP_LineST);
1171         if (line_status & TENBASET_ON) {
1172                 ifmr->ifm_active |= IFM_10_T;
1173                 if (sc->chip_type != CS8900) {
1174                         if (cs_readreg(sc, PP_AutoNegST) & FDX_ACTIVE)
1175                                 ifmr->ifm_active |= IFM_FDX;
1176                         if (cs_readreg(sc, PP_AutoNegST) & HDX_ACTIVE)
1177                                 ifmr->ifm_active |= IFM_HDX;
1178                 }
1179                 ifmr->ifm_status = IFM_AVALID;
1180                 if (line_status & LINK_OK)
1181                         ifmr->ifm_status |= IFM_ACTIVE;
1182         } else {
1183                 if (line_status & AUI_ON) {
1184                         cs_writereg(sc, PP_SelfCTL, cs_readreg(sc, PP_SelfCTL) |
1185                             HCB1_ENBL);
1186                         if (((sc->adapter_cnf & A_CNF_DC_DC_POLARITY)!=0)^
1187                             (cs_readreg(sc, PP_SelfCTL) & HCB1))
1188                                 ifmr->ifm_active |= IFM_10_2;
1189                         else
1190                                 ifmr->ifm_active |= IFM_10_5;
1191                 }
1192         }
1193 }
1194
1195 static int
1196 cs_mediaset(struct cs_softc *sc, int media)
1197 {
1198         int error;
1199
1200         /* Stop the receiver & transmitter */
1201         cs_writereg(sc, PP_LineCTL, cs_readreg(sc, PP_LineCTL) &
1202             ~(SERIAL_RX_ON | SERIAL_TX_ON));
1203
1204 #ifdef CS_DEBUG
1205         if_printf(&sc->arpcom.ac_if, "cs_setmedia(%x)\n", media);
1206 #endif
1207
1208         switch (IFM_SUBTYPE(media)) {
1209         default:
1210         case IFM_AUTO:
1211                 if ((error=enable_tp(sc))==0)
1212                         error = cs_duplex_auto(sc);
1213                 else if ((error=enable_bnc(sc)) != 0)
1214                         error = enable_aui(sc);
1215                 break;
1216         case IFM_10_T:
1217                 if ((error=enable_tp(sc)) != 0)
1218                         break;
1219                 if (media & IFM_FDX)
1220                         cs_duplex_full(sc);
1221                 else if (media & IFM_HDX)
1222                         cs_duplex_half(sc);
1223                 else
1224                         error = cs_duplex_auto(sc);
1225                 break;
1226         case IFM_10_2:
1227                 error = enable_bnc(sc);
1228                 break;
1229         case IFM_10_5:
1230                 error = enable_aui(sc);
1231                 break;
1232         }
1233
1234         /*
1235          * Turn the transmitter & receiver back on
1236          */
1237         cs_writereg(sc, PP_LineCTL, cs_readreg(sc, PP_LineCTL) |
1238             SERIAL_RX_ON | SERIAL_TX_ON); 
1239
1240         return error;
1241 }