xemac.c
来自「适合KS8695X」· C语言 代码 · 共 845 行 · 第 1/2 页
C
845 行
*/
if (InstancePtr->IsStarted != XCOMPONENT_IS_STARTED) {
return XST_DEVICE_IS_STOPPED;
}
/*
* If configured for scatter-gather DMA, stop the DMA channels. Ignore
* the XST_DMA_SG_IS_STOPPED return code. There is a critical section
* here between SgStart and SgStop, and SgStart can be called in interrupt
* context, so disable interrupts while calling SgStop.
*/
if (XEmac_mIsSgDma(InstancePtr)) {
XBufDescriptor *BdTemp; /* temporary descriptor pointer */
XIIF_V123B_GINTR_DISABLE(InstancePtr->BaseAddress);
(void) XDmaChannel_SgStop(&InstancePtr->SendChannel, &BdTemp);
(void) XDmaChannel_SgStop(&InstancePtr->RecvChannel, &BdTemp);
XIIF_V123B_GINTR_ENABLE(InstancePtr->BaseAddress);
}
/*
* Disable the transmitter and receiver. There is no critical section
* here since this register is not modified during interrupt context.
*/
ControlReg = XIo_In32(InstancePtr->BaseAddress + XEM_ECR_OFFSET);
ControlReg &= ~(XEM_ECR_XMIT_ENABLE_MASK | XEM_ECR_RECV_ENABLE_MASK);
XIo_Out32(InstancePtr->BaseAddress + XEM_ECR_OFFSET, ControlReg);
/*
* If not in polled mode, disable interrupts for IPIF (includes MAC and
* DMAs)
*/
if (!InstancePtr->IsPolled) {
XIIF_V123B_GINTR_DISABLE(InstancePtr->BaseAddress);
}
InstancePtr->IsStarted = 0;
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* Reset the Ethernet MAC. This is a graceful reset in that the device is stopped
* first. Resets the DMA channels, the FIFOs, the transmitter, and the receiver.
* The PHY is not reset. Any frames in the scatter-gather descriptor lists will
* remain in the lists. The side effect of doing this is that after a reset and
* following a restart of the device, frames that were in the list before the
* reset may be transmitted or received. Reset must only be called after the
* driver has been initialized.
*
* The driver is also taken out of polled mode if polled mode was set. The user
* is responsbile for re-configuring the driver into polled mode after the
* reset if desired.
*
* The configuration after this reset is as follows:
* - Half duplex
* - Disabled transmitter and receiver
* - Enabled PHY (the PHY is not reset)
* - MAC transmitter does pad insertion, FCS insertion, and source address
* overwrite.
* - MAC receiver does not strip padding or FCS
* - Interframe Gap as recommended by IEEE Std. 802.3 (96 bit times)
* - Unicast addressing enabled
* - Broadcast addressing enabled
* - Multicast addressing disabled (addresses are preserved)
* - Promiscuous addressing disabled
* - Default packet threshold and packet wait bound register values for
* scatter-gather DMA operation
* - MAC address of all zeros
* - Non-polled mode
*
* The upper layer software is responsible for re-configuring (if necessary)
* and restarting the MAC after the reset. Note that the PHY is not reset. PHY
* control is left to the upper layer software. Note also that driver statistics
* are not cleared on reset. It is up to the upper layer software to clear the
* statistics if needed.
*
* When a reset is required due to an internal error, the driver notifies the
* upper layer software of this need through the ErrorHandler callback and
* specific status codes. The upper layer software is responsible for calling
* this Reset function and then re-configuring the device.
*
* @param InstancePtr is a pointer to the XEmac instance to be worked on.
*
* @return
*
* None.
*
* @note
*
* None.
*
* @internal
*
* The reset is accomplished by setting the IPIF reset register. This takes
* care of resetting all hardware blocks, including the MAC.
*
******************************************************************************/
void
XEmac_Reset(XEmac * InstancePtr)
{
XASSERT_VOID(InstancePtr != NULL);
XASSERT_VOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
/*
* Stop the device first
*/
(void) XEmac_Stop(InstancePtr);
/*
* Take the driver out of polled mode
*/
InstancePtr->IsPolled = FALSE;
/*
* Reset the entire IPIF at once. If we choose someday to reset each
* hardware block separately, the reset should occur in the direction of
* data flow. For example, for the send direction the reset order is DMA
* first, then FIFO, then the MAC transmitter.
*/
XIIF_V123B_RESET(InstancePtr->BaseAddress);
if (XEmac_mIsSgDma(InstancePtr)) {
/*
* After reset, configure the scatter-gather DMA packet threshold and
* packet wait bound registers to default values. Ignore the return
* values of these functions since they only return error if the device
* is not stopped.
*/
(void) XEmac_SetPktThreshold(InstancePtr, XEM_SEND,
XEM_SGDMA_DFT_THRESHOLD);
(void) XEmac_SetPktThreshold(InstancePtr, XEM_RECV,
XEM_SGDMA_DFT_THRESHOLD);
(void) XEmac_SetPktWaitBound(InstancePtr, XEM_SEND,
XEM_SGDMA_DFT_WAITBOUND);
(void) XEmac_SetPktWaitBound(InstancePtr, XEM_RECV,
XEM_SGDMA_DFT_WAITBOUND);
}
}
/*****************************************************************************/
/**
*
* Set the MAC address for this driver/device. The address is a 48-bit value.
* The device must be stopped before calling this function.
*
* @param InstancePtr is a pointer to the XEmac instance to be worked on.
* @param AddressPtr is a pointer to a 6-byte MAC address.
*
* @return
*
* - XST_SUCCESS if the MAC address was set successfully
* - XST_DEVICE_IS_STARTED if the device has not yet been stopped
*
* @note
*
* None.
*
******************************************************************************/
XStatus
XEmac_SetMacAddress(XEmac * InstancePtr, u8 * AddressPtr)
{
u32 MacAddr = 0;
XASSERT_NONVOID(InstancePtr != NULL);
XASSERT_NONVOID(AddressPtr != NULL);
XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
/*
* The device must be stopped before setting the MAC address
*/
if (InstancePtr->IsStarted == XCOMPONENT_IS_STARTED) {
return XST_DEVICE_IS_STARTED;
}
/*
* Set the device station address high and low registers
*/
MacAddr = (AddressPtr[0] << 8) | AddressPtr[1];
XIo_Out32(InstancePtr->BaseAddress + XEM_SAH_OFFSET, MacAddr);
MacAddr = (AddressPtr[2] << 24) | (AddressPtr[3] << 16) |
(AddressPtr[4] << 8) | AddressPtr[5];
XIo_Out32(InstancePtr->BaseAddress + XEM_SAL_OFFSET, MacAddr);
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* Get the MAC address for this driver/device.
*
* @param InstancePtr is a pointer to the XEmac instance to be worked on.
* @param BufferPtr is an output parameter, and is a pointer to a buffer into
* which the current MAC address will be copied. The buffer must be at
* least 6 bytes.
*
* @return
*
* None.
*
* @note
*
* None.
*
******************************************************************************/
void
XEmac_GetMacAddress(XEmac * InstancePtr, u8 * BufferPtr)
{
u32 MacAddrHi;
u32 MacAddrLo;
XASSERT_VOID(InstancePtr != NULL);
XASSERT_VOID(BufferPtr != NULL);
XASSERT_VOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
MacAddrHi = XIo_In32(InstancePtr->BaseAddress + XEM_SAH_OFFSET);
MacAddrLo = XIo_In32(InstancePtr->BaseAddress + XEM_SAL_OFFSET);
BufferPtr[0] = (u8) (MacAddrHi >> 8);
BufferPtr[1] = (u8) MacAddrHi;
BufferPtr[2] = (u8) (MacAddrLo >> 24);
BufferPtr[3] = (u8) (MacAddrLo >> 16);
BufferPtr[4] = (u8) (MacAddrLo >> 8);
BufferPtr[5] = (u8) MacAddrLo;
}
/******************************************************************************/
/**
*
* Configure DMA capabilities.
*
* @param InstancePtr is a pointer to the XEmac instance to be worked on.
*
* @return
*
* - XST_SUCCESS if successful initialization of DMA
*
* @note
*
* None.
*
******************************************************************************/
static XStatus
ConfigureDma(XEmac * InstancePtr)
{
XStatus Result;
/*
* Initialize the DMA channels with their base addresses. We assume
* scatter-gather DMA is the only possible configuration. Descriptor space
* will need to be set later by the upper layer.
*/
Result = XDmaChannel_Initialize(&InstancePtr->RecvChannel,
InstancePtr->BaseAddress +
XEM_DMA_RECV_OFFSET);
if (Result != XST_SUCCESS) {
return Result;
}
Result = XDmaChannel_Initialize(&InstancePtr->SendChannel,
InstancePtr->BaseAddress +
XEM_DMA_SEND_OFFSET);
return Result;
}
/******************************************************************************/
/**
*
* Configure the send and receive FIFO components with their base addresses
* and interrupt masks. Currently the base addresses are defined constants.
*
* @param InstancePtr is a pointer to the XEmac instance to be worked on.
*
* @return
*
* XST_SUCCESS if successful initialization of the packet FIFOs
*
* @note
*
* None.
*
******************************************************************************/
static XStatus
ConfigureFifo(XEmac * InstancePtr)
{
XStatus Result;
/*
* Return status from the packet FIFOs initialization is ignored since
* they always return success.
*/
Result = XPacketFifoV100b_Initialize(&InstancePtr->RecvFifo,
InstancePtr->BaseAddress +
XEM_PFIFO_RXREG_OFFSET,
InstancePtr->BaseAddress +
XEM_PFIFO_RXDATA_OFFSET);
if (Result != XST_SUCCESS) {
return Result;
}
Result = XPacketFifoV100b_Initialize(&InstancePtr->SendFifo,
InstancePtr->BaseAddress +
XEM_PFIFO_TXREG_OFFSET,
InstancePtr->BaseAddress +
XEM_PFIFO_TXDATA_OFFSET);
return Result;
}
/******************************************************************************/
/**
*
* This is a stub for the scatter-gather send and recv callbacks. The stub
* is here in case the upper layers forget to set the handlers.
*
* @param CallBackRef is a pointer to the upper layer callback reference
* @param BdPtr is a pointer to the first buffer descriptor in a list
* @param NumBds is the number of descriptors in the list.
*
* @return
*
* None.
*
* @note
*
* None.
*
******************************************************************************/
static void
StubSgHandler(void *CallBackRef, XBufDescriptor * BdPtr, u32 NumBds)
{
XASSERT_VOID_ALWAYS();
}
/******************************************************************************/
/**
*
* This is a stub for the non-DMA send and recv callbacks. The stub is here in
* case the upper layers forget to set the handlers.
*
* @param CallBackRef is a pointer to the upper layer callback reference
*
* @return
*
* None.
*
* @note
*
* None.
*
******************************************************************************/
static void
StubFifoHandler(void *CallBackRef)
{
XASSERT_VOID_ALWAYS();
}
/******************************************************************************/
/**
*
* This is a stub for the asynchronous error callback. The stub is here in
* case the upper layers forget to set the handler.
*
* @param CallBackRef is a pointer to the upper layer callback reference
* @param ErrorCode is the Xilinx error code, indicating the cause of the error
*
* @return
*
* None.
*
* @note
*
* None.
*
******************************************************************************/
static void
StubErrorHandler(void *CallBackRef, XStatus ErrorCode)
{
XASSERT_VOID_ALWAYS();
}
/*****************************************************************************/
/**
*
* Lookup the device configuration based on the unique device ID. The table
* EmacConfigTable contains the configuration info for each device in the system.
*
* @param DeviceId is the unique device ID of the device being looked up.
*
* @return
*
* A pointer to the configuration table entry corresponding to the given
* device ID, or NULL if no match is found.
*
* @note
*
* None.
*
******************************************************************************/
XEmac_Config *
XEmac_LookupConfig(u16 DeviceId)
{
XEmac_Config *CfgPtr = NULL;
int i;
for (i = 0; i < XPAR_XEMAC_NUM_INSTANCES; i++) {
if (XEmac_ConfigTable[i].DeviceId == DeviceId) {
CfgPtr = &XEmac_ConfigTable[i];
break;
}
}
return CfgPtr;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?