source: rtems/c/src/libchip/network/dec21140.c @ 38b81b5

4.104.114.84.95
Last change on this file since 38b81b5 was 38b81b5, checked in by Joel Sherrill <joel.sherrill@…>, on 12/13/99 at 16:25:03

Patch from Emmanuel Raguet <raguet@…> to correct some problems
in the dec21140 driver. Comments follow:

I have tried to use bootp with the dec21140 driver
and I had problems. I have found them

  • Ethernet address must be known in Attach step (read from the board)
  • Endian problem for Ethernet address storage.

Now it is solved and I can use bootp to obtain
the network configuration of the target.

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