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