1 //==========================================================================
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.
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.
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
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.
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.
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.
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####
44 // Contributors: gthomas, jskov
45 // Grant Edwards <grante@visi.com>
50 //####DESCRIPTIONEND####
52 //========================================================================*/
54 #include <pkgconf/system.h>
55 #include <pkgconf/devs_eth_arm_ks32c5000.h>
56 #include <pkgconf/io_eth_drivers.h>
59 #if defined(CYGPKG_IO)
60 #include <pkgconf/io.h>
61 #include <cyg/io/io.h>
62 #include <cyg/io/devtab.h>
64 // need to provide fake values for errno?
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>
80 #if defined(CYGPKG_REDBOOT)
81 #include <pkgconf/redboot.h>
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 */
96 #define HavePHYinterrupt 0
99 #include "ks5000_regs.h"
100 #include "ks5000_ether.h"
102 #if CYGINT_DEVS_ETH_ARM_KS32C5000_PHY
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)
110 #define debug1_printf(args...) /* noop */
112 #if CYGPKG_DEVS_ETH_ARM_KS32C5000_DEBUG_LEVEL > 1
113 #define debug2_printf(args...) diag_printf(args)
115 #define debug2_printf(args...) /* noop */
118 #define Bit(n) (1<<(n))
120 // enable/disable software verification of rx CRC
121 // should be moved to user-controlled valud in CDL file
123 #if defined(CYG_HAL_CPUTYPE_KS32C5000A)
124 #define SoftwareCRC 1
125 #include <cyg/crc/crc.h>
127 #define SoftwareCRC 0
130 // --------------------------------------------------------------
131 // RedBoot configuration options for managing ESAs for us
133 // Decide whether to have redboot config vars for it...
134 #if defined(CYGSEM_REDBOOT_FLASH_CONFIG) && defined(CYGPKG_REDBOOT_NETWORKING)
136 #include <flash_config.h>
138 #ifdef CYGSEM_DEVS_ETH_ARM_KS32C5000_REDBOOT_HOLDS_ESA_ETH0
139 RedBoot_config_option("Network hardware address [MAC] for eth0",
141 ALWAYS_ENABLED, true,
145 #endif // CYGPKG_REDBOOT_NETWORKING && CYGSEM_REDBOOT_FLASH_CONFIG
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
151 #include <cyg/hal/hal_if.h>
154 #define CONFIG_ESA (6)
157 #define CYGHWR_DEVS_ETH_ARM_KS32C5000_GET_ESA( mac_address, ok ) \
159 ok = CYGACC_CALL_IF_FLASH_CFG_OP( CYGNUM_CALL_IF_FLASH_CFG_GET, \
160 "eth0_esa_data", mac_address, CONFIG_ESA); \
163 #endif // CYGPKG_DEVS_ETH_I82559_ETH_REDBOOT_HOLDS_ESA
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
173 void MiiStationWrite(U32 RegAddr, U32 PhyAddr, U32 PhyWrData)
175 STADATA = PhyWrData ;
176 STACON = RegAddr | (PhyAddr<<5) | MiiStart | PHYREGWRITE ;
177 while (STACON & MiiStart)
179 //debug1_printf("PHY Wr %x:%02x := %04x\n",PhyAddr, RegAddr, PhyWrData) ;
182 U32 MiiStationRead(U32 RegAddr, U32 PhyAddr)
185 STACON = RegAddr | (PhyAddr<<5) | MiiStart;
186 while (STACON & MiiStart)
189 //debug1_printf("PHY Rd %x:%02x %04x\n",PhyAddr,RegAddr,PhyRdData) ;
194 // miscellaneous data structures
196 typedef BYTE ETH_ADDR[6] __attribute__((packed));
198 typedef struct tagETH_HEADER
200 ETH_ADDR daddr __attribute__((packed));
201 ETH_ADDR saddr __attribute__((packed));
202 WORD type __attribute__((packed));
203 } ETH_HEADER __attribute__((packed));
205 #define ETH_HEADER_SIZE 14
207 // Tx/Rx common descriptor structure
208 typedef struct tagFRAME_DESCRIPTOR
211 LWORD Reserved; /* cf: RX-reserved, TX-Reserved(25bits) + Control bits(7bits) */
212 LWORD StatusAndFrameLength;
213 struct tagFRAME_DESCRIPTOR *NextFD;
218 U8 DestinationAddr[6];
224 #if defined(CYGPKG_NET)
225 struct ether_drv_stats ifStats;
228 #if defined(CYGINT_IO_ETH_INT_SUPPORT_REQUIRED)
229 static cyg_drv_mutex_t txMutex;
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;
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;
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 | */
276 MACTXCON_EN_LATE_COLL |
279 static volatile U32 MACRxConfigVar =
282 MACRXCON_EN_CRC_ERR |
284 MACRXCON_EN_LONG_ERR |
287 static volatile U32 BDMATxConfigVar =
290 3; /* burst size - 1 */
292 #define EtherFramePadding 2
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
303 #error "EtherFramePadding must be 0,1,2 or 3"
306 #if (CYG_BYTEORDER == CYG_MSBFIRST) // Big endian
307 static volatile U32 BDMARxConfigVar =
315 15; /* burst size - 1 */
317 #else // Little endian
318 static volatile U32 BDMARxConfigVar =
326 15; /* burst size - 1 */
330 /* Global variables For BDMA Error Report */
332 static BDMA_TX_ERR BDMATxErrCnt = {0,0,0};
333 static BDMA_RX_ERR BDMARxErrCnt = {0,0,0,0,0};
336 static void Init_TxFrameDescriptorArray(void);
337 static void Init_RxFrameDescriptorArray(void);
339 // number of ethernet buffers should be enough to keep both rx
340 // and tx queues full plus some extras for in-process packets
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
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
352 static FRAME_DESCRIPTOR _rxFrameDescrArray[MAX_RX_FRAME_DESCRIPTORS] __attribute__((aligned(16)));
353 static FRAME_DESCRIPTOR _txFrameDescrArray[MAX_TX_FRAME_DESCRIPTORS] __attribute__((aligned(16)));
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))
359 static volatile FRAME_DESCRIPTOR *rxReadPointer;
360 static volatile FRAME_DESCRIPTOR *txDonePointer;
361 static volatile FRAME_DESCRIPTOR *txWritePointer;
363 static cyg_drv_mutex_t oldRxMutex;
364 static cyg_drv_cond_t oldRxCond;
367 static bool configDone;
369 /*----------------------------------------------------------------------
370 * Data structures used to manage ethernet buffers
372 #define MAX_ETH_FRAME_SIZE 1520
374 typedef struct tEthBufferTag
376 unsigned char data[MAX_ETH_FRAME_SIZE+8];
379 struct tEthBufferTag *next;
380 struct tEthBufferTag *prev;
390 #define EmptyQueue {NULL,NULL}
392 static void ethBufQueueClear(tEthBufQueue *q)
398 static tEthBuffer *ethBufQueueGet(tEthBufQueue *q)
410 static void ethBufQueuePut(tEthBufQueue *q, tEthBuffer *b)
427 // not used at the moment
428 static bool ethBufQueueEmpty(tEthBufQueue *q)
430 return q->head != NULL;
434 /*----------------------------------------------------------------------
435 * Free pool and routines to manipulate it.
438 static tEthBuffer __bufferPool[NUM_ETH_BUFFERS] __attribute__((aligned(16)));
439 #define bufferPool ((tEthBuffer*)((unsigned)__bufferPool|0x4000000))
441 static tEthBufQueue freeList;
442 static int freeCount;
444 // do not call from ISR routine
445 static void freeBuffer(tEthBuffer *b)
449 ethBufQueuePut(&freeList,b);
450 cyg_drv_isr_unlock();
453 static int allocFail;
455 void bufferListError(void)
461 // do not call from ISR routine
462 static tEthBuffer *allocBuffer(void)
466 r = ethBufQueueGet(&freeList);
467 cyg_drv_isr_unlock();
479 // call only from ISR routine or init
480 static void isrFreeBuffer(tEthBuffer *b)
483 ethBufQueuePut(&freeList,b);
487 // not used at the moment
489 // call only from ISR routine or init
490 static tEthBuffer *isrAllocBuffer(void)
493 r = ethBufQueueGet(&freeList);
506 static void initFreeList(void)
509 ethBufQueueClear(&freeList);
511 for (i=0; i<NUM_ETH_BUFFERS; ++i)
512 isrFreeBuffer(bufferPool+i);
516 //----------------------------------------------------------------------
517 // queue a buffer for transmit
519 // returns true if buffer was queued.
521 static int ks32c5000_eth_buffer_send(tEthBuffer *buf)
523 #if defined(CYGINT_IO_ETH_INT_SUPPORT_REQUIRED)
525 cyg_thread_delay(10);
528 if (txWritePointer->FrameDataPtr & FRM_OWNERSHIP_BDMA)
530 // queue is full! make sure transmit is running
531 BDMATXCON |= BDMATXCON_EN;
532 MACTXCON |= MACTXCON_TX_EN;
536 cyg_drv_mutex_lock(&txMutex);
538 // free old buffer if we need to
541 if (txWritePointer->FrameDataPtr)
543 freeBuffer((tEthBuffer*)txWritePointer->FrameDataPtr);
544 txWritePointer->FrameDataPtr = 0;
546 cyg_drv_isr_unlock();
549 MAC_Tx_Octets += buf->length;
551 // fill in the packet descriptor
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);
563 txWritePointer->StatusAndFrameLength = buf->length;
564 txWritePointer->FrameDataPtr = ((unsigned)buf | FRM_OWNERSHIP_BDMA);
566 txWritePointer = txWritePointer->NextFD;
568 cyg_drv_mutex_unlock(&txMutex);
572 #if defined(CYGPKG_NET)
576 BDMATXCON |= BDMATXCON_EN;
577 MACTXCON |= MACTXCON_TX_EN;
582 //======================================================================
583 // check to see if there's a frame waiting
585 static int rx_frame_avail(void)
587 if (rxReadPointer->FrameDataPtr & FRM_OWNERSHIP_BDMA)
589 // queue is empty -- make sure Rx is running
590 if (!(BDMARXCON & BDMARXCON_EN))
592 ++BDMARxErrCnt.queueOverflow;
593 BDMARXCON |= BDMARXCON_EN;
602 //======================================================================
603 // de-queue a receive buffer
604 static tEthBuffer *ks32c5000_eth_get_recv_buffer(void)
606 unsigned RxStatusAndLength;
607 tEthBuffer *RxBufPtr;
608 tEthBuffer *emptyBuf;
610 unsigned crc, crclen;
618 if (rxReadPointer->FrameDataPtr & FRM_OWNERSHIP_BDMA)
620 // queue is empty -- make sure Rx is running
621 if (!(BDMARXCON & BDMARXCON_EN))
623 ++BDMARxErrCnt.queueOverflow;
624 BDMARXCON |= BDMARXCON_EN;
629 RxBufPtr = (tEthBuffer*)rxReadPointer->FrameDataPtr;
630 RxStatusAndLength = rxReadPointer->StatusAndFrameLength;
632 // counting on short-circuit && evaluation below to only
633 // allocate a fresh buffer if rx packet is good!!
635 #if defined (CYGPKG_NET)
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]);
647 if ((RxStatusAndLength & (RXFDSTAT_GOOD<<16))
649 && (emptyBuf = allocBuffer()))
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;
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;
669 ++ifStats.rx_crc_errors;
671 rxReadPointer->FrameDataPtr |= FRM_OWNERSHIP_BDMA;
672 rxReadPointer = rxReadPointer->NextFD;
677 //======================================================================
678 static int EthInit(U08* mac_address)
680 #if CYGINT_DEVS_ETH_ARM_KS32C5000_PHY && defined(CYGPKG_NET)
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]);
689 debug2_printf("EthInit(NULL)\n");
691 #if CYGINT_DEVS_ETH_ARM_KS32C5000_PHY
695 /* Set the initial condition of the BDMA. */
696 BDMARXCON = BDMARXCON_RESET;
697 BDMATXCON = BDMATXCON_RESET;
698 BDMARXLSZ = MAX_ETH_FRAME_SIZE;
700 BDMARXPTR = (U32)rxReadPointer;
701 BDMATXPTR = (U32)txWritePointer;
703 MACCON = MACON_SW_RESET;
704 MACCON = MACConfigVar;
706 CAMCON = CAMConfigVar;
708 // set up our MAC address
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);
724 // update the Configuration of BDMA and MAC to begin Rx/Tx
726 BDMARXCON = BDMARxConfigVar;
727 MACRXCON = MACRxConfigVar;
729 BDMATXCON = BDMATxConfigVar;
730 MACTXCON = MACTxConfigVar;
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));
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)
748 if (linkStatus & PhyStatus_LinkUp)
749 ifStats.operational = 3;
751 ifStats.operational = 2;
753 if (linkStatus & PhyStatus_100Mb)
754 ifStats.speed = 100000000;
756 ifStats.speed = 10000000;
760 debug2_printf("Software CRC\n");
762 debug2_printf("Hardware CRC\n");
768 //======================================================================
769 static void Init_TxFrameDescriptorArray(void)
771 FRAME_DESCRIPTOR *pFrameDescriptor;
774 // Each Frame Descriptor's frame data pointer points is NULL
775 // if not in use, otherwise points to an ethBuffer
777 pFrameDescriptor = txFrameDescrArray;
779 for(i=0; i < MAX_TX_FRAME_DESCRIPTORS; i++)
781 pFrameDescriptor->FrameDataPtr = 0;
782 pFrameDescriptor->Reserved = 0;
783 pFrameDescriptor->StatusAndFrameLength = 0;
784 pFrameDescriptor->NextFD = pFrameDescriptor+1;
788 // fix up the last pointer to loop back to the first
790 txFrameDescrArray[MAX_TX_FRAME_DESCRIPTORS-1].NextFD = txFrameDescrArray;
792 txDonePointer = txWritePointer = txFrameDescrArray;
798 //======================================================================
799 static void Init_RxFrameDescriptorArray(void)
801 FRAME_DESCRIPTOR *pFrameDescriptor;
804 // Each Frame Descriptor's frame data pointer points to
805 // an ethBuffer struct
807 pFrameDescriptor = rxFrameDescrArray;
809 for(i=0; i < MAX_RX_FRAME_DESCRIPTORS; i++)
811 pFrameDescriptor->FrameDataPtr = ((unsigned)allocBuffer() | FRM_OWNERSHIP_BDMA);
812 pFrameDescriptor->Reserved = 0;
813 pFrameDescriptor->StatusAndFrameLength = 0;
814 pFrameDescriptor->NextFD = pFrameDescriptor+1;
818 // fix up the last pointer to loop back to the first
820 rxFrameDescrArray[MAX_RX_FRAME_DESCRIPTORS-1].NextFD = rxFrameDescrArray;
822 rxReadPointer = rxFrameDescrArray;
827 #if CYGINT_DEVS_ETH_ARM_KS32C5000_PHY
830 static unsigned linkStatus;
832 static cyg_uint32 MAC_Phy_isr(cyg_vector_t vector, cyg_addrword_t data)
834 cyg_drv_interrupt_acknowledge(vector);
836 ++ks5000_MAC_Phy_Cnt;
837 linkStatus = PhyStatus();
838 if (linkStatus & PhyStatus_FullDuplex)
839 MACConfigVar |= (MACON_FULL_DUP);
841 MACConfigVar &= ~(MACON_FULL_DUP);
843 #if defined(CYGPKG_NET)
844 if (linkStatus & PhyStatus_FullDuplex)
849 if (linkStatus & PhyStatus_LinkUp)
850 ifStats.operational = 3;
852 ifStats.operational = 2;
854 if (linkStatus & PhyStatus_100Mb)
855 ifStats.speed = 100000000;
857 ifStats.speed = 10000000;
860 MACCON = MACConfigVar;
861 return CYG_ISR_HANDLED;
866 static void ks32c5000_handle_tx_complete(void)
869 // record status and then free any buffers we're done with
871 while (txDonePointer->FrameDataPtr && !(txDonePointer->FrameDataPtr & FRM_OWNERSHIP_BDMA))
873 #if defined(CYGPKG_NET)
876 txStatus = txDonePointer->StatusAndFrameLength>>16;
879 ++ifStats.interrupts;
881 if (txStatus & MACTXSTAT_COMP)
882 ++ifStats.tx_complete;
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))
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)
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)
907 if (txStatus & MACTXSTAT_PAUSED)
909 if (txStatus & MACTXSTAT_HALTED)
915 int collisionCnt = txStatus & 0x0f;
919 if (collisionCnt == 1)
920 ++ifStats.tx_single_collisions;
922 ++ifStats.tx_mult_collisions;
923 ifStats.tx_total_collisions += collisionCnt;
927 isrFreeBuffer((tEthBuffer*)txDonePointer->FrameDataPtr);
928 txDonePointer->FrameDataPtr = 0;
929 txDonePointer = txDonePointer->NextFD;
934 //======================================================================
935 static cyg_uint32 MAC_Tx_isr(cyg_vector_t vector, cyg_addrword_t data)
937 cyg_drv_interrupt_acknowledge(vector);
938 ks32c5000_handle_tx_complete();
939 return CYG_ISR_HANDLED;
942 static unsigned accumulatedMaxRxStatus=0;
944 //======================================================================
945 static cyg_uint32 MAC_Rx_isr(cyg_vector_t vector, cyg_addrword_t data)
949 cyg_drv_interrupt_acknowledge(vector);
951 IntMACRxStatus = MACRXSTAT;
952 MACRXSTAT = IntMACRxStatus;
954 accumulatedMaxRxStatus |= IntMACRxStatus;
958 #if defined(CYGPKG_NET)
960 ++ifStats.interrupts;
962 if (IntMACRxStatus & MACRXSTAT_GOOD)
966 if (IntMACRxStatus & MACRXSTAT_CTL_RECD)
967 ; // we don't do anything with control packets
969 return CYG_ISR_HANDLED;
972 if (IntMACRxStatus & (MACRXSTAT_ALLIGN_ERR | MACRXSTAT_CRC_ERR |
973 MACRXSTAT_OVERFLOW | MACRXSTAT_LONG_ERR |
974 MACRXSTAT_PAR | MACRXSTAT_HALTED) )
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)
990 return CYG_ISR_HANDLED;
995 //======================================================================
996 // This interrupt only happens when errors occur
997 static cyg_uint32 BDMA_Tx_isr(cyg_vector_t vector, cyg_addrword_t data)
1001 cyg_drv_interrupt_acknowledge(vector);
1003 IntBDMATxStatus = BDMASTAT;
1004 BDMASTAT = IntBDMATxStatus;
1006 ++ks5000_BDMA_Tx_Isr_Cnt;
1007 #if defined(CYGPKG_NET)
1008 ++ifStats.interrupts;
1010 if (IntBDMATxStatus & BDMASTAT_TX_CCP)
1012 debug1_printf("+-- Control Packet Transfered : %x\r",ERMPZCNT);
1013 debug1_printf(" Tx Control Frame Status : %x\r",ETXSTAT);
1016 if (IntBDMATxStatus & (BDMASTAT_TX_NL|BDMASTAT_TX_NO|BDMASTAT_TX_EMPTY) )
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++;
1026 // free any buffers we're done with
1028 while (txDonePointer->FrameDataPtr && !(txDonePointer->FrameDataPtr & FRM_OWNERSHIP_BDMA))
1030 freeBuffer((tEthBuffer*)txDonePointer->FrameDataPtr);
1031 txDonePointer->FrameDataPtr = 0;
1032 txDonePointer = txDonePointer->NextFD;
1035 // don't call tx dsr for now -- it has nothing to do
1037 return CYG_ISR_HANDLED;
1041 static void BDMA_Tx_dsr(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
1043 ++ks5000_BDMA_Tx_Dsr_Cnt;
1048 //======================================================================
1049 static cyg_uint32 BDMA_Rx_isr(cyg_vector_t vector, cyg_addrword_t data)
1051 U32 IntBDMARxStatus;
1053 cyg_drv_interrupt_acknowledge(vector);
1055 IntBDMARxStatus = BDMASTAT;
1056 BDMASTAT = IntBDMARxStatus;
1058 ++ks5000_BDMA_Rx_Isr_Cnt;
1059 #if defined(CYGPKG_NET)
1060 ++ifStats.interrupts;
1062 if (IntBDMARxStatus & (BDMASTAT_RX_NL | BDMASTAT_RX_NO |
1063 BDMASTAT_RX_MSO | BDMASTAT_RX_EMPTY |
1064 BDMASTAT_RX_SEARLY) )
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++;
1079 return CYG_ISR_HANDLED|CYG_ISR_CALL_DSR;
1082 static void eth_handle_recv_buffer(tEthBuffer*);
1084 static cyg_handle_t bdmaRxIntrHandle;
1085 static cyg_handle_t bdmaTxIntrHandle;
1086 static cyg_handle_t macRxIntrHandle;
1087 static cyg_handle_t macTxIntrHandle;
1089 static cyg_interrupt bdmaRxIntrObject;
1090 static cyg_interrupt bdmaTxIntrObject;
1091 static cyg_interrupt macRxIntrObject;
1092 static cyg_interrupt macTxIntrObject;
1094 static int ethernetRunning;
1096 #if HavePHYinterrupt
1097 static cyg_handle_t macPhyIntrHandle;
1098 static cyg_interrupt macPhyIntrObject;
1101 static void ks32c5000_eth_deliver(struct eth_drv_sc *sc)
1104 tEthBuffer *rxBuffer;
1105 extern void cyg_interrupt_post_dsr(CYG_ADDRWORD intr_obj);
1107 ++ks5000_BDMA_Rx_Dsr_Cnt;
1111 if (!rx_frame_avail())
1117 if (!(rxBuffer=ks32c5000_eth_get_recv_buffer()))
1119 // no buffers available
1123 p = *((unsigned short*)(rxBuffer->data+EtherFramePadding+ETH_HEADER_SIZE-2));
1125 if (ethernetRunning)
1126 eth_handle_recv_buffer(rxBuffer);
1128 freeBuffer(rxBuffer);
1133 static void installInterrupts(void)
1135 extern struct eth_drv_sc ks32c5000_sc;
1136 static bool firstTime=true;
1138 debug1_printf("ks5000_ether: installInterrupts()\n");
1145 Init_RxFrameDescriptorArray();
1146 Init_TxFrameDescriptorArray();
1148 BDMARXPTR = (U32)rxReadPointer;
1149 BDMATXPTR = (U32)txWritePointer;
1151 cyg_drv_mutex_init(&txMutex);
1152 cyg_drv_mutex_init(&oldRxMutex);
1153 cyg_drv_cond_init(&oldRxCond,&oldRxMutex);
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);
1164 cyg_drv_interrupt_attach(bdmaRxIntrHandle);
1165 cyg_drv_interrupt_attach(bdmaTxIntrHandle);
1166 cyg_drv_interrupt_attach(macRxIntrHandle);
1167 cyg_drv_interrupt_attach(macTxIntrHandle);
1169 #if HavePHYinterrupt
1170 cyg_drv_interrupt_acknowledge(CYGNUM_HAL_INTERRUPT_EXT0);
1171 cyg_drv_interrupt_unmask(CYGNUM_HAL_INTERRUPT_EXT0);
1175 //======================================================================
1176 // Driver code that interfaces to the TCP/IP stack via the common
1177 // Ethernet interface.
1180 // don't have any private data, but if we did, this is where it would go
1184 }ks32c5000_priv_data_t;
1186 ks32c5000_priv_data_t ks32c5000_priv_data;
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)
1192 static bool ks32c5000_eth_init(struct cyg_netdevtab_entry *tab)
1194 unsigned char myMacAddr[6] = { CYGPKG_DEVS_ETH_ARM_KS32C5000_MACADDR };
1195 struct eth_drv_sc *sc = (struct eth_drv_sc *)tab->device_instance;
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
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
1214 installInterrupts();
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);
1221 ethernetRunning = 1;
1222 eth_drv_init(sc, myMacAddr);
1226 static void ks32c5000_eth_start(struct eth_drv_sc *sc, unsigned char *enaddr, int flags)
1228 debug2_printf("ks32c5000_eth_start()\n");
1229 if (!ethernetRunning)
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);
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;
1244 static void ks32c5000_eth_stop(struct eth_drv_sc *sc)
1246 debug1_printf("ks32c5000_eth_stop()\n");
1247 ethernetRunning = 0;
1250 static int ks32c5000_eth_control(struct eth_drv_sc *sc,
1257 #if defined(CYGPKG_NET)
1258 case ETH_DRV_GET_IF_STATS_UD:
1259 case ETH_DRV_GET_IF_STATS:
1261 struct ether_drv_stats *p = (struct ether_drv_stats*)data;
1263 #if CYGINT_DEVS_ETH_ARM_KS32C5000_PHY
1264 unsigned linkStatus;
1266 // Read link status to be up to date
1267 linkStatus = PhyStatus();
1268 if (linkStatus & PhyStatus_FullDuplex)
1273 if (linkStatus & PhyStatus_LinkUp)
1274 ifStats.operational = 3;
1276 ifStats.operational = 2;
1278 if (linkStatus & PhyStatus_100Mb)
1279 ifStats.speed = 100000000;
1281 ifStats.speed = 10000000;
1288 case ETH_DRV_SET_MAC_ADDRESS: {
1291 if (ETHER_ADDR_LEN != len)
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;
1300 #ifdef ETH_DRV_GET_MAC_ADDRESS
1301 case ETH_DRV_GET_MAC_ADDRESS: {
1302 if (len < ETHER_ADDR_LEN)
1304 debug1_printf("ks32c5000_eth_control: ETH_DRV_GET_MAC_ADDRESS.\n");
1305 memcpy(data, (void *)CAM_BaseAddr, ETHER_ADDR_LEN);
1314 static int ks32c5000_eth_can_send_count=0;
1315 static int ks32c5000_eth_can_send_count_OK=0;
1317 // In case there are multiple Tx frames waiting, we should
1318 // return how many empty Tx spots we have. For now we just
1320 static int ks32c5000_eth_can_send(struct eth_drv_sc *sc)
1322 FRAME_DESCRIPTOR *TxFp, *StartFp;
1324 // find the next unused spot in the queue
1326 ++ks32c5000_eth_can_send_count;
1328 StartFp = TxFp = (FRAME_DESCRIPTOR*)BDMATXPTR;
1330 while (TxFp->FrameDataPtr & FRM_OWNERSHIP_BDMA)
1332 TxFp = TxFp->NextFD;
1333 if (TxFp == StartFp)
1336 ++ks32c5000_eth_can_send_count_OK;
1340 static int ks5000_eth_send_count=0;
1342 static void ks32c5000_eth_send(struct eth_drv_sc *sc,
1343 struct eth_drv_sg *sg_list,
1348 unsigned char *dest;
1352 if (total_len >= MAX_ETH_FRAME_SIZE)
1354 eth_drv_tx_done(sc,key,-EINVAL);
1358 ++ks5000_eth_send_count;
1362 buf = allocBuffer();
1366 eth_drv_tx_done(sc,key,-EIO);
1370 // copy data from scatter/gather list into BDMA data buffer
1377 memcpy(dest,(unsigned char*)sg_list->buf,sg_list->len);
1378 len += sg_list->len;
1379 dest += sg_list->len;
1386 // tell upper layer that we're done with this sglist
1388 eth_drv_tx_done(sc,key,0);
1390 // queue packet for transmit
1392 while(!ks32c5000_eth_buffer_send(buf))
1394 #if defined(CYGPKG_KERNEL)
1395 // wait a tick and try again.
1396 cyg_thread_delay(1);
1407 static int ks5000_eth_rcv_count=0;
1408 static tEthBuffer *tcpIpRxBuffer;
1411 static void eth_handle_recv_buffer(tEthBuffer* rxBuffer)
1413 extern struct eth_drv_sc ks32c5000_sc;
1414 tcpIpRxBuffer = rxBuffer;
1415 eth_drv_recv(&ks32c5000_sc,tcpIpRxBuffer->length-4); // discard 32-bit CRC
1418 static void ks32c5000_eth_recv(struct eth_drv_sc *sc,
1419 struct eth_drv_sg *sg_list,
1422 unsigned char *source;
1424 ++ks5000_eth_rcv_count;
1427 return; // no packet waiting, shouldn't be here!
1429 // copy data from eth buffer into scatter/gather list
1431 source = tcpIpRxBuffer->data + EtherFramePadding;
1436 memcpy((unsigned char*)sg_list->buf,source,sg_list->len);
1437 source += sg_list->len;
1442 freeBuffer(tcpIpRxBuffer);
1443 tcpIpRxBuffer = NULL;
1447 // routine called to handle ethernet controller in polled mode
1448 static void ks32c5000_eth_poll(struct eth_drv_sc *sc)
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();
1455 static int ks32c5000_eth_int_vector(struct eth_drv_sc *sc)
1457 return CYGNUM_HAL_INTERRUPT_ETH_BDMA_RX;
1461 ETH_DRV_SC(ks32c5000_sc,
1462 &ks32c5000_priv_data, // Driver specific data
1463 "eth0", // Name for this interface
1464 ks32c5000_eth_start,
1466 ks32c5000_eth_control,
1467 ks32c5000_eth_can_send,
1470 ks32c5000_eth_deliver,
1472 ks32c5000_eth_int_vector
1475 NETDEVTAB_ENTRY(ks32c5000_netdev,
1480 // EOF ks5000_ether.c