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