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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [devs/] [eth/] [arm/] [ks32c5000/] [v2_0/] [src/] [ks5000_ether.c] - Blame information for rev 174

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 27 unneback
//==========================================================================
2
//
3
//      ks5000_ether.c
4
//
5
//      
6
//
7
//==========================================================================
8
//####ECOSGPLCOPYRIGHTBEGIN####
9
// -------------------------------------------
10
// This file is part of eCos, the Embedded Configurable Operating System.
11
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12
//
13
// eCos is free software; you can redistribute it and/or modify it under
14
// the terms of the GNU General Public License as published by the Free
15
// Software Foundation; either version 2 or (at your option) any later version.
16
//
17
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
19
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20
// for more details.
21
//
22
// You should have received a copy of the GNU General Public License along
23
// with eCos; if not, write to the Free Software Foundation, Inc.,
24
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25
//
26
// As a special exception, if other files instantiate templates or use macros
27
// or inline functions from this file, or you compile this file and link it
28
// with other works to produce a work based on this file, this file does not
29
// by itself cause the resulting work to be covered by the GNU General Public
30
// License. However the source code for this file must still be made available
31
// in accordance with section (3) of the GNU General Public License.
32
//
33
// This exception does not invalidate any other reasons why a work based on
34
// this file might be covered by the GNU General Public License.
35
//
36
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37
// at http://sources.redhat.com/ecos/ecos-license/
38
// -------------------------------------------
39
//####ECOSGPLCOPYRIGHTEND####
40
//==========================================================================
41
//#####DESCRIPTIONBEGIN####
42
//
43
// Author(s):    gthomas
44
// Contributors: gthomas, jskov
45
//               Grant Edwards <grante@visi.com>
46
// Date:         2001-07-31
47
// Purpose:      
48
// Description:  
49
//
50
//####DESCRIPTIONEND####
51
//
52
//========================================================================*/
53
 
54
#include <pkgconf/system.h>
55
#include <pkgconf/devs_eth_arm_ks32c5000.h>
56
#include <pkgconf/io_eth_drivers.h>
57
 
58
#if defined(CYGPKG_IO)
59
#include <pkgconf/io.h>
60
#include <cyg/io/io.h>
61
#include <cyg/io/devtab.h>
62
#else
63
// need to provide fake values for errno
64
#define EIO 1
65
#define EINVAL 2
66
#endif
67
 
68
#include <cyg/infra/cyg_type.h>  // Common type definitions and support
69
                                 // including endian-ness
70
#include <cyg/infra/diag.h>
71
#include <cyg/io/eth/netdev.h>
72
#include <cyg/io/eth/eth_drv.h>
73
#include <cyg/io/eth/eth_drv_stats.h>
74
#include <cyg/hal/hal_intr.h>
75
 
76
#if defined(CYGPKG_REDBOOT)
77
#include <pkgconf/redboot.h>
78
#endif
79
 
80
#if !defined(CYGPKG_NET)
81
#define cyg_drv_interrupt_unmask(v) /* noop */
82
#define cyg_drv_interrupt_mask(v)   /* noop */
83
#define cyg_drv_isr_lock()          /* noop */
84
#define cyg_drv_isr_unlock()        /* noop */
85
#define cyg_drv_mutex_init(m)       /* noop */
86
#define cyg_drv_mutex_lock(m)       /* noop */
87
#define cyg_drv_mutex_unlock(m)     /* noop */
88
#define cyg_drv_dsr_lock()          /* noop */
89
#define cyg_drv_dsr_unlock()        /* noop */
90
#endif
91
 
92
#define HavePHY 1
93
#define HavePHYinterrupt 0
94
 
95
#include "std.h"
96
#include "ks5000_regs.h"
97
#include "ks5000_ether.h"
98
 
99
#if HavePHY
100
#include "phy.h"
101
#endif
102
 
103
// Set up the level of debug output
104
#if CYGPKG_DEVS_ETH_ARM_KS32C5000_DEBUG_LEVEL > 0
105
#define debug1_printf(args...) diag_printf(args)
106
#else
107
#define debug1_printf(args...) /* noop */
108
#endif
109
#if CYGPKG_DEVS_ETH_ARM_KS32C5000_DEBUG_LEVEL > 1
110
#define debug2_printf(args...) diag_printf(args)
111
#else
112
#define debug2_printf(args...) /* noop */
113
#endif
114
 
115
#define Bit(n) (1<<(n))
116
 
117
// enable/disable software verification of rx CRC
118
// should be moved to user-controlled valud in CDL file
119
 
120
#if defined(CYG_HAL_CPUTYPE_KS32C5000A)
121
#define SoftwareCRC 1
122
#include <cyg/crc/crc.h>
123
#else
124
#define SoftwareCRC 0
125
#endif
126
 
127
#if HavePHY
128
// functions to read/write Phy chip registers via MII interface
129
// on 32c5000.  These need to be non-static since they're used
130
// by PHY-specific routines in a different file.
131
#define PHYREGWRITE     0x0400
132
#define MiiStart       0x0800
133
 
134
void MiiStationWrite(U32 RegAddr, U32 PhyAddr, U32 PhyWrData)
135
{
136
  STADATA = PhyWrData ;
137
  STACON = RegAddr | (PhyAddr<<5) |  MiiStart | PHYREGWRITE ;
138
  while (STACON & MiiStart)
139
    ;
140
  //debug1_printf("PHY Wr %x:%02x := %04x\n",PhyAddr, RegAddr, PhyWrData) ;
141
}
142
 
143
U32 MiiStationRead(U32 RegAddr, U32 PhyAddr)
144
{
145
  U32   PhyRdData;
146
  STACON = RegAddr | (PhyAddr<<5) |  MiiStart;
147
  while (STACON & MiiStart)
148
    ;
149
  PhyRdData = STADATA;
150
  //debug1_printf("PHY Rd %x:%02x  %04x\n",PhyAddr,RegAddr,PhyRdData) ;
151
  return PhyRdData ;
152
}
153
#endif
154
 
155
// miscellaneous data structures
156
 
157
typedef  BYTE  ETH_ADDR[6] __attribute__((packed));
158
 
159
typedef  struct tagETH_HEADER
160
{
161
  ETH_ADDR daddr __attribute__((packed));
162
  ETH_ADDR saddr __attribute__((packed));
163
  WORD type      __attribute__((packed));
164
} ETH_HEADER __attribute__((packed));
165
 
166
#define ETH_HEADER_SIZE   14
167
 
168
// Tx/Rx common descriptor structure
169
typedef  struct tagFRAME_DESCRIPTOR
170
{
171
  LWORD FrameDataPtr;
172
  LWORD Reserved;   /*  cf: RX-reserved, TX-Reserved(25bits) + Control bits(7bits) */
173
  LWORD StatusAndFrameLength;
174
  struct tagFRAME_DESCRIPTOR   *NextFD;
175
} FRAME_DESCRIPTOR;
176
 
177
typedef struct
178
{
179
  U8 DestinationAddr[6];
180
  U8 SourceAddr[6];
181
  U8 LengthOrType[2];
182
  U8 LLCData[1506];
183
} MAC_FRAME;
184
 
185
#if defined(CYGPKG_NET)
186
static cyg_drv_mutex_t txMutex;
187
struct ether_drv_stats ifStats;
188
#endif
189
 
190
typedef struct
191
{
192
  LWORD BTxNLErr;
193
  LWORD BTxNOErr;
194
  LWORD BTxEmptyErr;
195
} BDMA_TX_ERR;
196
 
197
typedef struct
198
{
199
  LWORD BRxNLErr;
200
  LWORD BRxNOErr;
201
  LWORD BRxMSOErr;
202
  LWORD BRxEmptyErr;
203
  LWORD sBRxSEarly;
204
  LWORD noBufferAvail;
205
  LWORD queueOverflow;
206
  LWORD bad;
207
} BDMA_RX_ERR;
208
 
209
 
210
// interrupt entry counters
211
U32 ks5000_MAC_Rx_Cnt;
212
U32 ks5000_MAC_Tx_Cnt;
213
U32 ks5000_MAC_Phy_Cnt;
214
U32 ks5000_BDMA_Tx_Isr_Cnt;
215
U32 ks5000_BDMA_Tx_Dsr_Cnt;
216
U32 ks5000_BDMA_Rx_Isr_Cnt;
217
U32 ks5000_BDMA_Rx_Dsr_Cnt;
218
 
219
 
220
// packet and byte counters
221
static U32 MAC_Tx_Pkts;
222
static U32 MAC_Tx_Octets;
223
// static U32 BDMA_Rx_Pkts;
224
// static U32 BDMA_Rx_Octets;
225
 
226
// configuration values
227
static volatile U32 MACConfigVar;
228
static volatile U32 CAMConfigVar = CAMCON_COMP_EN | CAMCON_BROAD_ACC;
229
static volatile U32 MACTxConfigVar =
230
  /* MACTXCON_EN_UNDER | */
231
  MACTXCON_EN_DEFER |
232
  MACTXCON_EN_NCARR |
233
  MACTXCON_EN_EXCOLL |
234
  MACTXCON_EN_LATE_COLL |
235
  MACTXCON_ENTX_PAR |
236
  MACTXCON_EN_COMP;
237
static volatile U32 MACRxConfigVar =
238
  MACRXCON_RX_EN |
239
  MACRXCON_EN_ALIGN |
240
  MACRXCON_EN_CRC_ERR |
241
  MACRXCON_EN_OVER |
242
  MACRXCON_EN_LONG_ERR |
243
  MACRXCON_EN_RX_PAR;
244
 
245
static volatile U32 BDMATxConfigVar =
246
  BDMATXCON_MSL111 |
247
  BDMATXCON_STP_SKP |
248
  3;   /* burst size - 1 */
249
 
250
#define EtherFramePadding 2
251
 
252
#if EtherFramePadding == 0
253
#define BDMARXCON_ALIGN BDMARXCON_WA00
254
#elif EtherFramePadding == 1
255
#define BDMARXCON_ALIGN BDMARXCON_WA01
256
#elif EtherFramePadding == 2
257
#define BDMARXCON_ALIGN BDMARXCON_WA10
258
#elif EtherFramePadding == 3
259
#define BDMARXCON_ALIGN BDMARXCON_WA11
260
#else
261
#error "EtherFramePadding must be 0,1,2 or 3"
262
#endif
263
 
264
#if (CYG_BYTEORDER == CYG_MSBFIRST) // Big endian
265
static volatile U32 BDMARxConfigVar =
266
  BDMARXCON_DIE |
267
  BDMARXCON_EN |
268
  BDMARXCON_BIG |
269
  BDMARXCON_MA_INC |
270
  BDMARXCON_NOIE |
271
  BDMARXCON_ALIGN |
272
  BDMARXCON_STP_SKP |
273
  15;  /* burst size - 1 */
274
 
275
#else // Little endian
276
static volatile U32 BDMARxConfigVar =
277
  BDMARXCON_DIE |
278
  BDMARXCON_EN |
279
  BDMARXCON_LITTLE |
280
  BDMARXCON_MA_INC |
281
  BDMARXCON_NOIE |
282
  BDMARXCON_ALIGN |
283
  BDMARXCON_STP_SKP |
284
  15;  /* burst size - 1 */
285
#endif
286
 
287
 
288
/* Global variables For BDMA Error Report */
289
 
290
static BDMA_TX_ERR BDMATxErrCnt = {0,0,0};
291
static BDMA_RX_ERR BDMARxErrCnt = {0,0,0,0,0};
292
 
293
 
294
static void Init_TxFrameDescriptorArray(void);
295
static void Init_RxFrameDescriptorArray(void);
296
 
297
// number of ethernet buffers should be enough to keep both rx
298
// and tx queues full plus some extras for in-process packets
299
 
300
#if defined(CYGPKG_REDBOOT)
301
#define NUM_ETH_BUFFERS 10
302
#define MAX_RX_FRAME_DESCRIPTORS        4     // Max number of Rx Frame Descriptors
303
#define MAX_TX_FRAME_DESCRIPTORS        4     // Max number of Tx Frame Descriptors
304
#else
305
#define NUM_ETH_BUFFERS 80
306
#define MAX_RX_FRAME_DESCRIPTORS        32     // Max number of Rx Frame Descriptors
307
#define MAX_TX_FRAME_DESCRIPTORS        32     // Max number of Tx Frame Descriptors
308
#endif
309
 
310
static FRAME_DESCRIPTOR _rxFrameDescrArray[MAX_RX_FRAME_DESCRIPTORS] __attribute__((aligned(16)));
311
static FRAME_DESCRIPTOR _txFrameDescrArray[MAX_TX_FRAME_DESCRIPTORS] __attribute__((aligned(16)));
312
 
313
/* define aliases that will set the no-cache bit */
314
#define rxFrameDescrArray ((FRAME_DESCRIPTOR*)(((unsigned)_rxFrameDescrArray)|0x4000000))
315
#define txFrameDescrArray ((FRAME_DESCRIPTOR*)(((unsigned)_txFrameDescrArray)|0x4000000))
316
 
317
static volatile FRAME_DESCRIPTOR *rxReadPointer;
318
static volatile FRAME_DESCRIPTOR *txDonePointer;
319
static volatile FRAME_DESCRIPTOR *txWritePointer;
320
 
321
static cyg_drv_mutex_t oldRxMutex;
322
static cyg_drv_cond_t  oldRxCond;
323
 
324
 
325
static bool configDone;
326
 
327
/*----------------------------------------------------------------------
328
 * Data structures used to manage ethernet buffers
329
 */
330
#define MAX_ETH_FRAME_SIZE 1520
331
 
332
typedef struct tEthBufferTag
333
{
334
  unsigned char data[MAX_ETH_FRAME_SIZE+8];
335
  unsigned length;
336
  unsigned userData;
337
  struct tEthBufferTag *next;
338
  struct tEthBufferTag *prev;
339
}tEthBuffer;
340
 
341
 
342
typedef struct
343
{
344
  tEthBuffer *head;
345
  tEthBuffer *tail;
346
}tEthBufQueue;
347
 
348
#define EmptyQueue {NULL,NULL}
349
 
350
static void ethBufQueueClear(tEthBufQueue *q)
351
{
352
  q->head = NULL;
353
  q->tail = NULL;
354
}
355
 
356
static tEthBuffer *ethBufQueueGet(tEthBufQueue *q)
357
{
358
  tEthBuffer *r;
359
 
360
  r = q->head;
361
 
362
  if (r)
363
    q->head = r->next;
364
 
365
  return r;
366
}
367
 
368
static void ethBufQueuePut(tEthBufQueue *q, tEthBuffer *b)
369
{
370
  b->next = NULL;
371
 
372
  if (!q->head)
373
    {
374
      q->head = b;
375
      q->tail = b;
376
    }
377
  else
378
    {
379
      q->tail->next = b;
380
      q->tail = b;
381
    }
382
}
383
 
384
#if 0
385
// not used at the moment
386
static bool ethBufQueueEmpty(tEthBufQueue *q)
387
{
388
  return q->head != NULL;
389
}
390
#endif
391
 
392
/*----------------------------------------------------------------------
393
 * Free pool and routines to manipulate it.
394
 */
395
 
396
static tEthBuffer __bufferPool[NUM_ETH_BUFFERS] __attribute__((aligned(16)));
397
#define bufferPool ((tEthBuffer*)((unsigned)__bufferPool|0x4000000))
398
 
399
static tEthBufQueue freeList;
400
static int freeCount;
401
 
402
// do not call from ISR routine
403
static void freeBuffer(tEthBuffer *b)
404
{
405
  cyg_drv_isr_lock();
406
  ++freeCount;
407
  ethBufQueuePut(&freeList,b);
408
  cyg_drv_isr_unlock();
409
}
410
 
411
static int allocFail;
412
 
413
void bufferListError(void)
414
{
415
  while (1)
416
    ;
417
}
418
 
419
// do not call from ISR routine
420
static tEthBuffer *allocBuffer(void)
421
{
422
  tEthBuffer *r;
423
  cyg_drv_isr_lock();
424
  r = ethBufQueueGet(&freeList);
425
  cyg_drv_isr_unlock();
426
  if (r)
427
    --freeCount;
428
  else
429
    {
430
      ++allocFail;
431
      if (freeCount)
432
        bufferListError();
433
    }
434
  return r;
435
}
436
 
437
// call only from ISR routine or init
438
static void isrFreeBuffer(tEthBuffer *b)
439
{
440
  ++freeCount;
441
  ethBufQueuePut(&freeList,b);
442
}
443
 
444
#if 0
445
// not used at the moment
446
 
447
// call only from ISR routine or init
448
static tEthBuffer *isrAllocBuffer(void)
449
{
450
  tEthBuffer *r;
451
  r = ethBufQueueGet(&freeList);
452
  if (r)
453
    --freeCount;
454
  else
455
    {
456
      ++allocFail;
457
      if (freeCount)
458
        bufferListError();
459
    }
460
  return r;
461
}
462
#endif
463
 
464
static void initFreeList(void)
465
{
466
  int i;
467
  ethBufQueueClear(&freeList);
468
  freeCount = 0;
469
  for (i=0; i<NUM_ETH_BUFFERS; ++i)
470
    isrFreeBuffer(bufferPool+i);
471
}
472
 
473
 
474
//----------------------------------------------------------------------
475
// queue a buffer for transmit
476
//
477
// returns true if buffer was queued.
478
 
479
static int ks32c5000_eth_buffer_send(tEthBuffer *buf)
480
{
481
#if defined(CYGPKG_NET)  
482
  while (!configDone)
483
    cyg_thread_delay(10);
484
#endif
485
 
486
  if (txWritePointer->FrameDataPtr & FRM_OWNERSHIP_BDMA)
487
    {
488
      // queue is full!  make sure transmit is running
489
      BDMATXCON |= BDMATXCON_EN;
490
      MACTXCON |= MACTXCON_TX_EN;
491
      return 0;
492
    }
493
 
494
  cyg_drv_mutex_lock(&txMutex);
495
 
496
  // free old buffer if we need to
497
 
498
  cyg_drv_isr_lock();
499
  if (txWritePointer->FrameDataPtr)
500
    {
501
      freeBuffer((tEthBuffer*)txWritePointer->FrameDataPtr);
502
      txWritePointer->FrameDataPtr = 0;
503
    }
504
  cyg_drv_isr_unlock();
505
 
506
  MAC_Tx_Pkts += 1;
507
  MAC_Tx_Octets += buf->length;
508
 
509
  // fill in the packet descriptor
510
 
511
#if (CYG_BYTEORDER == CYG_MSBFIRST) // Big endian
512
  txWritePointer->Reserved = (TXFDCON_PADDING_MODE | TXFDCON_CRC_MODE |
513
                    TXFDCON_SRC_ADDR_INC | TXFDCON_BIG_ENDIAN |
514
                    TXFDCON_WIDGET_ALIGN00 | TXFDCON_MAC_TX_INT_EN);
515
#else // Little endian
516
  txWritePointer->Reserved = (TXFDCON_PADDING_MODE | TXFDCON_CRC_MODE |
517
                    TXFDCON_SRC_ADDR_INC | TXFDCON_LITTLE_ENDIAN |
518
                    TXFDCON_WIDGET_ALIGN00 | TXFDCON_MAC_TX_INT_EN);
519
#endif
520
 
521
  txWritePointer->StatusAndFrameLength = buf->length;
522
  txWritePointer->FrameDataPtr = ((unsigned)buf | FRM_OWNERSHIP_BDMA);
523
 
524
  txWritePointer = txWritePointer->NextFD;
525
 
526
  cyg_drv_mutex_unlock(&txMutex);
527
 
528
  // start transmit
529
 
530
#if defined(CYGPKG_NET)  
531
  ++ifStats.tx_count;
532
#endif
533
 
534
  BDMATXCON |= BDMATXCON_EN;
535
  MACTXCON |= MACTXCON_TX_EN;
536
  return 1;
537
}
538
 
539
 
540
//======================================================================
541
// check to see if there's a frame waiting
542
 
543
static int rx_frame_avail(void)
544
{
545
  if (rxReadPointer->FrameDataPtr & FRM_OWNERSHIP_BDMA)
546
    {
547
      // queue is empty -- make sure Rx is running
548
      if (!(BDMARXCON & BDMARXCON_EN))
549
          {
550
            ++BDMARxErrCnt.queueOverflow;
551
            BDMARXCON |= BDMARXCON_EN;
552
          }
553
      return 0;
554
    }
555
  else
556
    return 1;
557
}
558
 
559
 
560
//======================================================================
561
// de-queue a receive buffer
562
static tEthBuffer *ks32c5000_eth_get_recv_buffer(void)
563
{
564
  unsigned RxStatusAndLength;
565
  tEthBuffer *RxBufPtr;
566
  tEthBuffer *emptyBuf;
567
#if SoftwareCRC  
568
  unsigned crc, crclen;
569
  int crcOK;
570
#else
571
# define crcOK 1
572
#endif
573
 
574
  while (1)
575
    {
576
      if (rxReadPointer->FrameDataPtr & FRM_OWNERSHIP_BDMA)
577
        {
578
          // queue is empty -- make sure Rx is running
579
          if (!(BDMARXCON & BDMARXCON_EN))
580
            {
581
              ++BDMARxErrCnt.queueOverflow;
582
              BDMARXCON |= BDMARXCON_EN;
583
            }
584
          return NULL;
585
        }
586
 
587
      RxBufPtr = (tEthBuffer*)rxReadPointer->FrameDataPtr;
588
      RxStatusAndLength = rxReadPointer->StatusAndFrameLength;
589
 
590
      // counting on short-circuit && evaluation below to only
591
      // allocate a fresh buffer if rx packet is good!!
592
 
593
#if defined (CYGPKG_NET)      
594
      ++ifStats.rx_count;
595
#endif      
596
 
597
#if SoftwareCRC
598
      crclen = (RxStatusAndLength & 0xffff) - 4;
599
      crc = cyg_ether_crc32(RxBufPtr->data+2,crclen);
600
      crcOK = ((U08)(crc>>0) == RxBufPtr->data[2+crclen+0] &&
601
               (U08)(crc>>8) == RxBufPtr->data[2+crclen+1] &&
602
               (U08)(crc>>16) == RxBufPtr->data[2+crclen+2] &&
603
               (U08)(crc>>24) == RxBufPtr->data[2+crclen+3]);
604
#endif
605
      if ((RxStatusAndLength & (RXFDSTAT_GOOD<<16))
606
          && crcOK
607
          && (emptyBuf = allocBuffer()))
608
        {
609
          // good packet and we've got a fresh buffer to take
610
          // it's place in the receive queue
611
          rxReadPointer->FrameDataPtr = (unsigned)emptyBuf | FRM_OWNERSHIP_BDMA;
612
          rxReadPointer = rxReadPointer->NextFD;
613
          RxBufPtr->length = RxStatusAndLength & 0xffff;
614
#if defined(CYGPKG_NET)
615
          ++ifStats.rx_deliver;
616
#endif          
617
          return RxBufPtr;
618
        }
619
      else
620
        {
621
          // bad packet or out of buffers.  either way we
622
          // ignore this packet, and reuse the buffer
623
#if defined(CYGPKG_NET)
624
          if (RxStatusAndLength & (RXFDSTAT_GOOD<<16) && crcOK)
625
            ++ifStats.rx_resource;
626
          else
627
            ++ifStats.rx_crc_errors;
628
#endif          
629
          rxReadPointer->FrameDataPtr |= FRM_OWNERSHIP_BDMA;
630
          rxReadPointer = rxReadPointer->NextFD;
631
        }
632
    }
633
}
634
 
635
//======================================================================
636
static int EthInit(U08* mac_address)
637
{
638
  if (mac_address)
639
    debug2_printf("EthInit(%02x:%02x:%02x:%02x:%02x:%02x)\n",
640
                mac_address[0],mac_address[1],mac_address[2],
641
                mac_address[3],mac_address[4],mac_address[5]);
642
  else
643
    debug2_printf("EthInit(NULL)\n");
644
 
645
#if HavePHY  
646
  PhyReset();
647
#endif
648
 
649
  /* Set the initial condition of the BDMA. */
650
  BDMARXCON = BDMARXCON_RESET;
651
  BDMATXCON = BDMATXCON_RESET;
652
  BDMARXLSZ = MAX_ETH_FRAME_SIZE;
653
 
654
  BDMARXPTR = (U32)rxReadPointer;
655
  BDMATXPTR = (U32)txWritePointer;
656
 
657
  MACCON = MACON_SW_RESET;
658
  MACCON = MACConfigVar;
659
 
660
  CAMCON = CAMConfigVar;
661
 
662
  // set up our MAC address
663
 
664
  if (mac_address)
665
    {
666
      *((volatile U32*)CAM_BaseAddr) =
667
        (mac_address[0]<<24) |
668
        (mac_address[1]<<16) |
669
        (mac_address[2]<< 8) |
670
        (mac_address[3]<< 0);
671
      *((volatile U16*)(CAM_BaseAddr+4)) =
672
        (mac_address[4]<< 8) |
673
        (mac_address[5]<< 0);
674
    }
675
 
676
  // CAM Enable
677
  CAMEN = 0x0001;
678
 
679
  // update the Configuration of BDMA and MAC to begin Rx/Tx
680
 
681
  BDMARXCON = BDMARxConfigVar;
682
  MACRXCON = MACRxConfigVar;
683
 
684
  BDMATXCON = BDMATxConfigVar;
685
  MACTXCON =  MACTxConfigVar;
686
 
687
    debug2_printf("ks32C5000 eth: %02x:%02x:%02x:%02x:%02x:%02x  ",
688
              *((volatile unsigned char*)CAM_BaseAddr+0),
689
              *((volatile unsigned char*)CAM_BaseAddr+1),
690
              *((volatile unsigned char*)CAM_BaseAddr+2),
691
              *((volatile unsigned char*)CAM_BaseAddr+3),
692
              *((volatile unsigned char*)CAM_BaseAddr+4),
693
              *((volatile unsigned char*)CAM_BaseAddr+5));
694
 
695
#if SoftwareCRC
696
  debug2_printf("Software CRC\n");
697
#else
698
  debug2_printf("Hardware CRC\n");
699
#endif
700
 
701
  return 0;
702
}
703
 
704
//======================================================================
705
static void Init_TxFrameDescriptorArray(void)
706
{
707
  FRAME_DESCRIPTOR *pFrameDescriptor;
708
  int i;
709
 
710
  // Each Frame Descriptor's frame data pointer points is NULL
711
  // if not in use, otherwise points to an ethBuffer
712
 
713
  pFrameDescriptor = txFrameDescrArray;
714
 
715
  for(i=0; i < MAX_TX_FRAME_DESCRIPTORS; i++)
716
    {
717
      pFrameDescriptor->FrameDataPtr = 0;
718
      pFrameDescriptor->Reserved = 0;
719
      pFrameDescriptor->StatusAndFrameLength = 0;
720
      pFrameDescriptor->NextFD = pFrameDescriptor+1;
721
      pFrameDescriptor++;
722
    }
723
 
724
  // fix up the last pointer to loop back to the first
725
 
726
  txFrameDescrArray[MAX_TX_FRAME_DESCRIPTORS-1].NextFD = txFrameDescrArray;
727
 
728
  txDonePointer = txWritePointer = txFrameDescrArray;
729
 
730
  return;
731
}
732
 
733
 
734
//======================================================================
735
static void Init_RxFrameDescriptorArray(void)
736
{
737
  FRAME_DESCRIPTOR *pFrameDescriptor;
738
  int i;
739
 
740
  // Each Frame Descriptor's frame data pointer points to
741
  // an ethBuffer struct
742
 
743
  pFrameDescriptor = rxFrameDescrArray;
744
 
745
  for(i=0; i < MAX_RX_FRAME_DESCRIPTORS; i++)
746
    {
747
      pFrameDescriptor->FrameDataPtr = ((unsigned)allocBuffer() | FRM_OWNERSHIP_BDMA);
748
      pFrameDescriptor->Reserved = 0;
749
      pFrameDescriptor->StatusAndFrameLength = 0;
750
      pFrameDescriptor->NextFD = pFrameDescriptor+1;
751
      pFrameDescriptor++;
752
    }
753
 
754
  // fix up the last pointer to loop back to the first
755
 
756
  rxFrameDescrArray[MAX_RX_FRAME_DESCRIPTORS-1].NextFD = rxFrameDescrArray;
757
 
758
  rxReadPointer = rxFrameDescrArray;
759
 
760
  return;
761
}
762
 
763
#if HavePHY
764
 
765
#if HavePHYinterrupt
766
static unsigned linkStatus;
767
 
768
static cyg_uint32 MAC_Phy_isr(cyg_vector_t vector, cyg_addrword_t data)
769
{
770
  cyg_drv_interrupt_acknowledge(vector);
771
  PhyInterruptAck();
772
  ++ks5000_MAC_Phy_Cnt;
773
  linkStatus = PhyStatus();
774
  if (linkStatus & PhyStatus_FullDuplex)
775
    MACConfigVar |= (MACON_FULL_DUP);
776
  else
777
    MACConfigVar &= ~(MACON_FULL_DUP);
778
 
779
#if defined(CYGPKG_NET)      
780
  if (linkStatus & PhyStatus_FullDuplex)
781
    ifStats.duplex = 3;
782
  else
783
    ifStats.duplex = 2;
784
 
785
  if (linkStatus & PhyStatus_LinkUp)
786
    ifStats.operational = 3;
787
  else
788
    ifStats.operational = 2;
789
 
790
  if (linkStatus & PhyStatus_100Mb)
791
    ifStats.speed = 100000000;
792
  else
793
    ifStats.speed = 10000000;
794
#endif  
795
 
796
  MACCON = MACConfigVar;
797
  return CYG_ISR_HANDLED;
798
}
799
#endif
800
#endif
801
 
802
static void ks32c5000_handle_tx_complete(void)
803
{
804
 
805
  // record status and then free any buffers we're done with
806
 
807
  while (txDonePointer->FrameDataPtr && !(txDonePointer->FrameDataPtr & FRM_OWNERSHIP_BDMA))
808
    {
809
#if defined(CYGPKG_NET)
810
      U32 txStatus;
811
 
812
      txStatus = txDonePointer->StatusAndFrameLength>>16;
813
 
814
      ++ks5000_MAC_Tx_Cnt;
815
      ++ifStats.interrupts;
816
 
817
      if (txStatus & MACTXSTAT_COMP)
818
        ++ifStats.tx_complete;
819
 
820
      if (txStatus & (MACTXSTAT_EX_COLL | MACTXSTAT_DEFFERED |
821
                            MACTXSTAT_UNDER | MACTXSTAT_DEFER |
822
                            MACTXSTAT_NCARR | MACTXSTAT_SIG_QUAL |
823
                            MACTXSTAT_LATE_COLL | MACTXSTAT_PAR |
824
                            MACTXSTAT_PAUSED | MACTXSTAT_HALTED))
825
        {
826
          // transmit failed, log errors
827
          if (txStatus & MACTXSTAT_EX_COLL)
828
            ++ifStats.tx_max_collisions;
829
          if (txStatus & MACTXSTAT_DEFFERED)
830
            ++ifStats.tx_deferred;
831
          if (txStatus & MACTXSTAT_UNDER)
832
            ++ifStats.tx_underrun;
833
          if (txStatus & MACTXSTAT_DEFER)
834
            ;
835
          if (txStatus & MACTXSTAT_NCARR)
836
            ++ifStats.tx_carrier_loss;
837
          if (txStatus & MACTXSTAT_SIG_QUAL)
838
            ++ifStats.tx_sqetesterrors;
839
          if (txStatus & MACTXSTAT_LATE_COLL)
840
            ++ifStats.tx_late_collisions;
841
          if (txStatus & MACTXSTAT_PAR)
842
            ;
843
          if (txStatus & MACTXSTAT_PAUSED)
844
            ;
845
          if (txStatus & MACTXSTAT_HALTED)
846
            ;
847
        }
848
      else
849
        {
850
          // transmit OK
851
          int collisionCnt = txStatus & 0x0f;
852
          ++ifStats.tx_good;
853
          if (collisionCnt)
854
            {
855
              if (collisionCnt == 1)
856
                ++ifStats.tx_single_collisions;
857
              else
858
                ++ifStats.tx_mult_collisions;
859
              ifStats.tx_total_collisions += collisionCnt;
860
            }
861
        }
862
#endif      
863
      isrFreeBuffer((tEthBuffer*)txDonePointer->FrameDataPtr);
864
      txDonePointer->FrameDataPtr = 0;
865
      txDonePointer = txDonePointer->NextFD;
866
    }
867
}
868
 
869
 
870
//======================================================================
871
static cyg_uint32 MAC_Tx_isr(cyg_vector_t vector, cyg_addrword_t data)
872
{
873
  cyg_drv_interrupt_acknowledge(vector);
874
  ks32c5000_handle_tx_complete();
875
  return CYG_ISR_HANDLED;
876
}
877
 
878
static unsigned accumulatedMaxRxStatus=0;
879
 
880
//======================================================================
881
static cyg_uint32 MAC_Rx_isr(cyg_vector_t vector, cyg_addrword_t data)
882
{
883
  U32 IntMACRxStatus;
884
 
885
  cyg_drv_interrupt_acknowledge(vector);
886
 
887
  IntMACRxStatus = MACRXSTAT;
888
  MACRXSTAT = IntMACRxStatus;
889
 
890
  accumulatedMaxRxStatus |= IntMACRxStatus;
891
 
892
  ++ks5000_MAC_Rx_Cnt;
893
 
894
#if defined(CYGPKG_NET)
895
 
896
  ++ifStats.interrupts;
897
 
898
  if (IntMACRxStatus & MACRXSTAT_GOOD)
899
    {
900
      ++ifStats.rx_good;
901
 
902
      if (IntMACRxStatus & MACRXSTAT_CTL_RECD)
903
        ;  // we don't do anything with control packets
904
 
905
      return CYG_ISR_HANDLED;
906
    }
907
 
908
  if (IntMACRxStatus & (MACRXSTAT_ALLIGN_ERR | MACRXSTAT_CRC_ERR |
909
                        MACRXSTAT_OVERFLOW | MACRXSTAT_LONG_ERR |
910
                        MACRXSTAT_PAR | MACRXSTAT_HALTED) )
911
    {
912
      if (IntMACRxStatus & MACRXSTAT_ALLIGN_ERR)
913
        ++ifStats.rx_align_errors;
914
      if (IntMACRxStatus & MACRXSTAT_CRC_ERR)
915
        ++ifStats.rx_crc_errors;
916
      if (IntMACRxStatus & MACRXSTAT_OVERFLOW)
917
        ++ifStats.rx_overrun_errors;
918
      if (IntMACRxStatus & MACRXSTAT_LONG_ERR)
919
        ++ifStats.rx_too_long_frames;
920
      if (IntMACRxStatus & MACRXSTAT_PAR)
921
        ++ifStats.rx_symbol_errors;
922
      if (IntMACRxStatus & MACRXSTAT_HALTED)
923
        ;
924
    }
925
#endif  
926
  return CYG_ISR_HANDLED;
927
}
928
 
929
 
930
 
931
//======================================================================
932
// This interrupt only happens when errors occur
933
static cyg_uint32 BDMA_Tx_isr(cyg_vector_t vector, cyg_addrword_t data)
934
{
935
  U32 IntBDMATxStatus;
936
 
937
  cyg_drv_interrupt_acknowledge(vector);
938
 
939
  IntBDMATxStatus = BDMASTAT;
940
  BDMASTAT = IntBDMATxStatus;
941
 
942
  ++ks5000_BDMA_Tx_Isr_Cnt;
943
#if defined(CYGPKG_NET)  
944
  ++ifStats.interrupts;
945
#endif  
946
  if (IntBDMATxStatus & BDMASTAT_TX_CCP)
947
    {
948
      debug1_printf("+-- Control Packet Transfered : %x\r",ERMPZCNT);
949
      debug1_printf("    Tx Control Frame Status : %x\r",ETXSTAT);
950
    }
951
 
952
  if (IntBDMATxStatus & (BDMASTAT_TX_NL|BDMASTAT_TX_NO|BDMASTAT_TX_EMPTY) )
953
    {
954
      if (IntBDMATxStatus & BDMASTAT_TX_NL)
955
        BDMATxErrCnt.BTxNLErr++;
956
      if (IntBDMATxStatus & BDMASTAT_TX_NO)
957
        BDMATxErrCnt.BTxNOErr++;
958
      if (IntBDMATxStatus & BDMASTAT_TX_EMPTY)
959
        BDMATxErrCnt.BTxEmptyErr++;
960
    }
961
 
962
  // free any buffers we're done with
963
 
964
  while (txDonePointer->FrameDataPtr && !(txDonePointer->FrameDataPtr & FRM_OWNERSHIP_BDMA))
965
    {
966
      freeBuffer((tEthBuffer*)txDonePointer->FrameDataPtr);
967
      txDonePointer->FrameDataPtr = 0;
968
      txDonePointer = txDonePointer->NextFD;
969
    }
970
 
971
  // don't call tx dsr for now -- it has nothing to do
972
 
973
  return CYG_ISR_HANDLED;
974
}
975
 
976
 
977
static void BDMA_Tx_dsr(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
978
{
979
  ++ks5000_BDMA_Tx_Dsr_Cnt;
980
}
981
 
982
 
983
 
984
//======================================================================
985
static cyg_uint32 BDMA_Rx_isr(cyg_vector_t vector, cyg_addrword_t data)
986
{
987
  U32 IntBDMARxStatus;
988
 
989
  cyg_drv_interrupt_acknowledge(vector);
990
 
991
  IntBDMARxStatus = BDMASTAT;
992
  BDMASTAT = IntBDMARxStatus;
993
 
994
  ++ks5000_BDMA_Rx_Isr_Cnt;
995
#if defined(CYGPKG_NET)  
996
  ++ifStats.interrupts;
997
#endif
998
  if (IntBDMARxStatus & (BDMASTAT_RX_NL  | BDMASTAT_RX_NO |
999
                         BDMASTAT_RX_MSO | BDMASTAT_RX_EMPTY |
1000
                         BDMASTAT_RX_SEARLY) )
1001
    {
1002
//      printf("RxIsr %u\r\n", (unsigned)cyg_current_time());
1003
      if (IntBDMARxStatus & BDMASTAT_RX_NL)
1004
        BDMARxErrCnt.BRxNLErr++;
1005
      if (IntBDMARxStatus & BDMASTAT_RX_NO)
1006
        BDMARxErrCnt.BRxNOErr++;
1007
      if (IntBDMARxStatus & BDMASTAT_RX_MSO)
1008
        BDMARxErrCnt.BRxMSOErr++;
1009
      if (IntBDMARxStatus & BDMASTAT_RX_EMPTY)
1010
        BDMARxErrCnt.BRxEmptyErr++;
1011
      if (IntBDMARxStatus & BDMASTAT_RX_SEARLY)
1012
        BDMARxErrCnt.sBRxSEarly++;
1013
    }
1014
 
1015
  return CYG_ISR_HANDLED|CYG_ISR_CALL_DSR;
1016
}
1017
 
1018
static void eth_handle_recv_buffer(tEthBuffer*);
1019
 
1020
static cyg_handle_t  bdmaRxIntrHandle;
1021
static cyg_handle_t  bdmaTxIntrHandle;
1022
static cyg_handle_t  macRxIntrHandle;
1023
static cyg_handle_t  macTxIntrHandle;
1024
 
1025
static cyg_interrupt  bdmaRxIntrObject;
1026
static cyg_interrupt  bdmaTxIntrObject;
1027
static cyg_interrupt  macRxIntrObject;
1028
static cyg_interrupt  macTxIntrObject;
1029
 
1030
static int ethernetRunning;
1031
 
1032
#if HavePHYinterrupt
1033
static cyg_handle_t  macPhyIntrHandle;
1034
static cyg_interrupt  macPhyIntrObject;
1035
#endif
1036
 
1037
static void ks32c5000_eth_deliver(struct eth_drv_sc *sc)
1038
{
1039
  unsigned short p;
1040
  tEthBuffer *rxBuffer;
1041
  extern void cyg_interrupt_post_dsr(CYG_ADDRWORD intr_obj);
1042
 
1043
  ++ks5000_BDMA_Rx_Dsr_Cnt;
1044
 
1045
  while (1)
1046
    {
1047
      if (!rx_frame_avail())
1048
        {
1049
          // no more frames
1050
          return;
1051
        }
1052
 
1053
      if (!(rxBuffer=ks32c5000_eth_get_recv_buffer()))
1054
        {
1055
          // no buffers available
1056
          return;
1057
        }
1058
 
1059
      p = *((unsigned short*)(rxBuffer->data+EtherFramePadding+ETH_HEADER_SIZE-2));
1060
 
1061
      if (ethernetRunning)
1062
        eth_handle_recv_buffer(rxBuffer);
1063
      else
1064
        freeBuffer(rxBuffer);
1065
    }
1066
}
1067
 
1068
 
1069
static void installInterrupts(void)
1070
{
1071
  extern struct eth_drv_sc ks32c5000_sc;
1072
  bool firstTime=true;
1073
 
1074
  debug1_printf("ks5000_ether: installInterrupts()\n");
1075
 
1076
  if (!firstTime)
1077
    return;
1078
  firstTime = false;
1079
 
1080
  initFreeList();
1081
  Init_RxFrameDescriptorArray();
1082
  Init_TxFrameDescriptorArray();
1083
 
1084
  BDMARXPTR = (U32)rxReadPointer;
1085
  BDMATXPTR = (U32)txWritePointer;
1086
 
1087
  cyg_drv_mutex_init(&txMutex);
1088
  cyg_drv_mutex_init(&oldRxMutex);
1089
  cyg_drv_cond_init(&oldRxCond,&oldRxMutex);
1090
 
1091
  cyg_drv_interrupt_create(CYGNUM_HAL_INTERRUPT_ETH_BDMA_RX,0,(unsigned)&ks32c5000_sc,BDMA_Rx_isr,eth_drv_dsr,&bdmaRxIntrHandle,&bdmaRxIntrObject);
1092
  cyg_drv_interrupt_create(CYGNUM_HAL_INTERRUPT_ETH_BDMA_TX,0,0,BDMA_Tx_isr,BDMA_Tx_dsr,&bdmaTxIntrHandle,&bdmaTxIntrObject);
1093
  cyg_drv_interrupt_create(CYGNUM_HAL_INTERRUPT_ETH_MAC_RX,0,0,MAC_Rx_isr,NULL,&macRxIntrHandle,&macRxIntrObject);
1094
  cyg_drv_interrupt_create(CYGNUM_HAL_INTERRUPT_ETH_MAC_TX,0,0,MAC_Tx_isr,NULL,&macTxIntrHandle,&macTxIntrObject);
1095
#if HavePHYinterrupt
1096
  cyg_drv_interrupt_create(CYGNUM_HAL_INTERRUPT_EXT0,0,0,MAC_Phy_isr,NULL,&macPhyIntrHandle,&macPhyIntrObject);
1097
  cyg_drv_interrupt_attach(macPhyIntrHandle);
1098
#endif  
1099
 
1100
  cyg_drv_interrupt_attach(bdmaRxIntrHandle);
1101
  cyg_drv_interrupt_attach(bdmaTxIntrHandle);
1102
  cyg_drv_interrupt_attach(macRxIntrHandle);
1103
  cyg_drv_interrupt_attach(macTxIntrHandle);
1104
 
1105
#if HavePHYinterrupt
1106
  cyg_drv_interrupt_acknowledge(CYGNUM_HAL_INTERRUPT_EXT0);
1107
  cyg_drv_interrupt_unmask(CYGNUM_HAL_INTERRUPT_EXT0);
1108
#endif  
1109
}
1110
 
1111
//======================================================================
1112
// Driver code that interfaces to the TCP/IP stack via the common
1113
// Ethernet interface.
1114
 
1115
 
1116
// don't have any private data, but if we did, this is where it would go
1117
typedef struct
1118
{
1119
  int j;
1120
}ks32c5000_priv_data_t;
1121
 
1122
ks32c5000_priv_data_t ks32c5000_priv_data;
1123
 
1124
#define eth_drv_tx_done(sc,key,retval) (sc)->funs->eth_drv->tx_done(sc,key,retval)
1125
#define eth_drv_init(sc,enaddr)  ((sc)->funs->eth_drv->init)(sc, enaddr)
1126
#define eth_drv_recv(sc,len)  ((sc)->funs->eth_drv->recv)(sc, len)
1127
 
1128
static unsigned char myMacAddr[6] = { CYGPKG_DEVS_ETH_ARM_KS32C5000_MACADDR };
1129
 
1130
static bool ks32c5000_eth_init(struct cyg_netdevtab_entry *tab)
1131
{
1132
  struct eth_drv_sc *sc = (struct eth_drv_sc *)tab->device_instance;
1133
  debug1_printf("ks32c5000_eth_init()\n");
1134
  debug1_printf("  MAC address %02x:%02x:%02x:%02x:%02x:%02x\n",myMacAddr[0],myMacAddr[1],myMacAddr[2],myMacAddr[3],myMacAddr[4],myMacAddr[5]);
1135
#if defined(CYGPKG_NET)  
1136
  ifStats.duplex = 1;      //unknown
1137
  ifStats.operational = 1; //unknown
1138
  ifStats.tx_queue_len = MAX_TX_FRAME_DESCRIPTORS;
1139
#endif  
1140
  installInterrupts();
1141
  EthInit(myMacAddr);
1142
  cyg_drv_interrupt_unmask(CYGNUM_HAL_INTERRUPT_ETH_BDMA_RX);
1143
  cyg_drv_interrupt_unmask(CYGNUM_HAL_INTERRUPT_ETH_BDMA_TX);
1144
  cyg_drv_interrupt_unmask(CYGNUM_HAL_INTERRUPT_ETH_MAC_RX);
1145
  cyg_drv_interrupt_unmask(CYGNUM_HAL_INTERRUPT_ETH_MAC_TX);
1146
  configDone = 1;
1147
  ethernetRunning = 1;
1148
  eth_drv_init(sc, myMacAddr);
1149
  return true;
1150
}
1151
 
1152
static void ks32c5000_eth_start(struct eth_drv_sc *sc, unsigned char *enaddr, int flags)
1153
{
1154
  debug2_printf("ks32c5000_eth_start()\n");
1155
  if (!ethernetRunning)
1156
    {
1157
      cyg_drv_interrupt_mask(CYGNUM_HAL_INTERRUPT_ETH_BDMA_RX);
1158
      cyg_drv_interrupt_mask(CYGNUM_HAL_INTERRUPT_ETH_BDMA_TX);
1159
      cyg_drv_interrupt_mask(CYGNUM_HAL_INTERRUPT_ETH_MAC_RX);
1160
      cyg_drv_interrupt_mask(CYGNUM_HAL_INTERRUPT_ETH_MAC_TX);
1161
      EthInit(enaddr);
1162
      cyg_drv_interrupt_unmask(CYGNUM_HAL_INTERRUPT_ETH_BDMA_RX);
1163
      cyg_drv_interrupt_unmask(CYGNUM_HAL_INTERRUPT_ETH_BDMA_TX);
1164
      cyg_drv_interrupt_unmask(CYGNUM_HAL_INTERRUPT_ETH_MAC_RX);
1165
      cyg_drv_interrupt_unmask(CYGNUM_HAL_INTERRUPT_ETH_MAC_TX);
1166
      ethernetRunning = 1;
1167
    }
1168
}
1169
 
1170
static void ks32c5000_eth_stop(struct eth_drv_sc *sc)
1171
{
1172
  debug1_printf("ks32c5000_eth_stop()\n");
1173
  ethernetRunning = 0;
1174
}
1175
 
1176
static int ks32c5000_eth_control(struct eth_drv_sc *sc,
1177
                          unsigned long cmd,
1178
                          void *data,
1179
                          int len)
1180
{
1181
  switch (cmd)
1182
    {
1183
#if defined(CYGPKG_NET)      
1184
     case ETH_DRV_GET_IF_STATS_UD:
1185
     case ETH_DRV_GET_IF_STATS:
1186
        {
1187
          struct ether_drv_stats *p = (struct ether_drv_stats*)data;
1188
          *p = ifStats;
1189
          strncpy(p->description,"description goes here",sizeof(p->description)-1);
1190
                  p->description[sizeof(p->description)-1] = '\0';
1191
          strncpy(p->snmp_chipset,"chipset name",sizeof(p->snmp_chipset)-1);
1192
                  p->snmp_chipset[sizeof(p->snmp_chipset)-1] = '\0';
1193
          return 0;
1194
        }
1195
#endif      
1196
     case ETH_DRV_SET_MAC_ADDRESS: {
1197
         int act;
1198
 
1199
         if (ETHER_ADDR_LEN != len)
1200
             return -1;
1201
         debug1_printf("ks32c5000_eth_control: ETH_DRV_SET_MAC_ADDRESS.\n");
1202
         act = ethernetRunning;
1203
         ks32c5000_eth_stop(sc);
1204
         ks32c5000_eth_start(sc, data, 0);
1205
         ethernetRunning = act;
1206
         return 0;
1207
     }
1208
#ifdef  ETH_DRV_GET_MAC_ADDRESS
1209
     case ETH_DRV_GET_MAC_ADDRESS: {
1210
         if (len < ETHER_ADDR_LEN)
1211
             return -1;
1212
         debug1_printf("ks32c5000_eth_control: ETH_DRV_GET_MAC_ADDRESS.\n");
1213
         memcpy(data, (void *)CAM_BaseAddr, ETHER_ADDR_LEN);
1214
         return 0;
1215
     }
1216
#endif
1217
     default:
1218
      return -1;
1219
    }
1220
}
1221
 
1222
static int ks32c5000_eth_can_send_count=0;
1223
static int ks32c5000_eth_can_send_count_OK=0;
1224
 
1225
// In case there are multiple Tx frames waiting, we should
1226
// return how many empty Tx spots we have.  For now we just
1227
// return 0 or 1.
1228
static int ks32c5000_eth_can_send(struct eth_drv_sc *sc)
1229
{
1230
  FRAME_DESCRIPTOR *TxFp, *StartFp;
1231
 
1232
  // find the next unused spot in the queue
1233
 
1234
  ++ks32c5000_eth_can_send_count;
1235
 
1236
  StartFp = TxFp = (FRAME_DESCRIPTOR*)BDMATXPTR;
1237
 
1238
  while (TxFp->FrameDataPtr & FRM_OWNERSHIP_BDMA)
1239
    {
1240
      TxFp = TxFp->NextFD;
1241
      if (TxFp == StartFp)
1242
        return 0;
1243
    }
1244
  ++ks32c5000_eth_can_send_count_OK;
1245
  return 1;
1246
}
1247
 
1248
static int ks5000_eth_send_count=0;
1249
 
1250
static void ks32c5000_eth_send(struct eth_drv_sc *sc,
1251
                               struct eth_drv_sg *sg_list,
1252
                               int sg_len,
1253
                               int total_len,
1254
                               unsigned long key)
1255
{
1256
  unsigned char *dest;
1257
  unsigned        len;
1258
  tEthBuffer *buf;
1259
 
1260
  if (total_len >= MAX_ETH_FRAME_SIZE)
1261
    {
1262
      eth_drv_tx_done(sc,key,-EINVAL);
1263
      return;
1264
    }
1265
 
1266
  ++ks5000_eth_send_count;
1267
 
1268
  // allocate buffer
1269
 
1270
  buf = allocBuffer();
1271
  if (!buf)
1272
    {
1273
      // out of buffers
1274
      eth_drv_tx_done(sc,key,-EIO);
1275
      return;
1276
    }
1277
 
1278
  // copy data from scatter/gather list into BDMA data buffer
1279
 
1280
  len = 0;
1281
  dest = buf->data;
1282
 
1283
  while (sg_len)
1284
    {
1285
      memcpy(dest,(unsigned char*)sg_list->buf,sg_list->len);
1286
      len += sg_list->len;
1287
      dest += sg_list->len;
1288
      ++sg_list;
1289
      --sg_len;
1290
    }
1291
 
1292
  buf->length = len;
1293
 
1294
  // tell upper layer that we're done with this sglist
1295
 
1296
  eth_drv_tx_done(sc,key,0);
1297
 
1298
  // queue packet for transmit
1299
 
1300
  while(!ks32c5000_eth_buffer_send(buf))
1301
    {
1302
#if defined(CYGPKG_KERNEL)
1303
      // wait a tick and try again.
1304
      cyg_thread_delay(1);
1305
#else
1306
      // toss it.
1307
      freeBuffer(buf);
1308
      break;
1309
#endif      
1310
    }
1311
 
1312
}
1313
 
1314
 
1315
static int ks5000_eth_rcv_count=0;
1316
static tEthBuffer *tcpIpRxBuffer;
1317
 
1318
// called from DSR
1319
static void eth_handle_recv_buffer(tEthBuffer* rxBuffer)
1320
{
1321
  extern struct eth_drv_sc ks32c5000_sc;
1322
  tcpIpRxBuffer = rxBuffer;
1323
  eth_drv_recv(&ks32c5000_sc,tcpIpRxBuffer->length-4);  // discard 32-bit CRC
1324
}
1325
 
1326
static void ks32c5000_eth_recv(struct eth_drv_sc *sc,
1327
                        struct eth_drv_sg *sg_list,
1328
                        int sg_len)
1329
{
1330
  unsigned char *source;
1331
 
1332
  ++ks5000_eth_rcv_count;
1333
 
1334
  if (!tcpIpRxBuffer)
1335
      return;  // no packet waiting, shouldn't be here!
1336
 
1337
  // copy data from eth buffer into scatter/gather list
1338
 
1339
  source = tcpIpRxBuffer->data + EtherFramePadding;
1340
 
1341
  while (sg_len)
1342
    {
1343
          if (sg_list->buf)
1344
                memcpy((unsigned char*)sg_list->buf,source,sg_list->len);
1345
      source += sg_list->len;
1346
      ++sg_list;
1347
      --sg_len;
1348
    }
1349
 
1350
  freeBuffer(tcpIpRxBuffer);
1351
  tcpIpRxBuffer = NULL;
1352
  return;
1353
}
1354
 
1355
// routine called to handle ethernet controller in polled mode
1356
static void ks32c5000_eth_poll(struct eth_drv_sc *sc)
1357
{
1358
  BDMA_Rx_isr(CYGNUM_HAL_INTERRUPT_ETH_BDMA_RX, 0); // Call ISR routine
1359
  ks32c5000_eth_deliver(sc);  // handle rx frames
1360
  ks32c5000_handle_tx_complete();
1361
}
1362
 
1363
static int ks32c5000_eth_int_vector(struct eth_drv_sc *sc)
1364
{
1365
  return CYGNUM_HAL_INTERRUPT_ETH_BDMA_RX;
1366
}
1367
 
1368
 
1369
ETH_DRV_SC(ks32c5000_sc,
1370
           &ks32c5000_priv_data, // Driver specific data
1371
           "eth0",                // Name for this interface
1372
           ks32c5000_eth_start,
1373
           ks32c5000_eth_stop,
1374
           ks32c5000_eth_control,
1375
           ks32c5000_eth_can_send,
1376
           ks32c5000_eth_send,
1377
           ks32c5000_eth_recv,
1378
           ks32c5000_eth_deliver,
1379
           ks32c5000_eth_poll,
1380
           ks32c5000_eth_int_vector
1381
           );
1382
 
1383
NETDEVTAB_ENTRY(ks32c5000_netdev,
1384
                "ks32c5000",
1385
                ks32c5000_eth_init,
1386
                &ks32c5000_sc);

powered by: WebSVN 2.1.0

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