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.25 2006/12/22 23:26:21 swildner 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>
75 #include <sys/thread2.h>
78 #include <net/ifq_var.h>
79 #include <net/ethernet.h>
80 #include <net/if_arp.h>
83 #include "if_sbnireg.h"
84 #include "if_sbnivar.h"
88 static void sbni_init(void *);
89 static void sbni_start(struct ifnet *);
90 static int sbni_ioctl(struct ifnet *, u_long, caddr_t, struct ucred *);
91 static void sbni_watchdog(struct ifnet *);
92 static void sbni_stop(struct sbni_softc *);
93 static void handle_channel(struct sbni_softc *);
95 static void card_start(struct sbni_softc *);
96 static int recv_frame(struct sbni_softc *);
97 static void send_frame(struct sbni_softc *);
98 static int upload_data(struct sbni_softc *, u_int, u_int, u_int, u_int32_t);
99 static int skip_tail(struct sbni_softc *, u_int, u_int32_t);
100 static void interpret_ack(struct sbni_softc *, u_int);
101 static void download_data(struct sbni_softc *, u_int32_t *);
102 static void prepare_to_send(struct sbni_softc *);
103 static void drop_xmit_queue(struct sbni_softc *);
104 static int get_rx_buf(struct sbni_softc *);
105 static void indicate_pkt(struct sbni_softc *);
106 static void change_level(struct sbni_softc *);
107 static int check_fhdr(struct sbni_softc *, u_int *, u_int *,
108 u_int *, u_int *, u_int32_t *);
109 static int append_frame_to_pkt(struct sbni_softc *, u_int, u_int32_t);
110 static void timeout_change_level(struct sbni_softc *);
111 static void send_frame_header(struct sbni_softc *, u_int32_t *);
112 static void set_initial_values(struct sbni_softc *, struct sbni_flags);
114 static u_int32_t calc_crc32(u_int32_t, caddr_t, u_int);
115 static timeout_t sbni_timeout;
117 static __inline u_char sbni_inb(struct sbni_softc *, enum sbni_reg);
118 static __inline void sbni_outb(struct sbni_softc *, enum sbni_reg, u_char);
119 static __inline void sbni_insb(struct sbni_softc *, u_char *, u_int);
120 static __inline void sbni_outsb(struct sbni_softc *, u_char *, u_int);
122 DECLARE_DUMMY_MODULE(if_sbni);
124 static u_int32_t crc32tab[];
126 #ifdef SBNI_DUAL_COMPOUND
127 struct sbni_softc *sbni_headlist;
130 u_int32_t next_sbni_unit;
132 /* -------------------------------------------------------------------------- */
134 static __inline u_char
135 sbni_inb(struct sbni_softc *sc, enum sbni_reg reg)
137 return bus_space_read_1(
138 rman_get_bustag(sc->io_res),
139 rman_get_bushandle(sc->io_res),
144 sbni_outb(struct sbni_softc *sc, enum sbni_reg reg, u_char value)
147 rman_get_bustag(sc->io_res),
148 rman_get_bushandle(sc->io_res),
149 sc->io_off + reg, value);
153 sbni_insb(struct sbni_softc *sc, u_char *to, u_int len)
155 bus_space_read_multi_1(
156 rman_get_bustag(sc->io_res),
157 rman_get_bushandle(sc->io_res),
158 sc->io_off + DAT, to, len);
162 sbni_outsb(struct sbni_softc *sc, u_char *from, u_int len)
164 bus_space_write_multi_1(
165 rman_get_bustag(sc->io_res),
166 rman_get_bushandle(sc->io_res),
167 sc->io_off + DAT, from, len);
172 Valid combinations in CSR0 (for probing):
174 VALID_DECODER 0000,0011,1011,1010
179 TR_RDY TR_REQ ; 3 ; +
181 BU_EMP TR_REQ ; 5 ; +
182 BU_EMP TR_RDY ; 6 ; -
183 BU_EMP TR_RDY TR_REQ ; 7 ; +
185 RC_RDY TR_REQ ; 9 ; +
186 RC_RDY TR_RDY ; 10 ; -
187 RC_RDY TR_RDY TR_REQ ; 11 ; -
188 RC_RDY BU_EMP ; 12 ; -
189 RC_RDY BU_EMP TR_REQ ; 13 ; -
190 RC_RDY BU_EMP TR_RDY ; 14 ; -
191 RC_RDY BU_EMP TR_RDY TR_REQ ; 15 ; -
194 #define VALID_DECODER (2 + 8 + 0x10 + 0x20 + 0x80 + 0x100 + 0x200)
198 sbni_probe(struct sbni_softc *sc)
202 csr0 = sbni_inb(sc, CSR0);
203 if (csr0 != 0xff && csr0 != 0x00) {
208 if (VALID_DECODER & (1 << (csr0 >> 4)))
217 * Install interface into kernel networking data structures
220 sbni_attach(struct sbni_softc *sc, int unit, struct sbni_flags flags)
225 ifp = &sc->arpcom.ac_if;
226 sbni_outb(sc, CSR0, 0);
227 set_initial_values(sc, flags);
229 callout_init(&sc->sbni_stat_timer);
230 /* Initialize ifnet structure */
232 if_initname(ifp, "sbni", unit);
233 ifp->if_init = sbni_init;
234 ifp->if_start = sbni_start;
235 ifp->if_ioctl = sbni_ioctl;
236 ifp->if_watchdog = sbni_watchdog;
237 ifq_set_maxlen(&ifp->if_snd, IFQ_MAXLEN);
238 ifq_set_ready(&ifp->if_snd);
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, sc->arpcom.ac_enaddr, NULL);
248 /* device attach does transition from UNCONFIGURED to IDLE state */
250 if_printf(ifp, "speed %ld, rxl ", ifp->if_baudrate);
254 kprintf("%d (fixed)\n", sc->cur_rxl_index);
257 /* -------------------------------------------------------------------------- */
262 struct sbni_softc *sc =xsc;
263 struct ifnet *ifp = &sc->arpcom.ac_if;
266 * kludge to avoid multiple initialization when more than once
267 * protocols configured
269 if (ifp->if_flags & IFF_RUNNING)
273 callout_reset(&sc->sbni_stat_timer,hz / SBNI_HZ, sbni_timeout, sc);
275 ifp->if_flags |= IFF_RUNNING;
276 ifp->if_flags &= ~IFF_OACTIVE;
278 /* attempt to start output */
284 sbni_start(struct ifnet *ifp)
286 struct sbni_softc *sc = ifp->if_softc;
287 if (sc->tx_frameno == 0)
293 sbni_stop(struct sbni_softc *sc)
295 sbni_outb(sc, CSR0, 0);
299 m_freem(sc->rx_buf_p);
303 callout_stop(&sc->sbni_stat_timer);
306 /* -------------------------------------------------------------------------- */
308 /* interrupt handler */
311 * SBNI12D-10, -11/ISA boards within "common interrupt" mode could not
312 * be looked as two independent single-channel devices. Every channel seems
313 * as Ethernet interface but interrupt handler must be common. Really, first
314 * channel ("master") driver only registers the handler. In it's struct softc
315 * it has got pointer to "slave" channel's struct softc and handles that's
317 * softc of successfully attached ISA SBNI boards is linked to list.
318 * While next board driver is initialized, it scans this list. If one
319 * has found softc with same irq and ioaddr different by 4 then it assumes
320 * this board to be "master".
326 struct sbni_softc *sc;
329 sc = (struct sbni_softc *)arg;
333 if (sbni_inb(sc, CSR0) & (RC_RDY | TR_RDY)) {
337 if (sc->slave_sc && /* second channel present */
338 (sbni_inb(sc->slave_sc, CSR0) & (RC_RDY | TR_RDY))) {
339 handle_channel(sc->slave_sc);
347 handle_channel(struct sbni_softc *sc)
352 sbni_outb(sc, CSR0, (sbni_inb(sc, CSR0) & ~EN_INT) | TR_REQ);
354 sc->timer_ticks = CHANGE_LEVEL_START_TICKS;
356 csr0 = sbni_inb(sc, CSR0);
357 if ((csr0 & (RC_RDY | TR_RDY)) == 0)
360 req_ans = !(sc->state & FL_PREV_OK);
363 req_ans = recv_frame(sc);
366 * TR_RDY always equals 1 here because we have owned the marker,
367 * and we set TR_REQ when disabled interrupts
369 csr0 = sbni_inb(sc, CSR0);
370 if ((csr0 & TR_RDY) == 0 || (csr0 & RC_RDY) != 0)
371 kprintf("sbni: internal error!\n");
373 /* if state & FL_NEED_RESEND != 0 then tx_frameno != 0 */
374 if (req_ans || sc->tx_frameno != 0)
377 /* send the marker without any data */
378 sbni_outb(sc, CSR0, sbni_inb(sc, CSR0) & ~TR_REQ);
382 sbni_outb(sc, CSR0, sbni_inb(sc, CSR0) | EN_INT);
387 * Routine returns 1 if it need to acknoweledge received frame.
388 * Empty frame received without errors won't be acknoweledged.
392 recv_frame(struct sbni_softc *sc)
395 u_int framelen, frameno, ack;
396 u_int is_first, frame_ok;
399 if (check_fhdr(sc, &framelen, &frameno, &ack, &is_first, &crc)) {
400 frame_ok = framelen > 4 ?
401 upload_data(sc, framelen, frameno, is_first, crc) :
402 skip_tail(sc, framelen, crc);
404 interpret_ack(sc, ack);
408 sbni_outb(sc, CSR0, sbni_inb(sc, CSR0) ^ CT_ZER);
410 sc->state |= FL_PREV_OK;
412 sc->in_stats.all_rx_number++;
414 sc->state &= ~FL_PREV_OK;
416 sc->in_stats.all_rx_number++;
417 sc->in_stats.bad_rx_number++;
420 return (!frame_ok || framelen > 4);
425 send_frame(struct sbni_softc *sc)
431 if (sc->state & FL_NEED_RESEND) {
433 /* if frame was sended but not ACK'ed - resend it */
434 if (sc->trans_errors) {
436 if (sc->framelen != 0)
437 sc->in_stats.resend_tx_number++;
439 /* cannot xmit with many attempts */
444 sc->trans_errors = TR_ERROR_COUNT;
446 send_frame_header(sc, &crc);
447 sc->state |= FL_NEED_RESEND;
449 * FL_NEED_RESEND will be cleared after ACK, but if empty
450 * frame sended then in prepare_to_send next frame
455 download_data(sc, &crc);
456 sc->in_stats.all_tx_number++;
457 sc->state |= FL_WAIT_ACK;
460 sbni_outsb(sc, (u_char *)&crc, sizeof crc);
463 csr0 = sbni_inb(sc, CSR0);
464 sbni_outb(sc, CSR0, csr0 & ~TR_REQ);
466 if (sc->tx_frameno) {
467 /* next frame exists - request to send */
468 sbni_outb(sc, CSR0, csr0 | TR_REQ);
474 download_data(struct sbni_softc *sc, u_int32_t *crc_p)
478 u_int data_len, pos, slice;
480 data_p = NULL; /* initialized to avoid warn */
483 for (m = sc->tx_buf_p; m != NULL && pos < sc->pktlen; m = m->m_next) {
484 if (pos + m->m_len > sc->outpos) {
485 data_len = m->m_len - (sc->outpos - pos);
486 data_p = mtod(m, caddr_t) + (sc->outpos - pos);
499 slice = min(data_len, sc->framelen - pos);
500 sbni_outsb(sc, data_p, slice);
501 *crc_p = calc_crc32(*crc_p, data_p, slice);
504 if (data_len -= slice)
509 } while (m != NULL && m->m_len == 0);
513 data_p = mtod(m, caddr_t);
517 /* frame too short - zero padding */
519 pos = sc->framelen - pos;
521 sbni_outb(sc, DAT, 0);
522 *crc_p = CRC32(0, *crc_p);
526 } while (pos < sc->framelen);
531 upload_data(struct sbni_softc *sc, u_int framelen, u_int frameno,
532 u_int is_first, u_int32_t crc)
537 sc->wait_frameno = frameno;
541 if (sc->wait_frameno == frameno) {
543 if (sc->inppos + framelen <= ETHER_MAX_LEN) {
544 frame_ok = append_frame_to_pkt(sc, framelen, crc);
547 * if CRC is right but framelen incorrect then transmitter
548 * error was occured... drop entire packet
550 } else if ((frame_ok = skip_tail(sc, framelen, crc)) != 0) {
551 sc->wait_frameno = 0;
553 sc->arpcom.ac_if.if_ierrors++;
554 /* now skip all frames until is_first != 0 */
557 frame_ok = skip_tail(sc, framelen, crc);
559 if (is_first && !frame_ok) {
561 * Frame has been violated, but we have stored
562 * is_first already... Drop entire packet.
564 sc->wait_frameno = 0;
565 sc->arpcom.ac_if.if_ierrors++;
572 static __inline void send_complete(struct sbni_softc *);
575 send_complete(struct sbni_softc *sc)
577 m_freem(sc->tx_buf_p);
579 sc->arpcom.ac_if.if_opackets++;
584 interpret_ack(struct sbni_softc *sc, u_int ack)
586 if (ack == FRAME_SENT_OK) {
587 sc->state &= ~FL_NEED_RESEND;
589 if (sc->state & FL_WAIT_ACK) {
590 sc->outpos += sc->framelen;
592 if (--sc->tx_frameno) {
594 sc->maxframe, sc->pktlen - sc->outpos);
602 sc->state &= ~FL_WAIT_ACK;
607 * Glue received frame with previous fragments of packet.
608 * Indicate packet when last frame would be accepted.
612 append_frame_to_pkt(struct sbni_softc *sc, u_int framelen, u_int32_t crc)
616 if (sc->inppos + framelen > ETHER_MAX_LEN)
619 if (!sc->rx_buf_p && !get_rx_buf(sc))
622 p = sc->rx_buf_p->m_data + sc->inppos;
623 sbni_insb(sc, p, framelen);
624 if (calc_crc32(crc, p, framelen) != CRC32_REMAINDER)
627 sc->inppos += framelen - 4;
628 if (--sc->wait_frameno == 0) { /* last frame received */
630 sc->arpcom.ac_if.if_ipackets++;
638 * Prepare to start output on adapter.
639 * Transmitter will be actually activated when marker has been accepted.
643 prepare_to_send(struct sbni_softc *sc)
648 /* sc->tx_buf_p == NULL here! */
650 kprintf("sbni: memory leak!\n");
653 sc->state &= ~(FL_WAIT_ACK | FL_NEED_RESEND);
656 sc->tx_buf_p = ifq_dequeue(&sc->arpcom.ac_if.if_snd, NULL);
657 if (sc->tx_buf_p == NULL) {
658 /* nothing to transmit... */
662 sc->arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
666 for (len = 0, m = sc->tx_buf_p; m; m = m->m_next)
671 m_freem(sc->tx_buf_p);
674 if (len < SBNI_MIN_LEN)
678 sc->tx_frameno = (len + sc->maxframe - 1) / sc->maxframe;
679 sc->framelen = min(len, sc->maxframe);
681 sbni_outb(sc, CSR0, sbni_inb(sc, CSR0) | TR_REQ);
682 sc->arpcom.ac_if.if_flags |= IFF_OACTIVE;
683 BPF_MTAP(&sc->arpcom.ac_if, sc->tx_buf_p);
688 drop_xmit_queue(struct sbni_softc *sc)
691 m_freem(sc->tx_buf_p);
693 sc->arpcom.ac_if.if_oerrors++;
696 ifq_purge(&sc->arpcom.ac_if.if_snd);
701 sc->state &= ~(FL_WAIT_ACK | FL_NEED_RESEND);
702 sc->arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
707 send_frame_header(struct sbni_softc *sc, u_int32_t *crc_p)
714 len_field = sc->framelen + 6; /* CRC + frameno + reserved */
716 if (sc->state & FL_NEED_RESEND)
717 len_field |= FRAME_RETRY; /* non-first attempt... */
720 len_field |= FRAME_FIRST;
722 len_field |= (sc->state & FL_PREV_OK) ? FRAME_SENT_OK : FRAME_SENT_BAD;
723 sbni_outb(sc, DAT, SBNI_SIG);
725 value = (u_char)len_field;
726 sbni_outb(sc, DAT, value);
727 crc = CRC32(value, crc);
728 value = (u_char)(len_field >> 8);
729 sbni_outb(sc, DAT, value);
730 crc = CRC32(value, crc);
732 sbni_outb(sc, DAT, sc->tx_frameno);
733 crc = CRC32(sc->tx_frameno, crc);
734 sbni_outb(sc, DAT, 0);
741 * if frame tail not needed (incorrect number or received twice),
742 * it won't store, but CRC will be calculated
746 skip_tail(struct sbni_softc *sc, u_int tail_len, u_int32_t crc)
749 crc = CRC32(sbni_inb(sc, DAT), crc);
751 return (crc == CRC32_REMAINDER);
756 check_fhdr(struct sbni_softc *sc, u_int *framelen, u_int *frameno,
757 u_int *ack, u_int *is_first, u_int32_t *crc_p)
763 if (sbni_inb(sc, DAT) != SBNI_SIG)
766 value = sbni_inb(sc, DAT);
767 *framelen = (u_int)value;
768 crc = CRC32(value, crc);
769 value = sbni_inb(sc, DAT);
770 *framelen |= ((u_int)value) << 8;
771 crc = CRC32(value, crc);
773 *ack = *framelen & FRAME_ACK_MASK;
774 *is_first = (*framelen & FRAME_FIRST) != 0;
776 if ((*framelen &= FRAME_LEN_MASK) < 6 || *framelen > SBNI_MAX_FRAME - 3)
779 value = sbni_inb(sc, DAT);
780 *frameno = (u_int)value;
781 crc = CRC32(value, crc);
783 crc = CRC32(sbni_inb(sc, DAT), crc); /* reserved byte */
792 get_rx_buf(struct sbni_softc *sc)
796 MGETHDR(m, MB_DONTWAIT, MT_DATA);
798 kprintf("%s: cannot allocate header mbuf\n",
799 sc->arpcom.ac_if.if_xname);
804 * We always put the received packet in a single buffer -
805 * either with just an mbuf header or in a cluster attached
806 * to the header. The +2 is to compensate for the alignment
809 if (ETHER_MAX_LEN + 2 > MHLEN) {
810 /* Attach an mbuf cluster */
811 MCLGET(m, MB_DONTWAIT);
812 if ((m->m_flags & M_EXT) == 0) {
817 m->m_pkthdr.len = m->m_len = ETHER_MAX_LEN + 2;
820 * The +2 is to longword align the start of the real packet.
821 * (sizeof ether_header == 14)
822 * This is important for NFS.
831 indicate_pkt(struct sbni_softc *sc)
833 struct ifnet *ifp = &sc->arpcom.ac_if;
837 m->m_pkthdr.rcvif = ifp;
838 m->m_pkthdr.len = m->m_len = sc->inppos;
840 ifp->if_input(ifp, m);
844 /* -------------------------------------------------------------------------- */
847 * Routine checks periodically wire activity and regenerates marker if
848 * connect was inactive for a long time.
852 sbni_timeout(void *xsc)
854 struct sbni_softc *sc = xsc;
857 lwkt_serialize_enter(sc->arpcom.ac_if.if_serializer);
859 csr0 = sbni_inb(sc, CSR0);
862 if (sc->timer_ticks) {
863 if (csr0 & (RC_RDY | BU_EMP))
864 /* receiving not active */
867 sc->in_stats.timeout_number++;
869 timeout_change_level(sc);
871 sbni_outb(sc, CSR1, *(u_char *)&sc->csr1 | PR_RES);
872 csr0 = sbni_inb(sc, CSR0);
876 sbni_outb(sc, CSR0, csr0 | RC_CHK);
877 callout_reset(&sc->sbni_stat_timer, hz / SBNI_HZ, sbni_timeout, sc);
879 lwkt_serialize_exit(sc->arpcom.ac_if.if_serializer);
882 /* -------------------------------------------------------------------------- */
885 card_start(struct sbni_softc *sc)
887 sc->timer_ticks = CHANGE_LEVEL_START_TICKS;
888 sc->state &= ~(FL_WAIT_ACK | FL_NEED_RESEND);
889 sc->state |= FL_PREV_OK;
892 sc->wait_frameno = 0;
894 sbni_outb(sc, CSR1, *(u_char *)&sc->csr1 | PR_RES);
895 sbni_outb(sc, CSR0, EN_INT);
898 /* -------------------------------------------------------------------------- */
901 * Device timeout/watchdog routine. Entered if the device neglects to
902 * generate an interrupt after a transmit has been started on it.
906 sbni_watchdog(struct ifnet *ifp)
908 log(LOG_ERR, "%s: device timeout\n", ifp->if_xname);
913 static u_char rxl_tab[] = {
914 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x08,
915 0x0a, 0x0c, 0x0f, 0x16, 0x18, 0x1a, 0x1c, 0x1f
918 #define SIZE_OF_TIMEOUT_RXL_TAB 4
919 static u_char timeout_rxl_tab[] = {
920 0x03, 0x05, 0x08, 0x0b
924 set_initial_values(struct sbni_softc *sc, struct sbni_flags flags)
926 if (flags.fixed_rxl) {
927 sc->delta_rxl = 0; /* disable receive level autodetection */
928 sc->cur_rxl_index = flags.rxl;
930 sc->delta_rxl = DEF_RXL_DELTA;
931 sc->cur_rxl_index = DEF_RXL;
934 sc->csr1.rate = flags.fixed_rate ? flags.rate : DEFAULT_RATE;
935 sc->csr1.rxl = rxl_tab[sc->cur_rxl_index];
936 sc->maxframe = DEFAULT_FRAME_LEN;
939 * generate Ethernet address (0x00ff01xxxxxx)
941 *(u_int16_t *) sc->arpcom.ac_enaddr = htons(0x00ff);
942 if (flags.mac_addr) {
943 *(u_int32_t *) (sc->arpcom.ac_enaddr + 2) =
944 htonl(flags.mac_addr | 0x01000000);
946 *(u_char *) (sc->arpcom.ac_enaddr + 2) = 0x01;
947 read_random_unlimited(sc->arpcom.ac_enaddr + 3, 3);
952 #ifdef SBNI_DUAL_COMPOUND
955 connect_to_master(struct sbni_softc *sc)
957 struct sbni_softc *p, *p_prev;
959 for (p = sbni_headlist, p_prev = NULL; p; p_prev = p, p = p->link) {
960 if (rman_get_start(p->io_res) == rman_get_start(sc->io_res) + 4 ||
961 rman_get_start(p->io_res) == rman_get_start(sc->io_res) - 4) {
964 p_prev->link = p->link;
966 sbni_headlist = p->link;
974 #endif /* SBNI_DUAL_COMPOUND */
977 /* Receive level auto-selection */
980 change_level(struct sbni_softc *sc)
982 if (sc->delta_rxl == 0) /* do not auto-negotiate RxL */
985 if (sc->cur_rxl_index == 0)
987 else if (sc->cur_rxl_index == 15)
989 else if (sc->cur_rxl_rcvd < sc->prev_rxl_rcvd)
990 sc->delta_rxl = -sc->delta_rxl;
992 sc->csr1.rxl = rxl_tab[sc->cur_rxl_index += sc->delta_rxl];
993 sbni_inb(sc, CSR0); /* it needed for PCI cards */
994 sbni_outb(sc, CSR1, *(u_char *)&sc->csr1);
996 sc->prev_rxl_rcvd = sc->cur_rxl_rcvd;
997 sc->cur_rxl_rcvd = 0;
1002 timeout_change_level(struct sbni_softc *sc)
1004 sc->cur_rxl_index = timeout_rxl_tab[sc->timeout_rxl];
1005 if (++sc->timeout_rxl >= 4)
1006 sc->timeout_rxl = 0;
1008 sc->csr1.rxl = rxl_tab[sc->cur_rxl_index];
1010 sbni_outb(sc, CSR1, *(u_char *)&sc->csr1);
1012 sc->prev_rxl_rcvd = sc->cur_rxl_rcvd;
1013 sc->cur_rxl_rcvd = 0;
1016 /* -------------------------------------------------------------------------- */
1019 * Process an ioctl request. This code needs some work - it looks
1024 sbni_ioctl(struct ifnet *ifp, u_long command, caddr_t data, struct ucred *cr)
1026 struct sbni_softc *sc;
1028 struct sbni_in_stats *in_stats;
1029 struct sbni_flags flags;
1033 ifr = (struct ifreq *)data;
1039 * If the interface is marked up and stopped, then start it.
1040 * If it is marked down and running, then stop it.
1042 if (ifp->if_flags & IFF_UP) {
1043 if (!(ifp->if_flags & IFF_RUNNING))
1046 if (ifp->if_flags & IFF_RUNNING) {
1048 ifp->if_flags &= ~IFF_RUNNING;
1056 * Multicast list has changed; set the hardware filter
1061 error = EAFNOSUPPORT; */
1065 if (ifr->ifr_mtu > ETHERMTU)
1068 ifp->if_mtu = ifr->ifr_mtu;
1072 * SBNI specific ioctl
1074 case SIOCGHWFLAGS: /* get flags */
1075 bcopy((caddr_t) sc->arpcom.ac_enaddr+3, (caddr_t) &flags, 3);
1076 flags.rxl = sc->cur_rxl_index;
1077 flags.rate = sc->csr1.rate;
1078 flags.fixed_rxl = (sc->delta_rxl == 0);
1079 flags.fixed_rate = 1;
1080 ifr->ifr_data = *(caddr_t*) &flags;
1084 in_stats = (struct sbni_in_stats *)ifr->ifr_data;
1085 bcopy((void *)(&(sc->in_stats)), (void *)in_stats,
1086 sizeof(struct sbni_in_stats));
1089 case SIOCSHWFLAGS: /* set flags */
1091 error = suser_cred(cr, NULL_CRED_OKAY);
1092 /* NOTE: returns EPERM if no proc */
1095 flags = *(struct sbni_flags*)&ifr->ifr_data;
1096 if (flags.fixed_rxl) {
1098 sc->cur_rxl_index = flags.rxl;
1100 sc->delta_rxl = DEF_RXL_DELTA;
1101 sc->cur_rxl_index = DEF_RXL;
1103 sc->csr1.rxl = rxl_tab[sc->cur_rxl_index];
1104 sc->csr1.rate = flags.fixed_rate ? flags.rate : DEFAULT_RATE;
1106 bcopy((caddr_t) &flags,
1107 (caddr_t) sc->arpcom.ac_enaddr+3, 3);
1109 /* Don't be afraid... */
1110 sbni_outb(sc, CSR1, *(char*)(&sc->csr1) | PR_RES);
1114 if (!(error = suser_cred(cr, NULL_CRED_OKAY))) /* root only */
1115 bzero(&sc->in_stats, sizeof(struct sbni_in_stats));
1119 error = ether_ioctl(ifp, command, data);
1125 /* -------------------------------------------------------------------------- */
1130 calc_crc32(u_int32_t crc, caddr_t p, u_int len)
1136 "xorl %%ebx, %%ebx\n"
1139 "movl $crc32tab, %%edi\n"
1146 "movl (%%esi), %%edx\n"
1150 "xorl (%%edi,%%ebx,4), %%eax\n"
1156 "xorl (%%edi,%%ebx,4), %%eax\n"
1162 "xorl (%%edi,%%ebx,4), %%eax\n"
1168 "xorl (%%edi,%%ebx,4), %%eax\n"
1180 "xorb (%%esi), %%bl\n"
1181 "xorl (%%edi,%%ebx,4), %%eax\n"
1188 "xorb 1(%%esi), %%bl\n"
1189 "xorl (%%edi,%%ebx,4), %%eax\n"
1196 "xorb 2(%%esi), %%bl\n"
1197 "xorl (%%edi,%%ebx,4), %%eax\n"
1200 : "a" (_crc), "g" (p), "g" (len)
1201 : "bx", "cx", "dx", "si", "di"
1210 calc_crc32(u_int32_t crc, caddr_t p, u_int len)
1213 crc = CRC32(*p++, crc);
1218 #endif /* ASM_CRC */
1221 static u_int32_t crc32tab[] __attribute__ ((aligned(8))) = {
1222 0xD202EF8D, 0xA505DF1B, 0x3C0C8EA1, 0x4B0BBE37,
1223 0xD56F2B94, 0xA2681B02, 0x3B614AB8, 0x4C667A2E,
1224 0xDCD967BF, 0xABDE5729, 0x32D70693, 0x45D03605,
1225 0xDBB4A3A6, 0xACB39330, 0x35BAC28A, 0x42BDF21C,
1226 0xCFB5FFE9, 0xB8B2CF7F, 0x21BB9EC5, 0x56BCAE53,
1227 0xC8D83BF0, 0xBFDF0B66, 0x26D65ADC, 0x51D16A4A,
1228 0xC16E77DB, 0xB669474D, 0x2F6016F7, 0x58672661,
1229 0xC603B3C2, 0xB1048354, 0x280DD2EE, 0x5F0AE278,
1230 0xE96CCF45, 0x9E6BFFD3, 0x0762AE69, 0x70659EFF,
1231 0xEE010B5C, 0x99063BCA, 0x000F6A70, 0x77085AE6,
1232 0xE7B74777, 0x90B077E1, 0x09B9265B, 0x7EBE16CD,
1233 0xE0DA836E, 0x97DDB3F8, 0x0ED4E242, 0x79D3D2D4,
1234 0xF4DBDF21, 0x83DCEFB7, 0x1AD5BE0D, 0x6DD28E9B,
1235 0xF3B61B38, 0x84B12BAE, 0x1DB87A14, 0x6ABF4A82,
1236 0xFA005713, 0x8D076785, 0x140E363F, 0x630906A9,
1237 0xFD6D930A, 0x8A6AA39C, 0x1363F226, 0x6464C2B0,
1238 0xA4DEAE1D, 0xD3D99E8B, 0x4AD0CF31, 0x3DD7FFA7,
1239 0xA3B36A04, 0xD4B45A92, 0x4DBD0B28, 0x3ABA3BBE,
1240 0xAA05262F, 0xDD0216B9, 0x440B4703, 0x330C7795,
1241 0xAD68E236, 0xDA6FD2A0, 0x4366831A, 0x3461B38C,
1242 0xB969BE79, 0xCE6E8EEF, 0x5767DF55, 0x2060EFC3,
1243 0xBE047A60, 0xC9034AF6, 0x500A1B4C, 0x270D2BDA,
1244 0xB7B2364B, 0xC0B506DD, 0x59BC5767, 0x2EBB67F1,
1245 0xB0DFF252, 0xC7D8C2C4, 0x5ED1937E, 0x29D6A3E8,
1246 0x9FB08ED5, 0xE8B7BE43, 0x71BEEFF9, 0x06B9DF6F,
1247 0x98DD4ACC, 0xEFDA7A5A, 0x76D32BE0, 0x01D41B76,
1248 0x916B06E7, 0xE66C3671, 0x7F6567CB, 0x0862575D,
1249 0x9606C2FE, 0xE101F268, 0x7808A3D2, 0x0F0F9344,
1250 0x82079EB1, 0xF500AE27, 0x6C09FF9D, 0x1B0ECF0B,
1251 0x856A5AA8, 0xF26D6A3E, 0x6B643B84, 0x1C630B12,
1252 0x8CDC1683, 0xFBDB2615, 0x62D277AF, 0x15D54739,
1253 0x8BB1D29A, 0xFCB6E20C, 0x65BFB3B6, 0x12B88320,
1254 0x3FBA6CAD, 0x48BD5C3B, 0xD1B40D81, 0xA6B33D17,
1255 0x38D7A8B4, 0x4FD09822, 0xD6D9C998, 0xA1DEF90E,
1256 0x3161E49F, 0x4666D409, 0xDF6F85B3, 0xA868B525,
1257 0x360C2086, 0x410B1010, 0xD80241AA, 0xAF05713C,
1258 0x220D7CC9, 0x550A4C5F, 0xCC031DE5, 0xBB042D73,
1259 0x2560B8D0, 0x52678846, 0xCB6ED9FC, 0xBC69E96A,
1260 0x2CD6F4FB, 0x5BD1C46D, 0xC2D895D7, 0xB5DFA541,
1261 0x2BBB30E2, 0x5CBC0074, 0xC5B551CE, 0xB2B26158,
1262 0x04D44C65, 0x73D37CF3, 0xEADA2D49, 0x9DDD1DDF,
1263 0x03B9887C, 0x74BEB8EA, 0xEDB7E950, 0x9AB0D9C6,
1264 0x0A0FC457, 0x7D08F4C1, 0xE401A57B, 0x930695ED,
1265 0x0D62004E, 0x7A6530D8, 0xE36C6162, 0x946B51F4,
1266 0x19635C01, 0x6E646C97, 0xF76D3D2D, 0x806A0DBB,
1267 0x1E0E9818, 0x6909A88E, 0xF000F934, 0x8707C9A2,
1268 0x17B8D433, 0x60BFE4A5, 0xF9B6B51F, 0x8EB18589,
1269 0x10D5102A, 0x67D220BC, 0xFEDB7106, 0x89DC4190,
1270 0x49662D3D, 0x3E611DAB, 0xA7684C11, 0xD06F7C87,
1271 0x4E0BE924, 0x390CD9B2, 0xA0058808, 0xD702B89E,
1272 0x47BDA50F, 0x30BA9599, 0xA9B3C423, 0xDEB4F4B5,
1273 0x40D06116, 0x37D75180, 0xAEDE003A, 0xD9D930AC,
1274 0x54D13D59, 0x23D60DCF, 0xBADF5C75, 0xCDD86CE3,
1275 0x53BCF940, 0x24BBC9D6, 0xBDB2986C, 0xCAB5A8FA,
1276 0x5A0AB56B, 0x2D0D85FD, 0xB404D447, 0xC303E4D1,
1277 0x5D677172, 0x2A6041E4, 0xB369105E, 0xC46E20C8,
1278 0x72080DF5, 0x050F3D63, 0x9C066CD9, 0xEB015C4F,
1279 0x7565C9EC, 0x0262F97A, 0x9B6BA8C0, 0xEC6C9856,
1280 0x7CD385C7, 0x0BD4B551, 0x92DDE4EB, 0xE5DAD47D,
1281 0x7BBE41DE, 0x0CB97148, 0x95B020F2, 0xE2B71064,
1282 0x6FBF1D91, 0x18B82D07, 0x81B17CBD, 0xF6B64C2B,
1283 0x68D2D988, 0x1FD5E91E, 0x86DCB8A4, 0xF1DB8832,
1284 0x616495A3, 0x1663A535, 0x8F6AF48F, 0xF86DC419,
1285 0x660951BA, 0x110E612C, 0x88073096, 0xFF000000