2 * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
19 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
21 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
24 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
27 * This file is part of the lwIP TCP/IP stack.
29 * Author: Adam Dunkels <adam@sics.se>
34 * Copyright (c) 2010 Texas Instruments Incorporated
36 * This file is dervied from the "ethernetif.c" skeleton Ethernet network
37 * interface driver for lwIP.
40 /* Copyright (C) 2013 Czech Technical University in Prague
43 * - Carlos Jenkins <carlos@jenkins.co.cr>
45 * - Jan Doležal <pm.jenik@gmail.com>
47 * This program is free software; you can redistribute it and/or modify
48 * it under the terms of the GNU General Public License as published by
49 * the Free Software Foundation; either version 2 of the License, or
50 * (at your option) any later version.
52 * This program is distributed in the hope that it will be useful,
53 * but WITHOUT ANY WARRANTY; without even the implied warranty of
54 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
55 * GNU General Public License for more details.
57 * You should have received a copy of the GNU General Public License
58 * along with this program. If not, see <http://www.gnu.org/licenses/>.
62 * Ethernet Communication RPP API implementation file. Using one PHY.
66 * RPP API documentation.
70 #include "lwip/init.h"
71 #include "lwip/timers.h" /* for DHCP binding in NO_SYS mode */
72 #include "lwip/sys.h" /* includes - lwip/opt.h, lwip/err.h, arch/sys_arch.h */
73 #include "lwip/tcpip.h" /* includes - lwip/opt.h, lwip/api_msg.h, lwip/netifapi.h, lwip/pbuf.h, lwip/api.h, lwip/sys.h, lwip/timers.h, lwip/netif.h */
74 #include "lwip/stats.h" /* includes - lwip/mem.h, lwip/memp.h, lwip/opt.h */
75 #include "netif/etharp.h" /* includes - lwip/ip.h, lwip/netif.h, lwip/ip_addr.h, lwip/pbuf.h */
77 #include "lwip/snmp.h"
78 #include "lwip/dhcp.h"
79 #include "lwip/autoip.h"
80 #include "netif/ppp_oe.h"
81 /* end - lwIP headers */
85 #include "sys/sys.h" /* includes - sys/phy_dp83848h.h */
91 #if rppCONFIG_INCLUDE_ETH == 1
95 /* Number of EMAC Instances */
96 #define MAX_EMAC_INSTANCE 1
98 #define DEFAULT_PHY_ADDR 0x1
99 #define FIND_FIRST_PHY_ALIVE 1 /* or use default (phy_address: 1) */
100 #define NUM_OF_PHYs 32
101 #define SIZE_OF_DESC 16 /* in bytes */
102 #define CHANNEL 0 /* channel number for everything - for rx, tx, unicast, broadcast or damaged frames ; there are different channels for rx and tx operations */
104 #define MAX_TRANSFER_UNIT 1500 /* take in account oversized frames */
105 #define PBUF_LEN_MAX MAX_TRANSFER_UNIT
106 #define MAX_RX_PBUF_ALLOC 10
107 #define MIN_PKT_LEN 60
109 /* Define those to better describe the network interface. */
114 /* Defining interface for all the emac instances */
115 static struct hdkif hdkif_data[MAX_EMAC_INSTANCE];
118 ** The lwIP network interface structure for the HDK Ethernet MAC.
120 static struct netif hdkNetIF[MAX_EMAC_INSTANCE];
122 /* rpp startup init indicator */
123 static boolean_t initialized = FALSE, postInitialized = FALSE;
125 boolean_t sendDone = TRUE;
127 /* free pbuf notification */
129 xSemaphoreHandle pbufFreed;
132 /**********************************************testing functions**********************************************/
134 uint32_t rpp_eth_phylinkstat(uint32_t instNum)
136 struct hdkif *hdkif = &hdkif_data[instNum];
137 return PHY_link_status_get(hdkif->mdio_base, hdkif->phy_addr, 1);
140 #define BYTE_BUFF_SIZE 2
141 #define OFFSET_MAC_LETTERS (MAC_BIG_LETTERS ? 'A' : 'a')
142 /* puts string of MAC address assigned to EMAC instance reffered by instNum into *mac */
143 void rpp_eth_get_macAddrStr(uint32_t instNum, uint8_t *macStr)
145 uint8_t index, outindex = 0;
146 char buff[BYTE_BUFF_SIZE];
147 struct hdkif *hdkif = &hdkif_data[instNum];
148 for(index = 0; index < MAC_ADDR_LEN; index++) {
149 if(index)macStr[outindex++] = ':';
150 buff[0] = (hdkif->mac_addr[(MAC_ADDR_LEN - 1) - index] >> 4);
151 buff[1] = (hdkif->mac_addr[(MAC_ADDR_LEN - 1) - index] & 0xf);
152 macStr[outindex++] = (buff[0]<10) ? (buff[0] + '0') : (buff[0] - '\012' + OFFSET_MAC_LETTERS);
153 macStr[outindex++] = (buff[1]<10) ? (buff[1] + '0') : (buff[1] - '\012' + OFFSET_MAC_LETTERS);
155 macStr[outindex] = '\0';
158 /* @param ip will be filled accroding to content of ipstr */
159 err_t rpp_eth_stringToIP(ip_addr_t * ip, uint8_t * ipstr)
161 uint8_t charProccessed, index = 0, dotindex = 0xff, tmp = 0, dots = 0, fldEdit = 0;
163 for(charProccessed = ipstr[index]; (charProccessed >= '0' && charProccessed <= '9') || charProccessed == '.' ; charProccessed = ipstr[++index])
165 if(charProccessed == '.')
167 if(++dotindex == index)
174 ipaddr = (ipaddr << 8) + tmp;
185 tmp = tmp*10 + charProccessed - '0';
188 if(dots != 3 || !fldEdit)
190 /* if unsuccesful, don't modify previous content */
193 ipaddr = (ipaddr << 8) + tmp;
198 /* returns number in range 0-65535 where 0 is error */
199 uint16_t rpp_eth_portStrToInt(uint8_t *string)
203 for(index = 0;string[index] != '\0';index++)
205 if(string[index] < '0' || string[index] > '9')
210 portNO = portNO * 10 + string[index] - '0';
215 struct netif *rpp_eth_get_netif(uint32_t instNum)
217 return &hdkNetIF[instNum];
220 /********************************************** forward declares **********************************************/
223 * interface initializes
225 err_t rpp_eth_lwip_init(struct netif *netif);
228 * Initializes hw such as PHY, MDIO, EMAC, EMAC control module
230 * @return SUCCESS if initialization successful.\n
231 * FAILURE if initialization not successful.
233 err_t rpp_eth_hw_init(struct hdkif *hdkif);
236 * Initializes hw, after lwIP was initialized and
237 * OS was initialized in case OS is used.
239 err_t rpp_eth_hw_init_postInit(struct netif *netif);
241 /********************************************** utility functions **********************************************/
244 * Function to set the MAC address to the interface
245 * @param inst_num the instance number
247 * @note mac_addr[0] is considered MSB
250 hdkif_macaddrset(u32_t inst_num, u8_t *mac_addr) {
254 hdkif = &hdkif_data[inst_num];
256 /* set MAC hardware address */
257 for(temp = 0; temp < MAC_ADDR_LEN; temp++) {
258 hdkif->mac_addr[temp] = mac_addr[(MAC_ADDR_LEN - 1) - temp];
262 rpp_eth_get_macAddrStr(inst_num, macStr);
263 rpp_debug_printf("Setting MAC... %s\r\n", macStr);
268 * Function to setup the instance parameters inside the interface
273 hdkif_inst_config(struct hdkif *hdkif) {
274 if(hdkif->inst_num == 0)
276 hdkif->emac_base = EMAC_BASE_m(0);
277 hdkif->emac_ctrl_base = EMAC_CTRL_BASE_m(0);
278 hdkif->emac_ctrl_ram = EMAC_CTRL_RAM_BASE_m(0);
279 hdkif->mdio_base = MDIO_BASE_m(0);
280 hdkif->phy_addr = DEFAULT_PHY_ADDR; /* Default address of PHY on "MDIO bus" (depends on PHY hw configuration) */
281 hdkif->phy_autoneg = PHY_auto_negotiate;
282 hdkif->phy_autoneg_start = PHY_start_auto_negotiate;
283 hdkif->phy_autoneg_is_done = PHY_is_done_auto_negotiate;
284 hdkif->phy_partnerability = PHY_partner_ability_get;
288 /********************************************** initializing functions **********************************************/
290 int8_t rpp_eth_init()
293 int8_t retVal = SUCCESS;
298 /* config of EMAC instances and other stuff */
299 for(instNum = 0; instNum < MAX_EMAC_INSTANCE; instNum++)
301 hdkif_data[instNum].inst_num = instNum;
302 hdkif_inst_config(&hdkif_data[instNum]); /* hdkif_inst_config must contain instNum specific settings */
303 if(retVal = rpp_eth_hw_init(&hdkif_data[instNum]))
306 rpp_sci_printk("rpp_eth_hw_init: %d", retVal);
312 /* when one of instances was not initialized correctly return FAILURE without setting initialized variable to TRUE */
313 if(retVal)return FAILURE;
326 int8_t rpp_eth_init_postInit(uint32_t instNum, uint8_t *macArray)
328 if(postInitialized) {
331 int8_t retVal = SUCCESS;
332 struct netif *netif = &hdkNetIF[instNum];
333 u8_t mac_addr[MAC_ADDR_LEN] = RPP_MAC_ADDR;
335 /* ----- lwIP stuff ----- */
336 struct ip_addr ip_addr;
337 struct ip_addr net_mask;
338 struct ip_addr gw_addr;
339 volatile unsigned int dhcpBindWait = 0x3FFFFFFF;
343 macArray = mac_addr; /* use default MAC */
345 hdkif_macaddrset(instNum, macArray);
351 /* this can be called only within post OS init */
352 tcpip_init(NULL,NULL); /* calls lwip_init() implicitly, starts lwIP task (thread), when started function given to tcpip_init is executed first */
355 #if STATIC_IP_ADDRESS
356 ip_addr.addr = htonl(RPP_IP_ADDR);
357 net_mask.addr = htonl(RPP_NETMASK);
358 gw_addr.addr = htonl(RPP_GW);
359 #else /* STATIC_IP_ADDRESS */
363 #endif /* STATIC_IP_ADDRESS */
365 /* init and add new netif */
366 /* add new network interface to lwIP list of ifaces and initialize netif with specific function */
368 if( netif_add(netif, &ip_addr, &net_mask, &gw_addr, (void *) instNum, rpp_eth_lwip_init, ethernet_input) == NULL )
370 if( netif_add(netif, &ip_addr, &net_mask, &gw_addr, (void *) instNum, rpp_eth_lwip_init, tcpip_input) == NULL )
373 return NETIF_ADD_ERR;
376 netif_set_default(netif);
378 hdkif = (struct hdkif *) netif->state;
380 /* ----- freeRTOS elements ----- */
381 /* semaphore blocking receive task (rpp_eth_recv_raw) from receive operation, till RX interrupt occurs and notify it */
382 vSemaphoreCreateBinary(hdkif->goRX);
383 vSemaphoreCreateBinary(hdkif->goTX);
384 /* create semaphore notificating that pbuf was freed */
385 vSemaphoreCreateBinary(pbufFreed);
386 /* run task rpp_eth_recv_raw */
387 xTaskCreate( rpp_eth_recv_raw, "RXHandler", 200, netif, 0, NULL );
388 /* ----- end - freeRTOS ----- */
391 /* if we don't use link int change, then it must be done here */
392 #if !PHY_LINK_MONITOR_INT
393 if(rpp_eth_phylinkstat(hdkif->inst_num))
395 rpp_debug_printf((const char *)"cable connected ... setting IP params\r\n");
396 #if STATIC_IP_ADDRESS
398 #elif LWIP_DHCP /* STATIC_IP_ADDRESS-LWIP_DHCP */
399 if(dhcp_start(netif) != ERR_OK)
401 rpp_debug_printf("dhcp mem err\r\n");
404 rpp_debug_printf("binding DHCP\r");
405 while((netif->dhcp->state != DHCP_BOUND) && (dhcpBindWait--))/*sys_check_timeouts()*/;
407 rpp_debug_printf("dhcp binding timeout...\r\n");
408 #else /* LWIP_DHCP-LWIP_AUTOIP FIXME: there should be some kind of waiting till ip is assigned */
410 #endif /* STATIC_IP_ADDRESS-LWIP_DHCP-LWIP_AUTOIP */
412 uint8_t ipString[16];
413 rpp_eth_getIPDecimalStr(netif->ip_addr, ipString);
414 rpp_debug_printf("Address: %s\r\n", ipString);
415 rpp_eth_getIPDecimalStr(netif->netmask, ipString);
416 rpp_debug_printf("Netmask: %s\r\n", ipString);
417 rpp_eth_getIPDecimalStr(netif->gw, ipString);
418 rpp_debug_printf("Gateway: %s\r\n", ipString);
423 rpp_debug_printf((const char *)"cable not connected\r\n");
424 retVal = PHY_LINK_DOWN;
427 #else /* !PHY_LINK_MONITOR_INT */
428 /* now when we established environment needed for phy link status change we can allow it */
429 /* set PHY number which is monitored for link changes in MDIO and enable interrupt */
430 HWREG(hdkif->mdio_base + MDIO_USERPHYSEL0) = ((hdkif->phy_addr && 0x1f) | MDIO_USERPHYSEL0_LINKINTENB);
432 /* enable MISC interrupt - link monitoring in EMAC controle module */
433 HWREG(hdkif->emac_ctrl_base + EMAC_CTRL_CnMISCEN(0)) |= EMAC_CTRL_MISC_LINKINT0ENB;
435 #endif /* !PHY_LINK_MONITOR_INT */
436 /* ----- end - lwIP stuff ----- */
438 postInitialized = TRUE;
442 err_t rpp_eth_lwip_init(struct netif *netif)
444 #if LWIP_NETIF_HOSTNAME
445 /* Initialize interface hostname */
446 netif->hostname = "rpp";
447 #endif /* LWIP_NETIF_HOSTNAME */
449 uint32_t instNum = (uint32_t)netif->state;
450 /*netif->num = instNum; - auto-initiated when netif_add is called */
452 /* netif->state contained instNum, we replace it with corresponding hdkif */
453 struct hdkif *hdkif = &hdkif_data[instNum];
454 netif->state = hdkif;
456 netif->name[0] = IFNAME0;
457 netif->name[1] = IFNAME1;
460 hdkif->waitTicksForPHYAneg = TICKS_PHY_AUTONEG;
464 * Initialize the snmp variables and counters inside the struct netif.
465 * The last argument should be replaced with your link speed, in units
466 * of bits per second.
468 NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, 10000000);
470 /* We directly use etharp_output() here to save a function call.
471 * You can instead declare yo_SKIP_TO_HWur own function an call etharp_output()
472 * from it if you have to do some checks before sending (e.g. if link
475 netif->output = etharp_output;
476 netif->linkoutput = rpp_eth_send;
477 return rpp_eth_hw_init_postInit(netif);
480 #define INIT_ONLY_AFTER_RESET 1
481 err_t rpp_eth_hw_init(struct hdkif *hdkif)
487 /* Deactivate reset pin of PHY */
488 /* for hw reset of PHY, it is necessary that PIN_NAME_ETHRST is 1us logical low state, before putting it to logical high */
489 #if !INIT_ONLY_AFTER_RESET
491 uint8_t index = 80; /* Initially used to hw reset of PHY connected to GIO pin. This means 1us - for 80MHz clock. */
493 uint8_t index = configCPU_CLOCK_HZ/1000000; /* Initially used to hw reset of PHY connected to GIO pin 'rpp project only'; 1us - according to PHY specification. */
495 hal_gpio_pin_set_value(*hal_gpio_pin_get_dsc(PIN_NAME_ETHRST,-1),0);
497 #endif /* !INIT_ONLY_AFTER_RESET */
498 /* we have pull-down resistor, so after reset, we only need to put ETHRST pin to log. high */
499 hal_gpio_pin_set_value(*hal_gpio_pin_get_dsc(PIN_NAME_ETHRST,-1),1);
501 /* initializes EMAC control module and EMAC module */
502 EMACInit(hdkif->emac_ctrl_base, hdkif->emac_base);
503 /* initializes MDIO module (reset) */
504 MDIOInit(hdkif->mdio_base, 0x0, 0x0);
506 /* enable used receive channel if necessary */
509 /* try to read random register from defaultPhy to make MDIO fill alive bit for this one if it returned
510 ACK bit in msg response - this must be done, because MDIO has not set alive bit of PHY after that
511 short time after MDIOInit() */
512 MDIOPhyRegRead(hdkif->mdio_base, hdkif->phy_addr, PHY_BMSR, ®Content);
514 /* find first alive PHY - or use default if alive */
515 physAlive = MDIOPhyAliveStatusGet(hdkif->mdio_base);
516 if(!(physAlive & (1 << hdkif->phy_addr)))
518 #if FIND_FIRST_PHY_ALIVE
519 for(index = 0;index < NUM_OF_PHYs;index++) /* i..PHY tested */
521 if(physAlive && (1 << index))
523 hdkif->phy_addr = index;
528 MDIOPhyRegRead(hdkif->mdio_base, index, PHY_BMCR, ®Content); /* try to 'wake up' PHY on 'index' address by reading random register, making MDIO set alive bit for current PHY */
529 physAlive = MDIOPhyAliveStatusGet(hdkif->mdio_base); /* get updated register */
530 if(physAlive && (1 << index))
532 hdkif->phy_addr = index;
539 rpp_debug_printf("no phy found, phys: %d\r\n", physAlive);
543 rpp_debug_printf("default phy not alive\r\n");
544 return DFLT_PHY_NOT_ALIVE;
548 /* start autonegotiation and check on completion later or when complete link register will be updated */
549 hdkif->phy_autoneg_start(hdkif->mdio_base, hdkif->phy_addr, PHY_100BASETXDUPL_m | PHY_100BASETX_m | PHY_10BASETDUPL_m | PHY_10BASET_m);
551 /* TODO: you can implement init of receive flow control somewhere here if desired - set RXBUFFERFLOWEN in MACCONTROL */
554 /* acknowledge EMAC control module RX, TX and MISC interrupts */
555 EMACCoreIntAck(hdkif->emac_base, EMAC_INT_CORE0_RX);
556 EMACCoreIntAck(hdkif->emac_base, EMAC_INT_CORE0_TX);
557 EMACCoreIntAck(hdkif->emac_base, EMAC_INT_CORE0_MISC);
559 /* sets which channel will receive broadcasts */
560 EMACRxBroadCastEnable(hdkif->emac_base, CHANNEL);
561 /* sets channel where all frames will be copied to - either with MAC address different from local device address, either packets with error will be copied; appropriate error will be set in the frame EOP buffer descriptor */
562 EMACRxPromiscEnable(hdkif->emac_base, CHANNEL);
563 /* enables unicast */
564 EMACRxUnicastSet(hdkif->emac_base, CHANNEL);
566 /* enable TX and RX interrupts in both EMAC module and EMAC control module */
567 EMACTxIntPulseEnable(hdkif->emac_base, hdkif->emac_ctrl_base, 0, CHANNEL);
568 EMACRxIntPulseEnable(hdkif->emac_base, hdkif->emac_ctrl_base, 0, CHANNEL);
570 /* switch of send bd handling and when sending, just wait till send was done and then return (making the driver simple) */
571 //vim_mask_clr(TXinterruptVectorNumber);
576 err_t rpp_eth_hw_init_postInit(struct netif *netif)
578 volatile unsigned int autonegFinishWait = 0x3FFFFFFF; /* 0x3FFFFFFF is for 80MHz aproximately 13s */
580 uint32_t num_bd, pbuf_cnt = 0;
581 volatile struct emac_tx_bd *curr_txbd, *last_txbd;
582 volatile struct emac_rx_bd *curr_rxbd, *last_rxbd;
587 struct hdkif *hdkif = (struct hdkif *) netif->state;
589 rxch = &(hdkif->rxch);
590 txch = &(hdkif->txch);
592 rpp_debug_printf("autoneg started - check on cable if it's connected!\r\n");
596 * Initialize the Descriptor Memory For TX and RX
597 * Only Channel 0 is supported for both TX and RX
599 txch->free_head = ((volatile struct emac_tx_bd *) hdkif->emac_ctrl_ram);
600 txch->next_bd_to_process = txch->free_head;
601 txch->active_tail = NULL;
603 /* Set the number of descriptors for the channel */
604 num_bd = (SIZE_EMAC_CTRL_RAM >> 1) / sizeof(struct emac_tx_bd); /* take half of CPPI ram for TX BDs */
606 curr_txbd = txch->free_head;
608 /* Initialize all the TX buffer Descriptors */
610 curr_txbd->next = curr_txbd + 1;
611 curr_txbd->flags_pktlen = 0;
612 last_txbd = curr_txbd;
613 curr_txbd = curr_txbd->next;
615 last_txbd->next = txch->free_head;
617 /* Initialize the descriptors for the RX channel */
618 rxch->active_head = (volatile struct emac_rx_bd*)(curr_txbd);
619 rxch->free_head = NULL;
620 rxch->freed_pbuf_len = 0;
621 num_bd = ((SIZE_EMAC_CTRL_RAM >> 1) / sizeof(struct emac_rx_bd)); /* when using 20B emac_bd structs, u can allocate one more ;) ( 8192/20 = 409 together rx and tx and there is still 12 bytes remaining) */
622 curr_rxbd = rxch->active_head;
623 last_rxbd = curr_rxbd;
626 ** Allocate the pbufs for the maximum count permitted or till the
627 ** number of buffer desceriptors expire, which ever is earlier.
629 while(pbuf_cnt < MAX_RX_PBUF_ALLOC) {
630 p = pbuf_alloc(PBUF_RAW, PBUF_LEN_MAX, PBUF_POOL);
633 /* write the descriptors if there are enough numbers to hold the pbuf*/
634 if(((uint32_t)pbuf_clen(p)) <= num_bd) {
635 for(q = p; q != NULL; q = q->next) {
636 curr_rxbd->bufptr = (uint8_t *)(q->payload);
637 curr_rxbd->bufoff_len = q->len;
638 curr_rxbd->next = curr_rxbd + 1;
639 curr_rxbd->flags_pktlen = EMAC_DSC_FLAG_OWNER;
643 last_rxbd = curr_rxbd;
644 curr_rxbd = curr_rxbd->next;
649 /* free the allocated pbuf if no free descriptors are left */
661 if(!pbuf_cnt)rpp_debug_printf("no pbufs attached to rx buffer descriptors during init\n");
663 last_rxbd->next = NULL;
664 rxch->active_tail = last_rxbd;
666 num_bd = ( ((uint32_t)rxch->active_tail - (uint32_t)rxch->active_head) / sizeof(struct emac_rx_bd) + 1 );
667 rpp_debug_printf("%d pbuf chains allocated for %d rx buffer descriptors\n", pbuf_cnt, num_bd);
668 /* for flow control or QoS - there could be set an interrupt when we reach preset amount of receive descriptors remaining - see RXBUFFERFLOWEN */
669 /* EMACNumFreeBufSet(hdkif->emac_base, CHANNEL, num_bd); */ /* not used */
671 /* set header descriptor pointers - this shows EMAC which descriptor is beginning one for writing received frames/packets */
672 EMACRxHdrDescPtrWrite(hdkif->emac_base, (uint32_t)rxch->active_head, CHANNEL);
676 /* set length of MAC address */
677 netif->hwaddr_len = MAC_ADDR_LEN;
679 /* set MAC address */
680 for(regContent = 0; regContent < MAC_ADDR_LEN; regContent++) {
681 netif->hwaddr[regContent] = hdkif->mac_addr[(MAC_ADDR_LEN - 1) - regContent];
684 /* maximum transfer unit */
685 netif->mtu = MAX_TRANSFER_UNIT;
687 /* device capabilities */
688 /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */
689 netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;
691 /* lwIP stuff - end */
693 /* for flow control frames */
694 EMACMACSrcAddrSet(hdkif->emac_base, hdkif->mac_addr);
696 /* Be sure to program all eight MAC address registers -
697 * whether the receive channel is to be enabled or not.
699 for (regContent = 0; regContent < 8; regContent++) /* i..channel_number */
700 EMACMACAddrSet(hdkif->emac_base, regContent, hdkif->mac_addr, EMAC_MACADDR_NO_MATCH_NO_FILTER);
702 #if !PHY_LINK_MONITOR_INT /* in case we don't use interrupt when phy link status changes, we need to try to finish autoneg in here */
703 /* wait for autonegotiation to be done or continue, when delay was reached */
705 uint32_t timeToWake = hdkif->waitTicksForPHYAneg + sys_jiffies();
706 while(hdkif->phy_autoneg_is_done(hdkif->mdio_base, hdkif->phy_addr) == FALSE && timeToWake > sys_jiffies())vTaskDelay(20); /* XXX: if init is not done at the startup, but couple days later, this might cause troubles */
708 while(hdkif->phy_autoneg_is_done(hdkif->mdio_base, hdkif->phy_addr) == FALSE && autonegFinishWait--); /* wait till aneg done */
711 if(hdkif->phy_autoneg_is_done(hdkif->mdio_base, hdkif->phy_addr) != FALSE)
712 rpp_debug_printf("aneg finished \r\n");
714 rpp_debug_printf("aneg timeout \r\n");
716 /* provide informations retrieved from autoneg to EMAC module */
717 hdkif->phy_partnerability(hdkif->mdio_base, hdkif->phy_addr, ®Content);
718 if (regContent & (PHY_100BASETXDUPL_m | PHY_10BASETDUPL_m)) {
719 EMACDuplexSet(hdkif->emac_base, EMAC_DUPLEX_FULL);
720 /* this is right place to implement transmit flow control if desired - set TXFLOWEN in MACCONTROL */
721 } else if (regContent & (PHY_100BASETX_m | PHY_10BASET_m)) {
722 EMACDuplexSet(hdkif->emac_base, EMAC_DUPLEX_HALF);
724 rpp_debug_printf("Unknown duplex mode\r\n");
725 return UNKN_DUPLEX_MODE;
727 #endif /* !PHY_LINK_MONITOR_INT */
729 /* enable hostpend interrupts in emac module */
730 HWREG(hdkif->emac_base + EMAC_MACINTMASKSET) |= EMAC_MACINTMASKSET_HOSTMASK;
732 /* enable hostpend interrupts in emac control module */
733 HWREG(hdkif->emac_ctrl_base + EMAC_CTRL_CnMISCEN(0)) |= EMAC_CTRL_MISC_HOSTPENDENB;
735 /* enable EMAC's Media Independent Interface TX and RX */
736 EMACMIIEnable(hdkif->emac_base);
737 /* enable EMAC transmit */
738 EMACTxEnable(hdkif->emac_base);
739 /* enable EMAC receive */
740 EMACRxEnable(hdkif->emac_base);
758 /********************************************** send and receive functions / ISRs **********************************************/
760 err_t rpp_eth_send(struct netif * netif, struct pbuf *p)
762 err_t retVal = SUCCESS;
763 SYS_ARCH_DECL_PROTECT(lev);
766 * This entire function must run within a "critical section" to preserve
767 * the integrity of the transmit pbuf queue.
770 SYS_ARCH_PROTECT(lev);
772 /* protect from access receive acces from interrupt */
773 #if !SYS_LIGHTWEIGHT_PROT
774 uint32_t prevProt = (uint32_t) _get_CPSR() & 0x80;
779 /* adjust the packet length if less than minimum required */
780 if(p->tot_len < MIN_PKT_LEN) {
781 p->tot_len = MIN_PKT_LEN;
782 p->len = MIN_PKT_LEN;
785 /* call the actual transmit function */
786 retVal = rpp_eth_send_raw(netif, p);
788 /* Return to prior interrupt state and return. */
789 SYS_ARCH_UNPROTECT(lev);
791 #if !SYS_LIGHTWEIGHT_PROT
792 if(!prevProt)_enable_IRQ();
799 * send packet, blocks till it is sent
800 * every send uses bds on the beginning of CPPI RAM
802 err_t rpp_eth_send_raw(struct netif *netif, struct pbuf *p)
805 volatile struct emac_tx_bd *curr_bd, *bd_end;
808 hdkif = (struct hdkif *) netif->state;
809 curr_bd = (struct emac_tx_bd *) hdkif->emac_ctrl_ram;
811 /* destroy all flags previously set and update the total packet length */
812 curr_bd->flags_pktlen = p->tot_len;
814 /* Indicate the start of the packet */
815 curr_bd->flags_pktlen |= (EMAC_DSC_FLAG_SOP | EMAC_DSC_FLAG_OWNER);
817 /* Copy pbuf information into TX buffer descriptors */
818 for(q = p; q != NULL; q = q->next) {
820 /* Intialize the buffer pointer and length */
821 curr_bd->bufptr = (uint8_t *)(q->payload);
822 curr_bd->bufoff_len = (q->len) & 0xFFFF;
825 curr_bd = curr_bd->next;
826 curr_bd->flags_pktlen = 0x0; /* destroy all previously set flags */
829 /* Indicate the end of the packet */
831 bd_end->flags_pktlen |= EMAC_DSC_FLAG_EOP;
833 /* don't write to hdp till it turns zero */
834 while (0 != *((volatile uint32_t *) (hdkif->emac_base + EMAC_TXHDP(CHANNEL)) ));
835 /* notify hw where to start transmission from */
836 HWREG(hdkif->emac_base + EMAC_TXHDP(CHANNEL)) = hdkif->emac_ctrl_ram;
837 //EMACTxHdrDescPtrWrite(hdkif->emac_base, hdkif->emac_ctrl_ram, CHANNEL);
839 /* wait till queued pkt is sent */
840 vim_mask_set(TXinterruptVectorNumber);
841 xSemaphoreTake(hdkif->goTX, portMAX_DELAY);
842 while (!(bd_end->flags_pktlen & EMAC_DSC_FLAG_EOQ) || (((struct emac_tx_bd *)(hdkif->emac_ctrl_ram))->flags_pktlen & EMAC_DSC_FLAG_OWNER))rpp_sci_printk("!");
844 EMACTxCPWrite(hdkif->emac_base, CHANNEL, (uint32_t) bd_end);
846 EMACCoreIntAck(hdkif->emac_base, EMAC_INT_CORE0_TX);
848 /* restore bds chain */
849 bd_end->next = curr_bd;
851 LINK_STATS_INC(link.xmit);
855 void rpp_eth_recv_raw(void *arg)
857 volatile struct emac_rx_bd *curr_bd, *processed_bd, *curr_tail, *last_bd;
858 volatile struct pbuf *pbuf, *q, *new_pbuf;
859 uint32_t ex_len, len_to_alloc;
861 struct netif *netif = (struct netif *) arg;
862 struct hdkif *hdkif = (struct hdkif *) netif->state;
865 rxch = &(hdkif->rxch);
868 #if !NO_SYS && !ONE_DRIVER_TASK
869 SYS_ARCH_DECL_PROTECT(lev);
872 vim_mask_set(RXinterruptVectorNumber);
873 sys_arch_sem_wait(&(hdkif->goRX), 0);
874 SYS_ARCH_PROTECT(lev);
878 /* Get the bd which contains the earliest filled data */
879 curr_bd = rxch->active_head;
880 last_bd = rxch->active_tail;
882 if(curr_bd->flags_pktlen & EMAC_DSC_FLAG_SOP != EMAC_DSC_FLAG_SOP)rpp_debug_printf("ERR: Active head is not SOP!\n");
885 * Process the descriptors as long as data is available
886 * when the DMA is receiving data, SOP flag will be set
888 while(curr_bd->flags_pktlen & EMAC_DSC_FLAG_SOP)
892 /* Start processing once the packet is loaded */
893 if((curr_bd->flags_pktlen & EMAC_DSC_FLAG_OWNER) != EMAC_DSC_FLAG_OWNER)
895 if(rxch->free_head == NULL)
897 /* this bd chain will be freed after processing */
898 rxch->free_head = curr_bd;
901 /* Get the total length of the packet. curr_bd points to the start
904 tot_len = (curr_bd->flags_pktlen) & 0xFFFF;
906 /* Get the start of the pbuf queue */
910 /* Get the pbuf pointer which is associated with the current bd */
911 pbuf = curr_bd->pbuf;
913 /* If the earlier pbuf ended, update the chain */
914 if(pbuf->next == NULL)
916 pbuf->next = (struct pbuf*)(curr_bd->next)->pbuf;
919 len_to_alloc += pbuf->len;
920 /* Update the len and tot_len fields for the pbuf in the chain*/
921 pbuf->len = (curr_bd->bufoff_len) & 0xFFFF;
922 pbuf->tot_len = tot_len - ex_len ;
923 processed_bd = curr_bd;
925 curr_bd = curr_bd->next;
927 if(curr_bd == NULL)rpp_debug_printf("rx curr_bd set to zero!\n");
929 /* FIXME: curr_bd here could be NULL - (currently solved by having always allocated enough pbufs -> waiting for pbuf_free() function) a solution could be: we need to keep at least TCP_MSS bytes, so allocate at least that if not possible block */
930 } while((processed_bd->flags_pktlen & EMAC_DSC_FLAG_EOP) != EMAC_DSC_FLAG_EOP);
933 * Close the chain for this pbuf. A full packet is received in
934 * this pbuf chain. Now this pbuf can be given to upper layers for
935 * processing. The start of the pbuf chain is now 'q'.
939 /* Adjust the link statistics */
940 LINK_STATS_INC(link.recv);
942 /* Process the packet - this function is specified while adding netif using netif_add() function */
943 if(netif->input((struct pbuf *)q, netif) != ERR_OK)
945 /* Adjust the link statistics */
946 LINK_STATS_INC(link.memerr);
947 LINK_STATS_INC(link.drop);
950 /* Acknowledge that this packet is processed */
951 EMACRxCPWrite(hdkif->emac_base, CHANNEL, (unsigned int)processed_bd);
955 rxch->active_head = curr_bd;
959 rxch->active_head = processed_bd + 1; //todo:reconsider
963 * The earlier pbuf chain is freed from the upper layer. So, we need to
964 * allocate a new pbuf chain and update the descriptors with the pbuf info.
965 * To support chaining, the total length freed by the upper layer is tracked.
966 * Care should be taken even if the allocation fails.
969 * now len_to_alloc will contain the length of the pbuf which was freed
970 * from the upper layer
972 rxch->freed_pbuf_len += len_to_alloc;
974 /* if there is not enough pbufs predefined, we need application to process them and return them back to pool -> YIELD */
975 /* XXX: this is not fixed in NO_SYS version - problem is when curr_bd is set to NULL (see above), and we don't obtain new_pbuf
976 * from pool, then in *bd pointing to NULL might be such values (EMAC_DSC_FLAG_SOP == 1 &| EMAC_DSC_FLAG_OWNER == 0), that we
977 * stay cycling around */
981 new_pbuf = pbuf_alloc(PBUF_RAW, (rxch->freed_pbuf_len), PBUF_POOL);
986 xSemaphoreTake(pbufFreed, 0);
987 xSemaphoreTake(pbufFreed, portMAX_DELAY);
991 /* Write the descriptors with the pbuf info till either of them expires */
994 curr_bd = rxch->free_head;
996 for(q = new_pbuf; (q != NULL) && (curr_bd != rxch->active_head); q = q->next)
998 curr_bd->bufptr = (uint8_t *)(q->payload);
1000 /* no support for buf_offset. RXBUFFEROFFSET register is 0 */
1001 curr_bd->bufoff_len = (q->len) & 0xFFFF;
1002 curr_bd->flags_pktlen = EMAC_DSC_FLAG_OWNER;
1004 rxch->freed_pbuf_len -= q->len;
1009 curr_bd = curr_bd->next;
1013 * At this point either pbuf expired or no rxbd to allocate. If
1014 * there are no, enough rx bds to allocate all pbufs in the chain,
1015 * free the rest of the pbuf
1019 pbuf_free((struct pbuf *)q);
1022 curr_tail = rxch->active_tail;
1023 last_bd->next = NULL;
1025 curr_tail->next = rxch->free_head;
1028 * Check if the reception has ended. If the EOQ flag is set, the NULL
1029 * Pointer is taken by the DMA engine. So we need to write the RX HDP
1030 * with the next descriptor.
1032 if(curr_tail->flags_pktlen & EMAC_DSC_FLAG_EOQ)
1034 EMACRxHdrDescPtrWrite(hdkif->emac_base, (u32_t)(rxch->free_head), CHANNEL);
1037 rxch->free_head = curr_bd;
1038 rxch->active_tail = last_bd;
1041 curr_bd = rxch->active_head;
1043 EMACCoreIntAck(hdkif->emac_base, EMAC_INT_CORE0_RX);
1045 #if !NO_SYS && !ONE_DRIVER_TASK
1046 SYS_ARCH_UNPROTECT(lev);
1051 void RxIntHandler(u32_t instNum)
1054 vim_mask_clr(RXinterruptVectorNumber);
1056 static portBASE_TYPE xHigherPriorityTaskWoken;
1057 xHigherPriorityTaskWoken = pdFALSE;
1059 /* 'Give' the semaphore to unblock the task. */
1060 xSemaphoreGiveFromISR(hdkif_data[instNum].goRX, NULL); // whenever there is time to process received packets, wake up task processing them
1062 if( xHigherPriorityTaskWoken == pdTRUE )
1065 /* Giving the semaphore unblocked a task, and the priority of the
1066 unblocked task is higher than or equal to the currently running task
1067 - force a context switch to ensure that the interrupt returns directly
1068 to the unblocked (higher priority) task.
1069 NOTE: The actual macro to use to force a context switch from an
1070 ISR is dependent on the port. This is the correct macro for the
1071 Open Watcom DOS port. Other ports may require different syntax.
1072 Refer to the examples provided for the port being used to determine
1073 the syntax required. */
1075 portSWITCH_CONTEXT();
1079 rpp_eth_recv_raw((void *) &hdkNetIF[instNum]);
1083 void TxIntHandler(u32_t instNum)
1085 //struct hdkif *hdkif = &hdkif_data[instNum];
1087 vim_mask_clr(TXinterruptVectorNumber); /* see sys_startup.c */
1088 xSemaphoreGiveFromISR(hdkif_data[instNum].goTX, NULL);
1091 //rpp_eth_send_bd_handler((void *) &hdkif_data[instNum]);
1099 * 1h SOP error; the buffer is the first buffer in a packet, but the SOP bit is not set in software.
1100 * 2h Ownership bit not set in SOP buffer
1101 * 3h Zero next buffer descriptor pointer without EOP
1102 * 4h Zero buffer pointer
1103 * 5h Zero buffer length
1104 * 6h Packet length error (sum of buffers is less than packet length)
1111 * 2h Ownership bit not set in SOP buffer
1113 * 4h Zero buffer pointer
1115 boolean_t HostPendErrHandler(void)
1117 uint8_t index = MAX_EMAC_INSTANCE, errFound = FALSE;
1119 struct hdkif *hdkif;
1122 hdkif = &hdkif_data[--index];
1123 if(EMACIntVectorGet(hdkif->emac_base) & EMAC_MACINVECTOR_HOSTPEND)errFound = TRUE;
1125 if(!errFound)return FALSE; /* this is not the cause of the interrupt */
1126 rpp_sci_printk("HOSTPEND err\n");
1127 reg = HWREG(hdkif->emac_base + EMAC_MACSTATUS);
1128 rpp_sci_printk("TXCHERR: %d at CH: %d\n", ((reg >> EMAC_MACSTATUS_TXERRCODE_SHIFT) & 0x7), ((reg >> EMAC_MACSTATUS_TXERRCH_SHIFT) & 0x7));
1129 rpp_sci_printk("RXCHERR: %d at CH: %d\n", ((reg >> EMAC_MACSTATUS_RXERRCODE_SHIFT) & 0x7), ((reg >> EMAC_MACSTATUS_RXERRCH_SHIFT) & 0x7));
1130 /* no acknowledge - emac module has to be restarted */
1131 return TRUE; /* this was the reason of interrupt */
1134 #if PHY_LINK_MONITOR_INT
1135 boolean_t LinkIntHandler(void)
1137 uint8_t index = MAX_EMAC_INSTANCE, phyFound = FALSE;
1138 struct hdkif *hdkif;
1139 uint16_t regContent;
1140 volatile unsigned int autonegFinishWait = 0xFFFFFFF;
1141 volatile unsigned int dhcpBindWait = 0x3FFFFFFF;
1143 /* check each instance, whether this interrupt was meant for this function, if not return FALSE so other function may be tried */
1145 hdkif = &hdkif_data[--index];
1146 if( hdkif->phy_addr == (HWREG(hdkif->mdio_base + MDIO_USERPHYSEL0) & 0x1f) && EMACIntVectorGet(hdkif->emac_base) & EMAC_MACINVECTOR_LINKINT0 )phyFound = TRUE;
1148 if(!phyFound)return FALSE;
1149 struct netif *netif = &hdkNetIF[hdkif->inst_num];
1151 /* we handles here connection of cable after startup, not changes of linkstatus */
1153 /* wait for autonegotiation to be done */
1155 while(hdkif->phy_autoneg_is_done(hdkif->mdio_base, hdkif->phy_addr) == FALSE);
1156 #else /* ONCE_LINK_SETUP */
1157 while(hdkif->phy_autoneg_is_done(hdkif->mdio_base, hdkif->phy_addr) == FALSE & autonegFinishWait--);
1158 #endif /* ONCE_LINK_SETUP */
1160 /* provide informations retrieved from autoneg to EMAC module */
1161 hdkif->phy_partnerability(hdkif->mdio_base, hdkif->phy_addr, ®Content);
1162 if (regContent & (PHY_100BASETXDUPL_m | PHY_10BASETDUPL_m)) {
1163 EMACDuplexSet(hdkif->emac_base, EMAC_DUPLEX_FULL);
1164 /* this is right place to implement transmit flow control if desired - set TXFLOWEN in MACCONTROL */
1165 } else if (regContent & (PHY_100BASETX_m | PHY_10BASET_m)) {
1166 EMACDuplexSet(hdkif->emac_base, EMAC_DUPLEX_HALF);
1168 /* acknowledge MDIO module */
1169 HWREG(hdkif->mdio_base + MDIO_LINKINTRAW) = MDIO_LINKINTMASKED_USERPHY0;
1170 HWREG(hdkif->mdio_base + MDIO_LINKINTMASKED) = MDIO_LINKINTMASKED_USERPHY0;
1172 /* acknowledge EMAC control module by writing appropriate key to MACEOIVECTOR */
1173 EMACCoreIntAck(hdkif->emac_base, EMAC_INT_CORE0_MISC);
1176 /* if link is up configure lwip struct netif */
1177 if(rpp_eth_phylinkstat(hdkif->inst_num))
1179 #if STATIC_IP_ADDRESS
1180 netif_set_up(netif);
1181 #elif LWIP_DHCP /* STATIC_IP_ADDRESS-LWIP_DHCP */
1182 if(dhcp_start(netif) != ERR_OK) /* XXX: can't be used from ISR (mem_malloc()) */
1184 return DHCP_MEM_ERR;
1187 while(netif->dhcp->state != DHCP_BOUND);
1189 while(netif->dhcp->state != DHCP_BOUND & dhcpBindWait--);
1192 /* acknowledge MDIO module */
1193 HWREG(hdkif->mdio_base + MDIO_LINKINTRAW) = MDIO_LINKINTMASKED_USERPHY0;
1194 HWREG(hdkif->mdio_base + MDIO_LINKINTMASKED) = MDIO_LINKINTMASKED_USERPHY0;
1196 /* acknowledge EMAC control module by writing appropriate key to MACEOIVECTOR */
1197 EMACCoreIntAck(hdkif->emac_base, EMAC_INT_CORE0_MISC);
1201 #else /* LWIP_DHCP-LWIP_AUTOIP FIXME: there should be some kind of waiting till ip is assigned */
1202 autoip_start(netif);
1203 #endif /* STATIC_IP_ADDRESS-LWIP_DHCP-LWIP_AUTOIP */
1205 /* turn this interrupt off */
1206 HWREG(hdkif->emac_ctrl_base + EMAC_CTRL_CnMISCEN(0)) &= (~EMAC_CTRL_MISC_LINKINT0ENB & 0xf);
1207 #endif /* ONCE_LINK_SETUP */
1212 /* acknowledge MDIO module */
1213 HWREG(hdkif->mdio_base + MDIO_LINKINTRAW) = MDIO_LINKINTMASKED_USERPHY0;
1214 HWREG(hdkif->mdio_base + MDIO_LINKINTMASKED) = MDIO_LINKINTMASKED_USERPHY0;
1216 /* acknowledge EMAC control module by writing appropriate key to MACEOIVECTOR */
1217 EMACCoreIntAck(hdkif->emac_base, EMAC_INT_CORE0_MISC);
1220 #if STATIC_IP_ADDRESS
1221 netif_set_down(netif);
1222 #elif LWIP_DHCP /* STATIC_IP_ADDRESS-LWIP_DHCP */
1224 #endif /* STATIC_IP_ADDRESS-LWIP_DHCP-LWIP_AUTOIP */
1228 /* acknowledge MDIO module */
1229 HWREG(hdkif->mdio_base + MDIO_LINKINTRAW) = MDIO_LINKINTMASKED_USERPHY0;
1230 HWREG(hdkif->mdio_base + MDIO_LINKINTMASKED) = MDIO_LINKINTMASKED_USERPHY0;
1232 /* acknowledge EMAC control module by writing appropriate key to MACEOIVECTOR */
1233 EMACCoreIntAck(hdkif->emac_base, EMAC_INT_CORE0_MISC);
1237 #endif /* PHY_LINK_MONITOR_INT */
1239 #endif /* rppCONFIG_INCLUDE_ETH */