/*********************************************************************************************************************** * DISCLAIMER * This software is supplied by Renesas Electronics Corporation and is only intended for use with Renesas products. No * other uses are authorized. This software is owned by Renesas Electronics Corporation and is protected under all * applicable laws, including copyright laws. * THIS SOFTWARE IS PROVIDED "AS IS" AND RENESAS MAKES NO WARRANTIES REGARDING * THIS SOFTWARE, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. ALL SUCH WARRANTIES ARE EXPRESSLY DISCLAIMED. TO THE MAXIMUM * EXTENT PERMITTED NOT PROHIBITED BY LAW, NEITHER RENESAS ELECTRONICS CORPORATION NOR ANY OF ITS AFFILIATED COMPANIES * SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES FOR ANY REASON RELATED TO THIS * SOFTWARE, EVEN IF RENESAS OR ITS AFFILIATES HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. * Renesas reserves the right, without notice, to make changes to this software and to discontinue the availability of * this software. By using this software, you agree to the additional terms and conditions found by accessing the * following link: * http://www.renesas.com/disclaimer * * Copyright (C) 2018-2020 Renesas Electronics Corporation. All rights reserved. ***********************************************************************************************************************/ /* Copyright (c) 2018-2020 Renesas Electronics Corporation. * SPDX-License-Identifier: Apache-2.0 * * 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 Name : r_ether_rza2.c * Version : 1.0 * Description : Ethernet module device driver ***********************************************************************************************************************/ /*********************************************************************************************************************** Includes <System Includes> , "Project Includes" ***********************************************************************************************************************/ #include <string.h> #include "iodefine.h" #include "iobitmask.h" #include "cmsis.h" /* Access to peripherals and board defines. */ #include "r_ether_rza2_if.h" #include "src/r_ether_rza2_private.h" /*********************************************************************************************************************** Macro definitions ***********************************************************************************************************************/ #define ETHER_CFG_USE_VIRTUAL_ADDRESS 0 /* Since the virtual address is not used in the Mbed, the process is simplified. */ /*********************************************************************************************************************** Typedef definitions ***********************************************************************************************************************/ /*********************************************************************************************************************** Exported global variables (to be accessed by other files) ***********************************************************************************************************************/ /*********************************************************************************************************************** Private global variables and functions ***********************************************************************************************************************/ /* * Private global function prototypes */ static void ether_reset_mac (uint32_t channel); static void ether_init_descriptors (uint32_t channel); static void ether_config_ethernet (uint32_t channel, const uint8_t mode); static void ether_pause_resolution (uint16_t local_ability, uint16_t partner_ability, uint16_t *ptx_pause, uint16_t *prx_pause); static void ether_configure_mac (uint32_t channel, const uint8_t mac_addr[], const uint8_t mode); static ether_return_t ether_do_link (uint32_t channel, const uint8_t mode); static ether_return_t ether_set_callback (ether_param_t const control); static ether_return_t ether_set_promiscuous_mode (ether_param_t const control); static ether_return_t ether_set_int_handler (ether_param_t const control); static ether_return_t ether_power_on (ether_param_t const control); static ether_return_t ether_power_off (ether_param_t const control); static ether_return_t power_on (uint32_t channel); static void power_off (uint32_t channel); static ether_return_t ether_set_multicastframe_filter (ether_param_t const control); static ether_return_t ether_set_broadcastframe_filter (ether_param_t const control); #if (ETHER_CH0_EN == 1) static void ether_eint0 (void); #endif #if (ETHER_CH1_EN == 1) static void ether_eint1 (void); #endif static void ether_int_common (uint32_t channel); static ether_return_t power_on_control (uint32_t channel); static void power_off_control (uint32_t channel); static uint8_t check_mpde_bit (void); static uint32_t get_control_tbl_index (uint32_t channel); /* * Private global variables */ /* Pointer to the receive descriptors */ static descriptor_t * papp_rx_desc[ETHER_CHANNEL_MAX]; /* Pointer to the transmit descriptors */ static descriptor_t * papp_tx_desc[ETHER_CHANNEL_MAX]; /* Pointer to the callback function */ static ether_cb_t cb_func; /* * The flag which control the pause frame. * * The value of flag and the situation which is indicatived of by the value. * ETHER_FLAG_OFF (0): Don't use the pause frame (default). * ETHER_FLAG_ON (1): Use the pause frame. */ static uint8_t pause_frame_enable[ETHER_CHANNEL_MAX]; /* * The flag indicatives of the state that the interrupt of Link Up/Down occur. * * Value and state of flag * ETHER_FLAG_OFF (0): It is not possible to communicate. * ETHER_FLAG_ON (1): It is possible to communicate. */ static uint8_t transfer_enable_flag[ETHER_CHANNEL_MAX]; /* * The flag indicatives of the state that the interrupt of magic packet detection occur. * * Value and state of flag * ETHER_FLAG_OFF (0): The interrupt of the magic packet detection has not been generated. * ETHER_FLAG_ON (1): The interrupt of the magic packet detection was generated. * * If the R_ETHER_LinkProcess function is called, and the interrupt processing of the magic packet detection is done, * this flag becomes ETHER_FLAG_OFF(0). */ static uint8_t mpd_flag[ETHER_CHANNEL_MAX]; static uint8_t mac_addr_buf[ETHER_CHANNEL_MAX][6]; /* * The flag indicatives of the state that the interrupt of Link Up/Down occur. * * Value and state of flag * ETHER_FLAG_OFF (0) : The Link up/down interrupt has not been generated. * ETHER_FLAG_ON_LINK_OFF (2) : The Link down interrupt was generated. * ETHER_FLAG_ON_LINK_ON (3) : The Link up interrupt was generated. * * If the R_ETHER_LinkProcess function is called, and the interrupt processing of Link Up/Down is done, * this flag becomes ETHER_FLAG_OFF(0). */ static uint8_t lchng_flag[ETHER_CHANNEL_MAX]; /* * The flag indicatives of the state that enable/disable multicast frame filtering. * * Value and state of flag * ETHER_MC_FILTER_OFF (0) : Disable multicast frame filtering. * ETHER_MC_FILTER_ON (1) : Enable multicast frame filtering. * * The frame multicast filtering is software filter. If you want to use Hardware filter, * please use it EPTPC in RX64M/RX71M. */ static uint8_t mc_filter_flag[ETHER_CHANNEL_MAX]; /* * The value indicatives of receive count for continuous broadcast frame. */ static uint32_t bc_filter_count[ETHER_CHANNEL_MAX]; /* * PAUSE Resolution as documented in IEEE 802.3-2008_section2 Annex * 28B, Table 28B-3. The following table codify logic that * determines how the PAUSE is configured for local transmitter * and receiver and partner transmitter and receiver. */ static const pauseresolution_t pause_resolution[PAUSE_TABLE_ENTRIES] = { { PAUSE_MASKC, PAUSE_VAL0, XMIT_PAUSE_OFF, RECV_PAUSE_OFF }, { PAUSE_MASKE, PAUSE_VAL4, XMIT_PAUSE_OFF, RECV_PAUSE_OFF }, { PAUSE_MASKF, PAUSE_VAL6, XMIT_PAUSE_OFF, RECV_PAUSE_OFF }, { PAUSE_MASKF, PAUSE_VAL7, XMIT_PAUSE_ON, RECV_PAUSE_OFF }, { PAUSE_MASKE, PAUSE_VAL8, XMIT_PAUSE_OFF, RECV_PAUSE_OFF }, { PAUSE_MASKA, PAUSE_VALA, XMIT_PAUSE_ON, RECV_PAUSE_ON }, { PAUSE_MASKF, PAUSE_VALC, XMIT_PAUSE_OFF, RECV_PAUSE_OFF }, { PAUSE_MASKF, PAUSE_VALD, XMIT_PAUSE_OFF, RECV_PAUSE_ON } }; /* * Receive, transmit descriptors and their buffer. They are * defined with section pragma directives to easily locate them * on the memory map. */ static descriptor_t rx_descriptors[ETHER_CHANNEL_MAX][ETHER_CFG_EMAC_RX_DESCRIPTORS] __attribute((section("NC_BSS"),aligned(32))); static descriptor_t tx_descriptors[ETHER_CHANNEL_MAX][ETHER_CFG_EMAC_TX_DESCRIPTORS] __attribute((section("NC_BSS"),aligned(32))); /* * As for Ethernet buffer, the size of total buffer which are use for transmission and the reception is secured. * The total buffer's size which the value is integrated from EMAC_NUM_BUFFERS (buffer number) and * ETHER_CFG_BUFSIZE (the size of one buffer). * The ETHER_CFG_BUFSIZE and EMAC_NUM_BUFFERS are defined by macro in the file "r_ether_private.h". * It is sequentially used from the head of the buffer as a receive buffer or a transmission buffer. */ static etherbuffer_t ether_buffers[ETHER_CHANNEL_MAX] __attribute((section("NC_BSS"),aligned(32))); static uint8_t promiscuous_mode[ETHER_CHANNEL_MAX]; static uint8_t etherc_edmac_power_cont[ETHER_CHANNEL_MAX]; const ether_control_t g_eth_control_ch[ETHER_CHANNEL_MAX] = { #if (ETHER_CH0_EN == 1) /* Ether = ch0, Phy access = ch0 */ { ÐERC0, &EDMAC0, (volatile uint32_t*)ÐERC0.PIR.LONG, ETHER_CFG_CH0_PHY_ADDRESS, PORT_CONNECT_ET0 }, #endif #if (ETHER_CH1_EN == 1) /* Ether = ch1, Phy access = ch1 */ { ÐERC1, &EDMAC1, (volatile uint32_t*)ÐERC1.PIR.LONG, ETHER_CFG_CH1_PHY_ADDRESS, PORT_CONNECT_ET1 }, #endif }; #if (ETHER_CFG_USE_LINKSTA == 0) /* Previous link status */ static int16_t g_pre_link_stat[ETHER_CHANNEL_MAX]; #endif #if (ETHER_CFG_USE_VIRTUAL_ADDRESS) static uint32_t ether_mmu_uncached_diff; static uint32_t ether_mmu_VAtoPA(uint32_t vaddr) { uint32_t *ttb = (uint32_t *)(__get_TTBR0() & 0xFFFFC000); uint32_t *ttb_l2; uint32_t paddr = vaddr; ttb += (vaddr >> 20); if ((*ttb & (0x40000 | 0x3)) == 2) { paddr = (*ttb & 0xfff00000) | (vaddr & 0xfffff); } else if ((*ttb & 0x3) == 1) { ttb_l2 = (uint32_t *)(*ttb & 0xFFFFFC00); if ((*ttb_l2 & 0x3) == 0) { /* do nothing */ } else if ((*ttb_l2 & 0x3) == 1) { /* 64k page entry */ ttb_l2 += ((vaddr & 0x000ff000) >> 12); paddr = (*ttb_l2 & 0xffff0000) | (vaddr & 0xffff); } else { /* 4k page entry */ ttb_l2 += ((vaddr & 0x000ff000) >> 12); paddr = (*ttb_l2 & 0xfffff000) | (vaddr & 0xfff); } } else { /* do nothing */ } return paddr; } #endif /* * Renesas Ethernet API functions */ /*********************************************************************************************************************** * Function Name: R_ETHER_Initial (Implementation to file hwsetup.c) * Description : Initialization of Ether driver. * Arguments : none * Return Value : none ***********************************************************************************************************************/ void R_ETHER_Initial (void) { uint32_t i; /* Initialize the transmit and receive descriptor */ memset(&rx_descriptors, 0x00, sizeof(rx_descriptors)); memset(&tx_descriptors, 0x00, sizeof(tx_descriptors)); /* Initialize the Ether buffer */ memset(ðer_buffers, 0x00, sizeof(ether_buffers)); memset(etherc_edmac_power_cont, 0x00, sizeof(etherc_edmac_power_cont)); /* Initialize the callback function pointer */ cb_func.pcb_func = NULL; /* Initialize the interrupt handler pointer */ cb_func.pcb_int_hnd = NULL; /* Initialize */ for (i = 0; i < ETHER_CHANNEL_MAX; i++) { papp_rx_desc[i] = NULL; papp_tx_desc[i] = NULL; pause_frame_enable[i] = ETHER_FLAG_OFF; #if (ETHER_CFG_USE_LINKSTA == 0) g_pre_link_stat[i] = ETHER_ERR_OTHER; #endif promiscuous_mode[i] = ETHER_PROMISCUOUS_OFF; mc_filter_flag[i] = ETHER_MC_FILTER_OFF; bc_filter_count[i] = 0; } #if (ETHER_CFG_USE_VIRTUAL_ADDRESS) { uint32_t vaddress = (uint32_t)&rx_descriptors; uint32_t paddress; paddress = ether_mmu_VAtoPA(vaddress); ether_mmu_uncached_diff = vaddress - paddress; } #endif } /* End of function R_ETHER_Initial() */ /*********************************************************************************************************************** * Function Name: R_ETHER_Open_ZC2 * Description : After ETHERC, EDMAC,0x00000002; and PHY-LSI are reset in software, an auto negotiation of PHY-LSI is * begun. * Afterwards, the link signal change interrupt is permitted. * Arguments : channel - * ETHERC channel number * mac_addr - * The MAC address of ETHERC * pause - * Specifies whether flow control functionality is enabled or disabled. * Return Value : ETHER_SUCCESS - * Processing completed successfully * ETHER_ERR_INVALID_CHAN - * Nonexistent channel number * ETHER_ERR_INVALID_PTR - * Value of the pointer is NULL * ETHER_ERR_INVALID_DATA - * Value of the argument is out of range * ETHER_ERR_OTHER - * Initialization of PHY-LSI failed ***********************************************************************************************************************/ ether_return_t R_ETHER_Open_ZC2 (uint32_t channel, const uint8_t mac_addr[], uint8_t pause) { ether_return_t ret; int16_t phy_ret; volatile struct st_etherc * petherc_adr; volatile struct st_edmac * pedmac_adr; uint32_t channel_index = get_control_tbl_index(channel); if (NULL == mac_addr) { return ETHER_ERR_INVALID_PTR; } if ((ETHER_FLAG_OFF != pause) && (ETHER_FLAG_ON != pause)) { return ETHER_ERR_INVALID_DATA; } petherc_adr = g_eth_control_ch[channel_index].petherc; pedmac_adr = g_eth_control_ch[channel_index].pedmac; /* Initialize the flags */ transfer_enable_flag[channel_index] = ETHER_FLAG_OFF; mpd_flag[channel_index] = ETHER_FLAG_OFF; lchng_flag[channel_index] = ETHER_FLAG_OFF; pause_frame_enable[channel_index] = pause; mac_addr_buf[channel_index][0] = mac_addr[0]; mac_addr_buf[channel_index][1] = mac_addr[1]; mac_addr_buf[channel_index][2] = mac_addr[2]; mac_addr_buf[channel_index][3] = mac_addr[3]; mac_addr_buf[channel_index][4] = mac_addr[4]; mac_addr_buf[channel_index][5] = mac_addr[5]; #if (ETHER_CH0_EN == 1) InterruptHandlerRegister(EINT0_IRQn, ðer_eint0); #endif #if (ETHER_CH1_EN == 1) InterruptHandlerRegister(EINT1_IRQn, ðer_eint1); #endif /* Software reset */ ether_reset_mac(channel); /* Software reset the PHY */ phy_ret = phy_init(channel); if (R_PHY_OK == phy_ret) { phy_start_autonegotiate(channel, pause_frame_enable[channel_index]); /* Clear all ETHERC status BFR, PSRTO, LCHNG, MPD, ICD */ petherc_adr->ECSR.LONG = 0x00000037; /* Clear all EDMAC status bits */ pedmac_adr->EESR.LONG = 0x47FF0F9F; #if (ETHER_CFG_USE_LINKSTA == 1) /* Enable interrupts of interest only. */ petherc_adr->ECSIPR.BIT.LCHNGIP = 1; #endif pedmac_adr->EESIPR.BIT.ECIIP = 1; /* Set Ethernet interrupt level and enable */ #if (ETHER_CH0_EN == 1) GIC_SetPriority(EINT0_IRQn, 0x80); GIC_EnableIRQ(EINT0_IRQn); #endif #if (ETHER_CH1_EN == 1) GIC_SetPriority(EINT1_IRQn, 0x80); GIC_EnableIRQ(EINT1_IRQn); #endif ret = ETHER_SUCCESS; } else { ret = ETHER_ERR_OTHER; } return ret; } /* End of function R_ETHER_Open_ZC2() */ /*********************************************************************************************************************** * Function Name: R_ETHER_Close_ZC2 * Description : Disables Ethernet peripheral * Arguments : channel - * ETHERC channel number * Return Value : ETHER_SUCCESS - * Processing completed successfully * ETHER_ERR_INVALID_CHAN - * Nonexistent channel number ***********************************************************************************************************************/ ether_return_t R_ETHER_Close_ZC2 (uint32_t channel) { volatile struct st_etherc * petherc_adr; volatile struct st_edmac * pedmac_adr; uint32_t channel_index = get_control_tbl_index(channel); petherc_adr = g_eth_control_ch[channel_index].petherc; pedmac_adr = g_eth_control_ch[channel_index].pedmac; /* Disable Ethernet interrupt. */ #if (ETHER_CH0_EN == 1) GIC_DisableIRQ(EINT0_IRQn); #endif #if (ETHER_CH1_EN == 1) GIC_DisableIRQ(EINT1_IRQn); #endif petherc_adr->ECSIPR.BIT.LCHNGIP = 0; pedmac_adr->EESIPR.BIT.ECIIP = 0; /* Disable TE and RE */ petherc_adr->ECMR.LONG = 0x00000000; /* Initialize the flags */ transfer_enable_flag[channel_index] = ETHER_FLAG_OFF; mpd_flag[channel_index] = ETHER_FLAG_OFF; lchng_flag[channel_index] = ETHER_FLAG_OFF; #if (ETHER_CFG_USE_LINKSTA == 0) g_pre_link_stat[channel_index] = ETHER_ERR_OTHER; #endif return ETHER_SUCCESS; } /* End of function R_ETHER_Close_ZC2() */ /*********************************************************************************************************************** * Function Name: R_ETHER_Read_ZC2 * Description : Receives an Ethernet frame. Sets the passed * buffer pointer to the Ethernet frame buffer * from the driver. This makes the data available to * the caller as a zero-copy operation. * Arguments : channel - * ETHERC channel number * pbuf - * Pointer to buffer that holds the receive data * Return Value : Returns the number of bytes received. * ETHER_NO_DATA - * A zero value indicates no data is received. * ETHER_ERR_INVALID_CHAN - * Nonexistent channel number * ETHER_ERR_INVALID_PTR - * Value of the pointer is NULL * ETHER_ERR_LINK - * Auto-negotiation is not completed, and reception is not enabled. * ETHER_ERR_MPDE - * As a Magic Packet is being detected, transmission and reception is not enabled. * ETHER_ERR_MC_FRAME - * Multicast Frame filter is enable, and Multicast Address Frame is received. ***********************************************************************************************************************/ int32_t R_ETHER_Read_ZC2 (uint32_t channel, void **pbuf) { int32_t num_recvd; int32_t ret; int32_t complete_flag; int32_t ret2; descriptor_t * p_rx_desc; uint32_t channel_index = get_control_tbl_index(channel); p_rx_desc = papp_rx_desc[channel_index]; if (NULL == p_rx_desc) { return ETHER_ERR_INVALID_CHAN; } if (NULL == pbuf) { return ETHER_ERR_INVALID_PTR; } /* When the Link up processing is not completed, return error */ if (ETHER_FLAG_OFF == transfer_enable_flag[channel_index]) { return ETHER_ERR_LINK; } /* In case of detection mode of magic packet, return error. */ if (1 == check_mpde_bit()) { return ETHER_ERR_MPDE; } /* When the Link up processing is completed */ ret = ETHER_NO_DATA; complete_flag = ETHER_ERR_OTHER; while (ETHER_SUCCESS != complete_flag) { /* When receive data exists. */ if (RACT != (p_rx_desc->status & RACT)) { /* Check multicast is detected when multicast frame filter is enabled */ if (ETHER_MC_FILTER_ON == mc_filter_flag[channel_index]) { if (RFS7_RMAF == (p_rx_desc->status & RFS7_RMAF)) { /* The buffer is released at the multicast frame detect. */ ret2 = R_ETHER_Read_ZC2_BufRelease(channel); if (ETHER_SUCCESS != ret2) { return ret2; } ret = ETHER_ERR_MC_FRAME; complete_flag = ETHER_SUCCESS; } } if (ETHER_ERR_MC_FRAME != ret) { if (RFE == (p_rx_desc->status & RFE)) { /* The buffer is released at the error. */ ret2 = R_ETHER_Read_ZC2_BufRelease(channel); if (ETHER_SUCCESS != ret2) { return ret2; } } else { /** * Pass the pointer to received data to application. This is * zero-copy operation. */ #if (ETHER_CFG_USE_VIRTUAL_ADDRESS) (*pbuf) = (void *)(((uint32_t) p_rx_desc->buf_p) + ether_mmu_uncached_diff); #else (*pbuf) = (void *) p_rx_desc->buf_p; #endif /* Get bytes received */ num_recvd = p_rx_desc->size; ret = num_recvd; complete_flag = ETHER_SUCCESS; } } } else { ret = ETHER_NO_DATA; complete_flag = ETHER_SUCCESS; } } return ret; } /* End of function R_ETHER_Read_ZC2() */ /*********************************************************************************************************************** * Function Name: R_ETHER_Read_ZC2_BufRelease * Description : Release the receive buffer. * Arguments : channel - * Specifies the ETHERC channel number. * Return Value : ETHER_SUCCESS - * Processing completed successfully * ETHER_ERR_INVALID_CHAN - * Nonexistent channel number * ETHER_ERR_LINK - * Auto-negotiation is not completed, and reception is not enabled. * ETHER_ERR_MPDE - * As a Magic Packet is being detected, transmission and reception is not enabled. ***********************************************************************************************************************/ int32_t R_ETHER_Read_ZC2_BufRelease (uint32_t channel) { volatile struct st_edmac * pedmac_adr; uint32_t status; descriptor_t * p_rx_desc; uint32_t channel_index = get_control_tbl_index(channel); p_rx_desc = papp_rx_desc[channel_index]; if (NULL == p_rx_desc) { return ETHER_ERR_INVALID_CHAN; } /* When the Link up processing is not completed, return error */ if (ETHER_FLAG_OFF == transfer_enable_flag[channel_index]) { return ETHER_ERR_LINK; } /* In case of detection mode of magic packet, return error. */ if (1 == check_mpde_bit()) { return ETHER_ERR_MPDE; } /* When the Link up processing is completed */ /* When receive data exists */ if (RACT != (p_rx_desc->status & RACT)) { /* Move to next descriptor */ p_rx_desc->status |= RACT; status = RFP1; status |= RFP0; status |= RFE; status |= RFS9_RFOVER; status |= RFS8_RAD; status |= RFS7_RMAF; status |= RFS4_RRF; status |= RFS3_RTLF; status |= RFS2_RTSF; status |= RFS1_PRE; status |= RFS0_CERF; papp_rx_desc[channel_index]->status &= (~status); papp_rx_desc[channel_index] = papp_rx_desc[channel_index]->next; } pedmac_adr = g_eth_control_ch[channel_index].pedmac; if (0x00000000L == pedmac_adr->EDRRR.LONG) { /* Restart if stopped */ pedmac_adr->EDRRR.LONG = 0x00000001L; } return ETHER_SUCCESS; } /* End of function R_ETHER_Read_ZC2_BufRelease() */ /*********************************************************************************************************************** * Function Name: R_ETHER_Write_ZC2_GetBuf * Description : Get Points to the buffer pointer used by the stack. * Arguments : channel - * ETHERC channel number * pbuf - * Pointer to the starting address of the transmit data destination * pbuf_size - * The Maximum size to write to the buffer * Return Value : ETHER_SUCCESS - * Processing completed successfully * ETHER_ERR_INVALID_CHAN - * Nonexistent channel number * ETHER_ERR_INVALID_PTR - * Value of the pointer is NULL * ETHER_ERR_LINK - * Auto-negotiation is not completed, and reception is not enabled. * ETHER_ERR_MPDE - * As a Magic Packet is being detected, transmission and reception is not enabled. * ETHER_ERR_TACT - * Transmit buffer is not empty. ***********************************************************************************************************************/ ether_return_t R_ETHER_Write_ZC2_GetBuf (uint32_t channel, void **pbuf, uint16_t *pbuf_size) { /* Check argument */ descriptor_t* p_tx_desc; uint32_t channel_index = get_control_tbl_index(channel); p_tx_desc = papp_tx_desc[channel_index]; if (NULL == p_tx_desc) { return ETHER_ERR_INVALID_CHAN; } if (NULL == pbuf) { return ETHER_ERR_INVALID_PTR; } if (NULL == pbuf_size) { return ETHER_ERR_INVALID_PTR; } /* When the Link up processing is not completed, return error */ if (ETHER_FLAG_OFF == transfer_enable_flag[channel_index]) { return ETHER_ERR_LINK; } /* In case of detection mode of magic packet, return error. */ if (1 == check_mpde_bit()) { return ETHER_ERR_MPDE; } /* When the Link up processing is completed */ /* All transmit buffers are full */ if (TACT == (p_tx_desc->status & TACT)) { return ETHER_ERR_TACT; } /* Give application another buffer to work with */ #if (ETHER_CFG_USE_VIRTUAL_ADDRESS) (*pbuf) = (void*)((p_tx_desc->buf_p) + ether_mmu_uncached_diff); #else (*pbuf) = (void*) p_tx_desc->buf_p; #endif (*pbuf_size) = ETHER_CFG_BUFSIZE; return ETHER_SUCCESS; } /* End of function R_ETHER_Write_ZC2_GetBuf() */ /*********************************************************************************************************************** * Function Name: R_ETHER_Write_ZC2_SetBuf * Description : Transmits an Ethernet frame. * The transmit descriptor points to the data to transmit. * Data is sent directly from memory as a "zero copy" operation. * Arguments : channel - * ETHERC channel number * len - * The size (60 to 1,514 bytes) which is the Ethernet frame length minus 4 bytes of CRC * Return Value : ETHER_SUCCESS - * Processing completed successfully * ETHER_ERR_INVALID_CHAN - * Nonexistent channel number * ETHER_ERR_INVALID_DATA - * Value of the argument is out of range * ETHER_ERR_LINK - * Auto-negotiation is not completed, and reception is not enabled. * ETHER_ERR_MPDE - * As a Magic Packet is being detected, transmission and reception is not enabled. ***********************************************************************************************************************/ ether_return_t R_ETHER_Write_ZC2_SetBuf (uint32_t channel, const uint32_t len) { volatile struct st_edmac * pedmac_adr; descriptor_t* p_tx_desc; uint32_t channel_index = get_control_tbl_index(channel); p_tx_desc = papp_tx_desc[channel_index]; if (NULL == p_tx_desc) { return ETHER_ERR_INVALID_CHAN; } if ((ETHER_BUFSIZE_MIN > len) || (ETHER_BUFSIZE_MAX < len)) { return ETHER_ERR_INVALID_DATA; } /* When the Link up processing is not completed, return error */ if (ETHER_FLAG_OFF == transfer_enable_flag[channel_index]) { return ETHER_ERR_LINK; } /* In case of detection mode of magic packet, return error. */ if (1 == check_mpde_bit()) { return ETHER_ERR_MPDE; } /* When the Link up processing is completed */ /* The data of the buffer is made active. */ p_tx_desc->bufsize = len; p_tx_desc->status &= (~(TFP1 | TFP0)); p_tx_desc->status |= ((TFP1 | TFP0) | TACT); papp_tx_desc[channel_index] = p_tx_desc->next; pedmac_adr = g_eth_control_ch[channel_index].pedmac; if (0x00000000L == pedmac_adr->EDTRR.LONG) { /* Restart if stopped */ pedmac_adr->EDTRR.LONG = 0x00000001L; } return ETHER_SUCCESS; } /* End of function R_ETHER_Write_ZC2_SetBuf() */ /*********************************************************************************************************************** * Function Name: R_ETHER_CheckLink_ZC * Description : Verifies the Etherent link is up or not. * Arguments : channel - * ETHERC channel number * Return Value : ETHER_SUCCESS - * Link is up * ETHER_ERR_OTHER - * Link is down * ETHER_ERR_INVALID_CHAN - * Nonexistent channel number ***********************************************************************************************************************/ ether_return_t R_ETHER_CheckLink_ZC (uint32_t channel) { if (R_PHY_ERROR == phy_get_link_status(channel)) { /* Link is down */ return ETHER_ERR_OTHER; } /* Link is up */ return ETHER_SUCCESS; } /* End of function R_ETHER_CheckLink_ZC() */ /*********************************************************************************************************************** * Function Name: R_ETHER_LinkProcess * Description : The Link up processing, the Link down processing, and the magic packet detection processing are * executed. * Arguments : channel - * ETHERC channel number * Return Value : none ***********************************************************************************************************************/ void R_ETHER_LinkProcess (uint32_t channel) { volatile struct st_etherc * petherc_adr; int32_t ret; ether_cb_arg_t cb_arg; uint32_t channel_index = get_control_tbl_index(channel); /* When the magic packet is detected. */ if (ETHER_FLAG_ON == mpd_flag[channel_index]) { mpd_flag[channel_index] = ETHER_FLAG_OFF; if (NULL != cb_func.pcb_func) { cb_arg.channel = channel; cb_arg.event_id = ETHER_CB_EVENT_ID_WAKEON_LAN; (*cb_func.pcb_func)((void *) &cb_arg); } /* * After the close function is called, the open function is called * to have to set ETHERC to a usual operational mode * to usually communicate after magic packet is detected. */ R_ETHER_Close_ZC2(channel); R_ETHER_Open_ZC2(channel, mac_addr_buf[channel_index], pause_frame_enable[channel_index]); } #if (ETHER_CFG_USE_LINKSTA == 0) ret = R_ETHER_CheckLink_ZC(channel); if (g_pre_link_stat[channel_index] != ret) { if (ret == ETHER_SUCCESS) { /* The state of the link status in PHY-LSI is confirmed and Link Up/Down is judged. */ /* When becoming Link up */ lchng_flag[channel_index] = ETHER_FLAG_ON_LINK_ON; } else { /* When becoming Link down */ lchng_flag[channel_index] = ETHER_FLAG_ON_LINK_OFF; } } g_pre_link_stat[channel_index] = ret; #endif /* When the link is up */ if (ETHER_FLAG_ON_LINK_ON == lchng_flag[channel_index]) { #if (ETHER_CFG_USE_LINKSTA == 1) /* * The Link Up/Down is confirmed by the Link Status bit of PHY register1, * because the LINK signal of PHY-LSI is used for LED indicator, and * isn't used for notifing the Link Up/Down to external device. */ ret = R_ETHER_CheckLink_ZC(channel); if (ETHER_SUCCESS == ret) { /* * The status of the LINK signal became "link-up" even if PHY-LSI did not detect "link-up" * after a reset. To avoid this wrong detection, processing in R_ETHER_LinkProcess has been modified to * clear the flag after link-up is confirmed in R_ETHER_CheckLink_ZC. */ lchng_flag[channel_index] = ETHER_FLAG_OFF; /* Initialize the transmit and receive descriptor */ memset(&rx_descriptors[channel_index], 0x00, sizeof(rx_descriptors[channel_index])); memset(&tx_descriptors[channel_index], 0x00, sizeof(tx_descriptors[channel_index])); /* Initialize the Ether buffer */ memset(ðer_buffers[channel_index], 0x00, sizeof(ether_buffers[channel_index])); transfer_enable_flag[channel_index] = ETHER_FLAG_ON; /* * ETHERC and EDMAC are set after ETHERC and EDMAC are reset in software * and sending and receiving is permitted. */ ether_configure_mac(channel, mac_addr_buf[channel_index], NO_USE_MAGIC_PACKET_DETECT); ret = ether_do_link(channel, NO_USE_MAGIC_PACKET_DETECT); if (ETHER_SUCCESS == ret) { if (NULL != cb_func.pcb_func) { cb_arg.channel = channel; cb_arg.event_id = ETHER_CB_EVENT_ID_LINK_ON; (*cb_func.pcb_func)((void *) &cb_arg); } } else { /* When PHY auto-negotiation is not completed */ transfer_enable_flag[channel_index] = ETHER_FLAG_OFF; lchng_flag[channel_index] = ETHER_FLAG_ON_LINK_ON; } } else { /* no process */ } #elif (ETHER_CFG_USE_LINKSTA == 0) /* * The status of the LINK signal became "link-up" even if PHY-LSI did not detect "link-up" * after a reset. To avoid this wrong detection, processing in R_ETHER_LinkProcess has been modified to * clear the flag after link-up is confirmed in R_ETHER_CheckLink_ZC. */ lchng_flag[channel_index] = ETHER_FLAG_OFF; /* Initialize the transmit and receive descriptor */ memset(&rx_descriptors[channel_index], 0x00, sizeof(rx_descriptors[channel_index])); memset(&tx_descriptors[channel_index], 0x00, sizeof(tx_descriptors[channel_index])); /* Initialize the Ether buffer */ memset(ðer_buffers[channel_index], 0x00, sizeof(ether_buffers[channel_index])); transfer_enable_flag[channel_index] = ETHER_FLAG_ON; /* * ETHERC and EDMAC are set after ETHERC and EDMAC are reset in software * and sending and receiving is permitted. */ ether_configure_mac(channel, mac_addr_buf[channel_index], NO_USE_MAGIC_PACKET_DETECT); ret = ether_do_link(channel, NO_USE_MAGIC_PACKET_DETECT); if (ETHER_SUCCESS == ret) { if (NULL != cb_func.pcb_func) { cb_arg.channel = channel; cb_arg.event_id = ETHER_CB_EVENT_ID_LINK_ON; (*cb_func.pcb_func)((void *) &cb_arg); } } else { /* When PHY auto-negotiation is not completed */ transfer_enable_flag[channel_index] = ETHER_FLAG_OFF; lchng_flag[channel_index] = ETHER_FLAG_ON_LINK_ON; } #endif } /* When the link is down */ else if (ETHER_FLAG_ON_LINK_OFF == lchng_flag[channel_index]) { lchng_flag[channel_index] = ETHER_FLAG_OFF; #if (ETHER_CFG_USE_LINKSTA == 1) /* * The Link Up/Down is confirmed by the Link Status bit of PHY register1, * because the LINK signal of PHY-LSI is used for LED indicator, and * isn't used for notifying the Link Up/Down to external device. */ ret = R_ETHER_CheckLink_ZC(channel); if (ETHER_ERR_OTHER == ret) { petherc_adr = g_eth_control_ch[channel_index].petherc; /* Disable receive and transmit. */ petherc_adr->ECMR.BIT.RE = 0; petherc_adr->ECMR.BIT.TE = 0; transfer_enable_flag[channel_index] = ETHER_FLAG_OFF; if (NULL != cb_func.pcb_func) { cb_arg.channel = channel; cb_arg.event_id = ETHER_CB_EVENT_ID_LINK_OFF; (*cb_func.pcb_func)((void *) &cb_arg); } } #elif (ETHER_CFG_USE_LINKSTA == 0) petherc_adr = g_eth_control_ch[channel_index].petherc; /* Disable receive and transmit. */ petherc_adr->ECMR.BIT.RE = 0; petherc_adr->ECMR.BIT.TE = 0; transfer_enable_flag[channel_index] = ETHER_FLAG_OFF; if (NULL != cb_func.pcb_func) { cb_arg.channel = channel; cb_arg.event_id = ETHER_CB_EVENT_ID_LINK_OFF; (*cb_func.pcb_func)((void *) &cb_arg); } #endif } else { /* Do Nothing */ } } /* End of function R_ETHER_LinkProcess() */ /*********************************************************************************************************************** * Function Name: R_ETHER_WakeOnLAN * Description : The setting of ETHERC is changed from a usual sending and * receiving mode to the magic packet detection mode. * Arguments : channel - * ETHERC channel number * Return Value : ETHER_SUCCESS - * Processing completed successfully * ETHER_ERR_INVALID_CHAN - * Nonexistent channel number * ETHER_ERR_LINK - * Auto-negotiation is not completed, and reception is not enabled. * ETHER_ERR_OTHER - * A switch to magic packet detection was performed when the link state was link is down. ***********************************************************************************************************************/ ether_return_t R_ETHER_WakeOnLAN (uint32_t channel) { #if (ETHER_CFG_USE_LINKSTA == 1) volatile struct st_etherc * petherc_adr; #endif ether_return_t ret; uint32_t channel_index = get_control_tbl_index(channel); /* When the Link up processing is not completed, return error */ if (ETHER_FLAG_OFF == transfer_enable_flag[channel_index]) { return ETHER_ERR_LINK; } /* When the Link up processing is completed */ /* Change to the magic packet detection mode. */ ether_configure_mac(channel, mac_addr_buf[channel_index], USE_MAGIC_PACKET_DETECT); ret = ether_do_link(channel, USE_MAGIC_PACKET_DETECT); if (ETHER_SUCCESS == ret) { #if (ETHER_CFG_USE_LINKSTA == 1) petherc_adr = g_eth_control_ch[channel_index].petherc; /* It is confirmed not to become Link down while changing the setting. */ if (ETHER_CFG_LINK_PRESENT == petherc_adr->PSR.BIT.LMON) { ret = ETHER_SUCCESS; } else { ret = ETHER_ERR_OTHER; } #else /* It is confirmed not to become Link down while changing the setting. */ ret = R_ETHER_CheckLink_ZC(channel); #endif } else { ret = ETHER_ERR_OTHER; } return ret; } /* End of function R_ETHER_WakeOnLAN() */ /*********************************************************************************************************************** * Function Name: R_ETHER_Read * Description : Receive Ethernet frame. Receives data to the location specified by the pointer to the receive buffer, * using non-zero-copy communication. * Arguments : channel - * ETHERC channel number * pbuf - * The receive buffer (to store the receive data) * Return Value : Returns the number of bytes received. * ETHER_NO_DATA - * A zero value indicates no data is received. * ETHER_ERR_INVALID_CHAN - * Nonexistent channel number * ETHER_ERR_INVALID_PTR - * Value of the pointer is NULL * ETHER_ERR_LINK - * Auto-negotiation is not completed, and reception is not enabled. * ETHER_ERR_MPDE - * As a Magic Packet is being detected, transmission and reception is not enabled. * ETHER_ERR_MC_FRAME - * Multicast Frame filter is enable, and Multicast Address Frame is received. ***********************************************************************************************************************/ int32_t R_ETHER_Read (uint32_t channel, void *pbuf) { int32_t ret; int32_t ret2; uint8_t * pread_buffer_address; /* Buffer location controlled by the Ethernet driver */ /* Check argument */ if (NULL == pbuf) { return ETHER_ERR_INVALID_PTR; } /* (1) Retrieve the receive buffer location controlled by the descriptor. */ ret = R_ETHER_Read_ZC2(channel, (void **) &pread_buffer_address); /* When there is data to receive */ if (ret > ETHER_NO_DATA) { /* (2) Copy the data read from the receive buffer which is controlled by the descriptor to the buffer which is specified by the user (up to 1024 bytes). */ memcpy(pbuf, pread_buffer_address, (uint32_t )ret); /* (3) Read the receive data from the receive buffer controlled by the descriptor, and then release the receive buffer. */ ret2 = R_ETHER_Read_ZC2_BufRelease(channel); if (ETHER_SUCCESS == ret2) { /* When this function is completed successfully */ /* Do Nothing */ } /* Overwrite the error information */ else { ret = ret2; } } /* When there is no data to receive */ else { /* Do Nothing */ } return ret; } /* End of function R_ETHER_Read() */ /*********************************************************************************************************************** * Function Name: R_ETHER_Write * Description : Transmit Ethernet frame. Transmits data from the location specified by the pointer to the transmit * buffer, with the data size equal to the specified frame length, using non-zero-copy communication. * Arguments : channel - * ETHERC channel number * : *pbuf - * Transmit buffer pointer * : len - * The size (60 to 1,514 bytes) which is the Ethernet frame length minus 4 bytes of CRC * Return Value : ETHER_SUCCESS - * Processing completed successfully * ETHER_ERR_INVALID_CHAN - * Nonexistent channel number * ETHER_ERR_INVALID_DATA - * Value of the argument is out of range * ETHER_ERR_INVALID_PTR - * Value of the pointer is NULL * ETHER_ERR_LINK - * Auto-negotiation is not completed, and reception is not enabled. * ETHER_ERR_MPDE - * As a Magic Packet is being detected, transmission and reception is not enabled. * ETHER_ERR_TACT - * Transmit buffer is not empty. ***********************************************************************************************************************/ ether_return_t R_ETHER_Write (uint32_t channel, void *pbuf, const uint32_t len) { ether_return_t ret; uint8_t * pwrite_buffer_address; uint16_t write_buf_size; if (NULL == pbuf) { return ETHER_ERR_INVALID_PTR; } if ((ETHER_BUFSIZE_MIN > len) || (ETHER_BUFSIZE_MAX < len)) { return ETHER_ERR_INVALID_DATA; } /* (1) Retrieve the transmit buffer location controlled by the descriptor. */ ret = R_ETHER_Write_ZC2_GetBuf(channel, (void **) &pwrite_buffer_address, &write_buf_size); /* Writing to the transmit buffer (buf) is enabled. */ if (ETHER_SUCCESS == ret) { if (write_buf_size < len) { ret = ETHER_ERR_TACT; /* Transmit buffer overflow */ } else { /* Write the transmit data to the transmit buffer. */ /* (2) Write the data to the transmit buffer controlled by the descriptor. */ memcpy(pwrite_buffer_address, pbuf, len); /* (3) Enable the EDMAC to transmit data in the transmit buffer. */ ret = R_ETHER_Write_ZC2_SetBuf(channel, len); /* * Confirm that the transmission is completed. * Data written in the transmit buffer is transmitted by the EDMAC. Make sure that the * transmission is completed after writing data to the transmit buffer. * If the R_ETHER_Close_ZC2 function is called to stop the Ethernet communication before * verifying that the transmission is completed, the written data written may not be transmitted. */ ret = R_ETHER_CheckWrite(channel); } } return ret; } /* End of function R_ETHER_Write() */ /*********************************************************************************************************************** * Function Name: R_ETHER_CheckWrite * Description : Checking that the data has been sent. * Arguments : channel - * ETHERC channel number * Return Value : ETHER_SUCCESS - * Processing completed successfully * ETHER_ERR_INVALID_CHAN - * Nonexistent channel number ***********************************************************************************************************************/ ether_return_t R_ETHER_CheckWrite (uint32_t channel) { volatile struct st_edmac * pedmac_adr; uint32_t channel_index = get_control_tbl_index(channel); pedmac_adr = g_eth_control_ch[channel_index].pedmac; while (0 != pedmac_adr->EDTRR.BIT.TR) { /* Do Nothing */ } return ETHER_SUCCESS; } /* End of function R_ETHER_CheckWrite() */ /*********************************************************************************************************************** * Function Name: R_ETHER_Control * Description : By command argument is a function to change the settings of Ether driver. * Arguments : cmd - * Control code * control - * Parameters according to the control code * Return Value : ETHER_SUCCESS - * Processing completed successfully * ETHER_ERR_INVALID_CHAN - * Nonexistent channel number * ETHER_ERR_CHAN_OPEN - * Indicates the Ethernet cannot be opened because it is being used by another application * ETHER_ERR_INVALID_ARG - * Invalid argument * ETHER_ERR_RECV_ENABLE - * Receive function is enable. ***********************************************************************************************************************/ ether_return_t R_ETHER_Control (ether_cmd_t const cmd, ether_param_t const control) { ether_return_t ret; switch (cmd) { /* Set the callback function pointer */ case CONTROL_SET_CALLBACK : ret = ether_set_callback(control); break; case CONTROL_SET_PROMISCUOUS_MODE : ret = ether_set_promiscuous_mode(control); break; case CONTROL_SET_INT_HANDLER : ret = ether_set_int_handler(control); break; case CONTROL_POWER_ON : ret = ether_power_on(control); break; case CONTROL_POWER_OFF : ret = ether_power_off(control); break; case CONTROL_MULTICASTFRAME_FILTER : ret = ether_set_multicastframe_filter(control); break; case CONTROL_BROADCASTFRAME_FILTER : ret = ether_set_broadcastframe_filter(control); break; /* Commands not supported */ default : ret = ETHER_ERR_INVALID_ARG; break; } return ret; } /* End of function R_ETHER_Control() */ /*********************************************************************************************************************** * Function Name: R_ETHER_GetVersion * Description : Returns this module's version information. * The version number is encoded where the top 2 bytes are the major version number and the bottom 2 bytes * are the minor version number. For example, Version 4.25 would be returned as 0x00040019. * Arguments : none * Return Value : Version number ***********************************************************************************************************************/ //#pragma inline(R_ETHER_GetVersion) uint32_t R_ETHER_GetVersion (void) { return ((((uint32_t) ETHER_RZA2_VERSION_MAJOR) << 16) | ((uint32_t) ETHER_RZA2_VERSION_MINOR)); } /* End of function R_ETHER_GetVersion() */ /* * Private functions */ /*********************************************************************************************************************** * Function Name: ether_reset_mac * Description : The EDMAC and EtherC are reset through the software reset. * Arguments : channel - * ETHERC channel number * Return Value : none ***********************************************************************************************************************/ static void ether_reset_mac (uint32_t channel) { volatile uint32_t i; /* Software reset */ if (ETHER_CHANNEL_0 == channel) { EDMAC0.EDMR.BIT.SWR = 1; } else { EDMAC1.EDMR.BIT.SWR = 1; } /* * Waiting time until the initialization of ETHERC and EDMAC is completed is 64 cycles * in the clock conversion of an internal bus of EDMAC. */ for (i = 0; i < 0x00001180; i++) { ; } } /* End of function ether_reset_mac() */ /*********************************************************************************************************************** * Function Name: ether_init_descriptors * Description : The EDMAC descriptors and the driver buffers are initialized. * Arguments : channel - * ETHERC channel number * Return Value : none ***********************************************************************************************************************/ static void ether_init_descriptors (uint32_t channel) { descriptor_t * pdescriptor; uint32_t i; uint32_t channel_index = get_control_tbl_index(channel); /* Initialize the receive descriptors */ for (i = 0; i < ETHER_CFG_EMAC_RX_DESCRIPTORS; i++) { pdescriptor = (descriptor_t *) &rx_descriptors[channel_index][i]; #if (ETHER_CFG_USE_VIRTUAL_ADDRESS) pdescriptor->buf_p = (uint8_t *) ether_mmu_VAtoPA((uint32_t)&(ether_buffers[channel_index].buffer[i][0])); #else pdescriptor->buf_p = (uint8_t *) &(ether_buffers[channel_index].buffer[i][0]); #endif pdescriptor->bufsize = ETHER_CFG_BUFSIZE; pdescriptor->size = 0; pdescriptor->status = RACT; pdescriptor->next = (descriptor_t *) &rx_descriptors[channel_index][(i + 1)]; } /* The last descriptor points back to the start */ pdescriptor->status |= RDLE; pdescriptor->next = (descriptor_t *) &rx_descriptors[channel_index][0]; /* Initialize application receive descriptor pointer */ papp_rx_desc[channel_index] = (descriptor_t *) &rx_descriptors[channel_index][0]; /* Initialize the transmit descriptors */ for (i = 0; i < ETHER_CFG_EMAC_TX_DESCRIPTORS; i++) { pdescriptor = (descriptor_t *) &tx_descriptors[channel_index][i]; #if (ETHER_CFG_USE_VIRTUAL_ADDRESS) pdescriptor->buf_p = (uint8_t *) ether_mmu_VAtoPA((uint32_t)&(ether_buffers[channel_index].buffer[(ETHER_CFG_EMAC_RX_DESCRIPTORS + i)][0])); #else pdescriptor->buf_p = (uint8_t *) &(ether_buffers[channel_index].buffer[(ETHER_CFG_EMAC_RX_DESCRIPTORS + i)][0]); #endif pdescriptor->bufsize = 1; /* Set a value equal to or greater than 1. (reference to UMH) When transmitting data, the value of size is set to the function argument R_ETHER_Write_ZC2_SetBuf. */ pdescriptor->size = 0; /* Reserved : The write value should be 0. (reference to UMH) */ pdescriptor->status = 0; pdescriptor->next = (descriptor_t *) &(tx_descriptors[channel_index][(i + 1)]); } /* The last descriptor points back to the start */ pdescriptor->status |= TDLE; pdescriptor->next = (descriptor_t *) &tx_descriptors[channel_index][0]; /* Initialize application transmit descriptor pointer */ papp_tx_desc[channel_index] = (descriptor_t *) &tx_descriptors[channel_index][0]; } /* End of function ether_init_descriptors() */ /*********************************************************************************************************************** * Function Name: ether_config_ethernet * Description : Configure the Ethernet Controller (EtherC) and the Ethernet * Direct Memory Access controller (EDMAC). * Arguments : channel - * ETHERC channel number * mode - * The operational mode is specified. * NO_USE_MAGIC_PACKET_DETECT (0) - Communicate mode usually * USE_MAGIC_PACKET_DETECT (1) - Magic packet detection mode * Return Value : none ***********************************************************************************************************************/ static void ether_config_ethernet (uint32_t channel, const uint8_t mode) { volatile struct st_etherc * petherc_adr; volatile struct st_edmac * pedmac_adr; uint32_t channel_index = get_control_tbl_index(channel); petherc_adr = g_eth_control_ch[channel_index].petherc; pedmac_adr = g_eth_control_ch[channel_index].pedmac; /* Magic packet detection mode */ if (USE_MAGIC_PACKET_DETECT == mode) { #if (ETHER_CFG_USE_LINKSTA == 1) petherc_adr->ECSIPR.LONG = 0x00000006; #elif (ETHER_CFG_USE_LINKSTA == 0) petherc_adr->ECSIPR.LONG = 0x00000002; #endif pedmac_adr->EESIPR.LONG = 0x00400000; } /* Normal mode */ else { #if (ETHER_CFG_USE_LINKSTA == 1) /* LINK Signal Change Interrupt Enable */ petherc_adr->ECSR.BIT.LCHNG = 1; petherc_adr->ECSIPR.BIT.LCHNGIP = 1; #endif pedmac_adr->EESIPR.BIT.ECIIP = 1; /* Frame receive interrupt and frame transmit end interrupt */ pedmac_adr->EESIPR.BIT.FRIP = 1; /* Enable the frame receive interrupt. */ pedmac_adr->EESIPR.BIT.TCIP = 1; /* Enable the frame transmit end interrupt. */ } /* Ethernet length 1514bytes + CRC and intergap is 96-bit time */ petherc_adr->RFLR.LONG = 1518; petherc_adr->IPGR.LONG = 0x00000014; /* Continuous reception number of Broadcast frame */ petherc_adr->BCFRR.LONG = bc_filter_count[channel_index]; /* Set little endian mode */ /* Ethernet length 1514bytes + CRC and intergap is 96-bit time */ pedmac_adr->EDMR.BIT.DE = 1; /* Initialize Rx descriptor list address */ /* Casting the pointer to a uint32_t type is valid because the Renesas Compiler uses 4 bytes per pointer. */ #if (ETHER_CFG_USE_VIRTUAL_ADDRESS) pedmac_adr->RDLAR.LONG = ether_mmu_VAtoPA((uint32_t)papp_rx_desc[channel_index]); #else pedmac_adr->RDLAR.LONG = (uint32_t)papp_rx_desc[channel_index]; #endif /* Initialize Tx descriptor list address */ /* Casting the pointer to a uint32_t type is valid because the Renesas Compiler uses 4 bytes per pointer. */ #if (ETHER_CFG_USE_VIRTUAL_ADDRESS) pedmac_adr->TDLAR.LONG = ether_mmu_VAtoPA((uint32_t)papp_tx_desc[channel_index]); #else pedmac_adr->TDLAR.LONG = (uint32_t)papp_tx_desc[channel_index]; #endif if (ETHER_MC_FILTER_ON == mc_filter_flag[channel_index]) { /* Reflect the EESR.RMAF bit status in the RD0.RFS bit in the receive descriptor */ pedmac_adr->TRSCER.LONG = 0x00000000; } else { /* Don't reflect the EESR.RMAF bit status in the RD0.RFS bit in the receive descriptor */ pedmac_adr->TRSCER.LONG = 0x00000080; } /* Threshold of Tx_FIFO */ /* To prevent a transmit underflow, setting the initial value (store and forward modes) is recommended. */ pedmac_adr->TFTR.LONG = 0x00000000; /* transmit fifo is 2048 bytes, receive fifo is 4096 bytes */ pedmac_adr->FDR.LONG = 0x0000070F; /* Configure receiving method b0 RNR - Receive Request Bit Reset - Continuous reception of multiple frames is possible. b31:b1 Reserved set to 0 */ pedmac_adr->RMCR.LONG = 0x00000001; } /* End of function ether_config_ethernet() */ /*********************************************************************************************************************** * Function Name: ether_pause_resolution * Description : Determines PAUSE frame generation and handling. Uses * the resolution Table 28B-3 of IEEE 802.3-2008. * Arguments : local_ability - * local PAUSE capability (2 least significant bits) * partner_ability - * link partner PAUSE capability (2 least significant bits) * *ptx_pause - * pointer to location to store the result of the table lookup for transmit * PAUSE. 1 is enable, 0 is disable. * *prx_pause - * pointer to location to store the result of the table lookup for receive * PAUSE. 1 is enable, 0 is disable. * Return Value : none ***********************************************************************************************************************/ static void ether_pause_resolution (uint16_t local_ability, uint16_t partner_ability, uint16_t *ptx_pause, uint16_t *prx_pause) { uint32_t i; uint32_t ability_compare; /* * Arrange the bits so that they correspond to the Table 28B-3 * of the IEEE 802.3 values. */ ability_compare = (uint32_t) (((local_ability & LINK_RES_ABILITY_MASK) << LINK_RES_LOCAL_ABILITY_BITSHIFT) | (partner_ability & LINK_RES_ABILITY_MASK)); /* Walk through the look up table */ for (i = 0; i < PAUSE_TABLE_ENTRIES; i++) { if ((ability_compare & pause_resolution[i].mask) == pause_resolution[i].value) { (*ptx_pause) = pause_resolution[i].transmit; (*prx_pause) = pause_resolution[i].receive; return; } } } /* End of function ether_pause_resolution() */ /*********************************************************************************************************************** * Function Name: ether_configure_mac * Description : Software reset is executed, and ETHERC and EDMAC are configured. * Arguments : channel - * ETHERC channel number * mac_addr - * The MAC address of ETHERC * mode - * The operational mode is specified. * NO_USE_MAGIC_PACKET_DETECT (0) - Communicate mode usually * USE_MAGIC_PACKET_DETECT (1) - Magic packet detection mode * Return Value : none ***********************************************************************************************************************/ static void ether_configure_mac (uint32_t channel, const uint8_t mac_addr[], const uint8_t mode) { uint32_t mac_h; uint32_t mac_l; volatile struct st_etherc * petherc_adr; uint32_t channel_index = get_control_tbl_index(channel); petherc_adr = g_eth_control_ch[channel_index].petherc; /* Software reset */ ether_reset_mac(channel); /* Set MAC address */ mac_h = (((((uint32_t) mac_addr[0] << 24) | ((uint32_t) mac_addr[1] << 16)) | ((uint32_t) mac_addr[2] << 8)) | (uint32_t) mac_addr[3]); mac_l = (((uint32_t) mac_addr[4] << 8) | (uint32_t) mac_addr[5]); petherc_adr->MAHR.LONG = mac_h; petherc_adr->MALR.LONG = mac_l; /* Initialize receive and transmit descriptors */ ether_init_descriptors(channel); /* Perform reset of hardware interface configuration */ ether_config_ethernet(channel, mode); } /* End of function ether_configure_mac() */ /*********************************************************************************************************************** * Function Name: ether_do_link * Description : Determines the partner PHY capability through * auto-negotiation process. The link abilities * are handled to determine duplex, speed and flow * control (PAUSE frames). * Arguments : channel - * ETHERC channel number * mode - * The operational mode is specified. * NO_USE_MAGIC_PACKET_DETECT (0) - Communicate mode usually * USE_MAGIC_PACKET_DETECT (1) - Magic packet detection mode * Return Value : ETHER_SUCCESS - * Processing completed successfully * ETHER_ERR_INVALID_CHAN - * Nonexistent channel number * ETHER_ERR_OTHER - * Auto-negotiation of PHY-LSI is not completed or result of Auto-negotiation is abnormal. ***********************************************************************************************************************/ static ether_return_t ether_do_link (uint32_t channel, const uint8_t mode) { ether_return_t ret; uint16_t link_speed_duplex = 0; uint16_t local_pause_bits = 0; uint16_t partner_pause_bits = 0; uint16_t transmit_pause_set = 0; uint16_t receive_pause_set = 0; uint16_t full_duplex = 0; uint16_t link_result = 0; volatile struct st_etherc * petherc_adr; volatile struct st_edmac * pedmac_adr; uint32_t channel_index = get_control_tbl_index(channel); petherc_adr = g_eth_control_ch[channel_index].petherc; pedmac_adr = g_eth_control_ch[channel_index].pedmac; /* Set the link status */ link_result = phy_set_autonegotiate(channel, &link_speed_duplex, &local_pause_bits, &partner_pause_bits); if (R_PHY_OK == link_result) { switch (link_speed_duplex) { /* Half duplex link */ case PHY_LINK_100H : petherc_adr->ECMR.BIT.DM = 0; petherc_adr->ECMR.BIT.RTM = 1; ret = ETHER_SUCCESS; break; case PHY_LINK_10H : petherc_adr->ECMR.BIT.DM = 0; petherc_adr->ECMR.BIT.RTM = 0; ret = ETHER_SUCCESS; break; /* Full duplex link */ case PHY_LINK_100F : petherc_adr->ECMR.BIT.DM = 1; petherc_adr->ECMR.BIT.RTM = 1; full_duplex = 1; ret = ETHER_SUCCESS; break; case PHY_LINK_10F : petherc_adr->ECMR.BIT.DM = 1; petherc_adr->ECMR.BIT.RTM = 0; full_duplex = 1; ret = ETHER_SUCCESS; break; default : ret = ETHER_ERR_OTHER; break; } /* At the communicate mode usually */ if (ETHER_SUCCESS == ret) { if (NO_USE_MAGIC_PACKET_DETECT == mode) { /* When pause frame is used */ if ((full_duplex) && (ETHER_FLAG_ON == pause_frame_enable[channel_index])) { /* Set automatic PAUSE for 512 bit-time */ petherc_adr->APR.LONG = 0x0000FFFF; /* Set unlimited retransmit of PAUSE frames */ petherc_adr->TPAUSER.LONG = 0; /* PAUSE flow control FIFO settings. */ pedmac_adr->FCFTR.LONG = 0x00000000; /* Control of a PAUSE frame whose TIME parameter value is 0 is enabled. */ petherc_adr->ECMR.BIT.ZPF = 1; /** * Enable PAUSE for full duplex link depending on * the pause resolution results */ ether_pause_resolution(local_pause_bits, partner_pause_bits, &transmit_pause_set, &receive_pause_set); if (XMIT_PAUSE_ON == transmit_pause_set) { /* Enable automatic PAUSE frame transmission */ petherc_adr->ECMR.BIT.TXF = 1; } else { /* Disable automatic PAUSE frame transmission */ petherc_adr->ECMR.BIT.TXF = 0; } if (RECV_PAUSE_ON == receive_pause_set) { /* Enable reception of PAUSE frames */ petherc_adr->ECMR.BIT.RXF = 1; } else { /* Disable reception of PAUSE frames */ petherc_adr->ECMR.BIT.RXF = 0; } } /* When pause frame is not used */ else { /* Disable PAUSE for half duplex link */ petherc_adr->ECMR.BIT.TXF = 0; petherc_adr->ECMR.BIT.RXF = 0; } /* Set the promiscuous mode bit */ petherc_adr->ECMR.BIT.PRM = promiscuous_mode[channel_index]; /* Enable receive and transmit. */ petherc_adr->ECMR.BIT.RE = 1; petherc_adr->ECMR.BIT.TE = 1; /* Enable EDMAC receive */ pedmac_adr->EDRRR.LONG = 0x1; } /* At the magic packet detection mode */ else { /* The magic packet detection is permitted. */ petherc_adr->ECMR.BIT.MPDE = 1; /* Because data is not transmitted for the magic packet detection waiting, only the reception is permitted. */ petherc_adr->ECMR.BIT.RE = 1; /* * The reception function of EDMAC keep invalidity * because the receive data don't need to be read when the magic packet detection mode. */ } } } else { ret = ETHER_ERR_OTHER; } return ret; } /* End of function ether_do_link() */ /*********************************************************************************************************************** * Function Name: ether_set_callback * Description : Set the callback function * Arguments : control - * Callback function pointer. * If you would rather poll for finish then please input NULL for this argument. * Return Value : ETHER_SUCCESS * Processing completed successfully ***********************************************************************************************************************/ static ether_return_t ether_set_callback (ether_param_t const control) { void (*pcb_func) (void *); pcb_func = control.ether_callback.pcb_func; /* Check callback function pointer */ if (NULL != pcb_func) { cb_func.pcb_func = pcb_func; /* Set the callback function */ } return ETHER_SUCCESS; } /* End of function ether_set_callback() */ /*********************************************************************************************************************** * Function Name: ether_set_promiscuous_mode * Description : Set promiscuous mode bit * Arguments : control - * Promiscuous mode bit * Return Value : ETHER_SUCCESS - * Processing completed successfully * ETHER_ERR_INVALID_CHAN - * Nonexistent channel number ***********************************************************************************************************************/ static ether_return_t ether_set_promiscuous_mode (ether_param_t const control) { ether_promiscuous_t * p_arg; uint32_t channel_index = get_control_tbl_index((uint32_t)control.channel); p_arg = control.p_ether_promiscuous; promiscuous_mode[channel_index] = p_arg->bit; return ETHER_SUCCESS; } /* End of function ether_set_promiscuous_mode() */ /*********************************************************************************************************************** * Function Name: ether_set_int_handler * Description : Set the interrupt handler * Arguments : control - * Interrupt handler pointer. * If you would rather poll for finish then please input NULL for this argument. * Return Value : ETHER_SUCCESS - * Processing completed successfully * ETHER_ERR_INVALID_ARG - * Invalid argument ***********************************************************************************************************************/ static ether_return_t ether_set_int_handler (ether_param_t const control) { void (*pcb_int_hnd) (void *); ether_return_t ret = ETHER_ERR_INVALID_ARG; pcb_int_hnd = control.ether_int_hnd.pcb_int_hnd; if (NULL != pcb_int_hnd) { cb_func.pcb_int_hnd = pcb_int_hnd; ret = ETHER_SUCCESS; } return ret; } /* End of function ether_set_int_handler() */ /*********************************************************************************************************************** * Function Name: ether_power_on * Description : Turns on power to a ETHER channel. * Arguments : control - * Ethernet channel number * Return Value : ETHER_SUCCESS - * Processing completed successfully * ETHER_ERR_INVALID_CHAN - * Nonexistent channel number * ETHER_ERR_CHAN_OPEN - * Indicates the Ethernet cannot be opened because it is being used by another application * ETHER_ERR_INVALID_ARG - * Invalid argument ***********************************************************************************************************************/ static ether_return_t ether_power_on (ether_param_t const control) { uint32_t channel_index = get_control_tbl_index((uint32_t)control.channel); /* Set port connect */ ether_set_phy_mode(g_eth_control_ch[channel_index].port_connect); /* ETHERC/EDMAC Power on */ return power_on_control((uint32_t)control.channel); } /* End of function ether_power_on() */ /*********************************************************************************************************************** * Function Name: ether_power_off * Description : Turns on power to a ETHER channel. * Arguments : control - * Ethernet channel number * Return Value : ETHER_SUCCESS - * Processing completed successfully * ETHER_ERR_INVALID_ARG - * Invalid argument ***********************************************************************************************************************/ static ether_return_t ether_power_off (ether_param_t const control) { /* ETHERC/EDMAC Power off */ power_off_control((uint32_t)control.channel); return ETHER_SUCCESS; } /* End of function ether_power_off() */ /*********************************************************************************************************************** * Function Name: power_on * Description : Turns on power to a ETHER channel. * Arguments : channel - * ETHERC channel number * Return Value : ETHER_SUCCESS - * Processing completed successfully * ETHER_ERR_INVALID_CHAN - * Nonexistent channel number * ETHER_ERR_CHAN_OPEN - * Indicates the Ethernet cannot be opened because it is being used by another application ***********************************************************************************************************************/ static ether_return_t power_on (uint32_t channel) { volatile uint8_t dummy; #if (ETHER_CHANNEL_MAX == 1) (void)channel; #if (ETHER_CH0_EN == 1) CPG.STBCR6.BIT.MSTP65 = 0; CPG.STBCR6.BIT.MSTP62 = 0; dummy = CPG.STBCR6.BYTE; #else CPG.STBCR6.BIT.MSTP64 = 0; CPG.STBCR6.BIT.MSTP62 = 0; dummy = CPG.STBCR6.BYTE; #endif #else /* Check argument */ if (ETHER_CHANNEL_MAX <= channel) { /* Should never get here. Valid channel number is checked above. */ return ETHER_ERR_INVALID_CHAN; } if (ETHER_CHANNEL_0 == channel) { CPG.STBCR6.BIT.MSTP65 = 0; CPG.STBCR6.BIT.MSTP62 = 0; dummy = CPG.STBCR6.BYTE; } else { CPG.STBCR6.BIT.MSTP64 = 0; CPG.STBCR6.BIT.MSTP62 = 0; dummy = CPG.STBCR6.BYTE; } #endif (void)dummy; return ETHER_SUCCESS; } /* End of function power_on() */ /*********************************************************************************************************************** * Function Name: power_off * Description : Turns off power to a ETHER channel. * Arguments : channel - * ETHERC channel number * Return Value : none ***********************************************************************************************************************/ static void power_off (uint32_t channel) { volatile uint8_t dummy; #if (ETHER_CHANNEL_MAX == 1) (void)channel; #if (ETHER_CH0_EN == 1) CPG.STBCR6.BIT.MSTP65 = 1; dummy = CPG.STBCR6.BYTE; CPG.STBCR6.BIT.MSTP62 = 1; dummy = CPG.STBCR6.BYTE; #else CPG.STBCR6.BIT.MSTP64 = 1; dummy = CPG.STBCR6.BYTE; CPG.STBCR6.BIT.MSTP62 = 1; dummy = CPG.STBCR6.BYTE; #endif #else /* Check argument */ if (ETHER_CHANNEL_MAX <= channel) { /* Should never get here. Valid channel number is checked above. */ return; } if (ETHER_CHANNEL_0 == channel) { CPG.STBCR6.BIT.MSTP65 = 1; dummy = CPG.STBCR6.BYTE; if (CPG.STBCR6.BIT.MSTP64 == 1) { CPG.STBCR6.BIT.MSTP62 = 1; dummy = CPG.STBCR6.BYTE; } } else { CPG.STBCR6.BIT.MSTP64 = 1; dummy = CPG.STBCR6.BYTE; if (CPG.STBCR6.BIT.MSTP65 == 1) { CPG.STBCR6.BIT.MSTP62 = 1; dummy = CPG.STBCR6.BYTE; } } #endif (void)dummy; } /* End of function power_off() */ /*********************************************************************************************************************** * Function Name: ether_set_multicastframe_filter * Description : set multicast frame filtering function. * Arguments : control - * Ethernet channel number and Multicast Frame filter enable switch * Return Value : ETHER_SUCCESS - * Processing completed successfully * ETHER_ERR_INVALID_ARG - * Invalid argument * ETHER_ERR_RECV_ENABLE - * Receive function is enable. ***********************************************************************************************************************/ static ether_return_t ether_set_multicastframe_filter (ether_param_t const control) { ether_multicast_t * p_arg; ether_mc_filter_t flag; ether_return_t ret; volatile struct st_etherc * petherc_adr; uint32_t channel_index = get_control_tbl_index((uint32_t)control.channel); ret = ETHER_ERR_INVALID_ARG; p_arg = control.p_ether_multicast; flag = p_arg->flag; if ((ETHER_MC_FILTER_ON != flag) && (ETHER_MC_FILTER_OFF != flag)) { return ret; } petherc_adr = g_eth_control_ch[channel_index].petherc; /* Check receive function is enable in ETHERC */ if (0 == petherc_adr->ECMR.BIT.RE) { if (ETHER_MC_FILTER_ON == flag) { mc_filter_flag[channel_index] = ETHER_MC_FILTER_ON; } else { mc_filter_flag[channel_index] = ETHER_MC_FILTER_OFF; } ret = ETHER_SUCCESS; } else { ret = ETHER_ERR_RECV_ENABLE; } return ret; } /* End of function ether_set_multicastframe_filter() */ /*********************************************************************************************************************** * Function Name: ether_set_broadcastframe_filter * Description : set broadcast frame filtering function. * Arguments : control - * ETHERC channel number and receive count for continuous Broadcast Frame * Return Value : ETHER_SUCCESS - * Processing completed successfully * ETHER_ERR_INVALID_ARG - * Invalid argument * ETHER_ERR_RECV_ENABLE - * Receive function is enable. ***********************************************************************************************************************/ static ether_return_t ether_set_broadcastframe_filter (ether_param_t const control) { ether_broadcast_t * p_arg; uint32_t channel_index = get_control_tbl_index((uint32_t)control.channel); uint32_t counter; ether_return_t ret; volatile struct st_etherc * petherc_adr; ret = ETHER_ERR_INVALID_ARG; p_arg = control.p_ether_broadcast; counter = p_arg->counter; if (0 != (counter & 0x0FFFF0000)) { return ret; } petherc_adr = g_eth_control_ch[channel_index].petherc; /* Check receive function is enable in ETHERC */ if (0 == petherc_adr->ECMR.BIT.RE) { bc_filter_count[channel_index] = counter; ret = ETHER_SUCCESS; } else { ret = ETHER_ERR_RECV_ENABLE; } return ret; } /* End of function ether_set_broadcastframe_filter() */ /*********************************************************************************************************************** * Function Name: power_on_control * Description : Powers on the channel if the ETHEC channel used and the PHY access channel are different, or if the * PHY access channel is powered off. * Arguments : channel - * ETHERC channel number * Return Value : ETHER_SUCCESS - * Processing completed successfully * ETHER_ERR_INVALID_CHAN - * Nonexistent channel number * ETHER_ERR_CHAN_OPEN - * Indicates the Ethernet cannot be opened because it is being used by another application * : ETHER_ERR_OTHER - * ***********************************************************************************************************************/ static ether_return_t power_on_control (uint32_t channel) { uint32_t channel_index = get_control_tbl_index(channel); ether_return_t ret = ETHER_ERR_OTHER; etherc_edmac_power_cont[channel_index] = ETHER_MODULE_USE; ret = power_on(channel); return ret; } /* End of function power_on_control() */ /*********************************************************************************************************************** * Function Name: power_off_control * Description : Powers off the channel if the ETHEC channel used and the PHY access channel are different, or if the * PHY access channel is powered off. * Arguments : channel - * ETHERC channel number * Return Value : none ***********************************************************************************************************************/ static void power_off_control (uint32_t channel) { uint32_t channel_index = get_control_tbl_index(channel); etherc_edmac_power_cont[channel_index] = ETEHR_MODULE_NOT_USE; power_off(channel); } /* End of function power_off_control() */ /*********************************************************************************************************************** * Function Name: check_mpde_bit * Description : * Arguments : none * Return Value : 1: Magic Packet detection is enabled. * 0: Magic Packet detection is disabled. ***********************************************************************************************************************/ static uint8_t check_mpde_bit (void) { #if (ETHER_CHANNEL_MAX == 1) /* The MPDE bit can be referred to only when ETHERC operates. */ if ( (ETHER_MODULE_USE == etherc_edmac_power_cont[0]) #if (ETHER_CH0_EN == 1) && (1 == ETHERC0.ECMR.BIT.MPDE) #else && (1 == ETHERC1.ECMR.BIT.MPDE) #endif ) { return 1; } else { return 0; } #else /* The MPDE bit can be referred to only when ETHERC0 operates. */ if ( ( (ETHER_MODULE_USE == etherc_edmac_power_cont[ETHER_CHANNEL_0]) && (1 == ETHERC0.ECMR.BIT.MPDE) ) /* The MPDE bit can be referred to only when ETHERC1 operates. */ || ( (ETHER_MODULE_USE == etherc_edmac_power_cont[ETHER_CHANNEL_1]) && (1 == ETHERC1.ECMR.BIT.MPDE) ) ) { return 1; } else { return 0; } #endif } /* End of function check_mpde_bit() */ #if (ETHER_CH0_EN == 1) /*********************************************************************************************************************** * Function Name: ether_eint0 * Description : EINT0 interrupt processing (A callback function to be called from r_bsp.) * Arguments : pparam - * unused * Return Value : none ***********************************************************************************************************************/ static void ether_eint0 (void) { ether_int_common(ETHER_CHANNEL_0); } /* End of function ether_eint0() */ #endif #if (ETHER_CH1_EN == 1) /*********************************************************************************************************************** * Function Name: ether_eint1 * Description : EINT1 interrupt processing (A callback function to be called from r_bsp.) * Arguments : pparam - * unused * Return Value : none ***********************************************************************************************************************/ static void ether_eint1(void) { ether_int_common(ETHER_CHANNEL_1); } /* End of function ether_eint1() */ #endif /*********************************************************************************************************************** * Function Name: ether_int_common * Description : Interrupt handler for Ethernet receive and transmit interrupts. * Arguments : channel - * ETHERC channel number * Return Value : none ***********************************************************************************************************************/ static void ether_int_common (uint32_t channel) { uint32_t status_ecsr; uint32_t status_eesr; volatile struct st_etherc * petherc_adr; volatile struct st_edmac * pedmac_adr; ether_cb_arg_t cb_arg; uint32_t channel_index = get_control_tbl_index(channel); petherc_adr = g_eth_control_ch[channel_index].petherc; pedmac_adr = g_eth_control_ch[channel_index].pedmac; status_ecsr = petherc_adr->ECSR.LONG; status_eesr = pedmac_adr->EESR.LONG; /* Callback : Interrupt handler */ if (NULL != cb_func.pcb_int_hnd) { cb_arg.channel = channel; cb_arg.status_ecsr = status_ecsr; cb_arg.status_eesr = status_eesr; (*cb_func.pcb_int_hnd)((void *) &cb_arg); } /* When the ETHERC status interrupt is generated */ if (status_eesr & EMAC_ECI_INT) { #if (ETHER_CFG_USE_LINKSTA == 1) /* When the link signal change interrupt is generated */ if (EMAC_LCHNG_INT == (status_ecsr & EMAC_LCHNG_INT)) { /* The state of the link signal is confirmed and Link Up/Down is judged. */ /* When becoming Link up */ if (ETHER_CFG_LINK_PRESENT == petherc_adr->PSR.BIT.LMON) { lchng_flag[channel_index] = ETHER_FLAG_ON_LINK_ON; } /* When Link becomes down */ else { lchng_flag[channel_index] = ETHER_FLAG_ON_LINK_OFF; } } #endif /* When the Magic Packet detection interrupt is generated */ if (EMAC_MPD_INT == (status_ecsr & EMAC_MPD_INT)) { mpd_flag[channel_index] = ETHER_FLAG_ON; } /* * Because each bit of the ECSR register is cleared when one is written, * the value read from the register is written and the bit is cleared. */ /* Clear all ETHERC status BFR, PSRTO, LCHNG, MPD, ICD */ petherc_adr->ECSR.LONG = status_ecsr; } /* * Because each bit of the EESR register is cleared when one is written, * the value read from the register is written and the bit is cleared. */ pedmac_adr->EESR.LONG = status_eesr; /* Clear EDMAC status bits */ /* Whether it is a necessary code is confirmed. */ } /* End of function ether_int_common() */ /*********************************************************************************************************************** * Function Name: get_control_tbl_index * Description : get index of control table. * Arguments : channel - * ETHERC channel number * Return Value : Index of control table ***********************************************************************************************************************/ static uint32_t get_control_tbl_index (uint32_t channel) { #if (ETHER_CHANNEL_MAX == 1) return 0; #else return channel; #endif } /* End of function get_control_tbl_index() */