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