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