source: rtems/c/src/lib/libbsp/powerpc/motorola_powerpc/dec21140/dec21140.c @ 93180ea2

4.104.114.84.95
Last change on this file since 93180ea2 was 93180ea2, checked in by Joel Sherrill <joel.sherrill@…>, on 07/09/99 at 17:16:10

Patch from Eric Valette <valette@…>:

  • The same bug fix that was done on pc386 to prevent interrupt from occuring (never experienced it but who knows as I have 8259 emulation :()
  • Removed every compiler warning (except wrong ones and ones I can't do anything).
  • Removed any libc available code in code linked with mcp750 rtems executbale. Unfortunately using newlib functions for linking the bootloader does not work as the compilation options in bootloader (-mrelocatable -fixed-r13) are not compatible with newlib options. => I have put any libc external reference in one single new file (lib.c) that is linked only with the boot loader. Removing the file from ${OBJ} and using -lc crash the bootloader. Added big warning...
  • Property mode set to 100644
File size: 21.6 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    unsigned long 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       1520
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  struct MD                     *MDbase;
147  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  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  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(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(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(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  unsigned int *tbase;
372  union {char c[64]; unsigned short s[32];} rombuf;
373  int i, i2, i3;
374  char *cp, direction, *setup_frm, *eaddrs;
375  unsigned long csr12_val, mii_reg0;
376  unsigned char *buffer;
377  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 = (char *)malloc((NRXBUFS+NTXBUFS)*(sizeof(struct MD)+ RBUF_SIZE) + PPC_CACHE_ALIGNMENT);
421  sc->bufferBase = cp;
422  cp += (PPC_CACHE_ALIGNMENT - (int)cp) & MASK_OFFSET;
423#ifdef PCI_BRIDGE_DOES_NOT_ENSURE_CACHE_COHERENCY_FOR_DMA
424  if (_CPU_is_paging_enabled())
425    _CPU_change_memory_mapping_attribute
426                   (NULL, cp,
427                    (NRXBUFS+NTXBUFS)*(sizeof(struct MD)+ RBUF_SIZE),
428                    PTE_CACHE_DISABLE | PTE_WRITABLE);
429#endif
430  rmd = (struct MD*)cp;
431  sc->MDbase = rmd;
432  buffer = cp + ((NRXBUFS+NTXBUFS)*sizeof(struct MD));
433  st_le32( (tbase+memCSR3), (long)((long)(sc->MDbase) + PREP_PCI_DRAM_OFFSET));
434  for (i=0 ; i<NRXBUFS; i++){
435    rmd->buf2 = 0;
436    rmd->buf1 = (unsigned long)(buffer + (i*RBUF_SIZE) + PREP_PCI_DRAM_OFFSET); 
437    if (i == NRXBUFS-1)
438      rmd->counts = 0xfec00000 | (RBUF_SIZE);
439    else
440      rmd->counts = 0xfcc00000 | (RBUF_SIZE);
441    rmd->status = 0x80000000;
442    rmd++;
443  }
444
445  /*
446   * Init TX ring
447   */
448  sc->txBdCount = 0;
449  st_le32( (tbase+memCSR4), (long)((long)(rmd) + PREP_PCI_DRAM_OFFSET));
450  rmd->buf2 = 0;
451  rmd->buf1 = (unsigned long)(buffer + (NRXBUFS*RBUF_SIZE) + PREP_PCI_DRAM_OFFSET);
452  rmd->counts = 0x62000000;
453  rmd->status = 0x0;
454 
455  /*
456   * Set up interrupts
457   */
458  st_le32( (tbase+memCSR5), IT_SETUP);
459  st_le32( (tbase+memCSR7), IT_SETUP);
460
461  sc->irqInfo.hdl = (rtems_irq_hdl)dec21140Enet_interrupt_handler;
462  sc->irqInfo.on  = nopOn;
463  sc->irqInfo.off = nopOn;
464  sc->irqInfo.isOn = dec21140IsOn; 
465  st = BSP_install_rtems_irq_handler (&sc->irqInfo);
466  if (!st)
467    rtems_panic ("Can't attach DEC21140 interrupt handler for irq %d\n",
468                  sc->irqInfo.name);
469
470  /*
471   * Start TX for setup frame
472   */
473  st_le32( (tbase+memCSR6), CSR6_INIT | CSR6_TX);
474
475  /*
476   * Build setup frame
477   */
478  setup_frm = (char *)((long)(rmd->buf1) - PREP_PCI_DRAM_OFFSET);
479  eaddrs = (char *)(sc->arpcom.ac_enaddr);
480  /* Fill the buffer with our physical address. */
481  for (i = 1; i < 16; i++) {
482        *setup_frm++ = eaddrs[0];
483        *setup_frm++ = eaddrs[1];
484        *setup_frm++ = eaddrs[0];
485        *setup_frm++ = eaddrs[1];
486        *setup_frm++ = eaddrs[2];
487        *setup_frm++ = eaddrs[3];
488        *setup_frm++ = eaddrs[2];
489        *setup_frm++ = eaddrs[3];
490        *setup_frm++ = eaddrs[4];
491        *setup_frm++ = eaddrs[5];
492        *setup_frm++ = eaddrs[4];
493        *setup_frm++ = eaddrs[5];
494  }
495  /* Add the broadcast address when doing perfect filtering */
496  memset(setup_frm, 0xff, 12);
497  rmd->counts = 0x0a000000 | 192 ;
498  rmd->status = 0x80000000;
499  st_le32( (tbase+memCSR1), 1);
500  while (rmd->status != 0x7fffffff);
501
502  /*
503   * Enable RX and TX
504   */
505  st_le32( (unsigned int*)(tbase+memCSR6), CSR6_INIT | CSR6_TXRX);
506 
507  /*
508   * Set up PHY
509   */
510 
511  i = rombuf.c[27];
512  i+=2;
513  direction = rombuf.c[i];
514  i +=4;
515  st_le32( (tbase+memCSR12), direction | 0x100);
516  for (i2 = 0; i2 < rombuf.c[(i+2) + rombuf.c[i+1]]; i2++){
517    st_le32( (tbase + memCSR12), rombuf.c[(i+3) + rombuf.c[i+1] + i2]);
518  }
519  for (i2 = 0; i2 < rombuf.c[i+1]; i2++){
520    st_le32( (tbase + memCSR12), rombuf.c[(i+2) + i2]);
521  }
522}
523
524static void
525dec21140_rxDaemon (void *arg)
526{
527  unsigned int *tbase;
528  struct ether_header *eh;
529  struct dec21140_softc *dp = (struct dec21140_softc *)&dec21140_softc[0];
530  struct ifnet *ifp = &dp->arpcom.ac_if;
531  struct mbuf *m;
532  struct MD *rmd;
533  unsigned int len;
534  char *temp;
535  rtems_event_set events;
536  int nbMD;
537 
538  tbase = dec21140_softc[0].base ;
539
540  for (;;){
541
542    rtems_bsdnet_event_receive (INTERRUPT_EVENT,
543                                RTEMS_WAIT|RTEMS_EVENT_ANY,
544                                RTEMS_NO_TIMEOUT,
545                                &events);
546    rmd = dec21140_softc[0].MDbase;
547    nbMD = 0;
548   
549    while (nbMD < NRXBUFS){
550      if ( (rmd->status & 0x80000000) == 0){
551        len = (rmd->status >> 16) & 0x7ff;
552        MGETHDR (m, M_WAIT, MT_DATA);
553        MCLGET (m, M_WAIT);
554        m->m_pkthdr.rcvif = ifp;
555        temp = m->m_data;
556        m->m_len = m->m_pkthdr.len = len - sizeof(struct ether_header);
557        memcpy(temp, (char *)((long)(rmd->buf1)-PREP_PCI_DRAM_OFFSET), len);
558        rmd->status = 0x80000000;
559        eh = mtod (m, struct ether_header *);
560        m->m_data += sizeof(struct ether_header);
561        ether_input (ifp, eh, m);
562      }
563      rmd++;
564      nbMD++;
565    }
566    st_le32( (tbase+memCSR7), IT_SETUP);
567  }     
568}
569
570static void
571sendpacket (struct ifnet *ifp, struct mbuf *m)
572{
573  struct dec21140_softc *dp = ifp->if_softc;
574  volatile struct MD *tmd;
575  unsigned char *temp;
576  struct mbuf *n;
577  unsigned int len;
578  unsigned int *tbase;
579
580  tbase = dp->base;
581
582  /*
583   * Waiting for Transmitter ready
584   */   
585  tmd = dec21140_softc[0].MDbase + NRXBUFS;
586  while ( (tmd->status & 0x80000000) != 0 );
587  len = 0;
588  n = m;
589  temp = (char *)((long)(tmd->buf1)-PREP_PCI_DRAM_OFFSET);
590 
591  for (;;){
592    len += m->m_len;
593    memcpy(temp, (char *)m->m_data, m->m_len);
594    temp += m->m_len ;
595    if ((m = m->m_next) == NULL)
596      break;
597  }
598
599  if (len < ET_MINLEN) len = ET_MINLEN;
600  tmd->counts = 0xe2000000 | len;
601  tmd->status = 0x80000000;
602
603  st_le32( (tbase+memCSR1), 0x1);
604
605  m_freem(n);
606}
607
608/*
609 * Driver transmit daemon
610 */
611void
612dec21140_txDaemon (void *arg)
613{
614  struct dec21140_softc *sc = (struct dec21140_softc *)arg;
615  struct ifnet *ifp = &sc->arpcom.ac_if;
616  struct mbuf *m;
617  rtems_event_set events;
618
619  for (;;) {
620    /*
621     * Wait for packet
622     */
623
624    rtems_bsdnet_event_receive (START_TRANSMIT_EVENT, RTEMS_EVENT_ANY | RTEMS_WAIT, RTEMS_NO_TIMEOUT, &events);
625
626    /*
627     * Send packets till queue is empty
628     */
629    for (;;) {
630      /*
631       * Get the next mbuf chain to transmit.
632       */
633      IF_DEQUEUE(&ifp->if_snd, m);
634      if (!m)
635        break;
636      sendpacket (ifp, m);
637    }
638    ifp->if_flags &= ~IFF_OACTIVE;
639  }
640}       
641
642
643static void
644dec21140_start (struct ifnet *ifp)
645{
646        struct dec21140_softc *sc = ifp->if_softc;
647
648        rtems_event_send (sc->txDaemonTid, START_TRANSMIT_EVENT);
649        ifp->if_flags |= IFF_OACTIVE;
650}
651
652/*
653 * Initialize and start the device
654 */
655static void
656dec21140_init (void *arg)
657{
658  struct dec21140_softc *sc = arg;
659  struct ifnet *ifp = &sc->arpcom.ac_if;
660
661  if (sc->txDaemonTid == 0) {
662   
663    /*
664     * Set up DEC21140 hardware
665     */
666    dec21140Enet_initialize_hardware (sc);
667   
668    /*
669     * Start driver tasks
670     */
671    sc->rxDaemonTid = rtems_bsdnet_newproc ("DCrx", 4096,
672                                            dec21140_rxDaemon, sc);
673    sc->txDaemonTid = rtems_bsdnet_newproc ("DCtx", 4096,
674                                            dec21140_txDaemon, sc);
675  }
676
677  /*
678   * Tell the world that we're running.
679   */
680  ifp->if_flags |= IFF_RUNNING;
681
682}
683
684/*
685 * Stop the device
686 */
687static void
688dec21140_stop (struct dec21140_softc *sc)
689{
690  unsigned int *tbase;
691  struct ifnet *ifp = &sc->arpcom.ac_if;
692
693  ifp->if_flags &= ~IFF_RUNNING;
694
695  /*
696   * Stop the transmitter
697   */
698  tbase=dec21140_softc[0].base ;
699  st_le32( (tbase+memCSR7), NO_IT);
700  st_le32( (tbase+memCSR6), CSR6_INIT);
701  free(sc->bufferBase);
702}
703
704
705/*
706 * Show interface statistics
707 */
708static void
709dec21140_stats (struct dec21140_softc *sc)
710{
711        printf ("      Rx Interrupts:%-8lu", sc->rxInterrupts);
712        printf ("       Not First:%-8lu", sc->rxNotFirst);
713        printf ("        Not Last:%-8lu\n", sc->rxNotLast);
714        printf ("              Giant:%-8lu", sc->rxGiant);
715        printf ("            Runt:%-8lu", sc->rxRunt);
716        printf ("       Non-octet:%-8lu\n", sc->rxNonOctet);
717        printf ("            Bad CRC:%-8lu", sc->rxBadCRC);
718        printf ("         Overrun:%-8lu", sc->rxOverrun);
719        printf ("       Collision:%-8lu\n", sc->rxCollision);
720
721        printf ("      Tx Interrupts:%-8lu", sc->txInterrupts);
722        printf ("        Deferred:%-8lu", sc->txDeferred);
723        printf (" Missed Hearbeat:%-8lu\n", sc->txHeartbeat);
724        printf ("         No Carrier:%-8lu", sc->txLostCarrier);
725        printf ("Retransmit Limit:%-8lu", sc->txRetryLimit);
726        printf ("  Late Collision:%-8lu\n", sc->txLateCollision);
727        printf ("           Underrun:%-8lu", sc->txUnderrun);
728        printf (" Raw output wait:%-8lu\n", sc->txRawWait);
729}
730
731/*
732 * Driver ioctl handler
733 */
734static int
735dec21140_ioctl (struct ifnet *ifp, int command, caddr_t data)
736{
737        struct dec21140_softc *sc = ifp->if_softc;
738        int error = 0;
739
740        switch (command) {
741        case SIOCGIFADDR:
742        case SIOCSIFADDR:
743                ether_ioctl (ifp, command, data);
744                break;
745
746        case SIOCSIFFLAGS:
747                switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) {
748                case IFF_RUNNING:
749                        dec21140_stop (sc);
750                        break;
751
752                case IFF_UP:
753                        dec21140_init (sc);
754                        break;
755
756                case IFF_UP | IFF_RUNNING:
757                        dec21140_stop (sc);
758                        dec21140_init (sc);
759                        break;
760
761                default:
762                        break;
763                }
764                break;
765
766        case SIO_RTEMS_SHOW_STATS:
767                dec21140_stats (sc);
768                break;
769               
770        /*
771         * FIXME: All sorts of multicast commands need to be added here!
772         */
773        default:
774                error = EINVAL;
775                break;
776        }
777
778        return error;
779}
780
781/*
782 * Attach an DEC21140 driver to the system
783 */
784int
785rtems_dec21140_driver_attach (struct rtems_bsdnet_ifconfig *config)
786{
787        struct dec21140_softc *sc;
788        struct ifnet *ifp;
789        int mtu;
790        int i;
791        unsigned char ucSlotNumber, ucFnNumber;
792        unsigned int  ulDeviceID, lvalue, tmp; 
793        unsigned char cvalue;
794       
795        /*
796         * First, find a DEC board
797         */
798        for(ucSlotNumber=0;ucSlotNumber<PCI_MAX_DEVICES;ucSlotNumber++) {
799          for(ucFnNumber=0;ucFnNumber<PCI_MAX_FUNCTIONS;ucFnNumber++) {
800            (void)pci_read_config_dword(0,
801                                        ucSlotNumber,
802                                        ucFnNumber,
803                                        PCI_VENDOR_ID,
804                                        &ulDeviceID);
805            if(ulDeviceID==PCI_INVALID_VENDORDEVICEID) {
806              /*
807               * This slot is empty
808               */
809              continue;
810            }
811            if (ulDeviceID == ((PCI_DEVICE_ID_DEC_TULIP_FAST<<16) + PCI_VENDOR_ID_DEC))
812              break;
813          }
814          if (ulDeviceID == ((PCI_DEVICE_ID_DEC_TULIP_FAST<<16) + PCI_VENDOR_ID_DEC)){
815            printk("DEC Adapter found !!\n");
816            break;
817          }
818        }
819       
820        if(ulDeviceID==PCI_INVALID_VENDORDEVICEID)
821          rtems_panic("DEC PCI board not found !!\n");
822 
823        /*
824         * Find a free driver
825         */
826        for (i = 0 ; i < NDECDRIVER ; i++) {
827                sc = &dec21140_softc[i];
828                ifp = &sc->arpcom.ac_if;
829                if (ifp->if_softc == NULL)
830                        break;
831        }
832        if (i >= NDECDRIVER) {
833                printk ("Too many DEC drivers.\n");
834                return 0;
835        }
836
837        /*
838         * Process options
839         */
840
841        (void)pci_read_config_dword(0,
842                                    ucSlotNumber,
843                                    ucFnNumber,
844                                    PCI_BASE_ADDRESS_0,
845                                    &lvalue);
846
847        sc->port = lvalue & (unsigned int)(~IO_MASK);
848       
849        (void)pci_read_config_dword(0,
850                                    ucSlotNumber,
851                                    ucFnNumber,
852                                    PCI_BASE_ADDRESS_1  ,
853                                    &lvalue);
854
855
856        tmp = (unsigned int)(lvalue & (unsigned int)(~MEM_MASK))
857          + (unsigned int)PREP_ISA_MEM_BASE;
858        sc->base = (unsigned int *)(tmp);
859
860        (void)pci_read_config_byte(0,
861                                   ucSlotNumber,
862                                   ucFnNumber,
863                                   PCI_INTERRUPT_LINE,
864                                   &cvalue);
865        sc->irqInfo.name = (rtems_irq_symbolic_name)cvalue;
866
867        if (config->hardware_address) {
868          memcpy (sc->arpcom.ac_enaddr, config->hardware_address,
869                  ETHER_ADDR_LEN);
870        }
871        else {
872          memset (sc->arpcom.ac_enaddr, 0x08,ETHER_ADDR_LEN);
873        }
874        if (config->mtu)
875                mtu = config->mtu;
876        else
877                mtu = ETHERMTU;
878
879        sc->acceptBroadcast = !config->ignore_broadcast;
880
881        /*
882         * Set up network interface values
883         */
884        ifp->if_softc = sc;
885        ifp->if_unit = i + 1;
886        ifp->if_name = "dc";
887        ifp->if_mtu = mtu;
888        ifp->if_init = dec21140_init;
889        ifp->if_ioctl = dec21140_ioctl;
890        ifp->if_start = dec21140_start;
891        ifp->if_output = ether_output;
892        ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;
893        if (ifp->if_snd.ifq_maxlen == 0)
894                ifp->if_snd.ifq_maxlen = ifqmaxlen;
895
896        /*
897         * Attach the interface
898         */
899        if_attach (ifp);
900        ether_ifattach (ifp);
901
902        return 1;
903};
904
Note: See TracBrowser for help on using the repository browser.