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 $
31 * Device driver for Granch SBNI12 leased line adapters
33 * Revision 2.0.0 1997/08/06
34 * Initial revision by Alexey Zverev
36 * Revision 2.0.1 1997/08/11
37 * Additional internal statistics support (tx statistics)
39 * Revision 2.0.2 1997/11/05
40 * if_bpf bug has been fixed
42 * Revision 2.0.3 1998/12/20
43 * Memory leakage has been eliminated in
44 * the sbni_st and sbni_timeout routines.
46 * Revision 3.0 2000/08/10 by Yaroslav Polyakov
47 * Support for PCI cards. 4.1 modification.
49 * Revision 3.1 2000/09/12
50 * Removed extra #defines around bpf functions
52 * Revision 4.0 2000/11/23 by Denis Timofeev
53 * Completely redesigned the buffer management
55 * Revision 4.1 2001/01/21
56 * Support for PCI Dual cards and new SBNI12D-10, -11 Dual/ISA cards
58 * Written with reference to NE2000 driver developed by David Greenman.
62 #include <sys/param.h>
63 #include <sys/systm.h>
64 #include <sys/socket.h>
65 #include <sys/sockio.h>
67 #include <sys/kernel.h>
69 #include <sys/callout.h>
70 #include <sys/syslog.h>
71 #include <sys/random.h>
73 #include <machine/bus.h>
75 #include <machine/resource.h>
78 #include <net/ethernet.h>
79 #include <net/if_arp.h>
82 #include <dev/sbni/if_sbnireg.h>
83 #include <dev/sbni/if_sbnivar.h>
87 static void sbni_init(void *);
88 static void sbni_start(struct ifnet *);
89 static int sbni_ioctl(struct ifnet *, u_long, caddr_t);
90 static void sbni_watchdog(struct ifnet *);
91 static void sbni_stop(struct sbni_softc *);
92 static void handle_channel(struct sbni_softc *);
94 static void card_start(struct sbni_softc *);
95 static int recv_frame(struct sbni_softc *);
96 static void send_frame(struct sbni_softc *);
97 static int upload_data(struct sbni_softc *, u_int, u_int, u_int, u_int32_t);
98 static int skip_tail(struct sbni_softc *, u_int, u_int32_t);
99 static void interpret_ack(struct sbni_softc *, u_int);
100 static void download_data(struct sbni_softc *, u_int32_t *);
101 static void prepare_to_send(struct sbni_softc *);
102 static void drop_xmit_queue(struct sbni_softc *);
103 static int get_rx_buf(struct sbni_softc *);
104 static void indicate_pkt(struct sbni_softc *);
105 static void change_level(struct sbni_softc *);
106 static int check_fhdr(struct sbni_softc *, u_int *, u_int *,
107 u_int *, u_int *, u_int32_t *);
108 static int append_frame_to_pkt(struct sbni_softc *, u_int, u_int32_t);
109 static void timeout_change_level(struct sbni_softc *);
110 static void send_frame_header(struct sbni_softc *, u_int32_t *);
111 static void set_initial_values(struct sbni_softc *, struct sbni_flags);
113 static u_int32_t calc_crc32(u_int32_t, caddr_t, u_int);
114 static timeout_t sbni_timeout;
116 static __inline u_char sbni_inb(struct sbni_softc *, enum sbni_reg);
117 static __inline void sbni_outb(struct sbni_softc *, enum sbni_reg, u_char);
118 static __inline void sbni_insb(struct sbni_softc *, u_char *, u_int);
119 static __inline void sbni_outsb(struct sbni_softc *, u_char *, u_int);
121 static u_int32_t crc32tab[];
123 #ifdef SBNI_DUAL_COMPOUND
124 struct sbni_softc *sbni_headlist;
127 u_int32_t next_sbni_unit;
129 /* -------------------------------------------------------------------------- */
131 static __inline u_char
132 sbni_inb(struct sbni_softc *sc, enum sbni_reg reg)
134 return bus_space_read_1(
135 rman_get_bustag(sc->io_res),
136 rman_get_bushandle(sc->io_res),
141 sbni_outb(struct sbni_softc *sc, enum sbni_reg reg, u_char value)
144 rman_get_bustag(sc->io_res),
145 rman_get_bushandle(sc->io_res),
146 sc->io_off + reg, value);
150 sbni_insb(struct sbni_softc *sc, u_char *to, u_int len)
152 bus_space_read_multi_1(
153 rman_get_bustag(sc->io_res),
154 rman_get_bushandle(sc->io_res),
155 sc->io_off + DAT, to, len);
159 sbni_outsb(struct sbni_softc *sc, u_char *from, u_int len)
161 bus_space_write_multi_1(
162 rman_get_bustag(sc->io_res),
163 rman_get_bushandle(sc->io_res),
164 sc->io_off + DAT, from, len);
169 Valid combinations in CSR0 (for probing):
171 VALID_DECODER 0000,0011,1011,1010
176 TR_RDY TR_REQ ; 3 ; +
178 BU_EMP TR_REQ ; 5 ; +
179 BU_EMP TR_RDY ; 6 ; -
180 BU_EMP TR_RDY TR_REQ ; 7 ; +
182 RC_RDY TR_REQ ; 9 ; +
183 RC_RDY TR_RDY ; 10 ; -
184 RC_RDY TR_RDY TR_REQ ; 11 ; -
185 RC_RDY BU_EMP ; 12 ; -
186 RC_RDY BU_EMP TR_REQ ; 13 ; -
187 RC_RDY BU_EMP TR_RDY ; 14 ; -
188 RC_RDY BU_EMP TR_RDY TR_REQ ; 15 ; -
191 #define VALID_DECODER (2 + 8 + 0x10 + 0x20 + 0x80 + 0x100 + 0x200)
195 sbni_probe(struct sbni_softc *sc)
199 csr0 = sbni_inb(sc, CSR0);
200 if (csr0 != 0xff && csr0 != 0x00) {
205 if (VALID_DECODER & (1 << (csr0 >> 4)))
214 * Install interface into kernel networking data structures
217 sbni_attach(struct sbni_softc *sc, int unit, struct sbni_flags flags)
222 ifp = &sc->arpcom.ac_if;
223 sbni_outb(sc, CSR0, 0);
224 set_initial_values(sc, flags);
226 callout_handle_init(&sc->wch);
228 /* Initialize ifnet structure */
231 ifp->if_name = "sbni";
232 ifp->if_init = sbni_init;
233 ifp->if_start = sbni_start;
234 ifp->if_output = ether_output;
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, ETHER_BPF_SUPPORTED);
247 /* device attach does transition from UNCONFIGURED to IDLE state */
249 printf("%s%d: speed %ld, address %6D, rxl ", ifp->if_name,
250 ifp->if_unit, ifp->if_baudrate, sc->arpcom.ac_enaddr, ":");
254 printf("%d (fixed)\n", sc->cur_rxl_index);
257 /* -------------------------------------------------------------------------- */
262 struct sbni_softc *sc;
266 sc = (struct sbni_softc *)xsc;
267 ifp = &sc->arpcom.ac_if;
269 /* address not known */
270 if (TAILQ_EMPTY(&ifp->if_addrhead))
274 * kludge to avoid multiple initialization when more than once
275 * protocols configured
277 if (ifp->if_flags & IFF_RUNNING)
283 sc->wch = timeout(sbni_timeout, sc, hz/SBNI_HZ);
285 ifp->if_flags |= IFF_RUNNING;
286 ifp->if_flags &= ~IFF_OACTIVE;
288 /* attempt to start output */
295 sbni_start(struct ifnet *ifp)
297 struct sbni_softc *sc = ifp->if_softc;
298 if (sc->tx_frameno == 0)
304 sbni_stop(struct sbni_softc *sc)
306 sbni_outb(sc, CSR0, 0);
310 m_freem(sc->rx_buf_p);
314 untimeout(sbni_timeout, sc, sc->wch);
315 sc->wch.callout = NULL;
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 IF_DEQUEUE(&sc->arpcom.ac_if.if_snd, sc->tx_buf_p);
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 if (sc->arpcom.ac_if.if_bpf)
697 bpf_mtap(&sc->arpcom.ac_if, sc->tx_buf_p);
702 drop_xmit_queue(struct sbni_softc *sc)
707 m_freem(sc->tx_buf_p);
709 sc->arpcom.ac_if.if_oerrors++;
713 IF_DEQUEUE(&sc->arpcom.ac_if.if_snd, m);
717 sc->arpcom.ac_if.if_oerrors++;
723 sc->state &= ~(FL_WAIT_ACK | FL_NEED_RESEND);
724 sc->arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
729 send_frame_header(struct sbni_softc *sc, u_int32_t *crc_p)
736 len_field = sc->framelen + 6; /* CRC + frameno + reserved */
738 if (sc->state & FL_NEED_RESEND)
739 len_field |= FRAME_RETRY; /* non-first attempt... */
742 len_field |= FRAME_FIRST;
744 len_field |= (sc->state & FL_PREV_OK) ? FRAME_SENT_OK : FRAME_SENT_BAD;
745 sbni_outb(sc, DAT, SBNI_SIG);
747 value = (u_char)len_field;
748 sbni_outb(sc, DAT, value);
749 crc = CRC32(value, crc);
750 value = (u_char)(len_field >> 8);
751 sbni_outb(sc, DAT, value);
752 crc = CRC32(value, crc);
754 sbni_outb(sc, DAT, sc->tx_frameno);
755 crc = CRC32(sc->tx_frameno, crc);
756 sbni_outb(sc, DAT, 0);
763 * if frame tail not needed (incorrect number or received twice),
764 * it won't store, but CRC will be calculated
768 skip_tail(struct sbni_softc *sc, u_int tail_len, u_int32_t crc)
771 crc = CRC32(sbni_inb(sc, DAT), crc);
773 return (crc == CRC32_REMAINDER);
778 check_fhdr(struct sbni_softc *sc, u_int *framelen, u_int *frameno,
779 u_int *ack, u_int *is_first, u_int32_t *crc_p)
785 if (sbni_inb(sc, DAT) != SBNI_SIG)
788 value = sbni_inb(sc, DAT);
789 *framelen = (u_int)value;
790 crc = CRC32(value, crc);
791 value = sbni_inb(sc, DAT);
792 *framelen |= ((u_int)value) << 8;
793 crc = CRC32(value, crc);
795 *ack = *framelen & FRAME_ACK_MASK;
796 *is_first = (*framelen & FRAME_FIRST) != 0;
798 if ((*framelen &= FRAME_LEN_MASK) < 6 || *framelen > SBNI_MAX_FRAME - 3)
801 value = sbni_inb(sc, DAT);
802 *frameno = (u_int)value;
803 crc = CRC32(value, crc);
805 crc = CRC32(sbni_inb(sc, DAT), crc); /* reserved byte */
814 get_rx_buf(struct sbni_softc *sc)
818 MGETHDR(m, M_DONTWAIT, MT_DATA);
820 printf("sbni%d: cannot allocate header mbuf\n",
821 sc->arpcom.ac_if.if_unit);
826 * We always put the received packet in a single buffer -
827 * either with just an mbuf header or in a cluster attached
828 * to the header. The +2 is to compensate for the alignment
831 if (ETHER_MAX_LEN + 2 > MHLEN) {
832 /* Attach an mbuf cluster */
833 MCLGET(m, M_DONTWAIT);
834 if ((m->m_flags & M_EXT) == 0) {
839 m->m_pkthdr.len = m->m_len = ETHER_MAX_LEN + 2;
842 * The +2 is to longword align the start of the real packet.
843 * (sizeof ether_header == 14)
844 * This is important for NFS.
853 indicate_pkt(struct sbni_softc *sc)
856 struct ether_header *eh;
859 m->m_pkthdr.rcvif = &sc->arpcom.ac_if;
860 m->m_pkthdr.len = m->m_len = sc->inppos;
861 eh = mtod(m, struct ether_header *);
863 /* Remove link layer address and indicate packet */
864 m_adj(m, sizeof(struct ether_header));
865 ether_input(&sc->arpcom.ac_if, eh, m);
869 /* -------------------------------------------------------------------------- */
872 * Routine checks periodically wire activity and regenerates marker if
873 * connect was inactive for a long time.
877 sbni_timeout(void *xsc)
879 struct sbni_softc *sc;
883 sc = (struct sbni_softc *)xsc;
886 csr0 = sbni_inb(sc, CSR0);
889 if (sc->timer_ticks) {
890 if (csr0 & (RC_RDY | BU_EMP))
891 /* receiving not active */
894 sc->in_stats.timeout_number++;
896 timeout_change_level(sc);
898 sbni_outb(sc, CSR1, *(u_char *)&sc->csr1 | PR_RES);
899 csr0 = sbni_inb(sc, CSR0);
903 sbni_outb(sc, CSR0, csr0 | RC_CHK);
904 sc->wch = timeout(sbni_timeout, sc, hz/SBNI_HZ);
908 /* -------------------------------------------------------------------------- */
911 card_start(struct sbni_softc *sc)
913 sc->timer_ticks = CHANGE_LEVEL_START_TICKS;
914 sc->state &= ~(FL_WAIT_ACK | FL_NEED_RESEND);
915 sc->state |= FL_PREV_OK;
918 sc->wait_frameno = 0;
920 sbni_outb(sc, CSR1, *(u_char *)&sc->csr1 | PR_RES);
921 sbni_outb(sc, CSR0, EN_INT);
924 /* -------------------------------------------------------------------------- */
927 * Device timeout/watchdog routine. Entered if the device neglects to
928 * generate an interrupt after a transmit has been started on it.
932 sbni_watchdog(struct ifnet *ifp)
934 log(LOG_ERR, "sbni%d: device timeout\n", ifp->if_unit);
939 static u_char rxl_tab[] = {
940 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x08,
941 0x0a, 0x0c, 0x0f, 0x16, 0x18, 0x1a, 0x1c, 0x1f
944 #define SIZE_OF_TIMEOUT_RXL_TAB 4
945 static u_char timeout_rxl_tab[] = {
946 0x03, 0x05, 0x08, 0x0b
950 set_initial_values(struct sbni_softc *sc, struct sbni_flags flags)
952 if (flags.fixed_rxl) {
953 sc->delta_rxl = 0; /* disable receive level autodetection */
954 sc->cur_rxl_index = flags.rxl;
956 sc->delta_rxl = DEF_RXL_DELTA;
957 sc->cur_rxl_index = DEF_RXL;
960 sc->csr1.rate = flags.fixed_rate ? flags.rate : DEFAULT_RATE;
961 sc->csr1.rxl = rxl_tab[sc->cur_rxl_index];
962 sc->maxframe = DEFAULT_FRAME_LEN;
965 * generate Ethernet address (0x00ff01xxxxxx)
967 *(u_int16_t *) sc->arpcom.ac_enaddr = htons(0x00ff);
968 if (flags.mac_addr) {
969 *(u_int32_t *) (sc->arpcom.ac_enaddr + 2) =
970 htonl(flags.mac_addr | 0x01000000);
972 *(u_char *) (sc->arpcom.ac_enaddr + 2) = 0x01;
973 read_random_unlimited(sc->arpcom.ac_enaddr + 3, 3);
978 #ifdef SBNI_DUAL_COMPOUND
981 connect_to_master(struct sbni_softc *sc)
983 struct sbni_softc *p, *p_prev;
985 for (p = sbni_headlist, p_prev = NULL; p; p_prev = p, p = p->link) {
986 if (rman_get_start(p->io_res) == rman_get_start(sc->io_res) + 4 ||
987 rman_get_start(p->io_res) == rman_get_start(sc->io_res) - 4) {
990 p_prev->link = p->link;
992 sbni_headlist = p->link;
1000 #endif /* SBNI_DUAL_COMPOUND */
1003 /* Receive level auto-selection */
1006 change_level(struct sbni_softc *sc)
1008 if (sc->delta_rxl == 0) /* do not auto-negotiate RxL */
1011 if (sc->cur_rxl_index == 0)
1013 else if (sc->cur_rxl_index == 15)
1015 else if (sc->cur_rxl_rcvd < sc->prev_rxl_rcvd)
1016 sc->delta_rxl = -sc->delta_rxl;
1018 sc->csr1.rxl = rxl_tab[sc->cur_rxl_index += sc->delta_rxl];
1019 sbni_inb(sc, CSR0); /* it needed for PCI cards */
1020 sbni_outb(sc, CSR1, *(u_char *)&sc->csr1);
1022 sc->prev_rxl_rcvd = sc->cur_rxl_rcvd;
1023 sc->cur_rxl_rcvd = 0;
1028 timeout_change_level(struct sbni_softc *sc)
1030 sc->cur_rxl_index = timeout_rxl_tab[sc->timeout_rxl];
1031 if (++sc->timeout_rxl >= 4)
1032 sc->timeout_rxl = 0;
1034 sc->csr1.rxl = rxl_tab[sc->cur_rxl_index];
1036 sbni_outb(sc, CSR1, *(u_char *)&sc->csr1);
1038 sc->prev_rxl_rcvd = sc->cur_rxl_rcvd;
1039 sc->cur_rxl_rcvd = 0;
1042 /* -------------------------------------------------------------------------- */
1045 * Process an ioctl request. This code needs some work - it looks
1050 sbni_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
1052 struct sbni_softc *sc;
1055 struct sbni_in_stats *in_stats;
1056 struct sbni_flags flags;
1060 ifr = (struct ifreq *)data;
1069 ether_ioctl(ifp, command, data);
1074 * If the interface is marked up and stopped, then start it.
1075 * If it is marked down and running, then stop it.
1077 if (ifp->if_flags & IFF_UP) {
1078 if (!(ifp->if_flags & IFF_RUNNING))
1081 if (ifp->if_flags & IFF_RUNNING) {
1083 ifp->if_flags &= ~IFF_RUNNING;
1091 * Multicast list has changed; set the hardware filter
1096 error = EAFNOSUPPORT; */
1100 if (ifr->ifr_mtu > ETHERMTU)
1103 ifp->if_mtu = ifr->ifr_mtu;
1107 * SBNI specific ioctl
1109 case SIOCGHWFLAGS: /* get flags */
1110 bcopy((caddr_t) sc->arpcom.ac_enaddr+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 ifr->ifr_data = *(caddr_t*) &flags;
1119 in_stats = (struct sbni_in_stats *)ifr->ifr_data;
1120 bcopy((void *)(&(sc->in_stats)), (void *)in_stats,
1121 sizeof(struct sbni_in_stats));
1124 case SIOCSHWFLAGS: /* set flags */
1129 flags = *(struct sbni_flags*)&ifr->ifr_data;
1130 if (flags.fixed_rxl) {
1132 sc->cur_rxl_index = flags.rxl;
1134 sc->delta_rxl = DEF_RXL_DELTA;
1135 sc->cur_rxl_index = DEF_RXL;
1137 sc->csr1.rxl = rxl_tab[sc->cur_rxl_index];
1138 sc->csr1.rate = flags.fixed_rate ? flags.rate : DEFAULT_RATE;
1140 bcopy((caddr_t) &flags,
1141 (caddr_t) sc->arpcom.ac_enaddr+3, 3);
1143 /* Don't be afraid... */
1144 sbni_outb(sc, CSR1, *(char*)(&sc->csr1) | PR_RES);
1148 if (!(error = suser(p))) /* root only */
1149 bzero(&sc->in_stats, sizeof(struct sbni_in_stats));
1160 /* -------------------------------------------------------------------------- */
1165 calc_crc32(u_int32_t crc, caddr_t p, u_int len)
1167 register u_int32_t _crc __asm ("ax");
1171 "xorl %%ebx, %%ebx\n"
1174 "movl $crc32tab, %%edi\n"
1181 "movl (%%esi), %%edx\n"
1185 "xorl (%%edi,%%ebx,4), %%eax\n"
1191 "xorl (%%edi,%%ebx,4), %%eax\n"
1197 "xorl (%%edi,%%ebx,4), %%eax\n"
1203 "xorl (%%edi,%%ebx,4), %%eax\n"
1215 "xorb (%%esi), %%bl\n"
1216 "xorl (%%edi,%%ebx,4), %%eax\n"
1223 "xorb 1(%%esi), %%bl\n"
1224 "xorl (%%edi,%%ebx,4), %%eax\n"
1231 "xorb 2(%%esi), %%bl\n"
1232 "xorl (%%edi,%%ebx,4), %%eax\n"
1235 : "a" (_crc), "g" (p), "g" (len)
1236 : "ax", "bx", "cx", "dx", "si", "di"
1245 calc_crc32(u_int32_t crc, caddr_t p, u_int len)
1248 crc = CRC32(*p++, crc);
1253 #endif /* ASM_CRC */
1256 static u_int32_t crc32tab[] __attribute__ ((aligned(8))) = {
1257 0xD202EF8D, 0xA505DF1B, 0x3C0C8EA1, 0x4B0BBE37,
1258 0xD56F2B94, 0xA2681B02, 0x3B614AB8, 0x4C667A2E,
1259 0xDCD967BF, 0xABDE5729, 0x32D70693, 0x45D03605,
1260 0xDBB4A3A6, 0xACB39330, 0x35BAC28A, 0x42BDF21C,
1261 0xCFB5FFE9, 0xB8B2CF7F, 0x21BB9EC5, 0x56BCAE53,
1262 0xC8D83BF0, 0xBFDF0B66, 0x26D65ADC, 0x51D16A4A,
1263 0xC16E77DB, 0xB669474D, 0x2F6016F7, 0x58672661,
1264 0xC603B3C2, 0xB1048354, 0x280DD2EE, 0x5F0AE278,
1265 0xE96CCF45, 0x9E6BFFD3, 0x0762AE69, 0x70659EFF,
1266 0xEE010B5C, 0x99063BCA, 0x000F6A70, 0x77085AE6,
1267 0xE7B74777, 0x90B077E1, 0x09B9265B, 0x7EBE16CD,
1268 0xE0DA836E, 0x97DDB3F8, 0x0ED4E242, 0x79D3D2D4,
1269 0xF4DBDF21, 0x83DCEFB7, 0x1AD5BE0D, 0x6DD28E9B,
1270 0xF3B61B38, 0x84B12BAE, 0x1DB87A14, 0x6ABF4A82,
1271 0xFA005713, 0x8D076785, 0x140E363F, 0x630906A9,
1272 0xFD6D930A, 0x8A6AA39C, 0x1363F226, 0x6464C2B0,
1273 0xA4DEAE1D, 0xD3D99E8B, 0x4AD0CF31, 0x3DD7FFA7,
1274 0xA3B36A04, 0xD4B45A92, 0x4DBD0B28, 0x3ABA3BBE,
1275 0xAA05262F, 0xDD0216B9, 0x440B4703, 0x330C7795,
1276 0xAD68E236, 0xDA6FD2A0, 0x4366831A, 0x3461B38C,
1277 0xB969BE79, 0xCE6E8EEF, 0x5767DF55, 0x2060EFC3,
1278 0xBE047A60, 0xC9034AF6, 0x500A1B4C, 0x270D2BDA,
1279 0xB7B2364B, 0xC0B506DD, 0x59BC5767, 0x2EBB67F1,
1280 0xB0DFF252, 0xC7D8C2C4, 0x5ED1937E, 0x29D6A3E8,
1281 0x9FB08ED5, 0xE8B7BE43, 0x71BEEFF9, 0x06B9DF6F,
1282 0x98DD4ACC, 0xEFDA7A5A, 0x76D32BE0, 0x01D41B76,
1283 0x916B06E7, 0xE66C3671, 0x7F6567CB, 0x0862575D,
1284 0x9606C2FE, 0xE101F268, 0x7808A3D2, 0x0F0F9344,
1285 0x82079EB1, 0xF500AE27, 0x6C09FF9D, 0x1B0ECF0B,
1286 0x856A5AA8, 0xF26D6A3E, 0x6B643B84, 0x1C630B12,
1287 0x8CDC1683, 0xFBDB2615, 0x62D277AF, 0x15D54739,
1288 0x8BB1D29A, 0xFCB6E20C, 0x65BFB3B6, 0x12B88320,
1289 0x3FBA6CAD, 0x48BD5C3B, 0xD1B40D81, 0xA6B33D17,
1290 0x38D7A8B4, 0x4FD09822, 0xD6D9C998, 0xA1DEF90E,
1291 0x3161E49F, 0x4666D409, 0xDF6F85B3, 0xA868B525,
1292 0x360C2086, 0x410B1010, 0xD80241AA, 0xAF05713C,
1293 0x220D7CC9, 0x550A4C5F, 0xCC031DE5, 0xBB042D73,
1294 0x2560B8D0, 0x52678846, 0xCB6ED9FC, 0xBC69E96A,
1295 0x2CD6F4FB, 0x5BD1C46D, 0xC2D895D7, 0xB5DFA541,
1296 0x2BBB30E2, 0x5CBC0074, 0xC5B551CE, 0xB2B26158,
1297 0x04D44C65, 0x73D37CF3, 0xEADA2D49, 0x9DDD1DDF,
1298 0x03B9887C, 0x74BEB8EA, 0xEDB7E950, 0x9AB0D9C6,
1299 0x0A0FC457, 0x7D08F4C1, 0xE401A57B, 0x930695ED,
1300 0x0D62004E, 0x7A6530D8, 0xE36C6162, 0x946B51F4,
1301 0x19635C01, 0x6E646C97, 0xF76D3D2D, 0x806A0DBB,
1302 0x1E0E9818, 0x6909A88E, 0xF000F934, 0x8707C9A2,
1303 0x17B8D433, 0x60BFE4A5, 0xF9B6B51F, 0x8EB18589,
1304 0x10D5102A, 0x67D220BC, 0xFEDB7106, 0x89DC4190,
1305 0x49662D3D, 0x3E611DAB, 0xA7684C11, 0xD06F7C87,
1306 0x4E0BE924, 0x390CD9B2, 0xA0058808, 0xD702B89E,
1307 0x47BDA50F, 0x30BA9599, 0xA9B3C423, 0xDEB4F4B5,
1308 0x40D06116, 0x37D75180, 0xAEDE003A, 0xD9D930AC,
1309 0x54D13D59, 0x23D60DCF, 0xBADF5C75, 0xCDD86CE3,
1310 0x53BCF940, 0x24BBC9D6, 0xBDB2986C, 0xCAB5A8FA,
1311 0x5A0AB56B, 0x2D0D85FD, 0xB404D447, 0xC303E4D1,
1312 0x5D677172, 0x2A6041E4, 0xB369105E, 0xC46E20C8,
1313 0x72080DF5, 0x050F3D63, 0x9C066CD9, 0xEB015C4F,
1314 0x7565C9EC, 0x0262F97A, 0x9B6BA8C0, 0xEC6C9856,
1315 0x7CD385C7, 0x0BD4B551, 0x92DDE4EB, 0xE5DAD47D,
1316 0x7BBE41DE, 0x0CB97148, 0x95B020F2, 0xE2B71064,
1317 0x6FBF1D91, 0x18B82D07, 0x81B17CBD, 0xF6B64C2B,
1318 0x68D2D988, 0x1FD5E91E, 0x86DCB8A4, 0xF1DB8832,
1319 0x616495A3, 0x1663A535, 0x8F6AF48F, 0xF86DC419,
1320 0x660951BA, 0x110E612C, 0x88073096, 0xFF000000