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