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