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