source: rtems/c/src/lib/libbsp/i386/pc386/ne2000/ne2000.c @ 3204a06

4.104.114.84.95
Last change on this file since 3204a06 was 3204a06, checked in by Joel Sherrill <joel.sherrill@…>, on 02/18/99 at 20:58:46

Added comments.

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