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
27 * $FreeBSD: src/sys/dev/sbni/if_sbni.c,v 1.1.2.4 2002/08/11 09:32:00 fjoe Exp $
28 * $DragonFly: src/sys/dev/netif/sbni/if_sbni.c,v 1.16 2004/09/15 00:39:53 joerg Exp $
32 * Device driver for Granch SBNI12 leased line adapters
34 * Revision 2.0.0 1997/08/06
35 * Initial revision by Alexey Zverev
37 * Revision 2.0.1 1997/08/11
38 * Additional internal statistics support (tx statistics)
40 * Revision 2.0.2 1997/11/05
41 * if_bpf bug has been fixed
43 * Revision 2.0.3 1998/12/20
44 * Memory leakage has been eliminated in
45 * the sbni_st and sbni_timeout routines.
47 * Revision 3.0 2000/08/10 by Yaroslav Polyakov
48 * Support for PCI cards. 4.1 modification.
50 * Revision 3.1 2000/09/12
51 * Removed extra #defines around bpf functions
53 * Revision 4.0 2000/11/23 by Denis Timofeev
54 * Completely redesigned the buffer management
56 * Revision 4.1 2001/01/21
57 * Support for PCI Dual cards and new SBNI12D-10, -11 Dual/ISA cards
59 * Written with reference to NE2000 driver developed by David Greenman.
63 #include <sys/param.h>
64 #include <sys/systm.h>
65 #include <sys/socket.h>
66 #include <sys/sockio.h>
68 #include <sys/kernel.h>
70 #include <sys/callout.h>
71 #include <sys/syslog.h>
72 #include <sys/random.h>
74 #include <machine/bus.h>
76 #include <machine/resource.h>
79 #include <net/ethernet.h>
80 #include <net/if_arp.h>
83 #include "if_sbnireg.h"
84 #include "if_sbnivar.h"
88 static void sbni_init(void *);
89 static void sbni_start(struct ifnet *);
90 static int sbni_ioctl(struct ifnet *, u_long, caddr_t, struct ucred *);
91 static void sbni_watchdog(struct ifnet *);
92 static void sbni_stop(struct sbni_softc *);
93 static void handle_channel(struct sbni_softc *);
95 static void card_start(struct sbni_softc *);
96 static int recv_frame(struct sbni_softc *);
97 static void send_frame(struct sbni_softc *);
98 static int upload_data(struct sbni_softc *, u_int, u_int, u_int, u_int32_t);
99 static int skip_tail(struct sbni_softc *, u_int, u_int32_t);
100 static void interpret_ack(struct sbni_softc *, u_int);
101 static void download_data(struct sbni_softc *, u_int32_t *);
102 static void prepare_to_send(struct sbni_softc *);
103 static void drop_xmit_queue(struct sbni_softc *);
104 static int get_rx_buf(struct sbni_softc *);
105 static void indicate_pkt(struct sbni_softc *);
106 static void change_level(struct sbni_softc *);
107 static int check_fhdr(struct sbni_softc *, u_int *, u_int *,
108 u_int *, u_int *, u_int32_t *);
109 static int append_frame_to_pkt(struct sbni_softc *, u_int, u_int32_t);
110 static void timeout_change_level(struct sbni_softc *);
111 static void send_frame_header(struct sbni_softc *, u_int32_t *);
112 static void set_initial_values(struct sbni_softc *, struct sbni_flags);
114 static u_int32_t calc_crc32(u_int32_t, caddr_t, u_int);
115 static timeout_t sbni_timeout;
117 static __inline u_char sbni_inb(struct sbni_softc *, enum sbni_reg);
118 static __inline void sbni_outb(struct sbni_softc *, enum sbni_reg, u_char);
119 static __inline void sbni_insb(struct sbni_softc *, u_char *, u_int);
120 static __inline void sbni_outsb(struct sbni_softc *, u_char *, u_int);
122 DECLARE_DUMMY_MODULE(if_sbni);
124 static u_int32_t crc32tab[];
126 #ifdef SBNI_DUAL_COMPOUND
127 struct sbni_softc *sbni_headlist;
130 u_int32_t next_sbni_unit;
132 /* -------------------------------------------------------------------------- */
134 static __inline u_char
135 sbni_inb(struct sbni_softc *sc, enum sbni_reg reg)
137 return bus_space_read_1(
138 rman_get_bustag(sc->io_res),
139 rman_get_bushandle(sc->io_res),
144 sbni_outb(struct sbni_softc *sc, enum sbni_reg reg, u_char value)
147 rman_get_bustag(sc->io_res),
148 rman_get_bushandle(sc->io_res),
149 sc->io_off + reg, value);
153 sbni_insb(struct sbni_softc *sc, u_char *to, u_int len)
155 bus_space_read_multi_1(
156 rman_get_bustag(sc->io_res),
157 rman_get_bushandle(sc->io_res),
158 sc->io_off + DAT, to, len);
162 sbni_outsb(struct sbni_softc *sc, u_char *from, u_int len)
164 bus_space_write_multi_1(
165 rman_get_bustag(sc->io_res),
166 rman_get_bushandle(sc->io_res),
167 sc->io_off + DAT, from, len);
172 Valid combinations in CSR0 (for probing):
174 VALID_DECODER 0000,0011,1011,1010
179 TR_RDY TR_REQ ; 3 ; +
181 BU_EMP TR_REQ ; 5 ; +
182 BU_EMP TR_RDY ; 6 ; -
183 BU_EMP TR_RDY TR_REQ ; 7 ; +
185 RC_RDY TR_REQ ; 9 ; +
186 RC_RDY TR_RDY ; 10 ; -
187 RC_RDY TR_RDY TR_REQ ; 11 ; -
188 RC_RDY BU_EMP ; 12 ; -
189 RC_RDY BU_EMP TR_REQ ; 13 ; -
190 RC_RDY BU_EMP TR_RDY ; 14 ; -
191 RC_RDY BU_EMP TR_RDY TR_REQ ; 15 ; -
194 #define VALID_DECODER (2 + 8 + 0x10 + 0x20 + 0x80 + 0x100 + 0x200)
198 sbni_probe(struct sbni_softc *sc)
202 csr0 = sbni_inb(sc, CSR0);
203 if (csr0 != 0xff && csr0 != 0x00) {
208 if (VALID_DECODER & (1 << (csr0 >> 4)))
217 * Install interface into kernel networking data structures
220 sbni_attach(struct sbni_softc *sc, int unit, struct sbni_flags flags)
225 ifp = &sc->arpcom.ac_if;
226 sbni_outb(sc, CSR0, 0);
227 set_initial_values(sc, flags);
229 callout_init(&sc->sbni_stat_timer);
230 /* Initialize ifnet structure */
232 if_initname(ifp, "sbni", unit);
233 ifp->if_init = sbni_init;
234 ifp->if_start = sbni_start;
235 ifp->if_ioctl = sbni_ioctl;
236 ifp->if_watchdog = sbni_watchdog;
237 ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
239 /* report real baud rate */
240 csr0 = sbni_inb(sc, CSR0);
242 (csr0 & 0x01 ? 500000 : 2000000) / (1 << flags.rate);
244 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
245 ether_ifattach(ifp, sc->arpcom.ac_enaddr);
247 /* device attach does transition from UNCONFIGURED to IDLE state */
249 if_printf(ifp, "speed %ld, rxl ", ifp->if_baudrate);
253 printf("%d (fixed)\n", sc->cur_rxl_index);
256 /* -------------------------------------------------------------------------- */
261 struct sbni_softc *sc;
265 sc = (struct sbni_softc *)xsc;
266 ifp = &sc->arpcom.ac_if;
268 /* address not known */
269 if (TAILQ_EMPTY(&ifp->if_addrhead))
273 * kludge to avoid multiple initialization when more than once
274 * protocols configured
276 if (ifp->if_flags & IFF_RUNNING)
282 callout_reset(&sc->sbni_stat_timer,hz / SBNI_HZ, sbni_timeout, sc);
284 ifp->if_flags |= IFF_RUNNING;
285 ifp->if_flags &= ~IFF_OACTIVE;
287 /* attempt to start output */
294 sbni_start(struct ifnet *ifp)
296 struct sbni_softc *sc = ifp->if_softc;
297 if (sc->tx_frameno == 0)
303 sbni_stop(struct sbni_softc *sc)
305 sbni_outb(sc, CSR0, 0);
309 m_freem(sc->rx_buf_p);
313 callout_stop(&sc->sbni_stat_timer);
316 /* -------------------------------------------------------------------------- */
318 /* interrupt handler */
321 * SBNI12D-10, -11/ISA boards within "common interrupt" mode could not
322 * be looked as two independent single-channel devices. Every channel seems
323 * as Ethernet interface but interrupt handler must be common. Really, first
324 * channel ("master") driver only registers the handler. In it's struct softc
325 * it has got pointer to "slave" channel's struct softc and handles that's
327 * softc of successfully attached ISA SBNI boards is linked to list.
328 * While next board driver is initialized, it scans this list. If one
329 * has found softc with same irq and ioaddr different by 4 then it assumes
330 * this board to be "master".
336 struct sbni_softc *sc;
339 sc = (struct sbni_softc *)arg;
343 if (sbni_inb(sc, CSR0) & (RC_RDY | TR_RDY)) {
347 if (sc->slave_sc && /* second channel present */
348 (sbni_inb(sc->slave_sc, CSR0) & (RC_RDY | TR_RDY))) {
349 handle_channel(sc->slave_sc);
357 handle_channel(struct sbni_softc *sc)
362 sbni_outb(sc, CSR0, (sbni_inb(sc, CSR0) & ~EN_INT) | TR_REQ);
364 sc->timer_ticks = CHANGE_LEVEL_START_TICKS;
366 csr0 = sbni_inb(sc, CSR0);
367 if ((csr0 & (RC_RDY | TR_RDY)) == 0)
370 req_ans = !(sc->state & FL_PREV_OK);
373 req_ans = recv_frame(sc);
376 * TR_RDY always equals 1 here because we have owned the marker,
377 * and we set TR_REQ when disabled interrupts
379 csr0 = sbni_inb(sc, CSR0);
380 if ((csr0 & TR_RDY) == 0 || (csr0 & RC_RDY) != 0)
381 printf("sbni: internal error!\n");
383 /* if state & FL_NEED_RESEND != 0 then tx_frameno != 0 */
384 if (req_ans || sc->tx_frameno != 0)
387 /* send the marker without any data */
388 sbni_outb(sc, CSR0, sbni_inb(sc, CSR0) & ~TR_REQ);
392 sbni_outb(sc, CSR0, sbni_inb(sc, CSR0) | EN_INT);
397 * Routine returns 1 if it need to acknoweledge received frame.
398 * Empty frame received without errors won't be acknoweledged.
402 recv_frame(struct sbni_softc *sc)
405 u_int framelen, frameno, ack;
406 u_int is_first, frame_ok;
409 if (check_fhdr(sc, &framelen, &frameno, &ack, &is_first, &crc)) {
410 frame_ok = framelen > 4 ?
411 upload_data(sc, framelen, frameno, is_first, crc) :
412 skip_tail(sc, framelen, crc);
414 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->arpcom.ac_if.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->arpcom.ac_if.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->arpcom.ac_if.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->arpcom.ac_if.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->arpcom.ac_if.if_snd, sc->tx_buf_p);
669 /* nothing to transmit... */
673 sc->arpcom.ac_if.if_flags &= ~IFF_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->arpcom.ac_if.if_flags |= IFF_OACTIVE;
694 if (sc->arpcom.ac_if.if_bpf)
695 bpf_mtap(&sc->arpcom.ac_if, sc->tx_buf_p);
700 drop_xmit_queue(struct sbni_softc *sc)
705 m_freem(sc->tx_buf_p);
707 sc->arpcom.ac_if.if_oerrors++;
711 IF_DEQUEUE(&sc->arpcom.ac_if.if_snd, m);
715 sc->arpcom.ac_if.if_oerrors++;
721 sc->state &= ~(FL_WAIT_ACK | FL_NEED_RESEND);
722 sc->arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
727 send_frame_header(struct sbni_softc *sc, u_int32_t *crc_p)
734 len_field = sc->framelen + 6; /* CRC + frameno + reserved */
736 if (sc->state & FL_NEED_RESEND)
737 len_field |= FRAME_RETRY; /* non-first attempt... */
740 len_field |= FRAME_FIRST;
742 len_field |= (sc->state & FL_PREV_OK) ? FRAME_SENT_OK : FRAME_SENT_BAD;
743 sbni_outb(sc, DAT, SBNI_SIG);
745 value = (u_char)len_field;
746 sbni_outb(sc, DAT, value);
747 crc = CRC32(value, crc);
748 value = (u_char)(len_field >> 8);
749 sbni_outb(sc, DAT, value);
750 crc = CRC32(value, crc);
752 sbni_outb(sc, DAT, sc->tx_frameno);
753 crc = CRC32(sc->tx_frameno, crc);
754 sbni_outb(sc, DAT, 0);
761 * if frame tail not needed (incorrect number or received twice),
762 * it won't store, but CRC will be calculated
766 skip_tail(struct sbni_softc *sc, u_int tail_len, u_int32_t crc)
769 crc = CRC32(sbni_inb(sc, DAT), crc);
771 return (crc == CRC32_REMAINDER);
776 check_fhdr(struct sbni_softc *sc, u_int *framelen, u_int *frameno,
777 u_int *ack, u_int *is_first, u_int32_t *crc_p)
783 if (sbni_inb(sc, DAT) != SBNI_SIG)
786 value = sbni_inb(sc, DAT);
787 *framelen = (u_int)value;
788 crc = CRC32(value, crc);
789 value = sbni_inb(sc, DAT);
790 *framelen |= ((u_int)value) << 8;
791 crc = CRC32(value, crc);
793 *ack = *framelen & FRAME_ACK_MASK;
794 *is_first = (*framelen & FRAME_FIRST) != 0;
796 if ((*framelen &= FRAME_LEN_MASK) < 6 || *framelen > SBNI_MAX_FRAME - 3)
799 value = sbni_inb(sc, DAT);
800 *frameno = (u_int)value;
801 crc = CRC32(value, crc);
803 crc = CRC32(sbni_inb(sc, DAT), crc); /* reserved byte */
812 get_rx_buf(struct sbni_softc *sc)
816 MGETHDR(m, MB_DONTWAIT, MT_DATA);
818 printf("%s: cannot allocate header mbuf\n",
819 sc->arpcom.ac_if.if_xname);
824 * We always put the received packet in a single buffer -
825 * either with just an mbuf header or in a cluster attached
826 * to the header. The +2 is to compensate for the alignment
829 if (ETHER_MAX_LEN + 2 > MHLEN) {
830 /* Attach an mbuf cluster */
831 MCLGET(m, MB_DONTWAIT);
832 if ((m->m_flags & M_EXT) == 0) {
837 m->m_pkthdr.len = m->m_len = ETHER_MAX_LEN + 2;
840 * The +2 is to longword align the start of the real packet.
841 * (sizeof ether_header == 14)
842 * This is important for NFS.
851 indicate_pkt(struct sbni_softc *sc)
853 struct ifnet *ifp = &sc->arpcom.ac_if;
857 m->m_pkthdr.rcvif = ifp;
858 m->m_pkthdr.len = m->m_len = sc->inppos;
860 (*ifp->if_input)(ifp, m);
864 /* -------------------------------------------------------------------------- */
867 * Routine checks periodically wire activity and regenerates marker if
868 * connect was inactive for a long time.
872 sbni_timeout(void *xsc)
874 struct sbni_softc *sc;
878 sc = (struct sbni_softc *)xsc;
881 csr0 = sbni_inb(sc, CSR0);
884 if (sc->timer_ticks) {
885 if (csr0 & (RC_RDY | BU_EMP))
886 /* receiving not active */
889 sc->in_stats.timeout_number++;
891 timeout_change_level(sc);
893 sbni_outb(sc, CSR1, *(u_char *)&sc->csr1 | PR_RES);
894 csr0 = sbni_inb(sc, CSR0);
898 sbni_outb(sc, CSR0, csr0 | RC_CHK);
899 callout_reset(&sc->sbni_stat_timer, hz / SBNI_HZ, sbni_timeout, sc);
903 /* -------------------------------------------------------------------------- */
906 card_start(struct sbni_softc *sc)
908 sc->timer_ticks = CHANGE_LEVEL_START_TICKS;
909 sc->state &= ~(FL_WAIT_ACK | FL_NEED_RESEND);
910 sc->state |= FL_PREV_OK;
913 sc->wait_frameno = 0;
915 sbni_outb(sc, CSR1, *(u_char *)&sc->csr1 | PR_RES);
916 sbni_outb(sc, CSR0, EN_INT);
919 /* -------------------------------------------------------------------------- */
922 * Device timeout/watchdog routine. Entered if the device neglects to
923 * generate an interrupt after a transmit has been started on it.
927 sbni_watchdog(struct ifnet *ifp)
929 log(LOG_ERR, "%s: device timeout\n", ifp->if_xname);
934 static u_char rxl_tab[] = {
935 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x08,
936 0x0a, 0x0c, 0x0f, 0x16, 0x18, 0x1a, 0x1c, 0x1f
939 #define SIZE_OF_TIMEOUT_RXL_TAB 4
940 static u_char timeout_rxl_tab[] = {
941 0x03, 0x05, 0x08, 0x0b
945 set_initial_values(struct sbni_softc *sc, struct sbni_flags flags)
947 if (flags.fixed_rxl) {
948 sc->delta_rxl = 0; /* disable receive level autodetection */
949 sc->cur_rxl_index = flags.rxl;
951 sc->delta_rxl = DEF_RXL_DELTA;
952 sc->cur_rxl_index = DEF_RXL;
955 sc->csr1.rate = flags.fixed_rate ? flags.rate : DEFAULT_RATE;
956 sc->csr1.rxl = rxl_tab[sc->cur_rxl_index];
957 sc->maxframe = DEFAULT_FRAME_LEN;
960 * generate Ethernet address (0x00ff01xxxxxx)
962 *(u_int16_t *) sc->arpcom.ac_enaddr = htons(0x00ff);
963 if (flags.mac_addr) {
964 *(u_int32_t *) (sc->arpcom.ac_enaddr + 2) =
965 htonl(flags.mac_addr | 0x01000000);
967 *(u_char *) (sc->arpcom.ac_enaddr + 2) = 0x01;
968 read_random_unlimited(sc->arpcom.ac_enaddr + 3, 3);
973 #ifdef SBNI_DUAL_COMPOUND
976 connect_to_master(struct sbni_softc *sc)
978 struct sbni_softc *p, *p_prev;
980 for (p = sbni_headlist, p_prev = NULL; p; p_prev = p, p = p->link) {
981 if (rman_get_start(p->io_res) == rman_get_start(sc->io_res) + 4 ||
982 rman_get_start(p->io_res) == rman_get_start(sc->io_res) - 4) {
985 p_prev->link = p->link;
987 sbni_headlist = p->link;
995 #endif /* SBNI_DUAL_COMPOUND */
998 /* Receive level auto-selection */
1001 change_level(struct sbni_softc *sc)
1003 if (sc->delta_rxl == 0) /* do not auto-negotiate RxL */
1006 if (sc->cur_rxl_index == 0)
1008 else if (sc->cur_rxl_index == 15)
1010 else if (sc->cur_rxl_rcvd < sc->prev_rxl_rcvd)
1011 sc->delta_rxl = -sc->delta_rxl;
1013 sc->csr1.rxl = rxl_tab[sc->cur_rxl_index += sc->delta_rxl];
1014 sbni_inb(sc, CSR0); /* it needed for PCI cards */
1015 sbni_outb(sc, CSR1, *(u_char *)&sc->csr1);
1017 sc->prev_rxl_rcvd = sc->cur_rxl_rcvd;
1018 sc->cur_rxl_rcvd = 0;
1023 timeout_change_level(struct sbni_softc *sc)
1025 sc->cur_rxl_index = timeout_rxl_tab[sc->timeout_rxl];
1026 if (++sc->timeout_rxl >= 4)
1027 sc->timeout_rxl = 0;
1029 sc->csr1.rxl = rxl_tab[sc->cur_rxl_index];
1031 sbni_outb(sc, CSR1, *(u_char *)&sc->csr1);
1033 sc->prev_rxl_rcvd = sc->cur_rxl_rcvd;
1034 sc->cur_rxl_rcvd = 0;
1037 /* -------------------------------------------------------------------------- */
1040 * Process an ioctl request. This code needs some work - it looks
1045 sbni_ioctl(struct ifnet *ifp, u_long command, caddr_t data, struct ucred *cr)
1047 struct sbni_softc *sc;
1049 struct sbni_in_stats *in_stats;
1050 struct sbni_flags flags;
1054 ifr = (struct ifreq *)data;
1062 ether_ioctl(ifp, command, data);
1067 * If the interface is marked up and stopped, then start it.
1068 * If it is marked down and running, then stop it.
1070 if (ifp->if_flags & IFF_UP) {
1071 if (!(ifp->if_flags & IFF_RUNNING))
1074 if (ifp->if_flags & IFF_RUNNING) {
1076 ifp->if_flags &= ~IFF_RUNNING;
1084 * Multicast list has changed; set the hardware filter
1089 error = EAFNOSUPPORT; */
1093 if (ifr->ifr_mtu > ETHERMTU)
1096 ifp->if_mtu = ifr->ifr_mtu;
1100 * SBNI specific ioctl
1102 case SIOCGHWFLAGS: /* get flags */
1103 bcopy((caddr_t) sc->arpcom.ac_enaddr+3, (caddr_t) &flags, 3);
1104 flags.rxl = sc->cur_rxl_index;
1105 flags.rate = sc->csr1.rate;
1106 flags.fixed_rxl = (sc->delta_rxl == 0);
1107 flags.fixed_rate = 1;
1108 ifr->ifr_data = *(caddr_t*) &flags;
1112 in_stats = (struct sbni_in_stats *)ifr->ifr_data;
1113 bcopy((void *)(&(sc->in_stats)), (void *)in_stats,
1114 sizeof(struct sbni_in_stats));
1117 case SIOCSHWFLAGS: /* set flags */
1119 error = suser_cred(cr, NULL_CRED_OKAY);
1120 /* NOTE: returns EPERM if no proc */
1123 flags = *(struct sbni_flags*)&ifr->ifr_data;
1124 if (flags.fixed_rxl) {
1126 sc->cur_rxl_index = flags.rxl;
1128 sc->delta_rxl = DEF_RXL_DELTA;
1129 sc->cur_rxl_index = DEF_RXL;
1131 sc->csr1.rxl = rxl_tab[sc->cur_rxl_index];
1132 sc->csr1.rate = flags.fixed_rate ? flags.rate : DEFAULT_RATE;
1134 bcopy((caddr_t) &flags,
1135 (caddr_t) sc->arpcom.ac_enaddr+3, 3);
1137 /* Don't be afraid... */
1138 sbni_outb(sc, CSR1, *(char*)(&sc->csr1) | PR_RES);
1142 if (!(error = suser_cred(cr, NULL_CRED_OKAY))) /* root only */
1143 bzero(&sc->in_stats, sizeof(struct sbni_in_stats));
1154 /* -------------------------------------------------------------------------- */
1159 calc_crc32(u_int32_t crc, caddr_t p, u_int len)
1165 "xorl %%ebx, %%ebx\n"
1168 "movl $crc32tab, %%edi\n"
1175 "movl (%%esi), %%edx\n"
1179 "xorl (%%edi,%%ebx,4), %%eax\n"
1185 "xorl (%%edi,%%ebx,4), %%eax\n"
1191 "xorl (%%edi,%%ebx,4), %%eax\n"
1197 "xorl (%%edi,%%ebx,4), %%eax\n"
1209 "xorb (%%esi), %%bl\n"
1210 "xorl (%%edi,%%ebx,4), %%eax\n"
1217 "xorb 1(%%esi), %%bl\n"
1218 "xorl (%%edi,%%ebx,4), %%eax\n"
1225 "xorb 2(%%esi), %%bl\n"
1226 "xorl (%%edi,%%ebx,4), %%eax\n"
1229 : "a" (_crc), "g" (p), "g" (len)
1230 : "bx", "cx", "dx", "si", "di"
1239 calc_crc32(u_int32_t crc, caddr_t p, u_int len)
1242 crc = CRC32(*p++, crc);
1247 #endif /* ASM_CRC */
1250 static u_int32_t crc32tab[] __attribute__ ((aligned(8))) = {
1251 0xD202EF8D, 0xA505DF1B, 0x3C0C8EA1, 0x4B0BBE37,
1252 0xD56F2B94, 0xA2681B02, 0x3B614AB8, 0x4C667A2E,
1253 0xDCD967BF, 0xABDE5729, 0x32D70693, 0x45D03605,
1254 0xDBB4A3A6, 0xACB39330, 0x35BAC28A, 0x42BDF21C,
1255 0xCFB5FFE9, 0xB8B2CF7F, 0x21BB9EC5, 0x56BCAE53,
1256 0xC8D83BF0, 0xBFDF0B66, 0x26D65ADC, 0x51D16A4A,
1257 0xC16E77DB, 0xB669474D, 0x2F6016F7, 0x58672661,
1258 0xC603B3C2, 0xB1048354, 0x280DD2EE, 0x5F0AE278,
1259 0xE96CCF45, 0x9E6BFFD3, 0x0762AE69, 0x70659EFF,
1260 0xEE010B5C, 0x99063BCA, 0x000F6A70, 0x77085AE6,
1261 0xE7B74777, 0x90B077E1, 0x09B9265B, 0x7EBE16CD,
1262 0xE0DA836E, 0x97DDB3F8, 0x0ED4E242, 0x79D3D2D4,
1263 0xF4DBDF21, 0x83DCEFB7, 0x1AD5BE0D, 0x6DD28E9B,
1264 0xF3B61B38, 0x84B12BAE, 0x1DB87A14, 0x6ABF4A82,
1265 0xFA005713, 0x8D076785, 0x140E363F, 0x630906A9,
1266 0xFD6D930A, 0x8A6AA39C, 0x1363F226, 0x6464C2B0,
1267 0xA4DEAE1D, 0xD3D99E8B, 0x4AD0CF31, 0x3DD7FFA7,
1268 0xA3B36A04, 0xD4B45A92, 0x4DBD0B28, 0x3ABA3BBE,
1269 0xAA05262F, 0xDD0216B9, 0x440B4703, 0x330C7795,
1270 0xAD68E236, 0xDA6FD2A0, 0x4366831A, 0x3461B38C,
1271 0xB969BE79, 0xCE6E8EEF, 0x5767DF55, 0x2060EFC3,
1272 0xBE047A60, 0xC9034AF6, 0x500A1B4C, 0x270D2BDA,
1273 0xB7B2364B, 0xC0B506DD, 0x59BC5767, 0x2EBB67F1,
1274 0xB0DFF252, 0xC7D8C2C4, 0x5ED1937E, 0x29D6A3E8,
1275 0x9FB08ED5, 0xE8B7BE43, 0x71BEEFF9, 0x06B9DF6F,
1276 0x98DD4ACC, 0xEFDA7A5A, 0x76D32BE0, 0x01D41B76,
1277 0x916B06E7, 0xE66C3671, 0x7F6567CB, 0x0862575D,
1278 0x9606C2FE, 0xE101F268, 0x7808A3D2, 0x0F0F9344,
1279 0x82079EB1, 0xF500AE27, 0x6C09FF9D, 0x1B0ECF0B,
1280 0x856A5AA8, 0xF26D6A3E, 0x6B643B84, 0x1C630B12,
1281 0x8CDC1683, 0xFBDB2615, 0x62D277AF, 0x15D54739,
1282 0x8BB1D29A, 0xFCB6E20C, 0x65BFB3B6, 0x12B88320,
1283 0x3FBA6CAD, 0x48BD5C3B, 0xD1B40D81, 0xA6B33D17,
1284 0x38D7A8B4, 0x4FD09822, 0xD6D9C998, 0xA1DEF90E,
1285 0x3161E49F, 0x4666D409, 0xDF6F85B3, 0xA868B525,
1286 0x360C2086, 0x410B1010, 0xD80241AA, 0xAF05713C,
1287 0x220D7CC9, 0x550A4C5F, 0xCC031DE5, 0xBB042D73,
1288 0x2560B8D0, 0x52678846, 0xCB6ED9FC, 0xBC69E96A,
1289 0x2CD6F4FB, 0x5BD1C46D, 0xC2D895D7, 0xB5DFA541,
1290 0x2BBB30E2, 0x5CBC0074, 0xC5B551CE, 0xB2B26158,
1291 0x04D44C65, 0x73D37CF3, 0xEADA2D49, 0x9DDD1DDF,
1292 0x03B9887C, 0x74BEB8EA, 0xEDB7E950, 0x9AB0D9C6,
1293 0x0A0FC457, 0x7D08F4C1, 0xE401A57B, 0x930695ED,
1294 0x0D62004E, 0x7A6530D8, 0xE36C6162, 0x946B51F4,
1295 0x19635C01, 0x6E646C97, 0xF76D3D2D, 0x806A0DBB,
1296 0x1E0E9818, 0x6909A88E, 0xF000F934, 0x8707C9A2,
1297 0x17B8D433, 0x60BFE4A5, 0xF9B6B51F, 0x8EB18589,
1298 0x10D5102A, 0x67D220BC, 0xFEDB7106, 0x89DC4190,
1299 0x49662D3D, 0x3E611DAB, 0xA7684C11, 0xD06F7C87,
1300 0x4E0BE924, 0x390CD9B2, 0xA0058808, 0xD702B89E,
1301 0x47BDA50F, 0x30BA9599, 0xA9B3C423, 0xDEB4F4B5,
1302 0x40D06116, 0x37D75180, 0xAEDE003A, 0xD9D930AC,
1303 0x54D13D59, 0x23D60DCF, 0xBADF5C75, 0xCDD86CE3,
1304 0x53BCF940, 0x24BBC9D6, 0xBDB2986C, 0xCAB5A8FA,
1305 0x5A0AB56B, 0x2D0D85FD, 0xB404D447, 0xC303E4D1,
1306 0x5D677172, 0x2A6041E4, 0xB369105E, 0xC46E20C8,
1307 0x72080DF5, 0x050F3D63, 0x9C066CD9, 0xEB015C4F,
1308 0x7565C9EC, 0x0262F97A, 0x9B6BA8C0, 0xEC6C9856,
1309 0x7CD385C7, 0x0BD4B551, 0x92DDE4EB, 0xE5DAD47D,
1310 0x7BBE41DE, 0x0CB97148, 0x95B020F2, 0xE2B71064,
1311 0x6FBF1D91, 0x18B82D07, 0x81B17CBD, 0xF6B64C2B,
1312 0x68D2D988, 0x1FD5E91E, 0x86DCB8A4, 0xF1DB8832,
1313 0x616495A3, 0x1663A535, 0x8F6AF48F, 0xF86DC419,
1314 0x660951BA, 0x110E612C, 0x88073096, 0xFF000000