OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [rtems/] [c/] [src/] [libchip/] [network/] [dec21140.c] - Blame information for rev 30

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.