source: rtems/c/src/lib/libbsp/i386/ts_386ex/network/ne2000.c @ 3299388d

4.104.114.84.95
Last change on this file since 3299388d was e61df10, checked in by Joel Sherrill <joel.sherrill@…>, on Sep 4, 2003 at 6:51:28 PM

2003-09-04 Joel Sherrill <joel@…>

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