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