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.3 2003/06/23 17:55:34 dillon 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 <dev/sbni/if_sbnireg.h>
84 #include <dev/sbni/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);
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 static u_int32_t crc32tab[];
124 #ifdef SBNI_DUAL_COMPOUND
125 struct sbni_softc *sbni_headlist;
128 u_int32_t next_sbni_unit;
130 /* -------------------------------------------------------------------------- */
132 static __inline u_char
133 sbni_inb(struct sbni_softc *sc, enum sbni_reg reg)
135 return bus_space_read_1(
136 rman_get_bustag(sc->io_res),
137 rman_get_bushandle(sc->io_res),
142 sbni_outb(struct sbni_softc *sc, enum sbni_reg reg, u_char value)
145 rman_get_bustag(sc->io_res),
146 rman_get_bushandle(sc->io_res),
147 sc->io_off + reg, value);
151 sbni_insb(struct sbni_softc *sc, u_char *to, u_int len)
153 bus_space_read_multi_1(
154 rman_get_bustag(sc->io_res),
155 rman_get_bushandle(sc->io_res),
156 sc->io_off + DAT, to, len);
160 sbni_outsb(struct sbni_softc *sc, u_char *from, u_int len)
162 bus_space_write_multi_1(
163 rman_get_bustag(sc->io_res),
164 rman_get_bushandle(sc->io_res),
165 sc->io_off + DAT, from, len);
170 Valid combinations in CSR0 (for probing):
172 VALID_DECODER 0000,0011,1011,1010
177 TR_RDY TR_REQ ; 3 ; +
179 BU_EMP TR_REQ ; 5 ; +
180 BU_EMP TR_RDY ; 6 ; -
181 BU_EMP TR_RDY TR_REQ ; 7 ; +
183 RC_RDY TR_REQ ; 9 ; +
184 RC_RDY TR_RDY ; 10 ; -
185 RC_RDY TR_RDY TR_REQ ; 11 ; -
186 RC_RDY BU_EMP ; 12 ; -
187 RC_RDY BU_EMP TR_REQ ; 13 ; -
188 RC_RDY BU_EMP TR_RDY ; 14 ; -
189 RC_RDY BU_EMP TR_RDY TR_REQ ; 15 ; -
192 #define VALID_DECODER (2 + 8 + 0x10 + 0x20 + 0x80 + 0x100 + 0x200)
196 sbni_probe(struct sbni_softc *sc)
200 csr0 = sbni_inb(sc, CSR0);
201 if (csr0 != 0xff && csr0 != 0x00) {
206 if (VALID_DECODER & (1 << (csr0 >> 4)))
215 * Install interface into kernel networking data structures
218 sbni_attach(struct sbni_softc *sc, int unit, struct sbni_flags flags)
223 ifp = &sc->arpcom.ac_if;
224 sbni_outb(sc, CSR0, 0);
225 set_initial_values(sc, flags);
227 callout_handle_init(&sc->wch);
229 /* Initialize ifnet structure */
232 ifp->if_name = "sbni";
233 ifp->if_init = sbni_init;
234 ifp->if_start = sbni_start;
235 ifp->if_output = ether_output;
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;
246 ether_ifattach(ifp, ETHER_BPF_SUPPORTED);
248 /* device attach does transition from UNCONFIGURED to IDLE state */
250 printf("%s%d: speed %ld, address %6D, rxl ", ifp->if_name,
251 ifp->if_unit, ifp->if_baudrate, sc->arpcom.ac_enaddr, ":");
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 sc->wch = timeout(sbni_timeout, sc, hz/SBNI_HZ);
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 untimeout(sbni_timeout, sc, sc->wch);
316 sc->wch.callout = NULL;
319 /* -------------------------------------------------------------------------- */
321 /* interrupt handler */
324 * SBNI12D-10, -11/ISA boards within "common interrupt" mode could not
325 * be looked as two independent single-channel devices. Every channel seems
326 * as Ethernet interface but interrupt handler must be common. Really, first
327 * channel ("master") driver only registers the handler. In it's struct softc
328 * it has got pointer to "slave" channel's struct softc and handles that's
330 * softc of successfully attached ISA SBNI boards is linked to list.
331 * While next board driver is initialized, it scans this list. If one
332 * has found softc with same irq and ioaddr different by 4 then it assumes
333 * this board to be "master".
339 struct sbni_softc *sc;
342 sc = (struct sbni_softc *)arg;
346 if (sbni_inb(sc, CSR0) & (RC_RDY | TR_RDY)) {
350 if (sc->slave_sc && /* second channel present */
351 (sbni_inb(sc->slave_sc, CSR0) & (RC_RDY | TR_RDY))) {
352 handle_channel(sc->slave_sc);
360 handle_channel(struct sbni_softc *sc)
365 sbni_outb(sc, CSR0, (sbni_inb(sc, CSR0) & ~EN_INT) | TR_REQ);
367 sc->timer_ticks = CHANGE_LEVEL_START_TICKS;
369 csr0 = sbni_inb(sc, CSR0);
370 if ((csr0 & (RC_RDY | TR_RDY)) == 0)
373 req_ans = !(sc->state & FL_PREV_OK);
376 req_ans = recv_frame(sc);
379 * TR_RDY always equals 1 here because we have owned the marker,
380 * and we set TR_REQ when disabled interrupts
382 csr0 = sbni_inb(sc, CSR0);
383 if ((csr0 & TR_RDY) == 0 || (csr0 & RC_RDY) != 0)
384 printf("sbni: internal error!\n");
386 /* if state & FL_NEED_RESEND != 0 then tx_frameno != 0 */
387 if (req_ans || sc->tx_frameno != 0)
390 /* send the marker without any data */
391 sbni_outb(sc, CSR0, sbni_inb(sc, CSR0) & ~TR_REQ);
395 sbni_outb(sc, CSR0, sbni_inb(sc, CSR0) | EN_INT);
400 * Routine returns 1 if it need to acknoweledge received frame.
401 * Empty frame received without errors won't be acknoweledged.
405 recv_frame(struct sbni_softc *sc)
408 u_int framelen, frameno, ack;
409 u_int is_first, frame_ok;
412 if (check_fhdr(sc, &framelen, &frameno, &ack, &is_first, &crc)) {
413 frame_ok = framelen > 4 ?
414 upload_data(sc, framelen, frameno, is_first, crc) :
415 skip_tail(sc, framelen, crc);
417 interpret_ack(sc, ack);
421 sbni_outb(sc, CSR0, sbni_inb(sc, CSR0) ^ CT_ZER);
423 sc->state |= FL_PREV_OK;
425 sc->in_stats.all_rx_number++;
427 sc->state &= ~FL_PREV_OK;
429 sc->in_stats.all_rx_number++;
430 sc->in_stats.bad_rx_number++;
433 return (!frame_ok || framelen > 4);
438 send_frame(struct sbni_softc *sc)
444 if (sc->state & FL_NEED_RESEND) {
446 /* if frame was sended but not ACK'ed - resend it */
447 if (sc->trans_errors) {
449 if (sc->framelen != 0)
450 sc->in_stats.resend_tx_number++;
452 /* cannot xmit with many attempts */
457 sc->trans_errors = TR_ERROR_COUNT;
459 send_frame_header(sc, &crc);
460 sc->state |= FL_NEED_RESEND;
462 * FL_NEED_RESEND will be cleared after ACK, but if empty
463 * frame sended then in prepare_to_send next frame
468 download_data(sc, &crc);
469 sc->in_stats.all_tx_number++;
470 sc->state |= FL_WAIT_ACK;
473 sbni_outsb(sc, (u_char *)&crc, sizeof crc);
476 csr0 = sbni_inb(sc, CSR0);
477 sbni_outb(sc, CSR0, csr0 & ~TR_REQ);
479 if (sc->tx_frameno) {
480 /* next frame exists - request to send */
481 sbni_outb(sc, CSR0, csr0 | TR_REQ);
487 download_data(struct sbni_softc *sc, u_int32_t *crc_p)
491 u_int data_len, pos, slice;
493 data_p = NULL; /* initialized to avoid warn */
496 for (m = sc->tx_buf_p; m != NULL && pos < sc->pktlen; m = m->m_next) {
497 if (pos + m->m_len > sc->outpos) {
498 data_len = m->m_len - (sc->outpos - pos);
499 data_p = mtod(m, caddr_t) + (sc->outpos - pos);
512 slice = min(data_len, sc->framelen - pos);
513 sbni_outsb(sc, data_p, slice);
514 *crc_p = calc_crc32(*crc_p, data_p, slice);
517 if (data_len -= slice)
522 } while (m != NULL && m->m_len == 0);
526 data_p = mtod(m, caddr_t);
530 /* frame too short - zero padding */
532 pos = sc->framelen - pos;
534 sbni_outb(sc, DAT, 0);
535 *crc_p = CRC32(0, *crc_p);
539 } while (pos < sc->framelen);
544 upload_data(struct sbni_softc *sc, u_int framelen, u_int frameno,
545 u_int is_first, u_int32_t crc)
550 sc->wait_frameno = frameno;
554 if (sc->wait_frameno == frameno) {
556 if (sc->inppos + framelen <= ETHER_MAX_LEN) {
557 frame_ok = append_frame_to_pkt(sc, framelen, crc);
560 * if CRC is right but framelen incorrect then transmitter
561 * error was occured... drop entire packet
563 } else if ((frame_ok = skip_tail(sc, framelen, crc)) != 0) {
564 sc->wait_frameno = 0;
566 sc->arpcom.ac_if.if_ierrors++;
567 /* now skip all frames until is_first != 0 */
570 frame_ok = skip_tail(sc, framelen, crc);
572 if (is_first && !frame_ok) {
574 * Frame has been violated, but we have stored
575 * is_first already... Drop entire packet.
577 sc->wait_frameno = 0;
578 sc->arpcom.ac_if.if_ierrors++;
585 static __inline void send_complete(struct sbni_softc *);
588 send_complete(struct sbni_softc *sc)
590 m_freem(sc->tx_buf_p);
592 sc->arpcom.ac_if.if_opackets++;
597 interpret_ack(struct sbni_softc *sc, u_int ack)
599 if (ack == FRAME_SENT_OK) {
600 sc->state &= ~FL_NEED_RESEND;
602 if (sc->state & FL_WAIT_ACK) {
603 sc->outpos += sc->framelen;
605 if (--sc->tx_frameno) {
607 sc->maxframe, sc->pktlen - sc->outpos);
615 sc->state &= ~FL_WAIT_ACK;
620 * Glue received frame with previous fragments of packet.
621 * Indicate packet when last frame would be accepted.
625 append_frame_to_pkt(struct sbni_softc *sc, u_int framelen, u_int32_t crc)
629 if (sc->inppos + framelen > ETHER_MAX_LEN)
632 if (!sc->rx_buf_p && !get_rx_buf(sc))
635 p = sc->rx_buf_p->m_data + sc->inppos;
636 sbni_insb(sc, p, framelen);
637 if (calc_crc32(crc, p, framelen) != CRC32_REMAINDER)
640 sc->inppos += framelen - 4;
641 if (--sc->wait_frameno == 0) { /* last frame received */
643 sc->arpcom.ac_if.if_ipackets++;
651 * Prepare to start output on adapter. Current priority must be set to splimp
652 * before this routine is called.
653 * Transmitter will be actually activated when marker has been accepted.
657 prepare_to_send(struct sbni_softc *sc)
662 /* sc->tx_buf_p == NULL here! */
664 printf("sbni: memory leak!\n");
667 sc->state &= ~(FL_WAIT_ACK | FL_NEED_RESEND);
670 IF_DEQUEUE(&sc->arpcom.ac_if.if_snd, sc->tx_buf_p);
672 /* nothing to transmit... */
676 sc->arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
680 for (len = 0, m = sc->tx_buf_p; m; m = m->m_next)
685 m_freem(sc->tx_buf_p);
688 if (len < SBNI_MIN_LEN)
692 sc->tx_frameno = (len + sc->maxframe - 1) / sc->maxframe;
693 sc->framelen = min(len, sc->maxframe);
695 sbni_outb(sc, CSR0, sbni_inb(sc, CSR0) | TR_REQ);
696 sc->arpcom.ac_if.if_flags |= IFF_OACTIVE;
697 if (sc->arpcom.ac_if.if_bpf)
698 bpf_mtap(&sc->arpcom.ac_if, sc->tx_buf_p);
703 drop_xmit_queue(struct sbni_softc *sc)
708 m_freem(sc->tx_buf_p);
710 sc->arpcom.ac_if.if_oerrors++;
714 IF_DEQUEUE(&sc->arpcom.ac_if.if_snd, m);
718 sc->arpcom.ac_if.if_oerrors++;
724 sc->state &= ~(FL_WAIT_ACK | FL_NEED_RESEND);
725 sc->arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
730 send_frame_header(struct sbni_softc *sc, u_int32_t *crc_p)
737 len_field = sc->framelen + 6; /* CRC + frameno + reserved */
739 if (sc->state & FL_NEED_RESEND)
740 len_field |= FRAME_RETRY; /* non-first attempt... */
743 len_field |= FRAME_FIRST;
745 len_field |= (sc->state & FL_PREV_OK) ? FRAME_SENT_OK : FRAME_SENT_BAD;
746 sbni_outb(sc, DAT, SBNI_SIG);
748 value = (u_char)len_field;
749 sbni_outb(sc, DAT, value);
750 crc = CRC32(value, crc);
751 value = (u_char)(len_field >> 8);
752 sbni_outb(sc, DAT, value);
753 crc = CRC32(value, crc);
755 sbni_outb(sc, DAT, sc->tx_frameno);
756 crc = CRC32(sc->tx_frameno, crc);
757 sbni_outb(sc, DAT, 0);
764 * if frame tail not needed (incorrect number or received twice),
765 * it won't store, but CRC will be calculated
769 skip_tail(struct sbni_softc *sc, u_int tail_len, u_int32_t crc)
772 crc = CRC32(sbni_inb(sc, DAT), crc);
774 return (crc == CRC32_REMAINDER);
779 check_fhdr(struct sbni_softc *sc, u_int *framelen, u_int *frameno,
780 u_int *ack, u_int *is_first, u_int32_t *crc_p)
786 if (sbni_inb(sc, DAT) != SBNI_SIG)
789 value = sbni_inb(sc, DAT);
790 *framelen = (u_int)value;
791 crc = CRC32(value, crc);
792 value = sbni_inb(sc, DAT);
793 *framelen |= ((u_int)value) << 8;
794 crc = CRC32(value, crc);
796 *ack = *framelen & FRAME_ACK_MASK;
797 *is_first = (*framelen & FRAME_FIRST) != 0;
799 if ((*framelen &= FRAME_LEN_MASK) < 6 || *framelen > SBNI_MAX_FRAME - 3)
802 value = sbni_inb(sc, DAT);
803 *frameno = (u_int)value;
804 crc = CRC32(value, crc);
806 crc = CRC32(sbni_inb(sc, DAT), crc); /* reserved byte */
815 get_rx_buf(struct sbni_softc *sc)
819 MGETHDR(m, M_DONTWAIT, MT_DATA);
821 printf("sbni%d: cannot allocate header mbuf\n",
822 sc->arpcom.ac_if.if_unit);
827 * We always put the received packet in a single buffer -
828 * either with just an mbuf header or in a cluster attached
829 * to the header. The +2 is to compensate for the alignment
832 if (ETHER_MAX_LEN + 2 > MHLEN) {
833 /* Attach an mbuf cluster */
834 MCLGET(m, M_DONTWAIT);
835 if ((m->m_flags & M_EXT) == 0) {
840 m->m_pkthdr.len = m->m_len = ETHER_MAX_LEN + 2;
843 * The +2 is to longword align the start of the real packet.
844 * (sizeof ether_header == 14)
845 * This is important for NFS.
854 indicate_pkt(struct sbni_softc *sc)
857 struct ether_header *eh;
860 m->m_pkthdr.rcvif = &sc->arpcom.ac_if;
861 m->m_pkthdr.len = m->m_len = sc->inppos;
862 eh = mtod(m, struct ether_header *);
864 /* Remove link layer address and indicate packet */
865 m_adj(m, sizeof(struct ether_header));
866 ether_input(&sc->arpcom.ac_if, eh, m);
870 /* -------------------------------------------------------------------------- */
873 * Routine checks periodically wire activity and regenerates marker if
874 * connect was inactive for a long time.
878 sbni_timeout(void *xsc)
880 struct sbni_softc *sc;
884 sc = (struct sbni_softc *)xsc;
887 csr0 = sbni_inb(sc, CSR0);
890 if (sc->timer_ticks) {
891 if (csr0 & (RC_RDY | BU_EMP))
892 /* receiving not active */
895 sc->in_stats.timeout_number++;
897 timeout_change_level(sc);
899 sbni_outb(sc, CSR1, *(u_char *)&sc->csr1 | PR_RES);
900 csr0 = sbni_inb(sc, CSR0);
904 sbni_outb(sc, CSR0, csr0 | RC_CHK);
905 sc->wch = timeout(sbni_timeout, sc, hz/SBNI_HZ);
909 /* -------------------------------------------------------------------------- */
912 card_start(struct sbni_softc *sc)
914 sc->timer_ticks = CHANGE_LEVEL_START_TICKS;
915 sc->state &= ~(FL_WAIT_ACK | FL_NEED_RESEND);
916 sc->state |= FL_PREV_OK;
919 sc->wait_frameno = 0;
921 sbni_outb(sc, CSR1, *(u_char *)&sc->csr1 | PR_RES);
922 sbni_outb(sc, CSR0, EN_INT);
925 /* -------------------------------------------------------------------------- */
928 * Device timeout/watchdog routine. Entered if the device neglects to
929 * generate an interrupt after a transmit has been started on it.
933 sbni_watchdog(struct ifnet *ifp)
935 log(LOG_ERR, "sbni%d: device timeout\n", ifp->if_unit);
940 static u_char rxl_tab[] = {
941 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x08,
942 0x0a, 0x0c, 0x0f, 0x16, 0x18, 0x1a, 0x1c, 0x1f
945 #define SIZE_OF_TIMEOUT_RXL_TAB 4
946 static u_char timeout_rxl_tab[] = {
947 0x03, 0x05, 0x08, 0x0b
951 set_initial_values(struct sbni_softc *sc, struct sbni_flags flags)
953 if (flags.fixed_rxl) {
954 sc->delta_rxl = 0; /* disable receive level autodetection */
955 sc->cur_rxl_index = flags.rxl;
957 sc->delta_rxl = DEF_RXL_DELTA;
958 sc->cur_rxl_index = DEF_RXL;
961 sc->csr1.rate = flags.fixed_rate ? flags.rate : DEFAULT_RATE;
962 sc->csr1.rxl = rxl_tab[sc->cur_rxl_index];
963 sc->maxframe = DEFAULT_FRAME_LEN;
966 * generate Ethernet address (0x00ff01xxxxxx)
968 *(u_int16_t *) sc->arpcom.ac_enaddr = htons(0x00ff);
969 if (flags.mac_addr) {
970 *(u_int32_t *) (sc->arpcom.ac_enaddr + 2) =
971 htonl(flags.mac_addr | 0x01000000);
973 *(u_char *) (sc->arpcom.ac_enaddr + 2) = 0x01;
974 read_random_unlimited(sc->arpcom.ac_enaddr + 3, 3);
979 #ifdef SBNI_DUAL_COMPOUND
982 connect_to_master(struct sbni_softc *sc)
984 struct sbni_softc *p, *p_prev;
986 for (p = sbni_headlist, p_prev = NULL; p; p_prev = p, p = p->link) {
987 if (rman_get_start(p->io_res) == rman_get_start(sc->io_res) + 4 ||
988 rman_get_start(p->io_res) == rman_get_start(sc->io_res) - 4) {
991 p_prev->link = p->link;
993 sbni_headlist = p->link;
1001 #endif /* SBNI_DUAL_COMPOUND */
1004 /* Receive level auto-selection */
1007 change_level(struct sbni_softc *sc)
1009 if (sc->delta_rxl == 0) /* do not auto-negotiate RxL */
1012 if (sc->cur_rxl_index == 0)
1014 else if (sc->cur_rxl_index == 15)
1016 else if (sc->cur_rxl_rcvd < sc->prev_rxl_rcvd)
1017 sc->delta_rxl = -sc->delta_rxl;
1019 sc->csr1.rxl = rxl_tab[sc->cur_rxl_index += sc->delta_rxl];
1020 sbni_inb(sc, CSR0); /* it needed for PCI cards */
1021 sbni_outb(sc, CSR1, *(u_char *)&sc->csr1);
1023 sc->prev_rxl_rcvd = sc->cur_rxl_rcvd;
1024 sc->cur_rxl_rcvd = 0;
1029 timeout_change_level(struct sbni_softc *sc)
1031 sc->cur_rxl_index = timeout_rxl_tab[sc->timeout_rxl];
1032 if (++sc->timeout_rxl >= 4)
1033 sc->timeout_rxl = 0;
1035 sc->csr1.rxl = rxl_tab[sc->cur_rxl_index];
1037 sbni_outb(sc, CSR1, *(u_char *)&sc->csr1);
1039 sc->prev_rxl_rcvd = sc->cur_rxl_rcvd;
1040 sc->cur_rxl_rcvd = 0;
1043 /* -------------------------------------------------------------------------- */
1046 * Process an ioctl request. This code needs some work - it looks
1051 sbni_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
1053 struct proc *p = curproc;
1054 struct sbni_softc *sc;
1056 struct sbni_in_stats *in_stats;
1057 struct sbni_flags flags;
1061 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 */
1126 error = suser_xxx(p->p_ucred, 0);
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_xxx(p->p_ucred, 0))) /* 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