source: rtems/c/src/lib/libbsp/i386/pc386/ne2000/ne2000.c @ 1105818d

4.104.114.84.95
Last change on this file since 1105818d was 1105818d, checked in by Joel Sherrill <joel.sherrill@…>, on Mar 18, 1999 at 4:36:50 PM

Patch from Ian Lance Taylor <ian@…>:

Erik Ivanenko pointed out a problem in the ne2000.c driver I
submitted: it did not work correctly with bootp. Here is a patch,
based on a patch he sent me.

  • Property mode set to 100644
File size: 24.2 KB
Line 
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$
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.
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  int i;
369  rtems_irq_connect_data irq;
370
371#ifdef DEBUG_NE2000
372  printk ("ne_init_hardware\n");
373#endif
374
375  /* Initialize registers.  */
376
377  outport_byte (port + CMDR, MSK_PG0 | MSK_RD2 | MSK_STP);
378  outport_byte (port + DCR, MSK_FT10 | MSK_BMS | MSK_WTS);
379  outport_byte (port + RBCR0, 0);
380  outport_byte (port + RBCR1, 0);
381  outport_byte (port + RCR, MSK_MON);
382  outport_byte (port + TCR, MSK_LOOP);
383  outport_byte (port + IMR, 0);
384  outport_byte (port + ISR, 0xff);
385  outport_byte (port + PSTOP, NE_STOP_PAGE);
386  outport_byte (port + PSTART, NE_FIRST_RX_PAGE);
387  outport_byte (port + BNRY, NE_STOP_PAGE - 1);
388
389  /* Set the Ethernet hardware address.  */
390
391  outport_byte (port + CMDR, MSK_PG1 | MSK_RD2);
392  for (i = 0; i < ETHER_ADDR_LEN; ++i)
393    outport_byte (port + PAR + i, sc->arpcom.ac_enaddr[i]);
394
395  /* Clear the multicast address.  */
396  for (i = 0; i < MARsize; ++i)
397    outport_byte (port + MAR + i, 0);
398
399  outport_byte (port + CURR, NE_FIRST_RX_PAGE);
400
401  outport_byte (port + CMDR, MSK_PG0 | MSK_RD2);
402
403  /* Put the device on line.  */
404  outport_byte (port + CMDR, MSK_PG0 | MSK_STA | MSK_RD2);
405
406  /* Set up interrupts.  */
407
408  irq.name = sc->irno;
409  irq.hdl = ne_interrupt_handler;
410  irq.on = ne_interrupt_on;
411  irq.off = ne_interrupt_off;
412  irq.isOn = ne_interrupt_is_on;
413
414  if (! BSP_install_rtems_irq_handler (&irq))
415    rtems_panic ("Can't attach NE interrupt handler for irq %d.\n",
416                 sc->irno);
417
418  /* Prepare to receive packets.  */
419
420  outport_byte (port + TCR, 0);
421  outport_byte (port + RCR, (sc->accept_broadcasts ? MSK_AB : 0));
422}
423
424/* The NE2000 packet receive daemon.  This task is started when the
425   NE2000 driver is initialized.  */
426
427static void
428ne_rx_daemon (void *arg)
429{
430  struct ne_softc *sc = (struct ne_softc *) arg;
431  struct ifnet *ifp = &sc->arpcom.ac_if;
432  unsigned int port = sc->port;
433  unsigned int dport = port + DATAPORT;
434
435  while (1) {
436    rtems_event_set events;
437
438    /* Wait for the interrupt handler to tell us that there is a
439       packet ready to receive.  */
440    rtems_bsdnet_event_receive (INTERRUPT_EVENT,
441                                RTEMS_WAIT | RTEMS_EVENT_ANY,
442                                RTEMS_NO_TIMEOUT,
443                                &events);
444
445    /* Don't let the device interrupt us now.  */
446    outport_byte (port + IMR, 0);
447
448    while (1) {
449      unsigned char startpage, currpage;
450      unsigned short statnext, len;
451      int next;
452      struct mbuf *m;
453      unsigned char *p;
454      int startaddr;
455      int toend;
456      struct ether_header *eh;
457
458      inport_byte (port + BNRY, startpage);
459
460      outport_byte (port + CMDR, MSK_PG1 | MSK_RD2);
461      inport_byte (port + CURR, currpage);
462      outport_byte (port + CMDR, MSK_PG0 | MSK_RD2);
463
464      ++startpage;
465      if (startpage >= NE_STOP_PAGE)
466        startpage = NE_FIRST_RX_PAGE;
467
468      if (startpage == currpage)
469        break;
470
471#ifdef DEBUG_NE2000
472      printk ("ne_rx_daemon: start page %x; current page %x\n",
473              startpage, currpage);
474#endif
475
476      /* Read the buffer header.  This is 1 byte receive status, 1
477         byte page of next buffer, 2 bytes length.  */
478      outport_byte (port + CMDR, MSK_PG0 | MSK_RD2 | MSK_STA);
479      outport_byte (port + RBCR0, 4);
480      outport_byte (port + RBCR1, 0);
481      outport_byte (port + RSAR0, 0);
482      outport_byte (port + RSAR1, startpage);
483      outport_byte (port + CMDR, MSK_PG0 | MSK_RRE | MSK_STA);
484
485      inport_word (dport, statnext);
486      inport_word (dport, len);
487
488      outport_byte (port + ISR, MSK_RDC);
489
490      next = statnext >> 8;
491      if (next >= NE_STOP_PAGE)
492        next = NE_FIRST_RX_PAGE;
493
494      /* The first four bytes of the length are the buffer header.  */
495      len -= 4;
496      startaddr = startpage * NE_PAGE_SIZE + 4;
497
498      MGETHDR (m, M_WAIT, MT_DATA);
499      MCLGET (m, M_WAIT);
500      m->m_pkthdr.rcvif = ifp;
501
502      p = mtod (m, unsigned char *);
503      m->m_len = m->m_pkthdr.len = len - sizeof (struct ether_header);
504
505      toend = NE_STOP_PAGE * NE_PAGE_SIZE - startaddr;
506      if (toend < len) {
507        ne_read_data (sc, startaddr, toend, p);
508        p += toend;
509        len -= toend;
510        startaddr = NE_FIRST_RX_PAGE * NE_PAGE_SIZE;
511      }
512
513      if (len > 0)
514        ne_read_data (sc, startaddr, len, p);
515
516      eh = mtod (m, struct ether_header *);
517      m->m_data += sizeof (struct ether_header);
518      ether_input (ifp, eh, m);
519
520      ++sc->stats.rx_packets;
521
522      outport_byte (port + BNRY, next - 1);
523    }
524
525    if (sc->overrun) {
526      outport_byte (port + ISR, MSK_OVW);
527      outport_byte (port + TCR, 0);
528      if (sc->resend)
529        outport_byte (port + CMDR, MSK_PG0 | MSK_TXP | MSK_RD2 | MSK_STA);
530      sc->resend = 0;
531      sc->overrun = 0;
532    }
533
534    /* Reenable device interrupts.  */
535    outport_byte (port + IMR, NE_INTERRUPTS);
536  }
537}
538
539/* Load an NE2000 packet onto the device.  */
540
541static void
542ne_loadpacket (struct ne_softc *sc, struct mbuf *m)
543{
544  unsigned int port = sc->port;
545  unsigned int dport = port + DATAPORT;
546  struct mbuf *mhold = m;
547  int leftover;
548  unsigned char leftover_data;
549  int timeout;
550
551#ifdef DEBUG_NE2000
552  printk ("Uploading NE2000 packet\n");
553#endif
554
555  /* Reset remote DMA complete flag.  */
556  outport_byte (port + ISR, MSK_RDC);
557
558  /* Write out the count.  */
559  outport_byte (port + RBCR0, m->m_pkthdr.len);
560  outport_byte (port + RBCR1, m->m_pkthdr.len >> 8);
561
562  sc->sendlen[sc->nextavail] = m->m_pkthdr.len;
563
564  /* Tell the device which address we want to write to.  */
565  outport_byte (port + RSAR0, 0);
566  outport_byte (port + RSAR1,
567                NE_FIRST_TX_PAGE + (sc->nextavail * NE_TX_PAGES));
568
569  /* Set up the write.  */
570  outport_byte (port + CMDR, MSK_PG0 | MSK_RWR | MSK_STA);
571
572  /* Transfer the mbuf chain to device memory.  NE2000 devices require
573     that the data be transferred as words, so we need to handle odd
574     length mbufs.  */
575
576  leftover = 0;
577  leftover_data = '\0';
578
579  for (; m != NULL; m = m->m_next) {
580    int len;
581    unsigned char *data;
582
583    len = m->m_len;
584    if (len == 0)
585      continue;
586
587    data = mtod (m, unsigned char *);
588
589    if (leftover) {
590      unsigned char next;
591
592      /* Data left over from previous mbuf in chain.  */
593      next = *data++;
594      --len;
595      outport_word (dport, leftover_data | (next << 8));
596      leftover = 0;
597    }
598
599    while (len > 1) {
600      outport_word (dport, data[0] | (data[1] << 8));
601      data += 2;
602      len -= 2;
603    }
604
605    if (len > 0)
606      {
607        leftover = 1;
608        leftover_data = *data++;
609      }
610  }
611
612  if (leftover)
613    outport_word (dport, leftover_data);
614
615  m_freem (mhold);
616
617  /* Wait for the device to complete accepting the data, with a
618     limiting counter so that we don't wait too long.  */
619  for (timeout = 0; timeout < 100; ++timeout)
620    {
621      unsigned char status;
622
623      inport_byte (port + ISR, status);
624
625#ifdef DEBUG_NE2000
626      if ((status &~ MSK_RDC) != 0)
627        printk ("Status 0x%x while waiting for acknowledgement of uploaded packet\n",
628                status);
629#endif
630
631      if ((status & MSK_RDC) != 0) {
632        outport_byte (port + ISR, MSK_RDC);
633        break;
634      }
635    }
636
637  if (timeout >= 100)
638    printk ("Timed out waiting for acknowledgement of uploaded NE2000 packet\n");
639
640  ++sc->nextavail;
641  if (sc->nextavail == NE_TX_BUFS)
642    sc->nextavail = 0;
643}
644
645/* Tell the NE2000 to transmit a buffer whose contents we have already
646   loaded onto the device.  */
647
648static void
649ne_transmit (struct ne_softc *sc)
650{
651  unsigned int port = sc->port;
652  int len;
653
654#ifdef DEBUG_NE2000
655  printk ("Transmitting NE2000 packet\n");
656#endif
657
658  len = sc->sendlen[sc->nextsend];
659  if (len < ET_MINLEN)
660    len = ET_MINLEN;
661  outport_byte (port + TBCR0, len);
662  outport_byte (port + TBCR1, len >> 8);
663
664  outport_byte (port + TPSR, NE_FIRST_TX_PAGE + (sc->nextsend * NE_TX_PAGES));
665
666  outport_byte (port + CMDR, MSK_PG0 | MSK_TXP | MSK_RD2 | MSK_STA);
667
668  ++sc->nextsend;
669  if (sc->nextsend == NE_TX_BUFS)
670    sc->nextsend = 0;
671
672  ++sc->stats.tx_packets;
673}
674
675/* The NE2000 packet transmit daemon.  This task is started when the
676   NE2000 driver is initialized.  */
677
678static void
679ne_tx_daemon (void *arg)
680{
681  struct ne_softc *sc = (struct ne_softc *) arg;
682  unsigned int port = sc->port;
683  struct ifnet *ifp = &sc->arpcom.ac_if;
684
685  while (1) {
686    rtems_event_set events;
687
688    /* Wait for a packet to be ready for sending, or for there to be
689       room for another packet in the device memory.  */
690    rtems_bsdnet_event_receive (START_TRANSMIT_EVENT,
691                                RTEMS_EVENT_ANY | RTEMS_WAIT,
692                                RTEMS_NO_TIMEOUT,
693                                &events);
694
695#ifdef DEBUG_NE2000
696    printk ("ne_tx_daemon\n");
697#endif
698
699    /* This daemon handles both uploading data onto the device and
700       telling the device to transmit data which has been uploaded.
701       These are separate tasks, because while the device is
702       transmitting one buffer we will upload another.  */
703
704    /* Don't let the device interrupt us now.  */
705    outport_byte (port + IMR, 0);
706
707    while (1) {
708      struct mbuf *m;
709
710      /* If the device is not transmitting a packet, and we have
711         uploaded a packet, tell the device to transmit it.  */
712      if (! sc->transmitting && sc->inuse > 0) {
713        sc->transmitting = 1;
714        ne_transmit (sc);
715      }
716
717      /* If we don't have any more buffers to send, quit now.  */
718      if (ifp->if_snd.ifq_head == NULL) {
719        ifp->if_flags &= ~IFF_OACTIVE;
720        break;
721      }
722
723      /* Allocate a buffer to load data into.  If there are none
724         available, quit until a buffer has been transmitted.  */
725      if (sc->inuse >= NE_TX_BUFS)
726        break;
727
728      ++sc->inuse;
729
730      IF_DEQUEUE (&ifp->if_snd, m);
731      if (m == NULL)
732        panic ("ne_tx_daemon");
733
734      ne_loadpacket (sc, m);
735
736      /* Check the device status.  It may have finished transmitting
737         the last packet.  */
738      ne_check_status (sc);
739    }
740
741    /* Reenable device interrupts.  */
742    outport_byte (port + IMR, NE_INTERRUPTS);
743  }
744}
745
746/* Start sending an NE2000 packet.  */
747
748static void
749ne_start (struct ifnet *ifp)
750{
751  struct ne_softc *sc = ifp->if_softc;
752
753  /* Tell the transmit daemon to wake up and send a packet.  */
754  rtems_event_send (sc->tx_daemon_tid, START_TRANSMIT_EVENT);
755  ifp->if_flags |= IFF_OACTIVE;
756}
757
758/* Initialize and start and NE2000.  */
759
760static void
761ne_init (void *arg)
762{
763  struct ne_softc *sc = (struct ne_softc *) arg;
764  struct ifnet *ifp = &sc->arpcom.ac_if;
765
766  if (sc->tx_daemon_tid == 0) {
767    sc->inuse = 0;
768    sc->nextavail = 0;
769    sc->nextsend = 0;
770    sc->transmitting = 0;
771
772    ne_init_hardware (sc);
773
774    sc->tx_daemon_tid = rtems_bsdnet_newproc ("SCtx", 4096, ne_tx_daemon, sc);
775    sc->rx_daemon_tid = rtems_bsdnet_newproc ("SCrx", 4096, ne_rx_daemon, sc);
776  }
777
778  ifp->if_flags |= IFF_RUNNING;
779}
780
781/* Stop an NE2000.  */
782
783static void
784ne_stop (struct ne_softc *sc)
785{
786  unsigned int port = sc->port;
787  int i;
788
789  sc->arpcom.ac_if.if_flags &= ~IFF_RUNNING;
790
791  /* Stop everything.  */
792  outport_byte (port + CMDR, MSK_STP | MSK_RD2);
793
794  /* Wait for the interface to stop, using I as a time limit.  */
795  for (i = 0; i < 5000; ++i)
796    {
797      unsigned char status;
798
799      inport_byte (port + ISR, status);
800      if ((status & MSK_RST) != 0)
801        break;
802    }
803
804  sc->inuse = 0;
805  sc->nextavail = 0;
806  sc->nextsend = 0;
807  sc->transmitting = 0;
808}
809
810/* Show NE2000 interface statistics.  */
811
812static void
813ne_stats (struct ne_softc *sc)
814{
815  printf ("    Received packets: %-8lu", sc->stats.rx_packets);
816  printf (" Transmitted packets: %-8lu\n", sc->stats.tx_packets);
817  printf ("        Receive acks: %-8lu", sc->stats.rx_acks);
818  printf ("       Transmit acks: %-8lu\n", sc->stats.tx_acks);
819  printf ("     Packet overruns: %-8lu", sc->stats.overruns);
820  printf ("        Frame errors: %-8lu\n", sc->stats.rx_frame_errors);
821  printf ("          CRC errors: %-8lu", sc->stats.rx_crc_errors);
822  printf ("      Missed packets: %-8lu\n", sc->stats.rx_missed_errors);
823  printf ("          Interrupts: %-8lu\n", sc->stats.interrupts);
824}
825
826/* NE2000 driver ioctl handler.  */
827
828static int
829ne_ioctl (struct ifnet *ifp, int command, caddr_t data)
830{
831  struct ne_softc *sc = ifp->if_softc;
832  int error = 0;
833
834  switch (command) {
835  case SIOCGIFADDR:
836  case SIOCSIFADDR:
837    error = ether_ioctl (ifp, command, data);
838    break;
839
840  case SIOCSIFFLAGS:
841    switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) {
842    case IFF_RUNNING:
843      ne_stop (sc);
844      break;
845
846    case IFF_UP:
847      ne_init (sc);
848      break;
849
850    case IFF_UP | IFF_RUNNING:
851      ne_stop (sc);
852      ne_init (sc);
853      break;
854
855    default:
856      break;
857    }
858    break;
859
860  case SIO_RTEMS_SHOW_STATS:
861    ne_stats (sc);
862    break;
863
864    /* FIXME: Multicast commands must be added here.  */
865
866  default:
867    error = EINVAL;
868    break;
869  }
870
871  return error;
872}
873
874/* Attach an NE2000 driver to the system.  */
875
876int
877rtems_ne_driver_attach (struct rtems_bsdnet_ifconfig *config)
878{
879  int i;
880  struct ne_softc *sc;
881  struct ifnet *ifp;
882  int mtu;
883
884  /* Find a free driver.  */
885  sc = NULL;
886  for (i = 0; i < NNEDRIVER; ++i) {
887    sc = &ne_softc[i];
888    ifp = &sc->arpcom.ac_if;
889    if (ifp->if_softc == NULL)
890      break;
891  }
892
893  if (sc == NULL) {
894    printf ("Too many NE2000 drivers.\n");
895    return 0;
896  }
897
898  memset (sc, 0, sizeof *sc);
899
900  /* Handle the options passed in by the caller.  */
901
902  if (config->mtu != 0)
903    mtu = config->mtu;
904  else
905    mtu = ETHERMTU;
906
907  if (config->irno != 0)
908    sc->irno = config->irno;
909  else {
910    /* We use 5 as the default IRQ.  */
911    sc->irno = 5;
912  }
913
914  if (config->port != 0)
915    sc->port = config->port;
916  else {
917    /* We use 0x300 as the default IO port number.  */
918    sc->port = 0x300;
919  }
920
921  sc->accept_broadcasts = ! config->ignore_broadcast;
922
923  if (config->hardware_address != NULL)
924    memcpy (sc->arpcom.ac_enaddr, config->hardware_address,
925            ETHER_ADDR_LEN);
926  else
927    {
928      unsigned char prom[16];
929      int ia;
930
931      /* Read the PROM to get the Ethernet hardware address.  */
932
933      outport_byte (sc->port + CMDR, MSK_PG0 | MSK_RD2 | MSK_STP);
934      outport_byte (sc->port + DCR, MSK_FT10 | MSK_BMS | MSK_WTS);
935      outport_byte (sc->port + RBCR0, 0);
936      outport_byte (sc->port + RBCR1, 0);
937      outport_byte (sc->port + RCR, MSK_MON);
938      outport_byte (sc->port + TCR, MSK_LOOP);
939      outport_byte (sc->port + IMR, 0);
940      outport_byte (sc->port + ISR, 0xff);
941
942      ne_read_data (sc, 0, sizeof prom, prom);
943
944      outport_byte (sc->port + CMDR, MSK_PG0 | MSK_RD2 | MSK_STP);
945
946      for (ia = 0; ia < ETHER_ADDR_LEN; ++ia)
947        sc->arpcom.ac_enaddr[ia] = prom[ia * 2];
948    }
949
950  /* Set up the network interface.  */
951
952  ifp->if_softc = sc;
953  ifp->if_unit = i + 1;
954  ifp->if_name = "ne";
955  ifp->if_mtu = mtu;
956  ifp->if_init = ne_init;
957  ifp->if_ioctl = ne_ioctl;
958  ifp->if_start = ne_start;
959  ifp->if_output = ether_output;
960  ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;
961  if (ifp->if_snd.ifq_maxlen == 0)
962    ifp->if_snd.ifq_maxlen = ifqmaxlen;
963
964  /* Attach the interface.  */
965
966  if_attach (ifp);
967  ether_ifattach (ifp);
968
969  return 1;
970}
Note: See TracBrowser for help on using the repository browser.