2 * Copyright (c) 1997-2001 Granch, Ltd. All rights reserved.
3 * Author: Denis I.Timofeev <timofeev@granch.ru>
5 * Redistributon and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice unmodified, this list of conditions, and the following
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
33 * Device driver for Granch SBNI12 leased line adapters
35 * Revision 2.0.0 1997/08/06
36 * Initial revision by Alexey Zverev
38 * Revision 2.0.1 1997/08/11
39 * Additional internal statistics support (tx statistics)
41 * Revision 2.0.2 1997/11/05
42 * if_bpf bug has been fixed
44 * Revision 2.0.3 1998/12/20
45 * Memory leakage has been eliminated in
46 * the sbni_st and sbni_timeout routines.
48 * Revision 3.0 2000/08/10 by Yaroslav Polyakov
49 * Support for PCI cards. 4.1 modification.
51 * Revision 3.1 2000/09/12
52 * Removed extra #defines around bpf functions
54 * Revision 4.0 2000/11/23 by Denis Timofeev
55 * Completely redesigned the buffer management
57 * Revision 4.1 2001/01/21
58 * Support for PCI Dual cards and new SBNI12D-10, -11 Dual/ISA cards
60 * Written with reference to NE2000 driver developed by David Greenman.
64 #include <sys/param.h>
65 #include <sys/systm.h>
66 #include <sys/socket.h>
67 #include <sys/sockio.h>
69 #include <sys/kernel.h>
71 #include <sys/callout.h>
72 #include <sys/syslog.h>
73 #include <sys/random.h>
75 #include <machine/bus.h>
77 #include <machine/resource.h>
80 #include <net/ethernet.h>
81 #include <net/if_arp.h>
83 #include <net/if_types.h>
85 #include <dev/sbni/if_sbnireg.h>
86 #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->ifp = if_alloc(IFT_ETHER);
225 panic("sbni%d: can not if_alloc()", unit);
226 sbni_outb(sc, CSR0, 0);
227 set_initial_values(sc, flags);
229 callout_handle_init(&sc->wch);
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 |
246 ether_ifattach(ifp, sc->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;
269 * kludge to avoid multiple initialization when more than once
270 * protocols configured
272 if (ifp->if_drv_flags & IFF_DRV_RUNNING)
278 sc->wch = timeout(sbni_timeout, sc, hz/SBNI_HZ);
280 ifp->if_drv_flags |= IFF_DRV_RUNNING;
281 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
283 /* attempt to start output */
290 sbni_start(struct ifnet *ifp)
292 struct sbni_softc *sc = ifp->if_softc;
293 if (sc->tx_frameno == 0)
299 sbni_stop(struct sbni_softc *sc)
301 sbni_outb(sc, CSR0, 0);
305 m_freem(sc->rx_buf_p);
309 untimeout(sbni_timeout, sc, sc->wch);
310 sc->wch.callout = NULL;
313 /* -------------------------------------------------------------------------- */
315 /* interrupt handler */
318 * SBNI12D-10, -11/ISA boards within "common interrupt" mode could not
319 * be looked as two independent single-channel devices. Every channel seems
320 * as Ethernet interface but interrupt handler must be common. Really, first
321 * channel ("master") driver only registers the handler. In it's struct softc
322 * it has got pointer to "slave" channel's struct softc and handles that's
324 * softc of successfully attached ISA SBNI boards is linked to list.
325 * While next board driver is initialized, it scans this list. If one
326 * has found softc with same irq and ioaddr different by 4 then it assumes
327 * this board to be "master".
333 struct sbni_softc *sc;
336 sc = (struct sbni_softc *)arg;
340 if (sbni_inb(sc, CSR0) & (RC_RDY | TR_RDY)) {
344 if (sc->slave_sc && /* second channel present */
345 (sbni_inb(sc->slave_sc, CSR0) & (RC_RDY | TR_RDY))) {
346 handle_channel(sc->slave_sc);
354 handle_channel(struct sbni_softc *sc)
359 sbni_outb(sc, CSR0, (sbni_inb(sc, CSR0) & ~EN_INT) | TR_REQ);
361 sc->timer_ticks = CHANGE_LEVEL_START_TICKS;
363 csr0 = sbni_inb(sc, CSR0);
364 if ((csr0 & (RC_RDY | TR_RDY)) == 0)
367 req_ans = !(sc->state & FL_PREV_OK);
370 req_ans = recv_frame(sc);
373 * TR_RDY always equals 1 here because we have owned the marker,
374 * and we set TR_REQ when disabled interrupts
376 csr0 = sbni_inb(sc, CSR0);
377 if ((csr0 & TR_RDY) == 0 || (csr0 & RC_RDY) != 0)
378 printf("sbni: internal error!\n");
380 /* if state & FL_NEED_RESEND != 0 then tx_frameno != 0 */
381 if (req_ans || sc->tx_frameno != 0)
384 /* send the marker without any data */
385 sbni_outb(sc, CSR0, sbni_inb(sc, CSR0) & ~TR_REQ);
389 sbni_outb(sc, CSR0, sbni_inb(sc, CSR0) | EN_INT);
394 * Routine returns 1 if it need to acknoweledge received frame.
395 * Empty frame received without errors won't be acknoweledged.
399 recv_frame(struct sbni_softc *sc)
402 u_int framelen, frameno, ack;
403 u_int is_first, frame_ok;
406 if (check_fhdr(sc, &framelen, &frameno, &ack, &is_first, &crc)) {
407 frame_ok = framelen > 4 ?
408 upload_data(sc, framelen, frameno, is_first, crc) :
409 skip_tail(sc, framelen, crc);
411 interpret_ack(sc, ack);
415 sbni_outb(sc, CSR0, sbni_inb(sc, CSR0) ^ CT_ZER);
417 sc->state |= FL_PREV_OK;
419 sc->in_stats.all_rx_number++;
421 sc->state &= ~FL_PREV_OK;
423 sc->in_stats.all_rx_number++;
424 sc->in_stats.bad_rx_number++;
427 return (!frame_ok || framelen > 4);
432 send_frame(struct sbni_softc *sc)
438 if (sc->state & FL_NEED_RESEND) {
440 /* if frame was sended but not ACK'ed - resend it */
441 if (sc->trans_errors) {
443 if (sc->framelen != 0)
444 sc->in_stats.resend_tx_number++;
446 /* cannot xmit with many attempts */
451 sc->trans_errors = TR_ERROR_COUNT;
453 send_frame_header(sc, &crc);
454 sc->state |= FL_NEED_RESEND;
456 * FL_NEED_RESEND will be cleared after ACK, but if empty
457 * frame sended then in prepare_to_send next frame
462 download_data(sc, &crc);
463 sc->in_stats.all_tx_number++;
464 sc->state |= FL_WAIT_ACK;
467 sbni_outsb(sc, (u_char *)&crc, sizeof crc);
470 csr0 = sbni_inb(sc, CSR0);
471 sbni_outb(sc, CSR0, csr0 & ~TR_REQ);
473 if (sc->tx_frameno) {
474 /* next frame exists - request to send */
475 sbni_outb(sc, CSR0, csr0 | TR_REQ);
481 download_data(struct sbni_softc *sc, u_int32_t *crc_p)
485 u_int data_len, pos, slice;
487 data_p = NULL; /* initialized to avoid warn */
490 for (m = sc->tx_buf_p; m != NULL && pos < sc->pktlen; m = m->m_next) {
491 if (pos + m->m_len > sc->outpos) {
492 data_len = m->m_len - (sc->outpos - pos);
493 data_p = mtod(m, caddr_t) + (sc->outpos - pos);
506 slice = min(data_len, sc->framelen - pos);
507 sbni_outsb(sc, data_p, slice);
508 *crc_p = calc_crc32(*crc_p, data_p, slice);
511 if (data_len -= slice)
516 } while (m != NULL && m->m_len == 0);
520 data_p = mtod(m, caddr_t);
524 /* frame too short - zero padding */
526 pos = sc->framelen - pos;
528 sbni_outb(sc, DAT, 0);
529 *crc_p = CRC32(0, *crc_p);
533 } while (pos < sc->framelen);
538 upload_data(struct sbni_softc *sc, u_int framelen, u_int frameno,
539 u_int is_first, u_int32_t crc)
544 sc->wait_frameno = frameno;
548 if (sc->wait_frameno == frameno) {
550 if (sc->inppos + framelen <= ETHER_MAX_LEN) {
551 frame_ok = append_frame_to_pkt(sc, framelen, crc);
554 * if CRC is right but framelen incorrect then transmitter
555 * error was occured... drop entire packet
557 } else if ((frame_ok = skip_tail(sc, framelen, crc)) != 0) {
558 sc->wait_frameno = 0;
560 sc->ifp->if_ierrors++;
561 /* now skip all frames until is_first != 0 */
564 frame_ok = skip_tail(sc, framelen, crc);
566 if (is_first && !frame_ok) {
568 * Frame has been violated, but we have stored
569 * is_first already... Drop entire packet.
571 sc->wait_frameno = 0;
572 sc->ifp->if_ierrors++;
579 static __inline void send_complete(struct sbni_softc *);
582 send_complete(struct sbni_softc *sc)
584 m_freem(sc->tx_buf_p);
586 sc->ifp->if_opackets++;
591 interpret_ack(struct sbni_softc *sc, u_int ack)
593 if (ack == FRAME_SENT_OK) {
594 sc->state &= ~FL_NEED_RESEND;
596 if (sc->state & FL_WAIT_ACK) {
597 sc->outpos += sc->framelen;
599 if (--sc->tx_frameno) {
601 sc->maxframe, sc->pktlen - sc->outpos);
609 sc->state &= ~FL_WAIT_ACK;
614 * Glue received frame with previous fragments of packet.
615 * Indicate packet when last frame would be accepted.
619 append_frame_to_pkt(struct sbni_softc *sc, u_int framelen, u_int32_t crc)
623 if (sc->inppos + framelen > ETHER_MAX_LEN)
626 if (!sc->rx_buf_p && !get_rx_buf(sc))
629 p = sc->rx_buf_p->m_data + sc->inppos;
630 sbni_insb(sc, p, framelen);
631 if (calc_crc32(crc, p, framelen) != CRC32_REMAINDER)
634 sc->inppos += framelen - 4;
635 if (--sc->wait_frameno == 0) { /* last frame received */
637 sc->ifp->if_ipackets++;
645 * Prepare to start output on adapter. Current priority must be set to splimp
646 * before this routine is called.
647 * Transmitter will be actually activated when marker has been accepted.
651 prepare_to_send(struct sbni_softc *sc)
656 /* sc->tx_buf_p == NULL here! */
658 printf("sbni: memory leak!\n");
661 sc->state &= ~(FL_WAIT_ACK | FL_NEED_RESEND);
664 IF_DEQUEUE(&sc->ifp->if_snd, sc->tx_buf_p);
666 /* nothing to transmit... */
670 sc->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
674 for (len = 0, m = sc->tx_buf_p; m; m = m->m_next)
679 m_freem(sc->tx_buf_p);
682 if (len < SBNI_MIN_LEN)
686 sc->tx_frameno = (len + sc->maxframe - 1) / sc->maxframe;
687 sc->framelen = min(len, sc->maxframe);
689 sbni_outb(sc, CSR0, sbni_inb(sc, CSR0) | TR_REQ);
690 sc->ifp->if_drv_flags |= IFF_DRV_OACTIVE;
691 BPF_MTAP(sc->ifp, sc->tx_buf_p);
696 drop_xmit_queue(struct sbni_softc *sc)
701 m_freem(sc->tx_buf_p);
703 sc->ifp->if_oerrors++;
707 IF_DEQUEUE(&sc->ifp->if_snd, m);
711 sc->ifp->if_oerrors++;
717 sc->state &= ~(FL_WAIT_ACK | FL_NEED_RESEND);
718 sc->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
723 send_frame_header(struct sbni_softc *sc, u_int32_t *crc_p)
730 len_field = sc->framelen + 6; /* CRC + frameno + reserved */
732 if (sc->state & FL_NEED_RESEND)
733 len_field |= FRAME_RETRY; /* non-first attempt... */
736 len_field |= FRAME_FIRST;
738 len_field |= (sc->state & FL_PREV_OK) ? FRAME_SENT_OK : FRAME_SENT_BAD;
739 sbni_outb(sc, DAT, SBNI_SIG);
741 value = (u_char)len_field;
742 sbni_outb(sc, DAT, value);
743 crc = CRC32(value, crc);
744 value = (u_char)(len_field >> 8);
745 sbni_outb(sc, DAT, value);
746 crc = CRC32(value, crc);
748 sbni_outb(sc, DAT, sc->tx_frameno);
749 crc = CRC32(sc->tx_frameno, crc);
750 sbni_outb(sc, DAT, 0);
757 * if frame tail not needed (incorrect number or received twice),
758 * it won't store, but CRC will be calculated
762 skip_tail(struct sbni_softc *sc, u_int tail_len, u_int32_t crc)
765 crc = CRC32(sbni_inb(sc, DAT), crc);
767 return (crc == CRC32_REMAINDER);
772 check_fhdr(struct sbni_softc *sc, u_int *framelen, u_int *frameno,
773 u_int *ack, u_int *is_first, u_int32_t *crc_p)
779 if (sbni_inb(sc, DAT) != SBNI_SIG)
782 value = sbni_inb(sc, DAT);
783 *framelen = (u_int)value;
784 crc = CRC32(value, crc);
785 value = sbni_inb(sc, DAT);
786 *framelen |= ((u_int)value) << 8;
787 crc = CRC32(value, crc);
789 *ack = *framelen & FRAME_ACK_MASK;
790 *is_first = (*framelen & FRAME_FIRST) != 0;
792 if ((*framelen &= FRAME_LEN_MASK) < 6 || *framelen > SBNI_MAX_FRAME - 3)
795 value = sbni_inb(sc, DAT);
796 *frameno = (u_int)value;
797 crc = CRC32(value, crc);
799 crc = CRC32(sbni_inb(sc, DAT), crc); /* reserved byte */
808 get_rx_buf(struct sbni_softc *sc)
812 MGETHDR(m, M_DONTWAIT, MT_DATA);
814 if_printf(sc->ifp, "cannot allocate header mbuf\n");
819 * We always put the received packet in a single buffer -
820 * either with just an mbuf header or in a cluster attached
821 * to the header. The +2 is to compensate for the alignment
824 if (ETHER_MAX_LEN + 2 > MHLEN) {
825 /* Attach an mbuf cluster */
826 MCLGET(m, M_DONTWAIT);
827 if ((m->m_flags & M_EXT) == 0) {
832 m->m_pkthdr.len = m->m_len = ETHER_MAX_LEN + 2;
835 * The +2 is to longword align the start of the real packet.
836 * (sizeof ether_header == 14)
837 * This is important for NFS.
846 indicate_pkt(struct sbni_softc *sc)
848 struct ifnet *ifp = sc->ifp;
852 m->m_pkthdr.rcvif = ifp;
853 m->m_pkthdr.len = m->m_len = sc->inppos;
855 (*ifp->if_input)(ifp, m);
859 /* -------------------------------------------------------------------------- */
862 * Routine checks periodically wire activity and regenerates marker if
863 * connect was inactive for a long time.
867 sbni_timeout(void *xsc)
869 struct sbni_softc *sc;
873 sc = (struct sbni_softc *)xsc;
876 csr0 = sbni_inb(sc, CSR0);
879 if (sc->timer_ticks) {
880 if (csr0 & (RC_RDY | BU_EMP))
881 /* receiving not active */
884 sc->in_stats.timeout_number++;
886 timeout_change_level(sc);
888 sbni_outb(sc, CSR1, *(u_char *)&sc->csr1 | PR_RES);
889 csr0 = sbni_inb(sc, CSR0);
893 sbni_outb(sc, CSR0, csr0 | RC_CHK);
894 sc->wch = timeout(sbni_timeout, sc, hz/SBNI_HZ);
898 /* -------------------------------------------------------------------------- */
901 card_start(struct sbni_softc *sc)
903 sc->timer_ticks = CHANGE_LEVEL_START_TICKS;
904 sc->state &= ~(FL_WAIT_ACK | FL_NEED_RESEND);
905 sc->state |= FL_PREV_OK;
908 sc->wait_frameno = 0;
910 sbni_outb(sc, CSR1, *(u_char *)&sc->csr1 | PR_RES);
911 sbni_outb(sc, CSR0, EN_INT);
914 /* -------------------------------------------------------------------------- */
917 * Device timeout/watchdog routine. Entered if the device neglects to
918 * generate an interrupt after a transmit has been started on it.
922 sbni_watchdog(struct ifnet *ifp)
924 log(LOG_ERR, "%s: device timeout\n", ifp->if_xname);
929 static u_char rxl_tab[] = {
930 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x08,
931 0x0a, 0x0c, 0x0f, 0x16, 0x18, 0x1a, 0x1c, 0x1f
934 #define SIZE_OF_TIMEOUT_RXL_TAB 4
935 static u_char timeout_rxl_tab[] = {
936 0x03, 0x05, 0x08, 0x0b
940 set_initial_values(struct sbni_softc *sc, struct sbni_flags flags)
942 if (flags.fixed_rxl) {
943 sc->delta_rxl = 0; /* disable receive level autodetection */
944 sc->cur_rxl_index = flags.rxl;
946 sc->delta_rxl = DEF_RXL_DELTA;
947 sc->cur_rxl_index = DEF_RXL;
950 sc->csr1.rate = flags.fixed_rate ? flags.rate : DEFAULT_RATE;
951 sc->csr1.rxl = rxl_tab[sc->cur_rxl_index];
952 sc->maxframe = DEFAULT_FRAME_LEN;
955 * generate Ethernet address (0x00ff01xxxxxx)
957 *(u_int16_t *) sc->enaddr = htons(0x00ff);
958 if (flags.mac_addr) {
959 *(u_int32_t *) (sc->enaddr + 2) =
960 htonl(flags.mac_addr | 0x01000000);
962 *(u_char *) (sc->enaddr + 2) = 0x01;
963 read_random(sc->enaddr + 3, 3);
968 #ifdef SBNI_DUAL_COMPOUND
971 connect_to_master(struct sbni_softc *sc)
973 struct sbni_softc *p, *p_prev;
975 for (p = sbni_headlist, p_prev = NULL; p; p_prev = p, p = p->link) {
976 if (rman_get_start(p->io_res) == rman_get_start(sc->io_res) + 4 ||
977 rman_get_start(p->io_res) == rman_get_start(sc->io_res) - 4) {
980 p_prev->link = p->link;
982 sbni_headlist = p->link;
990 #endif /* SBNI_DUAL_COMPOUND */
993 /* Receive level auto-selection */
996 change_level(struct sbni_softc *sc)
998 if (sc->delta_rxl == 0) /* do not auto-negotiate RxL */
1001 if (sc->cur_rxl_index == 0)
1003 else if (sc->cur_rxl_index == 15)
1005 else if (sc->cur_rxl_rcvd < sc->prev_rxl_rcvd)
1006 sc->delta_rxl = -sc->delta_rxl;
1008 sc->csr1.rxl = rxl_tab[sc->cur_rxl_index += sc->delta_rxl];
1009 sbni_inb(sc, CSR0); /* it needed for PCI cards */
1010 sbni_outb(sc, CSR1, *(u_char *)&sc->csr1);
1012 sc->prev_rxl_rcvd = sc->cur_rxl_rcvd;
1013 sc->cur_rxl_rcvd = 0;
1018 timeout_change_level(struct sbni_softc *sc)
1020 sc->cur_rxl_index = timeout_rxl_tab[sc->timeout_rxl];
1021 if (++sc->timeout_rxl >= 4)
1022 sc->timeout_rxl = 0;
1024 sc->csr1.rxl = rxl_tab[sc->cur_rxl_index];
1026 sbni_outb(sc, CSR1, *(u_char *)&sc->csr1);
1028 sc->prev_rxl_rcvd = sc->cur_rxl_rcvd;
1029 sc->cur_rxl_rcvd = 0;
1032 /* -------------------------------------------------------------------------- */
1035 * Process an ioctl request. This code needs some work - it looks
1040 sbni_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
1042 struct sbni_softc *sc;
1045 struct sbni_in_stats *in_stats;
1046 struct sbni_flags flags;
1050 ifr = (struct ifreq *)data;
1059 * If the interface is marked up and stopped, then start it.
1060 * If it is marked down and running, then stop it.
1062 if (ifp->if_flags & IFF_UP) {
1063 if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
1066 if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
1068 ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
1076 * Multicast list has changed; set the hardware filter
1081 error = EAFNOSUPPORT; */
1085 if (ifr->ifr_mtu > ETHERMTU)
1088 ifp->if_mtu = ifr->ifr_mtu;
1092 * SBNI specific ioctl
1094 case SIOCGHWFLAGS: /* get flags */
1095 bcopy((caddr_t)IFP2ENADDR(sc->ifp)+3, (caddr_t) &flags, 3);
1096 flags.rxl = sc->cur_rxl_index;
1097 flags.rate = sc->csr1.rate;
1098 flags.fixed_rxl = (sc->delta_rxl == 0);
1099 flags.fixed_rate = 1;
1100 ifr->ifr_data = *(caddr_t*) &flags;
1104 in_stats = (struct sbni_in_stats *)ifr->ifr_data;
1105 bcopy((void *)(&(sc->in_stats)), (void *)in_stats,
1106 sizeof(struct sbni_in_stats));
1109 case SIOCSHWFLAGS: /* set flags */
1114 flags = *(struct sbni_flags*)&ifr->ifr_data;
1115 if (flags.fixed_rxl) {
1117 sc->cur_rxl_index = flags.rxl;
1119 sc->delta_rxl = DEF_RXL_DELTA;
1120 sc->cur_rxl_index = DEF_RXL;
1122 sc->csr1.rxl = rxl_tab[sc->cur_rxl_index];
1123 sc->csr1.rate = flags.fixed_rate ? flags.rate : DEFAULT_RATE;
1125 bcopy((caddr_t) &flags,
1126 (caddr_t) IFP2ENADDR(sc->ifp)+3, 3);
1128 /* Don't be afraid... */
1129 sbni_outb(sc, CSR1, *(char*)(&sc->csr1) | PR_RES);
1133 if (!(error = suser(td))) /* root only */
1134 bzero(&sc->in_stats, sizeof(struct sbni_in_stats));
1138 error = ether_ioctl(ifp, command, data);
1146 /* -------------------------------------------------------------------------- */
1149 calc_crc32(u_int32_t crc, caddr_t p, u_int len)
1152 crc = CRC32(*p++, crc);
1157 static u_int32_t crc32tab[] __aligned(8) = {
1158 0xD202EF8D, 0xA505DF1B, 0x3C0C8EA1, 0x4B0BBE37,
1159 0xD56F2B94, 0xA2681B02, 0x3B614AB8, 0x4C667A2E,
1160 0xDCD967BF, 0xABDE5729, 0x32D70693, 0x45D03605,
1161 0xDBB4A3A6, 0xACB39330, 0x35BAC28A, 0x42BDF21C,
1162 0xCFB5FFE9, 0xB8B2CF7F, 0x21BB9EC5, 0x56BCAE53,
1163 0xC8D83BF0, 0xBFDF0B66, 0x26D65ADC, 0x51D16A4A,
1164 0xC16E77DB, 0xB669474D, 0x2F6016F7, 0x58672661,
1165 0xC603B3C2, 0xB1048354, 0x280DD2EE, 0x5F0AE278,
1166 0xE96CCF45, 0x9E6BFFD3, 0x0762AE69, 0x70659EFF,
1167 0xEE010B5C, 0x99063BCA, 0x000F6A70, 0x77085AE6,
1168 0xE7B74777, 0x90B077E1, 0x09B9265B, 0x7EBE16CD,
1169 0xE0DA836E, 0x97DDB3F8, 0x0ED4E242, 0x79D3D2D4,
1170 0xF4DBDF21, 0x83DCEFB7, 0x1AD5BE0D, 0x6DD28E9B,
1171 0xF3B61B38, 0x84B12BAE, 0x1DB87A14, 0x6ABF4A82,
1172 0xFA005713, 0x8D076785, 0x140E363F, 0x630906A9,
1173 0xFD6D930A, 0x8A6AA39C, 0x1363F226, 0x6464C2B0,
1174 0xA4DEAE1D, 0xD3D99E8B, 0x4AD0CF31, 0x3DD7FFA7,
1175 0xA3B36A04, 0xD4B45A92, 0x4DBD0B28, 0x3ABA3BBE,
1176 0xAA05262F, 0xDD0216B9, 0x440B4703, 0x330C7795,
1177 0xAD68E236, 0xDA6FD2A0, 0x4366831A, 0x3461B38C,
1178 0xB969BE79, 0xCE6E8EEF, 0x5767DF55, 0x2060EFC3,
1179 0xBE047A60, 0xC9034AF6, 0x500A1B4C, 0x270D2BDA,
1180 0xB7B2364B, 0xC0B506DD, 0x59BC5767, 0x2EBB67F1,
1181 0xB0DFF252, 0xC7D8C2C4, 0x5ED1937E, 0x29D6A3E8,
1182 0x9FB08ED5, 0xE8B7BE43, 0x71BEEFF9, 0x06B9DF6F,
1183 0x98DD4ACC, 0xEFDA7A5A, 0x76D32BE0, 0x01D41B76,
1184 0x916B06E7, 0xE66C3671, 0x7F6567CB, 0x0862575D,
1185 0x9606C2FE, 0xE101F268, 0x7808A3D2, 0x0F0F9344,
1186 0x82079EB1, 0xF500AE27, 0x6C09FF9D, 0x1B0ECF0B,
1187 0x856A5AA8, 0xF26D6A3E, 0x6B643B84, 0x1C630B12,
1188 0x8CDC1683, 0xFBDB2615, 0x62D277AF, 0x15D54739,
1189 0x8BB1D29A, 0xFCB6E20C, 0x65BFB3B6, 0x12B88320,
1190 0x3FBA6CAD, 0x48BD5C3B, 0xD1B40D81, 0xA6B33D17,
1191 0x38D7A8B4, 0x4FD09822, 0xD6D9C998, 0xA1DEF90E,
1192 0x3161E49F, 0x4666D409, 0xDF6F85B3, 0xA868B525,
1193 0x360C2086, 0x410B1010, 0xD80241AA, 0xAF05713C,
1194 0x220D7CC9, 0x550A4C5F, 0xCC031DE5, 0xBB042D73,
1195 0x2560B8D0, 0x52678846, 0xCB6ED9FC, 0xBC69E96A,
1196 0x2CD6F4FB, 0x5BD1C46D, 0xC2D895D7, 0xB5DFA541,
1197 0x2BBB30E2, 0x5CBC0074, 0xC5B551CE, 0xB2B26158,
1198 0x04D44C65, 0x73D37CF3, 0xEADA2D49, 0x9DDD1DDF,
1199 0x03B9887C, 0x74BEB8EA, 0xEDB7E950, 0x9AB0D9C6,
1200 0x0A0FC457, 0x7D08F4C1, 0xE401A57B, 0x930695ED,
1201 0x0D62004E, 0x7A6530D8, 0xE36C6162, 0x946B51F4,
1202 0x19635C01, 0x6E646C97, 0xF76D3D2D, 0x806A0DBB,
1203 0x1E0E9818, 0x6909A88E, 0xF000F934, 0x8707C9A2,
1204 0x17B8D433, 0x60BFE4A5, 0xF9B6B51F, 0x8EB18589,
1205 0x10D5102A, 0x67D220BC, 0xFEDB7106, 0x89DC4190,
1206 0x49662D3D, 0x3E611DAB, 0xA7684C11, 0xD06F7C87,
1207 0x4E0BE924, 0x390CD9B2, 0xA0058808, 0xD702B89E,
1208 0x47BDA50F, 0x30BA9599, 0xA9B3C423, 0xDEB4F4B5,
1209 0x40D06116, 0x37D75180, 0xAEDE003A, 0xD9D930AC,
1210 0x54D13D59, 0x23D60DCF, 0xBADF5C75, 0xCDD86CE3,
1211 0x53BCF940, 0x24BBC9D6, 0xBDB2986C, 0xCAB5A8FA,
1212 0x5A0AB56B, 0x2D0D85FD, 0xB404D447, 0xC303E4D1,
1213 0x5D677172, 0x2A6041E4, 0xB369105E, 0xC46E20C8,
1214 0x72080DF5, 0x050F3D63, 0x9C066CD9, 0xEB015C4F,
1215 0x7565C9EC, 0x0262F97A, 0x9B6BA8C0, 0xEC6C9856,
1216 0x7CD385C7, 0x0BD4B551, 0x92DDE4EB, 0xE5DAD47D,
1217 0x7BBE41DE, 0x0CB97148, 0x95B020F2, 0xE2B71064,
1218 0x6FBF1D91, 0x18B82D07, 0x81B17CBD, 0xF6B64C2B,
1219 0x68D2D988, 0x1FD5E91E, 0x86DCB8A4, 0xF1DB8832,
1220 0x616495A3, 0x1663A535, 0x8F6AF48F, 0xF86DC419,
1221 0x660951BA, 0x110E612C, 0x88073096, 0xFF000000