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