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-2014 Czech Technical University in Prague
43 * - Carlos Jenkins <carlos@jenkins.co.cr>
45 * - Jan Doležal <pm.jenik@gmail.com>
47 * This document contains proprietary information belonging to Czech
48 * Technical University in Prague. Passing on and copying of this
49 * document, and communication of its contents is not permitted
50 * without prior written authorization.
54 * Ethernet Communication RPP API implementation file. Using one PHY.
58 * RPP API documentation.
63 #ifndef FREERTOS_POSIX
66 #include "lwip/init.h"
67 #include "lwip/timers.h" /* for DHCP binding in NO_SYS mode */
68 #include "lwip/sys.h" /* includes - lwip/opt.h, lwip/err.h, arch/sys_arch.h */
69 #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 */
70 #include "lwip/stats.h" /* includes - lwip/mem.h, lwip/memp.h, lwip/opt.h */
71 #include "netif/etharp.h" /* includes - lwip/ip.h, lwip/netif.h, lwip/ip_addr.h, lwip/pbuf.h */
73 #include "lwip/snmp.h"
74 #include "lwip/dhcp.h"
75 #include "lwip/autoip.h"
76 #include "netif/ppp_oe.h"
77 /* end - lwIP headers */
80 #include "sys/sys.h" /* includes - sys/phy_dp83848h.h */
88 /* Number of EMAC Instances */
89 #define MAX_EMAC_INSTANCE 1
91 #define DEFAULT_PHY_ADDR 0x1
92 #define FIND_FIRST_PHY_ALIVE 1 /* or use default (phy_address: 1) */
93 #define NUM_OF_PHYs 32
94 #define SIZE_OF_DESC 16 /* in bytes */
95 #define CHANNEL 0 /* channel number for everything - for rx, tx, unicast, broadcast or damaged frames ; there are different channels for rx and tx operations */
97 #define MAX_TRANSFER_UNIT 1500 /* take in account oversized frames */
98 #define PBUF_LEN_MAX MAX_TRANSFER_UNIT
99 #define MAX_RX_PBUF_ALLOC 10
100 #define MIN_PKT_LEN 60
102 /* Define those to better describe the network interface. */
108 * Time to wait for autonegotiation in ticks.
110 #define TICKS_PHY_AUTONEG 4000
114 * When cable is connected (link status goes up) autonegotiation and/or dhcp is started.
116 #define PHY_LINK_MONITOR_INT 0 /* turn on handling interrupt - not implemented now */
119 /* Defining interface for all the emac instances */
120 static struct hdkif hdkif_data[MAX_EMAC_INSTANCE];
123 ** The lwIP network interface structure for the HDK Ethernet MAC.
125 static struct netif hdkNetIF[MAX_EMAC_INSTANCE];
127 /* rpp startup init indicator */
128 static boolean_t initialized = FALSE, postInitialized = FALSE;
130 boolean_t sendDone = TRUE;
132 /* free pbuf notification */
134 xSemaphoreHandle pbufFreed;
137 /**********************************************testing functions**********************************************/
139 boolean_t isPostInitialized()
141 return postInitialized;
144 uint32_t rpp_eth_phylinkstat(uint32_t instNum)
146 struct hdkif *hdkif = &hdkif_data[instNum];
147 return PHY_link_status_get(hdkif->mdio_base, hdkif->phy_addr, 1);
150 #define BYTE_BUFF_SIZE 2
151 #define OFFSET_MAC_LETTERS (MAC_BIG_LETTERS ? 'A' : 'a')
152 /* puts string of MAC address assigned to EMAC instance reffered by instNum into *mac */
153 void rpp_eth_get_macAddrStr(uint32_t instNum, uint8_t *macStr)
155 uint8_t index, outindex = 0;
156 char buff[BYTE_BUFF_SIZE];
157 struct hdkif *hdkif = &hdkif_data[instNum];
158 for(index = 0; index < MAC_ADDR_LEN; index++) {
159 if(index)macStr[outindex++] = ':';
160 buff[0] = (hdkif->mac_addr[(MAC_ADDR_LEN - 1) - index] >> 4);
161 buff[1] = (hdkif->mac_addr[(MAC_ADDR_LEN - 1) - index] & 0xf);
162 macStr[outindex++] = (buff[0]<10) ? (buff[0] + '0') : (buff[0] - '\012' + OFFSET_MAC_LETTERS);
163 macStr[outindex++] = (buff[1]<10) ? (buff[1] + '0') : (buff[1] - '\012' + OFFSET_MAC_LETTERS);
165 macStr[outindex] = '\0';
168 /* @param ip will be filled accroding to content of ipstr */
169 err_t rpp_eth_stringToIP(ip_addr_t * ip, uint8_t * ipstr)
171 uint8_t charProccessed, index = 0, dotindex = 0xff, tmp = 0, dots = 0, fldEdit = 0;
173 for(charProccessed = ipstr[index]; (charProccessed >= '0' && charProccessed <= '9') || charProccessed == '.' ; charProccessed = ipstr[++index])
175 if(charProccessed == '.')
177 if(++dotindex == index)
184 ipaddr = (ipaddr << 8) + tmp;
195 tmp = tmp*10 + charProccessed - '0';
198 if(dots != 3 || !fldEdit)
200 /* if unsuccesful, don't modify previous content */
203 ipaddr = (ipaddr << 8) + tmp;
208 /* returns number in range 0-65535 where 0 is error */
209 uint16_t rpp_eth_portStrToInt(uint8_t *string)
213 for(index = 0;string[index] != '\0';index++)
215 if(string[index] < '0' || string[index] > '9')
220 portNO = portNO * 10 + string[index] - '0';
225 struct netif *rpp_eth_get_netif(uint32_t instNum)
227 return &hdkNetIF[instNum];
230 /********************************************** forward declares **********************************************/
233 * interface initializes
235 err_t rpp_eth_lwip_init(struct netif *netif);
238 * Initializes hw such as PHY, MDIO, EMAC, EMAC control module
240 * @return SUCCESS if initialization successful.\n
241 * FAILURE if initialization not successful.
243 err_t rpp_eth_hw_init(struct hdkif *hdkif);
246 * Initializes hw, after lwIP was initialized and
247 * OS was initialized in case OS is used.
249 err_t rpp_eth_hw_init_postInit(struct netif *netif);
251 /********************************************** utility functions **********************************************/
254 * Function to set the MAC address to the interface
255 * @param inst_num the instance number
257 * @note mac_addr[0] is considered MSB
260 hdkif_macaddrset(u32_t inst_num, u8_t *mac_addr) {
264 hdkif = &hdkif_data[inst_num];
266 /* set MAC hardware address */
267 for(temp = 0; temp < MAC_ADDR_LEN; temp++) {
268 hdkif->mac_addr[temp] = mac_addr[(MAC_ADDR_LEN - 1) - temp];
272 rpp_eth_get_macAddrStr(inst_num, macStr);
273 rpp_debug_printf("Setting MAC... %s\r\n", macStr);
278 * Function to setup the instance parameters inside the interface
283 hdkif_inst_config(struct hdkif *hdkif) {
284 if(hdkif->inst_num == 0)
286 hdkif->emac_base = EMAC_BASE_m(0);
287 hdkif->emac_ctrl_base = EMAC_CTRL_BASE_m(0);
288 hdkif->emac_ctrl_ram = EMAC_CTRL_RAM_BASE_m(0);
289 hdkif->mdio_base = MDIO_BASE_m(0);
290 hdkif->phy_addr = DEFAULT_PHY_ADDR; /* Default address of PHY on "MDIO bus" (depends on PHY hw configuration) */
291 hdkif->phy_autoneg = PHY_auto_negotiate;
292 hdkif->phy_autoneg_start = PHY_start_auto_negotiate;
293 hdkif->phy_autoneg_is_done = PHY_is_done_auto_negotiate;
294 hdkif->phy_partnerability = PHY_partner_ability_get;
298 /********************************************** initializing functions **********************************************/
300 int8_t rpp_eth_init()
303 int8_t retVal = SUCCESS;
308 /* config of EMAC instances and other stuff */
309 for(instNum = 0; instNum < MAX_EMAC_INSTANCE; instNum++)
311 hdkif_data[instNum].inst_num = instNum;
312 hdkif_inst_config(&hdkif_data[instNum]); /* hdkif_inst_config must contain instNum specific settings */
313 if(retVal = rpp_eth_hw_init(&hdkif_data[instNum]))
316 rpp_sci_printk("rpp_eth_hw_init: %d", retVal);
322 /* when one of instances was not initialized correctly return FAILURE without setting initialized variable to TRUE */
323 if(retVal)return FAILURE;
336 int8_t rpp_eth_init_postInit(uint32_t instNum, uint8_t *macArray)
338 if(postInitialized) {
341 int8_t retVal = SUCCESS;
342 struct netif *netif = &hdkNetIF[instNum];
343 u8_t mac_addr[MAC_ADDR_LEN] = RPP_MAC_ADDR;
345 /* ----- lwIP stuff ----- */
346 struct ip_addr ip_addr;
347 struct ip_addr net_mask;
348 struct ip_addr gw_addr;
349 volatile unsigned int dhcpBindWait = 0x3FFFFFFF;
353 macArray = mac_addr; /* use default MAC */
355 hdkif_macaddrset(instNum, macArray);
361 /* this can be called only within post OS init */
362 tcpip_init(NULL,NULL); /* calls lwip_init() implicitly, starts lwIP task (thread), when started function given to tcpip_init is executed first */
365 #if STATIC_IP_ADDRESS
366 ip_addr.addr = htonl(RPP_IP_ADDR);
367 net_mask.addr = htonl(RPP_NETMASK);
368 gw_addr.addr = htonl(RPP_GW);
369 #else /* STATIC_IP_ADDRESS */
373 #endif /* STATIC_IP_ADDRESS */
375 /* init and add new netif */
376 /* add new network interface to lwIP list of ifaces and initialize netif with specific function */
378 if( netif_add(netif, &ip_addr, &net_mask, &gw_addr, (void *) instNum, rpp_eth_lwip_init, ethernet_input) == NULL )
380 if( netif_add(netif, &ip_addr, &net_mask, &gw_addr, (void *) instNum, rpp_eth_lwip_init, tcpip_input) == NULL )
383 return NETIF_ADD_ERR;
386 netif_set_default(netif);
388 hdkif = (struct hdkif *) netif->state;
390 /* ----- freeRTOS elements ----- */
391 /* semaphore blocking receive task (rpp_eth_recv_raw) from receive operation, till RX interrupt occurs and notify it */
392 vSemaphoreCreateBinary(hdkif->goRX);
393 vSemaphoreCreateBinary(hdkif->goTX);
394 /* create semaphore notificating that pbuf was freed */
395 vSemaphoreCreateBinary(pbufFreed);
396 /* run task rpp_eth_recv_raw */
397 xTaskCreate( rpp_eth_recv_raw, "RXHandler", 200, netif, 0, NULL );
398 /* ----- end - freeRTOS ----- */
401 /* if we don't use link int change, then it must be done here */
402 #if !PHY_LINK_MONITOR_INT
403 if(rpp_eth_phylinkstat(hdkif->inst_num))
405 rpp_debug_printf((const char *)"cable connected ... setting IP params\r\n");
406 #if STATIC_IP_ADDRESS
408 #elif LWIP_DHCP /* STATIC_IP_ADDRESS-LWIP_DHCP */
409 if(dhcp_start(netif) != ERR_OK)
411 rpp_debug_printf("dhcp mem err\r\n");
414 rpp_debug_printf("binding DHCP\r");
415 while((netif->dhcp->state != DHCP_BOUND) && (dhcpBindWait--))/*sys_check_timeouts()*/;
417 rpp_debug_printf("dhcp binding timeout...\r\n");
418 #else /* LWIP_DHCP-LWIP_AUTOIP FIXME: there should be some kind of waiting till ip is assigned */
420 #endif /* STATIC_IP_ADDRESS-LWIP_DHCP-LWIP_AUTOIP */
422 uint8_t ipString[16];
423 rpp_eth_getIPDecimalStr(netif->ip_addr, ipString);
424 rpp_debug_printf("Address: %s\r\n", ipString);
425 rpp_eth_getIPDecimalStr(netif->netmask, ipString);
426 rpp_debug_printf("Netmask: %s\r\n", ipString);
427 rpp_eth_getIPDecimalStr(netif->gw, ipString);
428 rpp_debug_printf("Gateway: %s\r\n", ipString);
433 rpp_debug_printf((const char *)"cable not connected\r\n");
434 retVal = PHY_LINK_DOWN;
437 #else /* !PHY_LINK_MONITOR_INT */
438 /* now when we established environment needed for phy link status change we can allow it */
439 /* set PHY number which is monitored for link changes in MDIO and enable interrupt */
440 HWREG(hdkif->mdio_base + MDIO_USERPHYSEL0) = ((hdkif->phy_addr && 0x1f) | MDIO_USERPHYSEL0_LINKINTENB);
442 /* enable MISC interrupt - link monitoring in EMAC controle module */
443 HWREG(hdkif->emac_ctrl_base + EMAC_CTRL_CnMISCEN(0)) |= EMAC_CTRL_MISC_LINKINT0ENB;
445 #endif /* !PHY_LINK_MONITOR_INT */
446 /* ----- end - lwIP stuff ----- */
448 postInitialized = TRUE;
452 err_t rpp_eth_lwip_init(struct netif *netif)
454 #if LWIP_NETIF_HOSTNAME
455 /* Initialize interface hostname */
456 netif->hostname = "rpp";
457 #endif /* LWIP_NETIF_HOSTNAME */
459 uint32_t instNum = (uint32_t)netif->state;
460 /*netif->num = instNum; - auto-initiated when netif_add is called */
462 /* netif->state contained instNum, we replace it with corresponding hdkif */
463 struct hdkif *hdkif = &hdkif_data[instNum];
464 netif->state = hdkif;
466 netif->name[0] = IFNAME0;
467 netif->name[1] = IFNAME1;
470 hdkif->waitTicksForPHYAneg = TICKS_PHY_AUTONEG;
474 * Initialize the snmp variables and counters inside the struct netif.
475 * The last argument should be replaced with your link speed, in units
476 * of bits per second.
478 NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, 10000000);
480 /* We directly use etharp_output() here to save a function call.
481 * You can instead declare yo_SKIP_TO_HWur own function an call etharp_output()
482 * from it if you have to do some checks before sending (e.g. if link
485 netif->output = etharp_output;
486 netif->linkoutput = rpp_eth_send;
487 return rpp_eth_hw_init_postInit(netif);
490 #define INIT_ONLY_AFTER_RESET 1
491 err_t rpp_eth_hw_init(struct hdkif *hdkif)
497 /* Deactivate reset pin of PHY */
498 /* for hw reset of PHY, it is necessary that PIN_NAME_ETHRST is 1us logical low state, before putting it to logical high */
499 #if !INIT_ONLY_AFTER_RESET
501 uint8_t index = 80; /* Initially used to hw reset of PHY connected to GIO pin. This means 1us - for 80MHz clock. */
503 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. */
505 hal_gpio_pin_set_value(*hal_gpio_pin_get_dsc(PIN_NAME_ETHRST,-1),0);
507 #endif /* !INIT_ONLY_AFTER_RESET */
508 /* we have pull-down resistor, so after reset, we only need to put ETHRST pin to log. high */
509 hal_gpio_pin_set_value(*hal_gpio_pin_get_dsc(PIN_NAME_ETHRST,-1),1);
511 /* initializes EMAC control module and EMAC module */
512 EMACInit(hdkif->emac_ctrl_base, hdkif->emac_base);
513 /* initializes MDIO module (reset) */
514 MDIOInit(hdkif->mdio_base, 0x0, 0x0);
516 /* enable used receive channel if necessary */
519 /* try to read random register from defaultPhy to make MDIO fill alive bit for this one if it returned
520 ACK bit in msg response - this must be done, because MDIO has not set alive bit of PHY after that
521 short time after MDIOInit() */
522 MDIOPhyRegRead(hdkif->mdio_base, hdkif->phy_addr, PHY_BMSR, ®Content);
524 /* find first alive PHY - or use default if alive */
525 physAlive = MDIOPhyAliveStatusGet(hdkif->mdio_base);
526 if(!(physAlive & (1 << hdkif->phy_addr)))
528 #if FIND_FIRST_PHY_ALIVE
529 for(index = 0;index < NUM_OF_PHYs;index++) /* i..PHY tested */
531 if(physAlive && (1 << index))
533 hdkif->phy_addr = index;
538 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 */
539 physAlive = MDIOPhyAliveStatusGet(hdkif->mdio_base); /* get updated register */
540 if(physAlive && (1 << index))
542 hdkif->phy_addr = index;
549 rpp_debug_printf("no phy found, phys: %d\r\n", physAlive);
553 rpp_debug_printf("default phy not alive\r\n");
554 return DFLT_PHY_NOT_ALIVE;
558 /* start autonegotiation and check on completion later or when complete link register will be updated */
559 hdkif->phy_autoneg_start(hdkif->mdio_base, hdkif->phy_addr, PHY_100BASETXDUPL_m | PHY_100BASETX_m | PHY_10BASETDUPL_m | PHY_10BASET_m);
561 /* TODO: you can implement init of receive flow control somewhere here if desired - set RXBUFFERFLOWEN in MACCONTROL */
564 /* acknowledge EMAC control module RX, TX and MISC interrupts */
565 EMACCoreIntAck(hdkif->emac_base, EMAC_INT_CORE0_RX);
566 EMACCoreIntAck(hdkif->emac_base, EMAC_INT_CORE0_TX);
567 EMACCoreIntAck(hdkif->emac_base, EMAC_INT_CORE0_MISC);
569 /* sets which channel will receive broadcasts */
570 EMACRxBroadCastEnable(hdkif->emac_base, CHANNEL);
571 /* 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 */
572 EMACRxPromiscEnable(hdkif->emac_base, CHANNEL);
573 /* enables unicast */
574 EMACRxUnicastSet(hdkif->emac_base, CHANNEL);
576 /* enable TX and RX interrupts in both EMAC module and EMAC control module */
577 EMACTxIntPulseEnable(hdkif->emac_base, hdkif->emac_ctrl_base, 0, CHANNEL);
578 EMACRxIntPulseEnable(hdkif->emac_base, hdkif->emac_ctrl_base, 0, CHANNEL);
580 /* switch of send bd handling and when sending, just wait till send was done and then return (making the driver simple) */
581 //vim_mask_clr(TXinterruptVectorNumber);
586 err_t rpp_eth_hw_init_postInit(struct netif *netif)
588 volatile unsigned int autonegFinishWait = 0x3FFFFFFF; /* 0x3FFFFFFF is for 80MHz aproximately 13s */
590 uint32_t num_bd, pbuf_cnt = 0;
591 volatile struct emac_tx_bd *curr_txbd, *last_txbd;
592 volatile struct emac_rx_bd *curr_rxbd, *last_rxbd;
597 struct hdkif *hdkif = (struct hdkif *) netif->state;
599 rxch = &(hdkif->rxch);
600 txch = &(hdkif->txch);
602 rpp_debug_printf("autoneg started - check on cable if it's connected!\r\n");
606 * Initialize the Descriptor Memory For TX and RX
607 * Only Channel 0 is supported for both TX and RX
609 txch->free_head = ((volatile struct emac_tx_bd *) hdkif->emac_ctrl_ram);
610 txch->next_bd_to_process = txch->free_head;
611 txch->active_tail = NULL;
613 /* Set the number of descriptors for the channel */
614 num_bd = (SIZE_EMAC_CTRL_RAM >> 1) / sizeof(struct emac_tx_bd); /* take half of CPPI ram for TX BDs */
616 curr_txbd = txch->free_head;
618 /* Initialize all the TX buffer Descriptors */
620 curr_txbd->next = curr_txbd + 1;
621 curr_txbd->flags_pktlen = 0;
622 last_txbd = curr_txbd;
623 curr_txbd = curr_txbd->next;
625 last_txbd->next = txch->free_head;
627 /* Initialize the descriptors for the RX channel */
628 rxch->active_head = (volatile struct emac_rx_bd*)(curr_txbd);
629 rxch->free_head = NULL;
630 rxch->freed_pbuf_len = 0;
631 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) */
632 curr_rxbd = rxch->active_head;
633 last_rxbd = curr_rxbd;
636 ** Allocate the pbufs for the maximum count permitted or till the
637 ** number of buffer desceriptors expire, which ever is earlier.
639 while(pbuf_cnt < MAX_RX_PBUF_ALLOC) {
640 p = pbuf_alloc(PBUF_RAW, PBUF_LEN_MAX, PBUF_POOL);
643 /* write the descriptors if there are enough numbers to hold the pbuf*/
644 if(((uint32_t)pbuf_clen(p)) <= num_bd) {
645 for(q = p; q != NULL; q = q->next) {
646 curr_rxbd->bufptr = (uint8_t *)(q->payload);
647 curr_rxbd->bufoff_len = q->len;
648 curr_rxbd->next = curr_rxbd + 1;
649 curr_rxbd->flags_pktlen = EMAC_DSC_FLAG_OWNER;
653 last_rxbd = curr_rxbd;
654 curr_rxbd = curr_rxbd->next;
659 /* free the allocated pbuf if no free descriptors are left */
671 if(!pbuf_cnt)rpp_debug_printf("no pbufs attached to rx buffer descriptors during init\n");
673 last_rxbd->next = NULL;
674 rxch->active_tail = last_rxbd;
676 num_bd = ( ((uint32_t)rxch->active_tail - (uint32_t)rxch->active_head) / sizeof(struct emac_rx_bd) + 1 );
677 rpp_debug_printf("%d pbuf chains allocated for %d rx buffer descriptors\n", pbuf_cnt, num_bd);
678 /* for flow control or QoS - there could be set an interrupt when we reach preset amount of receive descriptors remaining - see RXBUFFERFLOWEN */
679 /* EMACNumFreeBufSet(hdkif->emac_base, CHANNEL, num_bd); */ /* not used */
681 /* set header descriptor pointers - this shows EMAC which descriptor is beginning one for writing received frames/packets */
682 EMACRxHdrDescPtrWrite(hdkif->emac_base, (uint32_t)rxch->active_head, CHANNEL);
686 /* set length of MAC address */
687 netif->hwaddr_len = MAC_ADDR_LEN;
689 /* set MAC address */
690 for(regContent = 0; regContent < MAC_ADDR_LEN; regContent++) {
691 netif->hwaddr[regContent] = hdkif->mac_addr[(MAC_ADDR_LEN - 1) - regContent];
694 /* maximum transfer unit */
695 netif->mtu = MAX_TRANSFER_UNIT;
697 /* device capabilities */
698 /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */
699 netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;
701 /* lwIP stuff - end */
703 /* for flow control frames */
704 EMACMACSrcAddrSet(hdkif->emac_base, hdkif->mac_addr);
706 /* Be sure to program all eight MAC address registers -
707 * whether the receive channel is to be enabled or not.
709 for (regContent = 0; regContent < 8; regContent++) /* i..channel_number */
710 EMACMACAddrSet(hdkif->emac_base, regContent, hdkif->mac_addr, EMAC_MACADDR_NO_MATCH_NO_FILTER);
712 #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 */
713 /* wait for autonegotiation to be done or continue, when delay was reached */
715 uint32_t timeToWake = hdkif->waitTicksForPHYAneg + sys_jiffies();
716 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 */
718 while(hdkif->phy_autoneg_is_done(hdkif->mdio_base, hdkif->phy_addr) == FALSE && autonegFinishWait--); /* wait till aneg done */
721 if(hdkif->phy_autoneg_is_done(hdkif->mdio_base, hdkif->phy_addr) != FALSE)
722 rpp_debug_printf("aneg finished \r\n");
724 rpp_debug_printf("aneg timeout \r\n");
726 /* provide informations retrieved from autoneg to EMAC module */
727 hdkif->phy_partnerability(hdkif->mdio_base, hdkif->phy_addr, ®Content);
728 if (regContent & (PHY_100BASETXDUPL_m | PHY_10BASETDUPL_m)) {
729 EMACDuplexSet(hdkif->emac_base, EMAC_DUPLEX_FULL);
730 /* this is right place to implement transmit flow control if desired - set TXFLOWEN in MACCONTROL */
731 } else if (regContent & (PHY_100BASETX_m | PHY_10BASET_m)) {
732 EMACDuplexSet(hdkif->emac_base, EMAC_DUPLEX_HALF);
734 rpp_debug_printf("Unknown duplex mode\r\n");
735 return UNKN_DUPLEX_MODE;
737 #endif /* !PHY_LINK_MONITOR_INT */
739 /* enable hostpend interrupts in emac module */
740 HWREG(hdkif->emac_base + EMAC_MACINTMASKSET) |= EMAC_MACINTMASKSET_HOSTMASK;
742 /* enable hostpend interrupts in emac control module */
743 HWREG(hdkif->emac_ctrl_base + EMAC_CTRL_CnMISCEN(0)) |= EMAC_CTRL_MISC_HOSTPENDENB;
745 /* enable EMAC's Media Independent Interface TX and RX */
746 EMACMIIEnable(hdkif->emac_base);
747 /* enable EMAC transmit */
748 EMACTxEnable(hdkif->emac_base);
749 /* enable EMAC receive */
750 EMACRxEnable(hdkif->emac_base);
768 /********************************************** send and receive functions / ISRs **********************************************/
770 err_t rpp_eth_send(struct netif * netif, struct pbuf *p)
772 err_t retVal = SUCCESS;
773 SYS_ARCH_DECL_PROTECT(lev);
776 * This entire function must run within a "critical section" to preserve
777 * the integrity of the transmit pbuf queue.
780 SYS_ARCH_PROTECT(lev);
782 /* protect from access receive acces from interrupt */
783 #if !SYS_LIGHTWEIGHT_PROT
784 uint32_t prevProt = (uint32_t) _get_CPSR() & 0x80;
789 /* adjust the packet length if less than minimum required */
790 if(p->tot_len < MIN_PKT_LEN) {
791 p->tot_len = MIN_PKT_LEN;
792 p->len = MIN_PKT_LEN;
795 /* call the actual transmit function */
796 retVal = rpp_eth_send_raw(netif, p);
798 /* Return to prior interrupt state and return. */
799 SYS_ARCH_UNPROTECT(lev);
801 #if !SYS_LIGHTWEIGHT_PROT
802 if(!prevProt)_enable_IRQ();
809 * send packet, blocks till it is sent
810 * every send uses bds on the beginning of CPPI RAM
812 err_t rpp_eth_send_raw(struct netif *netif, struct pbuf *p)
815 volatile struct emac_tx_bd *curr_bd, *bd_end;
818 hdkif = (struct hdkif *) netif->state;
819 curr_bd = (struct emac_tx_bd *) hdkif->emac_ctrl_ram;
821 /* destroy all flags previously set and update the total packet length */
822 curr_bd->flags_pktlen = p->tot_len;
824 /* Indicate the start of the packet */
825 curr_bd->flags_pktlen |= (EMAC_DSC_FLAG_SOP | EMAC_DSC_FLAG_OWNER);
827 /* Copy pbuf information into TX buffer descriptors */
828 for(q = p; q != NULL; q = q->next) {
830 /* Intialize the buffer pointer and length */
831 curr_bd->bufptr = (uint8_t *)(q->payload);
832 curr_bd->bufoff_len = (q->len) & 0xFFFF;
835 curr_bd = curr_bd->next;
836 curr_bd->flags_pktlen = 0x0; /* destroy all previously set flags */
839 /* Indicate the end of the packet */
841 bd_end->flags_pktlen |= EMAC_DSC_FLAG_EOP;
843 /* don't write to hdp till it turns zero */
844 while (0 != *((volatile uint32_t *) (hdkif->emac_base + EMAC_TXHDP(CHANNEL)) ));
845 /* notify hw where to start transmission from */
846 HWREG(hdkif->emac_base + EMAC_TXHDP(CHANNEL)) = hdkif->emac_ctrl_ram;
847 //EMACTxHdrDescPtrWrite(hdkif->emac_base, hdkif->emac_ctrl_ram, CHANNEL);
849 /* wait till queued pkt is sent */
850 vim_mask_set(TXinterruptVectorNumber);
851 xSemaphoreTake(hdkif->goTX, portMAX_DELAY);
852 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("!");
854 EMACTxCPWrite(hdkif->emac_base, CHANNEL, (uint32_t) bd_end);
856 EMACCoreIntAck(hdkif->emac_base, EMAC_INT_CORE0_TX);
858 /* restore bds chain */
859 bd_end->next = curr_bd;
861 LINK_STATS_INC(link.xmit);
865 void rpp_eth_recv_raw(void *arg)
867 volatile struct emac_rx_bd *curr_bd, *processed_bd, *curr_tail, *last_bd;
868 volatile struct pbuf *pbuf, *q, *new_pbuf;
869 uint32_t ex_len, len_to_alloc;
871 struct netif *netif = (struct netif *) arg;
872 struct hdkif *hdkif = (struct hdkif *) netif->state;
875 rxch = &(hdkif->rxch);
878 #if !NO_SYS && !ONE_DRIVER_TASK
879 SYS_ARCH_DECL_PROTECT(lev);
882 vim_mask_set(RXinterruptVectorNumber);
883 sys_arch_sem_wait(&(hdkif->goRX), 0);
884 SYS_ARCH_PROTECT(lev);
888 /* Get the bd which contains the earliest filled data */
889 curr_bd = rxch->active_head;
890 last_bd = rxch->active_tail;
892 if(curr_bd->flags_pktlen & EMAC_DSC_FLAG_SOP != EMAC_DSC_FLAG_SOP)rpp_debug_printf("ERR: Active head is not SOP!\n");
895 * Process the descriptors as long as data is available
896 * when the DMA is receiving data, SOP flag will be set
898 while(curr_bd->flags_pktlen & EMAC_DSC_FLAG_SOP)
902 /* Start processing once the packet is loaded */
903 if((curr_bd->flags_pktlen & EMAC_DSC_FLAG_OWNER) != EMAC_DSC_FLAG_OWNER)
905 if(rxch->free_head == NULL)
907 /* this bd chain will be freed after processing */
908 rxch->free_head = curr_bd;
911 /* Get the total length of the packet. curr_bd points to the start
914 tot_len = (curr_bd->flags_pktlen) & 0xFFFF;
916 /* Get the start of the pbuf queue */
920 /* Get the pbuf pointer which is associated with the current bd */
921 pbuf = curr_bd->pbuf;
923 /* If the earlier pbuf ended, update the chain */
924 if(pbuf->next == NULL)
926 pbuf->next = (struct pbuf*)(curr_bd->next)->pbuf;
929 len_to_alloc += pbuf->len;
930 /* Update the len and tot_len fields for the pbuf in the chain*/
931 pbuf->len = (curr_bd->bufoff_len) & 0xFFFF;
932 pbuf->tot_len = tot_len - ex_len ;
933 processed_bd = curr_bd;
935 curr_bd = curr_bd->next;
937 if(curr_bd == NULL)rpp_debug_printf("rx curr_bd set to zero!\n");
939 /* 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 */
940 } while((processed_bd->flags_pktlen & EMAC_DSC_FLAG_EOP) != EMAC_DSC_FLAG_EOP);
943 * Close the chain for this pbuf. A full packet is received in
944 * this pbuf chain. Now this pbuf can be given to upper layers for
945 * processing. The start of the pbuf chain is now 'q'.
949 /* Adjust the link statistics */
950 LINK_STATS_INC(link.recv);
952 /* Process the packet - this function is specified while adding netif using netif_add() function */
953 if(netif->input((struct pbuf *)q, netif) != ERR_OK)
955 /* Adjust the link statistics */
956 LINK_STATS_INC(link.memerr);
957 LINK_STATS_INC(link.drop);
960 /* Acknowledge that this packet is processed */
961 EMACRxCPWrite(hdkif->emac_base, CHANNEL, (unsigned int)processed_bd);
965 rxch->active_head = curr_bd;
969 rxch->active_head = processed_bd + 1; //todo:reconsider
973 * The earlier pbuf chain is freed from the upper layer. So, we need to
974 * allocate a new pbuf chain and update the descriptors with the pbuf info.
975 * To support chaining, the total length freed by the upper layer is tracked.
976 * Care should be taken even if the allocation fails.
979 * now len_to_alloc will contain the length of the pbuf which was freed
980 * from the upper layer
982 rxch->freed_pbuf_len += len_to_alloc;
984 /* if there is not enough pbufs predefined, we need application to process them and return them back to pool -> YIELD */
985 /* 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
986 * from pool, then in *bd pointing to NULL might be such values (EMAC_DSC_FLAG_SOP == 1 &| EMAC_DSC_FLAG_OWNER == 0), that we
987 * stay cycling around */
991 new_pbuf = pbuf_alloc(PBUF_RAW, (rxch->freed_pbuf_len), PBUF_POOL);
996 xSemaphoreTake(pbufFreed, 0);
997 xSemaphoreTake(pbufFreed, portMAX_DELAY);
1001 /* Write the descriptors with the pbuf info till either of them expires */
1002 if(new_pbuf != NULL)
1004 curr_bd = rxch->free_head;
1006 for(q = new_pbuf; (q != NULL) && (curr_bd != rxch->active_head); q = q->next)
1008 curr_bd->bufptr = (uint8_t *)(q->payload);
1010 /* no support for buf_offset. RXBUFFEROFFSET register is 0 */
1011 curr_bd->bufoff_len = (q->len) & 0xFFFF;
1012 curr_bd->flags_pktlen = EMAC_DSC_FLAG_OWNER;
1014 rxch->freed_pbuf_len -= q->len;
1019 curr_bd = curr_bd->next;
1023 * At this point either pbuf expired or no rxbd to allocate. If
1024 * there are no, enough rx bds to allocate all pbufs in the chain,
1025 * free the rest of the pbuf
1029 pbuf_free((struct pbuf *)q);
1032 curr_tail = rxch->active_tail;
1033 last_bd->next = NULL;
1035 curr_tail->next = rxch->free_head;
1038 * Check if the reception has ended. If the EOQ flag is set, the NULL
1039 * Pointer is taken by the DMA engine. So we need to write the RX HDP
1040 * with the next descriptor.
1042 if(curr_tail->flags_pktlen & EMAC_DSC_FLAG_EOQ)
1044 EMACRxHdrDescPtrWrite(hdkif->emac_base, (u32_t)(rxch->free_head), CHANNEL);
1047 rxch->free_head = curr_bd;
1048 rxch->active_tail = last_bd;
1051 curr_bd = rxch->active_head;
1053 EMACCoreIntAck(hdkif->emac_base, EMAC_INT_CORE0_RX);
1055 #if !NO_SYS && !ONE_DRIVER_TASK
1056 SYS_ARCH_UNPROTECT(lev);
1061 void RxIntHandler(u32_t instNum)
1064 vim_mask_clr(RXinterruptVectorNumber);
1066 static portBASE_TYPE xHigherPriorityTaskWoken;
1067 xHigherPriorityTaskWoken = pdFALSE;
1069 /* 'Give' the semaphore to unblock the task. */
1070 xSemaphoreGiveFromISR(hdkif_data[instNum].goRX, NULL); // whenever there is time to process received packets, wake up task processing them
1072 if( xHigherPriorityTaskWoken == pdTRUE )
1075 /* Giving the semaphore unblocked a task, and the priority of the
1076 unblocked task is higher than or equal to the currently running task
1077 - force a context switch to ensure that the interrupt returns directly
1078 to the unblocked (higher priority) task.
1079 NOTE: The actual macro to use to force a context switch from an
1080 ISR is dependent on the port. This is the correct macro for the
1081 Open Watcom DOS port. Other ports may require different syntax.
1082 Refer to the examples provided for the port being used to determine
1083 the syntax required. */
1085 portSWITCH_CONTEXT();
1089 rpp_eth_recv_raw((void *) &hdkNetIF[instNum]);
1093 void TxIntHandler(u32_t instNum)
1095 //struct hdkif *hdkif = &hdkif_data[instNum];
1097 vim_mask_clr(TXinterruptVectorNumber); /* see sys_startup.c */
1098 xSemaphoreGiveFromISR(hdkif_data[instNum].goTX, NULL);
1101 //rpp_eth_send_bd_handler((void *) &hdkif_data[instNum]);
1109 * 1h SOP error; the buffer is the first buffer in a packet, but the SOP bit is not set in software.
1110 * 2h Ownership bit not set in SOP buffer
1111 * 3h Zero next buffer descriptor pointer without EOP
1112 * 4h Zero buffer pointer
1113 * 5h Zero buffer length
1114 * 6h Packet length error (sum of buffers is less than packet length)
1121 * 2h Ownership bit not set in SOP buffer
1123 * 4h Zero buffer pointer
1125 boolean_t HostPendErrHandler(void)
1127 uint8_t index = MAX_EMAC_INSTANCE, errFound = FALSE;
1129 struct hdkif *hdkif;
1132 hdkif = &hdkif_data[--index];
1133 if(EMACIntVectorGet(hdkif->emac_base) & EMAC_MACINVECTOR_HOSTPEND)errFound = TRUE;
1135 if(!errFound)return FALSE; /* this is not the cause of the interrupt */
1136 rpp_sci_printk("HOSTPEND err\n");
1137 reg = HWREG(hdkif->emac_base + EMAC_MACSTATUS);
1138 rpp_sci_printk("TXCHERR: %d at CH: %d\n", ((reg >> EMAC_MACSTATUS_TXERRCODE_SHIFT) & 0x7), ((reg >> EMAC_MACSTATUS_TXERRCH_SHIFT) & 0x7));
1139 rpp_sci_printk("RXCHERR: %d at CH: %d\n", ((reg >> EMAC_MACSTATUS_RXERRCODE_SHIFT) & 0x7), ((reg >> EMAC_MACSTATUS_RXERRCH_SHIFT) & 0x7));
1140 /* no acknowledge - emac module has to be restarted */
1141 return TRUE; /* this was the reason of interrupt */
1144 #if PHY_LINK_MONITOR_INT
1145 boolean_t LinkIntHandler(void)
1147 uint8_t index = MAX_EMAC_INSTANCE, phyFound = FALSE;
1148 struct hdkif *hdkif;
1149 uint16_t regContent;
1150 volatile unsigned int autonegFinishWait = 0xFFFFFFF;
1151 volatile unsigned int dhcpBindWait = 0x3FFFFFFF;
1153 /* check each instance, whether this interrupt was meant for this function, if not return FALSE so other function may be tried */
1155 hdkif = &hdkif_data[--index];
1156 if( hdkif->phy_addr == (HWREG(hdkif->mdio_base + MDIO_USERPHYSEL0) & 0x1f) && EMACIntVectorGet(hdkif->emac_base) & EMAC_MACINVECTOR_LINKINT0 )phyFound = TRUE;
1158 if(!phyFound)return FALSE;
1159 struct netif *netif = &hdkNetIF[hdkif->inst_num];
1161 /* we handles here connection of cable after startup, not changes of linkstatus */
1163 /* wait for autonegotiation to be done */
1165 while(hdkif->phy_autoneg_is_done(hdkif->mdio_base, hdkif->phy_addr) == FALSE);
1166 #else /* ONCE_LINK_SETUP */
1167 while(hdkif->phy_autoneg_is_done(hdkif->mdio_base, hdkif->phy_addr) == FALSE & autonegFinishWait--);
1168 #endif /* ONCE_LINK_SETUP */
1170 /* provide informations retrieved from autoneg to EMAC module */
1171 hdkif->phy_partnerability(hdkif->mdio_base, hdkif->phy_addr, ®Content);
1172 if (regContent & (PHY_100BASETXDUPL_m | PHY_10BASETDUPL_m)) {
1173 EMACDuplexSet(hdkif->emac_base, EMAC_DUPLEX_FULL);
1174 /* this is right place to implement transmit flow control if desired - set TXFLOWEN in MACCONTROL */
1175 } else if (regContent & (PHY_100BASETX_m | PHY_10BASET_m)) {
1176 EMACDuplexSet(hdkif->emac_base, EMAC_DUPLEX_HALF);
1178 /* acknowledge MDIO module */
1179 HWREG(hdkif->mdio_base + MDIO_LINKINTRAW) = MDIO_LINKINTMASKED_USERPHY0;
1180 HWREG(hdkif->mdio_base + MDIO_LINKINTMASKED) = MDIO_LINKINTMASKED_USERPHY0;
1182 /* acknowledge EMAC control module by writing appropriate key to MACEOIVECTOR */
1183 EMACCoreIntAck(hdkif->emac_base, EMAC_INT_CORE0_MISC);
1186 /* if link is up configure lwip struct netif */
1187 if(rpp_eth_phylinkstat(hdkif->inst_num))
1189 #if STATIC_IP_ADDRESS
1190 netif_set_up(netif);
1191 #elif LWIP_DHCP /* STATIC_IP_ADDRESS-LWIP_DHCP */
1192 if(dhcp_start(netif) != ERR_OK) /* XXX: can't be used from ISR (mem_malloc()) */
1194 return DHCP_MEM_ERR;
1197 while(netif->dhcp->state != DHCP_BOUND);
1199 while(netif->dhcp->state != DHCP_BOUND & dhcpBindWait--);
1202 /* acknowledge MDIO module */
1203 HWREG(hdkif->mdio_base + MDIO_LINKINTRAW) = MDIO_LINKINTMASKED_USERPHY0;
1204 HWREG(hdkif->mdio_base + MDIO_LINKINTMASKED) = MDIO_LINKINTMASKED_USERPHY0;
1206 /* acknowledge EMAC control module by writing appropriate key to MACEOIVECTOR */
1207 EMACCoreIntAck(hdkif->emac_base, EMAC_INT_CORE0_MISC);
1211 #else /* LWIP_DHCP-LWIP_AUTOIP FIXME: there should be some kind of waiting till ip is assigned */
1212 autoip_start(netif);
1213 #endif /* STATIC_IP_ADDRESS-LWIP_DHCP-LWIP_AUTOIP */
1215 /* turn this interrupt off */
1216 HWREG(hdkif->emac_ctrl_base + EMAC_CTRL_CnMISCEN(0)) &= (~EMAC_CTRL_MISC_LINKINT0ENB & 0xf);
1217 #endif /* ONCE_LINK_SETUP */
1222 /* acknowledge MDIO module */
1223 HWREG(hdkif->mdio_base + MDIO_LINKINTRAW) = MDIO_LINKINTMASKED_USERPHY0;
1224 HWREG(hdkif->mdio_base + MDIO_LINKINTMASKED) = MDIO_LINKINTMASKED_USERPHY0;
1226 /* acknowledge EMAC control module by writing appropriate key to MACEOIVECTOR */
1227 EMACCoreIntAck(hdkif->emac_base, EMAC_INT_CORE0_MISC);
1230 #if STATIC_IP_ADDRESS
1231 netif_set_down(netif);
1232 #elif LWIP_DHCP /* STATIC_IP_ADDRESS-LWIP_DHCP */
1234 #endif /* STATIC_IP_ADDRESS-LWIP_DHCP-LWIP_AUTOIP */
1238 /* acknowledge MDIO module */
1239 HWREG(hdkif->mdio_base + MDIO_LINKINTRAW) = MDIO_LINKINTMASKED_USERPHY0;
1240 HWREG(hdkif->mdio_base + MDIO_LINKINTMASKED) = MDIO_LINKINTMASKED_USERPHY0;
1242 /* acknowledge EMAC control module by writing appropriate key to MACEOIVECTOR */
1243 EMACCoreIntAck(hdkif->emac_base, EMAC_INT_CORE0_MISC);
1247 #endif /* PHY_LINK_MONITOR_INT */
1248 #endif /* FREERTOS_POSIX */