if_sbni.c revision 180263
1139749Simp/*-
286752Sfjoe * Copyright (c) 1997-2001 Granch, Ltd. All rights reserved.
386752Sfjoe * Author: Denis I.Timofeev <timofeev@granch.ru>
486752Sfjoe *
586752Sfjoe * Redistributon and use in source and binary forms, with or without
686752Sfjoe * modification, are permitted provided that the following conditions
786752Sfjoe * are met:
886752Sfjoe * 1. Redistributions of source code must retain the above copyright
986752Sfjoe *    notice unmodified, this list of conditions, and the following
1086752Sfjoe *    disclaimer.
1186752Sfjoe * 2. Redistributions in binary form must reproduce the above copyright
1286752Sfjoe *    notice, this list of conditions and the following disclaimer in the
1386752Sfjoe *    documentation and/or other materials provided with the distribution.
1486752Sfjoe *
1586752Sfjoe * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1686752Sfjoe * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1786752Sfjoe * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1886752Sfjoe * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1986752Sfjoe * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2086752Sfjoe * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2186752Sfjoe * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2286752Sfjoe * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2386752Sfjoe * LIABILITY, OR TORT (INCLUDING NEIGENCE OR OTHERWISE) ARISING IN ANY WAY
2486752Sfjoe * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2586752Sfjoe * SUCH DAMAGE.
2686752Sfjoe *
2786752Sfjoe */
2886752Sfjoe
29119419Sobrien#include <sys/cdefs.h>
30119419Sobrien__FBSDID("$FreeBSD: head/sys/dev/sbni/if_sbni.c 180263 2008-07-04 20:53:41Z jhb $");
31119419Sobrien
3286752Sfjoe/*
3386752Sfjoe * Device driver for Granch SBNI12 leased line adapters
3486752Sfjoe *
3586752Sfjoe * Revision 2.0.0  1997/08/06
3686752Sfjoe * Initial revision by Alexey Zverev
3786752Sfjoe *
3886752Sfjoe * Revision 2.0.1 1997/08/11
3986752Sfjoe * Additional internal statistics support (tx statistics)
4086752Sfjoe *
4186752Sfjoe * Revision 2.0.2 1997/11/05
4286752Sfjoe * if_bpf bug has been fixed
4386752Sfjoe *
4486752Sfjoe * Revision 2.0.3 1998/12/20
4586752Sfjoe * Memory leakage has been eliminated in
4686752Sfjoe * the sbni_st and sbni_timeout routines.
4786752Sfjoe *
4886752Sfjoe * Revision 3.0 2000/08/10 by Yaroslav Polyakov
4986752Sfjoe * Support for PCI cards. 4.1 modification.
5086752Sfjoe *
5186752Sfjoe * Revision 3.1 2000/09/12
5286752Sfjoe * Removed extra #defines around bpf functions
5386752Sfjoe *
5486752Sfjoe * Revision 4.0 2000/11/23 by Denis Timofeev
5586752Sfjoe * Completely redesigned the buffer management
5686752Sfjoe *
5786752Sfjoe * Revision 4.1 2001/01/21
5886752Sfjoe * Support for PCI Dual cards and new SBNI12D-10, -11 Dual/ISA cards
5986752Sfjoe *
6086752Sfjoe * Written with reference to NE2000 driver developed by David Greenman.
6186752Sfjoe */
6286752Sfjoe
6386752Sfjoe
6486752Sfjoe#include <sys/param.h>
65180263Sjhb#include <sys/bus.h>
6686752Sfjoe#include <sys/systm.h>
6786752Sfjoe#include <sys/socket.h>
6886752Sfjoe#include <sys/sockio.h>
6986752Sfjoe#include <sys/mbuf.h>
7086752Sfjoe#include <sys/kernel.h>
71164033Srwatson#include <sys/priv.h>
7286752Sfjoe#include <sys/proc.h>
7386752Sfjoe#include <sys/callout.h>
7486752Sfjoe#include <sys/syslog.h>
75101400Sfjoe#include <sys/random.h>
7686752Sfjoe
77101400Sfjoe#include <machine/bus.h>
78101400Sfjoe#include <sys/rman.h>
79101400Sfjoe#include <machine/resource.h>
80101400Sfjoe
8186752Sfjoe#include <net/if.h>
82152315Sru#include <net/if_dl.h>
8386752Sfjoe#include <net/ethernet.h>
8486752Sfjoe#include <net/bpf.h>
85147256Sbrooks#include <net/if_types.h>
8686752Sfjoe
8786752Sfjoe#include <dev/sbni/if_sbnireg.h>
8886752Sfjoe#include <dev/sbni/if_sbnivar.h>
8986752Sfjoe
9086752Sfjoe#define ASM_CRC 1
9186752Sfjoe
9286752Sfjoestatic void	sbni_init(void *);
93180263Sjhbstatic void	sbni_init_locked(struct sbni_softc *);
9486752Sfjoestatic void	sbni_start(struct ifnet *);
95180263Sjhbstatic void	sbni_start_locked(struct ifnet *);
9686752Sfjoestatic int	sbni_ioctl(struct ifnet *, u_long, caddr_t);
9786752Sfjoestatic void	sbni_stop(struct sbni_softc *);
9886752Sfjoestatic void	handle_channel(struct sbni_softc *);
9986752Sfjoe
10086752Sfjoestatic void	card_start(struct sbni_softc *);
10186752Sfjoestatic int	recv_frame(struct sbni_softc *);
10286752Sfjoestatic void	send_frame(struct sbni_softc *);
10386752Sfjoestatic int	upload_data(struct sbni_softc *, u_int, u_int, u_int, u_int32_t);
10486752Sfjoestatic int	skip_tail(struct sbni_softc *, u_int, u_int32_t);
10586752Sfjoestatic void	interpret_ack(struct sbni_softc *, u_int);
10686752Sfjoestatic void	download_data(struct sbni_softc *, u_int32_t *);
10786752Sfjoestatic void	prepare_to_send(struct sbni_softc *);
10886752Sfjoestatic void	drop_xmit_queue(struct sbni_softc *);
10986752Sfjoestatic int	get_rx_buf(struct sbni_softc *);
11086752Sfjoestatic void	indicate_pkt(struct sbni_softc *);
11186752Sfjoestatic void	change_level(struct sbni_softc *);
11286752Sfjoestatic int	check_fhdr(struct sbni_softc *, u_int *, u_int *,
11386752Sfjoe			   u_int *, u_int *, u_int32_t *);
11486752Sfjoestatic int	append_frame_to_pkt(struct sbni_softc *, u_int, u_int32_t);
11586752Sfjoestatic void	timeout_change_level(struct sbni_softc *);
11686752Sfjoestatic void	send_frame_header(struct sbni_softc *, u_int32_t *);
11786752Sfjoestatic void	set_initial_values(struct sbni_softc *, struct sbni_flags);
11886752Sfjoe
11986752Sfjoestatic u_int32_t	calc_crc32(u_int32_t, caddr_t, u_int);
12086752Sfjoestatic timeout_t	sbni_timeout;
12186752Sfjoe
12286752Sfjoestatic __inline u_char	sbni_inb(struct sbni_softc *, enum sbni_reg);
12386752Sfjoestatic __inline void	sbni_outb(struct sbni_softc *, enum sbni_reg, u_char);
12486752Sfjoestatic __inline void	sbni_insb(struct sbni_softc *, u_char *, u_int);
12586752Sfjoestatic __inline void	sbni_outsb(struct sbni_softc *, u_char *, u_int);
12686752Sfjoe
12786752Sfjoestatic u_int32_t crc32tab[];
12886752Sfjoe
12986752Sfjoe#ifdef SBNI_DUAL_COMPOUND
130180263Sjhbstatic struct mtx headlist_lock;
131180263SjhbMTX_SYSINIT(headlist_lock, &headlist_lock, "sbni headlist", MTX_DEF);
132180263Sjhbstatic struct sbni_softc *sbni_headlist;
13386752Sfjoe#endif
13486752Sfjoe
13586752Sfjoe/* -------------------------------------------------------------------------- */
13686752Sfjoe
13786752Sfjoestatic __inline u_char
13886752Sfjoesbni_inb(struct sbni_softc *sc, enum sbni_reg reg)
13986752Sfjoe{
140101400Sfjoe	return bus_space_read_1(
141101400Sfjoe	    rman_get_bustag(sc->io_res),
142101400Sfjoe	    rman_get_bushandle(sc->io_res),
143101400Sfjoe	    sc->io_off + reg);
14486752Sfjoe}
14586752Sfjoe
14686752Sfjoestatic __inline void
14786752Sfjoesbni_outb(struct sbni_softc *sc, enum sbni_reg reg, u_char value)
14886752Sfjoe{
149101400Sfjoe	bus_space_write_1(
150101400Sfjoe	    rman_get_bustag(sc->io_res),
151101400Sfjoe	    rman_get_bushandle(sc->io_res),
152101400Sfjoe	    sc->io_off + reg, value);
15386752Sfjoe}
15486752Sfjoe
15586752Sfjoestatic __inline void
15686752Sfjoesbni_insb(struct sbni_softc *sc, u_char *to, u_int len)
15786752Sfjoe{
158101400Sfjoe	bus_space_read_multi_1(
159101400Sfjoe	    rman_get_bustag(sc->io_res),
160101400Sfjoe	    rman_get_bushandle(sc->io_res),
161101400Sfjoe	    sc->io_off + DAT, to, len);
16286752Sfjoe}
16386752Sfjoe
16486752Sfjoestatic __inline void
16586752Sfjoesbni_outsb(struct sbni_softc *sc, u_char *from, u_int len)
16686752Sfjoe{
167101400Sfjoe	bus_space_write_multi_1(
168101400Sfjoe	    rman_get_bustag(sc->io_res),
169101400Sfjoe	    rman_get_bushandle(sc->io_res),
170101400Sfjoe	    sc->io_off + DAT, from, len);
17186752Sfjoe}
17286752Sfjoe
17386752Sfjoe
17486752Sfjoe/*
17586752Sfjoe	Valid combinations in CSR0 (for probing):
17686752Sfjoe
17786752Sfjoe	VALID_DECODER	0000,0011,1011,1010
17886752Sfjoe
17986752Sfjoe				    	; 0   ; -
18086752Sfjoe				TR_REQ	; 1   ; +
18186752Sfjoe			TR_RDY	    	; 2   ; -
18286752Sfjoe			TR_RDY	TR_REQ	; 3   ; +
18386752Sfjoe		BU_EMP		    	; 4   ; +
18486752Sfjoe		BU_EMP	     	TR_REQ	; 5   ; +
18586752Sfjoe		BU_EMP	TR_RDY	    	; 6   ; -
18686752Sfjoe		BU_EMP	TR_RDY	TR_REQ	; 7   ; +
18786752Sfjoe	RC_RDY 		     		; 8   ; +
18886752Sfjoe	RC_RDY			TR_REQ	; 9   ; +
18986752Sfjoe	RC_RDY		TR_RDY		; 10  ; -
19086752Sfjoe	RC_RDY		TR_RDY	TR_REQ	; 11  ; -
19186752Sfjoe	RC_RDY	BU_EMP			; 12  ; -
19286752Sfjoe	RC_RDY	BU_EMP		TR_REQ	; 13  ; -
19386752Sfjoe	RC_RDY	BU_EMP	TR_RDY		; 14  ; -
19486752Sfjoe	RC_RDY	BU_EMP	TR_RDY	TR_REQ	; 15  ; -
19586752Sfjoe*/
19686752Sfjoe
19786752Sfjoe#define VALID_DECODER	(2 + 8 + 0x10 + 0x20 + 0x80 + 0x100 + 0x200)
19886752Sfjoe
19986752Sfjoe
20086752Sfjoeint
20186752Sfjoesbni_probe(struct sbni_softc *sc)
20286752Sfjoe{
20386752Sfjoe	u_char csr0;
20486752Sfjoe
20586752Sfjoe	csr0 = sbni_inb(sc, CSR0);
20686752Sfjoe	if (csr0 != 0xff && csr0 != 0x00) {
20786752Sfjoe		csr0 &= ~EN_INT;
20886752Sfjoe		if (csr0 & BU_EMP)
20986752Sfjoe			csr0 |= EN_INT;
21086752Sfjoe
21186752Sfjoe		if (VALID_DECODER & (1 << (csr0 >> 4)))
21286752Sfjoe			return (0);
21386752Sfjoe	}
21486752Sfjoe
21586752Sfjoe	return (ENXIO);
21686752Sfjoe}
21786752Sfjoe
21886752Sfjoe
21986752Sfjoe/*
22086752Sfjoe * Install interface into kernel networking data structures
22186752Sfjoe */
222180263Sjhbint
22386752Sfjoesbni_attach(struct sbni_softc *sc, int unit, struct sbni_flags flags)
22486752Sfjoe{
22586752Sfjoe	struct ifnet *ifp;
22686752Sfjoe	u_char csr0;
22786752Sfjoe
228147256Sbrooks	ifp = sc->ifp = if_alloc(IFT_ETHER);
229147256Sbrooks	if (ifp == NULL)
230180263Sjhb		return (ENOMEM);
23186752Sfjoe	sbni_outb(sc, CSR0, 0);
23286752Sfjoe	set_initial_values(sc, flags);
23386752Sfjoe
234121752Sbrooks	/* Initialize ifnet structure */
235121752Sbrooks	ifp->if_softc	= sc;
236121816Sbrooks	if_initname(ifp, "sbni", unit);
237121752Sbrooks	ifp->if_init	= sbni_init;
238121752Sbrooks	ifp->if_start	= sbni_start;
239121752Sbrooks	ifp->if_ioctl	= sbni_ioctl;
240180263Sjhb	IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
24186752Sfjoe
242121752Sbrooks	/* report real baud rate */
243121752Sbrooks	csr0 = sbni_inb(sc, CSR0);
244121752Sbrooks	ifp->if_baudrate =
245121752Sbrooks		(csr0 & 0x01 ? 500000 : 2000000) / (1 << flags.rate);
24686752Sfjoe
247180263Sjhb	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
248180263Sjhb
249180263Sjhb	mtx_init(&sc->lock, ifp->if_xname, MTX_NETWORK_LOCK, MTX_DEF);
250180263Sjhb	callout_init_mtx(&sc->wch, &sc->lock, 0);
251147256Sbrooks	ether_ifattach(ifp, sc->enaddr);
25286752Sfjoe	/* device attach does transition from UNCONFIGURED to IDLE state */
25386752Sfjoe
254126966Smdodd	if_printf(ifp, "speed %ld, rxl ", ifp->if_baudrate);
25586752Sfjoe	if (sc->delta_rxl)
25686752Sfjoe		printf("auto\n");
25786752Sfjoe	else
25886752Sfjoe		printf("%d (fixed)\n", sc->cur_rxl_index);
259180263Sjhb	return (0);
26086752Sfjoe}
26186752Sfjoe
262180263Sjhbvoid
263180263Sjhbsbni_detach(struct sbni_softc *sc)
264180263Sjhb{
265180263Sjhb
266180263Sjhb	SBNI_LOCK(sc);
267180263Sjhb	sbni_stop(sc);
268180263Sjhb	SBNI_UNLOCK(sc);
269180263Sjhb	callout_drain(&sc->wch);
270180263Sjhb	ether_ifdetach(sc->ifp);
271180263Sjhb	if (sc->irq_handle)
272180263Sjhb		bus_teardown_intr(sc->dev, sc->irq_res, sc->irq_handle);
273180263Sjhb	mtx_destroy(&sc->lock);
274180263Sjhb	if_free(sc->ifp);
275180263Sjhb}
276180263Sjhb
277180263Sjhbvoid
278180263Sjhbsbni_release_resources(struct sbni_softc *sc)
279180263Sjhb{
280180263Sjhb
281180263Sjhb	if (sc->irq_res)
282180263Sjhb		bus_release_resource(sc->dev, SYS_RES_IRQ, sc->irq_rid,
283180263Sjhb		    sc->irq_res);
284180263Sjhb	if (sc->io_res && sc->io_off == 0)
285180263Sjhb		bus_release_resource(sc->dev, SYS_RES_IOPORT, sc->io_rid,
286180263Sjhb		    sc->io_res);
287180263Sjhb}
288180263Sjhb
28986752Sfjoe/* -------------------------------------------------------------------------- */
29086752Sfjoe
29186752Sfjoestatic void
29286752Sfjoesbni_init(void *xsc)
29386752Sfjoe{
29486752Sfjoe	struct sbni_softc *sc;
295180263Sjhb
296180263Sjhb	sc = (struct sbni_softc *)xsc;
297180263Sjhb	SBNI_LOCK(sc);
298180263Sjhb	sbni_init_locked(sc);
299180263Sjhb	SBNI_UNLOCK(sc);
300180263Sjhb}
301180263Sjhb
302180263Sjhbstatic void
303180263Sjhbsbni_init_locked(struct sbni_softc *sc)
304180263Sjhb{
30586752Sfjoe	struct ifnet *ifp;
30686752Sfjoe
307147256Sbrooks	ifp = sc->ifp;
30886752Sfjoe
30986752Sfjoe	/*
31086752Sfjoe	 * kludge to avoid multiple initialization when more than once
31186752Sfjoe	 * protocols configured
31286752Sfjoe	 */
313148887Srwatson	if (ifp->if_drv_flags & IFF_DRV_RUNNING)
31486752Sfjoe		return;
31586752Sfjoe
31686752Sfjoe	card_start(sc);
317180263Sjhb	callout_reset(&sc->wch, hz/SBNI_HZ, sbni_timeout, sc);
31886752Sfjoe
319148887Srwatson	ifp->if_drv_flags |= IFF_DRV_RUNNING;
320148887Srwatson	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
32186752Sfjoe
32286752Sfjoe	/* attempt to start output */
323180263Sjhb	sbni_start_locked(ifp);
32486752Sfjoe}
32586752Sfjoe
32686752Sfjoestatic void
32786752Sfjoesbni_start(struct ifnet *ifp)
32886752Sfjoe{
32986752Sfjoe	struct sbni_softc *sc = ifp->if_softc;
330180263Sjhb
331180263Sjhb	SBNI_LOCK(sc);
332180263Sjhb	sbni_start_locked(ifp);
333180263Sjhb	SBNI_UNLOCK(sc);
334180263Sjhb}
335180263Sjhb
336180263Sjhbstatic void
337180263Sjhbsbni_start_locked(struct ifnet *ifp)
338180263Sjhb{
339180263Sjhb	struct sbni_softc *sc = ifp->if_softc;
340180263Sjhb
34186752Sfjoe	if (sc->tx_frameno == 0)
34286752Sfjoe		prepare_to_send(sc);
34386752Sfjoe}
34486752Sfjoe
34586752Sfjoe
34686752Sfjoestatic void
34786752Sfjoesbni_stop(struct sbni_softc *sc)
34886752Sfjoe{
34986752Sfjoe	sbni_outb(sc, CSR0, 0);
35086752Sfjoe	drop_xmit_queue(sc);
35186752Sfjoe
35286752Sfjoe	if (sc->rx_buf_p) {
35386752Sfjoe		m_freem(sc->rx_buf_p);
35486752Sfjoe		sc->rx_buf_p = NULL;
35586752Sfjoe	}
35686752Sfjoe
357180263Sjhb	callout_stop(&sc->wch);
358180263Sjhb	sc->ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
35986752Sfjoe}
36086752Sfjoe
36186752Sfjoe/* -------------------------------------------------------------------------- */
36286752Sfjoe
36386752Sfjoe/* interrupt handler */
36486752Sfjoe
36586752Sfjoe/*
36686752Sfjoe * 	SBNI12D-10, -11/ISA boards within "common interrupt" mode could not
36786752Sfjoe * be looked as two independent single-channel devices. Every channel seems
36886752Sfjoe * as Ethernet interface but interrupt handler must be common. Really, first
36986752Sfjoe * channel ("master") driver only registers the handler. In it's struct softc
37086752Sfjoe * it has got pointer to "slave" channel's struct softc and handles that's
37186752Sfjoe * interrupts too.
37286752Sfjoe *	softc of successfully attached ISA SBNI boards is linked to list.
37386752Sfjoe * While next board driver is initialized, it scans this list. If one
37486752Sfjoe * has found softc with same irq and ioaddr different by 4 then it assumes
37586752Sfjoe * this board to be "master".
37686752Sfjoe */
37786752Sfjoe
37886752Sfjoevoid
37986752Sfjoesbni_intr(void *arg)
38086752Sfjoe{
38186752Sfjoe	struct sbni_softc *sc;
38286752Sfjoe	int repeat;
38386752Sfjoe
38486752Sfjoe	sc = (struct sbni_softc *)arg;
38586752Sfjoe
38686752Sfjoe	do {
38786752Sfjoe		repeat = 0;
388180263Sjhb		SBNI_LOCK(sc);
38986752Sfjoe		if (sbni_inb(sc, CSR0) & (RC_RDY | TR_RDY)) {
39086752Sfjoe			handle_channel(sc);
39186752Sfjoe			repeat = 1;
39286752Sfjoe		}
393180263Sjhb		SBNI_UNLOCK(sc);
394180263Sjhb		if (sc->slave_sc) {
395180263Sjhb			/* second channel present */
396180263Sjhb			SBNI_LOCK(sc->slave_sc);
397180263Sjhb			if (sbni_inb(sc->slave_sc, CSR0) & (RC_RDY | TR_RDY)) {
398180263Sjhb				handle_channel(sc->slave_sc);
399180263Sjhb				repeat = 1;
400180263Sjhb			}
401180263Sjhb			SBNI_UNLOCK(sc->slave_sc);
40286752Sfjoe		}
40386752Sfjoe	} while (repeat);
40486752Sfjoe}
40586752Sfjoe
40686752Sfjoe
40786752Sfjoestatic void
40886752Sfjoehandle_channel(struct sbni_softc *sc)
40986752Sfjoe{
41086752Sfjoe	int req_ans;
41186752Sfjoe	u_char csr0;
41286752Sfjoe
41386752Sfjoe	sbni_outb(sc, CSR0, (sbni_inb(sc, CSR0) & ~EN_INT) | TR_REQ);
41486752Sfjoe
41586752Sfjoe	sc->timer_ticks = CHANGE_LEVEL_START_TICKS;
41686752Sfjoe	for (;;) {
41786752Sfjoe		csr0 = sbni_inb(sc, CSR0);
41886752Sfjoe		if ((csr0 & (RC_RDY | TR_RDY)) == 0)
41986752Sfjoe			break;
42086752Sfjoe
42186752Sfjoe		req_ans = !(sc->state & FL_PREV_OK);
42286752Sfjoe
42386752Sfjoe		if (csr0 & RC_RDY)
42486752Sfjoe			req_ans = recv_frame(sc);
42586752Sfjoe
42686752Sfjoe		/*
42786752Sfjoe		 * TR_RDY always equals 1 here because we have owned the marker,
42886752Sfjoe		 * and we set TR_REQ when disabled interrupts
42986752Sfjoe		 */
43086752Sfjoe		csr0 = sbni_inb(sc, CSR0);
43186752Sfjoe		if ((csr0 & TR_RDY) == 0 || (csr0 & RC_RDY) != 0)
432180263Sjhb			if_printf(sc->ifp, "internal error!\n");
43386752Sfjoe
43486752Sfjoe		/* if state & FL_NEED_RESEND != 0 then tx_frameno != 0 */
43586752Sfjoe		if (req_ans || sc->tx_frameno != 0)
43686752Sfjoe			send_frame(sc);
437101393Sfjoe		else {
43886752Sfjoe			/* send the marker without any data */
43986752Sfjoe			sbni_outb(sc, CSR0, sbni_inb(sc, CSR0) & ~TR_REQ);
440101393Sfjoe		}
44186752Sfjoe	}
44286752Sfjoe
44386752Sfjoe	sbni_outb(sc, CSR0, sbni_inb(sc, CSR0) | EN_INT);
44486752Sfjoe}
44586752Sfjoe
44686752Sfjoe
44786752Sfjoe/*
44886752Sfjoe * Routine returns 1 if it need to acknoweledge received frame.
44986752Sfjoe * Empty frame received without errors won't be acknoweledged.
45086752Sfjoe */
45186752Sfjoe
45286752Sfjoestatic int
45386752Sfjoerecv_frame(struct sbni_softc *sc)
45486752Sfjoe{
45586752Sfjoe	u_int32_t crc;
45686752Sfjoe	u_int framelen, frameno, ack;
45786752Sfjoe	u_int is_first, frame_ok;
45886752Sfjoe
45986752Sfjoe	crc = CRC32_INITIAL;
46086752Sfjoe	if (check_fhdr(sc, &framelen, &frameno, &ack, &is_first, &crc)) {
461101393Sfjoe		frame_ok = framelen > 4 ?
462101393Sfjoe		    upload_data(sc, framelen, frameno, is_first, crc) :
463101393Sfjoe		    skip_tail(sc, framelen, crc);
46486752Sfjoe		if (frame_ok)
46586752Sfjoe			interpret_ack(sc, ack);
466171243Speter	} else {
467171243Speter		framelen = 0;
46886752Sfjoe		frame_ok = 0;
469171243Speter	}
47086752Sfjoe
47186752Sfjoe	sbni_outb(sc, CSR0, sbni_inb(sc, CSR0) ^ CT_ZER);
47286752Sfjoe	if (frame_ok) {
47386752Sfjoe		sc->state |= FL_PREV_OK;
47486752Sfjoe		if (framelen > 4)
47586752Sfjoe			sc->in_stats.all_rx_number++;
47686752Sfjoe	} else {
47786752Sfjoe		sc->state &= ~FL_PREV_OK;
47886752Sfjoe		change_level(sc);
47986752Sfjoe		sc->in_stats.all_rx_number++;
48086752Sfjoe		sc->in_stats.bad_rx_number++;
48186752Sfjoe	}
48286752Sfjoe
48386752Sfjoe	return (!frame_ok || framelen > 4);
48486752Sfjoe}
48586752Sfjoe
48686752Sfjoe
48786752Sfjoestatic void
48886752Sfjoesend_frame(struct sbni_softc *sc)
48986752Sfjoe{
49086752Sfjoe	u_int32_t crc;
49186752Sfjoe	u_char csr0;
49286752Sfjoe
49386752Sfjoe	crc = CRC32_INITIAL;
49486752Sfjoe	if (sc->state & FL_NEED_RESEND) {
49586752Sfjoe
49686752Sfjoe		/* if frame was sended but not ACK'ed - resend it */
49786752Sfjoe		if (sc->trans_errors) {
49886752Sfjoe			sc->trans_errors--;
49986752Sfjoe			if (sc->framelen != 0)
50086752Sfjoe				sc->in_stats.resend_tx_number++;
50186752Sfjoe		} else {
50286752Sfjoe			/* cannot xmit with many attempts */
50386752Sfjoe			drop_xmit_queue(sc);
50486752Sfjoe			goto do_send;
50586752Sfjoe		}
50686752Sfjoe	} else
50786752Sfjoe		sc->trans_errors = TR_ERROR_COUNT;
50886752Sfjoe
50986752Sfjoe	send_frame_header(sc, &crc);
51086752Sfjoe	sc->state |= FL_NEED_RESEND;
51186752Sfjoe	/*
51286752Sfjoe	 * FL_NEED_RESEND will be cleared after ACK, but if empty
51386752Sfjoe	 * frame sended then in prepare_to_send next frame
51486752Sfjoe	 */
51586752Sfjoe
51686752Sfjoe
51786752Sfjoe	if (sc->framelen) {
51886752Sfjoe		download_data(sc, &crc);
51986752Sfjoe		sc->in_stats.all_tx_number++;
52086752Sfjoe		sc->state |= FL_WAIT_ACK;
52186752Sfjoe	}
52286752Sfjoe
52386752Sfjoe	sbni_outsb(sc, (u_char *)&crc, sizeof crc);
52486752Sfjoe
52586752Sfjoedo_send:
52686752Sfjoe	csr0 = sbni_inb(sc, CSR0);
52786752Sfjoe	sbni_outb(sc, CSR0, csr0 & ~TR_REQ);
52886752Sfjoe
52986752Sfjoe	if (sc->tx_frameno) {
53086752Sfjoe		/* next frame exists - request to send */
53186752Sfjoe		sbni_outb(sc, CSR0, csr0 | TR_REQ);
53286752Sfjoe	}
53386752Sfjoe}
53486752Sfjoe
53586752Sfjoe
53686752Sfjoestatic void
53786752Sfjoedownload_data(struct sbni_softc *sc, u_int32_t *crc_p)
53886752Sfjoe{
53986752Sfjoe	struct mbuf *m;
54086752Sfjoe	caddr_t	data_p;
54186752Sfjoe	u_int data_len, pos, slice;
54286752Sfjoe
54386752Sfjoe	data_p = NULL;		/* initialized to avoid warn */
54486752Sfjoe	pos = 0;
54586752Sfjoe
54686752Sfjoe	for (m = sc->tx_buf_p;  m != NULL && pos < sc->pktlen;  m = m->m_next) {
54786752Sfjoe		if (pos + m->m_len > sc->outpos) {
54886752Sfjoe			data_len = m->m_len - (sc->outpos - pos);
54986752Sfjoe			data_p = mtod(m, caddr_t) + (sc->outpos - pos);
55086752Sfjoe
55186752Sfjoe			goto do_copy;
55286752Sfjoe		} else
55386752Sfjoe			pos += m->m_len;
55486752Sfjoe	}
55586752Sfjoe
55686752Sfjoe	data_len = 0;
55786752Sfjoe
55886752Sfjoedo_copy:
55986752Sfjoe	pos = 0;
56086752Sfjoe	do {
56186752Sfjoe		if (data_len) {
56286752Sfjoe			slice = min(data_len, sc->framelen - pos);
56386752Sfjoe			sbni_outsb(sc, data_p, slice);
56486752Sfjoe			*crc_p = calc_crc32(*crc_p, data_p, slice);
56586752Sfjoe
56686752Sfjoe			pos += slice;
56786752Sfjoe			if (data_len -= slice)
56886752Sfjoe				data_p += slice;
56986752Sfjoe			else {
570101393Sfjoe				do {
571101393Sfjoe					m = m->m_next;
572101393Sfjoe				} while (m != NULL && m->m_len == 0);
57386752Sfjoe
57486752Sfjoe				if (m) {
57586752Sfjoe					data_len = m->m_len;
57686752Sfjoe					data_p = mtod(m, caddr_t);
57786752Sfjoe				}
57886752Sfjoe			}
57986752Sfjoe		} else {
58086752Sfjoe			/* frame too short - zero padding */
58186752Sfjoe
58286752Sfjoe			pos = sc->framelen - pos;
58386752Sfjoe			while (pos--) {
58486752Sfjoe				sbni_outb(sc, DAT, 0);
58586752Sfjoe				*crc_p = CRC32(0, *crc_p);
58686752Sfjoe			}
58786752Sfjoe			return;
58886752Sfjoe		}
58986752Sfjoe	} while (pos < sc->framelen);
59086752Sfjoe}
59186752Sfjoe
59286752Sfjoe
59386752Sfjoestatic int
59486752Sfjoeupload_data(struct sbni_softc *sc, u_int framelen, u_int frameno,
59586752Sfjoe	    u_int is_first, u_int32_t crc)
59686752Sfjoe{
59786752Sfjoe	int frame_ok;
59886752Sfjoe
59986752Sfjoe	if (is_first) {
60086752Sfjoe		sc->wait_frameno = frameno;
60186752Sfjoe		sc->inppos = 0;
60286752Sfjoe	}
60386752Sfjoe
60486752Sfjoe	if (sc->wait_frameno == frameno) {
60586752Sfjoe
60686752Sfjoe		if (sc->inppos + framelen  <=  ETHER_MAX_LEN) {
60786752Sfjoe			frame_ok = append_frame_to_pkt(sc, framelen, crc);
60886752Sfjoe
60986752Sfjoe		/*
61086752Sfjoe		 * if CRC is right but framelen incorrect then transmitter
61186752Sfjoe		 * error was occured... drop entire packet
61286752Sfjoe		 */
61386752Sfjoe		} else if ((frame_ok = skip_tail(sc, framelen, crc)) != 0) {
61486752Sfjoe			sc->wait_frameno = 0;
61586752Sfjoe			sc->inppos = 0;
616147256Sbrooks			sc->ifp->if_ierrors++;
61786752Sfjoe			/* now skip all frames until is_first != 0 */
61886752Sfjoe		}
61986752Sfjoe	} else
62086752Sfjoe		frame_ok = skip_tail(sc, framelen, crc);
62186752Sfjoe
62286752Sfjoe	if (is_first && !frame_ok) {
62386752Sfjoe		/*
62486752Sfjoe		 * Frame has been violated, but we have stored
62586752Sfjoe		 * is_first already... Drop entire packet.
62686752Sfjoe		 */
62786752Sfjoe		sc->wait_frameno = 0;
628147256Sbrooks		sc->ifp->if_ierrors++;
62986752Sfjoe	}
63086752Sfjoe
63186752Sfjoe	return (frame_ok);
63286752Sfjoe}
63386752Sfjoe
63486752Sfjoe
63586752Sfjoestatic __inline void	send_complete(struct sbni_softc *);
63686752Sfjoe
63786752Sfjoestatic __inline void
63886752Sfjoesend_complete(struct sbni_softc *sc)
63986752Sfjoe{
64086752Sfjoe	m_freem(sc->tx_buf_p);
64186752Sfjoe	sc->tx_buf_p = NULL;
642147256Sbrooks	sc->ifp->if_opackets++;
64386752Sfjoe}
64486752Sfjoe
64586752Sfjoe
64686752Sfjoestatic void
64786752Sfjoeinterpret_ack(struct sbni_softc *sc, u_int ack)
64886752Sfjoe{
64986752Sfjoe	if (ack == FRAME_SENT_OK) {
65086752Sfjoe		sc->state &= ~FL_NEED_RESEND;
65186752Sfjoe
65286752Sfjoe		if (sc->state & FL_WAIT_ACK) {
65386752Sfjoe			sc->outpos += sc->framelen;
65486752Sfjoe
655101393Sfjoe			if (--sc->tx_frameno) {
656101393Sfjoe				sc->framelen = min(
657101393Sfjoe				    sc->maxframe, sc->pktlen - sc->outpos);
658101393Sfjoe			} else {
65986752Sfjoe				send_complete(sc);
66086752Sfjoe				prepare_to_send(sc);
66186752Sfjoe			}
66286752Sfjoe		}
66386752Sfjoe	}
66486752Sfjoe
66586752Sfjoe	sc->state &= ~FL_WAIT_ACK;
66686752Sfjoe}
66786752Sfjoe
66886752Sfjoe
66986752Sfjoe/*
67086752Sfjoe * Glue received frame with previous fragments of packet.
67186752Sfjoe * Indicate packet when last frame would be accepted.
67286752Sfjoe */
67386752Sfjoe
67486752Sfjoestatic int
67586752Sfjoeappend_frame_to_pkt(struct sbni_softc *sc, u_int framelen, u_int32_t crc)
67686752Sfjoe{
67786752Sfjoe	caddr_t p;
67886752Sfjoe
67986752Sfjoe	if (sc->inppos + framelen > ETHER_MAX_LEN)
68086752Sfjoe		return (0);
68186752Sfjoe
68286752Sfjoe	if (!sc->rx_buf_p && !get_rx_buf(sc))
68386752Sfjoe		return (0);
68486752Sfjoe
68586752Sfjoe	p = sc->rx_buf_p->m_data + sc->inppos;
68686752Sfjoe	sbni_insb(sc, p, framelen);
68786752Sfjoe	if (calc_crc32(crc, p, framelen) != CRC32_REMAINDER)
68886752Sfjoe		return (0);
68986752Sfjoe
69086752Sfjoe	sc->inppos += framelen - 4;
69186752Sfjoe	if (--sc->wait_frameno == 0) {		/* last frame received */
69286752Sfjoe		indicate_pkt(sc);
693147256Sbrooks		sc->ifp->if_ipackets++;
69486752Sfjoe	}
69586752Sfjoe
69686752Sfjoe	return (1);
69786752Sfjoe}
69886752Sfjoe
69986752Sfjoe
70086752Sfjoe/*
70186752Sfjoe * Prepare to start output on adapter. Current priority must be set to splimp
70286752Sfjoe * before this routine is called.
70386752Sfjoe * Transmitter will be actually activated when marker has been accepted.
70486752Sfjoe */
70586752Sfjoe
70686752Sfjoestatic void
70786752Sfjoeprepare_to_send(struct sbni_softc *sc)
70886752Sfjoe{
70986752Sfjoe	struct mbuf *m;
71086752Sfjoe	u_int len;
71186752Sfjoe
71286752Sfjoe	/* sc->tx_buf_p == NULL here! */
71386752Sfjoe	if (sc->tx_buf_p)
71486752Sfjoe		printf("sbni: memory leak!\n");
71586752Sfjoe
71686752Sfjoe	sc->outpos = 0;
71786752Sfjoe	sc->state &= ~(FL_WAIT_ACK | FL_NEED_RESEND);
71886752Sfjoe
71986752Sfjoe	for (;;) {
720147256Sbrooks		IF_DEQUEUE(&sc->ifp->if_snd, sc->tx_buf_p);
72186752Sfjoe		if (!sc->tx_buf_p) {
72286752Sfjoe			/* nothing to transmit... */
72386752Sfjoe			sc->pktlen     = 0;
72486752Sfjoe			sc->tx_frameno = 0;
72586752Sfjoe			sc->framelen   = 0;
726148887Srwatson			sc->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
72786752Sfjoe			return;
72886752Sfjoe		}
72986752Sfjoe
73086752Sfjoe		for (len = 0, m = sc->tx_buf_p;  m;  m = m->m_next)
73186752Sfjoe			len += m->m_len;
73286752Sfjoe
73386752Sfjoe		if (len != 0)
73486752Sfjoe			break;
73586752Sfjoe		m_freem(sc->tx_buf_p);
73686752Sfjoe	}
73786752Sfjoe
73886752Sfjoe	if (len < SBNI_MIN_LEN)
73986752Sfjoe		len = SBNI_MIN_LEN;
74086752Sfjoe
74186752Sfjoe	sc->pktlen	= len;
74286752Sfjoe	sc->tx_frameno	= (len + sc->maxframe - 1) / sc->maxframe;
74386752Sfjoe	sc->framelen	= min(len, sc->maxframe);
74486752Sfjoe
74586752Sfjoe	sbni_outb(sc, CSR0, sbni_inb(sc, CSR0) | TR_REQ);
746148887Srwatson	sc->ifp->if_drv_flags |= IFF_DRV_OACTIVE;
747147256Sbrooks	BPF_MTAP(sc->ifp, sc->tx_buf_p);
74886752Sfjoe}
74986752Sfjoe
75086752Sfjoe
75186752Sfjoestatic void
75286752Sfjoedrop_xmit_queue(struct sbni_softc *sc)
75386752Sfjoe{
75486752Sfjoe	struct mbuf *m;
75586752Sfjoe
75686752Sfjoe	if (sc->tx_buf_p) {
75786752Sfjoe		m_freem(sc->tx_buf_p);
75886752Sfjoe		sc->tx_buf_p = NULL;
759147256Sbrooks		sc->ifp->if_oerrors++;
76086752Sfjoe	}
76186752Sfjoe
76286752Sfjoe	for (;;) {
763147256Sbrooks		IF_DEQUEUE(&sc->ifp->if_snd, m);
76486752Sfjoe		if (m == NULL)
76586752Sfjoe			break;
76686752Sfjoe		m_freem(m);
767147256Sbrooks		sc->ifp->if_oerrors++;
76886752Sfjoe	}
76986752Sfjoe
77086752Sfjoe	sc->tx_frameno	= 0;
77186752Sfjoe	sc->framelen	= 0;
77286752Sfjoe	sc->outpos	= 0;
77386752Sfjoe	sc->state &= ~(FL_WAIT_ACK | FL_NEED_RESEND);
774148887Srwatson	sc->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
77586752Sfjoe}
77686752Sfjoe
77786752Sfjoe
77886752Sfjoestatic void
77986752Sfjoesend_frame_header(struct sbni_softc *sc, u_int32_t *crc_p)
78086752Sfjoe{
78186752Sfjoe	u_int32_t crc;
78286752Sfjoe	u_int len_field;
78386752Sfjoe	u_char value;
78486752Sfjoe
78586752Sfjoe	crc = *crc_p;
78686752Sfjoe	len_field = sc->framelen + 6;	/* CRC + frameno + reserved */
78786752Sfjoe
78886752Sfjoe	if (sc->state & FL_NEED_RESEND)
78986752Sfjoe		len_field |= FRAME_RETRY;	/* non-first attempt... */
79086752Sfjoe
79186752Sfjoe	if (sc->outpos == 0)
79286752Sfjoe		len_field |= FRAME_FIRST;
79386752Sfjoe
79486752Sfjoe	len_field |= (sc->state & FL_PREV_OK) ? FRAME_SENT_OK : FRAME_SENT_BAD;
79586752Sfjoe	sbni_outb(sc, DAT, SBNI_SIG);
79686752Sfjoe
79786752Sfjoe	value = (u_char)len_field;
79886752Sfjoe	sbni_outb(sc, DAT, value);
79986752Sfjoe	crc = CRC32(value, crc);
80086752Sfjoe	value = (u_char)(len_field >> 8);
80186752Sfjoe	sbni_outb(sc, DAT, value);
80286752Sfjoe	crc = CRC32(value, crc);
80386752Sfjoe
80486752Sfjoe	sbni_outb(sc, DAT, sc->tx_frameno);
80586752Sfjoe	crc = CRC32(sc->tx_frameno, crc);
80686752Sfjoe	sbni_outb(sc, DAT, 0);
80786752Sfjoe	crc = CRC32(0, crc);
80886752Sfjoe	*crc_p = crc;
80986752Sfjoe}
81086752Sfjoe
81186752Sfjoe
81286752Sfjoe/*
81386752Sfjoe * if frame tail not needed (incorrect number or received twice),
81486752Sfjoe * it won't store, but CRC will be calculated
81586752Sfjoe */
81686752Sfjoe
81786752Sfjoestatic int
81886752Sfjoeskip_tail(struct sbni_softc *sc, u_int tail_len, u_int32_t crc)
81986752Sfjoe{
82086752Sfjoe	while (tail_len--)
82186752Sfjoe		crc = CRC32(sbni_inb(sc, DAT), crc);
82286752Sfjoe
82386752Sfjoe	return (crc == CRC32_REMAINDER);
82486752Sfjoe}
82586752Sfjoe
82686752Sfjoe
82786752Sfjoestatic int
82886752Sfjoecheck_fhdr(struct sbni_softc *sc, u_int *framelen, u_int *frameno,
82986752Sfjoe	   u_int *ack, u_int *is_first, u_int32_t *crc_p)
83086752Sfjoe{
83186752Sfjoe	u_int32_t crc;
83286752Sfjoe	u_char value;
83386752Sfjoe
83486752Sfjoe	crc = *crc_p;
83586752Sfjoe	if (sbni_inb(sc, DAT) != SBNI_SIG)
83686752Sfjoe		return (0);
83786752Sfjoe
83886752Sfjoe	value = sbni_inb(sc, DAT);
83986752Sfjoe	*framelen = (u_int)value;
84086752Sfjoe	crc = CRC32(value, crc);
84186752Sfjoe	value = sbni_inb(sc, DAT);
84286752Sfjoe	*framelen |= ((u_int)value) << 8;
84386752Sfjoe	crc = CRC32(value, crc);
84486752Sfjoe
84586752Sfjoe	*ack = *framelen & FRAME_ACK_MASK;
84686752Sfjoe	*is_first = (*framelen & FRAME_FIRST) != 0;
84786752Sfjoe
84886752Sfjoe	if ((*framelen &= FRAME_LEN_MASK) < 6 || *framelen > SBNI_MAX_FRAME - 3)
84986752Sfjoe		return (0);
85086752Sfjoe
85186752Sfjoe	value = sbni_inb(sc, DAT);
85286752Sfjoe	*frameno = (u_int)value;
85386752Sfjoe	crc = CRC32(value, crc);
85486752Sfjoe
85586752Sfjoe	crc = CRC32(sbni_inb(sc, DAT), crc);		/* reserved byte */
85686752Sfjoe	*framelen -= 2;
85786752Sfjoe
85886752Sfjoe	*crc_p = crc;
85986752Sfjoe	return (1);
86086752Sfjoe}
86186752Sfjoe
86286752Sfjoe
86386752Sfjoestatic int
86486752Sfjoeget_rx_buf(struct sbni_softc *sc)
86586752Sfjoe{
86686752Sfjoe	struct mbuf *m;
86786752Sfjoe
868111119Simp	MGETHDR(m, M_DONTWAIT, MT_DATA);
86986752Sfjoe	if (m == NULL) {
870147256Sbrooks		if_printf(sc->ifp, "cannot allocate header mbuf\n");
87186752Sfjoe		return (0);
87286752Sfjoe	}
87386752Sfjoe
87486752Sfjoe	/*
87586752Sfjoe	 * We always put the received packet in a single buffer -
87686752Sfjoe	 * either with just an mbuf header or in a cluster attached
87786752Sfjoe	 * to the header. The +2 is to compensate for the alignment
87886752Sfjoe	 * fixup below.
87986752Sfjoe	 */
88086752Sfjoe	if (ETHER_MAX_LEN + 2 > MHLEN) {
88186752Sfjoe		/* Attach an mbuf cluster */
882111119Simp		MCLGET(m, M_DONTWAIT);
88386752Sfjoe		if ((m->m_flags & M_EXT) == 0) {
88486752Sfjoe			m_freem(m);
88586752Sfjoe			return (0);
88686752Sfjoe		}
88786752Sfjoe	}
88886752Sfjoe	m->m_pkthdr.len = m->m_len = ETHER_MAX_LEN + 2;
88986752Sfjoe
89086752Sfjoe	/*
89186752Sfjoe	 * The +2 is to longword align the start of the real packet.
89286752Sfjoe	 * (sizeof ether_header == 14)
89386752Sfjoe	 * This is important for NFS.
89486752Sfjoe	 */
89586752Sfjoe	m_adj(m, 2);
89686752Sfjoe	sc->rx_buf_p = m;
89786752Sfjoe	return (1);
89886752Sfjoe}
89986752Sfjoe
90086752Sfjoe
90186752Sfjoestatic void
90286752Sfjoeindicate_pkt(struct sbni_softc *sc)
90386752Sfjoe{
904147256Sbrooks	struct ifnet *ifp = sc->ifp;
90586752Sfjoe	struct mbuf *m;
90686752Sfjoe
90786752Sfjoe	m = sc->rx_buf_p;
908106937Ssam	m->m_pkthdr.rcvif = ifp;
90986752Sfjoe	m->m_pkthdr.len   = m->m_len = sc->inppos;
910180263Sjhb	sc->rx_buf_p = NULL;
91186752Sfjoe
912180263Sjhb	SBNI_UNLOCK(sc);
913106937Ssam	(*ifp->if_input)(ifp, m);
914180263Sjhb	SBNI_LOCK(sc);
91586752Sfjoe}
91686752Sfjoe
91786752Sfjoe/* -------------------------------------------------------------------------- */
91886752Sfjoe
91986752Sfjoe/*
92086752Sfjoe * Routine checks periodically wire activity and regenerates marker if
92186752Sfjoe * connect was inactive for a long time.
92286752Sfjoe */
92386752Sfjoe
92486752Sfjoestatic void
92586752Sfjoesbni_timeout(void *xsc)
92686752Sfjoe{
92786752Sfjoe	struct sbni_softc *sc;
92886752Sfjoe	u_char csr0;
92986752Sfjoe
93086752Sfjoe	sc = (struct sbni_softc *)xsc;
931180263Sjhb	SBNI_ASSERT_LOCKED(sc);
93286752Sfjoe
93386752Sfjoe	csr0 = sbni_inb(sc, CSR0);
93486752Sfjoe	if (csr0 & RC_CHK) {
93586752Sfjoe
93686752Sfjoe		if (sc->timer_ticks) {
93786752Sfjoe			if (csr0 & (RC_RDY | BU_EMP))
93886752Sfjoe				/* receiving not active */
93986752Sfjoe				sc->timer_ticks--;
94086752Sfjoe		} else {
94186752Sfjoe			sc->in_stats.timeout_number++;
94286752Sfjoe			if (sc->delta_rxl)
94386752Sfjoe				timeout_change_level(sc);
94486752Sfjoe
94586752Sfjoe			sbni_outb(sc, CSR1, *(u_char *)&sc->csr1 | PR_RES);
94686752Sfjoe			csr0 = sbni_inb(sc, CSR0);
94786752Sfjoe		}
94886752Sfjoe	}
94986752Sfjoe
950180263Sjhb	sbni_outb(sc, CSR0, csr0 | RC_CHK);
951180263Sjhb	callout_reset(&sc->wch, hz/SBNI_HZ, sbni_timeout, sc);
95286752Sfjoe}
95386752Sfjoe
95486752Sfjoe/* -------------------------------------------------------------------------- */
95586752Sfjoe
95686752Sfjoestatic void
95786752Sfjoecard_start(struct sbni_softc *sc)
95886752Sfjoe{
95986752Sfjoe	sc->timer_ticks = CHANGE_LEVEL_START_TICKS;
96086752Sfjoe	sc->state &= ~(FL_WAIT_ACK | FL_NEED_RESEND);
96186752Sfjoe	sc->state |= FL_PREV_OK;
96286752Sfjoe
96386752Sfjoe	sc->inppos = 0;
96486752Sfjoe	sc->wait_frameno = 0;
96586752Sfjoe
96686752Sfjoe	sbni_outb(sc, CSR1, *(u_char *)&sc->csr1 | PR_RES);
96786752Sfjoe	sbni_outb(sc, CSR0, EN_INT);
96886752Sfjoe}
96986752Sfjoe
97086752Sfjoe/* -------------------------------------------------------------------------- */
97186752Sfjoe
97286752Sfjoestatic u_char rxl_tab[] = {
97386752Sfjoe	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x08,
97486752Sfjoe	0x0a, 0x0c, 0x0f, 0x16, 0x18, 0x1a, 0x1c, 0x1f
97586752Sfjoe};
97686752Sfjoe
97786752Sfjoe#define SIZE_OF_TIMEOUT_RXL_TAB 4
97886752Sfjoestatic u_char timeout_rxl_tab[] = {
97986752Sfjoe	0x03, 0x05, 0x08, 0x0b
98086752Sfjoe};
98186752Sfjoe
98286752Sfjoestatic void
98386752Sfjoeset_initial_values(struct sbni_softc *sc, struct sbni_flags flags)
98486752Sfjoe{
98586752Sfjoe	if (flags.fixed_rxl) {
98686752Sfjoe		sc->delta_rxl = 0; /* disable receive level autodetection */
98786752Sfjoe		sc->cur_rxl_index = flags.rxl;
98886752Sfjoe	} else {
98986752Sfjoe		sc->delta_rxl = DEF_RXL_DELTA;
99086752Sfjoe		sc->cur_rxl_index = DEF_RXL;
99186752Sfjoe	}
99286752Sfjoe
99386752Sfjoe	sc->csr1.rate = flags.fixed_rate ? flags.rate : DEFAULT_RATE;
99486752Sfjoe	sc->csr1.rxl  = rxl_tab[sc->cur_rxl_index];
99586752Sfjoe	sc->maxframe  = DEFAULT_FRAME_LEN;
99686752Sfjoe
99786752Sfjoe	/*
99886752Sfjoe	 * generate Ethernet address (0x00ff01xxxxxx)
99986752Sfjoe	 */
1000147256Sbrooks	*(u_int16_t *) sc->enaddr = htons(0x00ff);
1001101400Sfjoe	if (flags.mac_addr) {
1002147256Sbrooks		*(u_int32_t *) (sc->enaddr + 2) =
1003101400Sfjoe		    htonl(flags.mac_addr | 0x01000000);
1004101400Sfjoe	} else {
1005147256Sbrooks		*(u_char *) (sc->enaddr + 2) = 0x01;
1006147256Sbrooks		read_random(sc->enaddr + 3, 3);
100786752Sfjoe	}
100886752Sfjoe}
100986752Sfjoe
101086752Sfjoe
101186752Sfjoe#ifdef SBNI_DUAL_COMPOUND
1012180263Sjhbvoid
1013180263Sjhbsbni_add(struct sbni_softc *sc)
1014180263Sjhb{
101586752Sfjoe
1016180263Sjhb	mtx_lock(&headlist_lock);
1017180263Sjhb	sc->link = sbni_headlist;
1018180263Sjhb	sbni_headlist = sc;
1019180263Sjhb	mtx_unlock(&headlist_lock);
1020180263Sjhb}
1021180263Sjhb
102286752Sfjoestruct sbni_softc *
102386752Sfjoeconnect_to_master(struct sbni_softc *sc)
102486752Sfjoe{
1025101400Sfjoe	struct sbni_softc *p, *p_prev;
102686752Sfjoe
1027180263Sjhb	mtx_lock(&headlist_lock);
1028101400Sfjoe	for (p = sbni_headlist, p_prev = NULL; p; p_prev = p, p = p->link) {
1029101400Sfjoe		if (rman_get_start(p->io_res) == rman_get_start(sc->io_res) + 4 ||
1030101400Sfjoe		    rman_get_start(p->io_res) == rman_get_start(sc->io_res) - 4) {
1031101400Sfjoe			p->slave_sc = sc;
1032101400Sfjoe			if (p_prev)
1033101400Sfjoe				p_prev->link = p->link;
1034101400Sfjoe			else
1035101400Sfjoe				sbni_headlist = p->link;
1036180263Sjhb			mtx_unlock(&headlist_lock);
1037101400Sfjoe			return p;
103886752Sfjoe		}
103986752Sfjoe	}
1040180263Sjhb	mtx_unlock(&headlist_lock);
104186752Sfjoe
104286752Sfjoe	return (NULL);
104386752Sfjoe}
104486752Sfjoe
104586752Sfjoe#endif	/* SBNI_DUAL_COMPOUND */
104686752Sfjoe
104786752Sfjoe
104886752Sfjoe/* Receive level auto-selection */
104986752Sfjoe
105086752Sfjoestatic void
105186752Sfjoechange_level(struct sbni_softc *sc)
105286752Sfjoe{
105386752Sfjoe	if (sc->delta_rxl == 0)		/* do not auto-negotiate RxL */
105486752Sfjoe		return;
105586752Sfjoe
105686752Sfjoe	if (sc->cur_rxl_index == 0)
105786752Sfjoe		sc->delta_rxl = 1;
105886752Sfjoe	else if (sc->cur_rxl_index == 15)
105986752Sfjoe		sc->delta_rxl = -1;
106086752Sfjoe	else if (sc->cur_rxl_rcvd < sc->prev_rxl_rcvd)
106186752Sfjoe		sc->delta_rxl = -sc->delta_rxl;
106286752Sfjoe
106386752Sfjoe	sc->csr1.rxl = rxl_tab[sc->cur_rxl_index += sc->delta_rxl];
106486752Sfjoe	sbni_inb(sc, CSR0);	/* it needed for PCI cards */
106586752Sfjoe	sbni_outb(sc, CSR1, *(u_char *)&sc->csr1);
106686752Sfjoe
106786752Sfjoe	sc->prev_rxl_rcvd = sc->cur_rxl_rcvd;
106886752Sfjoe	sc->cur_rxl_rcvd  = 0;
106986752Sfjoe}
107086752Sfjoe
107186752Sfjoe
107286752Sfjoestatic void
107386752Sfjoetimeout_change_level(struct sbni_softc *sc)
107486752Sfjoe{
107586752Sfjoe	sc->cur_rxl_index = timeout_rxl_tab[sc->timeout_rxl];
107686752Sfjoe	if (++sc->timeout_rxl >= 4)
107786752Sfjoe		sc->timeout_rxl = 0;
107886752Sfjoe
107986752Sfjoe	sc->csr1.rxl = rxl_tab[sc->cur_rxl_index];
108086752Sfjoe	sbni_inb(sc, CSR0);
108186752Sfjoe	sbni_outb(sc, CSR1, *(u_char *)&sc->csr1);
108286752Sfjoe
108386752Sfjoe	sc->prev_rxl_rcvd = sc->cur_rxl_rcvd;
108486752Sfjoe	sc->cur_rxl_rcvd  = 0;
108586752Sfjoe}
108686752Sfjoe
108786752Sfjoe/* -------------------------------------------------------------------------- */
108886752Sfjoe
108986752Sfjoe/*
109086752Sfjoe * Process an ioctl request. This code needs some work - it looks
109186752Sfjoe *	pretty ugly.
109286752Sfjoe */
109386752Sfjoe
109486752Sfjoestatic int
109586752Sfjoesbni_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
109686752Sfjoe{
109786752Sfjoe	struct sbni_softc *sc;
109886752Sfjoe	struct ifreq *ifr;
109993593Sjhb	struct thread *td;
110086752Sfjoe	struct sbni_in_stats *in_stats;
110186752Sfjoe	struct sbni_flags flags;
1102180263Sjhb	int error;
110386752Sfjoe
110486752Sfjoe	sc = ifp->if_softc;
110586752Sfjoe	ifr = (struct ifreq *)data;
110693593Sjhb	td = curthread;
110786752Sfjoe	error = 0;
110886752Sfjoe
110986752Sfjoe	switch (command) {
111086752Sfjoe	case SIOCSIFFLAGS:
111186752Sfjoe		/*
111286752Sfjoe		 * If the interface is marked up and stopped, then start it.
111386752Sfjoe		 * If it is marked down and running, then stop it.
111486752Sfjoe		 */
1115180263Sjhb		SBNI_LOCK(sc);
111686752Sfjoe		if (ifp->if_flags & IFF_UP) {
1117148887Srwatson			if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
1118180263Sjhb				sbni_init_locked(sc);
111986752Sfjoe		} else {
1120148887Srwatson			if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
112186752Sfjoe				sbni_stop(sc);
112286752Sfjoe			}
112386752Sfjoe		}
1124180263Sjhb		SBNI_UNLOCK(sc);
112586752Sfjoe		break;
112686752Sfjoe
112786752Sfjoe	case SIOCADDMULTI:
112886752Sfjoe	case SIOCDELMULTI:
112986752Sfjoe		/*
113086752Sfjoe		 * Multicast list has changed; set the hardware filter
113186752Sfjoe		 * accordingly.
113286752Sfjoe		 */
113386752Sfjoe		error = 0;
113486752Sfjoe		/* if (ifr == NULL)
113586752Sfjoe			error = EAFNOSUPPORT; */
113686752Sfjoe		break;
113786752Sfjoe
113886752Sfjoe		/*
113986752Sfjoe		 * SBNI specific ioctl
114086752Sfjoe		 */
114186752Sfjoe	case SIOCGHWFLAGS:	/* get flags */
1142180263Sjhb		SBNI_LOCK(sc);
1143152315Sru		bcopy((caddr_t)IF_LLADDR(sc->ifp)+3, (caddr_t) &flags, 3);
114486752Sfjoe		flags.rxl = sc->cur_rxl_index;
114586752Sfjoe		flags.rate = sc->csr1.rate;
114686752Sfjoe		flags.fixed_rxl = (sc->delta_rxl == 0);
114786752Sfjoe		flags.fixed_rate = 1;
1148180263Sjhb		SBNI_UNLOCK(sc);
114986752Sfjoe		ifr->ifr_data = *(caddr_t*) &flags;
115086752Sfjoe		break;
115186752Sfjoe
115286752Sfjoe	case SIOCGINSTATS:
1153180263Sjhb		in_stats = malloc(sizeof(struct sbni_in_stats), M_DEVBUF,
1154180263Sjhb		    M_WAITOK);
1155180263Sjhb		SBNI_LOCK(sc);
1156180263Sjhb		bcopy(&sc->in_stats, in_stats, sizeof(struct sbni_in_stats));
1157180263Sjhb		SBNI_UNLOCK(sc);
1158180263Sjhb		error = copyout(ifr->ifr_data, in_stats,
1159180263Sjhb		    sizeof(struct sbni_in_stats));
1160180263Sjhb		free(in_stats, M_DEVBUF);
116186752Sfjoe		break;
116286752Sfjoe
116386752Sfjoe	case SIOCSHWFLAGS:	/* set flags */
116486752Sfjoe		/* root only */
1165164033Srwatson		error = priv_check(td, PRIV_DRIVER);
116686752Sfjoe		if (error)
116786752Sfjoe			break;
116886752Sfjoe		flags = *(struct sbni_flags*)&ifr->ifr_data;
1169180263Sjhb		SBNI_LOCK(sc);
117086752Sfjoe		if (flags.fixed_rxl) {
117186752Sfjoe			sc->delta_rxl = 0;
117286752Sfjoe			sc->cur_rxl_index = flags.rxl;
117386752Sfjoe		} else {
117486752Sfjoe			sc->delta_rxl = DEF_RXL_DELTA;
117586752Sfjoe			sc->cur_rxl_index = DEF_RXL;
117686752Sfjoe		}
117786752Sfjoe		sc->csr1.rxl = rxl_tab[sc->cur_rxl_index];
117886752Sfjoe		sc->csr1.rate = flags.fixed_rate ? flags.rate : DEFAULT_RATE;
117986752Sfjoe		if (flags.mac_addr)
118086752Sfjoe			bcopy((caddr_t) &flags,
1181152315Sru			      (caddr_t) IF_LLADDR(sc->ifp)+3, 3);
118286752Sfjoe
118386752Sfjoe		/* Don't be afraid... */
118486752Sfjoe		sbni_outb(sc, CSR1, *(char*)(&sc->csr1) | PR_RES);
1185180263Sjhb		SBNI_UNLOCK(sc);
118686752Sfjoe		break;
118786752Sfjoe
118886752Sfjoe	case SIOCRINSTATS:
1189180263Sjhb		SBNI_LOCK(sc);
1190164033Srwatson		if (!(error = priv_check(td, PRIV_DRIVER)))	/* root only */
119186752Sfjoe			bzero(&sc->in_stats, sizeof(struct sbni_in_stats));
1192180263Sjhb		SBNI_UNLOCK(sc);
119386752Sfjoe		break;
119486752Sfjoe
119586752Sfjoe	default:
1196106937Ssam		error = ether_ioctl(ifp, command, data);
1197106937Ssam		break;
119886752Sfjoe	}
119986752Sfjoe
120086752Sfjoe	return (error);
120186752Sfjoe}
120286752Sfjoe
120386752Sfjoe/* -------------------------------------------------------------------------- */
120486752Sfjoe
120586752Sfjoe#ifdef ASM_CRC
120686752Sfjoe
120786752Sfjoestatic u_int32_t
120886752Sfjoecalc_crc32(u_int32_t crc, caddr_t p, u_int len)
120986752Sfjoe{
121086752Sfjoe	register u_int32_t  _crc __asm ("ax");
121186752Sfjoe	_crc = crc;
121286752Sfjoe
121386752Sfjoe	__asm __volatile (
121486752Sfjoe		"xorl	%%ebx, %%ebx\n"
121586752Sfjoe		"movl	%1, %%esi\n"
121686752Sfjoe		"movl	%2, %%ecx\n"
121786752Sfjoe		"movl	$crc32tab, %%edi\n"
121886752Sfjoe		"shrl	$2, %%ecx\n"
121986752Sfjoe		"jz	1f\n"
122086752Sfjoe
122186752Sfjoe		".align 4\n"
122286752Sfjoe	"0:\n"
122386752Sfjoe		"movb	%%al, %%bl\n"
122486752Sfjoe		"movl	(%%esi), %%edx\n"
122586752Sfjoe		"shrl	$8, %%eax\n"
122686752Sfjoe		"xorb	%%dl, %%bl\n"
122786752Sfjoe		"shrl	$8, %%edx\n"
122886752Sfjoe		"xorl	(%%edi,%%ebx,4), %%eax\n"
122986752Sfjoe
123086752Sfjoe		"movb	%%al, %%bl\n"
123186752Sfjoe		"shrl	$8, %%eax\n"
123286752Sfjoe		"xorb	%%dl, %%bl\n"
123386752Sfjoe		"shrl	$8, %%edx\n"
123486752Sfjoe		"xorl	(%%edi,%%ebx,4), %%eax\n"
123586752Sfjoe
123686752Sfjoe		"movb	%%al, %%bl\n"
123786752Sfjoe		"shrl	$8, %%eax\n"
123886752Sfjoe		"xorb	%%dl, %%bl\n"
123986752Sfjoe		"movb	%%dh, %%dl\n"
124086752Sfjoe		"xorl	(%%edi,%%ebx,4), %%eax\n"
124186752Sfjoe
124286752Sfjoe		"movb	%%al, %%bl\n"
124386752Sfjoe		"shrl	$8, %%eax\n"
124486752Sfjoe		"xorb	%%dl, %%bl\n"
124586752Sfjoe		"addl	$4, %%esi\n"
124686752Sfjoe		"xorl	(%%edi,%%ebx,4), %%eax\n"
124786752Sfjoe
124886752Sfjoe		"decl	%%ecx\n"
124986752Sfjoe		"jnz	0b\n"
125086752Sfjoe
125186752Sfjoe	"1:\n"
125286752Sfjoe		"movl	%2, %%ecx\n"
125386752Sfjoe		"andl	$3, %%ecx\n"
125486752Sfjoe		"jz	2f\n"
125586752Sfjoe
125686752Sfjoe		"movb	%%al, %%bl\n"
125786752Sfjoe		"shrl	$8, %%eax\n"
125886752Sfjoe		"xorb	(%%esi), %%bl\n"
125986752Sfjoe		"xorl	(%%edi,%%ebx,4), %%eax\n"
126086752Sfjoe
126186752Sfjoe		"decl	%%ecx\n"
126286752Sfjoe		"jz	2f\n"
126386752Sfjoe
126486752Sfjoe		"movb	%%al, %%bl\n"
126586752Sfjoe		"shrl	$8, %%eax\n"
126686752Sfjoe		"xorb	1(%%esi), %%bl\n"
126786752Sfjoe		"xorl	(%%edi,%%ebx,4), %%eax\n"
126886752Sfjoe
126986752Sfjoe		"decl	%%ecx\n"
127086752Sfjoe		"jz	2f\n"
127186752Sfjoe
127286752Sfjoe		"movb	%%al, %%bl\n"
127386752Sfjoe		"shrl	$8, %%eax\n"
127486752Sfjoe		"xorb	2(%%esi), %%bl\n"
127586752Sfjoe		"xorl	(%%edi,%%ebx,4), %%eax\n"
127686752Sfjoe	"2:\n"
1277117433Skan		: "=a" (_crc)
1278117433Skan		: "g" (p), "g" (len)
1279117433Skan		: "bx", "cx", "dx", "si", "di"
128086752Sfjoe	);
128186752Sfjoe
128286752Sfjoe	return (_crc);
128386752Sfjoe}
128486752Sfjoe
128586752Sfjoe#else	/* ASM_CRC */
128686752Sfjoe
128786752Sfjoestatic u_int32_t
128886752Sfjoecalc_crc32(u_int32_t crc, caddr_t p, u_int len)
128986752Sfjoe{
129086752Sfjoe	while (len--)
129186752Sfjoe		crc = CRC32(*p++, crc);
129286752Sfjoe
129386752Sfjoe	return (crc);
129486752Sfjoe}
129586752Sfjoe
129686752Sfjoe#endif	/* ASM_CRC */
129786752Sfjoe
129886752Sfjoe
1299103844Salfredstatic u_int32_t crc32tab[] __aligned(8) = {
130086752Sfjoe	0xD202EF8D,  0xA505DF1B,  0x3C0C8EA1,  0x4B0BBE37,
130186752Sfjoe	0xD56F2B94,  0xA2681B02,  0x3B614AB8,  0x4C667A2E,
130286752Sfjoe	0xDCD967BF,  0xABDE5729,  0x32D70693,  0x45D03605,
130386752Sfjoe	0xDBB4A3A6,  0xACB39330,  0x35BAC28A,  0x42BDF21C,
130486752Sfjoe	0xCFB5FFE9,  0xB8B2CF7F,  0x21BB9EC5,  0x56BCAE53,
130586752Sfjoe	0xC8D83BF0,  0xBFDF0B66,  0x26D65ADC,  0x51D16A4A,
130686752Sfjoe	0xC16E77DB,  0xB669474D,  0x2F6016F7,  0x58672661,
130786752Sfjoe	0xC603B3C2,  0xB1048354,  0x280DD2EE,  0x5F0AE278,
130886752Sfjoe	0xE96CCF45,  0x9E6BFFD3,  0x0762AE69,  0x70659EFF,
130986752Sfjoe	0xEE010B5C,  0x99063BCA,  0x000F6A70,  0x77085AE6,
131086752Sfjoe	0xE7B74777,  0x90B077E1,  0x09B9265B,  0x7EBE16CD,
131186752Sfjoe	0xE0DA836E,  0x97DDB3F8,  0x0ED4E242,  0x79D3D2D4,
131286752Sfjoe	0xF4DBDF21,  0x83DCEFB7,  0x1AD5BE0D,  0x6DD28E9B,
131386752Sfjoe	0xF3B61B38,  0x84B12BAE,  0x1DB87A14,  0x6ABF4A82,
131486752Sfjoe	0xFA005713,  0x8D076785,  0x140E363F,  0x630906A9,
131586752Sfjoe	0xFD6D930A,  0x8A6AA39C,  0x1363F226,  0x6464C2B0,
131686752Sfjoe	0xA4DEAE1D,  0xD3D99E8B,  0x4AD0CF31,  0x3DD7FFA7,
131786752Sfjoe	0xA3B36A04,  0xD4B45A92,  0x4DBD0B28,  0x3ABA3BBE,
131886752Sfjoe	0xAA05262F,  0xDD0216B9,  0x440B4703,  0x330C7795,
131986752Sfjoe	0xAD68E236,  0xDA6FD2A0,  0x4366831A,  0x3461B38C,
132086752Sfjoe	0xB969BE79,  0xCE6E8EEF,  0x5767DF55,  0x2060EFC3,
132186752Sfjoe	0xBE047A60,  0xC9034AF6,  0x500A1B4C,  0x270D2BDA,
132286752Sfjoe	0xB7B2364B,  0xC0B506DD,  0x59BC5767,  0x2EBB67F1,
132386752Sfjoe	0xB0DFF252,  0xC7D8C2C4,  0x5ED1937E,  0x29D6A3E8,
132486752Sfjoe	0x9FB08ED5,  0xE8B7BE43,  0x71BEEFF9,  0x06B9DF6F,
132586752Sfjoe	0x98DD4ACC,  0xEFDA7A5A,  0x76D32BE0,  0x01D41B76,
132686752Sfjoe	0x916B06E7,  0xE66C3671,  0x7F6567CB,  0x0862575D,
132786752Sfjoe	0x9606C2FE,  0xE101F268,  0x7808A3D2,  0x0F0F9344,
132886752Sfjoe	0x82079EB1,  0xF500AE27,  0x6C09FF9D,  0x1B0ECF0B,
132986752Sfjoe	0x856A5AA8,  0xF26D6A3E,  0x6B643B84,  0x1C630B12,
133086752Sfjoe	0x8CDC1683,  0xFBDB2615,  0x62D277AF,  0x15D54739,
133186752Sfjoe	0x8BB1D29A,  0xFCB6E20C,  0x65BFB3B6,  0x12B88320,
133286752Sfjoe	0x3FBA6CAD,  0x48BD5C3B,  0xD1B40D81,  0xA6B33D17,
133386752Sfjoe	0x38D7A8B4,  0x4FD09822,  0xD6D9C998,  0xA1DEF90E,
133486752Sfjoe	0x3161E49F,  0x4666D409,  0xDF6F85B3,  0xA868B525,
133586752Sfjoe	0x360C2086,  0x410B1010,  0xD80241AA,  0xAF05713C,
133686752Sfjoe	0x220D7CC9,  0x550A4C5F,  0xCC031DE5,  0xBB042D73,
133786752Sfjoe	0x2560B8D0,  0x52678846,  0xCB6ED9FC,  0xBC69E96A,
133886752Sfjoe	0x2CD6F4FB,  0x5BD1C46D,  0xC2D895D7,  0xB5DFA541,
133986752Sfjoe	0x2BBB30E2,  0x5CBC0074,  0xC5B551CE,  0xB2B26158,
134086752Sfjoe	0x04D44C65,  0x73D37CF3,  0xEADA2D49,  0x9DDD1DDF,
134186752Sfjoe	0x03B9887C,  0x74BEB8EA,  0xEDB7E950,  0x9AB0D9C6,
134286752Sfjoe	0x0A0FC457,  0x7D08F4C1,  0xE401A57B,  0x930695ED,
134386752Sfjoe	0x0D62004E,  0x7A6530D8,  0xE36C6162,  0x946B51F4,
134486752Sfjoe	0x19635C01,  0x6E646C97,  0xF76D3D2D,  0x806A0DBB,
134586752Sfjoe	0x1E0E9818,  0x6909A88E,  0xF000F934,  0x8707C9A2,
134686752Sfjoe	0x17B8D433,  0x60BFE4A5,  0xF9B6B51F,  0x8EB18589,
134786752Sfjoe	0x10D5102A,  0x67D220BC,  0xFEDB7106,  0x89DC4190,
134886752Sfjoe	0x49662D3D,  0x3E611DAB,  0xA7684C11,  0xD06F7C87,
134986752Sfjoe	0x4E0BE924,  0x390CD9B2,  0xA0058808,  0xD702B89E,
135086752Sfjoe	0x47BDA50F,  0x30BA9599,  0xA9B3C423,  0xDEB4F4B5,
135186752Sfjoe	0x40D06116,  0x37D75180,  0xAEDE003A,  0xD9D930AC,
135286752Sfjoe	0x54D13D59,  0x23D60DCF,  0xBADF5C75,  0xCDD86CE3,
135386752Sfjoe	0x53BCF940,  0x24BBC9D6,  0xBDB2986C,  0xCAB5A8FA,
135486752Sfjoe	0x5A0AB56B,  0x2D0D85FD,  0xB404D447,  0xC303E4D1,
135586752Sfjoe	0x5D677172,  0x2A6041E4,  0xB369105E,  0xC46E20C8,
135686752Sfjoe	0x72080DF5,  0x050F3D63,  0x9C066CD9,  0xEB015C4F,
135786752Sfjoe	0x7565C9EC,  0x0262F97A,  0x9B6BA8C0,  0xEC6C9856,
135886752Sfjoe	0x7CD385C7,  0x0BD4B551,  0x92DDE4EB,  0xE5DAD47D,
135986752Sfjoe	0x7BBE41DE,  0x0CB97148,  0x95B020F2,  0xE2B71064,
136086752Sfjoe	0x6FBF1D91,  0x18B82D07,  0x81B17CBD,  0xF6B64C2B,
136186752Sfjoe	0x68D2D988,  0x1FD5E91E,  0x86DCB8A4,  0xF1DB8832,
136286752Sfjoe	0x616495A3,  0x1663A535,  0x8F6AF48F,  0xF86DC419,
136386752Sfjoe	0x660951BA,  0x110E612C,  0x88073096,  0xFF000000
136486752Sfjoe};
1365