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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rtems-20020807/] [c/] [src/] [libchip/] [network/] [dec21140.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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