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.19 2005/05/27 15:36:10 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/ifq_var.h>
80 #include <net/ethernet.h>
81 #include <net/if_arp.h>
84 #include "if_sbnireg.h"
85 #include "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, struct ucred *);
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 DECLARE_DUMMY_MODULE(if_sbni);
125 static u_int32_t crc32tab[];
127 #ifdef SBNI_DUAL_COMPOUND
128 struct sbni_softc *sbni_headlist;
131 u_int32_t next_sbni_unit;
133 /* -------------------------------------------------------------------------- */
135 static __inline u_char
136 sbni_inb(struct sbni_softc *sc, enum sbni_reg reg)
138 return bus_space_read_1(
139 rman_get_bustag(sc->io_res),
140 rman_get_bushandle(sc->io_res),
145 sbni_outb(struct sbni_softc *sc, enum sbni_reg reg, u_char value)
148 rman_get_bustag(sc->io_res),
149 rman_get_bushandle(sc->io_res),
150 sc->io_off + reg, value);
154 sbni_insb(struct sbni_softc *sc, u_char *to, u_int len)
156 bus_space_read_multi_1(
157 rman_get_bustag(sc->io_res),
158 rman_get_bushandle(sc->io_res),
159 sc->io_off + DAT, to, len);
163 sbni_outsb(struct sbni_softc *sc, u_char *from, u_int len)
165 bus_space_write_multi_1(
166 rman_get_bustag(sc->io_res),
167 rman_get_bushandle(sc->io_res),
168 sc->io_off + DAT, from, len);
173 Valid combinations in CSR0 (for probing):
175 VALID_DECODER 0000,0011,1011,1010
180 TR_RDY TR_REQ ; 3 ; +
182 BU_EMP TR_REQ ; 5 ; +
183 BU_EMP TR_RDY ; 6 ; -
184 BU_EMP TR_RDY TR_REQ ; 7 ; +
186 RC_RDY TR_REQ ; 9 ; +
187 RC_RDY TR_RDY ; 10 ; -
188 RC_RDY TR_RDY TR_REQ ; 11 ; -
189 RC_RDY BU_EMP ; 12 ; -
190 RC_RDY BU_EMP TR_REQ ; 13 ; -
191 RC_RDY BU_EMP TR_RDY ; 14 ; -
192 RC_RDY BU_EMP TR_RDY TR_REQ ; 15 ; -
195 #define VALID_DECODER (2 + 8 + 0x10 + 0x20 + 0x80 + 0x100 + 0x200)
199 sbni_probe(struct sbni_softc *sc)
203 csr0 = sbni_inb(sc, CSR0);
204 if (csr0 != 0xff && csr0 != 0x00) {
209 if (VALID_DECODER & (1 << (csr0 >> 4)))
218 * Install interface into kernel networking data structures
221 sbni_attach(struct sbni_softc *sc, int unit, struct sbni_flags flags)
226 ifp = &sc->arpcom.ac_if;
227 sbni_outb(sc, CSR0, 0);
228 set_initial_values(sc, flags);
230 callout_init(&sc->sbni_stat_timer);
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 ifq_set_maxlen(&ifp->if_snd, IFQ_MAXLEN);
239 ifq_set_ready(&ifp->if_snd);
241 /* report real baud rate */
242 csr0 = sbni_inb(sc, CSR0);
244 (csr0 & 0x01 ? 500000 : 2000000) / (1 << flags.rate);
246 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
247 ether_ifattach(ifp, sc->arpcom.ac_enaddr);
249 /* device attach does transition from UNCONFIGURED to IDLE state */
251 if_printf(ifp, "speed %ld, rxl ", ifp->if_baudrate);
255 printf("%d (fixed)\n", sc->cur_rxl_index);
258 /* -------------------------------------------------------------------------- */
263 struct sbni_softc *sc;
267 sc = (struct sbni_softc *)xsc;
268 ifp = &sc->arpcom.ac_if;
270 /* address not known */
271 if (TAILQ_EMPTY(&ifp->if_addrhead))
275 * kludge to avoid multiple initialization when more than once
276 * protocols configured
278 if (ifp->if_flags & IFF_RUNNING)
284 callout_reset(&sc->sbni_stat_timer,hz / SBNI_HZ, sbni_timeout, sc);
286 ifp->if_flags |= IFF_RUNNING;
287 ifp->if_flags &= ~IFF_OACTIVE;
289 /* attempt to start output */
296 sbni_start(struct ifnet *ifp)
298 struct sbni_softc *sc = ifp->if_softc;
299 if (sc->tx_frameno == 0)
305 sbni_stop(struct sbni_softc *sc)
307 sbni_outb(sc, CSR0, 0);
311 m_freem(sc->rx_buf_p);
315 callout_stop(&sc->sbni_stat_timer);
318 /* -------------------------------------------------------------------------- */
320 /* interrupt handler */
323 * SBNI12D-10, -11/ISA boards within "common interrupt" mode could not
324 * be looked as two independent single-channel devices. Every channel seems
325 * as Ethernet interface but interrupt handler must be common. Really, first
326 * channel ("master") driver only registers the handler. In it's struct softc
327 * it has got pointer to "slave" channel's struct softc and handles that's
329 * softc of successfully attached ISA SBNI boards is linked to list.
330 * While next board driver is initialized, it scans this list. If one
331 * has found softc with same irq and ioaddr different by 4 then it assumes
332 * this board to be "master".
338 struct sbni_softc *sc;
341 sc = (struct sbni_softc *)arg;
345 if (sbni_inb(sc, CSR0) & (RC_RDY | TR_RDY)) {
349 if (sc->slave_sc && /* second channel present */
350 (sbni_inb(sc->slave_sc, CSR0) & (RC_RDY | TR_RDY))) {
351 handle_channel(sc->slave_sc);
359 handle_channel(struct sbni_softc *sc)
364 sbni_outb(sc, CSR0, (sbni_inb(sc, CSR0) & ~EN_INT) | TR_REQ);
366 sc->timer_ticks = CHANGE_LEVEL_START_TICKS;
368 csr0 = sbni_inb(sc, CSR0);
369 if ((csr0 & (RC_RDY | TR_RDY)) == 0)
372 req_ans = !(sc->state & FL_PREV_OK);
375 req_ans = recv_frame(sc);
378 * TR_RDY always equals 1 here because we have owned the marker,
379 * and we set TR_REQ when disabled interrupts
381 csr0 = sbni_inb(sc, CSR0);
382 if ((csr0 & TR_RDY) == 0 || (csr0 & RC_RDY) != 0)
383 printf("sbni: internal error!\n");
385 /* if state & FL_NEED_RESEND != 0 then tx_frameno != 0 */
386 if (req_ans || sc->tx_frameno != 0)
389 /* send the marker without any data */
390 sbni_outb(sc, CSR0, sbni_inb(sc, CSR0) & ~TR_REQ);
394 sbni_outb(sc, CSR0, sbni_inb(sc, CSR0) | EN_INT);
399 * Routine returns 1 if it need to acknoweledge received frame.
400 * Empty frame received without errors won't be acknoweledged.
404 recv_frame(struct sbni_softc *sc)
407 u_int framelen, frameno, ack;
408 u_int is_first, frame_ok;
411 if (check_fhdr(sc, &framelen, &frameno, &ack, &is_first, &crc)) {
412 frame_ok = framelen > 4 ?
413 upload_data(sc, framelen, frameno, is_first, crc) :
414 skip_tail(sc, framelen, crc);
416 interpret_ack(sc, ack);
420 sbni_outb(sc, CSR0, sbni_inb(sc, CSR0) ^ CT_ZER);
422 sc->state |= FL_PREV_OK;
424 sc->in_stats.all_rx_number++;
426 sc->state &= ~FL_PREV_OK;
428 sc->in_stats.all_rx_number++;
429 sc->in_stats.bad_rx_number++;
432 return (!frame_ok || framelen > 4);
437 send_frame(struct sbni_softc *sc)
443 if (sc->state & FL_NEED_RESEND) {
445 /* if frame was sended but not ACK'ed - resend it */
446 if (sc->trans_errors) {
448 if (sc->framelen != 0)
449 sc->in_stats.resend_tx_number++;
451 /* cannot xmit with many attempts */
456 sc->trans_errors = TR_ERROR_COUNT;
458 send_frame_header(sc, &crc);
459 sc->state |= FL_NEED_RESEND;
461 * FL_NEED_RESEND will be cleared after ACK, but if empty
462 * frame sended then in prepare_to_send next frame
467 download_data(sc, &crc);
468 sc->in_stats.all_tx_number++;
469 sc->state |= FL_WAIT_ACK;
472 sbni_outsb(sc, (u_char *)&crc, sizeof crc);
475 csr0 = sbni_inb(sc, CSR0);
476 sbni_outb(sc, CSR0, csr0 & ~TR_REQ);
478 if (sc->tx_frameno) {
479 /* next frame exists - request to send */
480 sbni_outb(sc, CSR0, csr0 | TR_REQ);
486 download_data(struct sbni_softc *sc, u_int32_t *crc_p)
490 u_int data_len, pos, slice;
492 data_p = NULL; /* initialized to avoid warn */
495 for (m = sc->tx_buf_p; m != NULL && pos < sc->pktlen; m = m->m_next) {
496 if (pos + m->m_len > sc->outpos) {
497 data_len = m->m_len - (sc->outpos - pos);
498 data_p = mtod(m, caddr_t) + (sc->outpos - pos);
511 slice = min(data_len, sc->framelen - pos);
512 sbni_outsb(sc, data_p, slice);
513 *crc_p = calc_crc32(*crc_p, data_p, slice);
516 if (data_len -= slice)
521 } while (m != NULL && m->m_len == 0);
525 data_p = mtod(m, caddr_t);
529 /* frame too short - zero padding */
531 pos = sc->framelen - pos;
533 sbni_outb(sc, DAT, 0);
534 *crc_p = CRC32(0, *crc_p);
538 } while (pos < sc->framelen);
543 upload_data(struct sbni_softc *sc, u_int framelen, u_int frameno,
544 u_int is_first, u_int32_t crc)
549 sc->wait_frameno = frameno;
553 if (sc->wait_frameno == frameno) {
555 if (sc->inppos + framelen <= ETHER_MAX_LEN) {
556 frame_ok = append_frame_to_pkt(sc, framelen, crc);
559 * if CRC is right but framelen incorrect then transmitter
560 * error was occured... drop entire packet
562 } else if ((frame_ok = skip_tail(sc, framelen, crc)) != 0) {
563 sc->wait_frameno = 0;
565 sc->arpcom.ac_if.if_ierrors++;
566 /* now skip all frames until is_first != 0 */
569 frame_ok = skip_tail(sc, framelen, crc);
571 if (is_first && !frame_ok) {
573 * Frame has been violated, but we have stored
574 * is_first already... Drop entire packet.
576 sc->wait_frameno = 0;
577 sc->arpcom.ac_if.if_ierrors++;
584 static __inline void send_complete(struct sbni_softc *);
587 send_complete(struct sbni_softc *sc)
589 m_freem(sc->tx_buf_p);
591 sc->arpcom.ac_if.if_opackets++;
596 interpret_ack(struct sbni_softc *sc, u_int ack)
598 if (ack == FRAME_SENT_OK) {
599 sc->state &= ~FL_NEED_RESEND;
601 if (sc->state & FL_WAIT_ACK) {
602 sc->outpos += sc->framelen;
604 if (--sc->tx_frameno) {
606 sc->maxframe, sc->pktlen - sc->outpos);
614 sc->state &= ~FL_WAIT_ACK;
619 * Glue received frame with previous fragments of packet.
620 * Indicate packet when last frame would be accepted.
624 append_frame_to_pkt(struct sbni_softc *sc, u_int framelen, u_int32_t crc)
628 if (sc->inppos + framelen > ETHER_MAX_LEN)
631 if (!sc->rx_buf_p && !get_rx_buf(sc))
634 p = sc->rx_buf_p->m_data + sc->inppos;
635 sbni_insb(sc, p, framelen);
636 if (calc_crc32(crc, p, framelen) != CRC32_REMAINDER)
639 sc->inppos += framelen - 4;
640 if (--sc->wait_frameno == 0) { /* last frame received */
642 sc->arpcom.ac_if.if_ipackets++;
650 * Prepare to start output on adapter. Current priority must be set to splimp
651 * before this routine is called.
652 * Transmitter will be actually activated when marker has been accepted.
656 prepare_to_send(struct sbni_softc *sc)
661 /* sc->tx_buf_p == NULL here! */
663 printf("sbni: memory leak!\n");
666 sc->state &= ~(FL_WAIT_ACK | FL_NEED_RESEND);
669 sc->tx_buf_p = ifq_dequeue(&sc->arpcom.ac_if.if_snd);
670 if (sc->tx_buf_p == NULL) {
671 /* nothing to transmit... */
675 sc->arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
679 for (len = 0, m = sc->tx_buf_p; m; m = m->m_next)
684 m_freem(sc->tx_buf_p);
687 if (len < SBNI_MIN_LEN)
691 sc->tx_frameno = (len + sc->maxframe - 1) / sc->maxframe;
692 sc->framelen = min(len, sc->maxframe);
694 sbni_outb(sc, CSR0, sbni_inb(sc, CSR0) | TR_REQ);
695 sc->arpcom.ac_if.if_flags |= IFF_OACTIVE;
696 BPF_MTAP(&sc->arpcom.ac_if, sc->tx_buf_p);
701 drop_xmit_queue(struct sbni_softc *sc)
704 m_freem(sc->tx_buf_p);
706 sc->arpcom.ac_if.if_oerrors++;
709 ifq_purge(&sc->arpcom.ac_if.if_snd);
714 sc->state &= ~(FL_WAIT_ACK | FL_NEED_RESEND);
715 sc->arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
720 send_frame_header(struct sbni_softc *sc, u_int32_t *crc_p)
727 len_field = sc->framelen + 6; /* CRC + frameno + reserved */
729 if (sc->state & FL_NEED_RESEND)
730 len_field |= FRAME_RETRY; /* non-first attempt... */
733 len_field |= FRAME_FIRST;
735 len_field |= (sc->state & FL_PREV_OK) ? FRAME_SENT_OK : FRAME_SENT_BAD;
736 sbni_outb(sc, DAT, SBNI_SIG);
738 value = (u_char)len_field;
739 sbni_outb(sc, DAT, value);
740 crc = CRC32(value, crc);
741 value = (u_char)(len_field >> 8);
742 sbni_outb(sc, DAT, value);
743 crc = CRC32(value, crc);
745 sbni_outb(sc, DAT, sc->tx_frameno);
746 crc = CRC32(sc->tx_frameno, crc);
747 sbni_outb(sc, DAT, 0);
754 * if frame tail not needed (incorrect number or received twice),
755 * it won't store, but CRC will be calculated
759 skip_tail(struct sbni_softc *sc, u_int tail_len, u_int32_t crc)
762 crc = CRC32(sbni_inb(sc, DAT), crc);
764 return (crc == CRC32_REMAINDER);
769 check_fhdr(struct sbni_softc *sc, u_int *framelen, u_int *frameno,
770 u_int *ack, u_int *is_first, u_int32_t *crc_p)
776 if (sbni_inb(sc, DAT) != SBNI_SIG)
779 value = sbni_inb(sc, DAT);
780 *framelen = (u_int)value;
781 crc = CRC32(value, crc);
782 value = sbni_inb(sc, DAT);
783 *framelen |= ((u_int)value) << 8;
784 crc = CRC32(value, crc);
786 *ack = *framelen & FRAME_ACK_MASK;
787 *is_first = (*framelen & FRAME_FIRST) != 0;
789 if ((*framelen &= FRAME_LEN_MASK) < 6 || *framelen > SBNI_MAX_FRAME - 3)
792 value = sbni_inb(sc, DAT);
793 *frameno = (u_int)value;
794 crc = CRC32(value, crc);
796 crc = CRC32(sbni_inb(sc, DAT), crc); /* reserved byte */
805 get_rx_buf(struct sbni_softc *sc)
809 MGETHDR(m, MB_DONTWAIT, MT_DATA);
811 printf("%s: cannot allocate header mbuf\n",
812 sc->arpcom.ac_if.if_xname);
817 * We always put the received packet in a single buffer -
818 * either with just an mbuf header or in a cluster attached
819 * to the header. The +2 is to compensate for the alignment
822 if (ETHER_MAX_LEN + 2 > MHLEN) {
823 /* Attach an mbuf cluster */
824 MCLGET(m, MB_DONTWAIT);
825 if ((m->m_flags & M_EXT) == 0) {
830 m->m_pkthdr.len = m->m_len = ETHER_MAX_LEN + 2;
833 * The +2 is to longword align the start of the real packet.
834 * (sizeof ether_header == 14)
835 * This is important for NFS.
844 indicate_pkt(struct sbni_softc *sc)
846 struct ifnet *ifp = &sc->arpcom.ac_if;
850 m->m_pkthdr.rcvif = ifp;
851 m->m_pkthdr.len = m->m_len = sc->inppos;
853 (*ifp->if_input)(ifp, m);
857 /* -------------------------------------------------------------------------- */
860 * Routine checks periodically wire activity and regenerates marker if
861 * connect was inactive for a long time.
865 sbni_timeout(void *xsc)
867 struct sbni_softc *sc;
871 sc = (struct sbni_softc *)xsc;
874 csr0 = sbni_inb(sc, CSR0);
877 if (sc->timer_ticks) {
878 if (csr0 & (RC_RDY | BU_EMP))
879 /* receiving not active */
882 sc->in_stats.timeout_number++;
884 timeout_change_level(sc);
886 sbni_outb(sc, CSR1, *(u_char *)&sc->csr1 | PR_RES);
887 csr0 = sbni_inb(sc, CSR0);
891 sbni_outb(sc, CSR0, csr0 | RC_CHK);
892 callout_reset(&sc->sbni_stat_timer, hz / SBNI_HZ, sbni_timeout, sc);
896 /* -------------------------------------------------------------------------- */
899 card_start(struct sbni_softc *sc)
901 sc->timer_ticks = CHANGE_LEVEL_START_TICKS;
902 sc->state &= ~(FL_WAIT_ACK | FL_NEED_RESEND);
903 sc->state |= FL_PREV_OK;
906 sc->wait_frameno = 0;
908 sbni_outb(sc, CSR1, *(u_char *)&sc->csr1 | PR_RES);
909 sbni_outb(sc, CSR0, EN_INT);
912 /* -------------------------------------------------------------------------- */
915 * Device timeout/watchdog routine. Entered if the device neglects to
916 * generate an interrupt after a transmit has been started on it.
920 sbni_watchdog(struct ifnet *ifp)
922 log(LOG_ERR, "%s: device timeout\n", ifp->if_xname);
927 static u_char rxl_tab[] = {
928 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x08,
929 0x0a, 0x0c, 0x0f, 0x16, 0x18, 0x1a, 0x1c, 0x1f
932 #define SIZE_OF_TIMEOUT_RXL_TAB 4
933 static u_char timeout_rxl_tab[] = {
934 0x03, 0x05, 0x08, 0x0b
938 set_initial_values(struct sbni_softc *sc, struct sbni_flags flags)
940 if (flags.fixed_rxl) {
941 sc->delta_rxl = 0; /* disable receive level autodetection */
942 sc->cur_rxl_index = flags.rxl;
944 sc->delta_rxl = DEF_RXL_DELTA;
945 sc->cur_rxl_index = DEF_RXL;
948 sc->csr1.rate = flags.fixed_rate ? flags.rate : DEFAULT_RATE;
949 sc->csr1.rxl = rxl_tab[sc->cur_rxl_index];
950 sc->maxframe = DEFAULT_FRAME_LEN;
953 * generate Ethernet address (0x00ff01xxxxxx)
955 *(u_int16_t *) sc->arpcom.ac_enaddr = htons(0x00ff);
956 if (flags.mac_addr) {
957 *(u_int32_t *) (sc->arpcom.ac_enaddr + 2) =
958 htonl(flags.mac_addr | 0x01000000);
960 *(u_char *) (sc->arpcom.ac_enaddr + 2) = 0x01;
961 read_random_unlimited(sc->arpcom.ac_enaddr + 3, 3);
966 #ifdef SBNI_DUAL_COMPOUND
969 connect_to_master(struct sbni_softc *sc)
971 struct sbni_softc *p, *p_prev;
973 for (p = sbni_headlist, p_prev = NULL; p; p_prev = p, p = p->link) {
974 if (rman_get_start(p->io_res) == rman_get_start(sc->io_res) + 4 ||
975 rman_get_start(p->io_res) == rman_get_start(sc->io_res) - 4) {
978 p_prev->link = p->link;
980 sbni_headlist = p->link;
988 #endif /* SBNI_DUAL_COMPOUND */
991 /* Receive level auto-selection */
994 change_level(struct sbni_softc *sc)
996 if (sc->delta_rxl == 0) /* do not auto-negotiate RxL */
999 if (sc->cur_rxl_index == 0)
1001 else if (sc->cur_rxl_index == 15)
1003 else if (sc->cur_rxl_rcvd < sc->prev_rxl_rcvd)
1004 sc->delta_rxl = -sc->delta_rxl;
1006 sc->csr1.rxl = rxl_tab[sc->cur_rxl_index += sc->delta_rxl];
1007 sbni_inb(sc, CSR0); /* it needed for PCI cards */
1008 sbni_outb(sc, CSR1, *(u_char *)&sc->csr1);
1010 sc->prev_rxl_rcvd = sc->cur_rxl_rcvd;
1011 sc->cur_rxl_rcvd = 0;
1016 timeout_change_level(struct sbni_softc *sc)
1018 sc->cur_rxl_index = timeout_rxl_tab[sc->timeout_rxl];
1019 if (++sc->timeout_rxl >= 4)
1020 sc->timeout_rxl = 0;
1022 sc->csr1.rxl = rxl_tab[sc->cur_rxl_index];
1024 sbni_outb(sc, CSR1, *(u_char *)&sc->csr1);
1026 sc->prev_rxl_rcvd = sc->cur_rxl_rcvd;
1027 sc->cur_rxl_rcvd = 0;
1030 /* -------------------------------------------------------------------------- */
1033 * Process an ioctl request. This code needs some work - it looks
1038 sbni_ioctl(struct ifnet *ifp, u_long command, caddr_t data, struct ucred *cr)
1040 struct sbni_softc *sc;
1042 struct sbni_in_stats *in_stats;
1043 struct sbni_flags flags;
1047 ifr = (struct ifreq *)data;
1055 * If the interface is marked up and stopped, then start it.
1056 * If it is marked down and running, then stop it.
1058 if (ifp->if_flags & IFF_UP) {
1059 if (!(ifp->if_flags & IFF_RUNNING))
1062 if (ifp->if_flags & IFF_RUNNING) {
1064 ifp->if_flags &= ~IFF_RUNNING;
1072 * Multicast list has changed; set the hardware filter
1077 error = EAFNOSUPPORT; */
1081 if (ifr->ifr_mtu > ETHERMTU)
1084 ifp->if_mtu = ifr->ifr_mtu;
1088 * SBNI specific ioctl
1090 case SIOCGHWFLAGS: /* get flags */
1091 bcopy((caddr_t) sc->arpcom.ac_enaddr+3, (caddr_t) &flags, 3);
1092 flags.rxl = sc->cur_rxl_index;
1093 flags.rate = sc->csr1.rate;
1094 flags.fixed_rxl = (sc->delta_rxl == 0);
1095 flags.fixed_rate = 1;
1096 ifr->ifr_data = *(caddr_t*) &flags;
1100 in_stats = (struct sbni_in_stats *)ifr->ifr_data;
1101 bcopy((void *)(&(sc->in_stats)), (void *)in_stats,
1102 sizeof(struct sbni_in_stats));
1105 case SIOCSHWFLAGS: /* set flags */
1107 error = suser_cred(cr, NULL_CRED_OKAY);
1108 /* NOTE: returns EPERM if no proc */
1111 flags = *(struct sbni_flags*)&ifr->ifr_data;
1112 if (flags.fixed_rxl) {
1114 sc->cur_rxl_index = flags.rxl;
1116 sc->delta_rxl = DEF_RXL_DELTA;
1117 sc->cur_rxl_index = DEF_RXL;
1119 sc->csr1.rxl = rxl_tab[sc->cur_rxl_index];
1120 sc->csr1.rate = flags.fixed_rate ? flags.rate : DEFAULT_RATE;
1122 bcopy((caddr_t) &flags,
1123 (caddr_t) sc->arpcom.ac_enaddr+3, 3);
1125 /* Don't be afraid... */
1126 sbni_outb(sc, CSR1, *(char*)(&sc->csr1) | PR_RES);
1130 if (!(error = suser_cred(cr, NULL_CRED_OKAY))) /* root only */
1131 bzero(&sc->in_stats, sizeof(struct sbni_in_stats));
1135 error = ether_ioctl(ifp, command, data);
1143 /* -------------------------------------------------------------------------- */
1148 calc_crc32(u_int32_t crc, caddr_t p, u_int len)
1154 "xorl %%ebx, %%ebx\n"
1157 "movl $crc32tab, %%edi\n"
1164 "movl (%%esi), %%edx\n"
1168 "xorl (%%edi,%%ebx,4), %%eax\n"
1174 "xorl (%%edi,%%ebx,4), %%eax\n"
1180 "xorl (%%edi,%%ebx,4), %%eax\n"
1186 "xorl (%%edi,%%ebx,4), %%eax\n"
1198 "xorb (%%esi), %%bl\n"
1199 "xorl (%%edi,%%ebx,4), %%eax\n"
1206 "xorb 1(%%esi), %%bl\n"
1207 "xorl (%%edi,%%ebx,4), %%eax\n"
1214 "xorb 2(%%esi), %%bl\n"
1215 "xorl (%%edi,%%ebx,4), %%eax\n"
1218 : "a" (_crc), "g" (p), "g" (len)
1219 : "bx", "cx", "dx", "si", "di"
1228 calc_crc32(u_int32_t crc, caddr_t p, u_int len)
1231 crc = CRC32(*p++, crc);
1236 #endif /* ASM_CRC */
1239 static u_int32_t crc32tab[] __attribute__ ((aligned(8))) = {
1240 0xD202EF8D, 0xA505DF1B, 0x3C0C8EA1, 0x4B0BBE37,
1241 0xD56F2B94, 0xA2681B02, 0x3B614AB8, 0x4C667A2E,
1242 0xDCD967BF, 0xABDE5729, 0x32D70693, 0x45D03605,
1243 0xDBB4A3A6, 0xACB39330, 0x35BAC28A, 0x42BDF21C,
1244 0xCFB5FFE9, 0xB8B2CF7F, 0x21BB9EC5, 0x56BCAE53,
1245 0xC8D83BF0, 0xBFDF0B66, 0x26D65ADC, 0x51D16A4A,
1246 0xC16E77DB, 0xB669474D, 0x2F6016F7, 0x58672661,
1247 0xC603B3C2, 0xB1048354, 0x280DD2EE, 0x5F0AE278,
1248 0xE96CCF45, 0x9E6BFFD3, 0x0762AE69, 0x70659EFF,
1249 0xEE010B5C, 0x99063BCA, 0x000F6A70, 0x77085AE6,
1250 0xE7B74777, 0x90B077E1, 0x09B9265B, 0x7EBE16CD,
1251 0xE0DA836E, 0x97DDB3F8, 0x0ED4E242, 0x79D3D2D4,
1252 0xF4DBDF21, 0x83DCEFB7, 0x1AD5BE0D, 0x6DD28E9B,
1253 0xF3B61B38, 0x84B12BAE, 0x1DB87A14, 0x6ABF4A82,
1254 0xFA005713, 0x8D076785, 0x140E363F, 0x630906A9,
1255 0xFD6D930A, 0x8A6AA39C, 0x1363F226, 0x6464C2B0,
1256 0xA4DEAE1D, 0xD3D99E8B, 0x4AD0CF31, 0x3DD7FFA7,
1257 0xA3B36A04, 0xD4B45A92, 0x4DBD0B28, 0x3ABA3BBE,
1258 0xAA05262F, 0xDD0216B9, 0x440B4703, 0x330C7795,
1259 0xAD68E236, 0xDA6FD2A0, 0x4366831A, 0x3461B38C,
1260 0xB969BE79, 0xCE6E8EEF, 0x5767DF55, 0x2060EFC3,
1261 0xBE047A60, 0xC9034AF6, 0x500A1B4C, 0x270D2BDA,
1262 0xB7B2364B, 0xC0B506DD, 0x59BC5767, 0x2EBB67F1,
1263 0xB0DFF252, 0xC7D8C2C4, 0x5ED1937E, 0x29D6A3E8,
1264 0x9FB08ED5, 0xE8B7BE43, 0x71BEEFF9, 0x06B9DF6F,
1265 0x98DD4ACC, 0xEFDA7A5A, 0x76D32BE0, 0x01D41B76,
1266 0x916B06E7, 0xE66C3671, 0x7F6567CB, 0x0862575D,
1267 0x9606C2FE, 0xE101F268, 0x7808A3D2, 0x0F0F9344,
1268 0x82079EB1, 0xF500AE27, 0x6C09FF9D, 0x1B0ECF0B,
1269 0x856A5AA8, 0xF26D6A3E, 0x6B643B84, 0x1C630B12,
1270 0x8CDC1683, 0xFBDB2615, 0x62D277AF, 0x15D54739,
1271 0x8BB1D29A, 0xFCB6E20C, 0x65BFB3B6, 0x12B88320,
1272 0x3FBA6CAD, 0x48BD5C3B, 0xD1B40D81, 0xA6B33D17,
1273 0x38D7A8B4, 0x4FD09822, 0xD6D9C998, 0xA1DEF90E,
1274 0x3161E49F, 0x4666D409, 0xDF6F85B3, 0xA868B525,
1275 0x360C2086, 0x410B1010, 0xD80241AA, 0xAF05713C,
1276 0x220D7CC9, 0x550A4C5F, 0xCC031DE5, 0xBB042D73,
1277 0x2560B8D0, 0x52678846, 0xCB6ED9FC, 0xBC69E96A,
1278 0x2CD6F4FB, 0x5BD1C46D, 0xC2D895D7, 0xB5DFA541,
1279 0x2BBB30E2, 0x5CBC0074, 0xC5B551CE, 0xB2B26158,
1280 0x04D44C65, 0x73D37CF3, 0xEADA2D49, 0x9DDD1DDF,
1281 0x03B9887C, 0x74BEB8EA, 0xEDB7E950, 0x9AB0D9C6,
1282 0x0A0FC457, 0x7D08F4C1, 0xE401A57B, 0x930695ED,
1283 0x0D62004E, 0x7A6530D8, 0xE36C6162, 0x946B51F4,
1284 0x19635C01, 0x6E646C97, 0xF76D3D2D, 0x806A0DBB,
1285 0x1E0E9818, 0x6909A88E, 0xF000F934, 0x8707C9A2,
1286 0x17B8D433, 0x60BFE4A5, 0xF9B6B51F, 0x8EB18589,
1287 0x10D5102A, 0x67D220BC, 0xFEDB7106, 0x89DC4190,
1288 0x49662D3D, 0x3E611DAB, 0xA7684C11, 0xD06F7C87,
1289 0x4E0BE924, 0x390CD9B2, 0xA0058808, 0xD702B89E,
1290 0x47BDA50F, 0x30BA9599, 0xA9B3C423, 0xDEB4F4B5,
1291 0x40D06116, 0x37D75180, 0xAEDE003A, 0xD9D930AC,
1292 0x54D13D59, 0x23D60DCF, 0xBADF5C75, 0xCDD86CE3,
1293 0x53BCF940, 0x24BBC9D6, 0xBDB2986C, 0xCAB5A8FA,
1294 0x5A0AB56B, 0x2D0D85FD, 0xB404D447, 0xC303E4D1,
1295 0x5D677172, 0x2A6041E4, 0xB369105E, 0xC46E20C8,
1296 0x72080DF5, 0x050F3D63, 0x9C066CD9, 0xEB015C4F,
1297 0x7565C9EC, 0x0262F97A, 0x9B6BA8C0, 0xEC6C9856,
1298 0x7CD385C7, 0x0BD4B551, 0x92DDE4EB, 0xE5DAD47D,
1299 0x7BBE41DE, 0x0CB97148, 0x95B020F2, 0xE2B71064,
1300 0x6FBF1D91, 0x18B82D07, 0x81B17CBD, 0xF6B64C2B,
1301 0x68D2D988, 0x1FD5E91E, 0x86DCB8A4, 0xF1DB8832,
1302 0x616495A3, 0x1663A535, 0x8F6AF48F, 0xF86DC419,
1303 0x660951BA, 0x110E612C, 0x88073096, 0xFF000000