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