source: rtems/c/src/libchip/network/dec21140.c @ 8730f45

4.104.114.84.95
Last change on this file since 8730f45 was a191b28, checked in by Joel Sherrill <joel.sherrill@…>, on 05/14/02 at 17:54:22

2001-05-14 Till Straumann <strauman@…>

  • bootloader/Makefile.am, console/Makefile.am, pci/Makefile.am: Per PR215 address the following issues:
    • _IO_BASE, _ISA_MEM_BASE and PCI_DRAM_OFFSET are no longer defined by libcpu (powerpc/shared/include/io.h) but by the BSP (who is the only one to know the values)
    • the affected BSP (shared/motorola) headers have been fixed in a separate "libbsp/powerpc/shared" patch.
    • the DEC 21140 driver (libchip/network/dec21140.c) has been fixed to use PCI_DRAM_OFFSET instead of PREP_PCI_DRAM_OFFSET. and PCI_MEM_BASE instead of PREP_ISA_MEM_BASE. PCI_MEM_BASE is to be defined by the BSP who is using this driver.
    • the DEC driver also has been fixed to use the newer rtems_bsp_delay_in_bus_cycles() instead of the obsolete delay_in_bus_cycles().
  • Property mode set to 100644
File size: 23.8 KB
Line 
1/*
2 *  RTEMS driver for TULIP based Ethernet Controller
3 *
4 *  Copyright (C) 1999 Emmanuel Raguet. raguet@crf.canon.fr
5 *
6 *  The license and distribution terms for this file may be
7 *  found in found in the file LICENSE in this distribution or at
8 *  http://www.OARcorp.com/rtems/license.html.
9 *
10 * $Id$
11 *
12 * ------------------------------------------------------------------------
13 * [22.05.2000,StWi/CWA] added support for the DEC/Intel 21143 chip
14 *
15 * The 21143 support is (for now) only available for the __i386 target,
16 * because that's the only testing platform I have. It should (to my best
17 * knowledge) work in the same way for the "__PPC" target, but someone
18 * should test this first before it's put into the code. Thanks go to
19 * Andrew Klossner who provided the vital information about the
20 * Intel 21143 chip.
21 * (FWIW: I tested this driver using a Kingston KNE100TX with 21143PD chip)
22 *
23 * The driver will automatically detect whether there is a 21140 or 21143
24 * network card in the system and activate support accordingly. It will
25 * look for the 21140 first. If the 21140 is not found the driver will
26 * look for the 21143.
27 * ------------------------------------------------------------------------
28 */
29
30#include <rtems.h>
31
32/*
33 *  This driver only supports architectures with the new style
34 *  exception processing.  The following checks try to keep this
35 *  from being compiled on systems which can't support this driver.
36 */
37
38#if defined(__i386__)
39  #define DEC21140_SUPPORTED
40#endif
41
42#if defined(__PPC__) && (defined(mpc604) || defined(mpc750))
43  #define DEC21140_SUPPORTED
44#endif
45
46#if defined(DEC21140_SUPPORTED)
47#include <bsp.h>
48#if defined(__i386__)
49#include <pcibios.h>
50#endif
51#if defined(__PPC__)
52#include <bsp/pci.h>
53#include <libcpu/byteorder.h>
54#include <libcpu/io.h>
55#endif
56
57#include <stdlib.h>
58#include <stdio.h>
59#include <stdarg.h>
60#include <rtems/error.h>
61#include <rtems/rtems_bsdnet.h>
62
63#include <sys/param.h>
64#include <sys/mbuf.h>
65
66#include <sys/socket.h>
67#include <sys/sockio.h>
68#include <net/if.h>
69#include <netinet/in.h>
70#include <netinet/if_ether.h>
71 
72#if defined(__i386__)
73#include <irq.h>
74#endif
75#if defined(__PPC)
76#include <bsp/irq.h>
77#endif
78
79#ifdef malloc
80#undef malloc
81#endif
82#ifdef free
83#undef free
84#endif
85
86#define DEC_DEBUG
87
88/* note: the 21143 isn't really a DEC, it's an Intel chip */
89#define PCI_INVALID_VENDORDEVICEID      0xffffffff
90#define PCI_VENDOR_ID_DEC 0x1011
91#define PCI_DEVICE_ID_DEC_21140 0x0009
92#define PCI_DEVICE_ID_DEC_21143 0x0019
93
94#define IO_MASK  0x3
95#define MEM_MASK  0xF
96
97/* command and status registers, 32-bit access, only if IO-ACCESS */
98#define ioCSR0  0x00    /* bus mode register */
99#define ioCSR1  0x08    /* transmit poll demand */
100#define ioCSR2  0x10    /* receive poll demand */
101#define ioCSR3  0x18    /* receive list base address */
102#define ioCSR4  0x20    /* transmit list base address */
103#define ioCSR5  0x28    /* status register */
104#define ioCSR6  0x30    /* operation mode register */
105#define ioCSR7  0x38    /* interrupt mask register */
106#define ioCSR8  0x40    /* missed frame counter */
107#define ioCSR9  0x48    /* Ethernet ROM register */
108#define ioCSR10 0x50    /* reserved */
109#define ioCSR11 0x58    /* full-duplex register */
110#define ioCSR12 0x60    /* SIA status register */
111#define ioCSR13 0x68
112#define ioCSR14 0x70
113#define ioCSR15 0x78    /* SIA general register */
114
115/* command and status registers, 32-bit access, only if MEMORY-ACCESS */
116#define memCSR0  0x00   /* bus mode register */
117#define memCSR1  0x02   /* transmit poll demand */
118#define memCSR2  0x04   /* receive poll demand */
119#define memCSR3  0x06   /* receive list base address */
120#define memCSR4  0x08   /* transmit list base address */
121#define memCSR5  0x0A   /* status register */
122#define memCSR6  0x0C   /* operation mode register */
123#define memCSR7  0x0E   /* interrupt mask register */
124#define memCSR8  0x10   /* missed frame counter */
125#define memCSR9  0x12   /* Ethernet ROM register */
126#define memCSR10 0x14   /* reserved */
127#define memCSR11 0x16   /* full-duplex register */
128#define memCSR12 0x18   /* SIA status register */
129#define memCSR13 0x1A
130#define memCSR14 0x1C
131#define memCSR15 0x1E   /* SIA general register */
132
133#define DEC_REGISTER_SIZE    0x100   /* to reserve virtual memory */
134
135#define RESET_CHIP   0x00000001
136#if defined(__PPC)
137#define CSR0_MODE    0x0030e002   /* 01b08000 */
138#else
139#define CSR0_MODE    0x0020e002   /* 01b08000 */
140#endif
141#define ROM_ADDRESS  0x00004800
142#define CSR6_INIT    0x022cc000   /* 022c0000 020c0000 */ 
143#define CSR6_TX      0x00002000   
144#define CSR6_TXRX    0x00002002   
145#define IT_SETUP     0x000100c0   /* 000100e0 */
146#define CLEAR_IT     0xFFFFFFFF   
147#define NO_IT        0x00000000   
148
149#define NRXBUFS 32      /* number of receive buffers */
150#define NTXBUFS 16      /* number of transmit buffers */
151
152/* message descriptor entry */
153struct MD {
154    /* used by hardware */
155    volatile unsigned32 status;
156    volatile unsigned32 counts;
157    unsigned32 buf1, buf2; 
158    /* used by software */
159    volatile struct mbuf *m;
160    volatile struct MD *next;
161};
162
163/*
164 * Number of DECs supported by this driver
165 */
166#define NDECDRIVER      1
167
168/*
169 * Receive buffer size -- Allow for a full ethernet packet including CRC
170 */
171#define RBUF_SIZE       1536
172
173#define ET_MINLEN 60            /* minimum message length */
174
175/*
176 * RTEMS event used by interrupt handler to signal driver tasks.
177 * This must not be any of the events used by the network task synchronization.
178 */
179#define INTERRUPT_EVENT RTEMS_EVENT_1
180
181/*
182 * RTEMS event used to start transmit daemon.
183 * This must not be the same as INTERRUPT_EVENT.
184 */
185#define START_TRANSMIT_EVENT    RTEMS_EVENT_2
186
187#if defined(__PPC)
188#define phys_to_bus(address) ((unsigned int)((address)) + PCI_DRAM_OFFSET)
189#define bus_to_phys(address) ((unsigned int)((address)) - PCI_DRAM_OFFSET)
190#define CPU_CACHE_ALIGNMENT_FOR_BUFFER PPC_CACHE_ALIGNMENT
191#else
192extern void Wait_X_ms( unsigned int timeToWait );
193#define phys_to_bus(address) ((unsigned int) ((address)))
194#define bus_to_phys(address) ((unsigned int) ((address)))
195#define rtems_bsp_delay_in_bus_cycles(cycle) Wait_X_ms( cycle/100 )
196#define CPU_CACHE_ALIGNMENT_FOR_BUFFER PG_SIZE
197
198inline void st_le32(volatile unsigned32 *addr, unsigned32 value)
199{
200  *(addr)=value ;
201}
202
203inline unsigned32 ld_le32(volatile unsigned32 *addr)
204{
205  return(*addr);
206}
207
208#endif
209
210#if (MCLBYTES < RBUF_SIZE)
211# error "Driver must have MCLBYTES > RBUF_SIZE"
212#endif
213
214/*
215 * Per-device data
216 */
217 struct dec21140_softc {
218
219   struct arpcom                        arpcom;
220
221   rtems_irq_connect_data       irqInfo;
222
223   volatile struct MD           *MDbase;
224   volatile unsigned char       *bufferBase;
225   int                          acceptBroadcast;
226   rtems_id                     rxDaemonTid;
227   rtems_id                     txDaemonTid;
228   
229   volatile struct MD   *TxMD;
230   volatile struct MD   *SentTxMD;
231   int         PendingTxCount;
232   int         TxSuspended;
233
234  unsigned int                  port;
235  volatile unsigned int         *base;
236   
237  /*
238   * Statistics
239   */
240  unsigned long rxInterrupts;
241  unsigned long rxNotFirst;
242  unsigned long rxNotLast;
243  unsigned long rxGiant;
244  unsigned long rxNonOctet;
245  unsigned long rxRunt;
246  unsigned long rxBadCRC;
247  unsigned long rxOverrun;
248  unsigned long rxCollision;
249 
250  unsigned long txInterrupts;
251  unsigned long txDeferred;
252  unsigned long txHeartbeat;
253  unsigned long txLateCollision;
254  unsigned long txRetryLimit;
255  unsigned long txUnderrun;
256  unsigned long txLostCarrier;
257  unsigned long txRawWait;
258};
259
260static struct dec21140_softc dec21140_softc[NDECDRIVER];
261
262/*
263 * DEC21140 interrupt handler
264 */
265static rtems_isr
266dec21140Enet_interrupt_handler (rtems_vector_number v)
267{
268    volatile unsigned32 *tbase;
269    unsigned32 status;
270    struct dec21140_softc *sc;
271
272    sc = &dec21140_softc[0];
273    tbase = (unsigned32 *)(sc->base) ;
274
275    /*
276     * Read status
277     */
278    status = ld_le32(tbase+memCSR5);
279    st_le32((tbase+memCSR5), status); /* clear the bits we've read */
280
281    /*
282     * Frame received?
283     */
284    if (status & 0x000000c0){
285      sc->rxInterrupts++;
286      rtems_event_send (sc->rxDaemonTid, INTERRUPT_EVENT);
287    }
288}
289
290static void nopOn(const rtems_irq_connect_data* notUsed)
291{
292  /*
293   * code should be moved from dec21140Enet_initialize_hardware
294   * to this location
295   */
296}
297
298static int dec21140IsOn(const rtems_irq_connect_data* irq)
299{
300  return BSP_irq_enabled_at_i8259s (irq->name);
301}
302
303
304/*
305 * This routine reads a word (16 bits) from the serial EEPROM.
306 */
307/*  EEPROM_Ctrl bits. */
308#define EE_SHIFT_CLK            0x02    /* EEPROM shift clock. */
309#define EE_CS                   0x01    /* EEPROM chip select. */
310#define EE_DATA_WRITE           0x04    /* EEPROM chip data in. */
311#define EE_WRITE_0              0x01
312#define EE_WRITE_1              0x05
313#define EE_DATA_READ            0x08    /* EEPROM chip data out. */
314#define EE_ENB                  (0x4800 | EE_CS)
315
316/* The EEPROM commands include the alway-set leading bit. */
317#define EE_WRITE_CMD    (5 << 6)
318#define EE_READ_CMD     (6 << 6)
319#define EE_ERASE_CMD    (7 << 6)
320
321static int eeget16(volatile unsigned int *ioaddr, int location)
322{
323        int i;
324        unsigned short retval = 0;
325        int read_cmd = location | EE_READ_CMD;
326       
327        st_le32(ioaddr, EE_ENB & ~EE_CS);
328        st_le32(ioaddr, EE_ENB);
329       
330        /* Shift the read command bits out. */
331        for (i = 10; i >= 0; i--) {
332                short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
333                st_le32(ioaddr, EE_ENB | dataval);
334                rtems_bsp_delay_in_bus_cycles(200);
335                st_le32(ioaddr, EE_ENB | dataval | EE_SHIFT_CLK);
336                rtems_bsp_delay_in_bus_cycles(200);
337                st_le32(ioaddr, EE_ENB | dataval); /* Finish EEPROM a clock tick. */
338                rtems_bsp_delay_in_bus_cycles(200);
339        }
340        st_le32(ioaddr, EE_ENB);
341       
342        for (i = 16; i > 0; i--) {
343                st_le32(ioaddr, EE_ENB | EE_SHIFT_CLK);
344                rtems_bsp_delay_in_bus_cycles(200);
345                retval = (retval << 1) | ((ld_le32(ioaddr) & EE_DATA_READ) ? 1 : 0);
346                st_le32(ioaddr, EE_ENB);
347                rtems_bsp_delay_in_bus_cycles(200);
348        }
349
350        /* Terminate the EEPROM access. */
351        st_le32(ioaddr, EE_ENB & ~EE_CS);
352        return ( ((retval<<8)&0xff00) | ((retval>>8)&0xff) );
353}
354
355/*
356 * Initialize the ethernet hardware
357 */
358static void
359dec21140Enet_initialize_hardware (struct dec21140_softc *sc)
360{
361  rtems_status_code st;
362  volatile unsigned int *tbase;
363  int i;
364  volatile unsigned char *cp, *setup_frm, *eaddrs;
365  volatile unsigned char *buffer;
366  volatile struct MD *rmd;
367
368  tbase = sc->base;
369
370  /*
371   * WARNING : First write in CSR6
372   *           Then Reset the chip ( 1 in CSR0)
373   */
374  st_le32( (tbase+memCSR6), CSR6_INIT); 
375  st_le32( (tbase+memCSR0), RESET_CHIP); 
376  rtems_bsp_delay_in_bus_cycles(200);
377
378  /*
379   * Init CSR0
380   */
381  st_le32( (tbase+memCSR0), CSR0_MODE); 
382
383#ifdef DEC_DEBUG
384  printk("DC2114x %x:%x:%x:%x:%x:%x IRQ %d IO %x M %x .........\n",
385         sc->arpcom.ac_enaddr[0], sc->arpcom.ac_enaddr[1],
386         sc->arpcom.ac_enaddr[2], sc->arpcom.ac_enaddr[3],
387         sc->arpcom.ac_enaddr[4], sc->arpcom.ac_enaddr[5],
388         sc->irqInfo.name, sc->port, (unsigned) sc->base);
389#endif
390 
391  /*
392   * Init RX ring
393   */
394  cp = (volatile unsigned char *)malloc(((NRXBUFS+NTXBUFS)*sizeof(struct MD))
395                                        + (NTXBUFS*RBUF_SIZE)
396                                        + CPU_CACHE_ALIGNMENT_FOR_BUFFER);
397  sc->bufferBase = cp;
398  cp += (CPU_CACHE_ALIGNMENT_FOR_BUFFER - (int)cp)
399         & (CPU_CACHE_ALIGNMENT_FOR_BUFFER - 1);
400#if defined(__i386__)
401#ifdef PCI_BRIDGE_DOES_NOT_ENSURE_CACHE_COHERENCY_FOR_DMA
402  if (_CPU_is_paging_enabled())
403    _CPU_change_memory_mapping_attribute
404                   (NULL, cp,
405                    ((NRXBUFS+NTXBUFS)*sizeof(struct MD))
406                    + (NTXBUFS*RBUF_SIZE),
407                    PTE_CACHE_DISABLE | PTE_WRITABLE);
408#endif
409#endif
410  rmd = (volatile struct MD*)cp;
411  sc->MDbase = rmd;
412  buffer = cp + ((NRXBUFS+NTXBUFS)*sizeof(struct MD));
413  st_le32( (tbase+memCSR3), (long)(phys_to_bus((long)(sc->MDbase))));
414  for (i=0 ; i<NRXBUFS; i++){
415    struct mbuf *m;
416   
417    /* allocate an mbuf for each receive descriptor */
418    MGETHDR (m, M_WAIT, MT_DATA);
419    MCLGET (m, M_WAIT);
420    m->m_pkthdr.rcvif = &sc->arpcom.ac_if;
421    rmd->m = m;
422
423    rmd->buf2   = phys_to_bus(rmd+1);
424    rmd->buf1   = phys_to_bus(mtod(m, void *)); 
425    rmd->counts = 0xfdc00000 | (RBUF_SIZE);
426    rmd->status = 0x80000000;
427    rmd->next   = rmd + 1;
428    rmd++;
429  }
430  /*
431   * mark last RX buffer.
432   */
433  sc->MDbase [NRXBUFS-1].counts = 0xfec00000 | (RBUF_SIZE);
434  sc->MDbase [NRXBUFS-1].next   = sc->MDbase;
435
436  /*
437   * Init TX ring
438   */
439  st_le32( (tbase+memCSR4), (long)(phys_to_bus((long)(rmd))) );
440  for (i=0 ; i<NTXBUFS; i++){
441    (rmd+i)->buf2   = phys_to_bus(rmd+i+1);
442    (rmd+i)->buf1   = phys_to_bus(buffer + (i*RBUF_SIZE));
443    (rmd+i)->counts = 0x01000000;
444    (rmd+i)->status = 0x0;
445    (rmd+i)->next   = rmd+i+1;
446    (rmd+i)->m      = 0;
447  }
448
449  /*
450   * mark last TX buffer.
451   */
452  (rmd+NTXBUFS-1)->buf2   = phys_to_bus(rmd);
453  (rmd+NTXBUFS-1)->next   = rmd;
454 
455  /*
456   * Set up interrupts
457   */
458  sc->irqInfo.hdl = (rtems_irq_hdl)dec21140Enet_interrupt_handler;
459  sc->irqInfo.on  = nopOn;
460  sc->irqInfo.off = nopOn;
461  sc->irqInfo.isOn = dec21140IsOn; 
462  st = BSP_install_rtems_irq_handler (&sc->irqInfo);
463  if (!st)
464    rtems_panic ("Can't attach DEC21140 interrupt handler for irq %d\n",
465                  sc->irqInfo.name);
466
467  st_le32( (tbase+memCSR7), NO_IT);
468
469  /*
470   * Build setup frame
471   */
472  setup_frm = (volatile unsigned char *)(bus_to_phys(rmd->buf1));
473  eaddrs = (char *)(sc->arpcom.ac_enaddr);
474  /* Fill the buffer with our physical address. */
475  for (i = 1; i < 16; i++) {
476        *setup_frm++ = eaddrs[0];
477        *setup_frm++ = eaddrs[1];
478        *setup_frm++ = eaddrs[0];
479        *setup_frm++ = eaddrs[1];
480        *setup_frm++ = eaddrs[2];
481        *setup_frm++ = eaddrs[3];
482        *setup_frm++ = eaddrs[2];
483        *setup_frm++ = eaddrs[3];
484        *setup_frm++ = eaddrs[4];
485        *setup_frm++ = eaddrs[5];
486        *setup_frm++ = eaddrs[4];
487        *setup_frm++ = eaddrs[5];
488  }
489  /* Add the broadcast address when doing perfect filtering */
490  memset((void*) setup_frm, 0xff, 12);
491  rmd->counts = 0x09000000 | 192 ;
492  rmd->status = 0x80000000;
493  st_le32( (tbase+memCSR6), CSR6_INIT | CSR6_TX);
494  st_le32( (tbase+memCSR1), 1);
495  while (rmd->status != 0x7fffffff);
496  rmd->counts = 0x01000000;   
497  sc->TxMD = rmd+1;
498 
499  /*
500   * Enable RX and TX
501   */
502  st_le32( (tbase+memCSR5), IT_SETUP);
503  st_le32( (tbase+memCSR7), IT_SETUP);
504  st_le32( (unsigned int*)(tbase+memCSR6), CSR6_INIT | CSR6_TXRX);
505}
506
507static void
508dec21140_rxDaemon (void *arg)
509{
510  volatile unsigned int *tbase;
511  struct ether_header *eh;
512  struct dec21140_softc *dp = (struct dec21140_softc *)&dec21140_softc[0];
513  struct ifnet *ifp = &dp->arpcom.ac_if;
514  struct mbuf *m;
515  volatile struct MD *rmd;
516  unsigned int len;
517  rtems_event_set events;
518 
519  tbase = dec21140_softc[0].base ;
520  rmd = dec21140_softc[0].MDbase;
521
522  for (;;){
523
524    rtems_bsdnet_event_receive (INTERRUPT_EVENT,
525                                RTEMS_WAIT|RTEMS_EVENT_ANY,
526                                RTEMS_NO_TIMEOUT,
527                                &events);
528   
529    while((rmd->status & 0x80000000) == 0){
530      /* pass on the packet in the mbuf */
531      len = (rmd->status >> 16) & 0x7ff;
532      m = (struct mbuf *)(rmd->m);
533      m->m_len = m->m_pkthdr.len = len - sizeof(struct ether_header);
534      eh = mtod (m, struct ether_header *);
535      m->m_data += sizeof(struct ether_header);
536      ether_input (ifp, eh, m);
537       
538      /* get a new mbuf for the 21140 */
539      MGETHDR (m, M_WAIT, MT_DATA);
540      MCLGET (m, M_WAIT);
541      m->m_pkthdr.rcvif = ifp;
542      rmd->m = m;
543      rmd->buf1 = phys_to_bus(mtod(m, void *)); 
544
545      rmd->status = 0x80000000;
546     
547      rmd=rmd->next;
548    }
549  }     
550}
551
552static void
553sendpacket (struct ifnet *ifp, struct mbuf *m)
554{
555  struct dec21140_softc *dp = ifp->if_softc;
556  volatile struct MD *tmd;
557  volatile unsigned char *temp;
558  struct mbuf *n;
559  unsigned int len;
560  volatile unsigned int *tbase;
561
562  tbase = dp->base;
563  /*
564   * Waiting for Transmitter ready
565   */   
566  tmd = dec21140_softc[0].TxMD;
567  n = m;
568
569  while ((tmd->status & 0x80000000) != 0){
570    tmd=tmd->next;
571    }
572
573  len = 0;
574  temp = (volatile unsigned char *)(bus_to_phys(tmd->buf1));
575 
576  for (;;){
577    len += m->m_len;
578    memcpy((void*) temp, (char *)m->m_data, m->m_len);
579    temp += m->m_len ;
580    if ((m = m->m_next) == NULL)
581      break;
582  }
583
584  if (len < ET_MINLEN) len = ET_MINLEN;
585  tmd->counts =  0xe1000000 | (len & 0x7ff); 
586  tmd->status = 0x80000000;
587
588  st_le32( (tbase+memCSR1), 0x1);
589
590  m_freem(n);
591  dec21140_softc[0].TxMD = tmd->next;
592}
593
594/*
595 * Driver transmit daemon
596 */
597void
598dec21140_txDaemon (void *arg)
599{
600  struct dec21140_softc *sc = (struct dec21140_softc *)arg;
601  struct ifnet *ifp = &sc->arpcom.ac_if;
602  struct mbuf *m;
603  rtems_event_set events;
604
605  for (;;) {
606    /*
607     * Wait for packet
608     */
609
610    rtems_bsdnet_event_receive (START_TRANSMIT_EVENT, RTEMS_EVENT_ANY | RTEMS_WAIT, RTEMS_NO_TIMEOUT, &events);
611
612    /*
613     * Send packets till queue is empty
614     */
615    for (;;) {
616      /*
617       * Get the next mbuf chain to transmit.
618       */
619      IF_DEQUEUE(&ifp->if_snd, m);
620      if (!m)
621        break;
622      sendpacket (ifp, m);
623    }
624    ifp->if_flags &= ~IFF_OACTIVE;
625  }
626}       
627
628
629static void
630dec21140_start (struct ifnet *ifp)
631{
632        struct dec21140_softc *sc = ifp->if_softc;
633
634        rtems_event_send (sc->txDaemonTid, START_TRANSMIT_EVENT);
635        ifp->if_flags |= IFF_OACTIVE;
636}
637
638/*
639 * Initialize and start the device
640 */
641static void
642dec21140_init (void *arg)
643{
644  struct dec21140_softc *sc = arg;
645  struct ifnet *ifp = &sc->arpcom.ac_if;
646
647  if (sc->txDaemonTid == 0) {
648   
649    /*
650     * Set up DEC21140 hardware
651     */
652    dec21140Enet_initialize_hardware (sc);
653   
654    /*
655     * Start driver tasks
656     */
657    sc->rxDaemonTid = rtems_bsdnet_newproc ("DCrx", 4096,
658                                            dec21140_rxDaemon, sc);
659    sc->txDaemonTid = rtems_bsdnet_newproc ("DCtx", 4096,
660                                            dec21140_txDaemon, sc);
661  }
662
663  /*
664   * Tell the world that we're running.
665   */
666  ifp->if_flags |= IFF_RUNNING;
667
668}
669
670/*
671 * Stop the device
672 */
673static void
674dec21140_stop (struct dec21140_softc *sc)
675{
676  volatile unsigned int *tbase;
677  struct ifnet *ifp = &sc->arpcom.ac_if;
678
679  ifp->if_flags &= ~IFF_RUNNING;
680
681  /*
682   * Stop the transmitter
683   */
684  tbase=dec21140_softc[0].base ;
685  st_le32( (tbase+memCSR7), NO_IT);
686  st_le32( (tbase+memCSR6), CSR6_INIT);
687  free((void*)sc->bufferBase);
688}
689
690
691/*
692 * Show interface statistics
693 */
694static void
695dec21140_stats (struct dec21140_softc *sc)
696{
697        printf ("      Rx Interrupts:%-8lu", sc->rxInterrupts);
698        printf ("       Not First:%-8lu", sc->rxNotFirst);
699        printf ("        Not Last:%-8lu\n", sc->rxNotLast);
700        printf ("              Giant:%-8lu", sc->rxGiant);
701        printf ("            Runt:%-8lu", sc->rxRunt);
702        printf ("       Non-octet:%-8lu\n", sc->rxNonOctet);
703        printf ("            Bad CRC:%-8lu", sc->rxBadCRC);
704        printf ("         Overrun:%-8lu", sc->rxOverrun);
705        printf ("       Collision:%-8lu\n", sc->rxCollision);
706
707        printf ("      Tx Interrupts:%-8lu", sc->txInterrupts);
708        printf ("        Deferred:%-8lu", sc->txDeferred);
709        printf (" Missed Hearbeat:%-8lu\n", sc->txHeartbeat);
710        printf ("         No Carrier:%-8lu", sc->txLostCarrier);
711        printf ("Retransmit Limit:%-8lu", sc->txRetryLimit);
712        printf ("  Late Collision:%-8lu\n", sc->txLateCollision);
713        printf ("           Underrun:%-8lu", sc->txUnderrun);
714        printf (" Raw output wait:%-8lu\n", sc->txRawWait);
715}
716
717/*
718 * Driver ioctl handler
719 */
720static int
721dec21140_ioctl (struct ifnet *ifp, int command, caddr_t data)
722{
723        struct dec21140_softc *sc = ifp->if_softc;
724        int error = 0;
725
726        switch (command) {
727        case SIOCGIFADDR:
728        case SIOCSIFADDR:
729                ether_ioctl (ifp, command, data);
730                break;
731
732        case SIOCSIFFLAGS:
733                switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) {
734                case IFF_RUNNING:
735                        dec21140_stop (sc);
736                        break;
737
738                case IFF_UP:
739                        dec21140_init (sc);
740                        break;
741
742                case IFF_UP | IFF_RUNNING:
743                        dec21140_stop (sc);
744                        dec21140_init (sc);
745                        break;
746
747                default:
748                        break;
749                }
750                break;
751
752        case SIO_RTEMS_SHOW_STATS:
753                dec21140_stats (sc);
754                break;
755               
756        /*
757         * FIXME: All sorts of multicast commands need to be added here!
758         */
759        default:
760                error = EINVAL;
761                break;
762        }
763
764        return error;
765}
766
767/*
768 * Attach an DEC21140 driver to the system
769 */
770int
771rtems_dec21140_driver_attach (struct rtems_bsdnet_ifconfig *config, int attach)
772{
773        struct dec21140_softc *sc;
774        struct ifnet *ifp;
775        int mtu;
776        int i;
777    int deviceId = PCI_DEVICE_ID_DEC_21140; /* network card device ID */
778       
779        /*
780         * First, find a DEC board
781         */
782#if defined(__i386__)
783        int signature;
784        int value;
785        char interrupt;
786        int diag;
787
788        if (pcib_init() == PCIB_ERR_NOTPRESENT)
789          rtems_panic("PCI BIOS not found !!");
790       
791        /*
792         * Try to find the network card on the PCI bus. Probe for a DEC 21140
793     * card first. If not found probe the bus for a DEC/Intel 21143 card.
794         */
795    deviceId = PCI_DEVICE_ID_DEC_21140;
796    diag = pcib_find_by_devid( PCI_VENDOR_ID_DEC, deviceId,
797                               0, &signature);
798    if ( diag == PCIB_ERR_SUCCESS)
799      printk( "DEC 21140 PCI network card found\n" );
800    else
801    {
802      deviceId = PCI_DEVICE_ID_DEC_21143;
803      diag = pcib_find_by_devid( PCI_VENDOR_ID_DEC, deviceId,
804                                 0, &signature);
805      if ( diag == PCIB_ERR_SUCCESS)
806        printk( "DEC/Intel 21143 PCI network card found\n" );
807      else
808        rtems_panic("DEC PCI network card not found !!\n");
809    }
810#endif 
811#if defined(__PPC)
812        unsigned char ucSlotNumber, ucFnNumber;
813        unsigned int  ulDeviceID, lvalue, tmp; 
814        unsigned char cvalue;
815
816        for(ucSlotNumber=0;ucSlotNumber<PCI_MAX_DEVICES;ucSlotNumber++) {
817          for(ucFnNumber=0;ucFnNumber<PCI_MAX_FUNCTIONS;ucFnNumber++) {
818            (void)pci_read_config_dword(0,
819                                        ucSlotNumber,
820                                        ucFnNumber,
821                                        PCI_VENDOR_ID,
822                                        &ulDeviceID);
823            if(ulDeviceID==PCI_INVALID_VENDORDEVICEID) {
824              /*
825               * This slot is empty
826               */
827              continue;
828            }
829            if (ulDeviceID == ((PCI_DEVICE_ID_DEC_21140<<16) + PCI_VENDOR_ID_DEC))
830              break;
831          }
832          if (ulDeviceID == ((PCI_DEVICE_ID_DEC_21140<<16) + PCI_VENDOR_ID_DEC)){
833            printk("DEC Adapter found !!\n");
834            break;
835          }
836        }
837       
838        if(ulDeviceID==PCI_INVALID_VENDORDEVICEID)
839          rtems_panic("DEC PCI board not found !!\n");
840#endif 
841        /*
842         * Find a free driver
843         */
844        for (i = 0 ; i < NDECDRIVER ; i++) {
845                sc = &dec21140_softc[i];
846                ifp = &sc->arpcom.ac_if;
847                if (ifp->if_softc == NULL)
848                        break;
849        }
850        if (i >= NDECDRIVER) {
851                printk ("Too many DEC drivers.\n");
852                return 0;
853        }
854
855        /*
856         * Process options
857         */
858#if defined(__i386__)
859
860    /* the 21143 chip must be enabled before it can be accessed */
861    if ( deviceId == PCI_DEVICE_ID_DEC_21143 )
862      pcib_conf_write32( signature, 0x40, 0 );
863
864        pcib_conf_read32(signature, 16, &value);
865        sc->port = value & ~IO_MASK;
866       
867        pcib_conf_read32(signature, 20, &value);
868        if (_CPU_is_paging_enabled())
869          _CPU_map_phys_address((void **) &(sc->base),
870                                (void *)(value & ~MEM_MASK),
871                                DEC_REGISTER_SIZE ,
872                                PTE_CACHE_DISABLE | PTE_WRITABLE);
873        else
874          sc->base = (unsigned int *)(value & ~MEM_MASK);
875       
876        pcib_conf_read8(signature, 60, &interrupt);
877          sc->irqInfo.name = (rtems_irq_symbolic_name)interrupt;
878#endif
879#if defined(__PPC)
880        (void)pci_read_config_dword(0,
881                                    ucSlotNumber,
882                                    ucFnNumber,
883                                    PCI_BASE_ADDRESS_0,
884                                    &lvalue);
885
886        sc->port = lvalue & (unsigned int)(~IO_MASK);
887       
888        (void)pci_read_config_dword(0,
889                                    ucSlotNumber,
890                                    ucFnNumber,
891                                    PCI_BASE_ADDRESS_1  ,
892                                    &lvalue);
893
894
895        tmp = (unsigned int)(lvalue & (unsigned int)(~MEM_MASK))
896          + (unsigned int)PCI_MEM_BASE;
897        sc->base = (unsigned int *)(tmp);
898
899        (void)pci_read_config_byte(0,
900                                   ucSlotNumber,
901                                   ucFnNumber,
902                                   PCI_INTERRUPT_LINE,
903                                   &cvalue);
904        sc->irqInfo.name = (rtems_irq_symbolic_name)cvalue;
905#endif
906        if (config->hardware_address) {
907          memcpy (sc->arpcom.ac_enaddr, config->hardware_address,
908                  ETHER_ADDR_LEN);
909        }
910        else {
911          union {char c[64]; unsigned short s[32];} rombuf;
912          int i;
913
914          for (i=0; i<32; i++){
915            rombuf.s[i] = eeget16(sc->base+memCSR9, i);
916          }
917#if defined(__i386__)
918          for (i=0 ; i<(ETHER_ADDR_LEN/2); i++){
919            sc->arpcom.ac_enaddr[2*i]   = rombuf.c[20+2*i+1];
920            sc->arpcom.ac_enaddr[2*i+1] = rombuf.c[20+2*i];
921          } 
922#endif
923#if defined(__PPC)
924          memcpy (sc->arpcom.ac_enaddr, rombuf.c+20, ETHER_ADDR_LEN);
925#endif
926        }
927
928        if (config->mtu)
929                mtu = config->mtu;
930        else
931                mtu = ETHERMTU;
932
933        sc->acceptBroadcast = !config->ignore_broadcast;
934
935        /*
936         * Set up network interface values
937         */
938        ifp->if_softc = sc;
939        ifp->if_unit = i + 1;
940        ifp->if_name = "dc";
941        ifp->if_mtu = mtu;
942        ifp->if_init = dec21140_init;
943        ifp->if_ioctl = dec21140_ioctl;
944        ifp->if_start = dec21140_start;
945        ifp->if_output = ether_output;
946        ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;
947        if (ifp->if_snd.ifq_maxlen == 0)
948                ifp->if_snd.ifq_maxlen = ifqmaxlen;
949
950        /*
951         * Attach the interface
952         */
953        if_attach (ifp);
954        ether_ifattach (ifp);
955
956        printk( "DC2114x : driver has been attached\n" );
957        return 1;
958};
959#endif /* DEC21140_SUPPORTED */
960
Note: See TracBrowser for help on using the repository browser.