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