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