| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831 |
- /**
- * @file - sitaraif.c
- * lwIP Ethernet interface for Sitara Devices
- *
- */
- /**
- * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
- * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
- * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
- * OF SUCH DAMAGE.
- *
- * This file is part of the lwIP TCP/IP stack.
- *
- * Author: Adam Dunkels <adam@sics.se>
- *
- */
- /**
- * Copyright (c) 2010 Texas Instruments Incorporated
- *
- * This file is dervied from the "ethernetif.c" skeleton Ethernet network
- * interface driver for lwIP.
- *
- */
- #include "src/include/lwip/opt.h"
- #include "src/include/lwip/def.h"
- #include "src/include/lwip/mem.h"
- #include "src/include/lwip/pbuf.h"
- #include "src/include/lwip/sys.h"
- #include "src/include/lwip/stats.h"
- #include "src/include/lwip/snmp.h"
- #include "src/include/netif/etharp.h"
- #include "src/include/netif/ppp_oe.h"
- #include "src/include/lwip/err.h"
- #include "ports/am1808/include/netif/sitaraif.h"
- #include "ports/am1808/include/arch/cc.h"
- /* Sitara DriverLib Header Files required for this interface driver. */
- #include "hw_types.h"
- #include "emac.h"
- #include "mdio.h"
- #include "interrupt.h"
- #include "lan8710a.h"
- /* EMAC Control RAM size in bytes */
- #ifndef SIZE_EMAC_CTRL_RAM
- #define SIZE_EMAC_CTRL_RAM 0x2000
- #endif
- /* MDIO input and output frequencies in Hz */
- #define MDIO_FREQ_INPUT 75000000
- #define MDIO_FREQ_OUTPUT 1000000
- #define EMAC_BUF_DESC_OWNER 0x20000000
- #define EMAC_BUF_DESC_SOP 0x80000000
- #define EMAC_BUF_DESC_EOP 0x40000000
- #define EMAC_BUF_DESC_EOQ 0x10000000
- #define MAX_TRANSFER_UNIT 1500
- #define PBUF_LEN_MAX MAX_TRANSFER_UNIT
- /* Base Addresses */
- #define EMAC_CTRL_RAM_0_BASE 0x01E20000
- #define EMAC_0_BASE 0x01E23000
- #define EMAC_CTRL_0_BASE 0x01E22000
- #define MDIO_0_BASE 0x01E24000
- #define MAX_RX_PBUF_ALLOC 10
- #define MIN_PKT_LEN 60
- /* Define those to better describe the network interface. */
- #define IFNAME0 'e'
- #define IFNAME1 'n'
- /* EMAC TX Buffer descriptor data structure */
- struct emac_tx_bd {
- volatile struct emac_tx_bd *next;
- volatile u32_t bufptr;
- volatile u32_t bufoff_len;
- volatile u32_t flags_pktlen;
-
- /* helper to know which pbuf this tx bd corresponds to */
- volatile struct pbuf *pbuf;
- }emac_tx_bd;
- /* EMAC RX Buffer descriptor data structure */
- struct emac_rx_bd {
- volatile struct emac_rx_bd *next;
- volatile u32_t bufptr;
- volatile u32_t bufoff_len;
- volatile u32_t flags_pktlen;
- /* helper to know which pbuf this rx bd corresponds to */
- volatile struct pbuf *pbuf;
- }emac_rx_bd;
- /**
- * Helper struct to hold the data used to operate on a particular
- * receive channel
- */
- struct rxch {
- volatile struct emac_rx_bd *free_head;
- volatile struct emac_rx_bd *active_head;
- volatile struct emac_rx_bd *active_tail;
- u32_t freed_pbuf_len;
- }rxch;
- /**
- * Helper struct to hold the data used to operate on a particular
- * transmit channel
- */
- struct txch {
- volatile struct emac_tx_bd *free_head;
- volatile struct emac_tx_bd *active_tail;
- volatile struct emac_tx_bd *next_bd_to_process;
- }txch;
-
- /**
- * Helper struct to hold private data used to operate the ethernet interface.
- */
- struct sitaraif {
- /* emac instance number */
- u32_t inst_num;
- u8_t mac_addr[6];
- /* emac base address */
- u32_t emac_base;
- /* emac controller base address */
- volatile u32_t emac_ctrl_base;
- volatile u32_t emac_ctrl_ram;
- /* mdio base address */
- volatile u32_t mdio_base;
- /* phy parameters for this instance - for future use */
- u32_t phy_addr;
- u32_t (*phy_autoneg)(u32_t, u32_t, u16_t);
- u32_t (*phy_partnerability)(u32_t, u32_t, u16_t*);
-
- /* The tx/rx channels for the interface */
- struct txch txch;
- struct rxch rxch;
- }sitaraif;
- /* Defining interface for all the emac instances */
- static struct sitaraif sitaraif_data[MAX_EMAC_INSTANCE];
- /**
- * Function to set the MAC address to the interface
- * @param inst_num the instance number
- * @return none.
- */
- void
- sitaraif_macaddrset(u32_t inst_num, u8_t *mac_addr) {
- struct sitaraif *sitaraif;
- u32_t temp;
- sitaraif = &sitaraif_data[inst_num];
- /* set MAC hardware address */
- for(temp = 0; temp < ETHARP_HWADDR_LEN; temp++) {
- sitaraif->mac_addr[temp] = mac_addr[(ETHARP_HWADDR_LEN - 1) - temp];
- }
- }
- /**
- * Function to setup the instance parameters inside the interface
- * @param sitaraif
- * @return none.
- */
- static void
- sitaraif_inst_config(struct sitaraif *sitaraif) {
- if(sitaraif->inst_num == 0) {
- sitaraif->emac_base = EMAC_0_BASE;
- sitaraif->emac_ctrl_base = EMAC_CTRL_0_BASE;
- sitaraif->emac_ctrl_ram = EMAC_CTRL_RAM_0_BASE;
- sitaraif->mdio_base = MDIO_0_BASE;
- #if defined(lcdkOMAPL138) || defined(lcdkC6748)
- sitaraif->phy_addr = 7;
- #else
- sitaraif->phy_addr = 0;
- #endif
- sitaraif->phy_autoneg = Lan8710aAutoNegotiate;
- sitaraif->phy_partnerability = Lan8710aPartnerAbilityGet;
- }
- }
- /**
- * Function to setup the link. AutoNegotiates with the phy for link
- * setup and set the EMAC with the result of autonegotiation.
- * @param sitaraif
- * @return ERR_OK if everything passed
- * others if not passed
- */
- static err_t
- sitaraif_link_setup(struct sitaraif *sitaraif) {
- err_t linkstat = ERR_CONN;
- u16_t partnr_ablty;
- u32_t phyduplex = EMAC_DUPLEX_HALF;
- volatile unsigned int delay = 0xFFFFF;
- if(sitaraif->inst_num == 0) {
- if(Lan8710aAutoNegotiate(sitaraif->mdio_base, sitaraif->phy_addr,
- (LAN8710A_100BTX | LAN8710A_100BTX_FD
- | LAN8710A_10BT | LAN8710A_10BT_FD)) == TRUE) {
- linkstat = ERR_OK;
- Lan8710aPartnerAbilityGet(sitaraif->mdio_base, sitaraif->phy_addr,
- &partnr_ablty);
-
- /* Check for 100 Mbps and duplex capability */
- if(partnr_ablty & LAN8710A_100BTX_FD) {
- phyduplex = EMAC_DUPLEX_FULL;
- }
- }
- else {
- linkstat = ERR_CONN;
- }
- }
- else {
- linkstat = ERR_CONN;
- }
-
- /* Set the EMAC with the negotiation results if it is successful */
- if(linkstat == ERR_OK) {
- EMACDuplexSet(sitaraif->emac_base, phyduplex);
- }
- /* Wait for the MII to settle down */
- while(delay--);
- return linkstat;
- }
- /**
- * This function should do the actual transmission of the packet. The packet is
- * contained in the pbuf that is passed to the function. This pbuf might be
- * chained. That is, one pbuf can span more than one tx buffer descriptors
- *
- * @param sitaraif the network interface state for this ethernetif
- * @param pbuf the pbuf which is to be sent over EMAC
- * @return None
- */
- static void
- sitaraif_transmit(struct sitaraif *sitaraif, struct pbuf *pbuf) {
- struct pbuf *q;
- struct txch *txch;
- volatile struct emac_tx_bd *curr_bd, *active_head, *bd_end;
- txch = &(sitaraif->txch);
-
- /* Get the buffer descriptor which is free to transmit */
- curr_bd = txch->free_head;
-
- active_head = curr_bd;
-
- /* Update the total packet length */
- curr_bd->flags_pktlen &= ~0xFFFF;
- curr_bd->flags_pktlen |= pbuf->tot_len;
- /* Indicate the start of the packet */
- curr_bd->flags_pktlen |= (EMAC_BUF_DESC_SOP | EMAC_BUF_DESC_OWNER);
- /* Copy pbuf information into TX buffer descriptors */
- for(q = pbuf; q != NULL; q = q->next) {
- /* Intialize the buffer pointer and length */
- curr_bd->bufptr = (u32_t)(q->payload);
- curr_bd->bufoff_len = (q->len) & 0xFFFF;
- bd_end = curr_bd;
- curr_bd->pbuf = pbuf;
- curr_bd = curr_bd->next;
- }
- /* Indicate the end of the packet */
- bd_end->next = NULL;
- bd_end->flags_pktlen |= EMAC_BUF_DESC_EOP;
-
- txch->free_head = curr_bd;
-
- /* For the first time, write the HDP with the filled bd */
- if(txch->active_tail == NULL) {
- EMACTxHdrDescPtrWrite(sitaraif->emac_base, (unsigned int)(active_head), 0);
- }
-
- /*
- * Chain the bd's. If the DMA engine, already reached the end of the chain,
- * the EOQ will be set. In that case, the HDP shall be written again.
- */
- else {
- curr_bd = txch->active_tail;
- curr_bd->next = active_head;
- //while((curr_bd->flags_pktlen & EMAC_BUF_DESC_EOQ) != EMAC_BUF_DESC_EOQ);
- if(curr_bd->flags_pktlen & EMAC_BUF_DESC_EOQ) {
- /* Write the Header Descriptor Pointer and start DMA */
- EMACTxHdrDescPtrWrite(sitaraif->emac_base, (unsigned int)(active_head), 0);
- }
- }
- txch->active_tail = bd_end;
- }
- /**
- * This function will send a packet through the emac if the channel is
- * available. Otherwise, the packet will be queued in a pbuf queue.
- *
- * @param netif the lwip network interface structure for this ethernetif
- * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type)
- * @return ERR_OK if the packet could be sent
- * an err_t value if the packet couldn't be sent
- *
- */
- static err_t
- sitaraif_output(struct netif *netif, struct pbuf *p) {
- SYS_ARCH_DECL_PROTECT(lev);
- /**
- * This entire function must run within a "critical section" to preserve
- * the integrity of the transmit pbuf queue.
- *
- */
- SYS_ARCH_PROTECT(lev);
- /* adjust the packet length if less than minimum required */
- if(p->tot_len < MIN_PKT_LEN) {
- p->tot_len = MIN_PKT_LEN;
- p->len = MIN_PKT_LEN;
- }
- /**
- * Bump the reference count on the pbuf to prevent it from being
- * freed till we are done with it.
- *
- */
- pbuf_ref(p);
-
- /* call the actual transmit function */
- sitaraif_transmit(netif->state, p);
- /* Return to prior interrupt state and return. */
- SYS_ARCH_UNPROTECT(lev);
-
- return ERR_OK;
- }
- /**
- * In this function, the hardware should be initialized.
- * Called from sitaraif_init().
- *
- * @param netif the already initialized lwip network interface structure
- * for this ethernetif
- */
- static err_t
- sitaraif_hw_init(struct netif *netif)
- {
- u32_t temp, channel;
- u32_t num_bd, pbuf_cnt = 0;
- #if defined(lcdkOMAPL138) || defined(lcdkC6748)
- volatile u32_t delay = 0xfffff;
- #else
- volatile u32_t delay = 0xfff;
- #endif
- volatile struct emac_tx_bd *curr_txbd, *last_txbd;
- volatile struct emac_rx_bd *curr_bd, *last_bd;
- struct sitaraif *sitaraif;
- struct txch *txch;
- struct rxch *rxch;
- struct pbuf *p, *q;
- sitaraif = netif->state;
- /* set MAC hardware address length */
- netif->hwaddr_len = ETHARP_HWADDR_LEN;
- /* set MAC hardware address */
- for(temp = 0; temp < ETHARP_HWADDR_LEN; temp++) {
- netif->hwaddr[temp] = sitaraif->mac_addr[(ETHARP_HWADDR_LEN - 1) - temp];
- }
- /* maximum transfer unit */
- netif->mtu = MAX_TRANSFER_UNIT;
- /* device capabilities */
- /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */
- netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;
- EMACInit(sitaraif->emac_ctrl_base, sitaraif->emac_base);
- MDIOInit(sitaraif->mdio_base, MDIO_FREQ_INPUT, MDIO_FREQ_OUTPUT);
- while(delay--);
-
- EMACRxBroadCastEnable(sitaraif->emac_base, 0);
- /* Set the MAC Addresses in EMAC hardware */
- EMACMACSrcAddrSet(sitaraif->emac_base, sitaraif->mac_addr);
-
- for(channel = 0; channel < 8; channel++) {
- EMACMACAddrSet(sitaraif->emac_base, channel, sitaraif->mac_addr, EMAC_MACADDR_MATCH);
- }
- if(!((MDIOPhyAliveStatusGet(sitaraif->mdio_base)
- >> sitaraif->phy_addr) & 0x01 )) {
- return ERR_CONN;
- }
- if(!Lan8710aLinkStatusGet(sitaraif->mdio_base, sitaraif->phy_addr, 10000)) {
- return ERR_CONN;
- }
- if(sitaraif_link_setup(sitaraif) != ERR_OK) {
- return ERR_CONN;
- }
- txch = &(sitaraif->txch);
- /**
- * Initialize the Descriptor Memory For TX and RX
- * Only Channel 0 is supported for both TX and RX
- */
- txch->free_head = (volatile struct emac_tx_bd*)(sitaraif->emac_ctrl_ram);
- txch->next_bd_to_process = txch->free_head;
- txch->active_tail = NULL;
-
- /* Set the number of descriptors for the channel */
- num_bd = (SIZE_EMAC_CTRL_RAM >> 1) / sizeof(emac_tx_bd);
-
- curr_txbd = txch->free_head;
- /* Initialize all the TX buffer Descriptors */
- while(num_bd--) {
- curr_txbd->next = curr_txbd + 1;
- curr_txbd->flags_pktlen = 0;
- last_txbd = curr_txbd;
- curr_txbd = curr_txbd->next;
- }
- last_txbd->next = txch->free_head;
-
- /* Initialize the descriptors for the RX channel */
- rxch = &(sitaraif->rxch);
- rxch->active_head = (volatile struct emac_rx_bd*)(curr_txbd + 1);
-
- rxch->free_head = NULL;
- rxch->freed_pbuf_len = 0;
- num_bd = ((SIZE_EMAC_CTRL_RAM >> 1) / sizeof(emac_rx_bd) - 1);
- curr_bd = rxch->active_head;
- last_bd = curr_bd;
- /*
- ** Allocate the pbufs for the maximum count permitted or till the
- ** number of buffer desceriptors expire, which ever is earlier.
- */
- while(pbuf_cnt < MAX_RX_PBUF_ALLOC) {
- p = pbuf_alloc(PBUF_RAW, PBUF_LEN_MAX, PBUF_POOL);
- pbuf_cnt++;
-
- if(p != NULL) {
- /* write the descriptors if there are enough numbers to hold the pbuf*/
- if(((u32_t)pbuf_clen(p)) <= num_bd) {
- for(q = p; q != NULL; q = q->next) {
- curr_bd->bufptr = (u32_t)(q->payload);
- curr_bd->bufoff_len = q->len;
- curr_bd->next = curr_bd + 1;
- curr_bd->flags_pktlen = EMAC_BUF_DESC_OWNER;
-
- /* Save the pbuf */
- curr_bd->pbuf = q;
- last_bd = curr_bd;
- curr_bd = curr_bd->next;
- num_bd--;
- }
- }
-
- /* free the allocated pbuf if no free descriptors are left */
- else {
- pbuf_free(p);
- break;
- }
- }
- else {
- break;
- }
- }
- last_bd->next = NULL;
- rxch->active_tail = last_bd;
- /* Acknowledge receive and transmit interrupts for proper interrupt pulsing*/
- EMACCoreIntAck(sitaraif->emac_base, EMAC_INT_CORE0_RX);
- EMACCoreIntAck(sitaraif->emac_base, EMAC_INT_CORE0_TX);
-
- EMACRxUnicastSet(sitaraif->emac_base, 0);
- EMACNumFreeBufSet(sitaraif->emac_base, 0, 10);
- EMACTxEnable(sitaraif->emac_base);
- EMACRxEnable(sitaraif->emac_base);
- /* Write the RX HDP for channel 0 */
- EMACRxHdrDescPtrWrite(sitaraif->emac_base, (u32_t)rxch->active_head, 0);
-
- EMACMIIEnable(sitaraif->emac_base);
-
- /**
- * Enable the Transmission and reception, enable the interrupts for
- * channel 0 and for control core 0
- */
- EMACTxIntPulseEnable(sitaraif->emac_base, sitaraif->emac_ctrl_base, 0, 0);
- EMACRxIntPulseEnable(sitaraif->emac_base, sitaraif->emac_ctrl_base, 0, 0);
- return ERR_OK;
- }
- /**
- * Should be called at the beginning of the program to set up the
- * network interface. It calls the function sitaraif_hw_init() to do the
- * low level initializations.
- *
- * @param netif the lwip network interface structure for this ethernetif
- * @return ERR_OK if the loopif is initialized
- * ERR_MEM if private data couldn't be allocated
- * any other err_t on error
- */
- err_t
- sitaraif_init(struct netif *netif)
- {
- /* Get the instance number first */
- unsigned int inst_num = *(unsigned int*)(netif->state);
- struct sitaraif *sitaraif;
- #if LWIP_NETIF_HOSTNAME
- /* Initialize interface hostname */
- netif->hostname = "lwip";
- #endif /* LWIP_NETIF_HOSTNAME */
- sitaraif = &sitaraif_data[inst_num];
-
- netif->state = sitaraif;
-
- /*
- * Initialize the snmp variables and counters inside the struct netif.
- * The last argument should be replaced with your link speed, in units
- * of bits per second.
- */
- NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, 10000000);
- sitaraif->inst_num = inst_num;
- netif->name[0] = IFNAME0;
- netif->name[1] = IFNAME1;
- netif->num = (u8_t)inst_num;
- /* We directly use etharp_output() here to save a function call.
- * You can instead declare your own function an call etharp_output()
- * from it if you have to do some checks before sending (e.g. if link
- * is available...)
- */
- netif->output = etharp_output;
- netif->linkoutput = sitaraif_output;
- /* initialize the hardware */
- sitaraif_inst_config(sitaraif);
- return (sitaraif_hw_init(netif));
- }
- /**
- * Handler for Receive interrupt. Packet processing is done in this
- * interrupt handler itself.
- *
- * @param netif the lwip network interface structure for this ethernetif
- * @return none
- */
- void
- sitaraif_rx_inthandler(struct netif *netif) {
- struct sitaraif *sitaraif;
- struct rxch *rxch;
- volatile struct emac_rx_bd *curr_bd, *processed_bd, *curr_tail, *last_bd;
- volatile struct pbuf *pbuf, *q, *new_pbuf;
- u32_t ex_len = 0, len_to_alloc = 0;
- u16_t tot_len;
-
- sitaraif = netif->state;
- rxch = &(sitaraif->rxch);
- /* Get the bd which contains the earliest filled data */
- curr_bd = rxch->active_head;
- last_bd = rxch->active_tail;
-
- /**
- * Process the descriptors as long as data is available
- * when the DMA is receiving data, SOP flag will be set
- */
- while(curr_bd->flags_pktlen & EMAC_BUF_DESC_SOP) {
- ex_len = 0;
- len_to_alloc = 0;
- /* Start processing once the packet is loaded */
- if((curr_bd->flags_pktlen & EMAC_BUF_DESC_OWNER)
- != EMAC_BUF_DESC_OWNER) {
-
- if(rxch->free_head == NULL) {
- /* this bd chain will be freed after processing */
- rxch->free_head = curr_bd;
- }
-
- /* Get the total length of the packet. curr_bd points to the start
- * of the packet.
- */
- tot_len = (curr_bd->flags_pktlen) & 0xFFFF;
- /* Get the start of the pbuf queue */
- q = curr_bd->pbuf;
-
- do {
- /* Get the pbuf pointer which is associated with the current bd */
- pbuf = curr_bd->pbuf;
-
- /* If the earlier pbuf ended, update the chain */
- if(pbuf->next == NULL) {
- pbuf->next = (struct pbuf*)(curr_bd->next)->pbuf;
- }
-
- len_to_alloc += pbuf->len;
- /* Update the len and tot_len fields for the pbuf in the chain*/
- pbuf->len = (curr_bd->bufoff_len) & 0xFFFF;
- pbuf->tot_len = tot_len - ex_len ;
- processed_bd = curr_bd;
- ex_len += pbuf->len;
- curr_bd = curr_bd->next;
- } while((processed_bd->flags_pktlen & EMAC_BUF_DESC_EOP)
- != EMAC_BUF_DESC_EOP);
- /**
- * Close the chain for this pbuf. A full packet is received in
- * this pbuf chain. Now this pbuf can be given to upper layers for
- * processing. The start of the pbuf chain is now 'q'.
- */
- pbuf->next = NULL;
-
- /* Adjust the link statistics */
- LINK_STATS_INC(link.recv);
- /* Process the packet */
- if(ethernet_input((struct pbuf *)q, netif) != ERR_OK) {
- /* Adjust the link statistics */
- LINK_STATS_INC(link.memerr);
- LINK_STATS_INC(link.drop);
- }
- /* Acknowledge that this packet is processed */
- EMACRxCPWrite(sitaraif->emac_base, 0, (unsigned int)processed_bd);
- rxch->active_head = curr_bd;
-
- /**
- * The earlier pbuf chain is freed from the upper layer. So, we need to
- * allocate a new pbuf chain and update the descriptors with the pbuf info.
- * To support chaining, the total length freed by the upper layer is tracked.
- * Care should be taken even if the allocation fails.
- */
- /**
- * now len_to_alloc will contain the length of the pbuf which was freed
- * from the upper layer
- */
- rxch->freed_pbuf_len += len_to_alloc;
- new_pbuf = pbuf_alloc(PBUF_RAW, (rxch->freed_pbuf_len), PBUF_POOL);
- /* Write the descriptors with the pbuf info till either of them expires */
- if(new_pbuf != NULL) {
- curr_bd = rxch->free_head;
- for(q = new_pbuf; (q != NULL) && (curr_bd != rxch->active_head); q = q->next) {
- curr_bd->bufptr = (u32_t)(q->payload);
-
- /* no support for buf_offset. RXBUFFEROFFEST register is 0 */
- curr_bd->bufoff_len = (q->len) & 0xFFFF;
- curr_bd->flags_pktlen = EMAC_BUF_DESC_OWNER;
-
- rxch->freed_pbuf_len -= q->len;
-
- /* Save the pbuf */
- curr_bd->pbuf = q;
- last_bd = curr_bd;
- curr_bd = curr_bd->next;
- }
-
- /**
- * At this point either pbuf expired or no rxbd to allocate. If
- * there are no, enough rx bds to allocate all pbufs in the chain,
- * free the rest of the pbuf
- */
- if(q != NULL) {
- pbuf_free((struct pbuf *)q);
- }
-
- curr_tail = rxch->active_tail;
- last_bd->next = NULL;
-
- curr_tail->next = rxch->free_head;
-
- /**
- * Check if the reception has ended. If the EOQ flag is set, the NULL
- * Pointer is taken by the DMA engine. So we need to write the RX HDP
- * with the next descriptor.
- */
- if(curr_tail->flags_pktlen & EMAC_BUF_DESC_EOQ) {
- EMACRxHdrDescPtrWrite(sitaraif->emac_base, (u32_t)(rxch->free_head), 0);
- }
- rxch->free_head = curr_bd;
- rxch->active_tail = last_bd;
- }
- }
- curr_bd = rxch->active_head;
- }
- EMACCoreIntAck(sitaraif->emac_base, EMAC_INT_CORE0_RX);
- EMACCoreIntAck(sitaraif->emac_base, EMAC_INT_CORE0_TX);
- }
- /**
- * Handler for EMAC Transmit interrupt
- *
- * @param netif the lwip network interface structure for this ethernetif
- * @return none
- */
- void
- sitaraif_tx_inthandler(struct netif *netif) {
- struct txch *txch;
- struct sitaraif *sitaraif;
- volatile struct emac_tx_bd *curr_bd, *next_bd_to_process;
- sitaraif = netif->state;
- txch = &(sitaraif->txch);
-
- next_bd_to_process = txch->next_bd_to_process;
-
- curr_bd = next_bd_to_process;
- /* Check for correct start of packet */
- while((curr_bd->flags_pktlen) & EMAC_BUF_DESC_SOP) {
-
- /* Make sure that the transmission is over */
- while((curr_bd->flags_pktlen & EMAC_BUF_DESC_OWNER)
- == EMAC_BUF_DESC_OWNER);
- /* Traverse till the end of packet is reached */
- while(((curr_bd->flags_pktlen) & EMAC_BUF_DESC_EOP) != EMAC_BUF_DESC_EOP) {
- curr_bd = curr_bd->next;
- }
-
- next_bd_to_process->flags_pktlen &= ~(EMAC_BUF_DESC_SOP);
- curr_bd->flags_pktlen &= ~(EMAC_BUF_DESC_EOP);
- /**
- * If there are no more data transmitted, the next interrupt
- * shall happen with the pbuf associated with the free_head
- */
- if(curr_bd->next == NULL) {
- txch->next_bd_to_process = txch->free_head;
- }
-
- else {
- txch->next_bd_to_process = curr_bd->next;
- }
-
- /* Acknowledge the EMAC and free the corresponding pbuf */
- EMACTxCPWrite(sitaraif->emac_base, 0, (u32_t)curr_bd);
- pbuf_free((struct pbuf *)curr_bd->pbuf);
- LINK_STATS_INC(link.xmit);
-
- next_bd_to_process = txch->next_bd_to_process;
- curr_bd = next_bd_to_process;
- }
- EMACCoreIntAck(sitaraif->emac_base, EMAC_INT_CORE0_RX);
- EMACCoreIntAck(sitaraif->emac_base, EMAC_INT_CORE0_TX);
- }
- /**
- * Gets the netif status
- *
- * @param the netif whoes status to be checked
- * @return the status
- */
- u32_t
- sitaraif_netif_status(struct netif *netif) {
- return (netif_is_up(netif));
- }
- /**
- * returns the link status
- *
- * @param the netif whoes link to be checked
- * @return the status
- */
- u32_t
- sitaraif_link_status(struct netif *netif) {
- struct sitaraif *sitaraif = netif->state;
- return (Lan8710aLinkStatusGet(sitaraif->mdio_base,
- sitaraif->phy_addr,
- 10000));
- }
|