Deleted Added
full compact
if_sbni.c (117433) if_sbni.c (119419)
1/*
2 * Copyright (c) 1997-2001 Granch, Ltd. All rights reserved.
3 * Author: Denis I.Timofeev <timofeev@granch.ru>
4 *
5 * Redistributon and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice unmodified, this list of conditions, and the following
10 * disclaimer.
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.
14 *
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
25 * SUCH DAMAGE.
26 *
1/*
2 * Copyright (c) 1997-2001 Granch, Ltd. All rights reserved.
3 * Author: Denis I.Timofeev <timofeev@granch.ru>
4 *
5 * Redistributon and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice unmodified, this list of conditions, and the following
10 * disclaimer.
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.
14 *
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
25 * SUCH DAMAGE.
26 *
27 * $FreeBSD: head/sys/dev/sbni/if_sbni.c 117433 2003-07-11 07:49:40Z kan $
28 */
29
27 */
28
29#include <sys/cdefs.h>
30__FBSDID("$FreeBSD: head/sys/dev/sbni/if_sbni.c 119419 2003-08-24 18:03:45Z obrien $");
31
30/*
31 * Device driver for Granch SBNI12 leased line adapters
32 *
33 * Revision 2.0.0 1997/08/06
34 * Initial revision by Alexey Zverev
35 *
36 * Revision 2.0.1 1997/08/11
37 * Additional internal statistics support (tx statistics)
38 *
39 * Revision 2.0.2 1997/11/05
40 * if_bpf bug has been fixed
41 *
42 * Revision 2.0.3 1998/12/20
43 * Memory leakage has been eliminated in
44 * the sbni_st and sbni_timeout routines.
45 *
46 * Revision 3.0 2000/08/10 by Yaroslav Polyakov
47 * Support for PCI cards. 4.1 modification.
48 *
49 * Revision 3.1 2000/09/12
50 * Removed extra #defines around bpf functions
51 *
52 * Revision 4.0 2000/11/23 by Denis Timofeev
53 * Completely redesigned the buffer management
54 *
55 * Revision 4.1 2001/01/21
56 * Support for PCI Dual cards and new SBNI12D-10, -11 Dual/ISA cards
57 *
58 * Written with reference to NE2000 driver developed by David Greenman.
59 */
60
61
62#include <sys/param.h>
63#include <sys/systm.h>
64#include <sys/socket.h>
65#include <sys/sockio.h>
66#include <sys/mbuf.h>
67#include <sys/kernel.h>
68#include <sys/proc.h>
69#include <sys/callout.h>
70#include <sys/syslog.h>
71#include <sys/random.h>
72
73#include <machine/bus.h>
74#include <sys/rman.h>
75#include <machine/resource.h>
76
77#include <net/if.h>
78#include <net/ethernet.h>
79#include <net/if_arp.h>
80#include <net/bpf.h>
81
82#include <dev/sbni/if_sbnireg.h>
83#include <dev/sbni/if_sbnivar.h>
84
85#define ASM_CRC 1
86
87static void sbni_init(void *);
88static void sbni_start(struct ifnet *);
89static int sbni_ioctl(struct ifnet *, u_long, caddr_t);
90static void sbni_watchdog(struct ifnet *);
91static void sbni_stop(struct sbni_softc *);
92static void handle_channel(struct sbni_softc *);
93
94static void card_start(struct sbni_softc *);
95static int recv_frame(struct sbni_softc *);
96static void send_frame(struct sbni_softc *);
97static int upload_data(struct sbni_softc *, u_int, u_int, u_int, u_int32_t);
98static int skip_tail(struct sbni_softc *, u_int, u_int32_t);
99static void interpret_ack(struct sbni_softc *, u_int);
100static void download_data(struct sbni_softc *, u_int32_t *);
101static void prepare_to_send(struct sbni_softc *);
102static void drop_xmit_queue(struct sbni_softc *);
103static int get_rx_buf(struct sbni_softc *);
104static void indicate_pkt(struct sbni_softc *);
105static void change_level(struct sbni_softc *);
106static int check_fhdr(struct sbni_softc *, u_int *, u_int *,
107 u_int *, u_int *, u_int32_t *);
108static int append_frame_to_pkt(struct sbni_softc *, u_int, u_int32_t);
109static void timeout_change_level(struct sbni_softc *);
110static void send_frame_header(struct sbni_softc *, u_int32_t *);
111static void set_initial_values(struct sbni_softc *, struct sbni_flags);
112
113static u_int32_t calc_crc32(u_int32_t, caddr_t, u_int);
114static timeout_t sbni_timeout;
115
116static __inline u_char sbni_inb(struct sbni_softc *, enum sbni_reg);
117static __inline void sbni_outb(struct sbni_softc *, enum sbni_reg, u_char);
118static __inline void sbni_insb(struct sbni_softc *, u_char *, u_int);
119static __inline void sbni_outsb(struct sbni_softc *, u_char *, u_int);
120
121static u_int32_t crc32tab[];
122
123#ifdef SBNI_DUAL_COMPOUND
124struct sbni_softc *sbni_headlist;
125#endif
126
127u_int32_t next_sbni_unit;
128
129/* -------------------------------------------------------------------------- */
130
131static __inline u_char
132sbni_inb(struct sbni_softc *sc, enum sbni_reg reg)
133{
134 return bus_space_read_1(
135 rman_get_bustag(sc->io_res),
136 rman_get_bushandle(sc->io_res),
137 sc->io_off + reg);
138}
139
140static __inline void
141sbni_outb(struct sbni_softc *sc, enum sbni_reg reg, u_char value)
142{
143 bus_space_write_1(
144 rman_get_bustag(sc->io_res),
145 rman_get_bushandle(sc->io_res),
146 sc->io_off + reg, value);
147}
148
149static __inline void
150sbni_insb(struct sbni_softc *sc, u_char *to, u_int len)
151{
152 bus_space_read_multi_1(
153 rman_get_bustag(sc->io_res),
154 rman_get_bushandle(sc->io_res),
155 sc->io_off + DAT, to, len);
156}
157
158static __inline void
159sbni_outsb(struct sbni_softc *sc, u_char *from, u_int len)
160{
161 bus_space_write_multi_1(
162 rman_get_bustag(sc->io_res),
163 rman_get_bushandle(sc->io_res),
164 sc->io_off + DAT, from, len);
165}
166
167
168/*
169 Valid combinations in CSR0 (for probing):
170
171 VALID_DECODER 0000,0011,1011,1010
172
173 ; 0 ; -
174 TR_REQ ; 1 ; +
175 TR_RDY ; 2 ; -
176 TR_RDY TR_REQ ; 3 ; +
177 BU_EMP ; 4 ; +
178 BU_EMP TR_REQ ; 5 ; +
179 BU_EMP TR_RDY ; 6 ; -
180 BU_EMP TR_RDY TR_REQ ; 7 ; +
181 RC_RDY ; 8 ; +
182 RC_RDY TR_REQ ; 9 ; +
183 RC_RDY TR_RDY ; 10 ; -
184 RC_RDY TR_RDY TR_REQ ; 11 ; -
185 RC_RDY BU_EMP ; 12 ; -
186 RC_RDY BU_EMP TR_REQ ; 13 ; -
187 RC_RDY BU_EMP TR_RDY ; 14 ; -
188 RC_RDY BU_EMP TR_RDY TR_REQ ; 15 ; -
189*/
190
191#define VALID_DECODER (2 + 8 + 0x10 + 0x20 + 0x80 + 0x100 + 0x200)
192
193
194int
195sbni_probe(struct sbni_softc *sc)
196{
197 u_char csr0;
198
199 csr0 = sbni_inb(sc, CSR0);
200 if (csr0 != 0xff && csr0 != 0x00) {
201 csr0 &= ~EN_INT;
202 if (csr0 & BU_EMP)
203 csr0 |= EN_INT;
204
205 if (VALID_DECODER & (1 << (csr0 >> 4)))
206 return (0);
207 }
208
209 return (ENXIO);
210}
211
212
213/*
214 * Install interface into kernel networking data structures
215 */
216void
217sbni_attach(struct sbni_softc *sc, int unit, struct sbni_flags flags)
218{
219 struct ifnet *ifp;
220 u_char csr0;
221
222 ifp = &sc->arpcom.ac_if;
223 sbni_outb(sc, CSR0, 0);
224 set_initial_values(sc, flags);
225
226 callout_handle_init(&sc->wch);
227 if (!ifp->if_name) {
228 /* Initialize ifnet structure */
229 ifp->if_softc = sc;
230 ifp->if_unit = unit;
231 ifp->if_name = "sbni";
232 ifp->if_init = sbni_init;
233 ifp->if_start = sbni_start;
234 ifp->if_output = ether_output;
235 ifp->if_ioctl = sbni_ioctl;
236 ifp->if_watchdog = sbni_watchdog;
237 ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
238
239 /* report real baud rate */
240 csr0 = sbni_inb(sc, CSR0);
241 ifp->if_baudrate =
242 (csr0 & 0x01 ? 500000 : 2000000) / (1 << flags.rate);
243
244 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
245 ether_ifattach(ifp, sc->arpcom.ac_enaddr);
246 }
247 /* device attach does transition from UNCONFIGURED to IDLE state */
248
249 if_printf(ifp, "speed %ld, address %6D, rxl ",
250 ifp->if_baudrate, sc->arpcom.ac_enaddr, ":");
251 if (sc->delta_rxl)
252 printf("auto\n");
253 else
254 printf("%d (fixed)\n", sc->cur_rxl_index);
255}
256
257/* -------------------------------------------------------------------------- */
258
259static void
260sbni_init(void *xsc)
261{
262 struct sbni_softc *sc;
263 struct ifnet *ifp;
264 int s;
265
266 sc = (struct sbni_softc *)xsc;
267 ifp = &sc->arpcom.ac_if;
268
269 /* address not known */
270 if (TAILQ_EMPTY(&ifp->if_addrhead))
271 return;
272
273 /*
274 * kludge to avoid multiple initialization when more than once
275 * protocols configured
276 */
277 if (ifp->if_flags & IFF_RUNNING)
278 return;
279
280 s = splimp();
281 ifp->if_timer = 0;
282 card_start(sc);
283 sc->wch = timeout(sbni_timeout, sc, hz/SBNI_HZ);
284
285 ifp->if_flags |= IFF_RUNNING;
286 ifp->if_flags &= ~IFF_OACTIVE;
287
288 /* attempt to start output */
289 sbni_start(ifp);
290 splx(s);
291}
292
293
294static void
295sbni_start(struct ifnet *ifp)
296{
297 struct sbni_softc *sc = ifp->if_softc;
298 if (sc->tx_frameno == 0)
299 prepare_to_send(sc);
300}
301
302
303static void
304sbni_stop(struct sbni_softc *sc)
305{
306 sbni_outb(sc, CSR0, 0);
307 drop_xmit_queue(sc);
308
309 if (sc->rx_buf_p) {
310 m_freem(sc->rx_buf_p);
311 sc->rx_buf_p = NULL;
312 }
313
314 untimeout(sbni_timeout, sc, sc->wch);
315 sc->wch.callout = NULL;
316}
317
318/* -------------------------------------------------------------------------- */
319
320/* interrupt handler */
321
322/*
323 * SBNI12D-10, -11/ISA boards within "common interrupt" mode could not
324 * be looked as two independent single-channel devices. Every channel seems
325 * as Ethernet interface but interrupt handler must be common. Really, first
326 * channel ("master") driver only registers the handler. In it's struct softc
327 * it has got pointer to "slave" channel's struct softc and handles that's
328 * interrupts too.
329 * softc of successfully attached ISA SBNI boards is linked to list.
330 * While next board driver is initialized, it scans this list. If one
331 * has found softc with same irq and ioaddr different by 4 then it assumes
332 * this board to be "master".
333 */
334
335void
336sbni_intr(void *arg)
337{
338 struct sbni_softc *sc;
339 int repeat;
340
341 sc = (struct sbni_softc *)arg;
342
343 do {
344 repeat = 0;
345 if (sbni_inb(sc, CSR0) & (RC_RDY | TR_RDY)) {
346 handle_channel(sc);
347 repeat = 1;
348 }
349 if (sc->slave_sc && /* second channel present */
350 (sbni_inb(sc->slave_sc, CSR0) & (RC_RDY | TR_RDY))) {
351 handle_channel(sc->slave_sc);
352 repeat = 1;
353 }
354 } while (repeat);
355}
356
357
358static void
359handle_channel(struct sbni_softc *sc)
360{
361 int req_ans;
362 u_char csr0;
363
364 sbni_outb(sc, CSR0, (sbni_inb(sc, CSR0) & ~EN_INT) | TR_REQ);
365
366 sc->timer_ticks = CHANGE_LEVEL_START_TICKS;
367 for (;;) {
368 csr0 = sbni_inb(sc, CSR0);
369 if ((csr0 & (RC_RDY | TR_RDY)) == 0)
370 break;
371
372 req_ans = !(sc->state & FL_PREV_OK);
373
374 if (csr0 & RC_RDY)
375 req_ans = recv_frame(sc);
376
377 /*
378 * TR_RDY always equals 1 here because we have owned the marker,
379 * and we set TR_REQ when disabled interrupts
380 */
381 csr0 = sbni_inb(sc, CSR0);
382 if ((csr0 & TR_RDY) == 0 || (csr0 & RC_RDY) != 0)
383 printf("sbni: internal error!\n");
384
385 /* if state & FL_NEED_RESEND != 0 then tx_frameno != 0 */
386 if (req_ans || sc->tx_frameno != 0)
387 send_frame(sc);
388 else {
389 /* send the marker without any data */
390 sbni_outb(sc, CSR0, sbni_inb(sc, CSR0) & ~TR_REQ);
391 }
392 }
393
394 sbni_outb(sc, CSR0, sbni_inb(sc, CSR0) | EN_INT);
395}
396
397
398/*
399 * Routine returns 1 if it need to acknoweledge received frame.
400 * Empty frame received without errors won't be acknoweledged.
401 */
402
403static int
404recv_frame(struct sbni_softc *sc)
405{
406 u_int32_t crc;
407 u_int framelen, frameno, ack;
408 u_int is_first, frame_ok;
409
410 crc = CRC32_INITIAL;
411 if (check_fhdr(sc, &framelen, &frameno, &ack, &is_first, &crc)) {
412 frame_ok = framelen > 4 ?
413 upload_data(sc, framelen, frameno, is_first, crc) :
414 skip_tail(sc, framelen, crc);
415 if (frame_ok)
416 interpret_ack(sc, ack);
417 } else
418 frame_ok = 0;
419
420 sbni_outb(sc, CSR0, sbni_inb(sc, CSR0) ^ CT_ZER);
421 if (frame_ok) {
422 sc->state |= FL_PREV_OK;
423 if (framelen > 4)
424 sc->in_stats.all_rx_number++;
425 } else {
426 sc->state &= ~FL_PREV_OK;
427 change_level(sc);
428 sc->in_stats.all_rx_number++;
429 sc->in_stats.bad_rx_number++;
430 }
431
432 return (!frame_ok || framelen > 4);
433}
434
435
436static void
437send_frame(struct sbni_softc *sc)
438{
439 u_int32_t crc;
440 u_char csr0;
441
442 crc = CRC32_INITIAL;
443 if (sc->state & FL_NEED_RESEND) {
444
445 /* if frame was sended but not ACK'ed - resend it */
446 if (sc->trans_errors) {
447 sc->trans_errors--;
448 if (sc->framelen != 0)
449 sc->in_stats.resend_tx_number++;
450 } else {
451 /* cannot xmit with many attempts */
452 drop_xmit_queue(sc);
453 goto do_send;
454 }
455 } else
456 sc->trans_errors = TR_ERROR_COUNT;
457
458 send_frame_header(sc, &crc);
459 sc->state |= FL_NEED_RESEND;
460 /*
461 * FL_NEED_RESEND will be cleared after ACK, but if empty
462 * frame sended then in prepare_to_send next frame
463 */
464
465
466 if (sc->framelen) {
467 download_data(sc, &crc);
468 sc->in_stats.all_tx_number++;
469 sc->state |= FL_WAIT_ACK;
470 }
471
472 sbni_outsb(sc, (u_char *)&crc, sizeof crc);
473
474do_send:
475 csr0 = sbni_inb(sc, CSR0);
476 sbni_outb(sc, CSR0, csr0 & ~TR_REQ);
477
478 if (sc->tx_frameno) {
479 /* next frame exists - request to send */
480 sbni_outb(sc, CSR0, csr0 | TR_REQ);
481 }
482}
483
484
485static void
486download_data(struct sbni_softc *sc, u_int32_t *crc_p)
487{
488 struct mbuf *m;
489 caddr_t data_p;
490 u_int data_len, pos, slice;
491
492 data_p = NULL; /* initialized to avoid warn */
493 pos = 0;
494
495 for (m = sc->tx_buf_p; m != NULL && pos < sc->pktlen; m = m->m_next) {
496 if (pos + m->m_len > sc->outpos) {
497 data_len = m->m_len - (sc->outpos - pos);
498 data_p = mtod(m, caddr_t) + (sc->outpos - pos);
499
500 goto do_copy;
501 } else
502 pos += m->m_len;
503 }
504
505 data_len = 0;
506
507do_copy:
508 pos = 0;
509 do {
510 if (data_len) {
511 slice = min(data_len, sc->framelen - pos);
512 sbni_outsb(sc, data_p, slice);
513 *crc_p = calc_crc32(*crc_p, data_p, slice);
514
515 pos += slice;
516 if (data_len -= slice)
517 data_p += slice;
518 else {
519 do {
520 m = m->m_next;
521 } while (m != NULL && m->m_len == 0);
522
523 if (m) {
524 data_len = m->m_len;
525 data_p = mtod(m, caddr_t);
526 }
527 }
528 } else {
529 /* frame too short - zero padding */
530
531 pos = sc->framelen - pos;
532 while (pos--) {
533 sbni_outb(sc, DAT, 0);
534 *crc_p = CRC32(0, *crc_p);
535 }
536 return;
537 }
538 } while (pos < sc->framelen);
539}
540
541
542static int
543upload_data(struct sbni_softc *sc, u_int framelen, u_int frameno,
544 u_int is_first, u_int32_t crc)
545{
546 int frame_ok;
547
548 if (is_first) {
549 sc->wait_frameno = frameno;
550 sc->inppos = 0;
551 }
552
553 if (sc->wait_frameno == frameno) {
554
555 if (sc->inppos + framelen <= ETHER_MAX_LEN) {
556 frame_ok = append_frame_to_pkt(sc, framelen, crc);
557
558 /*
559 * if CRC is right but framelen incorrect then transmitter
560 * error was occured... drop entire packet
561 */
562 } else if ((frame_ok = skip_tail(sc, framelen, crc)) != 0) {
563 sc->wait_frameno = 0;
564 sc->inppos = 0;
565 sc->arpcom.ac_if.if_ierrors++;
566 /* now skip all frames until is_first != 0 */
567 }
568 } else
569 frame_ok = skip_tail(sc, framelen, crc);
570
571 if (is_first && !frame_ok) {
572 /*
573 * Frame has been violated, but we have stored
574 * is_first already... Drop entire packet.
575 */
576 sc->wait_frameno = 0;
577 sc->arpcom.ac_if.if_ierrors++;
578 }
579
580 return (frame_ok);
581}
582
583
584static __inline void send_complete(struct sbni_softc *);
585
586static __inline void
587send_complete(struct sbni_softc *sc)
588{
589 m_freem(sc->tx_buf_p);
590 sc->tx_buf_p = NULL;
591 sc->arpcom.ac_if.if_opackets++;
592}
593
594
595static void
596interpret_ack(struct sbni_softc *sc, u_int ack)
597{
598 if (ack == FRAME_SENT_OK) {
599 sc->state &= ~FL_NEED_RESEND;
600
601 if (sc->state & FL_WAIT_ACK) {
602 sc->outpos += sc->framelen;
603
604 if (--sc->tx_frameno) {
605 sc->framelen = min(
606 sc->maxframe, sc->pktlen - sc->outpos);
607 } else {
608 send_complete(sc);
609 prepare_to_send(sc);
610 }
611 }
612 }
613
614 sc->state &= ~FL_WAIT_ACK;
615}
616
617
618/*
619 * Glue received frame with previous fragments of packet.
620 * Indicate packet when last frame would be accepted.
621 */
622
623static int
624append_frame_to_pkt(struct sbni_softc *sc, u_int framelen, u_int32_t crc)
625{
626 caddr_t p;
627
628 if (sc->inppos + framelen > ETHER_MAX_LEN)
629 return (0);
630
631 if (!sc->rx_buf_p && !get_rx_buf(sc))
632 return (0);
633
634 p = sc->rx_buf_p->m_data + sc->inppos;
635 sbni_insb(sc, p, framelen);
636 if (calc_crc32(crc, p, framelen) != CRC32_REMAINDER)
637 return (0);
638
639 sc->inppos += framelen - 4;
640 if (--sc->wait_frameno == 0) { /* last frame received */
641 indicate_pkt(sc);
642 sc->arpcom.ac_if.if_ipackets++;
643 }
644
645 return (1);
646}
647
648
649/*
650 * Prepare to start output on adapter. Current priority must be set to splimp
651 * before this routine is called.
652 * Transmitter will be actually activated when marker has been accepted.
653 */
654
655static void
656prepare_to_send(struct sbni_softc *sc)
657{
658 struct mbuf *m;
659 u_int len;
660
661 /* sc->tx_buf_p == NULL here! */
662 if (sc->tx_buf_p)
663 printf("sbni: memory leak!\n");
664
665 sc->outpos = 0;
666 sc->state &= ~(FL_WAIT_ACK | FL_NEED_RESEND);
667
668 for (;;) {
669 IF_DEQUEUE(&sc->arpcom.ac_if.if_snd, sc->tx_buf_p);
670 if (!sc->tx_buf_p) {
671 /* nothing to transmit... */
672 sc->pktlen = 0;
673 sc->tx_frameno = 0;
674 sc->framelen = 0;
675 sc->arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
676 return;
677 }
678
679 for (len = 0, m = sc->tx_buf_p; m; m = m->m_next)
680 len += m->m_len;
681
682 if (len != 0)
683 break;
684 m_freem(sc->tx_buf_p);
685 }
686
687 if (len < SBNI_MIN_LEN)
688 len = SBNI_MIN_LEN;
689
690 sc->pktlen = len;
691 sc->tx_frameno = (len + sc->maxframe - 1) / sc->maxframe;
692 sc->framelen = min(len, sc->maxframe);
693
694 sbni_outb(sc, CSR0, sbni_inb(sc, CSR0) | TR_REQ);
695 sc->arpcom.ac_if.if_flags |= IFF_OACTIVE;
696 BPF_MTAP(&sc->arpcom.ac_if, sc->tx_buf_p);
697}
698
699
700static void
701drop_xmit_queue(struct sbni_softc *sc)
702{
703 struct mbuf *m;
704
705 if (sc->tx_buf_p) {
706 m_freem(sc->tx_buf_p);
707 sc->tx_buf_p = NULL;
708 sc->arpcom.ac_if.if_oerrors++;
709 }
710
711 for (;;) {
712 IF_DEQUEUE(&sc->arpcom.ac_if.if_snd, m);
713 if (m == NULL)
714 break;
715 m_freem(m);
716 sc->arpcom.ac_if.if_oerrors++;
717 }
718
719 sc->tx_frameno = 0;
720 sc->framelen = 0;
721 sc->outpos = 0;
722 sc->state &= ~(FL_WAIT_ACK | FL_NEED_RESEND);
723 sc->arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
724}
725
726
727static void
728send_frame_header(struct sbni_softc *sc, u_int32_t *crc_p)
729{
730 u_int32_t crc;
731 u_int len_field;
732 u_char value;
733
734 crc = *crc_p;
735 len_field = sc->framelen + 6; /* CRC + frameno + reserved */
736
737 if (sc->state & FL_NEED_RESEND)
738 len_field |= FRAME_RETRY; /* non-first attempt... */
739
740 if (sc->outpos == 0)
741 len_field |= FRAME_FIRST;
742
743 len_field |= (sc->state & FL_PREV_OK) ? FRAME_SENT_OK : FRAME_SENT_BAD;
744 sbni_outb(sc, DAT, SBNI_SIG);
745
746 value = (u_char)len_field;
747 sbni_outb(sc, DAT, value);
748 crc = CRC32(value, crc);
749 value = (u_char)(len_field >> 8);
750 sbni_outb(sc, DAT, value);
751 crc = CRC32(value, crc);
752
753 sbni_outb(sc, DAT, sc->tx_frameno);
754 crc = CRC32(sc->tx_frameno, crc);
755 sbni_outb(sc, DAT, 0);
756 crc = CRC32(0, crc);
757 *crc_p = crc;
758}
759
760
761/*
762 * if frame tail not needed (incorrect number or received twice),
763 * it won't store, but CRC will be calculated
764 */
765
766static int
767skip_tail(struct sbni_softc *sc, u_int tail_len, u_int32_t crc)
768{
769 while (tail_len--)
770 crc = CRC32(sbni_inb(sc, DAT), crc);
771
772 return (crc == CRC32_REMAINDER);
773}
774
775
776static int
777check_fhdr(struct sbni_softc *sc, u_int *framelen, u_int *frameno,
778 u_int *ack, u_int *is_first, u_int32_t *crc_p)
779{
780 u_int32_t crc;
781 u_char value;
782
783 crc = *crc_p;
784 if (sbni_inb(sc, DAT) != SBNI_SIG)
785 return (0);
786
787 value = sbni_inb(sc, DAT);
788 *framelen = (u_int)value;
789 crc = CRC32(value, crc);
790 value = sbni_inb(sc, DAT);
791 *framelen |= ((u_int)value) << 8;
792 crc = CRC32(value, crc);
793
794 *ack = *framelen & FRAME_ACK_MASK;
795 *is_first = (*framelen & FRAME_FIRST) != 0;
796
797 if ((*framelen &= FRAME_LEN_MASK) < 6 || *framelen > SBNI_MAX_FRAME - 3)
798 return (0);
799
800 value = sbni_inb(sc, DAT);
801 *frameno = (u_int)value;
802 crc = CRC32(value, crc);
803
804 crc = CRC32(sbni_inb(sc, DAT), crc); /* reserved byte */
805 *framelen -= 2;
806
807 *crc_p = crc;
808 return (1);
809}
810
811
812static int
813get_rx_buf(struct sbni_softc *sc)
814{
815 struct mbuf *m;
816
817 MGETHDR(m, M_DONTWAIT, MT_DATA);
818 if (m == NULL) {
819 if_printf(&sc->arpcom.ac_if, "cannot allocate header mbuf\n");
820 return (0);
821 }
822
823 /*
824 * We always put the received packet in a single buffer -
825 * either with just an mbuf header or in a cluster attached
826 * to the header. The +2 is to compensate for the alignment
827 * fixup below.
828 */
829 if (ETHER_MAX_LEN + 2 > MHLEN) {
830 /* Attach an mbuf cluster */
831 MCLGET(m, M_DONTWAIT);
832 if ((m->m_flags & M_EXT) == 0) {
833 m_freem(m);
834 return (0);
835 }
836 }
837 m->m_pkthdr.len = m->m_len = ETHER_MAX_LEN + 2;
838
839 /*
840 * The +2 is to longword align the start of the real packet.
841 * (sizeof ether_header == 14)
842 * This is important for NFS.
843 */
844 m_adj(m, 2);
845 sc->rx_buf_p = m;
846 return (1);
847}
848
849
850static void
851indicate_pkt(struct sbni_softc *sc)
852{
853 struct ifnet *ifp = &sc->arpcom.ac_if;
854 struct mbuf *m;
855
856 m = sc->rx_buf_p;
857 m->m_pkthdr.rcvif = ifp;
858 m->m_pkthdr.len = m->m_len = sc->inppos;
859
860 (*ifp->if_input)(ifp, m);
861 sc->rx_buf_p = NULL;
862}
863
864/* -------------------------------------------------------------------------- */
865
866/*
867 * Routine checks periodically wire activity and regenerates marker if
868 * connect was inactive for a long time.
869 */
870
871static void
872sbni_timeout(void *xsc)
873{
874 struct sbni_softc *sc;
875 int s;
876 u_char csr0;
877
878 sc = (struct sbni_softc *)xsc;
879 s = splimp();
880
881 csr0 = sbni_inb(sc, CSR0);
882 if (csr0 & RC_CHK) {
883
884 if (sc->timer_ticks) {
885 if (csr0 & (RC_RDY | BU_EMP))
886 /* receiving not active */
887 sc->timer_ticks--;
888 } else {
889 sc->in_stats.timeout_number++;
890 if (sc->delta_rxl)
891 timeout_change_level(sc);
892
893 sbni_outb(sc, CSR1, *(u_char *)&sc->csr1 | PR_RES);
894 csr0 = sbni_inb(sc, CSR0);
895 }
896 }
897
898 sbni_outb(sc, CSR0, csr0 | RC_CHK);
899 sc->wch = timeout(sbni_timeout, sc, hz/SBNI_HZ);
900 splx(s);
901}
902
903/* -------------------------------------------------------------------------- */
904
905static void
906card_start(struct sbni_softc *sc)
907{
908 sc->timer_ticks = CHANGE_LEVEL_START_TICKS;
909 sc->state &= ~(FL_WAIT_ACK | FL_NEED_RESEND);
910 sc->state |= FL_PREV_OK;
911
912 sc->inppos = 0;
913 sc->wait_frameno = 0;
914
915 sbni_outb(sc, CSR1, *(u_char *)&sc->csr1 | PR_RES);
916 sbni_outb(sc, CSR0, EN_INT);
917}
918
919/* -------------------------------------------------------------------------- */
920
921/*
922 * Device timeout/watchdog routine. Entered if the device neglects to
923 * generate an interrupt after a transmit has been started on it.
924 */
925
926static void
927sbni_watchdog(struct ifnet *ifp)
928{
929 log(LOG_ERR, "sbni%d: device timeout\n", ifp->if_unit);
930 ifp->if_oerrors++;
931}
932
933
934static u_char rxl_tab[] = {
935 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x08,
936 0x0a, 0x0c, 0x0f, 0x16, 0x18, 0x1a, 0x1c, 0x1f
937};
938
939#define SIZE_OF_TIMEOUT_RXL_TAB 4
940static u_char timeout_rxl_tab[] = {
941 0x03, 0x05, 0x08, 0x0b
942};
943
944static void
945set_initial_values(struct sbni_softc *sc, struct sbni_flags flags)
946{
947 if (flags.fixed_rxl) {
948 sc->delta_rxl = 0; /* disable receive level autodetection */
949 sc->cur_rxl_index = flags.rxl;
950 } else {
951 sc->delta_rxl = DEF_RXL_DELTA;
952 sc->cur_rxl_index = DEF_RXL;
953 }
954
955 sc->csr1.rate = flags.fixed_rate ? flags.rate : DEFAULT_RATE;
956 sc->csr1.rxl = rxl_tab[sc->cur_rxl_index];
957 sc->maxframe = DEFAULT_FRAME_LEN;
958
959 /*
960 * generate Ethernet address (0x00ff01xxxxxx)
961 */
962 *(u_int16_t *) sc->arpcom.ac_enaddr = htons(0x00ff);
963 if (flags.mac_addr) {
964 *(u_int32_t *) (sc->arpcom.ac_enaddr + 2) =
965 htonl(flags.mac_addr | 0x01000000);
966 } else {
967 *(u_char *) (sc->arpcom.ac_enaddr + 2) = 0x01;
968 read_random(sc->arpcom.ac_enaddr + 3, 3);
969 }
970}
971
972
973#ifdef SBNI_DUAL_COMPOUND
974
975struct sbni_softc *
976connect_to_master(struct sbni_softc *sc)
977{
978 struct sbni_softc *p, *p_prev;
979
980 for (p = sbni_headlist, p_prev = NULL; p; p_prev = p, p = p->link) {
981 if (rman_get_start(p->io_res) == rman_get_start(sc->io_res) + 4 ||
982 rman_get_start(p->io_res) == rman_get_start(sc->io_res) - 4) {
983 p->slave_sc = sc;
984 if (p_prev)
985 p_prev->link = p->link;
986 else
987 sbni_headlist = p->link;
988 return p;
989 }
990 }
991
992 return (NULL);
993}
994
995#endif /* SBNI_DUAL_COMPOUND */
996
997
998/* Receive level auto-selection */
999
1000static void
1001change_level(struct sbni_softc *sc)
1002{
1003 if (sc->delta_rxl == 0) /* do not auto-negotiate RxL */
1004 return;
1005
1006 if (sc->cur_rxl_index == 0)
1007 sc->delta_rxl = 1;
1008 else if (sc->cur_rxl_index == 15)
1009 sc->delta_rxl = -1;
1010 else if (sc->cur_rxl_rcvd < sc->prev_rxl_rcvd)
1011 sc->delta_rxl = -sc->delta_rxl;
1012
1013 sc->csr1.rxl = rxl_tab[sc->cur_rxl_index += sc->delta_rxl];
1014 sbni_inb(sc, CSR0); /* it needed for PCI cards */
1015 sbni_outb(sc, CSR1, *(u_char *)&sc->csr1);
1016
1017 sc->prev_rxl_rcvd = sc->cur_rxl_rcvd;
1018 sc->cur_rxl_rcvd = 0;
1019}
1020
1021
1022static void
1023timeout_change_level(struct sbni_softc *sc)
1024{
1025 sc->cur_rxl_index = timeout_rxl_tab[sc->timeout_rxl];
1026 if (++sc->timeout_rxl >= 4)
1027 sc->timeout_rxl = 0;
1028
1029 sc->csr1.rxl = rxl_tab[sc->cur_rxl_index];
1030 sbni_inb(sc, CSR0);
1031 sbni_outb(sc, CSR1, *(u_char *)&sc->csr1);
1032
1033 sc->prev_rxl_rcvd = sc->cur_rxl_rcvd;
1034 sc->cur_rxl_rcvd = 0;
1035}
1036
1037/* -------------------------------------------------------------------------- */
1038
1039/*
1040 * Process an ioctl request. This code needs some work - it looks
1041 * pretty ugly.
1042 */
1043
1044static int
1045sbni_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
1046{
1047 struct sbni_softc *sc;
1048 struct ifreq *ifr;
1049 struct thread *td;
1050 struct sbni_in_stats *in_stats;
1051 struct sbni_flags flags;
1052 int error, s;
1053
1054 sc = ifp->if_softc;
1055 ifr = (struct ifreq *)data;
1056 td = curthread;
1057 error = 0;
1058
1059 s = splimp();
1060
1061 switch (command) {
1062 case SIOCSIFFLAGS:
1063 /*
1064 * If the interface is marked up and stopped, then start it.
1065 * If it is marked down and running, then stop it.
1066 */
1067 if (ifp->if_flags & IFF_UP) {
1068 if (!(ifp->if_flags & IFF_RUNNING))
1069 sbni_init(sc);
1070 } else {
1071 if (ifp->if_flags & IFF_RUNNING) {
1072 sbni_stop(sc);
1073 ifp->if_flags &= ~IFF_RUNNING;
1074 }
1075 }
1076 break;
1077
1078 case SIOCADDMULTI:
1079 case SIOCDELMULTI:
1080 /*
1081 * Multicast list has changed; set the hardware filter
1082 * accordingly.
1083 */
1084 error = 0;
1085 /* if (ifr == NULL)
1086 error = EAFNOSUPPORT; */
1087 break;
1088
1089 case SIOCSIFMTU:
1090 if (ifr->ifr_mtu > ETHERMTU)
1091 error = EINVAL;
1092 else
1093 ifp->if_mtu = ifr->ifr_mtu;
1094 break;
1095
1096 /*
1097 * SBNI specific ioctl
1098 */
1099 case SIOCGHWFLAGS: /* get flags */
1100 bcopy((caddr_t) sc->arpcom.ac_enaddr+3, (caddr_t) &flags, 3);
1101 flags.rxl = sc->cur_rxl_index;
1102 flags.rate = sc->csr1.rate;
1103 flags.fixed_rxl = (sc->delta_rxl == 0);
1104 flags.fixed_rate = 1;
1105 ifr->ifr_data = *(caddr_t*) &flags;
1106 break;
1107
1108 case SIOCGINSTATS:
1109 in_stats = (struct sbni_in_stats *)ifr->ifr_data;
1110 bcopy((void *)(&(sc->in_stats)), (void *)in_stats,
1111 sizeof(struct sbni_in_stats));
1112 break;
1113
1114 case SIOCSHWFLAGS: /* set flags */
1115 /* root only */
1116 error = suser(td);
1117 if (error)
1118 break;
1119 flags = *(struct sbni_flags*)&ifr->ifr_data;
1120 if (flags.fixed_rxl) {
1121 sc->delta_rxl = 0;
1122 sc->cur_rxl_index = flags.rxl;
1123 } else {
1124 sc->delta_rxl = DEF_RXL_DELTA;
1125 sc->cur_rxl_index = DEF_RXL;
1126 }
1127 sc->csr1.rxl = rxl_tab[sc->cur_rxl_index];
1128 sc->csr1.rate = flags.fixed_rate ? flags.rate : DEFAULT_RATE;
1129 if (flags.mac_addr)
1130 bcopy((caddr_t) &flags,
1131 (caddr_t) sc->arpcom.ac_enaddr+3, 3);
1132
1133 /* Don't be afraid... */
1134 sbni_outb(sc, CSR1, *(char*)(&sc->csr1) | PR_RES);
1135 break;
1136
1137 case SIOCRINSTATS:
1138 if (!(error = suser(td))) /* root only */
1139 bzero(&sc->in_stats, sizeof(struct sbni_in_stats));
1140 break;
1141
1142 default:
1143 error = ether_ioctl(ifp, command, data);
1144 break;
1145 }
1146
1147 splx(s);
1148 return (error);
1149}
1150
1151/* -------------------------------------------------------------------------- */
1152
1153#ifdef ASM_CRC
1154
1155static u_int32_t
1156calc_crc32(u_int32_t crc, caddr_t p, u_int len)
1157{
1158 register u_int32_t _crc __asm ("ax");
1159 _crc = crc;
1160
1161 __asm __volatile (
1162 "xorl %%ebx, %%ebx\n"
1163 "movl %1, %%esi\n"
1164 "movl %2, %%ecx\n"
1165 "movl $crc32tab, %%edi\n"
1166 "shrl $2, %%ecx\n"
1167 "jz 1f\n"
1168
1169 ".align 4\n"
1170 "0:\n"
1171 "movb %%al, %%bl\n"
1172 "movl (%%esi), %%edx\n"
1173 "shrl $8, %%eax\n"
1174 "xorb %%dl, %%bl\n"
1175 "shrl $8, %%edx\n"
1176 "xorl (%%edi,%%ebx,4), %%eax\n"
1177
1178 "movb %%al, %%bl\n"
1179 "shrl $8, %%eax\n"
1180 "xorb %%dl, %%bl\n"
1181 "shrl $8, %%edx\n"
1182 "xorl (%%edi,%%ebx,4), %%eax\n"
1183
1184 "movb %%al, %%bl\n"
1185 "shrl $8, %%eax\n"
1186 "xorb %%dl, %%bl\n"
1187 "movb %%dh, %%dl\n"
1188 "xorl (%%edi,%%ebx,4), %%eax\n"
1189
1190 "movb %%al, %%bl\n"
1191 "shrl $8, %%eax\n"
1192 "xorb %%dl, %%bl\n"
1193 "addl $4, %%esi\n"
1194 "xorl (%%edi,%%ebx,4), %%eax\n"
1195
1196 "decl %%ecx\n"
1197 "jnz 0b\n"
1198
1199 "1:\n"
1200 "movl %2, %%ecx\n"
1201 "andl $3, %%ecx\n"
1202 "jz 2f\n"
1203
1204 "movb %%al, %%bl\n"
1205 "shrl $8, %%eax\n"
1206 "xorb (%%esi), %%bl\n"
1207 "xorl (%%edi,%%ebx,4), %%eax\n"
1208
1209 "decl %%ecx\n"
1210 "jz 2f\n"
1211
1212 "movb %%al, %%bl\n"
1213 "shrl $8, %%eax\n"
1214 "xorb 1(%%esi), %%bl\n"
1215 "xorl (%%edi,%%ebx,4), %%eax\n"
1216
1217 "decl %%ecx\n"
1218 "jz 2f\n"
1219
1220 "movb %%al, %%bl\n"
1221 "shrl $8, %%eax\n"
1222 "xorb 2(%%esi), %%bl\n"
1223 "xorl (%%edi,%%ebx,4), %%eax\n"
1224 "2:\n"
1225 : "=a" (_crc)
1226 : "g" (p), "g" (len)
1227 : "bx", "cx", "dx", "si", "di"
1228 );
1229
1230 return (_crc);
1231}
1232
1233#else /* ASM_CRC */
1234
1235static u_int32_t
1236calc_crc32(u_int32_t crc, caddr_t p, u_int len)
1237{
1238 while (len--)
1239 crc = CRC32(*p++, crc);
1240
1241 return (crc);
1242}
1243
1244#endif /* ASM_CRC */
1245
1246
1247static u_int32_t crc32tab[] __aligned(8) = {
1248 0xD202EF8D, 0xA505DF1B, 0x3C0C8EA1, 0x4B0BBE37,
1249 0xD56F2B94, 0xA2681B02, 0x3B614AB8, 0x4C667A2E,
1250 0xDCD967BF, 0xABDE5729, 0x32D70693, 0x45D03605,
1251 0xDBB4A3A6, 0xACB39330, 0x35BAC28A, 0x42BDF21C,
1252 0xCFB5FFE9, 0xB8B2CF7F, 0x21BB9EC5, 0x56BCAE53,
1253 0xC8D83BF0, 0xBFDF0B66, 0x26D65ADC, 0x51D16A4A,
1254 0xC16E77DB, 0xB669474D, 0x2F6016F7, 0x58672661,
1255 0xC603B3C2, 0xB1048354, 0x280DD2EE, 0x5F0AE278,
1256 0xE96CCF45, 0x9E6BFFD3, 0x0762AE69, 0x70659EFF,
1257 0xEE010B5C, 0x99063BCA, 0x000F6A70, 0x77085AE6,
1258 0xE7B74777, 0x90B077E1, 0x09B9265B, 0x7EBE16CD,
1259 0xE0DA836E, 0x97DDB3F8, 0x0ED4E242, 0x79D3D2D4,
1260 0xF4DBDF21, 0x83DCEFB7, 0x1AD5BE0D, 0x6DD28E9B,
1261 0xF3B61B38, 0x84B12BAE, 0x1DB87A14, 0x6ABF4A82,
1262 0xFA005713, 0x8D076785, 0x140E363F, 0x630906A9,
1263 0xFD6D930A, 0x8A6AA39C, 0x1363F226, 0x6464C2B0,
1264 0xA4DEAE1D, 0xD3D99E8B, 0x4AD0CF31, 0x3DD7FFA7,
1265 0xA3B36A04, 0xD4B45A92, 0x4DBD0B28, 0x3ABA3BBE,
1266 0xAA05262F, 0xDD0216B9, 0x440B4703, 0x330C7795,
1267 0xAD68E236, 0xDA6FD2A0, 0x4366831A, 0x3461B38C,
1268 0xB969BE79, 0xCE6E8EEF, 0x5767DF55, 0x2060EFC3,
1269 0xBE047A60, 0xC9034AF6, 0x500A1B4C, 0x270D2BDA,
1270 0xB7B2364B, 0xC0B506DD, 0x59BC5767, 0x2EBB67F1,
1271 0xB0DFF252, 0xC7D8C2C4, 0x5ED1937E, 0x29D6A3E8,
1272 0x9FB08ED5, 0xE8B7BE43, 0x71BEEFF9, 0x06B9DF6F,
1273 0x98DD4ACC, 0xEFDA7A5A, 0x76D32BE0, 0x01D41B76,
1274 0x916B06E7, 0xE66C3671, 0x7F6567CB, 0x0862575D,
1275 0x9606C2FE, 0xE101F268, 0x7808A3D2, 0x0F0F9344,
1276 0x82079EB1, 0xF500AE27, 0x6C09FF9D, 0x1B0ECF0B,
1277 0x856A5AA8, 0xF26D6A3E, 0x6B643B84, 0x1C630B12,
1278 0x8CDC1683, 0xFBDB2615, 0x62D277AF, 0x15D54739,
1279 0x8BB1D29A, 0xFCB6E20C, 0x65BFB3B6, 0x12B88320,
1280 0x3FBA6CAD, 0x48BD5C3B, 0xD1B40D81, 0xA6B33D17,
1281 0x38D7A8B4, 0x4FD09822, 0xD6D9C998, 0xA1DEF90E,
1282 0x3161E49F, 0x4666D409, 0xDF6F85B3, 0xA868B525,
1283 0x360C2086, 0x410B1010, 0xD80241AA, 0xAF05713C,
1284 0x220D7CC9, 0x550A4C5F, 0xCC031DE5, 0xBB042D73,
1285 0x2560B8D0, 0x52678846, 0xCB6ED9FC, 0xBC69E96A,
1286 0x2CD6F4FB, 0x5BD1C46D, 0xC2D895D7, 0xB5DFA541,
1287 0x2BBB30E2, 0x5CBC0074, 0xC5B551CE, 0xB2B26158,
1288 0x04D44C65, 0x73D37CF3, 0xEADA2D49, 0x9DDD1DDF,
1289 0x03B9887C, 0x74BEB8EA, 0xEDB7E950, 0x9AB0D9C6,
1290 0x0A0FC457, 0x7D08F4C1, 0xE401A57B, 0x930695ED,
1291 0x0D62004E, 0x7A6530D8, 0xE36C6162, 0x946B51F4,
1292 0x19635C01, 0x6E646C97, 0xF76D3D2D, 0x806A0DBB,
1293 0x1E0E9818, 0x6909A88E, 0xF000F934, 0x8707C9A2,
1294 0x17B8D433, 0x60BFE4A5, 0xF9B6B51F, 0x8EB18589,
1295 0x10D5102A, 0x67D220BC, 0xFEDB7106, 0x89DC4190,
1296 0x49662D3D, 0x3E611DAB, 0xA7684C11, 0xD06F7C87,
1297 0x4E0BE924, 0x390CD9B2, 0xA0058808, 0xD702B89E,
1298 0x47BDA50F, 0x30BA9599, 0xA9B3C423, 0xDEB4F4B5,
1299 0x40D06116, 0x37D75180, 0xAEDE003A, 0xD9D930AC,
1300 0x54D13D59, 0x23D60DCF, 0xBADF5C75, 0xCDD86CE3,
1301 0x53BCF940, 0x24BBC9D6, 0xBDB2986C, 0xCAB5A8FA,
1302 0x5A0AB56B, 0x2D0D85FD, 0xB404D447, 0xC303E4D1,
1303 0x5D677172, 0x2A6041E4, 0xB369105E, 0xC46E20C8,
1304 0x72080DF5, 0x050F3D63, 0x9C066CD9, 0xEB015C4F,
1305 0x7565C9EC, 0x0262F97A, 0x9B6BA8C0, 0xEC6C9856,
1306 0x7CD385C7, 0x0BD4B551, 0x92DDE4EB, 0xE5DAD47D,
1307 0x7BBE41DE, 0x0CB97148, 0x95B020F2, 0xE2B71064,
1308 0x6FBF1D91, 0x18B82D07, 0x81B17CBD, 0xF6B64C2B,
1309 0x68D2D988, 0x1FD5E91E, 0x86DCB8A4, 0xF1DB8832,
1310 0x616495A3, 0x1663A535, 0x8F6AF48F, 0xF86DC419,
1311 0x660951BA, 0x110E612C, 0x88073096, 0xFF000000
1312};
32/*
33 * Device driver for Granch SBNI12 leased line adapters
34 *
35 * Revision 2.0.0 1997/08/06
36 * Initial revision by Alexey Zverev
37 *
38 * Revision 2.0.1 1997/08/11
39 * Additional internal statistics support (tx statistics)
40 *
41 * Revision 2.0.2 1997/11/05
42 * if_bpf bug has been fixed
43 *
44 * Revision 2.0.3 1998/12/20
45 * Memory leakage has been eliminated in
46 * the sbni_st and sbni_timeout routines.
47 *
48 * Revision 3.0 2000/08/10 by Yaroslav Polyakov
49 * Support for PCI cards. 4.1 modification.
50 *
51 * Revision 3.1 2000/09/12
52 * Removed extra #defines around bpf functions
53 *
54 * Revision 4.0 2000/11/23 by Denis Timofeev
55 * Completely redesigned the buffer management
56 *
57 * Revision 4.1 2001/01/21
58 * Support for PCI Dual cards and new SBNI12D-10, -11 Dual/ISA cards
59 *
60 * Written with reference to NE2000 driver developed by David Greenman.
61 */
62
63
64#include <sys/param.h>
65#include <sys/systm.h>
66#include <sys/socket.h>
67#include <sys/sockio.h>
68#include <sys/mbuf.h>
69#include <sys/kernel.h>
70#include <sys/proc.h>
71#include <sys/callout.h>
72#include <sys/syslog.h>
73#include <sys/random.h>
74
75#include <machine/bus.h>
76#include <sys/rman.h>
77#include <machine/resource.h>
78
79#include <net/if.h>
80#include <net/ethernet.h>
81#include <net/if_arp.h>
82#include <net/bpf.h>
83
84#include <dev/sbni/if_sbnireg.h>
85#include <dev/sbni/if_sbnivar.h>
86
87#define ASM_CRC 1
88
89static void sbni_init(void *);
90static void sbni_start(struct ifnet *);
91static int sbni_ioctl(struct ifnet *, u_long, caddr_t);
92static void sbni_watchdog(struct ifnet *);
93static void sbni_stop(struct sbni_softc *);
94static void handle_channel(struct sbni_softc *);
95
96static void card_start(struct sbni_softc *);
97static int recv_frame(struct sbni_softc *);
98static void send_frame(struct sbni_softc *);
99static int upload_data(struct sbni_softc *, u_int, u_int, u_int, u_int32_t);
100static int skip_tail(struct sbni_softc *, u_int, u_int32_t);
101static void interpret_ack(struct sbni_softc *, u_int);
102static void download_data(struct sbni_softc *, u_int32_t *);
103static void prepare_to_send(struct sbni_softc *);
104static void drop_xmit_queue(struct sbni_softc *);
105static int get_rx_buf(struct sbni_softc *);
106static void indicate_pkt(struct sbni_softc *);
107static void change_level(struct sbni_softc *);
108static int check_fhdr(struct sbni_softc *, u_int *, u_int *,
109 u_int *, u_int *, u_int32_t *);
110static int append_frame_to_pkt(struct sbni_softc *, u_int, u_int32_t);
111static void timeout_change_level(struct sbni_softc *);
112static void send_frame_header(struct sbni_softc *, u_int32_t *);
113static void set_initial_values(struct sbni_softc *, struct sbni_flags);
114
115static u_int32_t calc_crc32(u_int32_t, caddr_t, u_int);
116static timeout_t sbni_timeout;
117
118static __inline u_char sbni_inb(struct sbni_softc *, enum sbni_reg);
119static __inline void sbni_outb(struct sbni_softc *, enum sbni_reg, u_char);
120static __inline void sbni_insb(struct sbni_softc *, u_char *, u_int);
121static __inline void sbni_outsb(struct sbni_softc *, u_char *, u_int);
122
123static u_int32_t crc32tab[];
124
125#ifdef SBNI_DUAL_COMPOUND
126struct sbni_softc *sbni_headlist;
127#endif
128
129u_int32_t next_sbni_unit;
130
131/* -------------------------------------------------------------------------- */
132
133static __inline u_char
134sbni_inb(struct sbni_softc *sc, enum sbni_reg reg)
135{
136 return bus_space_read_1(
137 rman_get_bustag(sc->io_res),
138 rman_get_bushandle(sc->io_res),
139 sc->io_off + reg);
140}
141
142static __inline void
143sbni_outb(struct sbni_softc *sc, enum sbni_reg reg, u_char value)
144{
145 bus_space_write_1(
146 rman_get_bustag(sc->io_res),
147 rman_get_bushandle(sc->io_res),
148 sc->io_off + reg, value);
149}
150
151static __inline void
152sbni_insb(struct sbni_softc *sc, u_char *to, u_int len)
153{
154 bus_space_read_multi_1(
155 rman_get_bustag(sc->io_res),
156 rman_get_bushandle(sc->io_res),
157 sc->io_off + DAT, to, len);
158}
159
160static __inline void
161sbni_outsb(struct sbni_softc *sc, u_char *from, u_int len)
162{
163 bus_space_write_multi_1(
164 rman_get_bustag(sc->io_res),
165 rman_get_bushandle(sc->io_res),
166 sc->io_off + DAT, from, len);
167}
168
169
170/*
171 Valid combinations in CSR0 (for probing):
172
173 VALID_DECODER 0000,0011,1011,1010
174
175 ; 0 ; -
176 TR_REQ ; 1 ; +
177 TR_RDY ; 2 ; -
178 TR_RDY TR_REQ ; 3 ; +
179 BU_EMP ; 4 ; +
180 BU_EMP TR_REQ ; 5 ; +
181 BU_EMP TR_RDY ; 6 ; -
182 BU_EMP TR_RDY TR_REQ ; 7 ; +
183 RC_RDY ; 8 ; +
184 RC_RDY TR_REQ ; 9 ; +
185 RC_RDY TR_RDY ; 10 ; -
186 RC_RDY TR_RDY TR_REQ ; 11 ; -
187 RC_RDY BU_EMP ; 12 ; -
188 RC_RDY BU_EMP TR_REQ ; 13 ; -
189 RC_RDY BU_EMP TR_RDY ; 14 ; -
190 RC_RDY BU_EMP TR_RDY TR_REQ ; 15 ; -
191*/
192
193#define VALID_DECODER (2 + 8 + 0x10 + 0x20 + 0x80 + 0x100 + 0x200)
194
195
196int
197sbni_probe(struct sbni_softc *sc)
198{
199 u_char csr0;
200
201 csr0 = sbni_inb(sc, CSR0);
202 if (csr0 != 0xff && csr0 != 0x00) {
203 csr0 &= ~EN_INT;
204 if (csr0 & BU_EMP)
205 csr0 |= EN_INT;
206
207 if (VALID_DECODER & (1 << (csr0 >> 4)))
208 return (0);
209 }
210
211 return (ENXIO);
212}
213
214
215/*
216 * Install interface into kernel networking data structures
217 */
218void
219sbni_attach(struct sbni_softc *sc, int unit, struct sbni_flags flags)
220{
221 struct ifnet *ifp;
222 u_char csr0;
223
224 ifp = &sc->arpcom.ac_if;
225 sbni_outb(sc, CSR0, 0);
226 set_initial_values(sc, flags);
227
228 callout_handle_init(&sc->wch);
229 if (!ifp->if_name) {
230 /* Initialize ifnet structure */
231 ifp->if_softc = sc;
232 ifp->if_unit = unit;
233 ifp->if_name = "sbni";
234 ifp->if_init = sbni_init;
235 ifp->if_start = sbni_start;
236 ifp->if_output = ether_output;
237 ifp->if_ioctl = sbni_ioctl;
238 ifp->if_watchdog = sbni_watchdog;
239 ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
240
241 /* report real baud rate */
242 csr0 = sbni_inb(sc, CSR0);
243 ifp->if_baudrate =
244 (csr0 & 0x01 ? 500000 : 2000000) / (1 << flags.rate);
245
246 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
247 ether_ifattach(ifp, sc->arpcom.ac_enaddr);
248 }
249 /* device attach does transition from UNCONFIGURED to IDLE state */
250
251 if_printf(ifp, "speed %ld, address %6D, rxl ",
252 ifp->if_baudrate, sc->arpcom.ac_enaddr, ":");
253 if (sc->delta_rxl)
254 printf("auto\n");
255 else
256 printf("%d (fixed)\n", sc->cur_rxl_index);
257}
258
259/* -------------------------------------------------------------------------- */
260
261static void
262sbni_init(void *xsc)
263{
264 struct sbni_softc *sc;
265 struct ifnet *ifp;
266 int s;
267
268 sc = (struct sbni_softc *)xsc;
269 ifp = &sc->arpcom.ac_if;
270
271 /* address not known */
272 if (TAILQ_EMPTY(&ifp->if_addrhead))
273 return;
274
275 /*
276 * kludge to avoid multiple initialization when more than once
277 * protocols configured
278 */
279 if (ifp->if_flags & IFF_RUNNING)
280 return;
281
282 s = splimp();
283 ifp->if_timer = 0;
284 card_start(sc);
285 sc->wch = timeout(sbni_timeout, sc, hz/SBNI_HZ);
286
287 ifp->if_flags |= IFF_RUNNING;
288 ifp->if_flags &= ~IFF_OACTIVE;
289
290 /* attempt to start output */
291 sbni_start(ifp);
292 splx(s);
293}
294
295
296static void
297sbni_start(struct ifnet *ifp)
298{
299 struct sbni_softc *sc = ifp->if_softc;
300 if (sc->tx_frameno == 0)
301 prepare_to_send(sc);
302}
303
304
305static void
306sbni_stop(struct sbni_softc *sc)
307{
308 sbni_outb(sc, CSR0, 0);
309 drop_xmit_queue(sc);
310
311 if (sc->rx_buf_p) {
312 m_freem(sc->rx_buf_p);
313 sc->rx_buf_p = NULL;
314 }
315
316 untimeout(sbni_timeout, sc, sc->wch);
317 sc->wch.callout = NULL;
318}
319
320/* -------------------------------------------------------------------------- */
321
322/* interrupt handler */
323
324/*
325 * SBNI12D-10, -11/ISA boards within "common interrupt" mode could not
326 * be looked as two independent single-channel devices. Every channel seems
327 * as Ethernet interface but interrupt handler must be common. Really, first
328 * channel ("master") driver only registers the handler. In it's struct softc
329 * it has got pointer to "slave" channel's struct softc and handles that's
330 * interrupts too.
331 * softc of successfully attached ISA SBNI boards is linked to list.
332 * While next board driver is initialized, it scans this list. If one
333 * has found softc with same irq and ioaddr different by 4 then it assumes
334 * this board to be "master".
335 */
336
337void
338sbni_intr(void *arg)
339{
340 struct sbni_softc *sc;
341 int repeat;
342
343 sc = (struct sbni_softc *)arg;
344
345 do {
346 repeat = 0;
347 if (sbni_inb(sc, CSR0) & (RC_RDY | TR_RDY)) {
348 handle_channel(sc);
349 repeat = 1;
350 }
351 if (sc->slave_sc && /* second channel present */
352 (sbni_inb(sc->slave_sc, CSR0) & (RC_RDY | TR_RDY))) {
353 handle_channel(sc->slave_sc);
354 repeat = 1;
355 }
356 } while (repeat);
357}
358
359
360static void
361handle_channel(struct sbni_softc *sc)
362{
363 int req_ans;
364 u_char csr0;
365
366 sbni_outb(sc, CSR0, (sbni_inb(sc, CSR0) & ~EN_INT) | TR_REQ);
367
368 sc->timer_ticks = CHANGE_LEVEL_START_TICKS;
369 for (;;) {
370 csr0 = sbni_inb(sc, CSR0);
371 if ((csr0 & (RC_RDY | TR_RDY)) == 0)
372 break;
373
374 req_ans = !(sc->state & FL_PREV_OK);
375
376 if (csr0 & RC_RDY)
377 req_ans = recv_frame(sc);
378
379 /*
380 * TR_RDY always equals 1 here because we have owned the marker,
381 * and we set TR_REQ when disabled interrupts
382 */
383 csr0 = sbni_inb(sc, CSR0);
384 if ((csr0 & TR_RDY) == 0 || (csr0 & RC_RDY) != 0)
385 printf("sbni: internal error!\n");
386
387 /* if state & FL_NEED_RESEND != 0 then tx_frameno != 0 */
388 if (req_ans || sc->tx_frameno != 0)
389 send_frame(sc);
390 else {
391 /* send the marker without any data */
392 sbni_outb(sc, CSR0, sbni_inb(sc, CSR0) & ~TR_REQ);
393 }
394 }
395
396 sbni_outb(sc, CSR0, sbni_inb(sc, CSR0) | EN_INT);
397}
398
399
400/*
401 * Routine returns 1 if it need to acknoweledge received frame.
402 * Empty frame received without errors won't be acknoweledged.
403 */
404
405static int
406recv_frame(struct sbni_softc *sc)
407{
408 u_int32_t crc;
409 u_int framelen, frameno, ack;
410 u_int is_first, frame_ok;
411
412 crc = CRC32_INITIAL;
413 if (check_fhdr(sc, &framelen, &frameno, &ack, &is_first, &crc)) {
414 frame_ok = framelen > 4 ?
415 upload_data(sc, framelen, frameno, is_first, crc) :
416 skip_tail(sc, framelen, crc);
417 if (frame_ok)
418 interpret_ack(sc, ack);
419 } else
420 frame_ok = 0;
421
422 sbni_outb(sc, CSR0, sbni_inb(sc, CSR0) ^ CT_ZER);
423 if (frame_ok) {
424 sc->state |= FL_PREV_OK;
425 if (framelen > 4)
426 sc->in_stats.all_rx_number++;
427 } else {
428 sc->state &= ~FL_PREV_OK;
429 change_level(sc);
430 sc->in_stats.all_rx_number++;
431 sc->in_stats.bad_rx_number++;
432 }
433
434 return (!frame_ok || framelen > 4);
435}
436
437
438static void
439send_frame(struct sbni_softc *sc)
440{
441 u_int32_t crc;
442 u_char csr0;
443
444 crc = CRC32_INITIAL;
445 if (sc->state & FL_NEED_RESEND) {
446
447 /* if frame was sended but not ACK'ed - resend it */
448 if (sc->trans_errors) {
449 sc->trans_errors--;
450 if (sc->framelen != 0)
451 sc->in_stats.resend_tx_number++;
452 } else {
453 /* cannot xmit with many attempts */
454 drop_xmit_queue(sc);
455 goto do_send;
456 }
457 } else
458 sc->trans_errors = TR_ERROR_COUNT;
459
460 send_frame_header(sc, &crc);
461 sc->state |= FL_NEED_RESEND;
462 /*
463 * FL_NEED_RESEND will be cleared after ACK, but if empty
464 * frame sended then in prepare_to_send next frame
465 */
466
467
468 if (sc->framelen) {
469 download_data(sc, &crc);
470 sc->in_stats.all_tx_number++;
471 sc->state |= FL_WAIT_ACK;
472 }
473
474 sbni_outsb(sc, (u_char *)&crc, sizeof crc);
475
476do_send:
477 csr0 = sbni_inb(sc, CSR0);
478 sbni_outb(sc, CSR0, csr0 & ~TR_REQ);
479
480 if (sc->tx_frameno) {
481 /* next frame exists - request to send */
482 sbni_outb(sc, CSR0, csr0 | TR_REQ);
483 }
484}
485
486
487static void
488download_data(struct sbni_softc *sc, u_int32_t *crc_p)
489{
490 struct mbuf *m;
491 caddr_t data_p;
492 u_int data_len, pos, slice;
493
494 data_p = NULL; /* initialized to avoid warn */
495 pos = 0;
496
497 for (m = sc->tx_buf_p; m != NULL && pos < sc->pktlen; m = m->m_next) {
498 if (pos + m->m_len > sc->outpos) {
499 data_len = m->m_len - (sc->outpos - pos);
500 data_p = mtod(m, caddr_t) + (sc->outpos - pos);
501
502 goto do_copy;
503 } else
504 pos += m->m_len;
505 }
506
507 data_len = 0;
508
509do_copy:
510 pos = 0;
511 do {
512 if (data_len) {
513 slice = min(data_len, sc->framelen - pos);
514 sbni_outsb(sc, data_p, slice);
515 *crc_p = calc_crc32(*crc_p, data_p, slice);
516
517 pos += slice;
518 if (data_len -= slice)
519 data_p += slice;
520 else {
521 do {
522 m = m->m_next;
523 } while (m != NULL && m->m_len == 0);
524
525 if (m) {
526 data_len = m->m_len;
527 data_p = mtod(m, caddr_t);
528 }
529 }
530 } else {
531 /* frame too short - zero padding */
532
533 pos = sc->framelen - pos;
534 while (pos--) {
535 sbni_outb(sc, DAT, 0);
536 *crc_p = CRC32(0, *crc_p);
537 }
538 return;
539 }
540 } while (pos < sc->framelen);
541}
542
543
544static int
545upload_data(struct sbni_softc *sc, u_int framelen, u_int frameno,
546 u_int is_first, u_int32_t crc)
547{
548 int frame_ok;
549
550 if (is_first) {
551 sc->wait_frameno = frameno;
552 sc->inppos = 0;
553 }
554
555 if (sc->wait_frameno == frameno) {
556
557 if (sc->inppos + framelen <= ETHER_MAX_LEN) {
558 frame_ok = append_frame_to_pkt(sc, framelen, crc);
559
560 /*
561 * if CRC is right but framelen incorrect then transmitter
562 * error was occured... drop entire packet
563 */
564 } else if ((frame_ok = skip_tail(sc, framelen, crc)) != 0) {
565 sc->wait_frameno = 0;
566 sc->inppos = 0;
567 sc->arpcom.ac_if.if_ierrors++;
568 /* now skip all frames until is_first != 0 */
569 }
570 } else
571 frame_ok = skip_tail(sc, framelen, crc);
572
573 if (is_first && !frame_ok) {
574 /*
575 * Frame has been violated, but we have stored
576 * is_first already... Drop entire packet.
577 */
578 sc->wait_frameno = 0;
579 sc->arpcom.ac_if.if_ierrors++;
580 }
581
582 return (frame_ok);
583}
584
585
586static __inline void send_complete(struct sbni_softc *);
587
588static __inline void
589send_complete(struct sbni_softc *sc)
590{
591 m_freem(sc->tx_buf_p);
592 sc->tx_buf_p = NULL;
593 sc->arpcom.ac_if.if_opackets++;
594}
595
596
597static void
598interpret_ack(struct sbni_softc *sc, u_int ack)
599{
600 if (ack == FRAME_SENT_OK) {
601 sc->state &= ~FL_NEED_RESEND;
602
603 if (sc->state & FL_WAIT_ACK) {
604 sc->outpos += sc->framelen;
605
606 if (--sc->tx_frameno) {
607 sc->framelen = min(
608 sc->maxframe, sc->pktlen - sc->outpos);
609 } else {
610 send_complete(sc);
611 prepare_to_send(sc);
612 }
613 }
614 }
615
616 sc->state &= ~FL_WAIT_ACK;
617}
618
619
620/*
621 * Glue received frame with previous fragments of packet.
622 * Indicate packet when last frame would be accepted.
623 */
624
625static int
626append_frame_to_pkt(struct sbni_softc *sc, u_int framelen, u_int32_t crc)
627{
628 caddr_t p;
629
630 if (sc->inppos + framelen > ETHER_MAX_LEN)
631 return (0);
632
633 if (!sc->rx_buf_p && !get_rx_buf(sc))
634 return (0);
635
636 p = sc->rx_buf_p->m_data + sc->inppos;
637 sbni_insb(sc, p, framelen);
638 if (calc_crc32(crc, p, framelen) != CRC32_REMAINDER)
639 return (0);
640
641 sc->inppos += framelen - 4;
642 if (--sc->wait_frameno == 0) { /* last frame received */
643 indicate_pkt(sc);
644 sc->arpcom.ac_if.if_ipackets++;
645 }
646
647 return (1);
648}
649
650
651/*
652 * Prepare to start output on adapter. Current priority must be set to splimp
653 * before this routine is called.
654 * Transmitter will be actually activated when marker has been accepted.
655 */
656
657static void
658prepare_to_send(struct sbni_softc *sc)
659{
660 struct mbuf *m;
661 u_int len;
662
663 /* sc->tx_buf_p == NULL here! */
664 if (sc->tx_buf_p)
665 printf("sbni: memory leak!\n");
666
667 sc->outpos = 0;
668 sc->state &= ~(FL_WAIT_ACK | FL_NEED_RESEND);
669
670 for (;;) {
671 IF_DEQUEUE(&sc->arpcom.ac_if.if_snd, sc->tx_buf_p);
672 if (!sc->tx_buf_p) {
673 /* nothing to transmit... */
674 sc->pktlen = 0;
675 sc->tx_frameno = 0;
676 sc->framelen = 0;
677 sc->arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
678 return;
679 }
680
681 for (len = 0, m = sc->tx_buf_p; m; m = m->m_next)
682 len += m->m_len;
683
684 if (len != 0)
685 break;
686 m_freem(sc->tx_buf_p);
687 }
688
689 if (len < SBNI_MIN_LEN)
690 len = SBNI_MIN_LEN;
691
692 sc->pktlen = len;
693 sc->tx_frameno = (len + sc->maxframe - 1) / sc->maxframe;
694 sc->framelen = min(len, sc->maxframe);
695
696 sbni_outb(sc, CSR0, sbni_inb(sc, CSR0) | TR_REQ);
697 sc->arpcom.ac_if.if_flags |= IFF_OACTIVE;
698 BPF_MTAP(&sc->arpcom.ac_if, sc->tx_buf_p);
699}
700
701
702static void
703drop_xmit_queue(struct sbni_softc *sc)
704{
705 struct mbuf *m;
706
707 if (sc->tx_buf_p) {
708 m_freem(sc->tx_buf_p);
709 sc->tx_buf_p = NULL;
710 sc->arpcom.ac_if.if_oerrors++;
711 }
712
713 for (;;) {
714 IF_DEQUEUE(&sc->arpcom.ac_if.if_snd, m);
715 if (m == NULL)
716 break;
717 m_freem(m);
718 sc->arpcom.ac_if.if_oerrors++;
719 }
720
721 sc->tx_frameno = 0;
722 sc->framelen = 0;
723 sc->outpos = 0;
724 sc->state &= ~(FL_WAIT_ACK | FL_NEED_RESEND);
725 sc->arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
726}
727
728
729static void
730send_frame_header(struct sbni_softc *sc, u_int32_t *crc_p)
731{
732 u_int32_t crc;
733 u_int len_field;
734 u_char value;
735
736 crc = *crc_p;
737 len_field = sc->framelen + 6; /* CRC + frameno + reserved */
738
739 if (sc->state & FL_NEED_RESEND)
740 len_field |= FRAME_RETRY; /* non-first attempt... */
741
742 if (sc->outpos == 0)
743 len_field |= FRAME_FIRST;
744
745 len_field |= (sc->state & FL_PREV_OK) ? FRAME_SENT_OK : FRAME_SENT_BAD;
746 sbni_outb(sc, DAT, SBNI_SIG);
747
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);
754
755 sbni_outb(sc, DAT, sc->tx_frameno);
756 crc = CRC32(sc->tx_frameno, crc);
757 sbni_outb(sc, DAT, 0);
758 crc = CRC32(0, crc);
759 *crc_p = crc;
760}
761
762
763/*
764 * if frame tail not needed (incorrect number or received twice),
765 * it won't store, but CRC will be calculated
766 */
767
768static int
769skip_tail(struct sbni_softc *sc, u_int tail_len, u_int32_t crc)
770{
771 while (tail_len--)
772 crc = CRC32(sbni_inb(sc, DAT), crc);
773
774 return (crc == CRC32_REMAINDER);
775}
776
777
778static int
779check_fhdr(struct sbni_softc *sc, u_int *framelen, u_int *frameno,
780 u_int *ack, u_int *is_first, u_int32_t *crc_p)
781{
782 u_int32_t crc;
783 u_char value;
784
785 crc = *crc_p;
786 if (sbni_inb(sc, DAT) != SBNI_SIG)
787 return (0);
788
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);
795
796 *ack = *framelen & FRAME_ACK_MASK;
797 *is_first = (*framelen & FRAME_FIRST) != 0;
798
799 if ((*framelen &= FRAME_LEN_MASK) < 6 || *framelen > SBNI_MAX_FRAME - 3)
800 return (0);
801
802 value = sbni_inb(sc, DAT);
803 *frameno = (u_int)value;
804 crc = CRC32(value, crc);
805
806 crc = CRC32(sbni_inb(sc, DAT), crc); /* reserved byte */
807 *framelen -= 2;
808
809 *crc_p = crc;
810 return (1);
811}
812
813
814static int
815get_rx_buf(struct sbni_softc *sc)
816{
817 struct mbuf *m;
818
819 MGETHDR(m, M_DONTWAIT, MT_DATA);
820 if (m == NULL) {
821 if_printf(&sc->arpcom.ac_if, "cannot allocate header mbuf\n");
822 return (0);
823 }
824
825 /*
826 * We always put the received packet in a single buffer -
827 * either with just an mbuf header or in a cluster attached
828 * to the header. The +2 is to compensate for the alignment
829 * fixup below.
830 */
831 if (ETHER_MAX_LEN + 2 > MHLEN) {
832 /* Attach an mbuf cluster */
833 MCLGET(m, M_DONTWAIT);
834 if ((m->m_flags & M_EXT) == 0) {
835 m_freem(m);
836 return (0);
837 }
838 }
839 m->m_pkthdr.len = m->m_len = ETHER_MAX_LEN + 2;
840
841 /*
842 * The +2 is to longword align the start of the real packet.
843 * (sizeof ether_header == 14)
844 * This is important for NFS.
845 */
846 m_adj(m, 2);
847 sc->rx_buf_p = m;
848 return (1);
849}
850
851
852static void
853indicate_pkt(struct sbni_softc *sc)
854{
855 struct ifnet *ifp = &sc->arpcom.ac_if;
856 struct mbuf *m;
857
858 m = sc->rx_buf_p;
859 m->m_pkthdr.rcvif = ifp;
860 m->m_pkthdr.len = m->m_len = sc->inppos;
861
862 (*ifp->if_input)(ifp, m);
863 sc->rx_buf_p = NULL;
864}
865
866/* -------------------------------------------------------------------------- */
867
868/*
869 * Routine checks periodically wire activity and regenerates marker if
870 * connect was inactive for a long time.
871 */
872
873static void
874sbni_timeout(void *xsc)
875{
876 struct sbni_softc *sc;
877 int s;
878 u_char csr0;
879
880 sc = (struct sbni_softc *)xsc;
881 s = splimp();
882
883 csr0 = sbni_inb(sc, CSR0);
884 if (csr0 & RC_CHK) {
885
886 if (sc->timer_ticks) {
887 if (csr0 & (RC_RDY | BU_EMP))
888 /* receiving not active */
889 sc->timer_ticks--;
890 } else {
891 sc->in_stats.timeout_number++;
892 if (sc->delta_rxl)
893 timeout_change_level(sc);
894
895 sbni_outb(sc, CSR1, *(u_char *)&sc->csr1 | PR_RES);
896 csr0 = sbni_inb(sc, CSR0);
897 }
898 }
899
900 sbni_outb(sc, CSR0, csr0 | RC_CHK);
901 sc->wch = timeout(sbni_timeout, sc, hz/SBNI_HZ);
902 splx(s);
903}
904
905/* -------------------------------------------------------------------------- */
906
907static void
908card_start(struct sbni_softc *sc)
909{
910 sc->timer_ticks = CHANGE_LEVEL_START_TICKS;
911 sc->state &= ~(FL_WAIT_ACK | FL_NEED_RESEND);
912 sc->state |= FL_PREV_OK;
913
914 sc->inppos = 0;
915 sc->wait_frameno = 0;
916
917 sbni_outb(sc, CSR1, *(u_char *)&sc->csr1 | PR_RES);
918 sbni_outb(sc, CSR0, EN_INT);
919}
920
921/* -------------------------------------------------------------------------- */
922
923/*
924 * Device timeout/watchdog routine. Entered if the device neglects to
925 * generate an interrupt after a transmit has been started on it.
926 */
927
928static void
929sbni_watchdog(struct ifnet *ifp)
930{
931 log(LOG_ERR, "sbni%d: device timeout\n", ifp->if_unit);
932 ifp->if_oerrors++;
933}
934
935
936static u_char rxl_tab[] = {
937 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x08,
938 0x0a, 0x0c, 0x0f, 0x16, 0x18, 0x1a, 0x1c, 0x1f
939};
940
941#define SIZE_OF_TIMEOUT_RXL_TAB 4
942static u_char timeout_rxl_tab[] = {
943 0x03, 0x05, 0x08, 0x0b
944};
945
946static void
947set_initial_values(struct sbni_softc *sc, struct sbni_flags flags)
948{
949 if (flags.fixed_rxl) {
950 sc->delta_rxl = 0; /* disable receive level autodetection */
951 sc->cur_rxl_index = flags.rxl;
952 } else {
953 sc->delta_rxl = DEF_RXL_DELTA;
954 sc->cur_rxl_index = DEF_RXL;
955 }
956
957 sc->csr1.rate = flags.fixed_rate ? flags.rate : DEFAULT_RATE;
958 sc->csr1.rxl = rxl_tab[sc->cur_rxl_index];
959 sc->maxframe = DEFAULT_FRAME_LEN;
960
961 /*
962 * generate Ethernet address (0x00ff01xxxxxx)
963 */
964 *(u_int16_t *) sc->arpcom.ac_enaddr = htons(0x00ff);
965 if (flags.mac_addr) {
966 *(u_int32_t *) (sc->arpcom.ac_enaddr + 2) =
967 htonl(flags.mac_addr | 0x01000000);
968 } else {
969 *(u_char *) (sc->arpcom.ac_enaddr + 2) = 0x01;
970 read_random(sc->arpcom.ac_enaddr + 3, 3);
971 }
972}
973
974
975#ifdef SBNI_DUAL_COMPOUND
976
977struct sbni_softc *
978connect_to_master(struct sbni_softc *sc)
979{
980 struct sbni_softc *p, *p_prev;
981
982 for (p = sbni_headlist, p_prev = NULL; p; p_prev = p, p = p->link) {
983 if (rman_get_start(p->io_res) == rman_get_start(sc->io_res) + 4 ||
984 rman_get_start(p->io_res) == rman_get_start(sc->io_res) - 4) {
985 p->slave_sc = sc;
986 if (p_prev)
987 p_prev->link = p->link;
988 else
989 sbni_headlist = p->link;
990 return p;
991 }
992 }
993
994 return (NULL);
995}
996
997#endif /* SBNI_DUAL_COMPOUND */
998
999
1000/* Receive level auto-selection */
1001
1002static void
1003change_level(struct sbni_softc *sc)
1004{
1005 if (sc->delta_rxl == 0) /* do not auto-negotiate RxL */
1006 return;
1007
1008 if (sc->cur_rxl_index == 0)
1009 sc->delta_rxl = 1;
1010 else if (sc->cur_rxl_index == 15)
1011 sc->delta_rxl = -1;
1012 else if (sc->cur_rxl_rcvd < sc->prev_rxl_rcvd)
1013 sc->delta_rxl = -sc->delta_rxl;
1014
1015 sc->csr1.rxl = rxl_tab[sc->cur_rxl_index += sc->delta_rxl];
1016 sbni_inb(sc, CSR0); /* it needed for PCI cards */
1017 sbni_outb(sc, CSR1, *(u_char *)&sc->csr1);
1018
1019 sc->prev_rxl_rcvd = sc->cur_rxl_rcvd;
1020 sc->cur_rxl_rcvd = 0;
1021}
1022
1023
1024static void
1025timeout_change_level(struct sbni_softc *sc)
1026{
1027 sc->cur_rxl_index = timeout_rxl_tab[sc->timeout_rxl];
1028 if (++sc->timeout_rxl >= 4)
1029 sc->timeout_rxl = 0;
1030
1031 sc->csr1.rxl = rxl_tab[sc->cur_rxl_index];
1032 sbni_inb(sc, CSR0);
1033 sbni_outb(sc, CSR1, *(u_char *)&sc->csr1);
1034
1035 sc->prev_rxl_rcvd = sc->cur_rxl_rcvd;
1036 sc->cur_rxl_rcvd = 0;
1037}
1038
1039/* -------------------------------------------------------------------------- */
1040
1041/*
1042 * Process an ioctl request. This code needs some work - it looks
1043 * pretty ugly.
1044 */
1045
1046static int
1047sbni_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
1048{
1049 struct sbni_softc *sc;
1050 struct ifreq *ifr;
1051 struct thread *td;
1052 struct sbni_in_stats *in_stats;
1053 struct sbni_flags flags;
1054 int error, s;
1055
1056 sc = ifp->if_softc;
1057 ifr = (struct ifreq *)data;
1058 td = curthread;
1059 error = 0;
1060
1061 s = splimp();
1062
1063 switch (command) {
1064 case SIOCSIFFLAGS:
1065 /*
1066 * If the interface is marked up and stopped, then start it.
1067 * If it is marked down and running, then stop it.
1068 */
1069 if (ifp->if_flags & IFF_UP) {
1070 if (!(ifp->if_flags & IFF_RUNNING))
1071 sbni_init(sc);
1072 } else {
1073 if (ifp->if_flags & IFF_RUNNING) {
1074 sbni_stop(sc);
1075 ifp->if_flags &= ~IFF_RUNNING;
1076 }
1077 }
1078 break;
1079
1080 case SIOCADDMULTI:
1081 case SIOCDELMULTI:
1082 /*
1083 * Multicast list has changed; set the hardware filter
1084 * accordingly.
1085 */
1086 error = 0;
1087 /* if (ifr == NULL)
1088 error = EAFNOSUPPORT; */
1089 break;
1090
1091 case SIOCSIFMTU:
1092 if (ifr->ifr_mtu > ETHERMTU)
1093 error = EINVAL;
1094 else
1095 ifp->if_mtu = ifr->ifr_mtu;
1096 break;
1097
1098 /*
1099 * SBNI specific ioctl
1100 */
1101 case SIOCGHWFLAGS: /* get flags */
1102 bcopy((caddr_t) sc->arpcom.ac_enaddr+3, (caddr_t) &flags, 3);
1103 flags.rxl = sc->cur_rxl_index;
1104 flags.rate = sc->csr1.rate;
1105 flags.fixed_rxl = (sc->delta_rxl == 0);
1106 flags.fixed_rate = 1;
1107 ifr->ifr_data = *(caddr_t*) &flags;
1108 break;
1109
1110 case SIOCGINSTATS:
1111 in_stats = (struct sbni_in_stats *)ifr->ifr_data;
1112 bcopy((void *)(&(sc->in_stats)), (void *)in_stats,
1113 sizeof(struct sbni_in_stats));
1114 break;
1115
1116 case SIOCSHWFLAGS: /* set flags */
1117 /* root only */
1118 error = suser(td);
1119 if (error)
1120 break;
1121 flags = *(struct sbni_flags*)&ifr->ifr_data;
1122 if (flags.fixed_rxl) {
1123 sc->delta_rxl = 0;
1124 sc->cur_rxl_index = flags.rxl;
1125 } else {
1126 sc->delta_rxl = DEF_RXL_DELTA;
1127 sc->cur_rxl_index = DEF_RXL;
1128 }
1129 sc->csr1.rxl = rxl_tab[sc->cur_rxl_index];
1130 sc->csr1.rate = flags.fixed_rate ? flags.rate : DEFAULT_RATE;
1131 if (flags.mac_addr)
1132 bcopy((caddr_t) &flags,
1133 (caddr_t) sc->arpcom.ac_enaddr+3, 3);
1134
1135 /* Don't be afraid... */
1136 sbni_outb(sc, CSR1, *(char*)(&sc->csr1) | PR_RES);
1137 break;
1138
1139 case SIOCRINSTATS:
1140 if (!(error = suser(td))) /* root only */
1141 bzero(&sc->in_stats, sizeof(struct sbni_in_stats));
1142 break;
1143
1144 default:
1145 error = ether_ioctl(ifp, command, data);
1146 break;
1147 }
1148
1149 splx(s);
1150 return (error);
1151}
1152
1153/* -------------------------------------------------------------------------- */
1154
1155#ifdef ASM_CRC
1156
1157static u_int32_t
1158calc_crc32(u_int32_t crc, caddr_t p, u_int len)
1159{
1160 register u_int32_t _crc __asm ("ax");
1161 _crc = crc;
1162
1163 __asm __volatile (
1164 "xorl %%ebx, %%ebx\n"
1165 "movl %1, %%esi\n"
1166 "movl %2, %%ecx\n"
1167 "movl $crc32tab, %%edi\n"
1168 "shrl $2, %%ecx\n"
1169 "jz 1f\n"
1170
1171 ".align 4\n"
1172 "0:\n"
1173 "movb %%al, %%bl\n"
1174 "movl (%%esi), %%edx\n"
1175 "shrl $8, %%eax\n"
1176 "xorb %%dl, %%bl\n"
1177 "shrl $8, %%edx\n"
1178 "xorl (%%edi,%%ebx,4), %%eax\n"
1179
1180 "movb %%al, %%bl\n"
1181 "shrl $8, %%eax\n"
1182 "xorb %%dl, %%bl\n"
1183 "shrl $8, %%edx\n"
1184 "xorl (%%edi,%%ebx,4), %%eax\n"
1185
1186 "movb %%al, %%bl\n"
1187 "shrl $8, %%eax\n"
1188 "xorb %%dl, %%bl\n"
1189 "movb %%dh, %%dl\n"
1190 "xorl (%%edi,%%ebx,4), %%eax\n"
1191
1192 "movb %%al, %%bl\n"
1193 "shrl $8, %%eax\n"
1194 "xorb %%dl, %%bl\n"
1195 "addl $4, %%esi\n"
1196 "xorl (%%edi,%%ebx,4), %%eax\n"
1197
1198 "decl %%ecx\n"
1199 "jnz 0b\n"
1200
1201 "1:\n"
1202 "movl %2, %%ecx\n"
1203 "andl $3, %%ecx\n"
1204 "jz 2f\n"
1205
1206 "movb %%al, %%bl\n"
1207 "shrl $8, %%eax\n"
1208 "xorb (%%esi), %%bl\n"
1209 "xorl (%%edi,%%ebx,4), %%eax\n"
1210
1211 "decl %%ecx\n"
1212 "jz 2f\n"
1213
1214 "movb %%al, %%bl\n"
1215 "shrl $8, %%eax\n"
1216 "xorb 1(%%esi), %%bl\n"
1217 "xorl (%%edi,%%ebx,4), %%eax\n"
1218
1219 "decl %%ecx\n"
1220 "jz 2f\n"
1221
1222 "movb %%al, %%bl\n"
1223 "shrl $8, %%eax\n"
1224 "xorb 2(%%esi), %%bl\n"
1225 "xorl (%%edi,%%ebx,4), %%eax\n"
1226 "2:\n"
1227 : "=a" (_crc)
1228 : "g" (p), "g" (len)
1229 : "bx", "cx", "dx", "si", "di"
1230 );
1231
1232 return (_crc);
1233}
1234
1235#else /* ASM_CRC */
1236
1237static u_int32_t
1238calc_crc32(u_int32_t crc, caddr_t p, u_int len)
1239{
1240 while (len--)
1241 crc = CRC32(*p++, crc);
1242
1243 return (crc);
1244}
1245
1246#endif /* ASM_CRC */
1247
1248
1249static u_int32_t crc32tab[] __aligned(8) = {
1250 0xD202EF8D, 0xA505DF1B, 0x3C0C8EA1, 0x4B0BBE37,
1251 0xD56F2B94, 0xA2681B02, 0x3B614AB8, 0x4C667A2E,
1252 0xDCD967BF, 0xABDE5729, 0x32D70693, 0x45D03605,
1253 0xDBB4A3A6, 0xACB39330, 0x35BAC28A, 0x42BDF21C,
1254 0xCFB5FFE9, 0xB8B2CF7F, 0x21BB9EC5, 0x56BCAE53,
1255 0xC8D83BF0, 0xBFDF0B66, 0x26D65ADC, 0x51D16A4A,
1256 0xC16E77DB, 0xB669474D, 0x2F6016F7, 0x58672661,
1257 0xC603B3C2, 0xB1048354, 0x280DD2EE, 0x5F0AE278,
1258 0xE96CCF45, 0x9E6BFFD3, 0x0762AE69, 0x70659EFF,
1259 0xEE010B5C, 0x99063BCA, 0x000F6A70, 0x77085AE6,
1260 0xE7B74777, 0x90B077E1, 0x09B9265B, 0x7EBE16CD,
1261 0xE0DA836E, 0x97DDB3F8, 0x0ED4E242, 0x79D3D2D4,
1262 0xF4DBDF21, 0x83DCEFB7, 0x1AD5BE0D, 0x6DD28E9B,
1263 0xF3B61B38, 0x84B12BAE, 0x1DB87A14, 0x6ABF4A82,
1264 0xFA005713, 0x8D076785, 0x140E363F, 0x630906A9,
1265 0xFD6D930A, 0x8A6AA39C, 0x1363F226, 0x6464C2B0,
1266 0xA4DEAE1D, 0xD3D99E8B, 0x4AD0CF31, 0x3DD7FFA7,
1267 0xA3B36A04, 0xD4B45A92, 0x4DBD0B28, 0x3ABA3BBE,
1268 0xAA05262F, 0xDD0216B9, 0x440B4703, 0x330C7795,
1269 0xAD68E236, 0xDA6FD2A0, 0x4366831A, 0x3461B38C,
1270 0xB969BE79, 0xCE6E8EEF, 0x5767DF55, 0x2060EFC3,
1271 0xBE047A60, 0xC9034AF6, 0x500A1B4C, 0x270D2BDA,
1272 0xB7B2364B, 0xC0B506DD, 0x59BC5767, 0x2EBB67F1,
1273 0xB0DFF252, 0xC7D8C2C4, 0x5ED1937E, 0x29D6A3E8,
1274 0x9FB08ED5, 0xE8B7BE43, 0x71BEEFF9, 0x06B9DF6F,
1275 0x98DD4ACC, 0xEFDA7A5A, 0x76D32BE0, 0x01D41B76,
1276 0x916B06E7, 0xE66C3671, 0x7F6567CB, 0x0862575D,
1277 0x9606C2FE, 0xE101F268, 0x7808A3D2, 0x0F0F9344,
1278 0x82079EB1, 0xF500AE27, 0x6C09FF9D, 0x1B0ECF0B,
1279 0x856A5AA8, 0xF26D6A3E, 0x6B643B84, 0x1C630B12,
1280 0x8CDC1683, 0xFBDB2615, 0x62D277AF, 0x15D54739,
1281 0x8BB1D29A, 0xFCB6E20C, 0x65BFB3B6, 0x12B88320,
1282 0x3FBA6CAD, 0x48BD5C3B, 0xD1B40D81, 0xA6B33D17,
1283 0x38D7A8B4, 0x4FD09822, 0xD6D9C998, 0xA1DEF90E,
1284 0x3161E49F, 0x4666D409, 0xDF6F85B3, 0xA868B525,
1285 0x360C2086, 0x410B1010, 0xD80241AA, 0xAF05713C,
1286 0x220D7CC9, 0x550A4C5F, 0xCC031DE5, 0xBB042D73,
1287 0x2560B8D0, 0x52678846, 0xCB6ED9FC, 0xBC69E96A,
1288 0x2CD6F4FB, 0x5BD1C46D, 0xC2D895D7, 0xB5DFA541,
1289 0x2BBB30E2, 0x5CBC0074, 0xC5B551CE, 0xB2B26158,
1290 0x04D44C65, 0x73D37CF3, 0xEADA2D49, 0x9DDD1DDF,
1291 0x03B9887C, 0x74BEB8EA, 0xEDB7E950, 0x9AB0D9C6,
1292 0x0A0FC457, 0x7D08F4C1, 0xE401A57B, 0x930695ED,
1293 0x0D62004E, 0x7A6530D8, 0xE36C6162, 0x946B51F4,
1294 0x19635C01, 0x6E646C97, 0xF76D3D2D, 0x806A0DBB,
1295 0x1E0E9818, 0x6909A88E, 0xF000F934, 0x8707C9A2,
1296 0x17B8D433, 0x60BFE4A5, 0xF9B6B51F, 0x8EB18589,
1297 0x10D5102A, 0x67D220BC, 0xFEDB7106, 0x89DC4190,
1298 0x49662D3D, 0x3E611DAB, 0xA7684C11, 0xD06F7C87,
1299 0x4E0BE924, 0x390CD9B2, 0xA0058808, 0xD702B89E,
1300 0x47BDA50F, 0x30BA9599, 0xA9B3C423, 0xDEB4F4B5,
1301 0x40D06116, 0x37D75180, 0xAEDE003A, 0xD9D930AC,
1302 0x54D13D59, 0x23D60DCF, 0xBADF5C75, 0xCDD86CE3,
1303 0x53BCF940, 0x24BBC9D6, 0xBDB2986C, 0xCAB5A8FA,
1304 0x5A0AB56B, 0x2D0D85FD, 0xB404D447, 0xC303E4D1,
1305 0x5D677172, 0x2A6041E4, 0xB369105E, 0xC46E20C8,
1306 0x72080DF5, 0x050F3D63, 0x9C066CD9, 0xEB015C4F,
1307 0x7565C9EC, 0x0262F97A, 0x9B6BA8C0, 0xEC6C9856,
1308 0x7CD385C7, 0x0BD4B551, 0x92DDE4EB, 0xE5DAD47D,
1309 0x7BBE41DE, 0x0CB97148, 0x95B020F2, 0xE2B71064,
1310 0x6FBF1D91, 0x18B82D07, 0x81B17CBD, 0xF6B64C2B,
1311 0x68D2D988, 0x1FD5E91E, 0x86DCB8A4, 0xF1DB8832,
1312 0x616495A3, 0x1663A535, 0x8F6AF48F, 0xF86DC419,
1313 0x660951BA, 0x110E612C, 0x88073096, 0xFF000000
1314};