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
sbni_inb(struct sbni_softc * sc,enum sbni_reg reg)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
sbni_outb(struct sbni_softc * sc,enum sbni_reg reg,u_char value)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
sbni_insb(struct sbni_softc * sc,u_char * to,u_int len)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
sbni_outsb(struct sbni_softc * sc,u_char * from,u_int len)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
sbni_probe(struct sbni_softc * sc)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
sbni_attach(struct sbni_softc * sc,int unit,struct sbni_flags flags)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
sbni_detach(struct sbni_softc * sc)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
sbni_release_resources(struct sbni_softc * sc)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
sbni_init(void * xsc)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
sbni_init_locked(struct sbni_softc * sc)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
sbni_start(if_t ifp)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
sbni_start_locked(if_t ifp)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
sbni_stop(struct sbni_softc * sc)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
sbni_intr(void * arg)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
handle_channel(struct sbni_softc * sc)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
recv_frame(struct sbni_softc * sc)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
send_frame(struct sbni_softc * sc)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
download_data(struct sbni_softc * sc,u_int32_t * crc_p)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
upload_data(struct sbni_softc * sc,u_int framelen,u_int frameno,u_int is_first,u_int32_t crc)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
send_complete(struct sbni_softc * sc)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
interpret_ack(struct sbni_softc * sc,u_int ack)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
append_frame_to_pkt(struct sbni_softc * sc,u_int framelen,u_int32_t crc)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
prepare_to_send(struct sbni_softc * sc)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
drop_xmit_queue(struct sbni_softc * sc)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
send_frame_header(struct sbni_softc * sc,u_int32_t * crc_p)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
skip_tail(struct sbni_softc * sc,u_int tail_len,u_int32_t crc)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
check_fhdr(struct sbni_softc * sc,u_int * framelen,u_int * frameno,u_int * ack,u_int * is_first,u_int32_t * crc_p)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
get_rx_buf(struct sbni_softc * sc)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
indicate_pkt(struct sbni_softc * sc)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
sbni_timeout(void * xsc)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
card_start(struct sbni_softc * sc)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
set_initial_values(struct sbni_softc * sc,struct sbni_flags flags)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
sbni_add(struct sbni_softc * sc)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 *
connect_to_master(struct sbni_softc * sc)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
change_level(struct sbni_softc * sc)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
timeout_change_level(struct sbni_softc * sc)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
sbni_ioctl(if_t ifp,u_long command,caddr_t data)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
calc_crc32(u_int32_t crc,caddr_t p,u_int len)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