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