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 + -
显示快捷键?