source: rtems/c/src/lib/libbsp/i386/ts_386ex/network/ne2000.c @ 3e8cdf8

4.115
Last change on this file since 3e8cdf8 was 3e8cdf8, checked in by Joel Sherrill <joel.sherrill@…>, on 01/28/11 at 20:35:36

2011-01-28 Joel Sherrill <joel.sherrilL@…>

  • clock/rtc.c, console/console.c, network/ne2000.c: Fix typo where license said found in found in.
  • Property mode set to 100644
File size: 25.8 KB
RevLine 
[16a384cf]1/*  ne2k.c -- RTEMS NE2000 Ethernet driver.
2 *  Written by Ian Lance Taylor, Zembu Labs.
3 *  October, 1998.
4 *
5 *  The license and distribution terms for this file may be
[3e8cdf8]6 *  found in the file LICENSE in this distribution or at
[e61df10]7 *  http://www.rtems.com/license/LICENSE.
[16a384cf]8 *
9 *  $Id$
10 *
11 *  Both the ne2000 and the wd80x3 are based on the National Semiconductor
12 *  8390 chip, so there is a fair amount of overlap between the two
13 *  drivers.  It would be possible in principle to combine some code into
14 *  a separate set of subroutines called by both.  In fact, the drivers in
15 *  both OpenBSD and Linux work this way.  I didn't bother, because for
16 *  the relatively simple drivers used by RTEMS, the overlap is not
17 *  especially large, and any reasonable use of subroutines would lead to
18 *  slightly less efficient code.
19
20 *  This ne2000 driver uses two transmit buffers.  While one packet is
21 *  being transmitted over the Ethernet, RTEMS will upload another.  Since
22 *  uploading a packet to the ne2000 is rather slow, I don't think there
23 *  is any point to having more than two transmit buffers.  However, the
24 *  code does make it possible, by changing NE_TX_BUFS, although that
25 *  would of course reduce the number of receive buffers.
[6128a4a]26 *
[16a384cf]27 *  I suspect that the wd80x3 driver would benefit slightly from copying
28 *  the multiple transmit buffer code.  However, I have no way to test
29 *  that.
30 */
31
32#include <bsp.h>
33#include <wd80x3.h>
34
35#include <stdio.h>
36#include <assert.h>
37
38#include <rtems/error.h>
39#include <rtems/rtems_bsdnet.h>
40
41#include <sys/param.h>
42#include <sys/mbuf.h>
43#include <sys/socket.h>
44#include <sys/sockio.h>
[c140041b]45#include <errno.h>
[16a384cf]46
47#include <net/if.h>
48
49#include <netinet/in.h>
50#include <netinet/if_ether.h>
51
[48ad38db]52#include <bsp/irq.h>
[16a384cf]53
54/* Define this to force byte-wide data transfers with the NIC. This
55   is needed for boards like the TS-1325 386EX PC, which support only
56   an 8-bit PC/104 bus.  Undefine this on a normal PC.*/
57
58/* #define NE2000_BYTE_TRANSFERS */
59
60/* Define this to print debugging messages with printk.  */
61
62/* #define DEBUG_NE2000 */
63
64/* We expect to be able to read a complete packet into an mbuf.  */
65
66#if (MCLBYTES < 1520)
67# error "Driver must have MCLBYTES >= 1520"
68#endif
69
70/* The 8390 macro definitions in wd80x3.h expect RO to be defined.  */
71#define RO 0
72
73/* Minimum size of Ethernet packet.  */
74#define ET_MINLEN 60
75
76/* The number of NE2000 devices supported by this driver.  */
77
78#define NNEDRIVER       1
79
80/* RTEMS event number used by the interrupt handler to signal the
81   driver task.  This must not be any of the events used by the
82   network task synchronization.  */
83#define INTERRUPT_EVENT RTEMS_EVENT_1
84
85/* RTEMS event number used to start the transmit daemon.  This must
86   not be the same as INTERRUPT_EVENT.  */
87#define START_TRANSMIT_EVENT RTEMS_EVENT_2
88
89/* Interrupts we want to handle from the device.  */
90
91#define NE_INTERRUPTS \
92  (MSK_PRX | MSK_PTX | MSK_RXE | MSK_TXE | MSK_OVW | MSK_CNT)
93
94/* The size of a page in device memory.  */
95
96#define NE_PAGE_SIZE (256)
97
98/* The first page address in device memory.  */
99
100#define NE_START_PAGE (0x40)
101
102/* The last page address, plus 1.  */
103
104#define NE_STOP_PAGE (0x80)
105
106/* The number of pages used for a single transmit buffer.  This is
107   1536 bytes, enough for a full size packet.  */
108
109#define NE_TX_PAGES (6)
110
111/* The number of transmit buffers.  We use two, so we can load one
112   packet while the other is being sent.  */
113
114#define NE_TX_BUFS (2)
115
116/* We use the first pages in memory as transmit buffers, and the
117   remaining ones as receive buffers.  */
118
119#define NE_FIRST_TX_PAGE (NE_START_PAGE)
120
121#define NE_FIRST_RX_PAGE (NE_FIRST_TX_PAGE + NE_TX_PAGES * NE_TX_BUFS)
122
123/* Data we store for each NE2000 device.  */
124
125struct ne_softc {
126  /* The bsdnet information structure.  */
127  struct arpcom arpcom;
128
129  /* The interrupt request number.  */
130  unsigned int irno;
131  /* The base IO port number.  */
132  unsigned int port;
133
134  /* Whether we accept broadcasts.  */
135  int accept_broadcasts;
136
137  /* The thread ID of the transmit task.   */
138  rtems_id tx_daemon_tid;
139  /* The thread ID of the receive task.  */
140  rtems_id rx_daemon_tid;
141
142  /* Whether we use byte-transfers with the device. */
[57bc54dc]143  bool byte_transfers;
[16a384cf]144
145  /* The number of memory buffers which the transmit daemon has loaded
146     with data to be sent, but which have not yet been completely
147     sent.  */
148  int inuse;
149  /* The index of the next available transmit memory buffer.  */
150  int nextavail;
151  /* The index of the next transmit buffer to send.  */
152  int nextsend;
153  /* Nonzero if the device is currently transmitting a packet.  */
154  int transmitting;
155  /* The length of the data stored in each transmit buffer.  */
156  int sendlen[NE_TX_BUFS];
157
158  /* Set if we have a packet overrun while receiving.  */
159  int overrun;
160  /* Set if we should resend after an overrun.  */
161  int resend;
162
163  /* Statistics.  */
164  struct {
165    /* Number of packets received.  */
166    unsigned long rx_packets;
167    /* Number of packets sent.  */
168    unsigned long tx_packets;
169    /* Number of interrupts.  */
170    unsigned long interrupts;
171    /* Number of receive acknowledgements.  */
172    unsigned long rx_acks;
173    /* Number of transmit acknowledgements.  */
174    unsigned long tx_acks;
175    /* Number of packet overruns.  */
176    unsigned long overruns;
177    /* Number of frame errors.  */
178    unsigned long rx_frame_errors;
179    /* Number of CRC errors.  */
180    unsigned long rx_crc_errors;
181    /* Number of missed packets.  */
182    unsigned long rx_missed_errors;
183  } stats;
184};
185
186/* The list of NE2000 devices on this system.  */
187
188static struct ne_softc ne_softc[NNEDRIVER];
189
190/* Find the NE2000 device which is attached at a particular interrupt
191   vector.  */
192
193static struct ne_softc *
194ne_device_for_irno (int irno)
195{
196  int i;
197
198  for (i = 0; i < NNEDRIVER; ++i)
199    {
200      if (ne_softc[i].irno == irno
201          && ne_softc[i].arpcom.ac_if.if_softc != NULL)
202        return &ne_softc[i];
203    }
204
205  return NULL;
206}
207
208/* Read data from an NE2000 device.  Read LEN bytes at ADDR, storing
209   them into P.  */
210
211static void
212ne_read_data (struct ne_softc *sc, int addr, int len, unsigned char *p)
213{
214  unsigned int port = sc->port;
215  unsigned int dport = port + DATAPORT;
216
217  outport_byte (port + CMDR, MSK_PG0 | MSK_RD2 | MSK_STA);
218  outport_byte (port + RBCR0, len);
219  outport_byte (port + RBCR1, len >> 8);
220  outport_byte (port + RSAR0, addr);
221  outport_byte (port + RSAR1, addr >> 8);
222  outport_byte (port + CMDR, MSK_PG0 | MSK_RRE | MSK_STA);
223
224  if (sc->byte_transfers)
225    while (len > 0) {
226      unsigned char d;
[6128a4a]227
[16a384cf]228      inport_byte (dport, d);
229      *p++ = d;
230      len--;
231    }
232  else  /* word transfers */
233    while (len > 0) {
234      unsigned short d;
[6128a4a]235
[16a384cf]236      inport_word (dport, d);
237      *p++ = d;
238      *p++ = d >> 8;
239      len -= 2;
240    }
241
242  outport_byte (port + ISR, MSK_RDC);
243}
244
245/* Handle the current NE2000 status.  This is called when the device
246   signals an interrupt.  It is also called at other times while
247   NE2000 interrupts have been disabled.  */
248
249static void
250ne_check_status (struct ne_softc *sc)
251{
252  unsigned int port = sc->port;
253  unsigned char status;
254
255  /* It seems that we need to use a loop here, because if the NE2000
256     signals an interrupt because packet transmission is complete, and
257     then receives a packet while interrupts are disabled, it seems to
258     sometimes fail to signal the interrupt for the received packet
259     when interrupts are reenabled.  (Based on the behaviour of the
260     Realtek 8019AS chip).  */
261
262  while (1) {
263    inport_byte (port + ISR, status);
264    if (status == 0)
265      break;
266
267#ifdef DEBUG_NE2000
268    printk ("NE2000 status 0x%x (8259 enabled: %s; mask: %x)\n", status,
269            i8259s_cache & (1 << sc->irno) ? "no" : "yes",
270            i8259s_cache);
271#endif
272
273    /* Check for incoming packet overwrite.  */
274    if (status & MSK_OVW) {
275      unsigned char status2;
276
277      ++sc->stats.overruns;
278      outport_byte (port + CMDR, MSK_PG0 | MSK_STP | MSK_RD2);
279      Wait_X_ms (2);
280      outport_byte (port + RBCR0, 0);
281      outport_byte (port + RBCR1, 0);
282      inport_byte (port + ISR, status2);
283      status |= status2 & (MSK_PTX | MSK_TXE);
284      outport_byte (port + TCR, MSK_LOOP);
285      outport_byte (port + CMDR, MSK_PG0 | MSK_STA | MSK_RD2);
286      sc->overrun = 1;
287      if ((status & (MSK_PTX | MSK_TXE)) == 0)
288        sc->resend = 1;
289      rtems_event_send (sc->rx_daemon_tid, INTERRUPT_EVENT);
290    }
291
292    /* Check for transmitted packet.  The transmit daemon may now be
293       able to send another packet to the device.  */
294    if ((status & (MSK_PTX | MSK_TXE)) != 0) {
295      ++sc->stats.tx_acks;
296      outport_byte (port + ISR, status & (MSK_PTX | MSK_TXE));
297      --sc->inuse;
298      sc->transmitting = 0;
299      if (sc->inuse > 0 || (sc->arpcom.ac_if.if_flags & IFF_OACTIVE) != 0)
300        rtems_event_send (sc->tx_daemon_tid, START_TRANSMIT_EVENT);
301    }
302
303    /* Check for received packet.  */
304    if ((status & (MSK_PRX | MSK_RXE)) != 0) {
305      ++sc->stats.rx_acks;
306      outport_byte (port + ISR, status & (MSK_PRX | MSK_RXE));
307      rtems_event_send (sc->rx_daemon_tid, INTERRUPT_EVENT);
308    }
309
310    /* Check for counter change.  */
311    if ((status & MSK_CNT) != 0) {
312      unsigned char add;
313
314      inport_byte (port + CNTR0, add);
315      sc->stats.rx_frame_errors += add;
316      inport_byte (port + CNTR1, add);
317      sc->stats.rx_crc_errors += add;
318      inport_byte (port + CNTR2, add);
319      sc->stats.rx_missed_errors += add;
320      outport_byte (port + ISR, MSK_CNT);
321    }
322  }
323
324  outport_byte (port + CMDR, MSK_PG0 | MSK_STA | MSK_RD2);
325}
326
327/* Handle an NE2000 interrupt.  */
328
329static rtems_isr
330ne_interrupt_handler (rtems_vector_number v)
331{
332  struct ne_softc *sc;
333
334  sc = ne_device_for_irno (v);
335  if (sc == NULL)
336    return;
337
338  ++sc->stats.interrupts;
339
340  ne_check_status (sc);
341}
342
343/* Turn NE2000 interrupts on.  */
344
345static void
346ne_interrupt_on (const rtems_irq_connect_data *irq)
347{
348  struct ne_softc *sc;
349
350#ifdef DEBUG_NE2000
351  printk ("ne_interrupt_on\n");
352#endif
353  sc = ne_device_for_irno (irq->name);
354  if (sc != NULL)
355    outport_byte (sc->port + IMR, NE_INTERRUPTS);
356}
357
358/* Turn NE2000 interrupts off.  See ne_interrupt_on.  */
359
360static void
361ne_interrupt_off (const rtems_irq_connect_data *irq)
362{
363  struct ne_softc *sc;
364
365#ifdef DEBUG_NE2000
366  printk ("ne_interrupt_off\n");
367#endif
368  sc = ne_device_for_irno (irq->name);
369  if (sc != NULL)
370    outport_byte (sc->port + IMR, 0);
371}
372
373/* Return whether NE2000 interrupts are on.  */
374
375static int
376ne_interrupt_is_on (const rtems_irq_connect_data *irq)
377{
378  return BSP_irq_enabled_at_i8259s (irq->name);
379}
380
381/* Initialize the NE2000 hardware.  */
382
383static void
384ne_init_hardware (struct ne_softc *sc)
385{
386  unsigned int port = sc->port;
387  int i;
388  rtems_irq_connect_data irq;
389
390#ifdef DEBUG_NE2000
391  printk ("ne_init_hardware\n");
392#endif
393
394  /* Initialize registers.  */
395
396  outport_byte (port + CMDR, MSK_PG0 | MSK_RD2 | MSK_STP);
397
398  if (sc->byte_transfers) {
399    outport_byte (port + DCR, MSK_FT10 | MSK_BMS);
400  }
401  else {
402    outport_byte (port + DCR, MSK_FT10 | MSK_BMS | MSK_WTS);
403  }
404
405  outport_byte (port + RBCR0, 0);
406  outport_byte (port + RBCR1, 0);
407  outport_byte (port + RCR, MSK_MON);
408  outport_byte (port + TCR, MSK_LOOP);
409  outport_byte (port + IMR, 0);
410  outport_byte (port + ISR, 0xff);
411  outport_byte (port + PSTOP, NE_STOP_PAGE);
412  outport_byte (port + PSTART, NE_FIRST_RX_PAGE);
413  outport_byte (port + BNRY, NE_STOP_PAGE - 1);
414
415  /* Set the Ethernet hardware address.  */
416
417  outport_byte (port + CMDR, MSK_PG1 | MSK_RD2);
418  for (i = 0; i < ETHER_ADDR_LEN; ++i)
419    outport_byte (port + PAR + i, sc->arpcom.ac_enaddr[i]);
420
421#ifdef DEBUG_NE2000
422  printk ("Using ethernet address: ");
423  for (i = 0; i < ETHER_ADDR_LEN; ++i)
424    printk("%x ",sc->arpcom.ac_enaddr[i]);
425  printk ("\n");
426#endif
427
428  /* Clear the multicast address.  */
429  for (i = 0; i < MARsize; ++i)
430    outport_byte (port + MAR + i, 0);
431
432  outport_byte (port + CURR, NE_FIRST_RX_PAGE);
433
434  outport_byte (port + CMDR, MSK_PG0 | MSK_RD2);
435
436  /* Put the device on line.  */
437  outport_byte (port + CMDR, MSK_PG0 | MSK_STA | MSK_RD2);
438
439  /* Set up interrupts.  */
440
441  irq.name = sc->irno;
[202ed85]442  irq.hdl = (rtems_irq_hdl)ne_interrupt_handler;
[16a384cf]443  irq.on = ne_interrupt_on;
444  irq.off = ne_interrupt_off;
445  irq.isOn = ne_interrupt_is_on;
446
447  if (! BSP_install_rtems_irq_handler (&irq))
448    rtems_panic ("Can't attach NE interrupt handler for irq %d.\n",
449                 sc->irno);
450
451  /* Prepare to receive packets.  */
452
453  outport_byte (port + TCR, 0);
454  outport_byte (port + RCR, (sc->accept_broadcasts ? MSK_AB : 0));
455}
456
457/* The NE2000 packet receive daemon.  This task is started when the
458   NE2000 driver is initialized.  */
459
460static void
461ne_rx_daemon (void *arg)
462{
463  struct ne_softc *sc = (struct ne_softc *) arg;
464  struct ifnet *ifp = &sc->arpcom.ac_if;
465  unsigned int port = sc->port;
466  unsigned int dport = port + DATAPORT;
467
468  while (1) {
469    rtems_event_set events;
470
471    /* Wait for the interrupt handler to tell us that there is a
472       packet ready to receive.  */
473    rtems_bsdnet_event_receive (INTERRUPT_EVENT,
474                                RTEMS_WAIT | RTEMS_EVENT_ANY,
475                                RTEMS_NO_TIMEOUT,
476                                &events);
477
478    /* Don't let the device interrupt us now.  */
479    outport_byte (port + IMR, 0);
480
481    while (1) {
482      unsigned char startpage, currpage;
483      unsigned short statnext, len;
484      int next;
485      struct mbuf *m;
486      unsigned char *p;
487      int startaddr;
488      int toend;
489      struct ether_header *eh;
490
491      inport_byte (port + BNRY, startpage);
492
493      outport_byte (port + CMDR, MSK_PG1 | MSK_RD2);
494      inport_byte (port + CURR, currpage);
495      outport_byte (port + CMDR, MSK_PG0 | MSK_RD2);
496
497      ++startpage;
498      if (startpage >= NE_STOP_PAGE)
499        startpage = NE_FIRST_RX_PAGE;
500
501      if (startpage == currpage)
502        break;
503
504#ifdef DEBUG_NE2000
505      printk ("ne_rx_daemon: start page %x; current page %x\n",
506              startpage, currpage);
507#endif
508
509      /* Read the buffer header.  This is 1 byte receive status, 1
510         byte page of next buffer, 2 bytes length.  */
511      outport_byte (port + CMDR, MSK_PG0 | MSK_RD2 | MSK_STA);
512      outport_byte (port + RBCR0, 4);
513      outport_byte (port + RBCR1, 0);
514      outport_byte (port + RSAR0, 0);
515      outport_byte (port + RSAR1, startpage);
516      outport_byte (port + CMDR, MSK_PG0 | MSK_RRE | MSK_STA);
517
518      if (sc->byte_transfers) {
519        unsigned char data;
520
521        inport_byte (dport, data);  /* Throw away status  */
522        inport_byte (dport, data);
523        next = data;
524
525        inport_byte (dport, data);
526        len = data;
527        inport_byte (dport, data);
528        len |= data << 8;
529      }
530      else {                        /* Word transfers  */
531        inport_word (dport, statnext);
532        inport_word (dport, len);
533
534        next = statnext >> 8;
535      }
536
537      outport_byte (port + ISR, MSK_RDC);
538
539      if (next >= NE_STOP_PAGE)
540        next = NE_FIRST_RX_PAGE;
541
542      /* The first four bytes of the length are the buffer header.  */
543      len -= 4;
544      startaddr = startpage * NE_PAGE_SIZE + 4;
545
546      MGETHDR (m, M_WAIT, MT_DATA);
547      MCLGET (m, M_WAIT);
548      m->m_pkthdr.rcvif = ifp;
549
550      p = mtod (m, unsigned char *);
551      m->m_len = m->m_pkthdr.len = len - sizeof (struct ether_header);
552
553      toend = NE_STOP_PAGE * NE_PAGE_SIZE - startaddr;
554      if (toend < len) {
555        ne_read_data (sc, startaddr, toend, p);
556        p += toend;
557        len -= toend;
558        startaddr = NE_FIRST_RX_PAGE * NE_PAGE_SIZE;
559      }
560
561      if (len > 0)
562        ne_read_data (sc, startaddr, len, p);
563
564      eh = mtod (m, struct ether_header *);
565      m->m_data += sizeof (struct ether_header);
566      ether_input (ifp, eh, m);
567
568      ++sc->stats.rx_packets;
569
570      outport_byte (port + BNRY, next - 1);
571    }
572
573    if (sc->overrun) {
574      outport_byte (port + ISR, MSK_OVW);
575      outport_byte (port + TCR, 0);
576      if (sc->resend)
577        outport_byte (port + CMDR, MSK_PG0 | MSK_TXP | MSK_RD2 | MSK_STA);
578      sc->resend = 0;
579      sc->overrun = 0;
580    }
581
582    /* Reenable device interrupts.  */
583    outport_byte (port + IMR, NE_INTERRUPTS);
584  }
585}
586
587/* Load an NE2000 packet onto the device.  */
588
589static void
590ne_loadpacket (struct ne_softc *sc, struct mbuf *m)
591{
592  unsigned int port = sc->port;
593  unsigned int dport = port + DATAPORT;
594  struct mbuf *mhold = m;
595  int leftover;
596  unsigned char leftover_data;
597  int timeout;
598
599#ifdef DEBUG_NE2000
600  printk ("Uploading NE2000 packet\n");
601#endif
602
603  /* Reset remote DMA complete flag.  */
604  outport_byte (port + ISR, MSK_RDC);
605
606  /* Write out the count.  */
607  outport_byte (port + RBCR0, m->m_pkthdr.len);
608  outport_byte (port + RBCR1, m->m_pkthdr.len >> 8);
609
610  sc->sendlen[sc->nextavail] = m->m_pkthdr.len;
611
612  /* Tell the device which address we want to write to.  */
613  outport_byte (port + RSAR0, 0);
614  outport_byte (port + RSAR1,
615                NE_FIRST_TX_PAGE + (sc->nextavail * NE_TX_PAGES));
616
617  /* Set up the write.  */
618  outport_byte (port + CMDR, MSK_PG0 | MSK_RWR | MSK_STA);
619
620  /* Transfer the mbuf chain to device memory.  NE2000 devices require
621     that the data be transferred as words, so we need to handle odd
622     length mbufs.  Never occurs if we force byte transfers. */
623
624  leftover = 0;
625  leftover_data = '\0';
626
627  for (; m != NULL; m = m->m_next) {
628    int len;
629    unsigned char *data;
630
631    len = m->m_len;
632    if (len == 0)
633      continue;
634
635    data = mtod (m, unsigned char *);
636
637    if (leftover) {
638      unsigned char next;
639
640      /* Data left over from previous mbuf in chain.  */
641      next = *data++;
642      --len;
643      outport_word (dport, leftover_data | (next << 8));
644      leftover = 0;
645    }
646
[6128a4a]647    /* If using byte transfers, len always ends up as zero so
[16a384cf]648       there are no leftovers. */
649
650    if (sc->byte_transfers)
651      while (len > 0) {
652        outport_byte (dport, *data++);
653        len--;
654      }
655    else
656      while (len > 1) {
657        outport_word (dport, data[0] | (data[1] << 8));
658        data += 2;
659        len -= 2;
660      }
661
662    if (len > 0)
663      {
664        leftover = 1;
665        leftover_data = *data++;
666      }
667  }
668
669  if (leftover)
670    outport_word (dport, leftover_data);
671
672  m_freem (mhold);
673
674  /* Wait for the device to complete accepting the data, with a
675     limiting counter so that we don't wait too long.  */
676  for (timeout = 0; timeout < 100; ++timeout)
677    {
678      unsigned char status;
679
680      inport_byte (port + ISR, status);
681
682#ifdef DEBUG_NE2000
683      if ((status &~ MSK_RDC) != 0)
684        printk ("Status 0x%x while waiting for acknowledgement of uploaded packet\n",
685                status);
686#endif
687
688      if ((status & MSK_RDC) != 0) {
689        outport_byte (port + ISR, MSK_RDC);
690        break;
691      }
692    }
693
694  if (timeout >= 100)
695    printk ("Timed out waiting for acknowledgement of uploaded NE2000 packet\n");
696
697  ++sc->nextavail;
698  if (sc->nextavail == NE_TX_BUFS)
699    sc->nextavail = 0;
700}
701
702/* Tell the NE2000 to transmit a buffer whose contents we have already
703   loaded onto the device.  */
704
705static void
706ne_transmit (struct ne_softc *sc)
707{
708  unsigned int port = sc->port;
709  int len;
710
711#ifdef DEBUG_NE2000
712  printk ("Transmitting NE2000 packet\n");
713#endif
714
715  len = sc->sendlen[sc->nextsend];
716  if (len < ET_MINLEN)
717    len = ET_MINLEN;
718  outport_byte (port + TBCR0, len);
719  outport_byte (port + TBCR1, len >> 8);
720
721  outport_byte (port + TPSR, NE_FIRST_TX_PAGE + (sc->nextsend * NE_TX_PAGES));
722
723  outport_byte (port + CMDR, MSK_PG0 | MSK_TXP | MSK_RD2 | MSK_STA);
724
725  ++sc->nextsend;
726  if (sc->nextsend == NE_TX_BUFS)
727    sc->nextsend = 0;
728
729  ++sc->stats.tx_packets;
730}
731
732/* The NE2000 packet transmit daemon.  This task is started when the
733   NE2000 driver is initialized.  */
734
735static void
736ne_tx_daemon (void *arg)
737{
738  struct ne_softc *sc = (struct ne_softc *) arg;
739  unsigned int port = sc->port;
740  struct ifnet *ifp = &sc->arpcom.ac_if;
741
742  while (1) {
743    rtems_event_set events;
744
745    /* Wait for a packet to be ready for sending, or for there to be
746       room for another packet in the device memory.  */
747    rtems_bsdnet_event_receive (START_TRANSMIT_EVENT,
748                                RTEMS_EVENT_ANY | RTEMS_WAIT,
749                                RTEMS_NO_TIMEOUT,
750                                &events);
751
752#ifdef DEBUG_NE2000
753    printk ("ne_tx_daemon\n");
754#endif
755
756    /* This daemon handles both uploading data onto the device and
757       telling the device to transmit data which has been uploaded.
758       These are separate tasks, because while the device is
759       transmitting one buffer we will upload another.  */
760
761    /* Don't let the device interrupt us now.  */
762    outport_byte (port + IMR, 0);
763
764    while (1) {
765      struct mbuf *m;
766
767      /* If the device is not transmitting a packet, and we have
768         uploaded a packet, tell the device to transmit it.  */
769      if (! sc->transmitting && sc->inuse > 0) {
770        sc->transmitting = 1;
771        ne_transmit (sc);
772      }
773
774      /* If we don't have any more buffers to send, quit now.  */
775      if (ifp->if_snd.ifq_head == NULL) {
776        ifp->if_flags &= ~IFF_OACTIVE;
777        break;
778      }
779
780      /* Allocate a buffer to load data into.  If there are none
781         available, quit until a buffer has been transmitted.  */
782      if (sc->inuse >= NE_TX_BUFS)
783        break;
784
785      ++sc->inuse;
786
787      IF_DEQUEUE (&ifp->if_snd, m);
788      if (m == NULL)
789        panic ("ne_tx_daemon");
790
791      ne_loadpacket (sc, m);
792
793      /* Check the device status.  It may have finished transmitting
794         the last packet.  */
795      ne_check_status (sc);
796    }
797
798    /* Reenable device interrupts.  */
799    outport_byte (port + IMR, NE_INTERRUPTS);
800  }
801}
802
803/* Start sending an NE2000 packet.  */
804
805static void
806ne_start (struct ifnet *ifp)
807{
808  struct ne_softc *sc = ifp->if_softc;
809
810  /* Tell the transmit daemon to wake up and send a packet.  */
811  rtems_event_send (sc->tx_daemon_tid, START_TRANSMIT_EVENT);
812  ifp->if_flags |= IFF_OACTIVE;
813}
814
815/* Initialize and start and NE2000.  */
816
817static void
818ne_init (void *arg)
819{
820  struct ne_softc *sc = (struct ne_softc *) arg;
821  struct ifnet *ifp = &sc->arpcom.ac_if;
822
823  if (sc->tx_daemon_tid == 0) {
824    sc->inuse = 0;
825    sc->nextavail = 0;
826    sc->nextsend = 0;
827    sc->transmitting = 0;
828
829    ne_init_hardware (sc);
830
831    sc->tx_daemon_tid = rtems_bsdnet_newproc ("SCtx", 4096, ne_tx_daemon, sc);
832    sc->rx_daemon_tid = rtems_bsdnet_newproc ("SCrx", 4096, ne_rx_daemon, sc);
833  }
834
835  ifp->if_flags |= IFF_RUNNING;
836}
837
838/* Stop an NE2000.  */
839
840static void
841ne_stop (struct ne_softc *sc)
842{
843  unsigned int port = sc->port;
844  int i;
845
846  sc->arpcom.ac_if.if_flags &= ~IFF_RUNNING;
847
848  /* Stop everything.  */
849  outport_byte (port + CMDR, MSK_STP | MSK_RD2);
850
851  /* Wait for the interface to stop, using I as a time limit.  */
852  for (i = 0; i < 5000; ++i)
853    {
854      unsigned char status;
855
856      inport_byte (port + ISR, status);
857      if ((status & MSK_RST) != 0)
858        break;
859    }
860
861  sc->inuse = 0;
862  sc->nextavail = 0;
863  sc->nextsend = 0;
864  sc->transmitting = 0;
865}
866
867/* Show NE2000 interface statistics.  */
868
869static void
870ne_stats (struct ne_softc *sc)
871{
872  printf ("    Received packets: %-8lu", sc->stats.rx_packets);
873  printf (" Transmitted packets: %-8lu\n", sc->stats.tx_packets);
874  printf ("        Receive acks: %-8lu", sc->stats.rx_acks);
875  printf ("       Transmit acks: %-8lu\n", sc->stats.tx_acks);
876  printf ("     Packet overruns: %-8lu", sc->stats.overruns);
877  printf ("        Frame errors: %-8lu\n", sc->stats.rx_frame_errors);
878  printf ("          CRC errors: %-8lu", sc->stats.rx_crc_errors);
879  printf ("      Missed packets: %-8lu\n", sc->stats.rx_missed_errors);
880  printf ("          Interrupts: %-8lu\n", sc->stats.interrupts);
881}
882
883/* NE2000 driver ioctl handler.  */
884
885static int
[ff73cf6]886ne_ioctl (struct ifnet *ifp, ioctl_command_t command, caddr_t data)
[16a384cf]887{
888  struct ne_softc *sc = ifp->if_softc;
889  int error = 0;
890
891  switch (command) {
892  case SIOCGIFADDR:
893  case SIOCSIFADDR:
894    error = ether_ioctl (ifp, command, data);
895    break;
896
897  case SIOCSIFFLAGS:
898    switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) {
899    case IFF_RUNNING:
900      ne_stop (sc);
901      break;
902
903    case IFF_UP:
904      ne_init (sc);
905      break;
906
907    case IFF_UP | IFF_RUNNING:
908      ne_stop (sc);
909      ne_init (sc);
910      break;
911
912    default:
913      break;
914    }
915    break;
916
917  case SIO_RTEMS_SHOW_STATS:
918    ne_stats (sc);
919    break;
920
921    /* FIXME: Multicast commands must be added here.  */
922
923  default:
924    error = EINVAL;
925    break;
926  }
927
928  return error;
929}
930
931/* Attach an NE2000 driver to the system.  */
932
933int
934rtems_ne_driver_attach (struct rtems_bsdnet_ifconfig *config)
935{
936  int i;
937  struct ne_softc *sc;
938  struct ifnet *ifp;
939  int mtu;
940
941  /* Find a free driver.  */
942  sc = NULL;
943  for (i = 0; i < NNEDRIVER; ++i) {
944    sc = &ne_softc[i];
945    ifp = &sc->arpcom.ac_if;
946    if (ifp->if_softc == NULL)
947      break;
948  }
949
950  if (sc == NULL) {
951    printf ("Too many NE2000 drivers.\n");
952    return 0;
953  }
954
955  memset (sc, 0, sizeof *sc);
956
957  /* Check whether we do byte-wide or word-wide transfers.  */
[6128a4a]958
[16a384cf]959#ifdef NE2000_BYTE_TRANSFERS
[57bc54dc]960  sc->byte_transfers = true;
[16a384cf]961#else
[57bc54dc]962  sc->byte_transfers = false;
[16a384cf]963#endif
964
965  /* Handle the options passed in by the caller.  */
966
967  if (config->mtu != 0)
968    mtu = config->mtu;
969  else
970    mtu = ETHERMTU;
971
972  if (config->irno != 0)
973    sc->irno = config->irno;
974  else {
975    /* We use 5 as the default IRQ.  */
976    sc->irno = 5;
977  }
978
979  if (config->port != 0)
980    sc->port = config->port;
981  else {
982    /* We use 0x300 as the default IO port number.  */
983    sc->port = 0x300;
984  }
985
986  sc->accept_broadcasts = ! config->ignore_broadcast;
987
988  if (config->hardware_address != NULL)
989    memcpy (sc->arpcom.ac_enaddr, config->hardware_address,
990            ETHER_ADDR_LEN);
991  else
992    {
993      unsigned char prom[16];
994      int ia;
995
996      /* Read the PROM to get the Ethernet hardware address.  */
997
998      outport_byte (sc->port + CMDR, MSK_PG0 | MSK_RD2 | MSK_STP);
999
1000      if (sc->byte_transfers) {
1001        outport_byte (sc->port + DCR, MSK_FT10 | MSK_BMS);
1002      }
1003      else {
1004        outport_byte (sc->port + DCR, MSK_FT10 | MSK_BMS | MSK_WTS);
1005      }
1006
1007      outport_byte (sc->port + RBCR0, 0);
1008      outport_byte (sc->port + RBCR1, 0);
1009      outport_byte (sc->port + RCR, MSK_MON);
1010      outport_byte (sc->port + TCR, MSK_LOOP);
1011      outport_byte (sc->port + IMR, 0);
1012      outport_byte (sc->port + ISR, 0xff);
1013
1014      ne_read_data (sc, 0, sizeof prom, prom);
1015
1016      outport_byte (sc->port + CMDR, MSK_PG0 | MSK_RD2 | MSK_STP);
1017
1018      for (ia = 0; ia < ETHER_ADDR_LEN; ++ia)
1019        sc->arpcom.ac_enaddr[ia] = prom[ia * 2];
1020    }
1021
1022  /* Set up the network interface.  */
1023
1024  ifp->if_softc = sc;
1025  ifp->if_unit = i + 1;
1026  ifp->if_name = "ne";
1027  ifp->if_mtu = mtu;
1028  ifp->if_init = ne_init;
1029  ifp->if_ioctl = ne_ioctl;
1030  ifp->if_start = ne_start;
1031  ifp->if_output = ether_output;
1032  ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;
1033  if (ifp->if_snd.ifq_maxlen == 0)
1034    ifp->if_snd.ifq_maxlen = ifqmaxlen;
1035
1036  /* Attach the interface.  */
1037
1038  if_attach (ifp);
1039  ether_ifattach (ifp);
1040
1041  return 1;
1042}
Note: See TracBrowser for help on using the repository browser.