Deleted Added
full compact
if_cs.c (43314) if_cs.c (45720)
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/*
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/*
30 * $Id: if_cs.c,v 1.8 1999/01/12 00:27:43 eivind Exp $
30 * $Id: if_cs.c,v 1.9 1999/01/28 01:59:53 dillon Exp $
31 *
32 * Device driver for Crystal Semiconductor CS8920 based ethernet
33 * adapters. By Maxim Bolotin and Oleg Sharoiko, 27-April-1997
34 */
35
36/* #define CS_DEBUG */
37#include "cs.h"
38#include "bpfilter.h"
39
40#include <sys/param.h>
41#include <sys/systm.h>
42#include <sys/malloc.h>
43#include <sys/sockio.h>
44#include <sys/kernel.h>
45#include <sys/mbuf.h>
46#include <sys/socket.h>
47#include <sys/sysctl.h>
48#include <sys/syslog.h>
49
50#include <net/if.h>
51#include <net/if_arp.h>
52#include <net/if_media.h>
53#include <net/ethernet.h>
54
55#if NBPFILTER > 0
56#include <net/bpf.h>
57#endif
58
59#include <machine/clock.h>
60
61#include <i386/isa/isa_device.h>
62#include <i386/isa/if_csreg.h>
63
64#include "pnp.h"
65
66#if NPNP > 0
67#include <i386/isa/pnp.h>
68#endif
69
70#ifdef CS_USE_64K_DMA
71#define CS_DMA_BUFFER_SIZE 65536
72#else
73#define CS_DMA_BUFFER_SIZE 16384
74#endif
75
76/*
77 * cs_softc: per line info and status
78 */
79static struct cs_softc {
80
81 /* Ethernet common code */
82 struct arpcom arpcom;
83
84 /* Configuration words from EEPROM */
85 int auto_neg_cnf; /* AutoNegotitation configuration */
86 int adapter_cnf; /* Adapter configuration */
87 int isa_config; /* ISA configuration */
88 int chip_type; /* Type of chip */
89
90 struct ifmedia media; /* Media information */
91
92 int nic_addr; /* Base IO address of card */
93 int send_cmd;
94 int line_ctl; /* */
95 int send_underrun;
96 void *recv_ring;
97
98 unsigned char *buffer;
99 int buf_len;
100
101} cs_softc[NCS];
102
103#if NPNP > 0
104static u_long cs_unit = NCS;
105#endif
106
107static int cs_recv_delay = 570;
108SYSCTL_INT(_machdep, OID_AUTO, cs_recv_delay, CTLFLAG_RW, &cs_recv_delay, 0, "");
109
110static int cs_attach __P((struct cs_softc *, int, int));
111static int cs_attach_isa __P((struct isa_device *));
112static void cs_init __P((void *));
113static ointhand2_t csintr;
114static int cs_ioctl __P((struct ifnet *, u_long, caddr_t));
115static int cs_probe __P((struct isa_device *));
116static int cs_cs89x0_probe __P((struct cs_softc *,
117 u_int *, int *, int, int, int));
118static void cs_start __P((struct ifnet *));
119static void cs_stop __P((struct cs_softc *));
120static void cs_reset __P((struct cs_softc *));
121static void cs_watchdog __P((struct ifnet *));
122
123static int cs_mediachange __P((struct ifnet *));
124static void cs_mediastatus __P((struct ifnet *, struct ifmediareq *));
125static int cs_mediaset __P((struct cs_softc *, int));
126
127static void cs_write_mbufs(struct cs_softc*, struct mbuf*);
128static void cs_xmit_buf(struct cs_softc*);
129static int cs_get_packet(struct cs_softc*);
130static void cs_setmode(struct cs_softc*);
131
132static int get_eeprom_data(struct cs_softc *sc, int, int, int *);
133static int get_eeprom_cksum(int, int, int *);
134static int wait_eeprom_ready( struct cs_softc *);
135static void control_dc_dc( struct cs_softc *, int );
136static int send_test_pkt( struct cs_softc * );
137static int enable_tp(struct cs_softc *);
138static int enable_aui(struct cs_softc *);
139static int enable_bnc(struct cs_softc *);
140static int cs_duplex_auto(struct cs_softc *);
141
142struct isa_driver csdriver = {
143 cs_probe,
144 cs_attach_isa,
145 CS_NAME,
146 0
147};
148
149static int
150get_eeprom_data( struct cs_softc *sc, int off, int len, int *buffer)
151{
152 int i;
153
154#ifdef CS_DEBUG
155 printf(CS_NAME":EEPROM data from %x for %x:\n", off,len);
156#endif
157
158 for (i=0;i<len;i++) {
159 if (wait_eeprom_ready(sc) < 0) return -1;
160 /* Send command to EEPROM to read */
161 cs_writereg(sc->nic_addr, PP_EECMD, (off+i)|EEPROM_READ_CMD );
162 if (wait_eeprom_ready(sc)<0)
163 return -1;
164 buffer[i] = cs_readreg (sc->nic_addr, PP_EEData);
165
166#ifdef CS_DEBUG
167 printf("%02x %02x ",(unsigned char)buffer[i],
168 (unsigned char)buffer[i+1]);
169#endif
170 }
171
172#ifdef CS_DEBUG
173 printf("\n");
174#endif
175
176 return 0;
177}
178
179static int
180get_eeprom_cksum(int off, int len, int *buffer)
181{
182 int i,cksum=0;
183
184 for (i=0;i<len;i++)
185 cksum+=buffer[i];
186 cksum &= 0xffff;
187 if (cksum==0)
188 return 0;
189 return -1;
190}
191
192static int
193wait_eeprom_ready(struct cs_softc *sc)
194{
195 DELAY ( 30000 ); /* XXX should we do some checks here ? */
196 return 0;
197}
198
199static void
200control_dc_dc(struct cs_softc *sc, int on_not_off)
201{
202 unsigned int self_control = HCB1_ENBL;
203
204 if (((sc->adapter_cnf & A_CNF_DC_DC_POLARITY)!=0) ^ on_not_off)
205 self_control |= HCB1;
206 else
207 self_control &= ~HCB1;
208 cs_writereg( sc->nic_addr, PP_SelfCTL, self_control );
209
210 DELAY( 500000 );
211}
212
213
214static int
215cs_duplex_auto(struct cs_softc *sc)
216{
217 int i, error=0, unit=sc->arpcom.ac_if.if_unit;
218
219 cs_writereg(sc->nic_addr, PP_AutoNegCTL,
220 RE_NEG_NOW | ALLOW_FDX | AUTO_NEG_ENABLE );
221 for (i=0; cs_readreg(sc->nic_addr,PP_AutoNegST)&AUTO_NEG_BUSY; i++) {
222 if (i > 40000) {
223 printf(CS_NAME"%1d: full/half duplex "
224 "auto negotiation timeout\n", unit);
225 error = ETIMEDOUT;
226 break;
227 }
228 DELAY(1000);
229 }
230 DELAY( 1000000 );
231 return error;
232}
233
234static int
235enable_tp(struct cs_softc *sc)
236{
237 int unit = sc->arpcom.ac_if.if_unit;
238
239 cs_writereg(sc->nic_addr, PP_LineCTL, sc->line_ctl & ~AUI_ONLY);
240 control_dc_dc(sc, 0);
241 DELAY( 150000 );
242
243 if ((cs_readreg(sc->nic_addr, PP_LineST) & LINK_OK)==0) {
244 printf(CS_NAME"%1d: failed to enable TP\n", unit);
245 return EINVAL;
246 }
247
248 return 0;
249}
250
251/*
252 * XXX This was rewritten from Linux driver without any tests.
253 */
254static int
255send_test_pkt(struct cs_softc *sc)
256{
257 char test_packet[] = { 0,0,0,0,0,0, 0,0,0,0,0,0,
258 0, 46, /* A 46 in network order */
259 0, 0, /* DSAP=0 & SSAP=0 fields */
260 0xf3, 0 /* Control (Test Req + P bit set) */ };
261 int i;
262 u_char ether_address_backup[ETHER_ADDR_LEN];
263
264 for (i = 0; i < ETHER_ADDR_LEN; i++) {
265 ether_address_backup[i] = sc->arpcom.ac_enaddr[i];
266 }
267
268 cs_writereg(sc->nic_addr, PP_LineCTL,
269 cs_readreg(sc->nic_addr, PP_LineCTL) | SERIAL_TX_ON );
270 bcopy(test_packet,
271 sc->arpcom.ac_enaddr, ETHER_ADDR_LEN);
272 bcopy(test_packet+ETHER_ADDR_LEN,
273 sc->arpcom.ac_enaddr, ETHER_ADDR_LEN);
274 outw(sc->nic_addr + TX_CMD_PORT, sc->send_cmd);
275 outw(sc->nic_addr + TX_LEN_PORT, sizeof(test_packet));
276
277 /* Wait for chip to allocate memory */
278 DELAY(50000);
279 if (!(cs_readreg(sc->nic_addr, PP_BusST) & READY_FOR_TX_NOW)) {
280 for (i = 0; i < ETHER_ADDR_LEN; i++) {
281 sc->arpcom.ac_enaddr[i] = ether_address_backup[i];
282 }
283 return 0;
284 }
285
286 outsw(sc->nic_addr + TX_FRAME_PORT, test_packet, sizeof(test_packet));
287
288 DELAY(30000);
289
290 if ((cs_readreg(sc->nic_addr,PP_TxEvent) & TX_SEND_OK_BITS) == TX_OK) {
291 for (i = 0; i < ETHER_ADDR_LEN; i++) {
292 sc->arpcom.ac_enaddr[i] = ether_address_backup[i];
293 }
294 return 1;
295 }
296 for (i = 0; i < ETHER_ADDR_LEN; i++) {
297 sc->arpcom.ac_enaddr[i] = ether_address_backup[i];
298 }
299 return 0;
300}
301
302/*
303 * XXX This was rewritten from Linux driver without any tests.
304 */
305static int
306enable_aui(struct cs_softc *sc)
307{
308 int unit = sc->arpcom.ac_if.if_unit;
309
310 control_dc_dc(sc, 0);
311 cs_writereg(sc->nic_addr, PP_LineCTL,
312 (sc->line_ctl & ~AUTO_AUI_10BASET) | AUI_ONLY);
313
314 if (!send_test_pkt(sc)) {
315 printf(CS_NAME"%1d failed to enable AUI\n", unit);
316 return EINVAL;
317 }
318 return 0;
319}
320
321/*
322 * XXX This was rewritten from Linux driver without any tests.
323 */
324static int
325enable_bnc(struct cs_softc *sc)
326{
327 int unit = sc->arpcom.ac_if.if_unit;
328
329 control_dc_dc(sc, 1);
330 cs_writereg(sc->nic_addr, PP_LineCTL,
331 (sc->line_ctl & ~AUTO_AUI_10BASET) | AUI_ONLY);
332
333 if (!send_test_pkt(sc)) {
334 printf(CS_NAME"%1d failed to enable BNC\n", unit);
335 return EINVAL;
336 }
337 return 0;
338}
339
340static int
341cs_cs89x0_probe(struct cs_softc *sc, u_int *dev_irq,
342 int *dev_drq, int iobase, int unit, int flags)
343{
344 unsigned rev_type = 0;
345 int i, irq=0;
346 int eeprom_buff[CHKSUM_LEN];
347 int chip_type, pp_isaint, pp_isadma;
348 char chip_revision;
349
350 if ((inw(iobase+ADD_PORT) & ADD_MASK) != ADD_SIG) {
351 /* Chip not detected. Let's try to reset it */
352 if (bootverbose)
353 printf(CS_NAME"%1d: trying to reset the chip.\n", unit);
354 outw(iobase+ADD_PORT, PP_SelfCTL);
355 i = inw(iobase+DATA_PORT);
356 outw(iobase+ADD_PORT, PP_SelfCTL);
357 outw(iobase+DATA_PORT, i | POWER_ON_RESET);
358 if ((inw(iobase+ADD_PORT) & ADD_MASK) != ADD_SIG)
359 return 0;
360 }
361
362 outw(iobase+ADD_PORT, PP_ChipID);
363 if (inw(iobase+DATA_PORT) != CHIP_EISA_ID_SIG)
364 return 0;
365
366 rev_type = cs_readreg(iobase, PRODUCT_ID_ADD);
367 chip_type = rev_type & ~REVISON_BITS;
368 chip_revision = ((rev_type & REVISON_BITS) >> 8) + 'A';
369
370 sc->nic_addr = iobase;
371 sc->chip_type = chip_type;
372 if(chip_type==CS8900) {
373 pp_isaint = PP_CS8900_ISAINT;
374 pp_isadma = PP_CS8900_ISADMA;
375 sc->send_cmd = TX_CS8900_AFTER_ALL;
376 } else {
377 pp_isaint = PP_CS8920_ISAINT;
378 pp_isadma = PP_CS8920_ISADMA;
379 sc->send_cmd = TX_CS8920_AFTER_ALL;
380 }
381
382 /*
383 * Clear some fields so that fail of EEPROM will left them clean
384 */
385 sc->auto_neg_cnf = 0;
386 sc->adapter_cnf = 0;
387 sc->isa_config = 0;
388
389 /*
390 * EEPROM
391 */
392 if((cs_readreg(iobase, PP_SelfST) & EEPROM_PRESENT) == 0) {
393 printf(CS_NAME"%1d: No EEPROM, assuming defaults.\n",
394 unit);
395 } else {
396 if (get_eeprom_data(sc,START_EEPROM_DATA,CHKSUM_LEN, eeprom_buff)<0) {
397 printf(CS_NAME"%1d: EEPROM read failed, "
398 "assuming defaults..\n", unit);
399 } else {
400 if (get_eeprom_cksum(START_EEPROM_DATA,CHKSUM_LEN, eeprom_buff)<0) {
401 printf( CS_NAME"%1d: EEPROM cheksum bad, "
402 "assuming defaults..\n", unit );
403 } else {
404 sc->auto_neg_cnf =
405 eeprom_buff[AUTO_NEG_CNF_OFFSET/2];
406 sc->adapter_cnf =
407 eeprom_buff[ADAPTER_CNF_OFFSET/2];
408 sc->isa_config =
409 eeprom_buff[ISA_CNF_OFFSET/2];
410
411 for (i=0; i<ETHER_ADDR_LEN/2; i++) {
412 sc->arpcom.ac_enaddr[i*2]=
413 eeprom_buff[i];
414 sc->arpcom.ac_enaddr[i*2+1]=
415 eeprom_buff[i] >> 8;
416 }
417
418 /*
419 * If no interrupt specified (or "?"),
420 * use what the board tells us.
421 */
422 if (*dev_irq <= 0) {
423 irq = sc->isa_config & INT_NO_MASK;
424 if (chip_type==CS8900) {
425 switch(irq) {
426 case 0: irq=10; break;
427 case 1: irq=11; break;
428 case 2: irq=12; break;
429 case 3: irq=5; break;
430 default: printf(CS_NAME"%1d: invalid irq in EEPROM.\n",unit);
431 }
432 if (irq!=0)
433 *dev_irq=(u_short)(1<<irq);
434 } else {
435 if (irq!=0 && irq<=CS8920_NO_INTS)
436 *dev_irq=(u_short)(1<<irq);
437 }
438 }
439 }
440 }
441 }
442
443 if ((irq=ffs(*dev_irq))) {
444 irq--;
445 if (chip_type == CS8900) {
446 switch(irq) {
447 case 5: irq = 3; break;
448 case 10: irq = 0; break;
449 case 11: irq = 1; break;
450 case 12: irq = 2; break;
451 default: printf(CS_NAME"%1d: invalid irq\n", unit);
452 return 0;
453 }
454 } else {
455 if (irq > CS8920_NO_INTS) {
456 printf(CS_NAME"%1d: invalid irq\n", unit);
457 return 0;
458 }
459 }
460 cs_writereg(iobase, pp_isaint, irq);
461 } else {
462 printf(CS_NAME"%1d: invalid irq\n", unit);
463 return 0;
464 }
465
466 /*
467 * Temporary disabled
468 *
469 if (drq>0)
470 cs_writereg(iobase, pp_isadma, drq);
471 else {
472 printf( CS_NAME"%1d: incorrect drq\n", unit );
473 return 0;
474 }
475 */
476
477 if (bootverbose)
478 printf(CS_NAME"%1d: model CS89%c0%s rev %c\n"
479 CS_NAME"%1d: media%s%s%s\n"
480 CS_NAME"%1d: irq %d drq %d\n",
481 unit,
482 chip_type==CS8900 ? '0' : '2',
483 chip_type==CS8920M ? "M" : "",
484 chip_revision,
485 unit,
486 (sc->adapter_cnf & A_CNF_10B_T) ? " TP" : "",
487 (sc->adapter_cnf & A_CNF_AUI) ? " AUI" : "",
488 (sc->adapter_cnf & A_CNF_10B_2) ? " BNC" : "",
489 unit, (int)*dev_irq, (int)*dev_drq);
490
491 if ((sc->adapter_cnf & A_CNF_EXTND_10B_2) &&
492 (sc->adapter_cnf & A_CNF_LOW_RX_SQUELCH))
493 sc->line_ctl = LOW_RX_SQUELCH;
494 else
495 sc->line_ctl = 0;
496
497
498 return PP_ISAIOB;
499}
500
501/*
502 * Determine if the device is present
503 *
504 * on entry:
505 * a pointer to an isa_device struct
506 * on exit:
507 * NULL if device not found
508 * or # of i/o addresses used (if found)
509 */
510static int
511cs_probe(struct isa_device *dev)
512{
513 int nports;
514
515 struct cs_softc *sc=&cs_softc[dev->id_unit];
516
517 nports=cs_cs89x0_probe(sc, &(dev->id_irq), &(dev->id_drq),
518 (dev->id_iobase), (dev->id_unit), (dev->id_flags));
519
520 if (nports)
521 return (nports);
522
523 return (0);
524}
525
526/*
527 * Install the interface into kernel networking data structures
528 */
529static int
530cs_attach(struct cs_softc *sc, int unit, int flags)
531{
532 int media=0;
533/* struct cs_softc *sc = &cs_softc[dev->id_unit]; */
534 struct ifnet *ifp = &(sc->arpcom.ac_if);
535
536 if (!ifp->if_name) {
537 ifp->if_softc=sc;
538 ifp->if_unit=unit;
539 ifp->if_name=csdriver.name;
540 ifp->if_output=ether_output;
541 ifp->if_start=cs_start;
542 ifp->if_ioctl=cs_ioctl;
543 ifp->if_watchdog=cs_watchdog;
544 ifp->if_init=cs_init;
545 ifp->if_snd.ifq_maxlen= IFQ_MAXLEN;
546 /*
547 * MIB DATA
548 */
549 /*
550 ifp->if_linkmib=&sc->mibdata;
551 ifp->if_linkmiblen=sizeof sc->mibdata;
552 */
553
554 ifp->if_flags=(IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST );
555
556 /*
557 * this code still in progress (DMA support)
558 *
559
560 sc->recv_ring=malloc(CS_DMA_BUFFER_SIZE<<1, M_DEVBUF, M_NOWAIT);
561 if (sc->recv_ring == NULL) {
562 log(LOG_ERR,CS_NAME
563 "%d: Couldn't allocate memory for NIC\n", unit);
564 return(0);
565 }
566 if ((sc->recv_ring-(sc->recv_ring & 0x1FFFF))
567 < (128*1024-CS_DMA_BUFFER_SIZE))
568 sc->recv_ring+=16*1024;
569
570 */
571
572 sc->buffer=malloc(ETHER_MAX_LEN-ETHER_CRC_LEN,M_DEVBUF,M_NOWAIT);
573 if (sc->buffer == NULL) {
574 printf(CS_NAME"%d: Couldn't allocate memory for NIC\n",
575 unit);
576 return(0);
577 }
578
579 /*
580 * Initialize the media structures.
581 */
582 ifmedia_init(&sc->media, 0, cs_mediachange, cs_mediastatus);
583
584 if (sc->adapter_cnf & A_CNF_10B_T) {
585 ifmedia_add(&sc->media, IFM_ETHER|IFM_10_T, 0, NULL);
586 if (sc->chip_type != CS8900) {
587 ifmedia_add(&sc->media,
588 IFM_ETHER|IFM_10_T|IFM_FDX, 0, NULL);
589 ifmedia_add(&sc->media,
590 IFM_ETHER|IFM_10_T|IFM_HDX, 0, NULL);
591 }
592 }
593
594 if (sc->adapter_cnf & A_CNF_10B_2)
595 ifmedia_add(&sc->media, IFM_ETHER|IFM_10_2, 0, NULL);
596
597 if (sc->adapter_cnf & A_CNF_AUI)
598 ifmedia_add(&sc->media, IFM_ETHER|IFM_10_5, 0, NULL);
599
600 if (sc->adapter_cnf & A_CNF_MEDIA)
601 ifmedia_add(&sc->media, IFM_ETHER|IFM_AUTO, 0, NULL);
602
603 /* Set default media from EEPROM */
604 switch (sc->adapter_cnf & A_CNF_MEDIA_TYPE) {
605 case A_CNF_MEDIA_AUTO: media = IFM_ETHER|IFM_AUTO; break;
606 case A_CNF_MEDIA_10B_T: media = IFM_ETHER|IFM_10_T; break;
607 case A_CNF_MEDIA_10B_2: media = IFM_ETHER|IFM_10_2; break;
608 case A_CNF_MEDIA_AUI: media = IFM_ETHER|IFM_10_5; break;
609 default: printf(CS_NAME"%d: adapter has no media\n", unit);
610 }
611 ifmedia_set(&sc->media, media);
612 cs_mediaset(sc, media);
613
614 if_attach(ifp);
615 cs_stop( sc );
616 ether_ifattach(ifp);
617 }
618
619 if (bootverbose)
620 printf(CS_NAME"%d: ethernet address %6D\n",
621 ifp->if_unit, sc->arpcom.ac_enaddr, ":");
622
623#if NBPFILTER > 0
624 bpfattach(ifp, DLT_EN10MB, sizeof (struct ether_header));
625#endif
626 return 1;
627}
628
629static int
630cs_attach_isa(struct isa_device *dev)
631{
632 int unit=dev->id_unit;
633 struct cs_softc *sc=&cs_softc[unit];
634 int flags=dev->id_flags;
635
636 dev->id_ointr = csintr;
637 return cs_attach(sc, unit, flags);
638}
639
640/*
641 * Initialize the board
642 */
643static void
644cs_init(void *xsc)
645{
646 struct cs_softc *sc=(struct cs_softc *)xsc;
647 struct ifnet *ifp = &sc->arpcom.ac_if;
648 int i, s, rx_cfg;
649
650 /* address not known */
651 if (TAILQ_EMPTY(&ifp->if_addrhead)) /* unlikely? XXX */
652 return;
653
654 /*
655 * reset whatchdog timer
656 */
657 ifp->if_timer=0;
658 sc->buf_len = 0;
659
660 s=splimp();
661
662 /*
663 * Hardware initialization of cs
664 */
665
666 /* Enable receiver and transmitter */
667 cs_writereg(sc->nic_addr, PP_LineCTL,
668 cs_readreg( sc->nic_addr, PP_LineCTL ) |
669 SERIAL_RX_ON | SERIAL_TX_ON);
670
671 /* Configure the receiver mode */
672 cs_setmode(sc);
673
674 /*
675 * This defines what type of frames will cause interrupts
676 * Bad frames should generate interrupts so that the driver
677 * could track statistics of discarded packets
678 */
679 rx_cfg = RX_OK_ENBL | RX_CRC_ERROR_ENBL | RX_RUNT_ENBL |
680 RX_EXTRA_DATA_ENBL;
681 if (sc->isa_config & STREAM_TRANSFER)
682 rx_cfg |= RX_STREAM_ENBL;
683 cs_writereg(sc->nic_addr, PP_RxCFG, rx_cfg);
684
685 cs_writereg(sc->nic_addr, PP_TxCFG, TX_LOST_CRS_ENBL |
686 TX_SQE_ERROR_ENBL | TX_OK_ENBL | TX_LATE_COL_ENBL |
687 TX_JBR_ENBL | TX_ANY_COL_ENBL | TX_16_COL_ENBL);
688
689 cs_writereg(sc->nic_addr, PP_BufCFG, READY_FOR_TX_ENBL |
690 RX_MISS_COUNT_OVRFLOW_ENBL | TX_COL_COUNT_OVRFLOW_ENBL |
691 TX_UNDERRUN_ENBL /*| RX_DMA_ENBL*/);
692
693 /* Write MAC address into IA filter */
694 for (i=0; i<ETHER_ADDR_LEN/2; i++)
695 cs_writereg(sc->nic_addr, PP_IA+i*2,
696 sc->arpcom.ac_enaddr[i*2] |
697 (sc->arpcom.ac_enaddr[i*2+1] << 8) );
698
699 /*
700 * Now enable everything
701 */
702/*
703#ifdef CS_USE_64K_DMA
704 cs_writereg(sc->nic_addr, PP_BusCTL, ENABLE_IRQ | RX_DMA_SIZE_64K);
705 #else
706
707 cs_writereg(sc->nic_addr, PP_BusCTL, ENABLE_IRQ);
708#endif
709*/
710 cs_writereg(sc->nic_addr, PP_BusCTL, ENABLE_IRQ);
711
712 /*
713 * Set running and clear output active flags
714 */
715 sc->arpcom.ac_if.if_flags |= IFF_RUNNING;
716 sc->arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
717
718 /*
719 * Start sending process
720 */
721 cs_start(ifp);
722
723 (void) splx(s);
724}
725
726/*
727 * Get the packet from the board and send it to the upper layer
728 * via ether_input().
729 */
730static int
731cs_get_packet(struct cs_softc *sc)
732{
733 struct ifnet *ifp = &(sc->arpcom.ac_if);
734 int iobase = sc->nic_addr, status, length;
735 struct ether_header *eh;
736 struct mbuf *m;
737
738#ifdef CS_DEBUG
739 int i;
740#endif
741
742 status = inw(iobase + RX_FRAME_PORT);
743 length = inw(iobase + RX_FRAME_PORT);
744
745#ifdef CS_DEBUG
746 printf(CS_NAME"%1d: rcvd: stat %x, len %d\n",
747 ifp->if_unit, status, length);
748#endif
749
750 if (!(status & RX_OK)) {
751#ifdef CS_DEBUG
752 printf(CS_NAME"%1d: bad pkt stat %x\n", ifp->if_unit, status);
753#endif
754 ifp->if_ierrors++;
755 return -1;
756 }
757
758 MGETHDR(m, M_DONTWAIT, MT_DATA);
759 if (m==NULL)
760 return -1;
761
762 if (length > MHLEN) {
763 MCLGET(m, M_DONTWAIT);
764 if (!(m->m_flags & M_EXT)) {
765 m_freem(m);
766 return -1;
767 }
768 }
769
770 /* Initialize packet's header info */
771 m->m_pkthdr.rcvif = ifp;
772 m->m_pkthdr.len = length;
773 m->m_len = length;
774
775 /* Get the data */
776 insw(iobase + RX_FRAME_PORT, m->m_data, (length+1)>>1);
777
778 eh = mtod(m, struct ether_header *);
779
780#if NBPFILTER > 0
781 if (ifp->if_bpf)
782 bpf_mtap(ifp, m);
783#endif
784
785#ifdef CS_DEBUG
786 for (i=0;i<length;i++)
787 printf(" %02x",(unsigned char)*((char *)(m->m_data+i)));
788 printf( "\n" );
789#endif
790
791 if (status & (RX_IA | RX_BROADCAST) ||
792 (ifp->if_flags & IFF_MULTICAST && status & RX_HASHED)) {
793 m->m_pkthdr.len -= sizeof(struct ether_header);
794 m->m_len -= sizeof(struct ether_header);
795 m->m_data += sizeof(struct ether_header);
796
797 /* Feed the packet to the upper layer */
798 ether_input(ifp, eh, m);
799
800 ifp->if_ipackets++;
801
802 if (length==ETHER_MAX_LEN-ETHER_CRC_LEN)
803 DELAY( cs_recv_delay );
804 } else {
805 m_freem(m);
806 }
807
808 return 0;
809}
810
811/*
812 * Software calls interrupt handler
813 */
814static void
815csintr_sc(struct cs_softc *sc, int unit)
816{
817 struct ifnet *ifp = &(sc->arpcom.ac_if);
818 int status;
819
820#ifdef CS_DEBUG
821 printf(CS_NAME"%1d: Interrupt.\n", unit);
822#endif
823
824 while ((status=cs_readword(sc->nic_addr, ISQ_PORT))) {
825
826#ifdef CS_DEBUG
827 printf( CS_NAME"%1d:from ISQ: %04x\n", unit, status );
828#endif
829
830 switch (status & ISQ_EVENT_MASK) {
831 case ISQ_RECEIVER_EVENT:
832 cs_get_packet(sc);
833 break;
834
835 case ISQ_TRANSMITTER_EVENT:
836 if (status & TX_OK)
837 ifp->if_opackets++;
838 else
839 ifp->if_oerrors++;
840 ifp->if_flags &= ~IFF_OACTIVE;
841 ifp->if_timer = 0;
842 break;
843
844 case ISQ_BUFFER_EVENT:
845 if (status & READY_FOR_TX) {
846 ifp->if_flags &= ~IFF_OACTIVE;
847 ifp->if_timer = 0;
848 }
849
850 if (status & TX_UNDERRUN) {
851 ifp->if_flags &= ~IFF_OACTIVE;
852 ifp->if_timer = 0;
853 ifp->if_oerrors++;
854 }
855 break;
856
857 case ISQ_RX_MISS_EVENT:
858 ifp->if_ierrors+=(status>>6);
859 break;
860
861 case ISQ_TX_COL_EVENT:
862 ifp->if_collisions+=(status>>6);
863 break;
864 }
865 }
866
867 if (!(ifp->if_flags & IFF_OACTIVE)) {
868 cs_start(ifp);
869 }
870}
871
872/*
873 * Handle interrupts
874 */
875static void
876csintr(int unit)
877{
878 struct cs_softc *sc = &cs_softc[unit];
879
880 csintr_sc(sc, unit);
881}
882
883/*
884 * Save the data in buffer
885 */
886
887static void
888cs_write_mbufs( struct cs_softc *sc, struct mbuf *m )
889{
890 int len;
891 struct mbuf *mp;
892 unsigned char *data, *buf;
893
894 for (mp=m, buf=sc->buffer, sc->buf_len=0; mp != NULL; mp=mp->m_next) {
895 len = mp->m_len;
896
897 /*
898 * Ignore empty parts
899 */
900 if (!len)
901 continue;
902
903 /*
904 * Find actual data address
905 */
906 data = mtod(mp, caddr_t);
907
908 bcopy((caddr_t) data, (caddr_t) buf, len);
909 buf += len;
910 sc->buf_len += len;
911 }
912}
913
914
915static void
916cs_xmit_buf( struct cs_softc *sc )
917{
918 outsw(sc->nic_addr+TX_FRAME_PORT, sc->buffer, (sc->buf_len+1)>>1);
919 sc->buf_len = 0;
920}
921
922static void
923cs_start(struct ifnet *ifp)
924{
925 int s, length;
926 struct mbuf *m, *mp;
927 struct cs_softc *sc = ifp->if_softc;
928
929 s = splimp();
930
931 for (;;) {
932 if (sc->buf_len)
933 length = sc->buf_len;
934 else {
935 IF_DEQUEUE( &ifp->if_snd, m );
936
937 if (m==NULL) {
938 (void) splx(s);
939 return;
940 }
941
942 for (length=0, mp=m; mp != NULL; mp=mp->m_next)
943 length += mp->m_len;
944
945 /* Skip zero-length packets */
946 if (length == 0) {
947 m_freem(m);
948 continue;
949 }
950
951 cs_write_mbufs(sc, m);
952
953#if NBPFILTER > 0
954 if (ifp->if_bpf) {
955 bpf_mtap(ifp, m);
956 }
957#endif
958
959 m_freem(m);
960 }
961
962 /*
963 * Issue a SEND command
964 */
965 outw(sc->nic_addr+TX_CMD_PORT, sc->send_cmd);
966 outw(sc->nic_addr+TX_LEN_PORT, length );
967
968 /*
969 * If there's no free space in the buffer then leave
970 * this packet for the next time: indicate output active
971 * and return.
972 */
973 if (!(cs_readreg(sc->nic_addr, PP_BusST) & READY_FOR_TX_NOW)) {
974 ifp->if_timer = sc->buf_len;
975 (void) splx(s);
976 ifp->if_flags |= IFF_OACTIVE;
977 return;
978 }
979
980 cs_xmit_buf(sc);
981
982 /*
983 * Set the watchdog timer in case we never hear
984 * from board again. (I don't know about correct
985 * value for this timeout)
986 */
987 ifp->if_timer = length;
988
989 (void) splx(s);
990 ifp->if_flags |= IFF_OACTIVE;
991 return;
992 }
993}
994
995/*
996 * Stop everything on the interface
997 */
998static void
999cs_stop(struct cs_softc *sc)
1000{
1001 int s = splimp();
1002
1003 cs_writereg(sc->nic_addr, PP_RxCFG, 0);
1004 cs_writereg(sc->nic_addr, PP_TxCFG, 0);
1005 cs_writereg(sc->nic_addr, PP_BufCFG, 0);
1006 cs_writereg(sc->nic_addr, PP_BusCTL, 0);
1007
1008 sc->arpcom.ac_if.if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
1009 sc->arpcom.ac_if.if_timer = 0;
1010
1011 (void) splx(s);
1012}
1013
1014/*
1015 * Reset the interface
1016 */
1017static void
1018cs_reset(struct cs_softc *sc)
1019{
1020 cs_stop(sc);
1021 cs_init(sc);
1022}
1023
1024static void
1025cs_setmode(struct cs_softc *sc)
1026{
1027 struct ifnet *ifp = &(sc->arpcom.ac_if);
1028 int rx_ctl;
1029
1030 /* Stop the receiver while changing filters */
1031 cs_writereg(sc->nic_addr, PP_LineCTL,
1032 cs_readreg(sc->nic_addr, PP_LineCTL) & ~SERIAL_RX_ON);
1033
1034 if (ifp->if_flags & IFF_PROMISC) {
1035 /* Turn on promiscuous mode. */
1036 rx_ctl = RX_OK_ACCEPT | RX_PROM_ACCEPT;
1037 } else {
1038 if (ifp->if_flags & IFF_MULTICAST) {
1039 /* Allow receiving frames with multicast addresses */
1040 rx_ctl = RX_IA_ACCEPT | RX_BROADCAST_ACCEPT |
1041 RX_OK_ACCEPT | RX_MULTCAST_ACCEPT;
1042 /*
1043 * Here the reconfiguration of chip's multicast
1044 * filters should be done but I've no idea about
1045 * hash transformation in this chip. If you can
1046 * add this code or describe me the transformation
1047 * I'd be very glad.
1048 */
1049 } else {
1050 /*
1051 * Receive only good frames addressed for us and
1052 * good broadcasts.
1053 */
1054 rx_ctl = RX_IA_ACCEPT | RX_BROADCAST_ACCEPT |
1055 RX_OK_ACCEPT;
1056 }
1057 }
1058
1059 /* Set up the filter */
1060 cs_writereg(sc->nic_addr, PP_RxCTL, RX_DEF_ACCEPT | rx_ctl);
1061
1062 /* Turn on receiver */
1063 cs_writereg(sc->nic_addr, PP_LineCTL,
1064 cs_readreg(sc->nic_addr, PP_LineCTL) | SERIAL_RX_ON);
1065}
1066
1067static int
1068cs_ioctl(register struct ifnet *ifp, u_long command, caddr_t data)
1069{
1070 struct cs_softc *sc=ifp->if_softc;
1071 struct ifreq *ifr = (struct ifreq *)data;
1072 int s,error=0;
1073
1074#ifdef CS_DEBUG
1075 printf(CS_NAME"%d: ioctl(%x)\n",sc->arpcom.ac_if.if_unit,command);
1076#endif
1077
1078 s=splimp();
1079
1080 switch (command) {
1081 case SIOCSIFADDR:
1082 case SIOCGIFADDR:
1083 case SIOCSIFMTU:
1084 ether_ioctl(ifp, command, data);
1085 break;
1086
1087 case SIOCSIFFLAGS:
1088 /*
1089 * Switch interface state between "running" and
1090 * "stopped", reflecting the UP flag.
1091 */
1092 if (sc->arpcom.ac_if.if_flags & IFF_UP) {
1093 if ((sc->arpcom.ac_if.if_flags & IFF_RUNNING)==0) {
1094 cs_init(sc);
1095 }
1096 } else {
1097 if ((sc->arpcom.ac_if.if_flags & IFF_RUNNING)!=0) {
1098 cs_stop(sc);
1099 }
1100 }
1101 /*
1102 * Promiscuous and/or multicast flags may have changed,
1103 * so reprogram the multicast filter and/or receive mode.
1104 *
1105 * See note about multicasts in cs_setmode
1106 */
1107 cs_setmode(sc);
1108 break;
1109
1110 case SIOCADDMULTI:
1111 case SIOCDELMULTI:
1112 /*
1113 * Multicast list has changed; set the hardware filter
1114 * accordingly.
1115 *
1116 * See note about multicasts in cs_setmode
1117 */
1118 cs_setmode(sc);
1119 error = 0;
1120 break;
1121
1122 case SIOCSIFMEDIA:
1123 case SIOCGIFMEDIA:
1124 error = ifmedia_ioctl(ifp, ifr, &sc->media, command);
1125 break;
1126
1127 default:
1128 error = EINVAL;
1129 }
1130
1131 (void) splx(s);
1132 return error;
1133}
1134
1135/*
1136 * Device timeout/watchdog routine. Entered if the device neglects to
1137 * generate an interrupt after a transmit has been started on it.
1138 */
1139static void
1140cs_watchdog(struct ifnet *ifp)
1141{
1142 struct cs_softc *sc = &cs_softc[ifp->if_unit];
1143
1144 ifp->if_oerrors++;
1145 log(LOG_ERR, CS_NAME"%d: device timeout\n", ifp->if_unit);
1146
1147 /* Reset the interface */
1148 if (ifp->if_flags & IFF_UP)
1149 cs_reset(sc);
1150 else
1151 cs_stop(sc);
1152}
1153
1154static int
1155cs_mediachange(struct ifnet *ifp)
1156{
1157 struct cs_softc *sc = ifp->if_softc;
1158 struct ifmedia *ifm = &sc->media;
1159
1160 if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER)
1161 return EINVAL;
1162
1163 return cs_mediaset(sc, ifm->ifm_media);
1164}
1165
1166static void
1167cs_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr)
1168{
1169 int line_status;
1170 struct cs_softc *sc = ifp->if_softc;
1171
1172 ifmr->ifm_active = IFM_ETHER;
1173 line_status = cs_readreg(sc->nic_addr, PP_LineST);
1174 if (line_status & TENBASET_ON) {
1175 ifmr->ifm_active |= IFM_10_T;
1176 if (sc->chip_type != CS8900) {
1177 if (cs_readreg(sc->nic_addr, PP_AutoNegST) & FDX_ACTIVE)
1178 ifmr->ifm_active |= IFM_FDX;
1179 if (cs_readreg(sc->nic_addr, PP_AutoNegST) & HDX_ACTIVE)
1180 ifmr->ifm_active |= IFM_HDX;
1181 }
1182 ifmr->ifm_status = IFM_AVALID;
1183 if (line_status & LINK_OK)
1184 ifmr->ifm_status |= IFM_ACTIVE;
1185 } else {
1186 if (line_status & AUI_ON) {
1187 cs_writereg(sc->nic_addr, PP_SelfCTL,
1188 cs_readreg(sc->nic_addr, PP_SelfCTL) |
1189 HCB1_ENBL);
1190 if (((sc->adapter_cnf & A_CNF_DC_DC_POLARITY)!=0)^
1191 (cs_readreg(sc->nic_addr, PP_SelfCTL)&HCB1))
1192 ifmr->ifm_active |= IFM_10_2;
1193 else
1194 ifmr->ifm_active |= IFM_10_5;
1195 }
1196 }
1197}
1198
1199static int
1200cs_mediaset(struct cs_softc *sc, int media)
1201{
1202 int error;
1203
1204 /* Stop the receiver & transmitter */
1205 cs_writereg(sc->nic_addr, PP_LineCTL,
1206 cs_readreg(sc->nic_addr, PP_LineCTL) &
1207 ~(SERIAL_RX_ON | SERIAL_TX_ON));
1208
1209#ifdef CS_DEBUG
1210 printf(CS_NAME"%d: cs_setmedia(%x)\n",sc->arpcom.ac_if.if_unit,media);
1211#endif
1212
1213 switch (IFM_SUBTYPE(media)) {
1214 default:
1215 case IFM_AUTO:
1216 if ((error=enable_tp(sc))==0)
1217 error = cs_duplex_auto(sc);
1218 else if ((error=enable_bnc(sc)) != 0)
1219 error = enable_aui(sc);
1220 break;
1221 case IFM_10_T:
1222 if ((error=enable_tp(sc)) != 0)
1223 break;
1224 if (media & IFM_FDX)
1225 cs_duplex_full(sc);
1226 else if (media & IFM_HDX)
1227 cs_duplex_half(sc);
1228 else
1229 error = cs_duplex_auto(sc);
1230 break;
1231 case IFM_10_2:
1232 error = enable_bnc(sc);
1233 break;
1234 case IFM_10_5:
1235 error = enable_aui(sc);
1236 break;
1237 }
1238
1239 /*
1240 * Turn the transmitter & receiver back on
1241 */
1242 cs_writereg(sc->nic_addr, PP_LineCTL,
1243 cs_readreg( sc->nic_addr, PP_LineCTL ) |
1244 SERIAL_RX_ON | SERIAL_TX_ON);
1245
1246 return error;
1247}
1248
1249
1250#if NPNP > 0
1251
1252static struct cspnp_ids {
1253 u_long vend_id;
1254 char *id_str;
1255} cspnp_ids[]= {
1256 { 0x4060630e, "CSC6040" },
1257 { 0x10104d24, "IBM EtherJet" },
1258 { 0 }
1259};
1260
1261static char *cs_pnp_probe(u_long, u_long);
1262static void cs_pnp_attach(u_long, u_long, char *, struct isa_device *);
1263
1264struct pnp_device cs_pnp = {
1265 "CS8920 based PnP Ethernet",
1266 cs_pnp_probe,
1267 cs_pnp_attach,
1268 &cs_unit,
1269 &net_imask /* imask */
1270};
1271
1272DATA_SET (pnpdevice_set, cs_pnp);
1273
1274struct csintr_list {
1275 struct cs_softc *sc;
1276 int unit;
1277 struct csintr_list *next;
1278};
1279
1280static struct csintr_list *csintr_head;
1281
1282static void csintr_pnp_add(struct cs_softc *sc, int unit);
1283static void csintr_pnp(int unit);
1284
1285static void
1286csintr_pnp_add(struct cs_softc *sc, int unit)
1287{
1288 struct csintr_list *intr;
1289
1290 if (!sc) return;
1291
1292 intr = malloc (sizeof (*intr), M_DEVBUF, M_WAITOK);
1293 if (!intr) return;
1294
1295 intr->sc = sc;
1296 intr->unit = unit;
1297 intr->next = csintr_head;
1298 csintr_head = intr;
1299}
1300
1301/*
1302 * Interrupt handler for PNP installed card
1303 * We have to find the number of the card.
1304 */
1305static void
1306csintr_pnp(int unit)
1307{
1308 struct csintr_list *intr;
1309
1310 for (intr=csintr_head; intr; intr=intr->next) {
1311 if (intr->unit == unit)
1312 csintr_sc(intr->sc, unit);
1313 break;
1314 }
1315}
1316
1317static char *
1318cs_pnp_probe(u_long csn, u_long vend_id)
1319{
1320 struct cspnp_ids *ids;
1321 char *s=NULL;
1322
1323 for(ids = cspnp_ids; ids->vend_id != 0; ids++) {
1324 if (vend_id == ids->vend_id) {
1325 s = ids->id_str;
1326 break;
1327 }
1328 }
1329
1330 if (s) {
1331 struct pnp_cinfo d;
1332 int ldn = 0;
1333
1334 read_pnp_parms(&d, ldn);
1335 if (d.enable == 0) {
1336 printf("This is a %s, but LDN %d is disabled\n", s, ldn);
1337 return NULL ;
1338 }
1339 return s;
1340 }
1341
1342 return NULL ;
1343}
1344
1345static void
1346cs_pnp_attach(u_long csn, u_long vend_id, char *name,
1347 struct isa_device *dev)
1348{
1349
1350 struct pnp_cinfo d;
1351 int ldn = 0;
1352 int iobase, unit, flags;
1353 u_int irq;
1354 int drq;
31 *
32 * Device driver for Crystal Semiconductor CS8920 based ethernet
33 * adapters. By Maxim Bolotin and Oleg Sharoiko, 27-April-1997
34 */
35
36/* #define CS_DEBUG */
37#include "cs.h"
38#include "bpfilter.h"
39
40#include <sys/param.h>
41#include <sys/systm.h>
42#include <sys/malloc.h>
43#include <sys/sockio.h>
44#include <sys/kernel.h>
45#include <sys/mbuf.h>
46#include <sys/socket.h>
47#include <sys/sysctl.h>
48#include <sys/syslog.h>
49
50#include <net/if.h>
51#include <net/if_arp.h>
52#include <net/if_media.h>
53#include <net/ethernet.h>
54
55#if NBPFILTER > 0
56#include <net/bpf.h>
57#endif
58
59#include <machine/clock.h>
60
61#include <i386/isa/isa_device.h>
62#include <i386/isa/if_csreg.h>
63
64#include "pnp.h"
65
66#if NPNP > 0
67#include <i386/isa/pnp.h>
68#endif
69
70#ifdef CS_USE_64K_DMA
71#define CS_DMA_BUFFER_SIZE 65536
72#else
73#define CS_DMA_BUFFER_SIZE 16384
74#endif
75
76/*
77 * cs_softc: per line info and status
78 */
79static struct cs_softc {
80
81 /* Ethernet common code */
82 struct arpcom arpcom;
83
84 /* Configuration words from EEPROM */
85 int auto_neg_cnf; /* AutoNegotitation configuration */
86 int adapter_cnf; /* Adapter configuration */
87 int isa_config; /* ISA configuration */
88 int chip_type; /* Type of chip */
89
90 struct ifmedia media; /* Media information */
91
92 int nic_addr; /* Base IO address of card */
93 int send_cmd;
94 int line_ctl; /* */
95 int send_underrun;
96 void *recv_ring;
97
98 unsigned char *buffer;
99 int buf_len;
100
101} cs_softc[NCS];
102
103#if NPNP > 0
104static u_long cs_unit = NCS;
105#endif
106
107static int cs_recv_delay = 570;
108SYSCTL_INT(_machdep, OID_AUTO, cs_recv_delay, CTLFLAG_RW, &cs_recv_delay, 0, "");
109
110static int cs_attach __P((struct cs_softc *, int, int));
111static int cs_attach_isa __P((struct isa_device *));
112static void cs_init __P((void *));
113static ointhand2_t csintr;
114static int cs_ioctl __P((struct ifnet *, u_long, caddr_t));
115static int cs_probe __P((struct isa_device *));
116static int cs_cs89x0_probe __P((struct cs_softc *,
117 u_int *, int *, int, int, int));
118static void cs_start __P((struct ifnet *));
119static void cs_stop __P((struct cs_softc *));
120static void cs_reset __P((struct cs_softc *));
121static void cs_watchdog __P((struct ifnet *));
122
123static int cs_mediachange __P((struct ifnet *));
124static void cs_mediastatus __P((struct ifnet *, struct ifmediareq *));
125static int cs_mediaset __P((struct cs_softc *, int));
126
127static void cs_write_mbufs(struct cs_softc*, struct mbuf*);
128static void cs_xmit_buf(struct cs_softc*);
129static int cs_get_packet(struct cs_softc*);
130static void cs_setmode(struct cs_softc*);
131
132static int get_eeprom_data(struct cs_softc *sc, int, int, int *);
133static int get_eeprom_cksum(int, int, int *);
134static int wait_eeprom_ready( struct cs_softc *);
135static void control_dc_dc( struct cs_softc *, int );
136static int send_test_pkt( struct cs_softc * );
137static int enable_tp(struct cs_softc *);
138static int enable_aui(struct cs_softc *);
139static int enable_bnc(struct cs_softc *);
140static int cs_duplex_auto(struct cs_softc *);
141
142struct isa_driver csdriver = {
143 cs_probe,
144 cs_attach_isa,
145 CS_NAME,
146 0
147};
148
149static int
150get_eeprom_data( struct cs_softc *sc, int off, int len, int *buffer)
151{
152 int i;
153
154#ifdef CS_DEBUG
155 printf(CS_NAME":EEPROM data from %x for %x:\n", off,len);
156#endif
157
158 for (i=0;i<len;i++) {
159 if (wait_eeprom_ready(sc) < 0) return -1;
160 /* Send command to EEPROM to read */
161 cs_writereg(sc->nic_addr, PP_EECMD, (off+i)|EEPROM_READ_CMD );
162 if (wait_eeprom_ready(sc)<0)
163 return -1;
164 buffer[i] = cs_readreg (sc->nic_addr, PP_EEData);
165
166#ifdef CS_DEBUG
167 printf("%02x %02x ",(unsigned char)buffer[i],
168 (unsigned char)buffer[i+1]);
169#endif
170 }
171
172#ifdef CS_DEBUG
173 printf("\n");
174#endif
175
176 return 0;
177}
178
179static int
180get_eeprom_cksum(int off, int len, int *buffer)
181{
182 int i,cksum=0;
183
184 for (i=0;i<len;i++)
185 cksum+=buffer[i];
186 cksum &= 0xffff;
187 if (cksum==0)
188 return 0;
189 return -1;
190}
191
192static int
193wait_eeprom_ready(struct cs_softc *sc)
194{
195 DELAY ( 30000 ); /* XXX should we do some checks here ? */
196 return 0;
197}
198
199static void
200control_dc_dc(struct cs_softc *sc, int on_not_off)
201{
202 unsigned int self_control = HCB1_ENBL;
203
204 if (((sc->adapter_cnf & A_CNF_DC_DC_POLARITY)!=0) ^ on_not_off)
205 self_control |= HCB1;
206 else
207 self_control &= ~HCB1;
208 cs_writereg( sc->nic_addr, PP_SelfCTL, self_control );
209
210 DELAY( 500000 );
211}
212
213
214static int
215cs_duplex_auto(struct cs_softc *sc)
216{
217 int i, error=0, unit=sc->arpcom.ac_if.if_unit;
218
219 cs_writereg(sc->nic_addr, PP_AutoNegCTL,
220 RE_NEG_NOW | ALLOW_FDX | AUTO_NEG_ENABLE );
221 for (i=0; cs_readreg(sc->nic_addr,PP_AutoNegST)&AUTO_NEG_BUSY; i++) {
222 if (i > 40000) {
223 printf(CS_NAME"%1d: full/half duplex "
224 "auto negotiation timeout\n", unit);
225 error = ETIMEDOUT;
226 break;
227 }
228 DELAY(1000);
229 }
230 DELAY( 1000000 );
231 return error;
232}
233
234static int
235enable_tp(struct cs_softc *sc)
236{
237 int unit = sc->arpcom.ac_if.if_unit;
238
239 cs_writereg(sc->nic_addr, PP_LineCTL, sc->line_ctl & ~AUI_ONLY);
240 control_dc_dc(sc, 0);
241 DELAY( 150000 );
242
243 if ((cs_readreg(sc->nic_addr, PP_LineST) & LINK_OK)==0) {
244 printf(CS_NAME"%1d: failed to enable TP\n", unit);
245 return EINVAL;
246 }
247
248 return 0;
249}
250
251/*
252 * XXX This was rewritten from Linux driver without any tests.
253 */
254static int
255send_test_pkt(struct cs_softc *sc)
256{
257 char test_packet[] = { 0,0,0,0,0,0, 0,0,0,0,0,0,
258 0, 46, /* A 46 in network order */
259 0, 0, /* DSAP=0 & SSAP=0 fields */
260 0xf3, 0 /* Control (Test Req + P bit set) */ };
261 int i;
262 u_char ether_address_backup[ETHER_ADDR_LEN];
263
264 for (i = 0; i < ETHER_ADDR_LEN; i++) {
265 ether_address_backup[i] = sc->arpcom.ac_enaddr[i];
266 }
267
268 cs_writereg(sc->nic_addr, PP_LineCTL,
269 cs_readreg(sc->nic_addr, PP_LineCTL) | SERIAL_TX_ON );
270 bcopy(test_packet,
271 sc->arpcom.ac_enaddr, ETHER_ADDR_LEN);
272 bcopy(test_packet+ETHER_ADDR_LEN,
273 sc->arpcom.ac_enaddr, ETHER_ADDR_LEN);
274 outw(sc->nic_addr + TX_CMD_PORT, sc->send_cmd);
275 outw(sc->nic_addr + TX_LEN_PORT, sizeof(test_packet));
276
277 /* Wait for chip to allocate memory */
278 DELAY(50000);
279 if (!(cs_readreg(sc->nic_addr, PP_BusST) & READY_FOR_TX_NOW)) {
280 for (i = 0; i < ETHER_ADDR_LEN; i++) {
281 sc->arpcom.ac_enaddr[i] = ether_address_backup[i];
282 }
283 return 0;
284 }
285
286 outsw(sc->nic_addr + TX_FRAME_PORT, test_packet, sizeof(test_packet));
287
288 DELAY(30000);
289
290 if ((cs_readreg(sc->nic_addr,PP_TxEvent) & TX_SEND_OK_BITS) == TX_OK) {
291 for (i = 0; i < ETHER_ADDR_LEN; i++) {
292 sc->arpcom.ac_enaddr[i] = ether_address_backup[i];
293 }
294 return 1;
295 }
296 for (i = 0; i < ETHER_ADDR_LEN; i++) {
297 sc->arpcom.ac_enaddr[i] = ether_address_backup[i];
298 }
299 return 0;
300}
301
302/*
303 * XXX This was rewritten from Linux driver without any tests.
304 */
305static int
306enable_aui(struct cs_softc *sc)
307{
308 int unit = sc->arpcom.ac_if.if_unit;
309
310 control_dc_dc(sc, 0);
311 cs_writereg(sc->nic_addr, PP_LineCTL,
312 (sc->line_ctl & ~AUTO_AUI_10BASET) | AUI_ONLY);
313
314 if (!send_test_pkt(sc)) {
315 printf(CS_NAME"%1d failed to enable AUI\n", unit);
316 return EINVAL;
317 }
318 return 0;
319}
320
321/*
322 * XXX This was rewritten from Linux driver without any tests.
323 */
324static int
325enable_bnc(struct cs_softc *sc)
326{
327 int unit = sc->arpcom.ac_if.if_unit;
328
329 control_dc_dc(sc, 1);
330 cs_writereg(sc->nic_addr, PP_LineCTL,
331 (sc->line_ctl & ~AUTO_AUI_10BASET) | AUI_ONLY);
332
333 if (!send_test_pkt(sc)) {
334 printf(CS_NAME"%1d failed to enable BNC\n", unit);
335 return EINVAL;
336 }
337 return 0;
338}
339
340static int
341cs_cs89x0_probe(struct cs_softc *sc, u_int *dev_irq,
342 int *dev_drq, int iobase, int unit, int flags)
343{
344 unsigned rev_type = 0;
345 int i, irq=0;
346 int eeprom_buff[CHKSUM_LEN];
347 int chip_type, pp_isaint, pp_isadma;
348 char chip_revision;
349
350 if ((inw(iobase+ADD_PORT) & ADD_MASK) != ADD_SIG) {
351 /* Chip not detected. Let's try to reset it */
352 if (bootverbose)
353 printf(CS_NAME"%1d: trying to reset the chip.\n", unit);
354 outw(iobase+ADD_PORT, PP_SelfCTL);
355 i = inw(iobase+DATA_PORT);
356 outw(iobase+ADD_PORT, PP_SelfCTL);
357 outw(iobase+DATA_PORT, i | POWER_ON_RESET);
358 if ((inw(iobase+ADD_PORT) & ADD_MASK) != ADD_SIG)
359 return 0;
360 }
361
362 outw(iobase+ADD_PORT, PP_ChipID);
363 if (inw(iobase+DATA_PORT) != CHIP_EISA_ID_SIG)
364 return 0;
365
366 rev_type = cs_readreg(iobase, PRODUCT_ID_ADD);
367 chip_type = rev_type & ~REVISON_BITS;
368 chip_revision = ((rev_type & REVISON_BITS) >> 8) + 'A';
369
370 sc->nic_addr = iobase;
371 sc->chip_type = chip_type;
372 if(chip_type==CS8900) {
373 pp_isaint = PP_CS8900_ISAINT;
374 pp_isadma = PP_CS8900_ISADMA;
375 sc->send_cmd = TX_CS8900_AFTER_ALL;
376 } else {
377 pp_isaint = PP_CS8920_ISAINT;
378 pp_isadma = PP_CS8920_ISADMA;
379 sc->send_cmd = TX_CS8920_AFTER_ALL;
380 }
381
382 /*
383 * Clear some fields so that fail of EEPROM will left them clean
384 */
385 sc->auto_neg_cnf = 0;
386 sc->adapter_cnf = 0;
387 sc->isa_config = 0;
388
389 /*
390 * EEPROM
391 */
392 if((cs_readreg(iobase, PP_SelfST) & EEPROM_PRESENT) == 0) {
393 printf(CS_NAME"%1d: No EEPROM, assuming defaults.\n",
394 unit);
395 } else {
396 if (get_eeprom_data(sc,START_EEPROM_DATA,CHKSUM_LEN, eeprom_buff)<0) {
397 printf(CS_NAME"%1d: EEPROM read failed, "
398 "assuming defaults..\n", unit);
399 } else {
400 if (get_eeprom_cksum(START_EEPROM_DATA,CHKSUM_LEN, eeprom_buff)<0) {
401 printf( CS_NAME"%1d: EEPROM cheksum bad, "
402 "assuming defaults..\n", unit );
403 } else {
404 sc->auto_neg_cnf =
405 eeprom_buff[AUTO_NEG_CNF_OFFSET/2];
406 sc->adapter_cnf =
407 eeprom_buff[ADAPTER_CNF_OFFSET/2];
408 sc->isa_config =
409 eeprom_buff[ISA_CNF_OFFSET/2];
410
411 for (i=0; i<ETHER_ADDR_LEN/2; i++) {
412 sc->arpcom.ac_enaddr[i*2]=
413 eeprom_buff[i];
414 sc->arpcom.ac_enaddr[i*2+1]=
415 eeprom_buff[i] >> 8;
416 }
417
418 /*
419 * If no interrupt specified (or "?"),
420 * use what the board tells us.
421 */
422 if (*dev_irq <= 0) {
423 irq = sc->isa_config & INT_NO_MASK;
424 if (chip_type==CS8900) {
425 switch(irq) {
426 case 0: irq=10; break;
427 case 1: irq=11; break;
428 case 2: irq=12; break;
429 case 3: irq=5; break;
430 default: printf(CS_NAME"%1d: invalid irq in EEPROM.\n",unit);
431 }
432 if (irq!=0)
433 *dev_irq=(u_short)(1<<irq);
434 } else {
435 if (irq!=0 && irq<=CS8920_NO_INTS)
436 *dev_irq=(u_short)(1<<irq);
437 }
438 }
439 }
440 }
441 }
442
443 if ((irq=ffs(*dev_irq))) {
444 irq--;
445 if (chip_type == CS8900) {
446 switch(irq) {
447 case 5: irq = 3; break;
448 case 10: irq = 0; break;
449 case 11: irq = 1; break;
450 case 12: irq = 2; break;
451 default: printf(CS_NAME"%1d: invalid irq\n", unit);
452 return 0;
453 }
454 } else {
455 if (irq > CS8920_NO_INTS) {
456 printf(CS_NAME"%1d: invalid irq\n", unit);
457 return 0;
458 }
459 }
460 cs_writereg(iobase, pp_isaint, irq);
461 } else {
462 printf(CS_NAME"%1d: invalid irq\n", unit);
463 return 0;
464 }
465
466 /*
467 * Temporary disabled
468 *
469 if (drq>0)
470 cs_writereg(iobase, pp_isadma, drq);
471 else {
472 printf( CS_NAME"%1d: incorrect drq\n", unit );
473 return 0;
474 }
475 */
476
477 if (bootverbose)
478 printf(CS_NAME"%1d: model CS89%c0%s rev %c\n"
479 CS_NAME"%1d: media%s%s%s\n"
480 CS_NAME"%1d: irq %d drq %d\n",
481 unit,
482 chip_type==CS8900 ? '0' : '2',
483 chip_type==CS8920M ? "M" : "",
484 chip_revision,
485 unit,
486 (sc->adapter_cnf & A_CNF_10B_T) ? " TP" : "",
487 (sc->adapter_cnf & A_CNF_AUI) ? " AUI" : "",
488 (sc->adapter_cnf & A_CNF_10B_2) ? " BNC" : "",
489 unit, (int)*dev_irq, (int)*dev_drq);
490
491 if ((sc->adapter_cnf & A_CNF_EXTND_10B_2) &&
492 (sc->adapter_cnf & A_CNF_LOW_RX_SQUELCH))
493 sc->line_ctl = LOW_RX_SQUELCH;
494 else
495 sc->line_ctl = 0;
496
497
498 return PP_ISAIOB;
499}
500
501/*
502 * Determine if the device is present
503 *
504 * on entry:
505 * a pointer to an isa_device struct
506 * on exit:
507 * NULL if device not found
508 * or # of i/o addresses used (if found)
509 */
510static int
511cs_probe(struct isa_device *dev)
512{
513 int nports;
514
515 struct cs_softc *sc=&cs_softc[dev->id_unit];
516
517 nports=cs_cs89x0_probe(sc, &(dev->id_irq), &(dev->id_drq),
518 (dev->id_iobase), (dev->id_unit), (dev->id_flags));
519
520 if (nports)
521 return (nports);
522
523 return (0);
524}
525
526/*
527 * Install the interface into kernel networking data structures
528 */
529static int
530cs_attach(struct cs_softc *sc, int unit, int flags)
531{
532 int media=0;
533/* struct cs_softc *sc = &cs_softc[dev->id_unit]; */
534 struct ifnet *ifp = &(sc->arpcom.ac_if);
535
536 if (!ifp->if_name) {
537 ifp->if_softc=sc;
538 ifp->if_unit=unit;
539 ifp->if_name=csdriver.name;
540 ifp->if_output=ether_output;
541 ifp->if_start=cs_start;
542 ifp->if_ioctl=cs_ioctl;
543 ifp->if_watchdog=cs_watchdog;
544 ifp->if_init=cs_init;
545 ifp->if_snd.ifq_maxlen= IFQ_MAXLEN;
546 /*
547 * MIB DATA
548 */
549 /*
550 ifp->if_linkmib=&sc->mibdata;
551 ifp->if_linkmiblen=sizeof sc->mibdata;
552 */
553
554 ifp->if_flags=(IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST );
555
556 /*
557 * this code still in progress (DMA support)
558 *
559
560 sc->recv_ring=malloc(CS_DMA_BUFFER_SIZE<<1, M_DEVBUF, M_NOWAIT);
561 if (sc->recv_ring == NULL) {
562 log(LOG_ERR,CS_NAME
563 "%d: Couldn't allocate memory for NIC\n", unit);
564 return(0);
565 }
566 if ((sc->recv_ring-(sc->recv_ring & 0x1FFFF))
567 < (128*1024-CS_DMA_BUFFER_SIZE))
568 sc->recv_ring+=16*1024;
569
570 */
571
572 sc->buffer=malloc(ETHER_MAX_LEN-ETHER_CRC_LEN,M_DEVBUF,M_NOWAIT);
573 if (sc->buffer == NULL) {
574 printf(CS_NAME"%d: Couldn't allocate memory for NIC\n",
575 unit);
576 return(0);
577 }
578
579 /*
580 * Initialize the media structures.
581 */
582 ifmedia_init(&sc->media, 0, cs_mediachange, cs_mediastatus);
583
584 if (sc->adapter_cnf & A_CNF_10B_T) {
585 ifmedia_add(&sc->media, IFM_ETHER|IFM_10_T, 0, NULL);
586 if (sc->chip_type != CS8900) {
587 ifmedia_add(&sc->media,
588 IFM_ETHER|IFM_10_T|IFM_FDX, 0, NULL);
589 ifmedia_add(&sc->media,
590 IFM_ETHER|IFM_10_T|IFM_HDX, 0, NULL);
591 }
592 }
593
594 if (sc->adapter_cnf & A_CNF_10B_2)
595 ifmedia_add(&sc->media, IFM_ETHER|IFM_10_2, 0, NULL);
596
597 if (sc->adapter_cnf & A_CNF_AUI)
598 ifmedia_add(&sc->media, IFM_ETHER|IFM_10_5, 0, NULL);
599
600 if (sc->adapter_cnf & A_CNF_MEDIA)
601 ifmedia_add(&sc->media, IFM_ETHER|IFM_AUTO, 0, NULL);
602
603 /* Set default media from EEPROM */
604 switch (sc->adapter_cnf & A_CNF_MEDIA_TYPE) {
605 case A_CNF_MEDIA_AUTO: media = IFM_ETHER|IFM_AUTO; break;
606 case A_CNF_MEDIA_10B_T: media = IFM_ETHER|IFM_10_T; break;
607 case A_CNF_MEDIA_10B_2: media = IFM_ETHER|IFM_10_2; break;
608 case A_CNF_MEDIA_AUI: media = IFM_ETHER|IFM_10_5; break;
609 default: printf(CS_NAME"%d: adapter has no media\n", unit);
610 }
611 ifmedia_set(&sc->media, media);
612 cs_mediaset(sc, media);
613
614 if_attach(ifp);
615 cs_stop( sc );
616 ether_ifattach(ifp);
617 }
618
619 if (bootverbose)
620 printf(CS_NAME"%d: ethernet address %6D\n",
621 ifp->if_unit, sc->arpcom.ac_enaddr, ":");
622
623#if NBPFILTER > 0
624 bpfattach(ifp, DLT_EN10MB, sizeof (struct ether_header));
625#endif
626 return 1;
627}
628
629static int
630cs_attach_isa(struct isa_device *dev)
631{
632 int unit=dev->id_unit;
633 struct cs_softc *sc=&cs_softc[unit];
634 int flags=dev->id_flags;
635
636 dev->id_ointr = csintr;
637 return cs_attach(sc, unit, flags);
638}
639
640/*
641 * Initialize the board
642 */
643static void
644cs_init(void *xsc)
645{
646 struct cs_softc *sc=(struct cs_softc *)xsc;
647 struct ifnet *ifp = &sc->arpcom.ac_if;
648 int i, s, rx_cfg;
649
650 /* address not known */
651 if (TAILQ_EMPTY(&ifp->if_addrhead)) /* unlikely? XXX */
652 return;
653
654 /*
655 * reset whatchdog timer
656 */
657 ifp->if_timer=0;
658 sc->buf_len = 0;
659
660 s=splimp();
661
662 /*
663 * Hardware initialization of cs
664 */
665
666 /* Enable receiver and transmitter */
667 cs_writereg(sc->nic_addr, PP_LineCTL,
668 cs_readreg( sc->nic_addr, PP_LineCTL ) |
669 SERIAL_RX_ON | SERIAL_TX_ON);
670
671 /* Configure the receiver mode */
672 cs_setmode(sc);
673
674 /*
675 * This defines what type of frames will cause interrupts
676 * Bad frames should generate interrupts so that the driver
677 * could track statistics of discarded packets
678 */
679 rx_cfg = RX_OK_ENBL | RX_CRC_ERROR_ENBL | RX_RUNT_ENBL |
680 RX_EXTRA_DATA_ENBL;
681 if (sc->isa_config & STREAM_TRANSFER)
682 rx_cfg |= RX_STREAM_ENBL;
683 cs_writereg(sc->nic_addr, PP_RxCFG, rx_cfg);
684
685 cs_writereg(sc->nic_addr, PP_TxCFG, TX_LOST_CRS_ENBL |
686 TX_SQE_ERROR_ENBL | TX_OK_ENBL | TX_LATE_COL_ENBL |
687 TX_JBR_ENBL | TX_ANY_COL_ENBL | TX_16_COL_ENBL);
688
689 cs_writereg(sc->nic_addr, PP_BufCFG, READY_FOR_TX_ENBL |
690 RX_MISS_COUNT_OVRFLOW_ENBL | TX_COL_COUNT_OVRFLOW_ENBL |
691 TX_UNDERRUN_ENBL /*| RX_DMA_ENBL*/);
692
693 /* Write MAC address into IA filter */
694 for (i=0; i<ETHER_ADDR_LEN/2; i++)
695 cs_writereg(sc->nic_addr, PP_IA+i*2,
696 sc->arpcom.ac_enaddr[i*2] |
697 (sc->arpcom.ac_enaddr[i*2+1] << 8) );
698
699 /*
700 * Now enable everything
701 */
702/*
703#ifdef CS_USE_64K_DMA
704 cs_writereg(sc->nic_addr, PP_BusCTL, ENABLE_IRQ | RX_DMA_SIZE_64K);
705 #else
706
707 cs_writereg(sc->nic_addr, PP_BusCTL, ENABLE_IRQ);
708#endif
709*/
710 cs_writereg(sc->nic_addr, PP_BusCTL, ENABLE_IRQ);
711
712 /*
713 * Set running and clear output active flags
714 */
715 sc->arpcom.ac_if.if_flags |= IFF_RUNNING;
716 sc->arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
717
718 /*
719 * Start sending process
720 */
721 cs_start(ifp);
722
723 (void) splx(s);
724}
725
726/*
727 * Get the packet from the board and send it to the upper layer
728 * via ether_input().
729 */
730static int
731cs_get_packet(struct cs_softc *sc)
732{
733 struct ifnet *ifp = &(sc->arpcom.ac_if);
734 int iobase = sc->nic_addr, status, length;
735 struct ether_header *eh;
736 struct mbuf *m;
737
738#ifdef CS_DEBUG
739 int i;
740#endif
741
742 status = inw(iobase + RX_FRAME_PORT);
743 length = inw(iobase + RX_FRAME_PORT);
744
745#ifdef CS_DEBUG
746 printf(CS_NAME"%1d: rcvd: stat %x, len %d\n",
747 ifp->if_unit, status, length);
748#endif
749
750 if (!(status & RX_OK)) {
751#ifdef CS_DEBUG
752 printf(CS_NAME"%1d: bad pkt stat %x\n", ifp->if_unit, status);
753#endif
754 ifp->if_ierrors++;
755 return -1;
756 }
757
758 MGETHDR(m, M_DONTWAIT, MT_DATA);
759 if (m==NULL)
760 return -1;
761
762 if (length > MHLEN) {
763 MCLGET(m, M_DONTWAIT);
764 if (!(m->m_flags & M_EXT)) {
765 m_freem(m);
766 return -1;
767 }
768 }
769
770 /* Initialize packet's header info */
771 m->m_pkthdr.rcvif = ifp;
772 m->m_pkthdr.len = length;
773 m->m_len = length;
774
775 /* Get the data */
776 insw(iobase + RX_FRAME_PORT, m->m_data, (length+1)>>1);
777
778 eh = mtod(m, struct ether_header *);
779
780#if NBPFILTER > 0
781 if (ifp->if_bpf)
782 bpf_mtap(ifp, m);
783#endif
784
785#ifdef CS_DEBUG
786 for (i=0;i<length;i++)
787 printf(" %02x",(unsigned char)*((char *)(m->m_data+i)));
788 printf( "\n" );
789#endif
790
791 if (status & (RX_IA | RX_BROADCAST) ||
792 (ifp->if_flags & IFF_MULTICAST && status & RX_HASHED)) {
793 m->m_pkthdr.len -= sizeof(struct ether_header);
794 m->m_len -= sizeof(struct ether_header);
795 m->m_data += sizeof(struct ether_header);
796
797 /* Feed the packet to the upper layer */
798 ether_input(ifp, eh, m);
799
800 ifp->if_ipackets++;
801
802 if (length==ETHER_MAX_LEN-ETHER_CRC_LEN)
803 DELAY( cs_recv_delay );
804 } else {
805 m_freem(m);
806 }
807
808 return 0;
809}
810
811/*
812 * Software calls interrupt handler
813 */
814static void
815csintr_sc(struct cs_softc *sc, int unit)
816{
817 struct ifnet *ifp = &(sc->arpcom.ac_if);
818 int status;
819
820#ifdef CS_DEBUG
821 printf(CS_NAME"%1d: Interrupt.\n", unit);
822#endif
823
824 while ((status=cs_readword(sc->nic_addr, ISQ_PORT))) {
825
826#ifdef CS_DEBUG
827 printf( CS_NAME"%1d:from ISQ: %04x\n", unit, status );
828#endif
829
830 switch (status & ISQ_EVENT_MASK) {
831 case ISQ_RECEIVER_EVENT:
832 cs_get_packet(sc);
833 break;
834
835 case ISQ_TRANSMITTER_EVENT:
836 if (status & TX_OK)
837 ifp->if_opackets++;
838 else
839 ifp->if_oerrors++;
840 ifp->if_flags &= ~IFF_OACTIVE;
841 ifp->if_timer = 0;
842 break;
843
844 case ISQ_BUFFER_EVENT:
845 if (status & READY_FOR_TX) {
846 ifp->if_flags &= ~IFF_OACTIVE;
847 ifp->if_timer = 0;
848 }
849
850 if (status & TX_UNDERRUN) {
851 ifp->if_flags &= ~IFF_OACTIVE;
852 ifp->if_timer = 0;
853 ifp->if_oerrors++;
854 }
855 break;
856
857 case ISQ_RX_MISS_EVENT:
858 ifp->if_ierrors+=(status>>6);
859 break;
860
861 case ISQ_TX_COL_EVENT:
862 ifp->if_collisions+=(status>>6);
863 break;
864 }
865 }
866
867 if (!(ifp->if_flags & IFF_OACTIVE)) {
868 cs_start(ifp);
869 }
870}
871
872/*
873 * Handle interrupts
874 */
875static void
876csintr(int unit)
877{
878 struct cs_softc *sc = &cs_softc[unit];
879
880 csintr_sc(sc, unit);
881}
882
883/*
884 * Save the data in buffer
885 */
886
887static void
888cs_write_mbufs( struct cs_softc *sc, struct mbuf *m )
889{
890 int len;
891 struct mbuf *mp;
892 unsigned char *data, *buf;
893
894 for (mp=m, buf=sc->buffer, sc->buf_len=0; mp != NULL; mp=mp->m_next) {
895 len = mp->m_len;
896
897 /*
898 * Ignore empty parts
899 */
900 if (!len)
901 continue;
902
903 /*
904 * Find actual data address
905 */
906 data = mtod(mp, caddr_t);
907
908 bcopy((caddr_t) data, (caddr_t) buf, len);
909 buf += len;
910 sc->buf_len += len;
911 }
912}
913
914
915static void
916cs_xmit_buf( struct cs_softc *sc )
917{
918 outsw(sc->nic_addr+TX_FRAME_PORT, sc->buffer, (sc->buf_len+1)>>1);
919 sc->buf_len = 0;
920}
921
922static void
923cs_start(struct ifnet *ifp)
924{
925 int s, length;
926 struct mbuf *m, *mp;
927 struct cs_softc *sc = ifp->if_softc;
928
929 s = splimp();
930
931 for (;;) {
932 if (sc->buf_len)
933 length = sc->buf_len;
934 else {
935 IF_DEQUEUE( &ifp->if_snd, m );
936
937 if (m==NULL) {
938 (void) splx(s);
939 return;
940 }
941
942 for (length=0, mp=m; mp != NULL; mp=mp->m_next)
943 length += mp->m_len;
944
945 /* Skip zero-length packets */
946 if (length == 0) {
947 m_freem(m);
948 continue;
949 }
950
951 cs_write_mbufs(sc, m);
952
953#if NBPFILTER > 0
954 if (ifp->if_bpf) {
955 bpf_mtap(ifp, m);
956 }
957#endif
958
959 m_freem(m);
960 }
961
962 /*
963 * Issue a SEND command
964 */
965 outw(sc->nic_addr+TX_CMD_PORT, sc->send_cmd);
966 outw(sc->nic_addr+TX_LEN_PORT, length );
967
968 /*
969 * If there's no free space in the buffer then leave
970 * this packet for the next time: indicate output active
971 * and return.
972 */
973 if (!(cs_readreg(sc->nic_addr, PP_BusST) & READY_FOR_TX_NOW)) {
974 ifp->if_timer = sc->buf_len;
975 (void) splx(s);
976 ifp->if_flags |= IFF_OACTIVE;
977 return;
978 }
979
980 cs_xmit_buf(sc);
981
982 /*
983 * Set the watchdog timer in case we never hear
984 * from board again. (I don't know about correct
985 * value for this timeout)
986 */
987 ifp->if_timer = length;
988
989 (void) splx(s);
990 ifp->if_flags |= IFF_OACTIVE;
991 return;
992 }
993}
994
995/*
996 * Stop everything on the interface
997 */
998static void
999cs_stop(struct cs_softc *sc)
1000{
1001 int s = splimp();
1002
1003 cs_writereg(sc->nic_addr, PP_RxCFG, 0);
1004 cs_writereg(sc->nic_addr, PP_TxCFG, 0);
1005 cs_writereg(sc->nic_addr, PP_BufCFG, 0);
1006 cs_writereg(sc->nic_addr, PP_BusCTL, 0);
1007
1008 sc->arpcom.ac_if.if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
1009 sc->arpcom.ac_if.if_timer = 0;
1010
1011 (void) splx(s);
1012}
1013
1014/*
1015 * Reset the interface
1016 */
1017static void
1018cs_reset(struct cs_softc *sc)
1019{
1020 cs_stop(sc);
1021 cs_init(sc);
1022}
1023
1024static void
1025cs_setmode(struct cs_softc *sc)
1026{
1027 struct ifnet *ifp = &(sc->arpcom.ac_if);
1028 int rx_ctl;
1029
1030 /* Stop the receiver while changing filters */
1031 cs_writereg(sc->nic_addr, PP_LineCTL,
1032 cs_readreg(sc->nic_addr, PP_LineCTL) & ~SERIAL_RX_ON);
1033
1034 if (ifp->if_flags & IFF_PROMISC) {
1035 /* Turn on promiscuous mode. */
1036 rx_ctl = RX_OK_ACCEPT | RX_PROM_ACCEPT;
1037 } else {
1038 if (ifp->if_flags & IFF_MULTICAST) {
1039 /* Allow receiving frames with multicast addresses */
1040 rx_ctl = RX_IA_ACCEPT | RX_BROADCAST_ACCEPT |
1041 RX_OK_ACCEPT | RX_MULTCAST_ACCEPT;
1042 /*
1043 * Here the reconfiguration of chip's multicast
1044 * filters should be done but I've no idea about
1045 * hash transformation in this chip. If you can
1046 * add this code or describe me the transformation
1047 * I'd be very glad.
1048 */
1049 } else {
1050 /*
1051 * Receive only good frames addressed for us and
1052 * good broadcasts.
1053 */
1054 rx_ctl = RX_IA_ACCEPT | RX_BROADCAST_ACCEPT |
1055 RX_OK_ACCEPT;
1056 }
1057 }
1058
1059 /* Set up the filter */
1060 cs_writereg(sc->nic_addr, PP_RxCTL, RX_DEF_ACCEPT | rx_ctl);
1061
1062 /* Turn on receiver */
1063 cs_writereg(sc->nic_addr, PP_LineCTL,
1064 cs_readreg(sc->nic_addr, PP_LineCTL) | SERIAL_RX_ON);
1065}
1066
1067static int
1068cs_ioctl(register struct ifnet *ifp, u_long command, caddr_t data)
1069{
1070 struct cs_softc *sc=ifp->if_softc;
1071 struct ifreq *ifr = (struct ifreq *)data;
1072 int s,error=0;
1073
1074#ifdef CS_DEBUG
1075 printf(CS_NAME"%d: ioctl(%x)\n",sc->arpcom.ac_if.if_unit,command);
1076#endif
1077
1078 s=splimp();
1079
1080 switch (command) {
1081 case SIOCSIFADDR:
1082 case SIOCGIFADDR:
1083 case SIOCSIFMTU:
1084 ether_ioctl(ifp, command, data);
1085 break;
1086
1087 case SIOCSIFFLAGS:
1088 /*
1089 * Switch interface state between "running" and
1090 * "stopped", reflecting the UP flag.
1091 */
1092 if (sc->arpcom.ac_if.if_flags & IFF_UP) {
1093 if ((sc->arpcom.ac_if.if_flags & IFF_RUNNING)==0) {
1094 cs_init(sc);
1095 }
1096 } else {
1097 if ((sc->arpcom.ac_if.if_flags & IFF_RUNNING)!=0) {
1098 cs_stop(sc);
1099 }
1100 }
1101 /*
1102 * Promiscuous and/or multicast flags may have changed,
1103 * so reprogram the multicast filter and/or receive mode.
1104 *
1105 * See note about multicasts in cs_setmode
1106 */
1107 cs_setmode(sc);
1108 break;
1109
1110 case SIOCADDMULTI:
1111 case SIOCDELMULTI:
1112 /*
1113 * Multicast list has changed; set the hardware filter
1114 * accordingly.
1115 *
1116 * See note about multicasts in cs_setmode
1117 */
1118 cs_setmode(sc);
1119 error = 0;
1120 break;
1121
1122 case SIOCSIFMEDIA:
1123 case SIOCGIFMEDIA:
1124 error = ifmedia_ioctl(ifp, ifr, &sc->media, command);
1125 break;
1126
1127 default:
1128 error = EINVAL;
1129 }
1130
1131 (void) splx(s);
1132 return error;
1133}
1134
1135/*
1136 * Device timeout/watchdog routine. Entered if the device neglects to
1137 * generate an interrupt after a transmit has been started on it.
1138 */
1139static void
1140cs_watchdog(struct ifnet *ifp)
1141{
1142 struct cs_softc *sc = &cs_softc[ifp->if_unit];
1143
1144 ifp->if_oerrors++;
1145 log(LOG_ERR, CS_NAME"%d: device timeout\n", ifp->if_unit);
1146
1147 /* Reset the interface */
1148 if (ifp->if_flags & IFF_UP)
1149 cs_reset(sc);
1150 else
1151 cs_stop(sc);
1152}
1153
1154static int
1155cs_mediachange(struct ifnet *ifp)
1156{
1157 struct cs_softc *sc = ifp->if_softc;
1158 struct ifmedia *ifm = &sc->media;
1159
1160 if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER)
1161 return EINVAL;
1162
1163 return cs_mediaset(sc, ifm->ifm_media);
1164}
1165
1166static void
1167cs_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr)
1168{
1169 int line_status;
1170 struct cs_softc *sc = ifp->if_softc;
1171
1172 ifmr->ifm_active = IFM_ETHER;
1173 line_status = cs_readreg(sc->nic_addr, PP_LineST);
1174 if (line_status & TENBASET_ON) {
1175 ifmr->ifm_active |= IFM_10_T;
1176 if (sc->chip_type != CS8900) {
1177 if (cs_readreg(sc->nic_addr, PP_AutoNegST) & FDX_ACTIVE)
1178 ifmr->ifm_active |= IFM_FDX;
1179 if (cs_readreg(sc->nic_addr, PP_AutoNegST) & HDX_ACTIVE)
1180 ifmr->ifm_active |= IFM_HDX;
1181 }
1182 ifmr->ifm_status = IFM_AVALID;
1183 if (line_status & LINK_OK)
1184 ifmr->ifm_status |= IFM_ACTIVE;
1185 } else {
1186 if (line_status & AUI_ON) {
1187 cs_writereg(sc->nic_addr, PP_SelfCTL,
1188 cs_readreg(sc->nic_addr, PP_SelfCTL) |
1189 HCB1_ENBL);
1190 if (((sc->adapter_cnf & A_CNF_DC_DC_POLARITY)!=0)^
1191 (cs_readreg(sc->nic_addr, PP_SelfCTL)&HCB1))
1192 ifmr->ifm_active |= IFM_10_2;
1193 else
1194 ifmr->ifm_active |= IFM_10_5;
1195 }
1196 }
1197}
1198
1199static int
1200cs_mediaset(struct cs_softc *sc, int media)
1201{
1202 int error;
1203
1204 /* Stop the receiver & transmitter */
1205 cs_writereg(sc->nic_addr, PP_LineCTL,
1206 cs_readreg(sc->nic_addr, PP_LineCTL) &
1207 ~(SERIAL_RX_ON | SERIAL_TX_ON));
1208
1209#ifdef CS_DEBUG
1210 printf(CS_NAME"%d: cs_setmedia(%x)\n",sc->arpcom.ac_if.if_unit,media);
1211#endif
1212
1213 switch (IFM_SUBTYPE(media)) {
1214 default:
1215 case IFM_AUTO:
1216 if ((error=enable_tp(sc))==0)
1217 error = cs_duplex_auto(sc);
1218 else if ((error=enable_bnc(sc)) != 0)
1219 error = enable_aui(sc);
1220 break;
1221 case IFM_10_T:
1222 if ((error=enable_tp(sc)) != 0)
1223 break;
1224 if (media & IFM_FDX)
1225 cs_duplex_full(sc);
1226 else if (media & IFM_HDX)
1227 cs_duplex_half(sc);
1228 else
1229 error = cs_duplex_auto(sc);
1230 break;
1231 case IFM_10_2:
1232 error = enable_bnc(sc);
1233 break;
1234 case IFM_10_5:
1235 error = enable_aui(sc);
1236 break;
1237 }
1238
1239 /*
1240 * Turn the transmitter & receiver back on
1241 */
1242 cs_writereg(sc->nic_addr, PP_LineCTL,
1243 cs_readreg( sc->nic_addr, PP_LineCTL ) |
1244 SERIAL_RX_ON | SERIAL_TX_ON);
1245
1246 return error;
1247}
1248
1249
1250#if NPNP > 0
1251
1252static struct cspnp_ids {
1253 u_long vend_id;
1254 char *id_str;
1255} cspnp_ids[]= {
1256 { 0x4060630e, "CSC6040" },
1257 { 0x10104d24, "IBM EtherJet" },
1258 { 0 }
1259};
1260
1261static char *cs_pnp_probe(u_long, u_long);
1262static void cs_pnp_attach(u_long, u_long, char *, struct isa_device *);
1263
1264struct pnp_device cs_pnp = {
1265 "CS8920 based PnP Ethernet",
1266 cs_pnp_probe,
1267 cs_pnp_attach,
1268 &cs_unit,
1269 &net_imask /* imask */
1270};
1271
1272DATA_SET (pnpdevice_set, cs_pnp);
1273
1274struct csintr_list {
1275 struct cs_softc *sc;
1276 int unit;
1277 struct csintr_list *next;
1278};
1279
1280static struct csintr_list *csintr_head;
1281
1282static void csintr_pnp_add(struct cs_softc *sc, int unit);
1283static void csintr_pnp(int unit);
1284
1285static void
1286csintr_pnp_add(struct cs_softc *sc, int unit)
1287{
1288 struct csintr_list *intr;
1289
1290 if (!sc) return;
1291
1292 intr = malloc (sizeof (*intr), M_DEVBUF, M_WAITOK);
1293 if (!intr) return;
1294
1295 intr->sc = sc;
1296 intr->unit = unit;
1297 intr->next = csintr_head;
1298 csintr_head = intr;
1299}
1300
1301/*
1302 * Interrupt handler for PNP installed card
1303 * We have to find the number of the card.
1304 */
1305static void
1306csintr_pnp(int unit)
1307{
1308 struct csintr_list *intr;
1309
1310 for (intr=csintr_head; intr; intr=intr->next) {
1311 if (intr->unit == unit)
1312 csintr_sc(intr->sc, unit);
1313 break;
1314 }
1315}
1316
1317static char *
1318cs_pnp_probe(u_long csn, u_long vend_id)
1319{
1320 struct cspnp_ids *ids;
1321 char *s=NULL;
1322
1323 for(ids = cspnp_ids; ids->vend_id != 0; ids++) {
1324 if (vend_id == ids->vend_id) {
1325 s = ids->id_str;
1326 break;
1327 }
1328 }
1329
1330 if (s) {
1331 struct pnp_cinfo d;
1332 int ldn = 0;
1333
1334 read_pnp_parms(&d, ldn);
1335 if (d.enable == 0) {
1336 printf("This is a %s, but LDN %d is disabled\n", s, ldn);
1337 return NULL ;
1338 }
1339 return s;
1340 }
1341
1342 return NULL ;
1343}
1344
1345static void
1346cs_pnp_attach(u_long csn, u_long vend_id, char *name,
1347 struct isa_device *dev)
1348{
1349
1350 struct pnp_cinfo d;
1351 int ldn = 0;
1352 int iobase, unit, flags;
1353 u_int irq;
1354 int drq;
1355 struct isa_device *dvp;
1356 struct cs_softc *sc = malloc(sizeof *sc, M_DEVBUF, M_NOWAIT);
1357
1358 if (read_pnp_parms ( &d , ldn ) == 0 ) {
1359 printf("failed to read pnp parms\n");
1360 return;
1361 }
1362
1363 write_pnp_parms( &d, ldn );
1364 enable_pnp_card();
1365
1366 iobase = dev->id_iobase = d.port[0];
1367 irq = dev->id_irq = (1 << d.irq[0] );
1368 drq = dev->id_drq = d.drq[0];
1369 dev->id_maddr = 0;
1370 dev->id_ointr = csintr_pnp;
1371 flags = dev->id_flags = 0;
1372 unit = dev->id_unit;
1373
1374 if (dev->id_driver == NULL) {
1375 dev->id_driver = &csdriver;
1355 struct cs_softc *sc = malloc(sizeof *sc, M_DEVBUF, M_NOWAIT);
1356
1357 if (read_pnp_parms ( &d , ldn ) == 0 ) {
1358 printf("failed to read pnp parms\n");
1359 return;
1360 }
1361
1362 write_pnp_parms( &d, ldn );
1363 enable_pnp_card();
1364
1365 iobase = dev->id_iobase = d.port[0];
1366 irq = dev->id_irq = (1 << d.irq[0] );
1367 drq = dev->id_drq = d.drq[0];
1368 dev->id_maddr = 0;
1369 dev->id_ointr = csintr_pnp;
1370 flags = dev->id_flags = 0;
1371 unit = dev->id_unit;
1372
1373 if (dev->id_driver == NULL) {
1374 dev->id_driver = &csdriver;
1376 dvp = find_isadev(isa_devtab_net, &csdriver, 0);
1377 if (dvp != NULL)
1378 dev->id_id = dvp->id_id;
1375 dev->id_id = isa_compat_nextid();
1379 }
1380
1381 if (!sc) return;
1382
1383 bzero(sc, sizeof *sc);
1384 if (cs_cs89x0_probe(sc, &irq, &drq, iobase, unit, flags) == 0
1385 || cs_attach(sc, unit, flags) == 0) {
1386 free(sc, M_DEVBUF);
1387 } else {
1388 if ((irq != dev->id_irq)
1389 || (drq != dev->id_drq)
1390 || (iobase != dev->id_iobase)
1391 || (unit != dev->id_unit)
1392 || (flags != dev->id_flags)
1393 ) {
1394 printf("failed to pnp card parametars\n");
1395 }
1396 }
1397 csintr_pnp_add(sc, dev->id_unit);
1398}
1399#endif /* NPNP */
1376 }
1377
1378 if (!sc) return;
1379
1380 bzero(sc, sizeof *sc);
1381 if (cs_cs89x0_probe(sc, &irq, &drq, iobase, unit, flags) == 0
1382 || cs_attach(sc, unit, flags) == 0) {
1383 free(sc, M_DEVBUF);
1384 } else {
1385 if ((irq != dev->id_irq)
1386 || (drq != dev->id_drq)
1387 || (iobase != dev->id_iobase)
1388 || (unit != dev->id_unit)
1389 || (flags != dev->id_flags)
1390 ) {
1391 printf("failed to pnp card parametars\n");
1392 }
1393 }
1394 csintr_pnp_add(sc, dev->id_unit);
1395}
1396#endif /* NPNP */