2 * Copyright (c) 1997-2001 Granch, Ltd. All rights reserved.
3 * Author: Denis I.Timofeev <timofeev@granch.ru>
5 * Redistributon and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice unmodified, this list of conditions, and the following
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.
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
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
33 * Device driver for Granch SBNI12 leased line adapters
35 * Revision 2.0.0 1997/08/06
36 * Initial revision by Alexey Zverev
38 * Revision 2.0.1 1997/08/11
39 * Additional internal statistics support (tx statistics)
41 * Revision 2.0.2 1997/11/05
42 * if_bpf bug has been fixed
44 * Revision 2.0.3 1998/12/20
45 * Memory leakage has been eliminated in
46 * the sbni_st and sbni_timeout routines.
48 * Revision 3.0 2000/08/10 by Yaroslav Polyakov
49 * Support for PCI cards. 4.1 modification.
51 * Revision 3.1 2000/09/12
52 * Removed extra #defines around bpf functions
54 * Revision 4.0 2000/11/23 by Denis Timofeev
55 * Completely redesigned the buffer management
57 * Revision 4.1 2001/01/21
58 * Support for PCI Dual cards and new SBNI12D-10, -11 Dual/ISA cards
60 * Written with reference to NE2000 driver developed by David Greenman.
64 #include <sys/param.h>
65 #include <sys/systm.h>
66 #include <sys/socket.h>
67 #include <sys/sockio.h>
69 #include <sys/kernel.h>
72 #include <sys/callout.h>
73 #include <sys/syslog.h>
74 #include <sys/random.h>
76 #include <machine/bus.h>
78 #include <machine/resource.h>
81 #include <net/if_dl.h>
82 #include <net/ethernet.h>
84 #include <net/if_types.h>
86 #include <dev/sbni/if_sbnireg.h>
87 #include <dev/sbni/if_sbnivar.h>
89 static void sbni_init(void *);
90 static void sbni_start(struct ifnet *);
91 static int sbni_ioctl(struct ifnet *, u_long, caddr_t);
92 static void sbni_watchdog(struct ifnet *);
93 static void sbni_stop(struct sbni_softc *);
94 static void handle_channel(struct sbni_softc *);
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);
115 static u_int32_t calc_crc32(u_int32_t, caddr_t, u_int);
116 static timeout_t sbni_timeout;
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);
123 static u_int32_t crc32tab[];
125 #ifdef SBNI_DUAL_COMPOUND
126 struct sbni_softc *sbni_headlist;
129 u_int32_t next_sbni_unit;
131 /* -------------------------------------------------------------------------- */
133 static __inline u_char
134 sbni_inb(struct sbni_softc *sc, enum sbni_reg reg)
136 return bus_space_read_1(
137 rman_get_bustag(sc->io_res),
138 rman_get_bushandle(sc->io_res),
143 sbni_outb(struct sbni_softc *sc, enum sbni_reg reg, u_char value)
146 rman_get_bustag(sc->io_res),
147 rman_get_bushandle(sc->io_res),
148 sc->io_off + reg, value);
152 sbni_insb(struct sbni_softc *sc, u_char *to, u_int len)
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);
161 sbni_outsb(struct sbni_softc *sc, u_char *from, u_int len)
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);
171 Valid combinations in CSR0 (for probing):
173 VALID_DECODER 0000,0011,1011,1010
178 TR_RDY TR_REQ ; 3 ; +
180 BU_EMP TR_REQ ; 5 ; +
181 BU_EMP TR_RDY ; 6 ; -
182 BU_EMP TR_RDY TR_REQ ; 7 ; +
184 RC_RDY TR_REQ ; 9 ; +
185 RC_RDY TR_RDY ; 10 ; -
186 RC_RDY TR_RDY TR_REQ ; 11 ; -
187 RC_RDY BU_EMP ; 12 ; -
188 RC_RDY BU_EMP TR_REQ ; 13 ; -
189 RC_RDY BU_EMP TR_RDY ; 14 ; -
190 RC_RDY BU_EMP TR_RDY TR_REQ ; 15 ; -
193 #define VALID_DECODER (2 + 8 + 0x10 + 0x20 + 0x80 + 0x100 + 0x200)
197 sbni_probe(struct sbni_softc *sc)
201 csr0 = sbni_inb(sc, CSR0);
202 if (csr0 != 0xff && csr0 != 0x00) {
207 if (VALID_DECODER & (1 << (csr0 >> 4)))
216 * Install interface into kernel networking data structures
219 sbni_attach(struct sbni_softc *sc, int unit, struct sbni_flags flags)
224 ifp = sc->ifp = if_alloc(IFT_ETHER);
226 panic("sbni%d: can not if_alloc()", unit);
227 sbni_outb(sc, CSR0, 0);
228 set_initial_values(sc, flags);
230 callout_handle_init(&sc->wch);
231 /* Initialize ifnet structure */
233 if_initname(ifp, "sbni", unit);
234 ifp->if_init = sbni_init;
235 ifp->if_start = sbni_start;
236 ifp->if_ioctl = sbni_ioctl;
237 ifp->if_watchdog = sbni_watchdog;
238 ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
240 /* report real baud rate */
241 csr0 = sbni_inb(sc, CSR0);
243 (csr0 & 0x01 ? 500000 : 2000000) / (1 << flags.rate);
245 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST |
247 ether_ifattach(ifp, sc->enaddr);
248 /* device attach does transition from UNCONFIGURED to IDLE state */
250 if_printf(ifp, "speed %ld, rxl ", ifp->if_baudrate);
254 printf("%d (fixed)\n", sc->cur_rxl_index);
257 /* -------------------------------------------------------------------------- */
262 struct sbni_softc *sc;
266 sc = (struct sbni_softc *)xsc;
270 * kludge to avoid multiple initialization when more than once
271 * protocols configured
273 if (ifp->if_drv_flags & IFF_DRV_RUNNING)
279 sc->wch = timeout(sbni_timeout, sc, hz/SBNI_HZ);
281 ifp->if_drv_flags |= IFF_DRV_RUNNING;
282 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
284 /* attempt to start output */
291 sbni_start(struct ifnet *ifp)
293 struct sbni_softc *sc = ifp->if_softc;
294 if (sc->tx_frameno == 0)
300 sbni_stop(struct sbni_softc *sc)
302 sbni_outb(sc, CSR0, 0);
306 m_freem(sc->rx_buf_p);
310 untimeout(sbni_timeout, sc, sc->wch);
311 sc->wch.callout = NULL;
314 /* -------------------------------------------------------------------------- */
316 /* interrupt handler */
319 * SBNI12D-10, -11/ISA boards within "common interrupt" mode could not
320 * be looked as two independent single-channel devices. Every channel seems
321 * as Ethernet interface but interrupt handler must be common. Really, first
322 * channel ("master") driver only registers the handler. In it's struct softc
323 * it has got pointer to "slave" channel's struct softc and handles that's
325 * softc of successfully attached ISA SBNI boards is linked to list.
326 * While next board driver is initialized, it scans this list. If one
327 * has found softc with same irq and ioaddr different by 4 then it assumes
328 * this board to be "master".
334 struct sbni_softc *sc;
337 sc = (struct sbni_softc *)arg;
341 if (sbni_inb(sc, CSR0) & (RC_RDY | TR_RDY)) {
345 if (sc->slave_sc && /* second channel present */
346 (sbni_inb(sc->slave_sc, CSR0) & (RC_RDY | TR_RDY))) {
347 handle_channel(sc->slave_sc);
355 handle_channel(struct sbni_softc *sc)
360 sbni_outb(sc, CSR0, (sbni_inb(sc, CSR0) & ~EN_INT) | TR_REQ);
362 sc->timer_ticks = CHANGE_LEVEL_START_TICKS;
364 csr0 = sbni_inb(sc, CSR0);
365 if ((csr0 & (RC_RDY | TR_RDY)) == 0)
368 req_ans = !(sc->state & FL_PREV_OK);
371 req_ans = recv_frame(sc);
374 * TR_RDY always equals 1 here because we have owned the marker,
375 * and we set TR_REQ when disabled interrupts
377 csr0 = sbni_inb(sc, CSR0);
378 if ((csr0 & TR_RDY) == 0 || (csr0 & RC_RDY) != 0)
379 printf("sbni: internal error!\n");
381 /* if state & FL_NEED_RESEND != 0 then tx_frameno != 0 */
382 if (req_ans || sc->tx_frameno != 0)
385 /* send the marker without any data */
386 sbni_outb(sc, CSR0, sbni_inb(sc, CSR0) & ~TR_REQ);
390 sbni_outb(sc, CSR0, sbni_inb(sc, CSR0) | EN_INT);
395 * Routine returns 1 if it need to acknoweledge received frame.
396 * Empty frame received without errors won't be acknoweledged.
400 recv_frame(struct sbni_softc *sc)
403 u_int framelen, frameno, ack;
404 u_int is_first, frame_ok;
407 if (check_fhdr(sc, &framelen, &frameno, &ack, &is_first, &crc)) {
408 frame_ok = framelen > 4 ?
409 upload_data(sc, framelen, frameno, is_first, crc) :
410 skip_tail(sc, framelen, crc);
412 interpret_ack(sc, ack);
418 sbni_outb(sc, CSR0, sbni_inb(sc, CSR0) ^ CT_ZER);
420 sc->state |= FL_PREV_OK;
422 sc->in_stats.all_rx_number++;
424 sc->state &= ~FL_PREV_OK;
426 sc->in_stats.all_rx_number++;
427 sc->in_stats.bad_rx_number++;
430 return (!frame_ok || framelen > 4);
435 send_frame(struct sbni_softc *sc)
441 if (sc->state & FL_NEED_RESEND) {
443 /* if frame was sended but not ACK'ed - resend it */
444 if (sc->trans_errors) {
446 if (sc->framelen != 0)
447 sc->in_stats.resend_tx_number++;
449 /* cannot xmit with many attempts */
454 sc->trans_errors = TR_ERROR_COUNT;
456 send_frame_header(sc, &crc);
457 sc->state |= FL_NEED_RESEND;
459 * FL_NEED_RESEND will be cleared after ACK, but if empty
460 * frame sended then in prepare_to_send next frame
465 download_data(sc, &crc);
466 sc->in_stats.all_tx_number++;
467 sc->state |= FL_WAIT_ACK;
470 sbni_outsb(sc, (u_char *)&crc, sizeof crc);
473 csr0 = sbni_inb(sc, CSR0);
474 sbni_outb(sc, CSR0, csr0 & ~TR_REQ);
476 if (sc->tx_frameno) {
477 /* next frame exists - request to send */
478 sbni_outb(sc, CSR0, csr0 | TR_REQ);
484 download_data(struct sbni_softc *sc, u_int32_t *crc_p)
488 u_int data_len, pos, slice;
490 data_p = NULL; /* initialized to avoid warn */
493 for (m = sc->tx_buf_p; m != NULL && pos < sc->pktlen; m = m->m_next) {
494 if (pos + m->m_len > sc->outpos) {
495 data_len = m->m_len - (sc->outpos - pos);
496 data_p = mtod(m, caddr_t) + (sc->outpos - pos);
509 slice = min(data_len, sc->framelen - pos);
510 sbni_outsb(sc, data_p, slice);
511 *crc_p = calc_crc32(*crc_p, data_p, slice);
514 if (data_len -= slice)
519 } while (m != NULL && m->m_len == 0);
523 data_p = mtod(m, caddr_t);
527 /* frame too short - zero padding */
529 pos = sc->framelen - pos;
531 sbni_outb(sc, DAT, 0);
532 *crc_p = CRC32(0, *crc_p);
536 } while (pos < sc->framelen);
541 upload_data(struct sbni_softc *sc, u_int framelen, u_int frameno,
542 u_int is_first, u_int32_t crc)
547 sc->wait_frameno = frameno;
551 if (sc->wait_frameno == frameno) {
553 if (sc->inppos + framelen <= ETHER_MAX_LEN) {
554 frame_ok = append_frame_to_pkt(sc, framelen, crc);
557 * if CRC is right but framelen incorrect then transmitter
558 * error was occured... drop entire packet
560 } else if ((frame_ok = skip_tail(sc, framelen, crc)) != 0) {
561 sc->wait_frameno = 0;
563 sc->ifp->if_ierrors++;
564 /* now skip all frames until is_first != 0 */
567 frame_ok = skip_tail(sc, framelen, crc);
569 if (is_first && !frame_ok) {
571 * Frame has been violated, but we have stored
572 * is_first already... Drop entire packet.
574 sc->wait_frameno = 0;
575 sc->ifp->if_ierrors++;
582 static __inline void send_complete(struct sbni_softc *);
585 send_complete(struct sbni_softc *sc)
587 m_freem(sc->tx_buf_p);
589 sc->ifp->if_opackets++;
594 interpret_ack(struct sbni_softc *sc, u_int ack)
596 if (ack == FRAME_SENT_OK) {
597 sc->state &= ~FL_NEED_RESEND;
599 if (sc->state & FL_WAIT_ACK) {
600 sc->outpos += sc->framelen;
602 if (--sc->tx_frameno) {
604 sc->maxframe, sc->pktlen - sc->outpos);
612 sc->state &= ~FL_WAIT_ACK;
617 * Glue received frame with previous fragments of packet.
618 * Indicate packet when last frame would be accepted.
622 append_frame_to_pkt(struct sbni_softc *sc, u_int framelen, u_int32_t crc)
626 if (sc->inppos + framelen > ETHER_MAX_LEN)
629 if (!sc->rx_buf_p && !get_rx_buf(sc))
632 p = sc->rx_buf_p->m_data + sc->inppos;
633 sbni_insb(sc, p, framelen);
634 if (calc_crc32(crc, p, framelen) != CRC32_REMAINDER)
637 sc->inppos += framelen - 4;
638 if (--sc->wait_frameno == 0) { /* last frame received */
640 sc->ifp->if_ipackets++;
648 * Prepare to start output on adapter. Current priority must be set to splimp
649 * before this routine is called.
650 * Transmitter will be actually activated when marker has been accepted.
654 prepare_to_send(struct sbni_softc *sc)
659 /* sc->tx_buf_p == NULL here! */
661 printf("sbni: memory leak!\n");
664 sc->state &= ~(FL_WAIT_ACK | FL_NEED_RESEND);
667 IF_DEQUEUE(&sc->ifp->if_snd, sc->tx_buf_p);
669 /* nothing to transmit... */
673 sc->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
677 for (len = 0, m = sc->tx_buf_p; m; m = m->m_next)
682 m_freem(sc->tx_buf_p);
685 if (len < SBNI_MIN_LEN)
689 sc->tx_frameno = (len + sc->maxframe - 1) / sc->maxframe;
690 sc->framelen = min(len, sc->maxframe);
692 sbni_outb(sc, CSR0, sbni_inb(sc, CSR0) | TR_REQ);
693 sc->ifp->if_drv_flags |= IFF_DRV_OACTIVE;
694 BPF_MTAP(sc->ifp, sc->tx_buf_p);
699 drop_xmit_queue(struct sbni_softc *sc)
704 m_freem(sc->tx_buf_p);
706 sc->ifp->if_oerrors++;
710 IF_DEQUEUE(&sc->ifp->if_snd, m);
714 sc->ifp->if_oerrors++;
720 sc->state &= ~(FL_WAIT_ACK | FL_NEED_RESEND);
721 sc->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
726 send_frame_header(struct sbni_softc *sc, u_int32_t *crc_p)
733 len_field = sc->framelen + 6; /* CRC + frameno + reserved */
735 if (sc->state & FL_NEED_RESEND)
736 len_field |= FRAME_RETRY; /* non-first attempt... */
739 len_field |= FRAME_FIRST;
741 len_field |= (sc->state & FL_PREV_OK) ? FRAME_SENT_OK : FRAME_SENT_BAD;
742 sbni_outb(sc, DAT, SBNI_SIG);
744 value = (u_char)len_field;
745 sbni_outb(sc, DAT, value);
746 crc = CRC32(value, crc);
747 value = (u_char)(len_field >> 8);
748 sbni_outb(sc, DAT, value);
749 crc = CRC32(value, crc);
751 sbni_outb(sc, DAT, sc->tx_frameno);
752 crc = CRC32(sc->tx_frameno, crc);
753 sbni_outb(sc, DAT, 0);
760 * if frame tail not needed (incorrect number or received twice),
761 * it won't store, but CRC will be calculated
765 skip_tail(struct sbni_softc *sc, u_int tail_len, u_int32_t crc)
768 crc = CRC32(sbni_inb(sc, DAT), crc);
770 return (crc == CRC32_REMAINDER);
775 check_fhdr(struct sbni_softc *sc, u_int *framelen, u_int *frameno,
776 u_int *ack, u_int *is_first, u_int32_t *crc_p)
782 if (sbni_inb(sc, DAT) != SBNI_SIG)
785 value = sbni_inb(sc, DAT);
786 *framelen = (u_int)value;
787 crc = CRC32(value, crc);
788 value = sbni_inb(sc, DAT);
789 *framelen |= ((u_int)value) << 8;
790 crc = CRC32(value, crc);
792 *ack = *framelen & FRAME_ACK_MASK;
793 *is_first = (*framelen & FRAME_FIRST) != 0;
795 if ((*framelen &= FRAME_LEN_MASK) < 6 || *framelen > SBNI_MAX_FRAME - 3)
798 value = sbni_inb(sc, DAT);
799 *frameno = (u_int)value;
800 crc = CRC32(value, crc);
802 crc = CRC32(sbni_inb(sc, DAT), crc); /* reserved byte */
811 get_rx_buf(struct sbni_softc *sc)
815 MGETHDR(m, M_DONTWAIT, MT_DATA);
817 if_printf(sc->ifp, "cannot allocate header mbuf\n");
822 * We always put the received packet in a single buffer -
823 * either with just an mbuf header or in a cluster attached
824 * to the header. The +2 is to compensate for the alignment
827 if (ETHER_MAX_LEN + 2 > MHLEN) {
828 /* Attach an mbuf cluster */
829 MCLGET(m, M_DONTWAIT);
830 if ((m->m_flags & M_EXT) == 0) {
835 m->m_pkthdr.len = m->m_len = ETHER_MAX_LEN + 2;
838 * The +2 is to longword align the start of the real packet.
839 * (sizeof ether_header == 14)
840 * This is important for NFS.
849 indicate_pkt(struct sbni_softc *sc)
851 struct ifnet *ifp = sc->ifp;
855 m->m_pkthdr.rcvif = ifp;
856 m->m_pkthdr.len = m->m_len = sc->inppos;
858 (*ifp->if_input)(ifp, m);
862 /* -------------------------------------------------------------------------- */
865 * Routine checks periodically wire activity and regenerates marker if
866 * connect was inactive for a long time.
870 sbni_timeout(void *xsc)
872 struct sbni_softc *sc;
876 sc = (struct sbni_softc *)xsc;
879 csr0 = sbni_inb(sc, CSR0);
882 if (sc->timer_ticks) {
883 if (csr0 & (RC_RDY | BU_EMP))
884 /* receiving not active */
887 sc->in_stats.timeout_number++;
889 timeout_change_level(sc);
891 sbni_outb(sc, CSR1, *(u_char *)&sc->csr1 | PR_RES);
892 csr0 = sbni_inb(sc, CSR0);
896 sbni_outb(sc, CSR0, csr0 | RC_CHK);
897 sc->wch = timeout(sbni_timeout, sc, hz/SBNI_HZ);
901 /* -------------------------------------------------------------------------- */
904 card_start(struct sbni_softc *sc)
906 sc->timer_ticks = CHANGE_LEVEL_START_TICKS;
907 sc->state &= ~(FL_WAIT_ACK | FL_NEED_RESEND);
908 sc->state |= FL_PREV_OK;
911 sc->wait_frameno = 0;
913 sbni_outb(sc, CSR1, *(u_char *)&sc->csr1 | PR_RES);
914 sbni_outb(sc, CSR0, EN_INT);
917 /* -------------------------------------------------------------------------- */
920 * Device timeout/watchdog routine. Entered if the device neglects to
921 * generate an interrupt after a transmit has been started on it.
925 sbni_watchdog(struct ifnet *ifp)
927 log(LOG_ERR, "%s: device timeout\n", ifp->if_xname);
932 static u_char rxl_tab[] = {
933 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x08,
934 0x0a, 0x0c, 0x0f, 0x16, 0x18, 0x1a, 0x1c, 0x1f
937 #define SIZE_OF_TIMEOUT_RXL_TAB 4
938 static u_char timeout_rxl_tab[] = {
939 0x03, 0x05, 0x08, 0x0b
943 set_initial_values(struct sbni_softc *sc, struct sbni_flags flags)
945 if (flags.fixed_rxl) {
946 sc->delta_rxl = 0; /* disable receive level autodetection */
947 sc->cur_rxl_index = flags.rxl;
949 sc->delta_rxl = DEF_RXL_DELTA;
950 sc->cur_rxl_index = DEF_RXL;
953 sc->csr1.rate = flags.fixed_rate ? flags.rate : DEFAULT_RATE;
954 sc->csr1.rxl = rxl_tab[sc->cur_rxl_index];
955 sc->maxframe = DEFAULT_FRAME_LEN;
958 * generate Ethernet address (0x00ff01xxxxxx)
960 *(u_int16_t *) sc->enaddr = htons(0x00ff);
961 if (flags.mac_addr) {
962 *(u_int32_t *) (sc->enaddr + 2) =
963 htonl(flags.mac_addr | 0x01000000);
965 *(u_char *) (sc->enaddr + 2) = 0x01;
966 read_random(sc->enaddr + 3, 3);
971 #ifdef SBNI_DUAL_COMPOUND
974 connect_to_master(struct sbni_softc *sc)
976 struct sbni_softc *p, *p_prev;
978 for (p = sbni_headlist, p_prev = NULL; p; p_prev = p, p = p->link) {
979 if (rman_get_start(p->io_res) == rman_get_start(sc->io_res) + 4 ||
980 rman_get_start(p->io_res) == rman_get_start(sc->io_res) - 4) {
983 p_prev->link = p->link;
985 sbni_headlist = p->link;
993 #endif /* SBNI_DUAL_COMPOUND */
996 /* Receive level auto-selection */
999 change_level(struct sbni_softc *sc)
1001 if (sc->delta_rxl == 0) /* do not auto-negotiate RxL */
1004 if (sc->cur_rxl_index == 0)
1006 else if (sc->cur_rxl_index == 15)
1008 else if (sc->cur_rxl_rcvd < sc->prev_rxl_rcvd)
1009 sc->delta_rxl = -sc->delta_rxl;
1011 sc->csr1.rxl = rxl_tab[sc->cur_rxl_index += sc->delta_rxl];
1012 sbni_inb(sc, CSR0); /* it needed for PCI cards */
1013 sbni_outb(sc, CSR1, *(u_char *)&sc->csr1);
1015 sc->prev_rxl_rcvd = sc->cur_rxl_rcvd;
1016 sc->cur_rxl_rcvd = 0;
1021 timeout_change_level(struct sbni_softc *sc)
1023 sc->cur_rxl_index = timeout_rxl_tab[sc->timeout_rxl];
1024 if (++sc->timeout_rxl >= 4)
1025 sc->timeout_rxl = 0;
1027 sc->csr1.rxl = rxl_tab[sc->cur_rxl_index];
1029 sbni_outb(sc, CSR1, *(u_char *)&sc->csr1);
1031 sc->prev_rxl_rcvd = sc->cur_rxl_rcvd;
1032 sc->cur_rxl_rcvd = 0;
1035 /* -------------------------------------------------------------------------- */
1038 * Process an ioctl request. This code needs some work - it looks
1043 sbni_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
1045 struct sbni_softc *sc;
1048 struct sbni_in_stats *in_stats;
1049 struct sbni_flags flags;
1053 ifr = (struct ifreq *)data;
1062 * If the interface is marked up and stopped, then start it.
1063 * If it is marked down and running, then stop it.
1065 if (ifp->if_flags & IFF_UP) {
1066 if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
1069 if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
1071 ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
1079 * Multicast list has changed; set the hardware filter
1084 error = EAFNOSUPPORT; */
1088 if (ifr->ifr_mtu > ETHERMTU)
1091 ifp->if_mtu = ifr->ifr_mtu;
1095 * SBNI specific ioctl
1097 case SIOCGHWFLAGS: /* get flags */
1098 bcopy((caddr_t)IF_LLADDR(sc->ifp)+3, (caddr_t) &flags, 3);
1099 flags.rxl = sc->cur_rxl_index;
1100 flags.rate = sc->csr1.rate;
1101 flags.fixed_rxl = (sc->delta_rxl == 0);
1102 flags.fixed_rate = 1;
1103 ifr->ifr_data = *(caddr_t*) &flags;
1107 in_stats = (struct sbni_in_stats *)ifr->ifr_data;
1108 bcopy((void *)(&(sc->in_stats)), (void *)in_stats,
1109 sizeof(struct sbni_in_stats));
1112 case SIOCSHWFLAGS: /* set flags */
1114 error = priv_check(td, PRIV_DRIVER);
1117 flags = *(struct sbni_flags*)&ifr->ifr_data;
1118 if (flags.fixed_rxl) {
1120 sc->cur_rxl_index = flags.rxl;
1122 sc->delta_rxl = DEF_RXL_DELTA;
1123 sc->cur_rxl_index = DEF_RXL;
1125 sc->csr1.rxl = rxl_tab[sc->cur_rxl_index];
1126 sc->csr1.rate = flags.fixed_rate ? flags.rate : DEFAULT_RATE;
1128 bcopy((caddr_t) &flags,
1129 (caddr_t) IF_LLADDR(sc->ifp)+3, 3);
1131 /* Don't be afraid... */
1132 sbni_outb(sc, CSR1, *(char*)(&sc->csr1) | PR_RES);
1136 if (!(error = priv_check(td, PRIV_DRIVER))) /* root only */
1137 bzero(&sc->in_stats, sizeof(struct sbni_in_stats));
1141 error = ether_ioctl(ifp, command, data);
1149 /* -------------------------------------------------------------------------- */
1152 calc_crc32(u_int32_t crc, caddr_t p, u_int len)
1155 crc = CRC32(*p++, crc);
1160 static u_int32_t crc32tab[] __aligned(8) = {
1161 0xD202EF8D, 0xA505DF1B, 0x3C0C8EA1, 0x4B0BBE37,
1162 0xD56F2B94, 0xA2681B02, 0x3B614AB8, 0x4C667A2E,
1163 0xDCD967BF, 0xABDE5729, 0x32D70693, 0x45D03605,
1164 0xDBB4A3A6, 0xACB39330, 0x35BAC28A, 0x42BDF21C,
1165 0xCFB5FFE9, 0xB8B2CF7F, 0x21BB9EC5, 0x56BCAE53,
1166 0xC8D83BF0, 0xBFDF0B66, 0x26D65ADC, 0x51D16A4A,
1167 0xC16E77DB, 0xB669474D, 0x2F6016F7, 0x58672661,
1168 0xC603B3C2, 0xB1048354, 0x280DD2EE, 0x5F0AE278,
1169 0xE96CCF45, 0x9E6BFFD3, 0x0762AE69, 0x70659EFF,
1170 0xEE010B5C, 0x99063BCA, 0x000F6A70, 0x77085AE6,
1171 0xE7B74777, 0x90B077E1, 0x09B9265B, 0x7EBE16CD,
1172 0xE0DA836E, 0x97DDB3F8, 0x0ED4E242, 0x79D3D2D4,
1173 0xF4DBDF21, 0x83DCEFB7, 0x1AD5BE0D, 0x6DD28E9B,
1174 0xF3B61B38, 0x84B12BAE, 0x1DB87A14, 0x6ABF4A82,
1175 0xFA005713, 0x8D076785, 0x140E363F, 0x630906A9,
1176 0xFD6D930A, 0x8A6AA39C, 0x1363F226, 0x6464C2B0,
1177 0xA4DEAE1D, 0xD3D99E8B, 0x4AD0CF31, 0x3DD7FFA7,
1178 0xA3B36A04, 0xD4B45A92, 0x4DBD0B28, 0x3ABA3BBE,
1179 0xAA05262F, 0xDD0216B9, 0x440B4703, 0x330C7795,
1180 0xAD68E236, 0xDA6FD2A0, 0x4366831A, 0x3461B38C,
1181 0xB969BE79, 0xCE6E8EEF, 0x5767DF55, 0x2060EFC3,
1182 0xBE047A60, 0xC9034AF6, 0x500A1B4C, 0x270D2BDA,
1183 0xB7B2364B, 0xC0B506DD, 0x59BC5767, 0x2EBB67F1,
1184 0xB0DFF252, 0xC7D8C2C4, 0x5ED1937E, 0x29D6A3E8,
1185 0x9FB08ED5, 0xE8B7BE43, 0x71BEEFF9, 0x06B9DF6F,
1186 0x98DD4ACC, 0xEFDA7A5A, 0x76D32BE0, 0x01D41B76,
1187 0x916B06E7, 0xE66C3671, 0x7F6567CB, 0x0862575D,
1188 0x9606C2FE, 0xE101F268, 0x7808A3D2, 0x0F0F9344,
1189 0x82079EB1, 0xF500AE27, 0x6C09FF9D, 0x1B0ECF0B,
1190 0x856A5AA8, 0xF26D6A3E, 0x6B643B84, 0x1C630B12,
1191 0x8CDC1683, 0xFBDB2615, 0x62D277AF, 0x15D54739,
1192 0x8BB1D29A, 0xFCB6E20C, 0x65BFB3B6, 0x12B88320,
1193 0x3FBA6CAD, 0x48BD5C3B, 0xD1B40D81, 0xA6B33D17,
1194 0x38D7A8B4, 0x4FD09822, 0xD6D9C998, 0xA1DEF90E,
1195 0x3161E49F, 0x4666D409, 0xDF6F85B3, 0xA868B525,
1196 0x360C2086, 0x410B1010, 0xD80241AA, 0xAF05713C,
1197 0x220D7CC9, 0x550A4C5F, 0xCC031DE5, 0xBB042D73,
1198 0x2560B8D0, 0x52678846, 0xCB6ED9FC, 0xBC69E96A,
1199 0x2CD6F4FB, 0x5BD1C46D, 0xC2D895D7, 0xB5DFA541,
1200 0x2BBB30E2, 0x5CBC0074, 0xC5B551CE, 0xB2B26158,
1201 0x04D44C65, 0x73D37CF3, 0xEADA2D49, 0x9DDD1DDF,
1202 0x03B9887C, 0x74BEB8EA, 0xEDB7E950, 0x9AB0D9C6,
1203 0x0A0FC457, 0x7D08F4C1, 0xE401A57B, 0x930695ED,
1204 0x0D62004E, 0x7A6530D8, 0xE36C6162, 0x946B51F4,
1205 0x19635C01, 0x6E646C97, 0xF76D3D2D, 0x806A0DBB,
1206 0x1E0E9818, 0x6909A88E, 0xF000F934, 0x8707C9A2,
1207 0x17B8D433, 0x60BFE4A5, 0xF9B6B51F, 0x8EB18589,
1208 0x10D5102A, 0x67D220BC, 0xFEDB7106, 0x89DC4190,
1209 0x49662D3D, 0x3E611DAB, 0xA7684C11, 0xD06F7C87,
1210 0x4E0BE924, 0x390CD9B2, 0xA0058808, 0xD702B89E,
1211 0x47BDA50F, 0x30BA9599, 0xA9B3C423, 0xDEB4F4B5,
1212 0x40D06116, 0x37D75180, 0xAEDE003A, 0xD9D930AC,
1213 0x54D13D59, 0x23D60DCF, 0xBADF5C75, 0xCDD86CE3,
1214 0x53BCF940, 0x24BBC9D6, 0xBDB2986C, 0xCAB5A8FA,
1215 0x5A0AB56B, 0x2D0D85FD, 0xB404D447, 0xC303E4D1,
1216 0x5D677172, 0x2A6041E4, 0xB369105E, 0xC46E20C8,
1217 0x72080DF5, 0x050F3D63, 0x9C066CD9, 0xEB015C4F,
1218 0x7565C9EC, 0x0262F97A, 0x9B6BA8C0, 0xEC6C9856,
1219 0x7CD385C7, 0x0BD4B551, 0x92DDE4EB, 0xE5DAD47D,
1220 0x7BBE41DE, 0x0CB97148, 0x95B020F2, 0xE2B71064,
1221 0x6FBF1D91, 0x18B82D07, 0x81B17CBD, 0xF6B64C2B,
1222 0x68D2D988, 0x1FD5E91E, 0x86DCB8A4, 0xF1DB8832,
1223 0x616495A3, 0x1663A535, 0x8F6AF48F, 0xF86DC419,
1224 0x660951BA, 0x110E612C, 0x88073096, 0xFF000000