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