source: rtems/c/src/lib/libbsp/i386/pc386/dec21140/dec21140.c @ 66a8c6f

4.104.114.84.95
Last change on this file since 66a8c6f was 66a8c6f, checked in by Joel Sherrill <joel.sherrill@…>, on 10/26/99 at 15:21:01

Patch from Emmanuel Raguet <raguet@…> to fix a small bug where
the receive buffer size was 16 bytes too small.

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