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