if_sbni.c revision 152315
1/*-
2 * Copyright (c) 1997-2001 Granch, Ltd. All rights reserved.
3 * Author: Denis I.Timofeev <timofeev@granch.ru>
4 *
5 * Redistributon 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 NEIGENCE 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/sbni/if_sbni.c 152315 2005-11-11 16:04:59Z ru $");
31
32/*
33 * Device driver for Granch SBNI12 leased line adapters
34 *
35 * Revision 2.0.0  1997/08/06
36 * Initial revision by Alexey Zverev
37 *
38 * Revision 2.0.1 1997/08/11
39 * Additional internal statistics support (tx statistics)
40 *
41 * Revision 2.0.2 1997/11/05
42 * if_bpf bug has been fixed
43 *
44 * Revision 2.0.3 1998/12/20
45 * Memory leakage has been eliminated in
46 * the sbni_st and sbni_timeout routines.
47 *
48 * Revision 3.0 2000/08/10 by Yaroslav Polyakov
49 * Support for PCI cards. 4.1 modification.
50 *
51 * Revision 3.1 2000/09/12
52 * Removed extra #defines around bpf functions
53 *
54 * Revision 4.0 2000/11/23 by Denis Timofeev
55 * Completely redesigned the buffer management
56 *
57 * Revision 4.1 2001/01/21
58 * Support for PCI Dual cards and new SBNI12D-10, -11 Dual/ISA cards
59 *
60 * Written with reference to NE2000 driver developed by David Greenman.
61 */
62
63
64#include <sys/param.h>
65#include <sys/systm.h>
66#include <sys/socket.h>
67#include <sys/sockio.h>
68#include <sys/mbuf.h>
69#include <sys/kernel.h>
70#include <sys/proc.h>
71#include <sys/callout.h>
72#include <sys/syslog.h>
73#include <sys/random.h>
74
75#include <machine/bus.h>
76#include <sys/rman.h>
77#include <machine/resource.h>
78
79#include <net/if.h>
80#include <net/if_dl.h>
81#include <net/ethernet.h>
82#include <net/bpf.h>
83#include <net/if_types.h>
84
85#include <dev/sbni/if_sbnireg.h>
86#include <dev/sbni/if_sbnivar.h>
87
88#define ASM_CRC 1
89
90static void	sbni_init(void *);
91static void	sbni_start(struct ifnet *);
92static int	sbni_ioctl(struct ifnet *, u_long, caddr_t);
93static void	sbni_watchdog(struct ifnet *);
94static void	sbni_stop(struct sbni_softc *);
95static void	handle_channel(struct sbni_softc *);
96
97static void	card_start(struct sbni_softc *);
98static int	recv_frame(struct sbni_softc *);
99static void	send_frame(struct sbni_softc *);
100static int	upload_data(struct sbni_softc *, u_int, u_int, u_int, u_int32_t);
101static int	skip_tail(struct sbni_softc *, u_int, u_int32_t);
102static void	interpret_ack(struct sbni_softc *, u_int);
103static void	download_data(struct sbni_softc *, u_int32_t *);
104static void	prepare_to_send(struct sbni_softc *);
105static void	drop_xmit_queue(struct sbni_softc *);
106static int	get_rx_buf(struct sbni_softc *);
107static void	indicate_pkt(struct sbni_softc *);
108static void	change_level(struct sbni_softc *);
109static int	check_fhdr(struct sbni_softc *, u_int *, u_int *,
110			   u_int *, u_int *, u_int32_t *);
111static int	append_frame_to_pkt(struct sbni_softc *, u_int, u_int32_t);
112static void	timeout_change_level(struct sbni_softc *);
113static void	send_frame_header(struct sbni_softc *, u_int32_t *);
114static void	set_initial_values(struct sbni_softc *, struct sbni_flags);
115
116static u_int32_t	calc_crc32(u_int32_t, caddr_t, u_int);
117static timeout_t	sbni_timeout;
118
119static __inline u_char	sbni_inb(struct sbni_softc *, enum sbni_reg);
120static __inline void	sbni_outb(struct sbni_softc *, enum sbni_reg, u_char);
121static __inline void	sbni_insb(struct sbni_softc *, u_char *, u_int);
122static __inline void	sbni_outsb(struct sbni_softc *, u_char *, u_int);
123
124static u_int32_t crc32tab[];
125
126#ifdef SBNI_DUAL_COMPOUND
127struct sbni_softc *sbni_headlist;
128#endif
129
130u_int32_t next_sbni_unit;
131
132/* -------------------------------------------------------------------------- */
133
134static __inline u_char
135sbni_inb(struct sbni_softc *sc, enum sbni_reg reg)
136{
137	return bus_space_read_1(
138	    rman_get_bustag(sc->io_res),
139	    rman_get_bushandle(sc->io_res),
140	    sc->io_off + reg);
141}
142
143static __inline void
144sbni_outb(struct sbni_softc *sc, enum sbni_reg reg, u_char value)
145{
146	bus_space_write_1(
147	    rman_get_bustag(sc->io_res),
148	    rman_get_bushandle(sc->io_res),
149	    sc->io_off + reg, value);
150}
151
152static __inline void
153sbni_insb(struct sbni_softc *sc, u_char *to, u_int len)
154{
155	bus_space_read_multi_1(
156	    rman_get_bustag(sc->io_res),
157	    rman_get_bushandle(sc->io_res),
158	    sc->io_off + DAT, to, len);
159}
160
161static __inline void
162sbni_outsb(struct sbni_softc *sc, u_char *from, u_int len)
163{
164	bus_space_write_multi_1(
165	    rman_get_bustag(sc->io_res),
166	    rman_get_bushandle(sc->io_res),
167	    sc->io_off + DAT, from, len);
168}
169
170
171/*
172	Valid combinations in CSR0 (for probing):
173
174	VALID_DECODER	0000,0011,1011,1010
175
176				    	; 0   ; -
177				TR_REQ	; 1   ; +
178			TR_RDY	    	; 2   ; -
179			TR_RDY	TR_REQ	; 3   ; +
180		BU_EMP		    	; 4   ; +
181		BU_EMP	     	TR_REQ	; 5   ; +
182		BU_EMP	TR_RDY	    	; 6   ; -
183		BU_EMP	TR_RDY	TR_REQ	; 7   ; +
184	RC_RDY 		     		; 8   ; +
185	RC_RDY			TR_REQ	; 9   ; +
186	RC_RDY		TR_RDY		; 10  ; -
187	RC_RDY		TR_RDY	TR_REQ	; 11  ; -
188	RC_RDY	BU_EMP			; 12  ; -
189	RC_RDY	BU_EMP		TR_REQ	; 13  ; -
190	RC_RDY	BU_EMP	TR_RDY		; 14  ; -
191	RC_RDY	BU_EMP	TR_RDY	TR_REQ	; 15  ; -
192*/
193
194#define VALID_DECODER	(2 + 8 + 0x10 + 0x20 + 0x80 + 0x100 + 0x200)
195
196
197int
198sbni_probe(struct sbni_softc *sc)
199{
200	u_char csr0;
201
202	csr0 = sbni_inb(sc, CSR0);
203	if (csr0 != 0xff && csr0 != 0x00) {
204		csr0 &= ~EN_INT;
205		if (csr0 & BU_EMP)
206			csr0 |= EN_INT;
207
208		if (VALID_DECODER & (1 << (csr0 >> 4)))
209			return (0);
210	}
211
212	return (ENXIO);
213}
214
215
216/*
217 * Install interface into kernel networking data structures
218 */
219void
220sbni_attach(struct sbni_softc *sc, int unit, struct sbni_flags flags)
221{
222	struct ifnet *ifp;
223	u_char csr0;
224
225	ifp = sc->ifp = if_alloc(IFT_ETHER);
226	if (ifp == NULL)
227		panic("sbni%d: can not if_alloc()", unit);
228	sbni_outb(sc, CSR0, 0);
229	set_initial_values(sc, flags);
230
231	callout_handle_init(&sc->wch);
232	/* Initialize ifnet structure */
233	ifp->if_softc	= sc;
234	if_initname(ifp, "sbni", unit);
235	ifp->if_init	= sbni_init;
236	ifp->if_start	= sbni_start;
237	ifp->if_ioctl	= sbni_ioctl;
238	ifp->if_watchdog	= sbni_watchdog;
239	ifp->if_snd.ifq_maxlen	= IFQ_MAXLEN;
240
241	/* report real baud rate */
242	csr0 = sbni_inb(sc, CSR0);
243	ifp->if_baudrate =
244		(csr0 & 0x01 ? 500000 : 2000000) / (1 << flags.rate);
245
246	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST |
247	    IFF_NEEDSGIANT;
248	ether_ifattach(ifp, sc->enaddr);
249	/* device attach does transition from UNCONFIGURED to IDLE state */
250
251	if_printf(ifp, "speed %ld, rxl ", ifp->if_baudrate);
252	if (sc->delta_rxl)
253		printf("auto\n");
254	else
255		printf("%d (fixed)\n", sc->cur_rxl_index);
256}
257
258/* -------------------------------------------------------------------------- */
259
260static void
261sbni_init(void *xsc)
262{
263	struct sbni_softc *sc;
264	struct ifnet *ifp;
265	int  s;
266
267	sc = (struct sbni_softc *)xsc;
268	ifp = sc->ifp;
269
270	/*
271	 * kludge to avoid multiple initialization when more than once
272	 * protocols configured
273	 */
274	if (ifp->if_drv_flags & IFF_DRV_RUNNING)
275		return;
276
277	s = splimp();
278	ifp->if_timer = 0;
279	card_start(sc);
280	sc->wch = timeout(sbni_timeout, sc, hz/SBNI_HZ);
281
282	ifp->if_drv_flags |= IFF_DRV_RUNNING;
283	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
284
285	/* attempt to start output */
286	sbni_start(ifp);
287	splx(s);
288}
289
290
291static void
292sbni_start(struct ifnet *ifp)
293{
294	struct sbni_softc *sc = ifp->if_softc;
295	if (sc->tx_frameno == 0)
296		prepare_to_send(sc);
297}
298
299
300static void
301sbni_stop(struct sbni_softc *sc)
302{
303	sbni_outb(sc, CSR0, 0);
304	drop_xmit_queue(sc);
305
306	if (sc->rx_buf_p) {
307		m_freem(sc->rx_buf_p);
308		sc->rx_buf_p = NULL;
309	}
310
311	untimeout(sbni_timeout, sc, sc->wch);
312	sc->wch.callout = NULL;
313}
314
315/* -------------------------------------------------------------------------- */
316
317/* interrupt handler */
318
319/*
320 * 	SBNI12D-10, -11/ISA boards within "common interrupt" mode could not
321 * be looked as two independent single-channel devices. Every channel seems
322 * as Ethernet interface but interrupt handler must be common. Really, first
323 * channel ("master") driver only registers the handler. In it's struct softc
324 * it has got pointer to "slave" channel's struct softc and handles that's
325 * interrupts too.
326 *	softc of successfully attached ISA SBNI boards is linked to list.
327 * While next board driver is initialized, it scans this list. If one
328 * has found softc with same irq and ioaddr different by 4 then it assumes
329 * this board to be "master".
330 */
331
332void
333sbni_intr(void *arg)
334{
335	struct sbni_softc *sc;
336	int repeat;
337
338	sc = (struct sbni_softc *)arg;
339
340	do {
341		repeat = 0;
342		if (sbni_inb(sc, CSR0) & (RC_RDY | TR_RDY)) {
343			handle_channel(sc);
344			repeat = 1;
345		}
346		if (sc->slave_sc && 	/* second channel present */
347		    (sbni_inb(sc->slave_sc, CSR0) & (RC_RDY | TR_RDY))) {
348			handle_channel(sc->slave_sc);
349			repeat = 1;
350		}
351	} while (repeat);
352}
353
354
355static void
356handle_channel(struct sbni_softc *sc)
357{
358	int req_ans;
359	u_char csr0;
360
361	sbni_outb(sc, CSR0, (sbni_inb(sc, CSR0) & ~EN_INT) | TR_REQ);
362
363	sc->timer_ticks = CHANGE_LEVEL_START_TICKS;
364	for (;;) {
365		csr0 = sbni_inb(sc, CSR0);
366		if ((csr0 & (RC_RDY | TR_RDY)) == 0)
367			break;
368
369		req_ans = !(sc->state & FL_PREV_OK);
370
371		if (csr0 & RC_RDY)
372			req_ans = recv_frame(sc);
373
374		/*
375		 * TR_RDY always equals 1 here because we have owned the marker,
376		 * and we set TR_REQ when disabled interrupts
377		 */
378		csr0 = sbni_inb(sc, CSR0);
379		if ((csr0 & TR_RDY) == 0 || (csr0 & RC_RDY) != 0)
380			printf("sbni: internal error!\n");
381
382		/* if state & FL_NEED_RESEND != 0 then tx_frameno != 0 */
383		if (req_ans || sc->tx_frameno != 0)
384			send_frame(sc);
385		else {
386			/* send the marker without any data */
387			sbni_outb(sc, CSR0, sbni_inb(sc, CSR0) & ~TR_REQ);
388		}
389	}
390
391	sbni_outb(sc, CSR0, sbni_inb(sc, CSR0) | EN_INT);
392}
393
394
395/*
396 * Routine returns 1 if it need to acknoweledge received frame.
397 * Empty frame received without errors won't be acknoweledged.
398 */
399
400static int
401recv_frame(struct sbni_softc *sc)
402{
403	u_int32_t crc;
404	u_int framelen, frameno, ack;
405	u_int is_first, frame_ok;
406
407	crc = CRC32_INITIAL;
408	if (check_fhdr(sc, &framelen, &frameno, &ack, &is_first, &crc)) {
409		frame_ok = framelen > 4 ?
410		    upload_data(sc, framelen, frameno, is_first, crc) :
411		    skip_tail(sc, framelen, crc);
412		if (frame_ok)
413			interpret_ack(sc, ack);
414	} else
415		frame_ok = 0;
416
417	sbni_outb(sc, CSR0, sbni_inb(sc, CSR0) ^ CT_ZER);
418	if (frame_ok) {
419		sc->state |= FL_PREV_OK;
420		if (framelen > 4)
421			sc->in_stats.all_rx_number++;
422	} else {
423		sc->state &= ~FL_PREV_OK;
424		change_level(sc);
425		sc->in_stats.all_rx_number++;
426		sc->in_stats.bad_rx_number++;
427	}
428
429	return (!frame_ok || framelen > 4);
430}
431
432
433static void
434send_frame(struct sbni_softc *sc)
435{
436	u_int32_t crc;
437	u_char csr0;
438
439	crc = CRC32_INITIAL;
440	if (sc->state & FL_NEED_RESEND) {
441
442		/* if frame was sended but not ACK'ed - resend it */
443		if (sc->trans_errors) {
444			sc->trans_errors--;
445			if (sc->framelen != 0)
446				sc->in_stats.resend_tx_number++;
447		} else {
448			/* cannot xmit with many attempts */
449			drop_xmit_queue(sc);
450			goto do_send;
451		}
452	} else
453		sc->trans_errors = TR_ERROR_COUNT;
454
455	send_frame_header(sc, &crc);
456	sc->state |= FL_NEED_RESEND;
457	/*
458	 * FL_NEED_RESEND will be cleared after ACK, but if empty
459	 * frame sended then in prepare_to_send next frame
460	 */
461
462
463	if (sc->framelen) {
464		download_data(sc, &crc);
465		sc->in_stats.all_tx_number++;
466		sc->state |= FL_WAIT_ACK;
467	}
468
469	sbni_outsb(sc, (u_char *)&crc, sizeof crc);
470
471do_send:
472	csr0 = sbni_inb(sc, CSR0);
473	sbni_outb(sc, CSR0, csr0 & ~TR_REQ);
474
475	if (sc->tx_frameno) {
476		/* next frame exists - request to send */
477		sbni_outb(sc, CSR0, csr0 | TR_REQ);
478	}
479}
480
481
482static void
483download_data(struct sbni_softc *sc, u_int32_t *crc_p)
484{
485	struct mbuf *m;
486	caddr_t	data_p;
487	u_int data_len, pos, slice;
488
489	data_p = NULL;		/* initialized to avoid warn */
490	pos = 0;
491
492	for (m = sc->tx_buf_p;  m != NULL && pos < sc->pktlen;  m = m->m_next) {
493		if (pos + m->m_len > sc->outpos) {
494			data_len = m->m_len - (sc->outpos - pos);
495			data_p = mtod(m, caddr_t) + (sc->outpos - pos);
496
497			goto do_copy;
498		} else
499			pos += m->m_len;
500	}
501
502	data_len = 0;
503
504do_copy:
505	pos = 0;
506	do {
507		if (data_len) {
508			slice = min(data_len, sc->framelen - pos);
509			sbni_outsb(sc, data_p, slice);
510			*crc_p = calc_crc32(*crc_p, data_p, slice);
511
512			pos += slice;
513			if (data_len -= slice)
514				data_p += slice;
515			else {
516				do {
517					m = m->m_next;
518				} while (m != NULL && m->m_len == 0);
519
520				if (m) {
521					data_len = m->m_len;
522					data_p = mtod(m, caddr_t);
523				}
524			}
525		} else {
526			/* frame too short - zero padding */
527
528			pos = sc->framelen - pos;
529			while (pos--) {
530				sbni_outb(sc, DAT, 0);
531				*crc_p = CRC32(0, *crc_p);
532			}
533			return;
534		}
535	} while (pos < sc->framelen);
536}
537
538
539static int
540upload_data(struct sbni_softc *sc, u_int framelen, u_int frameno,
541	    u_int is_first, u_int32_t crc)
542{
543	int frame_ok;
544
545	if (is_first) {
546		sc->wait_frameno = frameno;
547		sc->inppos = 0;
548	}
549
550	if (sc->wait_frameno == frameno) {
551
552		if (sc->inppos + framelen  <=  ETHER_MAX_LEN) {
553			frame_ok = append_frame_to_pkt(sc, framelen, crc);
554
555		/*
556		 * if CRC is right but framelen incorrect then transmitter
557		 * error was occured... drop entire packet
558		 */
559		} else if ((frame_ok = skip_tail(sc, framelen, crc)) != 0) {
560			sc->wait_frameno = 0;
561			sc->inppos = 0;
562			sc->ifp->if_ierrors++;
563			/* now skip all frames until is_first != 0 */
564		}
565	} else
566		frame_ok = skip_tail(sc, framelen, crc);
567
568	if (is_first && !frame_ok) {
569		/*
570		 * Frame has been violated, but we have stored
571		 * is_first already... Drop entire packet.
572		 */
573		sc->wait_frameno = 0;
574		sc->ifp->if_ierrors++;
575	}
576
577	return (frame_ok);
578}
579
580
581static __inline void	send_complete(struct sbni_softc *);
582
583static __inline void
584send_complete(struct sbni_softc *sc)
585{
586	m_freem(sc->tx_buf_p);
587	sc->tx_buf_p = NULL;
588	sc->ifp->if_opackets++;
589}
590
591
592static void
593interpret_ack(struct sbni_softc *sc, u_int ack)
594{
595	if (ack == FRAME_SENT_OK) {
596		sc->state &= ~FL_NEED_RESEND;
597
598		if (sc->state & FL_WAIT_ACK) {
599			sc->outpos += sc->framelen;
600
601			if (--sc->tx_frameno) {
602				sc->framelen = min(
603				    sc->maxframe, sc->pktlen - sc->outpos);
604			} else {
605				send_complete(sc);
606				prepare_to_send(sc);
607			}
608		}
609	}
610
611	sc->state &= ~FL_WAIT_ACK;
612}
613
614
615/*
616 * Glue received frame with previous fragments of packet.
617 * Indicate packet when last frame would be accepted.
618 */
619
620static int
621append_frame_to_pkt(struct sbni_softc *sc, u_int framelen, u_int32_t crc)
622{
623	caddr_t p;
624
625	if (sc->inppos + framelen > ETHER_MAX_LEN)
626		return (0);
627
628	if (!sc->rx_buf_p && !get_rx_buf(sc))
629		return (0);
630
631	p = sc->rx_buf_p->m_data + sc->inppos;
632	sbni_insb(sc, p, framelen);
633	if (calc_crc32(crc, p, framelen) != CRC32_REMAINDER)
634		return (0);
635
636	sc->inppos += framelen - 4;
637	if (--sc->wait_frameno == 0) {		/* last frame received */
638		indicate_pkt(sc);
639		sc->ifp->if_ipackets++;
640	}
641
642	return (1);
643}
644
645
646/*
647 * Prepare to start output on adapter. Current priority must be set to splimp
648 * before this routine is called.
649 * Transmitter will be actually activated when marker has been accepted.
650 */
651
652static void
653prepare_to_send(struct sbni_softc *sc)
654{
655	struct mbuf *m;
656	u_int len;
657
658	/* sc->tx_buf_p == NULL here! */
659	if (sc->tx_buf_p)
660		printf("sbni: memory leak!\n");
661
662	sc->outpos = 0;
663	sc->state &= ~(FL_WAIT_ACK | FL_NEED_RESEND);
664
665	for (;;) {
666		IF_DEQUEUE(&sc->ifp->if_snd, sc->tx_buf_p);
667		if (!sc->tx_buf_p) {
668			/* nothing to transmit... */
669			sc->pktlen     = 0;
670			sc->tx_frameno = 0;
671			sc->framelen   = 0;
672			sc->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
673			return;
674		}
675
676		for (len = 0, m = sc->tx_buf_p;  m;  m = m->m_next)
677			len += m->m_len;
678
679		if (len != 0)
680			break;
681		m_freem(sc->tx_buf_p);
682	}
683
684	if (len < SBNI_MIN_LEN)
685		len = SBNI_MIN_LEN;
686
687	sc->pktlen	= len;
688	sc->tx_frameno	= (len + sc->maxframe - 1) / sc->maxframe;
689	sc->framelen	= min(len, sc->maxframe);
690
691	sbni_outb(sc, CSR0, sbni_inb(sc, CSR0) | TR_REQ);
692	sc->ifp->if_drv_flags |= IFF_DRV_OACTIVE;
693	BPF_MTAP(sc->ifp, sc->tx_buf_p);
694}
695
696
697static void
698drop_xmit_queue(struct sbni_softc *sc)
699{
700	struct mbuf *m;
701
702	if (sc->tx_buf_p) {
703		m_freem(sc->tx_buf_p);
704		sc->tx_buf_p = NULL;
705		sc->ifp->if_oerrors++;
706	}
707
708	for (;;) {
709		IF_DEQUEUE(&sc->ifp->if_snd, m);
710		if (m == NULL)
711			break;
712		m_freem(m);
713		sc->ifp->if_oerrors++;
714	}
715
716	sc->tx_frameno	= 0;
717	sc->framelen	= 0;
718	sc->outpos	= 0;
719	sc->state &= ~(FL_WAIT_ACK | FL_NEED_RESEND);
720	sc->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
721}
722
723
724static void
725send_frame_header(struct sbni_softc *sc, u_int32_t *crc_p)
726{
727	u_int32_t crc;
728	u_int len_field;
729	u_char value;
730
731	crc = *crc_p;
732	len_field = sc->framelen + 6;	/* CRC + frameno + reserved */
733
734	if (sc->state & FL_NEED_RESEND)
735		len_field |= FRAME_RETRY;	/* non-first attempt... */
736
737	if (sc->outpos == 0)
738		len_field |= FRAME_FIRST;
739
740	len_field |= (sc->state & FL_PREV_OK) ? FRAME_SENT_OK : FRAME_SENT_BAD;
741	sbni_outb(sc, DAT, SBNI_SIG);
742
743	value = (u_char)len_field;
744	sbni_outb(sc, DAT, value);
745	crc = CRC32(value, crc);
746	value = (u_char)(len_field >> 8);
747	sbni_outb(sc, DAT, value);
748	crc = CRC32(value, crc);
749
750	sbni_outb(sc, DAT, sc->tx_frameno);
751	crc = CRC32(sc->tx_frameno, crc);
752	sbni_outb(sc, DAT, 0);
753	crc = CRC32(0, crc);
754	*crc_p = crc;
755}
756
757
758/*
759 * if frame tail not needed (incorrect number or received twice),
760 * it won't store, but CRC will be calculated
761 */
762
763static int
764skip_tail(struct sbni_softc *sc, u_int tail_len, u_int32_t crc)
765{
766	while (tail_len--)
767		crc = CRC32(sbni_inb(sc, DAT), crc);
768
769	return (crc == CRC32_REMAINDER);
770}
771
772
773static int
774check_fhdr(struct sbni_softc *sc, u_int *framelen, u_int *frameno,
775	   u_int *ack, u_int *is_first, u_int32_t *crc_p)
776{
777	u_int32_t crc;
778	u_char value;
779
780	crc = *crc_p;
781	if (sbni_inb(sc, DAT) != SBNI_SIG)
782		return (0);
783
784	value = sbni_inb(sc, DAT);
785	*framelen = (u_int)value;
786	crc = CRC32(value, crc);
787	value = sbni_inb(sc, DAT);
788	*framelen |= ((u_int)value) << 8;
789	crc = CRC32(value, crc);
790
791	*ack = *framelen & FRAME_ACK_MASK;
792	*is_first = (*framelen & FRAME_FIRST) != 0;
793
794	if ((*framelen &= FRAME_LEN_MASK) < 6 || *framelen > SBNI_MAX_FRAME - 3)
795		return (0);
796
797	value = sbni_inb(sc, DAT);
798	*frameno = (u_int)value;
799	crc = CRC32(value, crc);
800
801	crc = CRC32(sbni_inb(sc, DAT), crc);		/* reserved byte */
802	*framelen -= 2;
803
804	*crc_p = crc;
805	return (1);
806}
807
808
809static int
810get_rx_buf(struct sbni_softc *sc)
811{
812	struct mbuf *m;
813
814	MGETHDR(m, M_DONTWAIT, MT_DATA);
815	if (m == NULL) {
816		if_printf(sc->ifp, "cannot allocate header mbuf\n");
817		return (0);
818	}
819
820	/*
821	 * We always put the received packet in a single buffer -
822	 * either with just an mbuf header or in a cluster attached
823	 * to the header. The +2 is to compensate for the alignment
824	 * fixup below.
825	 */
826	if (ETHER_MAX_LEN + 2 > MHLEN) {
827		/* Attach an mbuf cluster */
828		MCLGET(m, M_DONTWAIT);
829		if ((m->m_flags & M_EXT) == 0) {
830			m_freem(m);
831			return (0);
832		}
833	}
834	m->m_pkthdr.len = m->m_len = ETHER_MAX_LEN + 2;
835
836	/*
837	 * The +2 is to longword align the start of the real packet.
838	 * (sizeof ether_header == 14)
839	 * This is important for NFS.
840	 */
841	m_adj(m, 2);
842	sc->rx_buf_p = m;
843	return (1);
844}
845
846
847static void
848indicate_pkt(struct sbni_softc *sc)
849{
850	struct ifnet *ifp = sc->ifp;
851	struct mbuf *m;
852
853	m = sc->rx_buf_p;
854	m->m_pkthdr.rcvif = ifp;
855	m->m_pkthdr.len   = m->m_len = sc->inppos;
856
857	(*ifp->if_input)(ifp, m);
858	sc->rx_buf_p = NULL;
859}
860
861/* -------------------------------------------------------------------------- */
862
863/*
864 * Routine checks periodically wire activity and regenerates marker if
865 * connect was inactive for a long time.
866 */
867
868static void
869sbni_timeout(void *xsc)
870{
871	struct sbni_softc *sc;
872	int s;
873	u_char csr0;
874
875	sc = (struct sbni_softc *)xsc;
876	s = splimp();
877
878	csr0 = sbni_inb(sc, CSR0);
879	if (csr0 & RC_CHK) {
880
881		if (sc->timer_ticks) {
882			if (csr0 & (RC_RDY | BU_EMP))
883				/* receiving not active */
884				sc->timer_ticks--;
885		} else {
886			sc->in_stats.timeout_number++;
887			if (sc->delta_rxl)
888				timeout_change_level(sc);
889
890			sbni_outb(sc, CSR1, *(u_char *)&sc->csr1 | PR_RES);
891			csr0 = sbni_inb(sc, CSR0);
892		}
893	}
894
895	sbni_outb(sc, CSR0, csr0 | RC_CHK);
896	sc->wch = timeout(sbni_timeout, sc, hz/SBNI_HZ);
897	splx(s);
898}
899
900/* -------------------------------------------------------------------------- */
901
902static void
903card_start(struct sbni_softc *sc)
904{
905	sc->timer_ticks = CHANGE_LEVEL_START_TICKS;
906	sc->state &= ~(FL_WAIT_ACK | FL_NEED_RESEND);
907	sc->state |= FL_PREV_OK;
908
909	sc->inppos = 0;
910	sc->wait_frameno = 0;
911
912	sbni_outb(sc, CSR1, *(u_char *)&sc->csr1 | PR_RES);
913	sbni_outb(sc, CSR0, EN_INT);
914}
915
916/* -------------------------------------------------------------------------- */
917
918/*
919 * Device timeout/watchdog routine. Entered if the device neglects to
920 *	generate an interrupt after a transmit has been started on it.
921 */
922
923static void
924sbni_watchdog(struct ifnet *ifp)
925{
926	log(LOG_ERR, "%s: device timeout\n", ifp->if_xname);
927	ifp->if_oerrors++;
928}
929
930
931static u_char rxl_tab[] = {
932	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x08,
933	0x0a, 0x0c, 0x0f, 0x16, 0x18, 0x1a, 0x1c, 0x1f
934};
935
936#define SIZE_OF_TIMEOUT_RXL_TAB 4
937static u_char timeout_rxl_tab[] = {
938	0x03, 0x05, 0x08, 0x0b
939};
940
941static void
942set_initial_values(struct sbni_softc *sc, struct sbni_flags flags)
943{
944	if (flags.fixed_rxl) {
945		sc->delta_rxl = 0; /* disable receive level autodetection */
946		sc->cur_rxl_index = flags.rxl;
947	} else {
948		sc->delta_rxl = DEF_RXL_DELTA;
949		sc->cur_rxl_index = DEF_RXL;
950	}
951
952	sc->csr1.rate = flags.fixed_rate ? flags.rate : DEFAULT_RATE;
953	sc->csr1.rxl  = rxl_tab[sc->cur_rxl_index];
954	sc->maxframe  = DEFAULT_FRAME_LEN;
955
956	/*
957	 * generate Ethernet address (0x00ff01xxxxxx)
958	 */
959	*(u_int16_t *) sc->enaddr = htons(0x00ff);
960	if (flags.mac_addr) {
961		*(u_int32_t *) (sc->enaddr + 2) =
962		    htonl(flags.mac_addr | 0x01000000);
963	} else {
964		*(u_char *) (sc->enaddr + 2) = 0x01;
965		read_random(sc->enaddr + 3, 3);
966	}
967}
968
969
970#ifdef SBNI_DUAL_COMPOUND
971
972struct sbni_softc *
973connect_to_master(struct sbni_softc *sc)
974{
975	struct sbni_softc *p, *p_prev;
976
977	for (p = sbni_headlist, p_prev = NULL; p; p_prev = p, p = p->link) {
978		if (rman_get_start(p->io_res) == rman_get_start(sc->io_res) + 4 ||
979		    rman_get_start(p->io_res) == rman_get_start(sc->io_res) - 4) {
980			p->slave_sc = sc;
981			if (p_prev)
982				p_prev->link = p->link;
983			else
984				sbni_headlist = p->link;
985			return p;
986		}
987	}
988
989	return (NULL);
990}
991
992#endif	/* SBNI_DUAL_COMPOUND */
993
994
995/* Receive level auto-selection */
996
997static void
998change_level(struct sbni_softc *sc)
999{
1000	if (sc->delta_rxl == 0)		/* do not auto-negotiate RxL */
1001		return;
1002
1003	if (sc->cur_rxl_index == 0)
1004		sc->delta_rxl = 1;
1005	else if (sc->cur_rxl_index == 15)
1006		sc->delta_rxl = -1;
1007	else if (sc->cur_rxl_rcvd < sc->prev_rxl_rcvd)
1008		sc->delta_rxl = -sc->delta_rxl;
1009
1010	sc->csr1.rxl = rxl_tab[sc->cur_rxl_index += sc->delta_rxl];
1011	sbni_inb(sc, CSR0);	/* it needed for PCI cards */
1012	sbni_outb(sc, CSR1, *(u_char *)&sc->csr1);
1013
1014	sc->prev_rxl_rcvd = sc->cur_rxl_rcvd;
1015	sc->cur_rxl_rcvd  = 0;
1016}
1017
1018
1019static void
1020timeout_change_level(struct sbni_softc *sc)
1021{
1022	sc->cur_rxl_index = timeout_rxl_tab[sc->timeout_rxl];
1023	if (++sc->timeout_rxl >= 4)
1024		sc->timeout_rxl = 0;
1025
1026	sc->csr1.rxl = rxl_tab[sc->cur_rxl_index];
1027	sbni_inb(sc, CSR0);
1028	sbni_outb(sc, CSR1, *(u_char *)&sc->csr1);
1029
1030	sc->prev_rxl_rcvd = sc->cur_rxl_rcvd;
1031	sc->cur_rxl_rcvd  = 0;
1032}
1033
1034/* -------------------------------------------------------------------------- */
1035
1036/*
1037 * Process an ioctl request. This code needs some work - it looks
1038 *	pretty ugly.
1039 */
1040
1041static int
1042sbni_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
1043{
1044	struct sbni_softc *sc;
1045	struct ifreq *ifr;
1046	struct thread *td;
1047	struct sbni_in_stats *in_stats;
1048	struct sbni_flags flags;
1049	int error, s;
1050
1051	sc = ifp->if_softc;
1052	ifr = (struct ifreq *)data;
1053	td = curthread;
1054	error = 0;
1055
1056	s = splimp();
1057
1058	switch (command) {
1059	case SIOCSIFFLAGS:
1060		/*
1061		 * If the interface is marked up and stopped, then start it.
1062		 * If it is marked down and running, then stop it.
1063		 */
1064		if (ifp->if_flags & IFF_UP) {
1065			if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
1066				sbni_init(sc);
1067		} else {
1068			if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
1069				sbni_stop(sc);
1070				ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
1071			}
1072		}
1073		break;
1074
1075	case SIOCADDMULTI:
1076	case SIOCDELMULTI:
1077		/*
1078		 * Multicast list has changed; set the hardware filter
1079		 * accordingly.
1080		 */
1081		error = 0;
1082		/* if (ifr == NULL)
1083			error = EAFNOSUPPORT; */
1084		break;
1085
1086	case SIOCSIFMTU:
1087		if (ifr->ifr_mtu > ETHERMTU)
1088			error = EINVAL;
1089		else
1090			ifp->if_mtu = ifr->ifr_mtu;
1091		break;
1092
1093		/*
1094		 * SBNI specific ioctl
1095		 */
1096	case SIOCGHWFLAGS:	/* get flags */
1097		bcopy((caddr_t)IF_LLADDR(sc->ifp)+3, (caddr_t) &flags, 3);
1098		flags.rxl = sc->cur_rxl_index;
1099		flags.rate = sc->csr1.rate;
1100		flags.fixed_rxl = (sc->delta_rxl == 0);
1101		flags.fixed_rate = 1;
1102		ifr->ifr_data = *(caddr_t*) &flags;
1103		break;
1104
1105	case SIOCGINSTATS:
1106		in_stats = (struct sbni_in_stats *)ifr->ifr_data;
1107		bcopy((void *)(&(sc->in_stats)), (void *)in_stats,
1108		      sizeof(struct sbni_in_stats));
1109		break;
1110
1111	case SIOCSHWFLAGS:	/* set flags */
1112		/* root only */
1113		error = suser(td);
1114		if (error)
1115			break;
1116		flags = *(struct sbni_flags*)&ifr->ifr_data;
1117		if (flags.fixed_rxl) {
1118			sc->delta_rxl = 0;
1119			sc->cur_rxl_index = flags.rxl;
1120		} else {
1121			sc->delta_rxl = DEF_RXL_DELTA;
1122			sc->cur_rxl_index = DEF_RXL;
1123		}
1124		sc->csr1.rxl = rxl_tab[sc->cur_rxl_index];
1125		sc->csr1.rate = flags.fixed_rate ? flags.rate : DEFAULT_RATE;
1126		if (flags.mac_addr)
1127			bcopy((caddr_t) &flags,
1128			      (caddr_t) IF_LLADDR(sc->ifp)+3, 3);
1129
1130		/* Don't be afraid... */
1131		sbni_outb(sc, CSR1, *(char*)(&sc->csr1) | PR_RES);
1132		break;
1133
1134	case SIOCRINSTATS:
1135		if (!(error = suser(td)))	/* root only */
1136			bzero(&sc->in_stats, sizeof(struct sbni_in_stats));
1137		break;
1138
1139	default:
1140		error = ether_ioctl(ifp, command, data);
1141		break;
1142	}
1143
1144	splx(s);
1145	return (error);
1146}
1147
1148/* -------------------------------------------------------------------------- */
1149
1150#ifdef ASM_CRC
1151
1152static u_int32_t
1153calc_crc32(u_int32_t crc, caddr_t p, u_int len)
1154{
1155	register u_int32_t  _crc __asm ("ax");
1156	_crc = crc;
1157
1158	__asm __volatile (
1159		"xorl	%%ebx, %%ebx\n"
1160		"movl	%1, %%esi\n"
1161		"movl	%2, %%ecx\n"
1162		"movl	$crc32tab, %%edi\n"
1163		"shrl	$2, %%ecx\n"
1164		"jz	1f\n"
1165
1166		".align 4\n"
1167	"0:\n"
1168		"movb	%%al, %%bl\n"
1169		"movl	(%%esi), %%edx\n"
1170		"shrl	$8, %%eax\n"
1171		"xorb	%%dl, %%bl\n"
1172		"shrl	$8, %%edx\n"
1173		"xorl	(%%edi,%%ebx,4), %%eax\n"
1174
1175		"movb	%%al, %%bl\n"
1176		"shrl	$8, %%eax\n"
1177		"xorb	%%dl, %%bl\n"
1178		"shrl	$8, %%edx\n"
1179		"xorl	(%%edi,%%ebx,4), %%eax\n"
1180
1181		"movb	%%al, %%bl\n"
1182		"shrl	$8, %%eax\n"
1183		"xorb	%%dl, %%bl\n"
1184		"movb	%%dh, %%dl\n"
1185		"xorl	(%%edi,%%ebx,4), %%eax\n"
1186
1187		"movb	%%al, %%bl\n"
1188		"shrl	$8, %%eax\n"
1189		"xorb	%%dl, %%bl\n"
1190		"addl	$4, %%esi\n"
1191		"xorl	(%%edi,%%ebx,4), %%eax\n"
1192
1193		"decl	%%ecx\n"
1194		"jnz	0b\n"
1195
1196	"1:\n"
1197		"movl	%2, %%ecx\n"
1198		"andl	$3, %%ecx\n"
1199		"jz	2f\n"
1200
1201		"movb	%%al, %%bl\n"
1202		"shrl	$8, %%eax\n"
1203		"xorb	(%%esi), %%bl\n"
1204		"xorl	(%%edi,%%ebx,4), %%eax\n"
1205
1206		"decl	%%ecx\n"
1207		"jz	2f\n"
1208
1209		"movb	%%al, %%bl\n"
1210		"shrl	$8, %%eax\n"
1211		"xorb	1(%%esi), %%bl\n"
1212		"xorl	(%%edi,%%ebx,4), %%eax\n"
1213
1214		"decl	%%ecx\n"
1215		"jz	2f\n"
1216
1217		"movb	%%al, %%bl\n"
1218		"shrl	$8, %%eax\n"
1219		"xorb	2(%%esi), %%bl\n"
1220		"xorl	(%%edi,%%ebx,4), %%eax\n"
1221	"2:\n"
1222		: "=a" (_crc)
1223		: "g" (p), "g" (len)
1224		: "bx", "cx", "dx", "si", "di"
1225	);
1226
1227	return (_crc);
1228}
1229
1230#else	/* ASM_CRC */
1231
1232static u_int32_t
1233calc_crc32(u_int32_t crc, caddr_t p, u_int len)
1234{
1235	while (len--)
1236		crc = CRC32(*p++, crc);
1237
1238	return (crc);
1239}
1240
1241#endif	/* ASM_CRC */
1242
1243
1244static u_int32_t crc32tab[] __aligned(8) = {
1245	0xD202EF8D,  0xA505DF1B,  0x3C0C8EA1,  0x4B0BBE37,
1246	0xD56F2B94,  0xA2681B02,  0x3B614AB8,  0x4C667A2E,
1247	0xDCD967BF,  0xABDE5729,  0x32D70693,  0x45D03605,
1248	0xDBB4A3A6,  0xACB39330,  0x35BAC28A,  0x42BDF21C,
1249	0xCFB5FFE9,  0xB8B2CF7F,  0x21BB9EC5,  0x56BCAE53,
1250	0xC8D83BF0,  0xBFDF0B66,  0x26D65ADC,  0x51D16A4A,
1251	0xC16E77DB,  0xB669474D,  0x2F6016F7,  0x58672661,
1252	0xC603B3C2,  0xB1048354,  0x280DD2EE,  0x5F0AE278,
1253	0xE96CCF45,  0x9E6BFFD3,  0x0762AE69,  0x70659EFF,
1254	0xEE010B5C,  0x99063BCA,  0x000F6A70,  0x77085AE6,
1255	0xE7B74777,  0x90B077E1,  0x09B9265B,  0x7EBE16CD,
1256	0xE0DA836E,  0x97DDB3F8,  0x0ED4E242,  0x79D3D2D4,
1257	0xF4DBDF21,  0x83DCEFB7,  0x1AD5BE0D,  0x6DD28E9B,
1258	0xF3B61B38,  0x84B12BAE,  0x1DB87A14,  0x6ABF4A82,
1259	0xFA005713,  0x8D076785,  0x140E363F,  0x630906A9,
1260	0xFD6D930A,  0x8A6AA39C,  0x1363F226,  0x6464C2B0,
1261	0xA4DEAE1D,  0xD3D99E8B,  0x4AD0CF31,  0x3DD7FFA7,
1262	0xA3B36A04,  0xD4B45A92,  0x4DBD0B28,  0x3ABA3BBE,
1263	0xAA05262F,  0xDD0216B9,  0x440B4703,  0x330C7795,
1264	0xAD68E236,  0xDA6FD2A0,  0x4366831A,  0x3461B38C,
1265	0xB969BE79,  0xCE6E8EEF,  0x5767DF55,  0x2060EFC3,
1266	0xBE047A60,  0xC9034AF6,  0x500A1B4C,  0x270D2BDA,
1267	0xB7B2364B,  0xC0B506DD,  0x59BC5767,  0x2EBB67F1,
1268	0xB0DFF252,  0xC7D8C2C4,  0x5ED1937E,  0x29D6A3E8,
1269	0x9FB08ED5,  0xE8B7BE43,  0x71BEEFF9,  0x06B9DF6F,
1270	0x98DD4ACC,  0xEFDA7A5A,  0x76D32BE0,  0x01D41B76,
1271	0x916B06E7,  0xE66C3671,  0x7F6567CB,  0x0862575D,
1272	0x9606C2FE,  0xE101F268,  0x7808A3D2,  0x0F0F9344,
1273	0x82079EB1,  0xF500AE27,  0x6C09FF9D,  0x1B0ECF0B,
1274	0x856A5AA8,  0xF26D6A3E,  0x6B643B84,  0x1C630B12,
1275	0x8CDC1683,  0xFBDB2615,  0x62D277AF,  0x15D54739,
1276	0x8BB1D29A,  0xFCB6E20C,  0x65BFB3B6,  0x12B88320,
1277	0x3FBA6CAD,  0x48BD5C3B,  0xD1B40D81,  0xA6B33D17,
1278	0x38D7A8B4,  0x4FD09822,  0xD6D9C998,  0xA1DEF90E,
1279	0x3161E49F,  0x4666D409,  0xDF6F85B3,  0xA868B525,
1280	0x360C2086,  0x410B1010,  0xD80241AA,  0xAF05713C,
1281	0x220D7CC9,  0x550A4C5F,  0xCC031DE5,  0xBB042D73,
1282	0x2560B8D0,  0x52678846,  0xCB6ED9FC,  0xBC69E96A,
1283	0x2CD6F4FB,  0x5BD1C46D,  0xC2D895D7,  0xB5DFA541,
1284	0x2BBB30E2,  0x5CBC0074,  0xC5B551CE,  0xB2B26158,
1285	0x04D44C65,  0x73D37CF3,  0xEADA2D49,  0x9DDD1DDF,
1286	0x03B9887C,  0x74BEB8EA,  0xEDB7E950,  0x9AB0D9C6,
1287	0x0A0FC457,  0x7D08F4C1,  0xE401A57B,  0x930695ED,
1288	0x0D62004E,  0x7A6530D8,  0xE36C6162,  0x946B51F4,
1289	0x19635C01,  0x6E646C97,  0xF76D3D2D,  0x806A0DBB,
1290	0x1E0E9818,  0x6909A88E,  0xF000F934,  0x8707C9A2,
1291	0x17B8D433,  0x60BFE4A5,  0xF9B6B51F,  0x8EB18589,
1292	0x10D5102A,  0x67D220BC,  0xFEDB7106,  0x89DC4190,
1293	0x49662D3D,  0x3E611DAB,  0xA7684C11,  0xD06F7C87,
1294	0x4E0BE924,  0x390CD9B2,  0xA0058808,  0xD702B89E,
1295	0x47BDA50F,  0x30BA9599,  0xA9B3C423,  0xDEB4F4B5,
1296	0x40D06116,  0x37D75180,  0xAEDE003A,  0xD9D930AC,
1297	0x54D13D59,  0x23D60DCF,  0xBADF5C75,  0xCDD86CE3,
1298	0x53BCF940,  0x24BBC9D6,  0xBDB2986C,  0xCAB5A8FA,
1299	0x5A0AB56B,  0x2D0D85FD,  0xB404D447,  0xC303E4D1,
1300	0x5D677172,  0x2A6041E4,  0xB369105E,  0xC46E20C8,
1301	0x72080DF5,  0x050F3D63,  0x9C066CD9,  0xEB015C4F,
1302	0x7565C9EC,  0x0262F97A,  0x9B6BA8C0,  0xEC6C9856,
1303	0x7CD385C7,  0x0BD4B551,  0x92DDE4EB,  0xE5DAD47D,
1304	0x7BBE41DE,  0x0CB97148,  0x95B020F2,  0xE2B71064,
1305	0x6FBF1D91,  0x18B82D07,  0x81B17CBD,  0xF6B64C2B,
1306	0x68D2D988,  0x1FD5E91E,  0x86DCB8A4,  0xF1DB8832,
1307	0x616495A3,  0x1663A535,  0x8F6AF48F,  0xF86DC419,
1308	0x660951BA,  0x110E612C,  0x88073096,  0xFF000000
1309};
1310