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>
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"
90 static void sbni_init(void *);
91 static void sbni_start(struct ifnet *, struct ifaltq_subque *);
92 static int sbni_ioctl(struct ifnet *, u_long, caddr_t, struct ucred *);
93 static void sbni_watchdog(struct ifnet *);
94 static void sbni_stop(struct sbni_softc *);
95 static void handle_channel(struct sbni_softc *);
97 static void card_start(struct sbni_softc *);
98 static int recv_frame(struct sbni_softc *);
99 static void send_frame(struct sbni_softc *);
100 static int upload_data(struct sbni_softc *, u_int, u_int, u_int, u_int32_t);
101 static int skip_tail(struct sbni_softc *, u_int, u_int32_t);
102 static void interpret_ack(struct sbni_softc *, u_int);
103 static void download_data(struct sbni_softc *, u_int32_t *);
104 static void prepare_to_send(struct sbni_softc *);
105 static void drop_xmit_queue(struct sbni_softc *);
106 static int get_rx_buf(struct sbni_softc *);
107 static void indicate_pkt(struct sbni_softc *);
108 static void change_level(struct sbni_softc *);
109 static int check_fhdr(struct sbni_softc *, u_int *, u_int *,
110 u_int *, u_int *, u_int32_t *);
111 static int append_frame_to_pkt(struct sbni_softc *, u_int, u_int32_t);
112 static void timeout_change_level(struct sbni_softc *);
113 static void send_frame_header(struct sbni_softc *, u_int32_t *);
114 static void set_initial_values(struct sbni_softc *, struct sbni_flags);
116 static u_int32_t calc_crc32(u_int32_t, caddr_t, u_int);
117 static timeout_t sbni_timeout;
119 static __inline u_char sbni_inb(struct sbni_softc *, enum sbni_reg);
120 static __inline void sbni_outb(struct sbni_softc *, enum sbni_reg, u_char);
121 static __inline void sbni_insb(struct sbni_softc *, u_char *, u_int);
122 static __inline void sbni_outsb(struct sbni_softc *, u_char *, u_int);
124 DECLARE_DUMMY_MODULE(if_sbni);
126 static u_int32_t crc32tab[];
128 #ifdef SBNI_DUAL_COMPOUND
129 struct sbni_softc *sbni_headlist;
132 u_int32_t next_sbni_unit;
134 /* -------------------------------------------------------------------------- */
136 static __inline u_char
137 sbni_inb(struct sbni_softc *sc, enum sbni_reg reg)
139 return bus_space_read_1(
140 rman_get_bustag(sc->io_res),
141 rman_get_bushandle(sc->io_res),
146 sbni_outb(struct sbni_softc *sc, enum sbni_reg reg, u_char value)
149 rman_get_bustag(sc->io_res),
150 rman_get_bushandle(sc->io_res),
151 sc->io_off + reg, value);
155 sbni_insb(struct sbni_softc *sc, u_char *to, u_int len)
157 bus_space_read_multi_1(
158 rman_get_bustag(sc->io_res),
159 rman_get_bushandle(sc->io_res),
160 sc->io_off + DAT, to, len);
164 sbni_outsb(struct sbni_softc *sc, u_char *from, u_int len)
166 bus_space_write_multi_1(
167 rman_get_bustag(sc->io_res),
168 rman_get_bushandle(sc->io_res),
169 sc->io_off + DAT, from, len);
174 Valid combinations in CSR0 (for probing):
176 VALID_DECODER 0000,0011,1011,1010
181 TR_RDY TR_REQ ; 3 ; +
183 BU_EMP TR_REQ ; 5 ; +
184 BU_EMP TR_RDY ; 6 ; -
185 BU_EMP TR_RDY TR_REQ ; 7 ; +
187 RC_RDY TR_REQ ; 9 ; +
188 RC_RDY TR_RDY ; 10 ; -
189 RC_RDY TR_RDY TR_REQ ; 11 ; -
190 RC_RDY BU_EMP ; 12 ; -
191 RC_RDY BU_EMP TR_REQ ; 13 ; -
192 RC_RDY BU_EMP TR_RDY ; 14 ; -
193 RC_RDY BU_EMP TR_RDY TR_REQ ; 15 ; -
196 #define VALID_DECODER (2 + 8 + 0x10 + 0x20 + 0x80 + 0x100 + 0x200)
200 sbni_probe(struct sbni_softc *sc)
204 csr0 = sbni_inb(sc, CSR0);
205 if (csr0 != 0xff && csr0 != 0x00) {
210 if (VALID_DECODER & (1 << (csr0 >> 4)))
219 * Install interface into kernel networking data structures
222 sbni_attach(struct sbni_softc *sc, int unit, struct sbni_flags flags)
227 ifp = &sc->arpcom.ac_if;
228 sbni_outb(sc, CSR0, 0);
229 set_initial_values(sc, flags);
231 callout_init(&sc->sbni_stat_timer);
232 /* Initialize ifnet structure */
234 if_initname(ifp, "sbni", unit);
235 ifp->if_init = sbni_init;
236 ifp->if_start = sbni_start;
237 ifp->if_ioctl = sbni_ioctl;
238 ifp->if_watchdog = sbni_watchdog;
239 ifq_set_maxlen(&ifp->if_snd, IFQ_MAXLEN);
240 ifq_set_ready(&ifp->if_snd);
242 /* report real baud rate */
243 csr0 = sbni_inb(sc, CSR0);
245 (csr0 & 0x01 ? 500000 : 2000000) / (1 << flags.rate);
247 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
248 ether_ifattach(ifp, sc->arpcom.ac_enaddr, NULL);
250 /* device attach does transition from UNCONFIGURED to IDLE state */
252 if_printf(ifp, "speed %ju, rxl ", (uintmax_t)ifp->if_baudrate);
256 kprintf("%d (fixed)\n", sc->cur_rxl_index);
259 /* -------------------------------------------------------------------------- */
264 struct sbni_softc *sc =xsc;
265 struct ifnet *ifp = &sc->arpcom.ac_if;
268 * kludge to avoid multiple initialization when more than once
269 * protocols configured
271 if (ifp->if_flags & IFF_RUNNING)
275 callout_reset(&sc->sbni_stat_timer,hz / SBNI_HZ, sbni_timeout, sc);
277 ifp->if_flags |= IFF_RUNNING;
278 ifq_clr_oactive(&ifp->if_snd);
280 /* attempt to start output */
286 sbni_start(struct ifnet *ifp, struct ifaltq_subque *ifsq)
288 struct sbni_softc *sc = ifp->if_softc;
290 ASSERT_ALTQ_SQ_DEFAULT(ifp, ifsq);
291 if (sc->tx_frameno == 0)
297 sbni_stop(struct sbni_softc *sc)
299 sbni_outb(sc, CSR0, 0);
303 m_freem(sc->rx_buf_p);
307 callout_stop(&sc->sbni_stat_timer);
310 /* -------------------------------------------------------------------------- */
312 /* interrupt handler */
315 * SBNI12D-10, -11/ISA boards within "common interrupt" mode could not
316 * be looked as two independent single-channel devices. Every channel seems
317 * as Ethernet interface but interrupt handler must be common. Really, first
318 * channel ("master") driver only registers the handler. In it's struct softc
319 * it has got pointer to "slave" channel's struct softc and handles that's
321 * softc of successfully attached ISA SBNI boards is linked to list.
322 * While next board driver is initialized, it scans this list. If one
323 * has found softc with same irq and ioaddr different by 4 then it assumes
324 * this board to be "master".
330 struct sbni_softc *sc;
333 sc = (struct sbni_softc *)arg;
337 if (sbni_inb(sc, CSR0) & (RC_RDY | TR_RDY)) {
341 if (sc->slave_sc && /* second channel present */
342 (sbni_inb(sc->slave_sc, CSR0) & (RC_RDY | TR_RDY))) {
343 handle_channel(sc->slave_sc);
351 handle_channel(struct sbni_softc *sc)
356 sbni_outb(sc, CSR0, (sbni_inb(sc, CSR0) & ~EN_INT) | TR_REQ);
358 sc->timer_ticks = CHANGE_LEVEL_START_TICKS;
360 csr0 = sbni_inb(sc, CSR0);
361 if ((csr0 & (RC_RDY | TR_RDY)) == 0)
364 req_ans = !(sc->state & FL_PREV_OK);
367 req_ans = recv_frame(sc);
370 * TR_RDY always equals 1 here because we have owned the marker,
371 * and we set TR_REQ when disabled interrupts
373 csr0 = sbni_inb(sc, CSR0);
374 if ((csr0 & TR_RDY) == 0 || (csr0 & RC_RDY) != 0)
375 kprintf("sbni: internal error!\n");
377 /* if state & FL_NEED_RESEND != 0 then tx_frameno != 0 */
378 if (req_ans || sc->tx_frameno != 0)
381 /* send the marker without any data */
382 sbni_outb(sc, CSR0, sbni_inb(sc, CSR0) & ~TR_REQ);
386 sbni_outb(sc, CSR0, sbni_inb(sc, CSR0) | EN_INT);
391 * Routine returns 1 if it need to acknoweledge received frame.
392 * Empty frame received without errors won't be acknoweledged.
396 recv_frame(struct sbni_softc *sc)
399 u_int framelen, frameno, ack;
400 u_int is_first, frame_ok;
404 if (check_fhdr(sc, &framelen, &frameno, &ack, &is_first, &crc)) {
405 frame_ok = framelen > 4 ?
406 upload_data(sc, framelen, frameno, is_first, crc) :
407 skip_tail(sc, framelen, crc);
409 interpret_ack(sc, ack);
413 sbni_outb(sc, CSR0, sbni_inb(sc, CSR0) ^ CT_ZER);
415 sc->state |= FL_PREV_OK;
417 sc->in_stats.all_rx_number++;
419 sc->state &= ~FL_PREV_OK;
421 sc->in_stats.all_rx_number++;
422 sc->in_stats.bad_rx_number++;
425 return (!frame_ok || framelen > 4);
430 send_frame(struct sbni_softc *sc)
436 if (sc->state & FL_NEED_RESEND) {
438 /* if frame was sended but not ACK'ed - resend it */
439 if (sc->trans_errors) {
441 if (sc->framelen != 0)
442 sc->in_stats.resend_tx_number++;
444 /* cannot xmit with many attempts */
449 sc->trans_errors = TR_ERROR_COUNT;
451 send_frame_header(sc, &crc);
452 sc->state |= FL_NEED_RESEND;
454 * FL_NEED_RESEND will be cleared after ACK, but if empty
455 * frame sended then in prepare_to_send next frame
460 download_data(sc, &crc);
461 sc->in_stats.all_tx_number++;
462 sc->state |= FL_WAIT_ACK;
465 sbni_outsb(sc, (u_char *)&crc, sizeof crc);
468 csr0 = sbni_inb(sc, CSR0);
469 sbni_outb(sc, CSR0, csr0 & ~TR_REQ);
471 if (sc->tx_frameno) {
472 /* next frame exists - request to send */
473 sbni_outb(sc, CSR0, csr0 | TR_REQ);
479 download_data(struct sbni_softc *sc, u_int32_t *crc_p)
483 u_int data_len, pos, slice;
485 data_p = NULL; /* initialized to avoid warn */
488 for (m = sc->tx_buf_p; m != NULL && pos < sc->pktlen; m = m->m_next) {
489 if (pos + m->m_len > sc->outpos) {
490 data_len = m->m_len - (sc->outpos - pos);
491 data_p = mtod(m, caddr_t) + (sc->outpos - pos);
504 slice = min(data_len, sc->framelen - pos);
505 sbni_outsb(sc, data_p, slice);
506 *crc_p = calc_crc32(*crc_p, data_p, slice);
509 if (data_len -= slice)
514 } while (m != NULL && m->m_len == 0);
518 data_p = mtod(m, caddr_t);
522 /* frame too short - zero padding */
524 pos = sc->framelen - pos;
526 sbni_outb(sc, DAT, 0);
527 *crc_p = CRC32(0, *crc_p);
531 } while (pos < sc->framelen);
536 upload_data(struct sbni_softc *sc, u_int framelen, u_int frameno,
537 u_int is_first, u_int32_t crc)
542 sc->wait_frameno = frameno;
546 if (sc->wait_frameno == frameno) {
548 if (sc->inppos + framelen <= ETHER_MAX_LEN) {
549 frame_ok = append_frame_to_pkt(sc, framelen, crc);
552 * if CRC is right but framelen incorrect then transmitter
553 * error was occured... drop entire packet
555 } else if ((frame_ok = skip_tail(sc, framelen, crc)) != 0) {
556 sc->wait_frameno = 0;
558 sc->arpcom.ac_if.if_ierrors++;
559 /* now skip all frames until is_first != 0 */
562 frame_ok = skip_tail(sc, framelen, crc);
564 if (is_first && !frame_ok) {
566 * Frame has been violated, but we have stored
567 * is_first already... Drop entire packet.
569 sc->wait_frameno = 0;
570 sc->arpcom.ac_if.if_ierrors++;
577 static __inline void send_complete(struct sbni_softc *);
580 send_complete(struct sbni_softc *sc)
582 m_freem(sc->tx_buf_p);
584 sc->arpcom.ac_if.if_opackets++;
589 interpret_ack(struct sbni_softc *sc, u_int ack)
591 if (ack == FRAME_SENT_OK) {
592 sc->state &= ~FL_NEED_RESEND;
594 if (sc->state & FL_WAIT_ACK) {
595 sc->outpos += sc->framelen;
597 if (--sc->tx_frameno) {
599 sc->maxframe, sc->pktlen - sc->outpos);
607 sc->state &= ~FL_WAIT_ACK;
612 * Glue received frame with previous fragments of packet.
613 * Indicate packet when last frame would be accepted.
617 append_frame_to_pkt(struct sbni_softc *sc, u_int framelen, u_int32_t crc)
621 if (sc->inppos + framelen > ETHER_MAX_LEN)
624 if (!sc->rx_buf_p && !get_rx_buf(sc))
627 p = sc->rx_buf_p->m_data + sc->inppos;
628 sbni_insb(sc, p, framelen);
629 if (calc_crc32(crc, p, framelen) != CRC32_REMAINDER)
632 sc->inppos += framelen - 4;
633 if (--sc->wait_frameno == 0) { /* last frame received */
635 sc->arpcom.ac_if.if_ipackets++;
643 * Prepare to start output on adapter.
644 * Transmitter will be actually activated when marker has been accepted.
648 prepare_to_send(struct sbni_softc *sc)
653 /* sc->tx_buf_p == NULL here! */
655 kprintf("sbni: memory leak!\n");
658 sc->state &= ~(FL_WAIT_ACK | FL_NEED_RESEND);
661 sc->tx_buf_p = ifq_dequeue(&sc->arpcom.ac_if.if_snd, NULL);
662 if (sc->tx_buf_p == NULL) {
663 /* nothing to transmit... */
667 ifq_clr_oactive(&sc->arpcom.ac_if.if_snd);
671 for (len = 0, m = sc->tx_buf_p; m; m = m->m_next)
676 m_freem(sc->tx_buf_p);
679 if (len < SBNI_MIN_LEN)
683 sc->tx_frameno = (len + sc->maxframe - 1) / sc->maxframe;
684 sc->framelen = min(len, sc->maxframe);
686 sbni_outb(sc, CSR0, sbni_inb(sc, CSR0) | TR_REQ);
687 ifq_set_oactive(&sc->arpcom.ac_if.if_snd);
688 BPF_MTAP(&sc->arpcom.ac_if, sc->tx_buf_p);
693 drop_xmit_queue(struct sbni_softc *sc)
696 m_freem(sc->tx_buf_p);
698 sc->arpcom.ac_if.if_oerrors++;
701 ifq_purge(&sc->arpcom.ac_if.if_snd);
706 sc->state &= ~(FL_WAIT_ACK | FL_NEED_RESEND);
707 ifq_clr_oactive(&sc->arpcom.ac_if.if_snd);
712 send_frame_header(struct sbni_softc *sc, u_int32_t *crc_p)
719 len_field = sc->framelen + 6; /* CRC + frameno + reserved */
721 if (sc->state & FL_NEED_RESEND)
722 len_field |= FRAME_RETRY; /* non-first attempt... */
725 len_field |= FRAME_FIRST;
727 len_field |= (sc->state & FL_PREV_OK) ? FRAME_SENT_OK : FRAME_SENT_BAD;
728 sbni_outb(sc, DAT, SBNI_SIG);
730 value = (u_char)len_field;
731 sbni_outb(sc, DAT, value);
732 crc = CRC32(value, crc);
733 value = (u_char)(len_field >> 8);
734 sbni_outb(sc, DAT, value);
735 crc = CRC32(value, crc);
737 sbni_outb(sc, DAT, sc->tx_frameno);
738 crc = CRC32(sc->tx_frameno, crc);
739 sbni_outb(sc, DAT, 0);
746 * if frame tail not needed (incorrect number or received twice),
747 * it won't store, but CRC will be calculated
751 skip_tail(struct sbni_softc *sc, u_int tail_len, u_int32_t crc)
754 crc = CRC32(sbni_inb(sc, DAT), crc);
756 return (crc == CRC32_REMAINDER);
761 check_fhdr(struct sbni_softc *sc, u_int *framelen, u_int *frameno,
762 u_int *ack, u_int *is_first, u_int32_t *crc_p)
768 if (sbni_inb(sc, DAT) != SBNI_SIG)
771 value = sbni_inb(sc, DAT);
772 *framelen = (u_int)value;
773 crc = CRC32(value, crc);
774 value = sbni_inb(sc, DAT);
775 *framelen |= ((u_int)value) << 8;
776 crc = CRC32(value, crc);
778 *ack = *framelen & FRAME_ACK_MASK;
779 *is_first = (*framelen & FRAME_FIRST) != 0;
781 if ((*framelen &= FRAME_LEN_MASK) < 6 || *framelen > SBNI_MAX_FRAME - 3)
784 value = sbni_inb(sc, DAT);
785 *frameno = (u_int)value;
786 crc = CRC32(value, crc);
788 crc = CRC32(sbni_inb(sc, DAT), crc); /* reserved byte */
797 get_rx_buf(struct sbni_softc *sc)
801 MGETHDR(m, MB_DONTWAIT, MT_DATA);
803 kprintf("%s: cannot allocate header mbuf\n",
804 sc->arpcom.ac_if.if_xname);
809 * We always put the received packet in a single buffer -
810 * either with just an mbuf header or in a cluster attached
811 * to the header. The +2 is to compensate for the alignment
814 if (ETHER_MAX_LEN + 2 > MHLEN) {
815 /* Attach an mbuf cluster */
816 MCLGET(m, MB_DONTWAIT);
817 if ((m->m_flags & M_EXT) == 0) {
822 m->m_pkthdr.len = m->m_len = ETHER_MAX_LEN + 2;
825 * The +2 is to longword align the start of the real packet.
826 * (sizeof ether_header == 14)
827 * This is important for NFS.
836 indicate_pkt(struct sbni_softc *sc)
838 struct ifnet *ifp = &sc->arpcom.ac_if;
842 m->m_pkthdr.rcvif = ifp;
843 m->m_pkthdr.len = m->m_len = sc->inppos;
845 ifp->if_input(ifp, m);
849 /* -------------------------------------------------------------------------- */
852 * Routine checks periodically wire activity and regenerates marker if
853 * connect was inactive for a long time.
857 sbni_timeout(void *xsc)
859 struct sbni_softc *sc = xsc;
862 lwkt_serialize_enter(sc->arpcom.ac_if.if_serializer);
864 csr0 = sbni_inb(sc, CSR0);
867 if (sc->timer_ticks) {
868 if (csr0 & (RC_RDY | BU_EMP))
869 /* receiving not active */
872 sc->in_stats.timeout_number++;
874 timeout_change_level(sc);
876 sbni_outb(sc, CSR1, *(u_char *)&sc->csr1 | PR_RES);
877 csr0 = sbni_inb(sc, CSR0);
881 sbni_outb(sc, CSR0, csr0 | RC_CHK);
882 callout_reset(&sc->sbni_stat_timer, hz / SBNI_HZ, sbni_timeout, sc);
884 lwkt_serialize_exit(sc->arpcom.ac_if.if_serializer);
887 /* -------------------------------------------------------------------------- */
890 card_start(struct sbni_softc *sc)
892 sc->timer_ticks = CHANGE_LEVEL_START_TICKS;
893 sc->state &= ~(FL_WAIT_ACK | FL_NEED_RESEND);
894 sc->state |= FL_PREV_OK;
897 sc->wait_frameno = 0;
899 sbni_outb(sc, CSR1, *(u_char *)&sc->csr1 | PR_RES);
900 sbni_outb(sc, CSR0, EN_INT);
903 /* -------------------------------------------------------------------------- */
906 * Device timeout/watchdog routine. Entered if the device neglects to
907 * generate an interrupt after a transmit has been started on it.
911 sbni_watchdog(struct ifnet *ifp)
913 log(LOG_ERR, "%s: device timeout\n", ifp->if_xname);
918 static u_char rxl_tab[] = {
919 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x08,
920 0x0a, 0x0c, 0x0f, 0x16, 0x18, 0x1a, 0x1c, 0x1f
923 #define SIZE_OF_TIMEOUT_RXL_TAB 4
924 static u_char timeout_rxl_tab[] = {
925 0x03, 0x05, 0x08, 0x0b
929 set_initial_values(struct sbni_softc *sc, struct sbni_flags flags)
931 if (flags.fixed_rxl) {
932 sc->delta_rxl = 0; /* disable receive level autodetection */
933 sc->cur_rxl_index = flags.rxl;
935 sc->delta_rxl = DEF_RXL_DELTA;
936 sc->cur_rxl_index = DEF_RXL;
939 sc->csr1.rate = flags.fixed_rate ? flags.rate : DEFAULT_RATE;
940 sc->csr1.rxl = rxl_tab[sc->cur_rxl_index];
941 sc->maxframe = DEFAULT_FRAME_LEN;
944 * generate Ethernet address (0x00ff01xxxxxx)
946 *(u_int16_t *) sc->arpcom.ac_enaddr = htons(0x00ff);
947 if (flags.mac_addr) {
948 *(u_int32_t *) (sc->arpcom.ac_enaddr + 2) =
949 htonl(flags.mac_addr | 0x01000000);
951 *(u_char *) (sc->arpcom.ac_enaddr + 2) = 0x01;
952 read_random_unlimited(sc->arpcom.ac_enaddr + 3, 3);
957 #ifdef SBNI_DUAL_COMPOUND
960 connect_to_master(struct sbni_softc *sc)
962 struct sbni_softc *p, *p_prev;
964 for (p = sbni_headlist, p_prev = NULL; p; p_prev = p, p = p->link) {
965 if (rman_get_start(p->io_res) == rman_get_start(sc->io_res) + 4 ||
966 rman_get_start(p->io_res) == rman_get_start(sc->io_res) - 4) {
969 p_prev->link = p->link;
971 sbni_headlist = p->link;
979 #endif /* SBNI_DUAL_COMPOUND */
982 /* Receive level auto-selection */
985 change_level(struct sbni_softc *sc)
987 if (sc->delta_rxl == 0) /* do not auto-negotiate RxL */
990 if (sc->cur_rxl_index == 0)
992 else if (sc->cur_rxl_index == 15)
994 else if (sc->cur_rxl_rcvd < sc->prev_rxl_rcvd)
995 sc->delta_rxl = -sc->delta_rxl;
997 sc->csr1.rxl = rxl_tab[sc->cur_rxl_index += sc->delta_rxl];
998 sbni_inb(sc, CSR0); /* it needed for PCI cards */
999 sbni_outb(sc, CSR1, *(u_char *)&sc->csr1);
1001 sc->prev_rxl_rcvd = sc->cur_rxl_rcvd;
1002 sc->cur_rxl_rcvd = 0;
1007 timeout_change_level(struct sbni_softc *sc)
1009 sc->cur_rxl_index = timeout_rxl_tab[sc->timeout_rxl];
1010 if (++sc->timeout_rxl >= 4)
1011 sc->timeout_rxl = 0;
1013 sc->csr1.rxl = rxl_tab[sc->cur_rxl_index];
1015 sbni_outb(sc, CSR1, *(u_char *)&sc->csr1);
1017 sc->prev_rxl_rcvd = sc->cur_rxl_rcvd;
1018 sc->cur_rxl_rcvd = 0;
1021 /* -------------------------------------------------------------------------- */
1024 * Process an ioctl request. This code needs some work - it looks
1029 sbni_ioctl(struct ifnet *ifp, u_long command, caddr_t data, struct ucred *cr)
1031 struct sbni_softc *sc;
1033 struct sbni_in_stats *in_stats;
1034 struct sbni_flags flags;
1038 ifr = (struct ifreq *)data;
1044 * If the interface is marked up and stopped, then start it.
1045 * If it is marked down and running, then stop it.
1047 if (ifp->if_flags & IFF_UP) {
1048 if (!(ifp->if_flags & IFF_RUNNING))
1051 if (ifp->if_flags & IFF_RUNNING) {
1053 ifp->if_flags &= ~IFF_RUNNING;
1061 * Multicast list has changed; set the hardware filter
1066 error = EAFNOSUPPORT; */
1070 if (ifr->ifr_mtu > ETHERMTU)
1073 ifp->if_mtu = ifr->ifr_mtu;
1077 * SBNI specific ioctl
1079 case SIOCGHWFLAGS: /* get flags */
1080 bcopy((caddr_t) sc->arpcom.ac_enaddr+3, (caddr_t) &flags, 3);
1081 flags.rxl = sc->cur_rxl_index;
1082 flags.rate = sc->csr1.rate;
1083 flags.fixed_rxl = (sc->delta_rxl == 0);
1084 flags.fixed_rate = 1;
1085 ifr->ifr_data = *(caddr_t*) &flags;
1089 in_stats = (struct sbni_in_stats *)ifr->ifr_data;
1090 bcopy((void *)(&(sc->in_stats)), (void *)in_stats,
1091 sizeof(struct sbni_in_stats));
1094 case SIOCSHWFLAGS: /* set flags */
1096 error = priv_check_cred(cr, PRIV_ROOT, NULL_CRED_OKAY);
1097 /* NOTE: returns EPERM if no proc */
1100 flags = *(struct sbni_flags*)&ifr->ifr_data;
1101 if (flags.fixed_rxl) {
1103 sc->cur_rxl_index = flags.rxl;
1105 sc->delta_rxl = DEF_RXL_DELTA;
1106 sc->cur_rxl_index = DEF_RXL;
1108 sc->csr1.rxl = rxl_tab[sc->cur_rxl_index];
1109 sc->csr1.rate = flags.fixed_rate ? flags.rate : DEFAULT_RATE;
1111 bcopy((caddr_t) &flags,
1112 (caddr_t) sc->arpcom.ac_enaddr+3, 3);
1114 /* Don't be afraid... */
1115 sbni_outb(sc, CSR1, *(char*)(&sc->csr1) | PR_RES);
1119 if (!(error = priv_check_cred(cr, PRIV_ROOT, NULL_CRED_OKAY))) /* root only */
1120 bzero(&sc->in_stats, sizeof(struct sbni_in_stats));
1124 error = ether_ioctl(ifp, command, data);
1130 /* -------------------------------------------------------------------------- */
1135 calc_crc32(u_int32_t crc, caddr_t p, u_int len)
1141 "xorl %%ebx, %%ebx\n"
1144 "movl $crc32tab, %%edi\n"
1151 "movl (%%esi), %%edx\n"
1155 "xorl (%%edi,%%ebx,4), %%eax\n"
1161 "xorl (%%edi,%%ebx,4), %%eax\n"
1167 "xorl (%%edi,%%ebx,4), %%eax\n"
1173 "xorl (%%edi,%%ebx,4), %%eax\n"
1185 "xorb (%%esi), %%bl\n"
1186 "xorl (%%edi,%%ebx,4), %%eax\n"
1193 "xorb 1(%%esi), %%bl\n"
1194 "xorl (%%edi,%%ebx,4), %%eax\n"
1201 "xorb 2(%%esi), %%bl\n"
1202 "xorl (%%edi,%%ebx,4), %%eax\n"
1205 : "a" (_crc), "g" (p), "g" (len)
1206 : "bx", "cx", "dx", "si", "di"
1215 calc_crc32(u_int32_t crc, caddr_t p, u_int len)
1218 crc = CRC32(*p++, crc);
1223 #endif /* ASM_CRC */
1226 static u_int32_t crc32tab[] __attribute__ ((aligned(8))) = {
1227 0xD202EF8D, 0xA505DF1B, 0x3C0C8EA1, 0x4B0BBE37,
1228 0xD56F2B94, 0xA2681B02, 0x3B614AB8, 0x4C667A2E,
1229 0xDCD967BF, 0xABDE5729, 0x32D70693, 0x45D03605,
1230 0xDBB4A3A6, 0xACB39330, 0x35BAC28A, 0x42BDF21C,
1231 0xCFB5FFE9, 0xB8B2CF7F, 0x21BB9EC5, 0x56BCAE53,
1232 0xC8D83BF0, 0xBFDF0B66, 0x26D65ADC, 0x51D16A4A,
1233 0xC16E77DB, 0xB669474D, 0x2F6016F7, 0x58672661,
1234 0xC603B3C2, 0xB1048354, 0x280DD2EE, 0x5F0AE278,
1235 0xE96CCF45, 0x9E6BFFD3, 0x0762AE69, 0x70659EFF,
1236 0xEE010B5C, 0x99063BCA, 0x000F6A70, 0x77085AE6,
1237 0xE7B74777, 0x90B077E1, 0x09B9265B, 0x7EBE16CD,
1238 0xE0DA836E, 0x97DDB3F8, 0x0ED4E242, 0x79D3D2D4,
1239 0xF4DBDF21, 0x83DCEFB7, 0x1AD5BE0D, 0x6DD28E9B,
1240 0xF3B61B38, 0x84B12BAE, 0x1DB87A14, 0x6ABF4A82,
1241 0xFA005713, 0x8D076785, 0x140E363F, 0x630906A9,
1242 0xFD6D930A, 0x8A6AA39C, 0x1363F226, 0x6464C2B0,
1243 0xA4DEAE1D, 0xD3D99E8B, 0x4AD0CF31, 0x3DD7FFA7,
1244 0xA3B36A04, 0xD4B45A92, 0x4DBD0B28, 0x3ABA3BBE,
1245 0xAA05262F, 0xDD0216B9, 0x440B4703, 0x330C7795,
1246 0xAD68E236, 0xDA6FD2A0, 0x4366831A, 0x3461B38C,
1247 0xB969BE79, 0xCE6E8EEF, 0x5767DF55, 0x2060EFC3,
1248 0xBE047A60, 0xC9034AF6, 0x500A1B4C, 0x270D2BDA,
1249 0xB7B2364B, 0xC0B506DD, 0x59BC5767, 0x2EBB67F1,
1250 0xB0DFF252, 0xC7D8C2C4, 0x5ED1937E, 0x29D6A3E8,
1251 0x9FB08ED5, 0xE8B7BE43, 0x71BEEFF9, 0x06B9DF6F,
1252 0x98DD4ACC, 0xEFDA7A5A, 0x76D32BE0, 0x01D41B76,
1253 0x916B06E7, 0xE66C3671, 0x7F6567CB, 0x0862575D,
1254 0x9606C2FE, 0xE101F268, 0x7808A3D2, 0x0F0F9344,
1255 0x82079EB1, 0xF500AE27, 0x6C09FF9D, 0x1B0ECF0B,
1256 0x856A5AA8, 0xF26D6A3E, 0x6B643B84, 0x1C630B12,
1257 0x8CDC1683, 0xFBDB2615, 0x62D277AF, 0x15D54739,
1258 0x8BB1D29A, 0xFCB6E20C, 0x65BFB3B6, 0x12B88320,
1259 0x3FBA6CAD, 0x48BD5C3B, 0xD1B40D81, 0xA6B33D17,
1260 0x38D7A8B4, 0x4FD09822, 0xD6D9C998, 0xA1DEF90E,
1261 0x3161E49F, 0x4666D409, 0xDF6F85B3, 0xA868B525,
1262 0x360C2086, 0x410B1010, 0xD80241AA, 0xAF05713C,
1263 0x220D7CC9, 0x550A4C5F, 0xCC031DE5, 0xBB042D73,
1264 0x2560B8D0, 0x52678846, 0xCB6ED9FC, 0xBC69E96A,
1265 0x2CD6F4FB, 0x5BD1C46D, 0xC2D895D7, 0xB5DFA541,
1266 0x2BBB30E2, 0x5CBC0074, 0xC5B551CE, 0xB2B26158,
1267 0x04D44C65, 0x73D37CF3, 0xEADA2D49, 0x9DDD1DDF,
1268 0x03B9887C, 0x74BEB8EA, 0xEDB7E950, 0x9AB0D9C6,
1269 0x0A0FC457, 0x7D08F4C1, 0xE401A57B, 0x930695ED,
1270 0x0D62004E, 0x7A6530D8, 0xE36C6162, 0x946B51F4,
1271 0x19635C01, 0x6E646C97, 0xF76D3D2D, 0x806A0DBB,
1272 0x1E0E9818, 0x6909A88E, 0xF000F934, 0x8707C9A2,
1273 0x17B8D433, 0x60BFE4A5, 0xF9B6B51F, 0x8EB18589,
1274 0x10D5102A, 0x67D220BC, 0xFEDB7106, 0x89DC4190,
1275 0x49662D3D, 0x3E611DAB, 0xA7684C11, 0xD06F7C87,
1276 0x4E0BE924, 0x390CD9B2, 0xA0058808, 0xD702B89E,
1277 0x47BDA50F, 0x30BA9599, 0xA9B3C423, 0xDEB4F4B5,
1278 0x40D06116, 0x37D75180, 0xAEDE003A, 0xD9D930AC,
1279 0x54D13D59, 0x23D60DCF, 0xBADF5C75, 0xCDD86CE3,
1280 0x53BCF940, 0x24BBC9D6, 0xBDB2986C, 0xCAB5A8FA,
1281 0x5A0AB56B, 0x2D0D85FD, 0xB404D447, 0xC303E4D1,
1282 0x5D677172, 0x2A6041E4, 0xB369105E, 0xC46E20C8,
1283 0x72080DF5, 0x050F3D63, 0x9C066CD9, 0xEB015C4F,
1284 0x7565C9EC, 0x0262F97A, 0x9B6BA8C0, 0xEC6C9856,
1285 0x7CD385C7, 0x0BD4B551, 0x92DDE4EB, 0xE5DAD47D,
1286 0x7BBE41DE, 0x0CB97148, 0x95B020F2, 0xE2B71064,
1287 0x6FBF1D91, 0x18B82D07, 0x81B17CBD, 0xF6B64C2B,
1288 0x68D2D988, 0x1FD5E91E, 0x86DCB8A4, 0xF1DB8832,
1289 0x616495A3, 0x1663A535, 0x8F6AF48F, 0xF86DC419,
1290 0x660951BA, 0x110E612C, 0x88073096, 0xFF000000