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