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