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