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