📄 ks5000_ether.c
字号:
--freeCount;
else
{
++allocFail;
if (freeCount)
bufferListError();
}
return r;
}
#endif
static void initFreeList(void)
{
int i;
ethBufQueueClear(&freeList);
freeCount = 0;
for (i=0; i<NUM_ETH_BUFFERS; ++i)
isrFreeBuffer(bufferPool+i);
}
//----------------------------------------------------------------------
// queue a buffer for transmit
//
// returns true if buffer was queued.
static int ks32c5000_eth_buffer_send(tEthBuffer *buf)
{
#if defined(CYGINT_IO_ETH_INT_SUPPORT_REQUIRED)
while (!configDone)
cyg_thread_delay(10);
#endif
if (txWritePointer->FrameDataPtr & FRM_OWNERSHIP_BDMA)
{
// queue is full! make sure transmit is running
BDMATXCON |= BDMATXCON_EN;
MACTXCON |= MACTXCON_TX_EN;
return 0;
}
cyg_drv_mutex_lock(&txMutex);
// free old buffer if we need to
cyg_drv_isr_lock();
if (txWritePointer->FrameDataPtr)
{
freeBuffer((tEthBuffer*)txWritePointer->FrameDataPtr);
txWritePointer->FrameDataPtr = 0;
}
cyg_drv_isr_unlock();
MAC_Tx_Pkts += 1;
MAC_Tx_Octets += buf->length;
// fill in the packet descriptor
#if (CYG_BYTEORDER == CYG_MSBFIRST) // Big endian
txWritePointer->Reserved = (TXFDCON_PADDING_MODE | TXFDCON_CRC_MODE |
TXFDCON_SRC_ADDR_INC | TXFDCON_BIG_ENDIAN |
TXFDCON_WIDGET_ALIGN00 | TXFDCON_MAC_TX_INT_EN);
#else // Little endian
txWritePointer->Reserved = (TXFDCON_PADDING_MODE | TXFDCON_CRC_MODE |
TXFDCON_SRC_ADDR_INC | TXFDCON_LITTLE_ENDIAN |
TXFDCON_WIDGET_ALIGN00 | TXFDCON_MAC_TX_INT_EN);
#endif
txWritePointer->StatusAndFrameLength = buf->length;
txWritePointer->FrameDataPtr = ((unsigned)buf | FRM_OWNERSHIP_BDMA);
txWritePointer = txWritePointer->NextFD;
cyg_drv_mutex_unlock(&txMutex);
// start transmit
#if defined(CYGPKG_NET)
++ifStats.tx_count;
#endif
BDMATXCON |= BDMATXCON_EN;
MACTXCON |= MACTXCON_TX_EN;
return 1;
}
//======================================================================
// check to see if there's a frame waiting
static int rx_frame_avail(void)
{
if (rxReadPointer->FrameDataPtr & FRM_OWNERSHIP_BDMA)
{
// queue is empty -- make sure Rx is running
if (!(BDMARXCON & BDMARXCON_EN))
{
++BDMARxErrCnt.queueOverflow;
BDMARXCON |= BDMARXCON_EN;
}
return 0;
}
else
return 1;
}
//======================================================================
// de-queue a receive buffer
static tEthBuffer *ks32c5000_eth_get_recv_buffer(void)
{
unsigned RxStatusAndLength;
tEthBuffer *RxBufPtr;
tEthBuffer *emptyBuf;
#if SoftwareCRC
unsigned crc, crclen;
int crcOK;
#else
# define crcOK 1
#endif
while (1)
{
if (rxReadPointer->FrameDataPtr & FRM_OWNERSHIP_BDMA)
{
// queue is empty -- make sure Rx is running
if (!(BDMARXCON & BDMARXCON_EN))
{
++BDMARxErrCnt.queueOverflow;
BDMARXCON |= BDMARXCON_EN;
}
return NULL;
}
RxBufPtr = (tEthBuffer*)rxReadPointer->FrameDataPtr;
RxStatusAndLength = rxReadPointer->StatusAndFrameLength;
// counting on short-circuit && evaluation below to only
// allocate a fresh buffer if rx packet is good!!
#if defined (CYGPKG_NET)
++ifStats.rx_count;
#endif
#if SoftwareCRC
crclen = (RxStatusAndLength & 0xffff) - 4;
crc = cyg_ether_crc32(RxBufPtr->data+2,crclen);
crcOK = ((U08)(crc>>0) == RxBufPtr->data[2+crclen+0] &&
(U08)(crc>>8) == RxBufPtr->data[2+crclen+1] &&
(U08)(crc>>16) == RxBufPtr->data[2+crclen+2] &&
(U08)(crc>>24) == RxBufPtr->data[2+crclen+3]);
#endif
if ((RxStatusAndLength & (RXFDSTAT_GOOD<<16))
&& crcOK
&& (emptyBuf = allocBuffer()))
{
// good packet and we've got a fresh buffer to take
// it's place in the receive queue
rxReadPointer->FrameDataPtr = (unsigned)emptyBuf | FRM_OWNERSHIP_BDMA;
rxReadPointer = rxReadPointer->NextFD;
RxBufPtr->length = RxStatusAndLength & 0xffff;
#if defined(CYGPKG_NET)
++ifStats.rx_deliver;
#endif
return RxBufPtr;
}
else
{
// bad packet or out of buffers. either way we
// ignore this packet, and reuse the buffer
#if defined(CYGPKG_NET)
if (RxStatusAndLength & (RXFDSTAT_GOOD<<16) && crcOK)
++ifStats.rx_resource;
else
++ifStats.rx_crc_errors;
#endif
rxReadPointer->FrameDataPtr |= FRM_OWNERSHIP_BDMA;
rxReadPointer = rxReadPointer->NextFD;
}
}
}
//======================================================================
static int EthInit(U08* mac_address)
{
#if CYGINT_DEVS_ETH_ARM_KS32C5000_PHY && defined(CYGPKG_NET)
unsigned linkStatus;
#endif
if (mac_address)
debug2_printf("EthInit(%02x:%02x:%02x:%02x:%02x:%02x)\n",
mac_address[0],mac_address[1],mac_address[2],
mac_address[3],mac_address[4],mac_address[5]);
else
debug2_printf("EthInit(NULL)\n");
#if CYGINT_DEVS_ETH_ARM_KS32C5000_PHY
PhyReset();
#endif
/* Set the initial condition of the BDMA. */
BDMARXCON = BDMARXCON_RESET;
BDMATXCON = BDMATXCON_RESET;
BDMARXLSZ = MAX_ETH_FRAME_SIZE;
BDMARXPTR = (U32)rxReadPointer;
BDMATXPTR = (U32)txWritePointer;
MACCON = MACON_SW_RESET;
MACCON = MACConfigVar;
CAMCON = CAMConfigVar;
// set up our MAC address
if (mac_address)
{
*((volatile U32*)CAM_BaseAddr) =
(mac_address[0]<<24) |
(mac_address[1]<<16) |
(mac_address[2]<< 8) |
(mac_address[3]<< 0);
*((volatile U16*)(CAM_BaseAddr+4)) =
(mac_address[4]<< 8) |
(mac_address[5]<< 0);
}
// CAM Enable
CAMEN = 0x0001;
// update the Configuration of BDMA and MAC to begin Rx/Tx
BDMARXCON = BDMARxConfigVar;
MACRXCON = MACRxConfigVar;
BDMATXCON = BDMATxConfigVar;
MACTXCON = MACTxConfigVar;
debug2_printf("ks32C5000 eth: %02x:%02x:%02x:%02x:%02x:%02x ",
*((volatile unsigned char*)CAM_BaseAddr+0),
*((volatile unsigned char*)CAM_BaseAddr+1),
*((volatile unsigned char*)CAM_BaseAddr+2),
*((volatile unsigned char*)CAM_BaseAddr+3),
*((volatile unsigned char*)CAM_BaseAddr+4),
*((volatile unsigned char*)CAM_BaseAddr+5));
#if CYGINT_DEVS_ETH_ARM_KS32C5000_PHY && defined(CYGPKG_NET)
// Read link status to be up to date
linkStatus = PhyStatus();
if (linkStatus & PhyStatus_FullDuplex)
ifStats.duplex = 3;
else
ifStats.duplex = 2;
if (linkStatus & PhyStatus_LinkUp)
ifStats.operational = 3;
else
ifStats.operational = 2;
if (linkStatus & PhyStatus_100Mb)
ifStats.speed = 100000000;
else
ifStats.speed = 10000000;
#endif
#if SoftwareCRC
debug2_printf("Software CRC\n");
#else
debug2_printf("Hardware CRC\n");
#endif
return 0;
}
//======================================================================
static void Init_TxFrameDescriptorArray(void)
{
FRAME_DESCRIPTOR *pFrameDescriptor;
int i;
// Each Frame Descriptor's frame data pointer points is NULL
// if not in use, otherwise points to an ethBuffer
pFrameDescriptor = txFrameDescrArray;
for(i=0; i < MAX_TX_FRAME_DESCRIPTORS; i++)
{
pFrameDescriptor->FrameDataPtr = 0;
pFrameDescriptor->Reserved = 0;
pFrameDescriptor->StatusAndFrameLength = 0;
pFrameDescriptor->NextFD = pFrameDescriptor+1;
pFrameDescriptor++;
}
// fix up the last pointer to loop back to the first
txFrameDescrArray[MAX_TX_FRAME_DESCRIPTORS-1].NextFD = txFrameDescrArray;
txDonePointer = txWritePointer = txFrameDescrArray;
return;
}
//======================================================================
static void Init_RxFrameDescriptorArray(void)
{
FRAME_DESCRIPTOR *pFrameDescriptor;
int i;
// Each Frame Descriptor's frame data pointer points to
// an ethBuffer struct
pFrameDescriptor = rxFrameDescrArray;
for(i=0; i < MAX_RX_FRAME_DESCRIPTORS; i++)
{
pFrameDescriptor->FrameDataPtr = ((unsigned)allocBuffer() | FRM_OWNERSHIP_BDMA);
pFrameDescriptor->Reserved = 0;
pFrameDescriptor->StatusAndFrameLength = 0;
pFrameDescriptor->NextFD = pFrameDescriptor+1;
pFrameDescriptor++;
}
// fix up the last pointer to loop back to the first
rxFrameDescrArray[MAX_RX_FRAME_DESCRIPTORS-1].NextFD = rxFrameDescrArray;
rxReadPointer = rxFrameDescrArray;
return;
}
#if CYGINT_DEVS_ETH_ARM_KS32C5000_PHY
#if HavePHYinterrupt
static unsigned linkStatus;
static cyg_uint32 MAC_Phy_isr(cyg_vector_t vector, cyg_addrword_t data)
{
cyg_drv_interrupt_acknowledge(vector);
PhyInterruptAck();
++ks5000_MAC_Phy_Cnt;
linkStatus = PhyStatus();
if (linkStatus & PhyStatus_FullDuplex)
MACConfigVar |= (MACON_FULL_DUP);
else
MACConfigVar &= ~(MACON_FULL_DUP);
#if defined(CYGPKG_NET)
if (linkStatus & PhyStatus_FullDuplex)
ifStats.duplex = 3;
else
ifStats.duplex = 2;
if (linkStatus & PhyStatus_LinkUp)
ifStats.operational = 3;
else
ifStats.operational = 2;
if (linkStatus & PhyStatus_100Mb)
ifStats.speed = 100000000;
else
ifStats.speed = 10000000;
#endif
MACCON = MACConfigVar;
return CYG_ISR_HANDLED;
}
#endif
#endif
static void ks32c5000_handle_tx_complete(void)
{
// record status and then free any buffers we're done with
while (txDonePointer->FrameDataPtr && !(txDonePointer->FrameDataPtr & FRM_OWNERSHIP_BDMA))
{
#if defined(CYGPKG_NET)
U32 txStatus;
txStatus = txDonePointer->StatusAndFrameLength>>16;
++ks5000_MAC_Tx_Cnt;
++ifStats.interrupts;
if (txStatus & MACTXSTAT_COMP)
++ifStats.tx_complete;
if (txStatus & (MACTXSTAT_EX_COLL | MACTXSTAT_DEFFERED |
MACTXSTAT_UNDER | MACTXSTAT_DEFER |
MACTXSTAT_NCARR | MACTXSTAT_SIG_QUAL |
MACTXSTAT_LATE_COLL | MACTXSTAT_PAR |
MACTXSTAT_PAUSED | MACTXSTAT_HALTED))
{
// transmit failed, log errors
if (txStatus & MACTXSTAT_EX_COLL)
++ifStats.tx_max_collisions;
if (txStatus & MACTXSTAT_DEFFERED)
++ifStats.tx_deferred;
if (txStatus & MACTXSTAT_UNDER)
++ifStats.tx_underrun;
if (txStatus & MACTXSTAT_DEFER)
;
if (txStatus & MACTXSTAT_NCARR)
++ifStats.tx_carrier_loss;
if (txStatus & MACTXSTAT_SIG_QUAL)
++ifStats.tx_sqetesterrors;
if (txStatus & MACTXSTAT_LATE_COLL)
++ifStats.tx_late_collisions;
if (txStatus & MACTXSTAT_PAR)
;
if (txStatus & MACTXSTAT_PAUSED)
;
if (txStatus & MACTXSTAT_HALTED)
;
}
else
{
// transmit OK
int collisionCnt = txStatus & 0x0f;
++ifStats.tx_good;
if (collisionCnt)
{
if (collisionCnt == 1)
++ifStats.tx_single_collisions;
else
++ifStats.tx_mult_collisions;
ifStats.tx_total_collisions += collisionCnt;
}
}
#endif
isrFreeBuffer((tEthBuffer*)txDonePointer->FrameDataPtr);
txDonePointer->FrameDataPtr = 0;
txDonePointer = txDonePointer->NextFD;
}
}
//======================================================================
static cyg_uint32 MAC_Tx_isr(cyg_vector_t vector, cyg_addrword_t data)
{
cyg_drv_interrupt_acknowledge(vector);
ks32c5000_handle_tx_complete();
return CYG_ISR_HANDLED;
}
static unsigned accumulatedMaxRxStatus=0;
//======================================================================
static cyg_uint32 MAC_Rx_isr(cyg_vector_t vector, cyg_addrword_t data)
{
U32 IntMACRxStatus;
cyg_drv_interrupt_acknowledge(vector);
IntMACRxStatus = MACRXSTAT;
MACRXSTAT = IntMACRxStatus;
accumulatedMaxRxStatus |= IntMACRxStatus;
++ks5000_MAC_Rx_Cnt;
#if defined(CYGPKG_NET)
++ifStats.interrupts;
if (IntMACRxStatus & MACRXSTAT_GOOD)
{
++ifStats.rx_good;
if (IntMACRxStatus & MACRXSTAT_CTL_RECD)
; // we don't do anything with control packets
return CYG_ISR_HANDLED;
}
if (IntMACRxStatus & (MACRXSTAT_ALLIGN_ERR | MACRXSTAT_CRC_ERR |
MACRXSTAT_OVERFLOW | MACRXSTAT_LONG_ERR |
MACRXSTAT_PAR | MACRXSTAT_HALTED) )
{
if (IntMACRxStatus & MACRXSTAT_ALLIGN_ERR)
++ifStats.rx_align_errors;
if (IntMACRxStatus & MACRXSTAT_CRC_ERR)
++ifStats.rx_crc_errors;
if (IntMACRxStatus & MACRXSTAT_OVERFLOW)
++ifStats.rx_overrun_errors;
if (IntMACRxStatus & MACRXSTAT_LONG_ERR)
++ifStats.rx_too_long_frames;
if (IntMACRxStatus & MACRXSTAT_PAR)
++ifStats.rx_symbol_errors;
if (IntMACRxStatus & MACRXSTAT_HALTED)
;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -