GMAC driver
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@11166 35acf78f-673a-0410-8e92-d51de3d6d3f4
This commit is contained in:
parent
0684b80fe1
commit
58883bb41b
|
@ -0,0 +1,9 @@
|
|||
ifeq ($(USE_SMART_BUILD),yes)
|
||||
ifneq ($(findstring HAL_USE_MAC TRUE,$(HALCONF)),)
|
||||
PLATFORMSRC += $(CHIBIOS)/os/hal/ports/SAMA/LLD/MACv1/hal_mac_lld.c
|
||||
endif
|
||||
else
|
||||
PLATFORMSRC += $(CHIBIOS)/os/hal/ports/SAMA/LLD/MACv1/hal_mac_lld.c
|
||||
endif
|
||||
|
||||
PLATFORMINC += $(CHIBIOS)/os/hal/ports/SAMA/LLD/MACv1
|
|
@ -0,0 +1,826 @@
|
|||
/*
|
||||
ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file MACv1/hal_mac_lld.c
|
||||
* @brief SAMA low level MAC driver code.
|
||||
*
|
||||
* @addtogroup MAC
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "hal.h"
|
||||
|
||||
#if HAL_USE_MAC || defined(__DOXYGEN__)
|
||||
|
||||
#include "hal_mii.h"
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local definitions. */
|
||||
/*===========================================================================*/
|
||||
#define BUFFER_SIZE ((((SAMA_MAC_BUFFERS_SIZE - 1) | 3) + 1) / 4)
|
||||
|
||||
/* MII divider optimal value.*/
|
||||
#if (SAMA_GMAC0CLK <= 20000000)
|
||||
#define GMAC_CLK GMAC_NCFGR_CLK_MCK_8
|
||||
#elif (SAMA_GMAC0CLK <= 40000000)
|
||||
#define GMAC_CLK GMAC_NCFGR_CLK_MCK_16
|
||||
#elif (SAMA_GMAC0CLK <= 80000000)
|
||||
#define GMAC_CLK GMAC_NCFGR_CLK_MCK_32
|
||||
#elif (SAMA_GMAC0CLK <= 120000000)
|
||||
#define GMAC_CLK GMAC_NCFGR_CLK_MCK_48
|
||||
#elif (SAMA_GMAC0CLK <= 160000000)
|
||||
#define GMAC_CLK GMAC_NCFGR_CLK_MCK_64
|
||||
#elif (SAMA_GMAC0CLK <= 240000000)
|
||||
#define GMAC_CLK GMAC_NCFGR_CLK_MCK_96
|
||||
#else
|
||||
#error "MCK too high, cannot configure MDC clock"
|
||||
#endif
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported variables. */
|
||||
/*===========================================================================*/
|
||||
/**
|
||||
* @brief Ethernet driver 0.
|
||||
*/
|
||||
MACDriver ETHD0;
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local variables and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
static const uint8_t default_mac_address[] = {0x54, 0x54, 0x08, 0x34, 0x1f, 0x3a};
|
||||
|
||||
/* Rx descriptor list */
|
||||
ALIGNED_VAR(8)
|
||||
static sama_eth_rx_descriptor_t __eth_rd[SAMA_MAC_RECEIVE_BUFFERS];
|
||||
|
||||
/* Tx descriptor list */
|
||||
ALIGNED_VAR(8)
|
||||
static sama_eth_tx_descriptor_t __eth_td[SAMA_MAC_TRANSMIT_BUFFERS];
|
||||
|
||||
static uint32_t __eth_rb[SAMA_MAC_RECEIVE_BUFFERS][BUFFER_SIZE];
|
||||
static uint32_t __eth_tb[SAMA_MAC_TRANSMIT_BUFFERS][BUFFER_SIZE];
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local macros. */
|
||||
/*===========================================================================*/
|
||||
/**
|
||||
* @brief Configures ETH pins.
|
||||
* TODO: move into board.c
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void configurePinsETH(void) {
|
||||
palSetGroupMode(PIOB, PAL_PORT_BIT(PIOB_ETH_GTXCK) | PAL_PORT_BIT(PIOB_ETH_GTXEN) |
|
||||
PAL_PORT_BIT(PIOB_ETH_GRXDV) | PAL_PORT_BIT(PIOB_ETH_GRXER) |
|
||||
PAL_PORT_BIT(PIOB_ETH_GRX0) | PAL_PORT_BIT(PIOB_ETH_GRX1) |
|
||||
PAL_PORT_BIT(PIOB_ETH_GTX0) | PAL_PORT_BIT(PIOB_ETH_GTX1) |
|
||||
PAL_PORT_BIT(PIOB_ETH_GMDC) | PAL_PORT_BIT(PIOB_ETH_GMDIO),
|
||||
0U, PAL_SAMA_FUNC_PERIPH_F | PAL_MODE_SECURE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Waits for phy management logic idle.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
#define phyWaitIdle() { \
|
||||
while ((GMAC0->GMAC_NSR & GMAC_NSR_IDLE) == 0) { \
|
||||
; \
|
||||
} \
|
||||
}
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local functions. */
|
||||
/*===========================================================================*/
|
||||
/**
|
||||
* @brief Writes a PHY register.
|
||||
*
|
||||
* @param[in] macp pointer to the @p MACDriver object
|
||||
* @param[in] reg_addr register address
|
||||
* @param[in] value new register value
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void mii_write(MACDriver *macp, uint32_t reg_addr, uint32_t value) {
|
||||
|
||||
phyWaitIdle();
|
||||
|
||||
/* Write maintenance register (Clause 22) */
|
||||
GMAC0->GMAC_MAN = GMAC_MAN_CLTTO | GMAC_MAN_OP(1) | GMAC_MAN_WTN(2) |
|
||||
GMAC_MAN_PHYA(macp->phyaddr) | GMAC_MAN_REGA(reg_addr) |
|
||||
GMAC_MAN_DATA(value);
|
||||
phyWaitIdle();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reads a PHY register.
|
||||
*
|
||||
* @param[in] macp pointer to the @p MACDriver object
|
||||
* @param[in] reg_addr register address
|
||||
*
|
||||
* @return The PHY register content.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
uint32_t mii_read(MACDriver *macp, uint32_t reg_addr) {
|
||||
|
||||
phyWaitIdle();
|
||||
|
||||
/* Read maintenance register */
|
||||
GMAC0->GMAC_MAN = GMAC_MAN_CLTTO | GMAC_MAN_OP(2) | GMAC_MAN_WTN(2) |
|
||||
GMAC_MAN_PHYA(macp->phyaddr) | GMAC_MAN_REGA(reg_addr);
|
||||
phyWaitIdle();
|
||||
|
||||
return (uint32_t) ((GMAC0->GMAC_MAN) & GMAC_MAN_DATA_Msk >> GMAC_MAN_DATA_Pos);
|
||||
}
|
||||
|
||||
#if !defined(BOARD_PHY_ADDRESS)
|
||||
/**
|
||||
* @brief PHY address detection.
|
||||
*
|
||||
* @param[in] macp pointer to the @p MACDriver object
|
||||
*/
|
||||
static void mii_find_phy(MACDriver *macp) {
|
||||
uint32_t i;
|
||||
|
||||
#if SAMA_MAC_PHY_TIMEOUT > 0
|
||||
unsigned n = SAMA_MAC_PHY_TIMEOUT;
|
||||
do {
|
||||
#endif
|
||||
for (i = 1U; i < 31U; i++) {
|
||||
macp->phyaddr = i;
|
||||
if ((mii_read(macp, MII_PHYSID1) == (BOARD_PHY_ID >> 16U)) &&
|
||||
((mii_read(macp, MII_PHYSID2) & 0xFFF0U) == (BOARD_PHY_ID & 0xFFF0U))) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
#if SAMA_MAC_PHY_TIMEOUT > 0
|
||||
n--;
|
||||
} while (n > 0U);
|
||||
#endif
|
||||
/* Wrong or defective board.*/
|
||||
osalSysHalt("MAC failure");
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief MAC address setup.
|
||||
*
|
||||
* @param[in] p pointer to a six bytes buffer containing the MAC
|
||||
* address
|
||||
*/
|
||||
static void mac_lld_set_address(const uint8_t *p) {
|
||||
|
||||
/* MAC address configuration, only a single address comparator is used,
|
||||
hash table not used.*/
|
||||
GMAC0->GMAC_SA[0].GMAC_SAB = (p[3] << 24) | (p[2] << 16) |
|
||||
(p[1] << 8) | p[0];
|
||||
GMAC0->GMAC_SA[0].GMAC_SAT = (p[5] << 8) | p[4];
|
||||
}
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver interrupt handlers. */
|
||||
/*===========================================================================*/
|
||||
|
||||
OSAL_IRQ_HANDLER(SAMA_ETH_HANDLER) {
|
||||
uint32_t isr;
|
||||
uint32_t rsr;
|
||||
uint32_t tsr;
|
||||
|
||||
OSAL_IRQ_PROLOGUE();
|
||||
|
||||
isr = GMAC0->GMAC_ISR;
|
||||
rsr = GMAC0->GMAC_RSR;
|
||||
tsr = GMAC0->GMAC_TSR;
|
||||
|
||||
if (isr & GMAC_ISR_RCOMP) {
|
||||
/* Data Received.*/
|
||||
osalSysLockFromISR();
|
||||
/* Clear Status Register */
|
||||
GMAC0->GMAC_RSR = rsr;
|
||||
osalThreadDequeueAllI(ÐD0.rdqueue, MSG_RESET);
|
||||
#if MAC_USE_EVENTS
|
||||
osalEventBroadcastFlagsI(ÐD0.rdevent, 0);
|
||||
#endif
|
||||
osalSysUnlockFromISR();
|
||||
}
|
||||
|
||||
if (isr & GMAC_ISR_TCOMP) {
|
||||
/* Data Transmitted.*/
|
||||
osalSysLockFromISR();
|
||||
/* Clear Status Register */
|
||||
GMAC0->GMAC_TSR = tsr;
|
||||
osalThreadDequeueAllI(ÐD0.tdqueue, MSG_RESET);
|
||||
osalSysUnlockFromISR();
|
||||
}
|
||||
aicAckInt();
|
||||
OSAL_IRQ_EPILOGUE();
|
||||
}
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Low level MAC initialization.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void mac_lld_init(void) {
|
||||
unsigned i;
|
||||
|
||||
configurePinsETH();
|
||||
macObjectInit(ÐD0);
|
||||
ETHD0.link_up = false;
|
||||
|
||||
/* Descriptor tables are initialized in chained mode, note that the status
|
||||
word is not initialized here but in mac_lld_start().*/
|
||||
for (i = 0; i < SAMA_MAC_RECEIVE_BUFFERS; i++) {
|
||||
__eth_rd[i].rdes0 = ((uint32_t)__eth_rb[i]) & (SAMA_RDES0_RBAP_MASK);
|
||||
/* Status reset */
|
||||
__eth_rd[i].rdes1 = 0;
|
||||
/* For last buffer wrap is set */
|
||||
if (i == (SAMA_MAC_RECEIVE_BUFFERS - 1)){
|
||||
__eth_rd[i].rdes0 |= SAMA_RDES0_WRAP;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < SAMA_MAC_TRANSMIT_BUFFERS; i++) {
|
||||
__eth_td[i].tdes0 = (uint32_t)__eth_tb[i];
|
||||
/* Status reset */
|
||||
__eth_td[i].tdes1 = 0;
|
||||
/* For last buffer wrap is set */
|
||||
if (i == (SAMA_MAC_TRANSMIT_BUFFERS - 1)){
|
||||
__eth_td[i].tdes1 |= SAMA_TDES1_WRAP;
|
||||
}
|
||||
}
|
||||
|
||||
/* Configures MDIO clock */
|
||||
GMAC0->GMAC_NCFGR = (GMAC0->GMAC_NCFGR & ~GMAC_NCFGR_CLK_Msk) | GMAC_CLK;
|
||||
|
||||
/* Enables management port */
|
||||
GMAC0->GMAC_NCR |= GMAC_NCR_MPE;
|
||||
|
||||
/* Selection of the RMII or MII mode based on info exported by board.h.*/
|
||||
#if defined(BOARD_PHY_RMII)
|
||||
GMAC0->GMAC_UR = GMAC_UR_RMII;
|
||||
#else
|
||||
GMAC0->GMAC_UR &= ~GMAC_UR_RMII;
|
||||
#endif
|
||||
|
||||
/* MAC clocks temporary activation.*/
|
||||
pmcEnableETH0();
|
||||
/* PHY address setup.*/
|
||||
#if defined(BOARD_PHY_ADDRESS)
|
||||
ETHD0.phyaddr = BOARD_PHY_ADDRESS;
|
||||
#else
|
||||
mii_find_phy(ÐD0);
|
||||
#endif
|
||||
|
||||
#if defined(BOARD_PHY_RESET)
|
||||
/* PHY board-specific reset procedure.*/
|
||||
BOARD_PHY_RESET();
|
||||
#else
|
||||
/* PHY soft reset procedure.*/
|
||||
mii_write(ÐD0, MII_BMCR, BMCR_RESET);
|
||||
#if defined(BOARD_PHY_RESET_DELAY)
|
||||
osalSysPolledDelayX(BOARD_PHY_RESET_DELAY);
|
||||
#endif
|
||||
while (mii_read(ÐD0, MII_BMCR) & BMCR_RESET)
|
||||
;
|
||||
#endif
|
||||
|
||||
#if SAMA_MAC_ETH0_CHANGE_PHY_STATE
|
||||
/* PHY in power down mode until the driver will be started.*/
|
||||
mii_write(ÐD0, MII_BMCR, mii_read(ÐD0, MII_BMCR) | BMCR_PDOWN);
|
||||
#endif
|
||||
|
||||
/* MAC clocks stopped again. */
|
||||
pmcDisableETH0();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configures and activates the MAC peripheral.
|
||||
*
|
||||
* @param[in] macp pointer to the @p MACDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void mac_lld_start(MACDriver *macp) {
|
||||
unsigned i;
|
||||
|
||||
/* Disable interrupts */
|
||||
GMAC0->GMAC_IDR = 0xFFFFFFFF; /* Queue 0 */
|
||||
GMAC0->GMAC_IDRPQ[0] = 0xFFFFFFFF; /* Queue 1 */
|
||||
GMAC0->GMAC_IDRPQ[1] = 0xFFFFFFFF; /* Queue 2 */
|
||||
|
||||
/* Clear statistic */
|
||||
GMAC0->GMAC_NCR |= GMAC_NCR_CLRSTAT;
|
||||
|
||||
/* Clear rx and tx status bit */
|
||||
GMAC0->GMAC_RSR = 0xF;
|
||||
GMAC0->GMAC_TSR = 0xFF;
|
||||
|
||||
/* Clear interrupt status register */
|
||||
GMAC0->GMAC_ISR; /* Queue 0 */
|
||||
GMAC0->GMAC_ISRPQ[0]; /* Queue 1 */
|
||||
GMAC0->GMAC_ISRPQ[1]; /* Queue 2 */
|
||||
|
||||
/* Free all descriptors.*/
|
||||
for (i = 0; i < SAMA_MAC_RECEIVE_BUFFERS; i++)
|
||||
__eth_rd[i].rdes0 &= ~SAMA_RDES0_OWN;
|
||||
|
||||
/* Current receive descriptor */
|
||||
macp->rxptr = (sama_eth_rx_descriptor_t *)__eth_rd;
|
||||
|
||||
for (i = 0; i < SAMA_MAC_TRANSMIT_BUFFERS; i++)
|
||||
__eth_td[i].tdes1 |= SAMA_TDES1_LAST_BUFF | SAMA_TDES1_USED;
|
||||
|
||||
macp->txptr = (sama_eth_tx_descriptor_t *)__eth_td;
|
||||
|
||||
/* MAC clocks activation and commanded reset procedure.*/
|
||||
pmcEnableETH0();
|
||||
|
||||
/* Enable interrupt */
|
||||
aicSetSourcePriority(ID_GMAC0, SAMA_MAC_ETH0_IRQ_PRIORITY);
|
||||
aicSetSourceHandler(ID_GMAC0, SAMA_ETH_HANDLER);
|
||||
aicEnableInt(ID_GMAC0);
|
||||
|
||||
#if SAMA_MAC_ETH0_CHANGE_PHY_STATE
|
||||
/* PHY in power up mode.*/
|
||||
mii_write(macp, MII_BMCR, mii_read(macp, MII_BMCR) & ~BMCR_PDOWN);
|
||||
#endif
|
||||
|
||||
/* MAC address setup.*/
|
||||
if (macp->config->mac_address == NULL)
|
||||
mac_lld_set_address(default_mac_address);
|
||||
else
|
||||
mac_lld_set_address(macp->config->mac_address);
|
||||
|
||||
/* Transmitter and receiver enabled.
|
||||
Note that the complete setup of the MAC is performed when the link
|
||||
status is detected.*/
|
||||
uint32_t ncfgr = GMAC0->GMAC_NCFGR;
|
||||
|
||||
#if SAMA_MAC_IP_CHECKSUM_OFFLOAD
|
||||
GMAC0->GMAC_NCFGR = GMAC_NCFGR_RXCOEN | GMAC_NCFGR_SPD |
|
||||
GMAC_NCFGR_FD | GMAC_NCFGR_MAXFS |
|
||||
GMAC_NCFGR_RFCS | ncfgr;
|
||||
GMAC0->GMAC_DCFGR |= GMAC_DCFGR_TXCOEN;
|
||||
#else
|
||||
GMAC0->GMAC_NCFGR = GMAC_NCFGR_SPD | GMAC_NCFGR_FD |
|
||||
GMAC_NCFGR_MAXFS | GMAC_NCFGR_RFCS |
|
||||
ncfgr;
|
||||
#endif
|
||||
|
||||
/* DMA configuration:
|
||||
* Descriptor chains pointers.
|
||||
*/
|
||||
GMAC0->GMAC_RBQB = (uint32_t)__eth_rd;
|
||||
/*
|
||||
* The queue pointers must be initialized and point to
|
||||
* USED descriptor for all queues including those not
|
||||
* intended for use.
|
||||
*/
|
||||
GMAC0->GMAC_RBQBAPQ[0] = (uint32_t)__eth_rd;
|
||||
GMAC0->GMAC_RBQBAPQ[1] = (uint32_t)__eth_rd;
|
||||
|
||||
GMAC0->GMAC_TBQB = (uint32_t)__eth_td;
|
||||
/*
|
||||
* The queue pointers must be initialized and point to
|
||||
* USED descriptor for alla queues including those not
|
||||
* intended for use.
|
||||
*/
|
||||
GMAC0->GMAC_TBQBAPQ[0] = (uint32_t)__eth_td;
|
||||
GMAC0->GMAC_TBQBAPQ[1] = (uint32_t)__eth_td;
|
||||
|
||||
/* Enabling required interrupt sources.*/
|
||||
GMAC0->GMAC_IER = GMAC_IER_TCOMP | GMAC_IER_RCOMP;
|
||||
|
||||
/* DMA general settings.*/
|
||||
uint32_t dcfgr = GMAC0->GMAC_DCFGR & 0xFFFF;
|
||||
GMAC0->GMAC_DCFGR = dcfgr | GMAC_DCFGR_DRBS(24);
|
||||
|
||||
/* Enable RX and TX.*/
|
||||
GMAC0->GMAC_NCR |= GMAC_NCR_RXEN | GMAC_NCR_TXEN;
|
||||
|
||||
/* Starts transmission */
|
||||
// GMAC0->GMAC_NCR |= GMAC_NCR_TSTART;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Deactivates the MAC peripheral.
|
||||
*
|
||||
* @param[in] macp pointer to the @p MACDriver object
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void mac_lld_stop(MACDriver *macp) {
|
||||
|
||||
if (macp->state != MAC_STOP) {
|
||||
#if SAMA_MAC_ETH0_CHANGE_PHY_STATE
|
||||
/* PHY in power down mode until the driver will be restarted.*/
|
||||
mii_write(macp, MII_BMCR, mii_read(macp, MII_BMCR) | BMCR_PDOWN);
|
||||
#endif
|
||||
|
||||
/* Reset Network Control Register */
|
||||
GMAC0->GMAC_NCR &= ~(GMAC_NCR_RXEN | GMAC_NCR_TXEN);
|
||||
|
||||
/* Disable interrupts */
|
||||
GMAC0->GMAC_IDR = 0xFFFFFFFF;
|
||||
|
||||
/* Clear statistic */
|
||||
GMAC0->GMAC_NCR |= GMAC_NCR_CLRSTAT;
|
||||
|
||||
/* Clear rx and tx status bit */
|
||||
GMAC0->GMAC_RSR = 0xF;
|
||||
GMAC0->GMAC_TSR = 0xFF;
|
||||
|
||||
/* Clear interrupt status register */
|
||||
GMAC0->GMAC_ISR;
|
||||
|
||||
/* MAC clocks stopped.*/
|
||||
pmcDisableETH0();
|
||||
|
||||
/* ISR vector disabled.*/
|
||||
aicDisableInt(ID_GMAC0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns a transmission descriptor.
|
||||
* @details One of the available transmission descriptors is locked and
|
||||
* returned.
|
||||
*
|
||||
* @param[in] macp pointer to the @p MACDriver object
|
||||
* @param[out] tdp pointer to a @p MACTransmitDescriptor structure
|
||||
* @return The operation status.
|
||||
* @retval MSG_OK the descriptor has been obtained.
|
||||
* @retval MSG_TIMEOUT descriptor not available.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
msg_t mac_lld_get_transmit_descriptor(MACDriver *macp,
|
||||
MACTransmitDescriptor *tdp) {
|
||||
sama_eth_tx_descriptor_t *tdes;
|
||||
|
||||
if (!macp->link_up)
|
||||
return MSG_TIMEOUT;
|
||||
|
||||
osalSysLock();
|
||||
|
||||
/* Get Current TX descriptor.*/
|
||||
tdes = macp->txptr;
|
||||
|
||||
/* Ensure that descriptor isn't owned by the Ethernet DMA or locked by
|
||||
another thread.*/
|
||||
if ((tdes->tdes1 & SAMA_TDES1_LOCKED) | (!(tdes->tdes1 & SAMA_TDES1_USED))) {
|
||||
osalSysUnlock();
|
||||
return MSG_TIMEOUT;
|
||||
}
|
||||
|
||||
/* Marks the current descriptor as locked using a reserved bit.*/
|
||||
tdes->tdes1 |= SAMA_TDES1_LOCKED;
|
||||
|
||||
if (!(tdes->tdes1 & SAMA_TDES1_WRAP)) {
|
||||
macp->txptr += 1;
|
||||
}
|
||||
else {
|
||||
macp->txptr = (sama_eth_tx_descriptor_t *)__eth_td;
|
||||
}
|
||||
|
||||
osalSysUnlock();
|
||||
|
||||
/* Set the buffer size and configuration.*/
|
||||
tdp->offset = 0;
|
||||
tdp->size = SAMA_MAC_BUFFERS_SIZE;
|
||||
tdp->physdesc = tdes;
|
||||
|
||||
return MSG_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Releases a transmit descriptor and starts the transmission of the
|
||||
* enqueued data as a single frame.
|
||||
*
|
||||
* @param[in] tdp the pointer to the @p MACTransmitDescriptor structure
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void mac_lld_release_transmit_descriptor(MACTransmitDescriptor *tdp) {
|
||||
|
||||
osalDbgAssert(tdp->physdesc->tdes1 & SAMA_TDES1_USED,
|
||||
"attempt to release descriptor already owned by DMA");
|
||||
|
||||
osalSysLock();
|
||||
|
||||
/* Unlocks the descriptor and returns it to the DMA engine.*/
|
||||
tdp->physdesc->tdes1 = SAMA_TDES1_LAST_BUFF | (SAMA_TDES1_LENGTH_BUFF & BUFFER_SIZE);
|
||||
|
||||
/* Wait for the write to tdes1 to go through before resuming the DMA.*/
|
||||
__DSB();
|
||||
|
||||
if (!(GMAC0->GMAC_TSR & GMAC_TSR_TXGO)) {
|
||||
GMAC0->GMAC_NCR |= GMAC_NCR_TSTART;
|
||||
}
|
||||
|
||||
osalSysUnlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns a receive descriptor.
|
||||
*
|
||||
* @param[in] macp pointer to the @p MACDriver object
|
||||
* @param[out] rdp pointer to a @p MACReceiveDescriptor structure
|
||||
* @return The operation status.
|
||||
* @retval MSG_OK the descriptor has been obtained.
|
||||
* @retval MSG_TIMEOUT descriptor not available.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
msg_t mac_lld_get_receive_descriptor(MACDriver *macp,
|
||||
MACReceiveDescriptor *rdp) {
|
||||
sama_eth_rx_descriptor_t *rdes;
|
||||
|
||||
osalSysLock();
|
||||
|
||||
/* Get Current RX descriptor.*/
|
||||
rdes = macp->rxptr;
|
||||
|
||||
/* Iterates through received frames until a valid one is found, invalid
|
||||
frames are discarded.*/
|
||||
while (rdes->rdes0 & SAMA_RDES0_OWN) {
|
||||
if (rdes->rdes1 & (SAMA_RDES1_EOF | SAMA_RDES1_SOF)
|
||||
#if SAMA_MAC_IP_CHECKSUM_OFFLOAD
|
||||
&& (rdes->rdes1 & (SAMA_RDES1_CHECKSUM_IP_TCP | SAMA_RDES1_CHECKSUM_IP_UDP))
|
||||
#endif
|
||||
) {
|
||||
/* Found a valid one.*/
|
||||
rdp->offset = 0;
|
||||
/* Only with RFCS set */
|
||||
rdp->size = (rdes->rdes1 & SAMA_RDES1_LOF);
|
||||
rdp->physdesc = rdes;
|
||||
if (!(rdes->rdes0 & SAMA_RDES0_WRAP)) {
|
||||
macp->rxptr += 1;
|
||||
}
|
||||
else {
|
||||
macp->rxptr = (sama_eth_rx_descriptor_t *)__eth_rd;
|
||||
}
|
||||
osalSysUnlock();
|
||||
return MSG_OK;
|
||||
}
|
||||
/* Invalid frame found, purging.*/
|
||||
rdes->rdes0 &= ~SAMA_RDES0_OWN;
|
||||
if (!(rdes->rdes0 & SAMA_RDES0_WRAP)) {
|
||||
rdes += 1;
|
||||
}
|
||||
else {
|
||||
rdes = (sama_eth_rx_descriptor_t *)__eth_rd;
|
||||
}
|
||||
}
|
||||
|
||||
/* Next descriptor to check.*/
|
||||
macp->rxptr = rdes;
|
||||
|
||||
osalSysUnlock();
|
||||
return MSG_TIMEOUT;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Releases a receive descriptor.
|
||||
* @details The descriptor and its buffer are made available for more incoming
|
||||
* frames.
|
||||
*
|
||||
* @param[in] rdp the pointer to the @p MACReceiveDescriptor structure
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void mac_lld_release_receive_descriptor(MACReceiveDescriptor *rdp) {
|
||||
|
||||
osalDbgAssert(rdp->physdesc->rdes0 & SAMA_RDES0_OWN,
|
||||
"attempt to release descriptor not owned by DMA");
|
||||
|
||||
osalSysLock();
|
||||
|
||||
/* Give buffer back to the Ethernet DMA.*/
|
||||
rdp->physdesc->rdes0 &= ~SAMA_RDES0_OWN;
|
||||
|
||||
/* Wait for the write to rdes0 to go through before resuming the DMA.*/
|
||||
__DSB();
|
||||
|
||||
osalSysUnlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Updates and returns the link status.
|
||||
*
|
||||
* @param[in] macp pointer to the @p MACDriver object
|
||||
* @return The link status.
|
||||
* @retval true if the link is active.
|
||||
* @retval false if the link is down.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
bool mac_lld_poll_link_status(MACDriver *macp) {
|
||||
uint32_t maccr, bmsr, bmcr;
|
||||
|
||||
maccr = GMAC0->GMAC_NCFGR;
|
||||
|
||||
/* PHY CR and SR registers read.*/
|
||||
(void)mii_read(macp, MII_BMSR);
|
||||
bmsr = mii_read(macp, MII_BMSR);
|
||||
bmcr = mii_read(macp, MII_BMCR);
|
||||
|
||||
/* Check on auto-negotiation mode.*/
|
||||
if (bmcr & BMCR_ANENABLE) {
|
||||
uint32_t lpa;
|
||||
|
||||
/* Auto-negotiation must be finished without faults and link established.*/
|
||||
if ((bmsr & (BMSR_LSTATUS | BMSR_RFAULT | BMSR_ANEGCOMPLETE)) !=
|
||||
(BMSR_LSTATUS | BMSR_ANEGCOMPLETE))
|
||||
return macp->link_up = false;
|
||||
|
||||
/* Auto-negotiation enabled, checks the LPA register.*/
|
||||
lpa = mii_read(macp, MII_LPA);
|
||||
|
||||
/* Check on link speed.*/
|
||||
if (lpa & (LPA_100HALF | LPA_100FULL | LPA_100BASE4))
|
||||
maccr |= GMAC_NCFGR_SPD;
|
||||
else
|
||||
maccr &= ~GMAC_NCFGR_SPD;
|
||||
|
||||
/* Check on link mode.*/
|
||||
if (lpa & (LPA_10FULL | LPA_100FULL))
|
||||
maccr |= GMAC_NCFGR_FD;
|
||||
else
|
||||
maccr &= ~GMAC_NCFGR_FD;
|
||||
}
|
||||
else {
|
||||
/* Link must be established.*/
|
||||
if (!(bmsr & BMSR_LSTATUS))
|
||||
return macp->link_up = false;
|
||||
|
||||
/* Check on link speed.*/
|
||||
if (bmcr & BMCR_SPEED100)
|
||||
maccr |= GMAC_NCFGR_SPD;
|
||||
else
|
||||
maccr &= ~GMAC_NCFGR_SPD;
|
||||
|
||||
/* Check on link mode.*/
|
||||
if (bmcr & BMCR_FULLDPLX)
|
||||
maccr |= GMAC_NCFGR_FD;
|
||||
else
|
||||
maccr &= ~GMAC_NCFGR_FD;
|
||||
}
|
||||
|
||||
/* Changes the mode in the MAC.*/
|
||||
GMAC0->GMAC_NCFGR = maccr;
|
||||
|
||||
/* Returns the link status.*/
|
||||
return macp->link_up = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Writes to a transmit descriptor's stream.
|
||||
*
|
||||
* @param[in] tdp pointer to a @p MACTransmitDescriptor structure
|
||||
* @param[in] buf pointer to the buffer containing the data to be
|
||||
* written
|
||||
* @param[in] size number of bytes to be written
|
||||
* @return The number of bytes written into the descriptor's
|
||||
* stream, this value can be less than the amount
|
||||
* specified in the parameter @p size if the maximum
|
||||
* frame size is reached.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
size_t mac_lld_write_transmit_descriptor(MACTransmitDescriptor *tdp,
|
||||
uint8_t *buf,
|
||||
size_t size) {
|
||||
|
||||
osalDbgAssert((tdp->physdesc->tdes1 & SAMA_TDES1_USED),
|
||||
"attempt to write descriptor not owned");
|
||||
|
||||
if (size > tdp->size - tdp->offset)
|
||||
size = tdp->size - tdp->offset;
|
||||
|
||||
if (size > 0) {
|
||||
memcpy((uint8_t *)(tdp->physdesc->tdes0) + tdp->offset, buf, size);
|
||||
tdp->offset += size;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reads from a receive descriptor's stream.
|
||||
*
|
||||
* @param[in] rdp pointer to a @p MACReceiveDescriptor structure
|
||||
* @param[in] buf pointer to the buffer that will receive the read data
|
||||
* @param[in] size number of bytes to be read
|
||||
* @return The number of bytes read from the descriptor's
|
||||
* stream, this value can be less than the amount
|
||||
* specified in the parameter @p size if there are
|
||||
* no more bytes to read.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
size_t mac_lld_read_receive_descriptor(MACReceiveDescriptor *rdp,
|
||||
uint8_t *buf,
|
||||
size_t size) {
|
||||
|
||||
osalDbgAssert((rdp->physdesc->rdes0 & SAMA_RDES0_OWN),
|
||||
"attempt to read descriptor not owned");
|
||||
|
||||
if (size > rdp->size - rdp->offset)
|
||||
size = rdp->size - rdp->offset;
|
||||
|
||||
if (size > 0) {
|
||||
memcpy(buf, (uint8_t *)(rdp->physdesc->rdes0 & SAMA_RDES0_RBAP_MASK) + rdp->offset, size);
|
||||
rdp->offset += size;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
#if MAC_USE_ZERO_COPY || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @brief Returns a pointer to the next transmit buffer in the descriptor
|
||||
* chain.
|
||||
* @note The API guarantees that enough buffers can be requested to fill
|
||||
* a whole frame.
|
||||
*
|
||||
* @param[in] tdp pointer to a @p MACTransmitDescriptor structure
|
||||
* @param[in] size size of the requested buffer. Specify the frame size
|
||||
* on the first call then scale the value down subtracting
|
||||
* the amount of data already copied into the previous
|
||||
* buffers.
|
||||
* @param[out] sizep pointer to variable receiving the buffer size, it is
|
||||
* zero when the last buffer has already been returned.
|
||||
* Note that a returned size lower than the amount
|
||||
* requested means that more buffers must be requested
|
||||
* in order to fill the frame data entirely.
|
||||
* @return Pointer to the returned buffer.
|
||||
* @retval NULL if the buffer chain has been entirely scanned.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
uint8_t *mac_lld_get_next_transmit_buffer(MACTransmitDescriptor *tdp,
|
||||
size_t size,
|
||||
size_t *sizep) {
|
||||
|
||||
if (tdp->offset == 0) {
|
||||
*sizep = tdp->size;
|
||||
tdp->offset = size;
|
||||
return (uint8_t *)tdp->physdesc->tdes0;
|
||||
}
|
||||
*sizep = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns a pointer to the next receive buffer in the descriptor
|
||||
* chain.
|
||||
* @note The API guarantees that the descriptor chain contains a whole
|
||||
* frame.
|
||||
*
|
||||
* @param[in] rdp pointer to a @p MACReceiveDescriptor structure
|
||||
* @param[out] sizep pointer to variable receiving the buffer size, it is
|
||||
* zero when the last buffer has already been returned.
|
||||
* @return Pointer to the returned buffer.
|
||||
* @retval NULL if the buffer chain has been entirely scanned.
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
const uint8_t *mac_lld_get_next_receive_buffer(MACReceiveDescriptor *rdp,
|
||||
size_t *sizep) {
|
||||
|
||||
if (rdp->size > 0) {
|
||||
*sizep = rdp->size;
|
||||
rdp->offset = rdp->size;
|
||||
rdp->size = 0;
|
||||
return (uint8_t *)rdp->physdesc->rdes0 & SAMA_RDES0_RBAP_MASK;
|
||||
}
|
||||
*sizep = 0;
|
||||
return NULL;
|
||||
}
|
||||
#endif /* MAC_USE_ZERO_COPY */
|
||||
|
||||
#endif /* HAL_USE_MAC */
|
||||
|
||||
/** @} */
|
|
@ -0,0 +1,329 @@
|
|||
/*
|
||||
ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file MACv1/hal_mac_lld.h
|
||||
* @brief SAMA low level MAC driver header.
|
||||
*
|
||||
* @addtogroup MAC
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef HAL_MAC_LLD_H
|
||||
#define HAL_MAC_LLD_H
|
||||
|
||||
#if HAL_USE_MAC || defined(__DOXYGEN__)
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver constants. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief This implementation supports the zero-copy mode API.
|
||||
*/
|
||||
#define MAC_SUPPORTS_ZERO_COPY FALSE
|
||||
|
||||
/**
|
||||
* @name RDES0 constants
|
||||
* @{
|
||||
*/
|
||||
#define SAMA_RDES0_RBAP_MASK 0xFFFFFFFC
|
||||
#define SAMA_RDES0_WRAP 0x00000002
|
||||
#define SAMA_RDES0_OWN 0x00000001
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name RDES1 constants
|
||||
* @{
|
||||
*/
|
||||
#define SAMA_RDES1_BROADCAST 0x80000000
|
||||
#define SAMA_RDES1_MULTICAST_HASH 0x40000000
|
||||
#define SAMA_RDES1_UNICAST_HASH 0x20000000
|
||||
#define SAMA_RDES1_ADDR_REG_MATCH 0x08000000
|
||||
#define SAMA_RDES1_ADDR_REG 0x06000000
|
||||
#define SAMA_RDES1_ID_REG_MATCH 0x01000000
|
||||
#define SAMA_RDES1_SNAP_ENCODED 0x01000000
|
||||
#define SAMA_RDES1_ID_REG 0x00C00000
|
||||
#define SAMA_RDES1_CHECKSUM_IP_TCP 0x00800000
|
||||
#define SAMA_RDES1_CHECKSUM_IP_UDP 0x00C00000
|
||||
#define SAMA_RDES1_CHECKSUM_IP 0x00400000
|
||||
#define SAMA_RDES1_VLAN_TAG_DET 0x00200000
|
||||
#define SAMA_RDES1_PRIOR_TAG_DET 0x00100000
|
||||
#define SAMA_RDES1_VLAN_PRIOR 0x000E0000
|
||||
#define SAMA_RDES1_CFI 0x00010000
|
||||
#define SAMA_RDES1_EOF 0x00008000
|
||||
#define SAMA_RDES1_SOF 0x00004000
|
||||
#define SAMA_RDES1_ADD_BIT_LOF 0x00002000
|
||||
#define SAMA_RDES1_BAD_FCS 0x00002000
|
||||
#define SAMA_RDES1_LOF 0x00001FFF
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name TDES0 constants
|
||||
* @{
|
||||
*/
|
||||
#define SAMA_TDES0_BYTE_ADDR 0xFFFFFFFF
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name TDES1 constants
|
||||
* @{
|
||||
*/
|
||||
#define SAMA_TDES1_USED 0x80000000
|
||||
#define SAMA_TDES1_WRAP 0x40000000
|
||||
#define SAMA_TDES1_RLE_TX_ERR 0x20000000
|
||||
#define SAMA_TDES1_LOCKED 0x10000000 /* NOTE: Pseudo flag. */
|
||||
#define SAMA_TDES1_AHB_TX_ERR 0x08000000
|
||||
#define SAMA_TDES1_LC_TX_ERR 0x04000000
|
||||
#define SAMA_TDES1_CHECKSUM_ERR 0x00700000
|
||||
#define SAMA_TDES1_CRC 0x00010000
|
||||
#define SAMA_TDES1_LAST_BUFF 0x00008000
|
||||
#define SAMA_TDES1_LENGTH_BUFF 0x00003FFF
|
||||
/** @} */
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver pre-compile time settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @name Configuration options
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @brief Number of available transmit buffers.
|
||||
*/
|
||||
#if !defined(SAMA_MAC_TRANSMIT_BUFFERS) || defined(__DOXYGEN__)
|
||||
#define SAMA_MAC_TRANSMIT_BUFFERS 2
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Number of available receive buffers.
|
||||
*/
|
||||
#if !defined(SAMA_MAC_RECEIVE_BUFFERS) || defined(__DOXYGEN__)
|
||||
#define SAMA_MAC_RECEIVE_BUFFERS 4
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Maximum supported frame size.
|
||||
*/
|
||||
#if !defined(SAMA_MAC_BUFFERS_SIZE) || defined(__DOXYGEN__)
|
||||
#define SAMA_MAC_BUFFERS_SIZE 1536
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief PHY detection timeout.
|
||||
* @details Timeout for PHY address detection, the scan for a PHY is performed
|
||||
* the specified number of times before invoking the failure handler.
|
||||
* This setting applies only if the PHY address is not explicitly
|
||||
* set in the board header file using @p BOARD_PHY_ADDRESS. A zero
|
||||
* value disables the timeout and a single search is performed.
|
||||
*/
|
||||
#if !defined(SAMA_MAC_PHY_TIMEOUT) || defined(__DOXYGEN__)
|
||||
#define SAMA_MAC_PHY_TIMEOUT 100
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Change the PHY power state inside the driver.
|
||||
*/
|
||||
#if !defined(SAMA_MAC_ETH0_CHANGE_PHY_STATE) || defined(__DOXYGEN__)
|
||||
#define SAMA_MAC_ETH0_CHANGE_PHY_STATE TRUE
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief ETHD0 interrupt priority level setting.
|
||||
*/
|
||||
#if !defined(SAMA_MAC_ETH0_IRQ_PRIORITY) || defined(__DOXYGEN__)
|
||||
#define SAMA_MAC_ETH0_IRQ_PRIORITY 7
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief IP checksum offload.
|
||||
* @details The following modes are available:
|
||||
* - 0 Function disabled.
|
||||
* - 1 Only IP header checksum calculation and insertion are enabled.
|
||||
*/
|
||||
#if !defined(SAMA_MAC_IP_CHECKSUM_OFFLOAD) || defined(__DOXYGEN__)
|
||||
#define SAMA_MAC_IP_CHECKSUM_OFFLOAD 1
|
||||
#endif
|
||||
/** @} */
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Derived constants and error checks. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver data structures and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Type of an SAMA Ethernet receive descriptor.
|
||||
*/
|
||||
typedef struct {
|
||||
volatile uint32_t rdes0;
|
||||
volatile uint32_t rdes1;
|
||||
} sama_eth_rx_descriptor_t;
|
||||
|
||||
/**
|
||||
* @brief Type of an SAMA Ethernet transmit descriptor.
|
||||
*/
|
||||
typedef struct {
|
||||
volatile uint32_t tdes0;
|
||||
volatile uint32_t tdes1;
|
||||
} sama_eth_tx_descriptor_t;
|
||||
|
||||
/**
|
||||
* @brief Driver configuration structure.
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* @brief MAC address.
|
||||
*/
|
||||
uint8_t *mac_address;
|
||||
/* End of the mandatory fields.*/
|
||||
} MACConfig;
|
||||
|
||||
/**
|
||||
* @brief Structure representing a MAC driver.
|
||||
*/
|
||||
struct MACDriver {
|
||||
/**
|
||||
* @brief Driver state.
|
||||
*/
|
||||
macstate_t state;
|
||||
/**
|
||||
* @brief Current configuration data.
|
||||
*/
|
||||
const MACConfig *config;
|
||||
/**
|
||||
* @brief Transmit semaphore.
|
||||
*/
|
||||
threads_queue_t tdqueue;
|
||||
/**
|
||||
* @brief Receive semaphore.
|
||||
*/
|
||||
threads_queue_t rdqueue;
|
||||
#if MAC_USE_EVENTS || defined(__DOXYGEN__)
|
||||
/**
|
||||
* @brief Receive event.
|
||||
*/
|
||||
event_source_t rdevent;
|
||||
#endif
|
||||
/* End of the mandatory fields.*/
|
||||
/**
|
||||
* @brief Link status flag.
|
||||
*/
|
||||
bool link_up;
|
||||
/**
|
||||
* @brief PHY address (pre shifted).
|
||||
*/
|
||||
uint32_t phyaddr;
|
||||
/**
|
||||
* @brief Receive next frame pointer.
|
||||
*/
|
||||
sama_eth_rx_descriptor_t *rxptr;
|
||||
/**
|
||||
* @brief Transmit next frame pointer.
|
||||
*/
|
||||
sama_eth_tx_descriptor_t *txptr;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Structure representing a transmit descriptor.
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* @brief Current write offset.
|
||||
*/
|
||||
size_t offset;
|
||||
/**
|
||||
* @brief Available space size.
|
||||
*/
|
||||
size_t size;
|
||||
/* End of the mandatory fields.*/
|
||||
/**
|
||||
* @brief Pointer to the physical descriptor.
|
||||
*/
|
||||
sama_eth_tx_descriptor_t *physdesc;
|
||||
} MACTransmitDescriptor;
|
||||
|
||||
/**
|
||||
* @brief Structure representing a receive descriptor.
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* @brief Current read offset.
|
||||
*/
|
||||
size_t offset;
|
||||
/**
|
||||
* @brief Available data size.
|
||||
*/
|
||||
size_t size;
|
||||
/* End of the mandatory fields.*/
|
||||
/**
|
||||
* @brief Pointer to the physical descriptor.
|
||||
*/
|
||||
sama_eth_rx_descriptor_t *physdesc;
|
||||
} MACReceiveDescriptor;
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver macros. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* External declarations. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#if !defined(__DOXYGEN__)
|
||||
extern MACDriver ETHD0;
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void mii_write(MACDriver *macp, uint32_t reg, uint32_t value);
|
||||
uint32_t mii_read(MACDriver *macp, uint32_t reg);
|
||||
void mac_lld_init(void);
|
||||
void mac_lld_start(MACDriver *macp);
|
||||
void mac_lld_stop(MACDriver *macp);
|
||||
msg_t mac_lld_get_transmit_descriptor(MACDriver *macp,
|
||||
MACTransmitDescriptor *tdp);
|
||||
void mac_lld_release_transmit_descriptor(MACTransmitDescriptor *tdp);
|
||||
msg_t mac_lld_get_receive_descriptor(MACDriver *macp,
|
||||
MACReceiveDescriptor *rdp);
|
||||
void mac_lld_release_receive_descriptor(MACReceiveDescriptor *rdp);
|
||||
bool mac_lld_poll_link_status(MACDriver *macp);
|
||||
size_t mac_lld_write_transmit_descriptor(MACTransmitDescriptor *tdp,
|
||||
uint8_t *buf,
|
||||
size_t size);
|
||||
size_t mac_lld_read_receive_descriptor(MACReceiveDescriptor *rdp,
|
||||
uint8_t *buf,
|
||||
size_t size);
|
||||
#if MAC_USE_ZERO_COPY
|
||||
uint8_t *mac_lld_get_next_transmit_buffer(MACTransmitDescriptor *tdp,
|
||||
size_t size,
|
||||
size_t *sizep);
|
||||
const uint8_t *mac_lld_get_next_receive_buffer(MACReceiveDescriptor *rdp,
|
||||
size_t *sizep);
|
||||
#endif /* MAC_USE_ZERO_COPY */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* HAL_USE_MAC */
|
||||
|
||||
#endif /* HAL_MAC_LLD_H */
|
||||
|
||||
/** @} */
|
Loading…
Reference in New Issue