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