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