source: rtems/c/src/lib/libbsp/powerpc/shared/dec21140/dec21140.c @ acc25ee

4.104.114.84.95
Last change on this file since acc25ee was acc25ee, checked in by Joel Sherrill <joel.sherrill@…>, on 12/02/99 at 14:31:19

Merged of mcp750 and mvme2307 BSP by Eric Valette <valette@…>.
As part of this effort, the mpc750 libcpu code is now shared with the
ppc6xx.

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