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];
148 return PHY_link_status_get(hdkif->mdio_base, hdkif->phy_addr, 1);
151 #define BYTE_BUFF_SIZE 2
152 #define OFFSET_MAC_LETTERS (MAC_BIG_LETTERS ? 'A' : 'a')
153 /* puts string of MAC address assigned to EMAC instance reffered by instNum into *mac */
154 void rpp_eth_get_macAddrStr(uint32_t instNum, uint8_t *macStr)
156 uint8_t index, outindex = 0;
157 char buff[BYTE_BUFF_SIZE];
158 struct hdkif *hdkif = &hdkif_data[instNum];
160 for (index = 0; index < MAC_ADDR_LEN; index++) {
161 if (index) macStr[outindex++] = ':';
162 buff[0] = (hdkif->mac_addr[(MAC_ADDR_LEN - 1) - index] >> 4);
163 buff[1] = (hdkif->mac_addr[(MAC_ADDR_LEN - 1) - index] & 0xf);
164 macStr[outindex++] = (buff[0] < 10) ? (buff[0] + '0') : (buff[0] - '\012' + OFFSET_MAC_LETTERS);
165 macStr[outindex++] = (buff[1] < 10) ? (buff[1] + '0') : (buff[1] - '\012' + OFFSET_MAC_LETTERS);
167 macStr[outindex] = '\0';
170 /* @param ip will be filled accroding to content of ipstr */
171 err_t rpp_eth_stringToIP(ip_addr_t *ip, uint8_t *ipstr)
173 uint8_t charProccessed, index = 0, dotindex = 0xff, tmp = 0, dots = 0, fldEdit = 0;
176 for (charProccessed = ipstr[index]; (charProccessed >= '0' && charProccessed <= '9') || charProccessed == '.'; charProccessed = ipstr[++index]) {
177 if (charProccessed == '.') {
178 if (++dotindex == index) {
184 ipaddr = (ipaddr << 8) + tmp;
195 tmp = tmp*10 + charProccessed - '0';
198 if (dots != 3 || !fldEdit)
199 /* if unsuccesful, don't modify previous content */
201 ipaddr = (ipaddr << 8) + tmp;
206 /* returns number in range 0-65535 where 0 is error */
207 uint16_t rpp_eth_portStrToInt(uint8_t *string)
212 for (index = 0; string[index] != '\0'; index++) {
213 if (string[index] < '0' || string[index] > '9') {
217 portNO = portNO * 10 + string[index] - '0';
222 struct netif*rpp_eth_get_netif(uint32_t instNum)
224 return &hdkNetIF[instNum];
227 /********************************************** forward declares **********************************************/
230 * interface initializes
232 err_t rpp_eth_lwip_init(struct netif *netif);
235 * Initializes hw such as PHY, MDIO, EMAC, EMAC control module
237 * @return SUCCESS if initialization successful.\n
238 * FAILURE if initialization not successful.
240 err_t rpp_eth_hw_init(struct hdkif *hdkif);
243 * Initializes hw, after lwIP was initialized and
244 * OS was initialized in case OS is used.
246 err_t rpp_eth_hw_init_postInit(struct netif *netif);
248 /********************************************** utility functions **********************************************/
251 * Function to set the MAC address to the interface
252 * @param inst_num the instance number
254 * @note mac_addr[0] is considered MSB
256 void hdkif_macaddrset(u32_t inst_num, u8_t *mac_addr)
261 hdkif = &hdkif_data[inst_num];
263 /* set MAC hardware address */
264 for (temp = 0; temp < MAC_ADDR_LEN; temp++) {
265 hdkif->mac_addr[temp] = mac_addr[(MAC_ADDR_LEN - 1) - temp];
269 rpp_eth_get_macAddrStr(inst_num, macStr);
270 rpp_debug_printf("Setting MAC... %s\r\n", macStr);
275 * Function to setup the instance parameters inside the interface
279 static void hdkif_inst_config(struct hdkif *hdkif)
281 if (hdkif->inst_num == 0) {
282 hdkif->emac_base = EMAC_BASE_m(0);
283 hdkif->emac_ctrl_base = EMAC_CTRL_BASE_m(0);
284 hdkif->emac_ctrl_ram = EMAC_CTRL_RAM_BASE_m(0);
285 hdkif->mdio_base = MDIO_BASE_m(0);
286 hdkif->phy_addr = DEFAULT_PHY_ADDR; /* Default address of PHY on "MDIO bus" (depends on PHY hw configuration) */
287 hdkif->phy_autoneg = PHY_auto_negotiate;
288 hdkif->phy_autoneg_start = PHY_start_auto_negotiate;
289 hdkif->phy_autoneg_is_done = PHY_is_done_auto_negotiate;
290 hdkif->phy_partnerability = PHY_partner_ability_get;
294 /********************************************** initializing functions **********************************************/
296 int8_t rpp_eth_init()
299 int8_t retVal = SUCCESS;
304 /* config of EMAC instances and other stuff */
305 for (instNum = 0; instNum < MAX_EMAC_INSTANCE; instNum++) {
306 hdkif_data[instNum].inst_num = instNum;
307 hdkif_inst_config(&hdkif_data[instNum]); /* hdkif_inst_config must contain instNum specific settings */
308 if (retVal = rpp_eth_hw_init(&hdkif_data[instNum])) {
310 rpp_sci_printk("rpp_eth_hw_init: %d", retVal);
316 /* when one of instances was not initialized correctly return FAILURE without setting initialized variable to TRUE */
317 if (retVal) return FAILURE;
330 int8_t rpp_eth_init_postInit(uint32_t instNum, uint8_t *macArray)
334 int8_t retVal = SUCCESS;
335 struct netif *netif = &hdkNetIF[instNum];
336 u8_t mac_addr[MAC_ADDR_LEN] = RPP_MAC_ADDR;
338 /* ----- lwIP stuff ----- */
339 struct ip_addr ip_addr;
340 struct ip_addr net_mask;
341 struct ip_addr gw_addr;
342 volatile unsigned int dhcpBindWait = 0x3FFFFFFF;
344 if (macArray == NULL)
345 macArray = mac_addr; /* use default MAC */
346 hdkif_macaddrset(instNum, macArray);
352 /* this can be called only within post OS init */
353 tcpip_init(NULL,NULL); /* calls lwip_init() implicitly, starts lwIP task (thread), when started function given to tcpip_init is executed first */
356 #if STATIC_IP_ADDRESS
357 ip_addr.addr = htonl(RPP_IP_ADDR);
358 net_mask.addr = htonl(RPP_NETMASK);
359 gw_addr.addr = htonl(RPP_GW);
360 #else /* STATIC_IP_ADDRESS */
364 #endif /* STATIC_IP_ADDRESS */
366 /* init and add new netif */
367 /* add new network interface to lwIP list of ifaces and initialize netif with specific function */
369 if ( netif_add(netif, &ip_addr, &net_mask, &gw_addr, (void*)instNum, rpp_eth_lwip_init, ethernet_input) == NULL )
371 if ( netif_add(netif, &ip_addr, &net_mask, &gw_addr, (void*)instNum, rpp_eth_lwip_init, tcpip_input) == NULL )
374 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)) {
394 rpp_debug_printf((const char*)"cable connected ... setting IP params\r\n");
395 #if STATIC_IP_ADDRESS
397 #elif LWIP_DHCP /* STATIC_IP_ADDRESS-LWIP_DHCP */
398 if (dhcp_start(netif) != ERR_OK) {
399 rpp_debug_printf("dhcp mem err\r\n");
402 rpp_debug_printf("binding DHCP\r");
403 while ((netif->dhcp->state != DHCP_BOUND) && (dhcpBindWait--)) /*sys_check_timeouts()*/;
405 rpp_debug_printf("dhcp binding timeout...\r\n");
406 #else /* LWIP_DHCP-LWIP_AUTOIP FIXME: there should be some kind of waiting till ip is assigned */
408 #endif /* STATIC_IP_ADDRESS-LWIP_DHCP-LWIP_AUTOIP */
410 uint8_t ipString[16];
411 rpp_eth_getIPDecimalStr(netif->ip_addr, ipString);
412 rpp_debug_printf("Address: %s\r\n", ipString);
413 rpp_eth_getIPDecimalStr(netif->netmask, ipString);
414 rpp_debug_printf("Netmask: %s\r\n", ipString);
415 rpp_eth_getIPDecimalStr(netif->gw, ipString);
416 rpp_debug_printf("Gateway: %s\r\n", ipString);
421 rpp_debug_printf((const char*)"cable not connected\r\n");
422 retVal = PHY_LINK_DOWN;
425 #else /* !PHY_LINK_MONITOR_INT */
426 /* now when we established environment needed for phy link status change we can allow it */
427 /* set PHY number which is monitored for link changes in MDIO and enable interrupt */
428 HWREG(hdkif->mdio_base + MDIO_USERPHYSEL0) = ((hdkif->phy_addr && 0x1f) | MDIO_USERPHYSEL0_LINKINTENB);
430 /* enable MISC interrupt - link monitoring in EMAC controle module */
431 HWREG(hdkif->emac_ctrl_base + EMAC_CTRL_CnMISCEN(0)) |= EMAC_CTRL_MISC_LINKINT0ENB;
433 #endif /* !PHY_LINK_MONITOR_INT */
434 /* ----- end - lwIP stuff ----- */
436 postInitialized = TRUE;
440 err_t rpp_eth_lwip_init(struct netif *netif)
442 #if LWIP_NETIF_HOSTNAME
443 /* Initialize interface hostname */
444 netif->hostname = "rpp";
445 #endif /* LWIP_NETIF_HOSTNAME */
447 uint32_t instNum = (uint32_t)netif->state;
448 /*netif->num = instNum; - auto-initiated when netif_add is called */
450 /* netif->state contained instNum, we replace it with corresponding hdkif */
451 struct hdkif *hdkif = &hdkif_data[instNum];
452 netif->state = hdkif;
454 netif->name[0] = IFNAME0;
455 netif->name[1] = IFNAME1;
458 hdkif->waitTicksForPHYAneg = TICKS_PHY_AUTONEG;
462 * Initialize the snmp variables and counters inside the struct netif.
463 * The last argument should be replaced with your link speed, in units
464 * of bits per second.
466 NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, 10000000);
468 /* We directly use etharp_output() here to save a function call.
469 * You can instead declare yo_SKIP_TO_HWur own function an call etharp_output()
470 * from it if you have to do some checks before sending (e.g. if link
473 netif->output = etharp_output;
474 netif->linkoutput = rpp_eth_send;
475 return rpp_eth_hw_init_postInit(netif);
478 #define INIT_ONLY_AFTER_RESET 1
479 err_t rpp_eth_hw_init(struct hdkif *hdkif)
485 /* Deactivate reset pin of PHY */
486 /* for hw reset of PHY, it is necessary that PIN_NAME_ETHRST is 1us logical low state, before putting it to logical high */
487 #if !INIT_ONLY_AFTER_RESET
489 uint8_t index = 80; /* Initially used to hw reset of PHY connected to GIO pin. This means 1us - for 80MHz clock. */
491 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. */
493 hal_gpio_pin_set_value(*hal_gpio_pin_get_dsc(PIN_NAME_ETHRST,-1),0);
495 #endif /* !INIT_ONLY_AFTER_RESET */
496 /* we have pull-down resistor, so after reset, we only need to put ETHRST pin to log. high */
497 hal_gpio_pin_set_value(*hal_gpio_pin_get_dsc(PIN_NAME_ETHRST,-1),1);
499 /* initializes EMAC control module and EMAC module */
500 EMACInit(hdkif->emac_ctrl_base, hdkif->emac_base);
501 /* initializes MDIO module (reset) */
502 MDIOInit(hdkif->mdio_base, 0x0, 0x0);
504 /* enable used receive channel if necessary */
507 /* try to read random register from defaultPhy to make MDIO fill alive bit for this one if it returned
508 ACK bit in msg response - this must be done, because MDIO has not set alive bit of PHY after that
509 short time after MDIOInit() */
510 MDIOPhyRegRead(hdkif->mdio_base, hdkif->phy_addr, PHY_BMSR, ®Content);
512 /* find first alive PHY - or use default if alive */
513 physAlive = MDIOPhyAliveStatusGet(hdkif->mdio_base);
514 if (!(physAlive & (1 << hdkif->phy_addr))) {
515 #if FIND_FIRST_PHY_ALIVE
516 for (index = 0; index < NUM_OF_PHYs; index++) { /* i..PHY tested */
517 if (physAlive && (1 << index)) {
518 hdkif->phy_addr = index;
523 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 */
524 physAlive = MDIOPhyAliveStatusGet(hdkif->mdio_base); /* get updated register */
525 if (physAlive && (1 << index)) {
526 hdkif->phy_addr = index;
532 rpp_debug_printf("no phy found, phys: %d\r\n", physAlive);
536 rpp_debug_printf("default phy not alive\r\n");
537 return DFLT_PHY_NOT_ALIVE;
541 /* start autonegotiation and check on completion later or when complete link register will be updated */
542 hdkif->phy_autoneg_start(hdkif->mdio_base, hdkif->phy_addr, PHY_100BASETXDUPL_m | PHY_100BASETX_m | PHY_10BASETDUPL_m | PHY_10BASET_m);
544 /* TODO: you can implement init of receive flow control somewhere here if desired - set RXBUFFERFLOWEN in MACCONTROL */
547 /* acknowledge EMAC control module RX, TX and MISC interrupts */
548 EMACCoreIntAck(hdkif->emac_base, EMAC_INT_CORE0_RX);
549 EMACCoreIntAck(hdkif->emac_base, EMAC_INT_CORE0_TX);
550 EMACCoreIntAck(hdkif->emac_base, EMAC_INT_CORE0_MISC);
552 /* sets which channel will receive broadcasts */
553 EMACRxBroadCastEnable(hdkif->emac_base, CHANNEL);
554 /* 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 */
555 EMACRxPromiscEnable(hdkif->emac_base, CHANNEL);
556 /* enables unicast */
557 EMACRxUnicastSet(hdkif->emac_base, CHANNEL);
559 /* enable TX and RX interrupts in both EMAC module and EMAC control module */
560 EMACTxIntPulseEnable(hdkif->emac_base, hdkif->emac_ctrl_base, 0, CHANNEL);
561 EMACRxIntPulseEnable(hdkif->emac_base, hdkif->emac_ctrl_base, 0, CHANNEL);
563 /* switch of send bd handling and when sending, just wait till send was done and then return (making the driver simple) */
564 //vim_mask_clr(TXinterruptVectorNumber);
569 err_t rpp_eth_hw_init_postInit(struct netif *netif)
571 volatile unsigned int autonegFinishWait = 0x3FFFFFFF; /* 0x3FFFFFFF is for 80MHz aproximately 13s */
573 uint32_t num_bd, pbuf_cnt = 0;
574 volatile struct emac_tx_bd *curr_txbd, *last_txbd;
575 volatile struct emac_rx_bd *curr_rxbd, *last_rxbd;
580 struct hdkif *hdkif = (struct hdkif*)netif->state;
582 rxch = &(hdkif->rxch);
583 txch = &(hdkif->txch);
585 rpp_debug_printf("autoneg started - check on cable if it's connected!\r\n");
589 * Initialize the Descriptor Memory For TX and RX
590 * Only Channel 0 is supported for both TX and RX
592 txch->free_head = ((volatile struct emac_tx_bd*)hdkif->emac_ctrl_ram);
593 txch->next_bd_to_process = txch->free_head;
594 txch->active_tail = NULL;
596 /* Set the number of descriptors for the channel */
597 num_bd = (SIZE_EMAC_CTRL_RAM >> 1) / sizeof(struct emac_tx_bd); /* take half of CPPI ram for TX BDs */
599 curr_txbd = txch->free_head;
601 /* Initialize all the TX buffer Descriptors */
603 curr_txbd->next = curr_txbd + 1;
604 curr_txbd->flags_pktlen = 0;
605 last_txbd = curr_txbd;
606 curr_txbd = curr_txbd->next;
608 last_txbd->next = txch->free_head;
610 /* Initialize the descriptors for the RX channel */
611 rxch->active_head = (volatile struct emac_rx_bd*)(curr_txbd);
612 rxch->free_head = NULL;
613 rxch->freed_pbuf_len = 0;
614 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) */
615 curr_rxbd = rxch->active_head;
616 last_rxbd = curr_rxbd;
619 ** Allocate the pbufs for the maximum count permitted or till the
620 ** number of buffer desceriptors expire, which ever is earlier.
622 while (pbuf_cnt < MAX_RX_PBUF_ALLOC) {
623 p = pbuf_alloc(PBUF_RAW, PBUF_LEN_MAX, PBUF_POOL);
626 /* write the descriptors if there are enough numbers to hold the pbuf*/
627 if (((uint32_t)pbuf_clen(p)) <= num_bd)
628 for (q = p; q != NULL; q = q->next) {
629 curr_rxbd->bufptr = (uint8_t*)(q->payload);
630 curr_rxbd->bufoff_len = q->len;
631 curr_rxbd->next = curr_rxbd + 1;
632 curr_rxbd->flags_pktlen = EMAC_DSC_FLAG_OWNER;
636 last_rxbd = curr_rxbd;
637 curr_rxbd = curr_rxbd->next;
641 /* free the allocated pbuf if no free descriptors are left */
652 if (!pbuf_cnt) rpp_debug_printf("no pbufs attached to rx buffer descriptors during init\n");
654 last_rxbd->next = NULL;
655 rxch->active_tail = last_rxbd;
657 num_bd = ( ((uint32_t)rxch->active_tail - (uint32_t)rxch->active_head) / sizeof(struct emac_rx_bd) + 1 );
658 rpp_debug_printf("%d pbuf chains allocated for %d rx buffer descriptors\n", pbuf_cnt, num_bd);
659 /* for flow control or QoS - there could be set an interrupt when we reach preset amount of receive descriptors remaining - see RXBUFFERFLOWEN */
660 /* EMACNumFreeBufSet(hdkif->emac_base, CHANNEL, num_bd); */ /* not used */
662 /* set header descriptor pointers - this shows EMAC which descriptor is beginning one for writing received frames/packets */
663 EMACRxHdrDescPtrWrite(hdkif->emac_base, (uint32_t)rxch->active_head, CHANNEL);
667 /* set length of MAC address */
668 netif->hwaddr_len = MAC_ADDR_LEN;
670 /* set MAC address */
671 for (regContent = 0; regContent < MAC_ADDR_LEN; regContent++) {
672 netif->hwaddr[regContent] = hdkif->mac_addr[(MAC_ADDR_LEN - 1) - regContent];
675 /* maximum transfer unit */
676 netif->mtu = MAX_TRANSFER_UNIT;
678 /* device capabilities */
679 /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */
680 netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;
682 /* lwIP stuff - end */
684 /* for flow control frames */
685 EMACMACSrcAddrSet(hdkif->emac_base, hdkif->mac_addr);
687 /* Be sure to program all eight MAC address registers -
688 * whether the receive channel is to be enabled or not.
690 for (regContent = 0; regContent < 8; regContent++) /* i..channel_number */
691 EMACMACAddrSet(hdkif->emac_base, regContent, hdkif->mac_addr, EMAC_MACADDR_NO_MATCH_NO_FILTER);
693 #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 */
694 /* wait for autonegotiation to be done or continue, when delay was reached */
696 uint32_t timeToWake = hdkif->waitTicksForPHYAneg + sys_jiffies();
697 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 */
699 while (hdkif->phy_autoneg_is_done(hdkif->mdio_base, hdkif->phy_addr) == FALSE && autonegFinishWait--) ; /* wait till aneg done */
702 if (hdkif->phy_autoneg_is_done(hdkif->mdio_base, hdkif->phy_addr) != FALSE)
703 rpp_debug_printf("aneg finished \r\n");
705 rpp_debug_printf("aneg timeout \r\n");
707 /* provide informations retrieved from autoneg to EMAC module */
708 hdkif->phy_partnerability(hdkif->mdio_base, hdkif->phy_addr, ®Content);
709 if (regContent & (PHY_100BASETXDUPL_m | PHY_10BASETDUPL_m))
710 EMACDuplexSet(hdkif->emac_base, EMAC_DUPLEX_FULL);
711 /* this is right place to implement transmit flow control if desired - set TXFLOWEN in MACCONTROL */
712 else if (regContent & (PHY_100BASETX_m | PHY_10BASET_m))
713 EMACDuplexSet(hdkif->emac_base, EMAC_DUPLEX_HALF);
715 rpp_debug_printf("Unknown duplex mode\r\n");
716 return UNKN_DUPLEX_MODE;
718 #endif /* !PHY_LINK_MONITOR_INT */
720 /* enable hostpend interrupts in emac module */
721 HWREG(hdkif->emac_base + EMAC_MACINTMASKSET) |= EMAC_MACINTMASKSET_HOSTMASK;
723 /* enable hostpend interrupts in emac control module */
724 HWREG(hdkif->emac_ctrl_base + EMAC_CTRL_CnMISCEN(0)) |= EMAC_CTRL_MISC_HOSTPENDENB;
726 /* enable EMAC's Media Independent Interface TX and RX */
727 EMACMIIEnable(hdkif->emac_base);
728 /* enable EMAC transmit */
729 EMACTxEnable(hdkif->emac_base);
730 /* enable EMAC receive */
731 EMACRxEnable(hdkif->emac_base);
749 /********************************************** send and receive functions / ISRs **********************************************/
751 err_t rpp_eth_send(struct netif *netif, struct pbuf *p)
753 err_t retVal = SUCCESS;
755 SYS_ARCH_DECL_PROTECT(lev);
758 * This entire function must run within a "critical section" to preserve
759 * the integrity of the transmit pbuf queue.
762 SYS_ARCH_PROTECT(lev);
764 /* protect from access receive acces from interrupt */
765 #if !SYS_LIGHTWEIGHT_PROT
766 uint32_t prevProt = (uint32_t)_get_CPSR() & 0x80;
771 /* adjust the packet length if less than minimum required */
772 if (p->tot_len < MIN_PKT_LEN) {
773 p->tot_len = MIN_PKT_LEN;
774 p->len = MIN_PKT_LEN;
777 /* call the actual transmit function */
778 retVal = rpp_eth_send_raw(netif, p);
780 /* Return to prior interrupt state and return. */
781 SYS_ARCH_UNPROTECT(lev);
783 #if !SYS_LIGHTWEIGHT_PROT
784 if (!prevProt) _enable_IRQ();
791 * send packet, blocks till it is sent
792 * every send uses bds on the beginning of CPPI RAM
794 err_t rpp_eth_send_raw(struct netif *netif, struct pbuf *p)
797 volatile struct emac_tx_bd *curr_bd, *bd_end;
800 hdkif = (struct hdkif*)netif->state;
801 curr_bd = (struct emac_tx_bd*)hdkif->emac_ctrl_ram;
803 /* destroy all flags previously set and update the total packet length */
804 curr_bd->flags_pktlen = p->tot_len;
806 /* Indicate the start of the packet */
807 curr_bd->flags_pktlen |= (EMAC_DSC_FLAG_SOP | EMAC_DSC_FLAG_OWNER);
809 /* Copy pbuf information into TX buffer descriptors */
810 for (q = p; q != NULL; q = q->next) {
812 /* Intialize the buffer pointer and length */
813 curr_bd->bufptr = (uint8_t*)(q->payload);
814 curr_bd->bufoff_len = (q->len) & 0xFFFF;
817 curr_bd = curr_bd->next;
818 curr_bd->flags_pktlen = 0x0; /* destroy all previously set flags */
821 /* Indicate the end of the packet */
823 bd_end->flags_pktlen |= EMAC_DSC_FLAG_EOP;
825 /* don't write to hdp till it turns zero */
826 while (0 != *((volatile uint32_t*)(hdkif->emac_base + EMAC_TXHDP(CHANNEL)) )) ;
827 /* notify hw where to start transmission from */
828 HWREG(hdkif->emac_base + EMAC_TXHDP(CHANNEL)) = hdkif->emac_ctrl_ram;
829 //EMACTxHdrDescPtrWrite(hdkif->emac_base, hdkif->emac_ctrl_ram, CHANNEL);
831 /* wait till queued pkt is sent */
832 vim_mask_set(TXinterruptVectorNumber);
833 xSemaphoreTake(hdkif->goTX, portMAX_DELAY);
834 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("!");
836 EMACTxCPWrite(hdkif->emac_base, CHANNEL, (uint32_t)bd_end);
838 EMACCoreIntAck(hdkif->emac_base, EMAC_INT_CORE0_TX);
840 /* restore bds chain */
841 bd_end->next = curr_bd;
843 LINK_STATS_INC(link.xmit);
847 void rpp_eth_recv_raw(void *arg)
849 volatile struct emac_rx_bd *curr_bd, *processed_bd, *curr_tail, *last_bd;
850 volatile struct pbuf *pbuf, *q, *new_pbuf;
851 uint32_t ex_len, len_to_alloc;
853 struct netif *netif = (struct netif*)arg;
854 struct hdkif *hdkif = (struct hdkif*)netif->state;
857 rxch = &(hdkif->rxch);
860 #if !NO_SYS && !ONE_DRIVER_TASK
861 SYS_ARCH_DECL_PROTECT(lev);
863 vim_mask_set(RXinterruptVectorNumber);
864 sys_arch_sem_wait(&(hdkif->goRX), 0);
865 SYS_ARCH_PROTECT(lev);
869 /* Get the bd which contains the earliest filled data */
870 curr_bd = rxch->active_head;
871 last_bd = rxch->active_tail;
873 if (curr_bd->flags_pktlen & EMAC_DSC_FLAG_SOP != EMAC_DSC_FLAG_SOP) rpp_debug_printf("ERR: Active head is not SOP!\n");
876 * Process the descriptors as long as data is available
877 * when the DMA is receiving data, SOP flag will be set
879 while (curr_bd->flags_pktlen & EMAC_DSC_FLAG_SOP) {
882 /* Start processing once the packet is loaded */
883 if ((curr_bd->flags_pktlen & EMAC_DSC_FLAG_OWNER) != EMAC_DSC_FLAG_OWNER) {
884 if (rxch->free_head == NULL)
885 /* this bd chain will be freed after processing */
886 rxch->free_head = curr_bd;
888 /* Get the total length of the packet. curr_bd points to the start
891 tot_len = (curr_bd->flags_pktlen) & 0xFFFF;
893 /* Get the start of the pbuf queue */
897 /* Get the pbuf pointer which is associated with the current bd */
898 pbuf = curr_bd->pbuf;
900 /* If the earlier pbuf ended, update the chain */
901 if (pbuf->next == NULL)
902 pbuf->next = (struct pbuf*)(curr_bd->next)->pbuf;
904 len_to_alloc += pbuf->len;
905 /* Update the len and tot_len fields for the pbuf in the chain*/
906 pbuf->len = (curr_bd->bufoff_len) & 0xFFFF;
907 pbuf->tot_len = tot_len - ex_len;
908 processed_bd = curr_bd;
910 curr_bd = curr_bd->next;
912 if (curr_bd == NULL) rpp_debug_printf("rx curr_bd set to zero!\n");
914 /* 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 */
915 } while ((processed_bd->flags_pktlen & EMAC_DSC_FLAG_EOP) != EMAC_DSC_FLAG_EOP);
918 * Close the chain for this pbuf. A full packet is received in
919 * this pbuf chain. Now this pbuf can be given to upper layers for
920 * processing. The start of the pbuf chain is now 'q'.
924 /* Adjust the link statistics */
925 LINK_STATS_INC(link.recv);
927 /* Process the packet - this function is specified while adding netif using netif_add() function */
928 if (netif->input((struct pbuf*)q, netif) != ERR_OK) {
929 /* Adjust the link statistics */
930 LINK_STATS_INC(link.memerr);
931 LINK_STATS_INC(link.drop);
934 /* Acknowledge that this packet is processed */
935 EMACRxCPWrite(hdkif->emac_base, CHANNEL, (unsigned int)processed_bd);
938 rxch->active_head = curr_bd;
940 rxch->active_head = processed_bd + 1; //todo:reconsider
943 * The earlier pbuf chain is freed from the upper layer. So, we need to
944 * allocate a new pbuf chain and update the descriptors with the pbuf info.
945 * To support chaining, the total length freed by the upper layer is tracked.
946 * Care should be taken even if the allocation fails.
949 * now len_to_alloc will contain the length of the pbuf which was freed
950 * from the upper layer
952 rxch->freed_pbuf_len += len_to_alloc;
954 /* if there is not enough pbufs predefined, we need application to process them and return them back to pool -> YIELD */
955 /* 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
956 * from pool, then in *bd pointing to NULL might be such values (EMAC_DSC_FLAG_SOP == 1 &| EMAC_DSC_FLAG_OWNER == 0), that we
957 * stay cycling around */
960 new_pbuf = pbuf_alloc(PBUF_RAW, (rxch->freed_pbuf_len), PBUF_POOL);
962 if (new_pbuf != NULL)
965 xSemaphoreTake(pbufFreed, 0);
966 xSemaphoreTake(pbufFreed, portMAX_DELAY);
971 /* Write the descriptors with the pbuf info till either of them expires */
972 if (new_pbuf != NULL) {
973 curr_bd = rxch->free_head;
975 for (q = new_pbuf; (q != NULL) && (curr_bd != rxch->active_head); q = q->next) {
976 curr_bd->bufptr = (uint8_t*)(q->payload);
978 /* no support for buf_offset. RXBUFFEROFFSET register is 0 */
979 curr_bd->bufoff_len = (q->len) & 0xFFFF;
980 curr_bd->flags_pktlen = EMAC_DSC_FLAG_OWNER;
982 rxch->freed_pbuf_len -= q->len;
987 curr_bd = curr_bd->next;
991 * At this point either pbuf expired or no rxbd to allocate. If
992 * there are no, enough rx bds to allocate all pbufs in the chain,
993 * free the rest of the pbuf
996 pbuf_free((struct pbuf*)q);
998 curr_tail = rxch->active_tail;
999 last_bd->next = NULL;
1001 curr_tail->next = rxch->free_head;
1004 * Check if the reception has ended. If the EOQ flag is set, the NULL
1005 * Pointer is taken by the DMA engine. So we need to write the RX HDP
1006 * with the next descriptor.
1008 if (curr_tail->flags_pktlen & EMAC_DSC_FLAG_EOQ)
1009 EMACRxHdrDescPtrWrite(hdkif->emac_base, (u32_t)(rxch->free_head), CHANNEL);
1011 rxch->free_head = curr_bd;
1012 rxch->active_tail = last_bd;
1015 curr_bd = rxch->active_head;
1017 EMACCoreIntAck(hdkif->emac_base, EMAC_INT_CORE0_RX);
1019 #if !NO_SYS && !ONE_DRIVER_TASK
1020 SYS_ARCH_UNPROTECT(lev);
1025 void RxIntHandler(u32_t instNum)
1028 vim_mask_clr(RXinterruptVectorNumber);
1030 static portBASE_TYPE xHigherPriorityTaskWoken;
1031 xHigherPriorityTaskWoken = pdFALSE;
1033 /* 'Give' the semaphore to unblock the task. */
1034 xSemaphoreGiveFromISR(hdkif_data[instNum].goRX, NULL); // whenever there is time to process received packets, wake up task processing them
1036 if( xHigherPriorityTaskWoken == pdTRUE )
1039 /* Giving the semaphore unblocked a task, and the priority of the
1040 unblocked task is higher than or equal to the currently running task
1041 - force a context switch to ensure that the interrupt returns directly
1042 to the unblocked (higher priority) task.
1043 NOTE: The actual macro to use to force a context switch from an
1044 ISR is dependent on the port. This is the correct macro for the
1045 Open Watcom DOS port. Other ports may require different syntax.
1046 Refer to the examples provided for the port being used to determine
1047 the syntax required. */
1049 portSWITCH_CONTEXT();
1053 rpp_eth_recv_raw((void*)&hdkNetIF[instNum]);
1057 void TxIntHandler(u32_t instNum)
1059 //struct hdkif *hdkif = &hdkif_data[instNum];
1061 vim_mask_clr(TXinterruptVectorNumber); /* see sys_startup.c */
1062 xSemaphoreGiveFromISR(hdkif_data[instNum].goTX, NULL);
1065 //rpp_eth_send_bd_handler((void *) &hdkif_data[instNum]);
1073 * 1h SOP error; the buffer is the first buffer in a packet, but the SOP bit is not set in software.
1074 * 2h Ownership bit not set in SOP buffer
1075 * 3h Zero next buffer descriptor pointer without EOP
1076 * 4h Zero buffer pointer
1077 * 5h Zero buffer length
1078 * 6h Packet length error (sum of buffers is less than packet length)
1085 * 2h Ownership bit not set in SOP buffer
1087 * 4h Zero buffer pointer
1089 boolean_t HostPendErrHandler(void)
1091 uint8_t index = MAX_EMAC_INSTANCE, errFound = FALSE;
1093 struct hdkif *hdkif;
1096 hdkif = &hdkif_data[--index];
1097 if (EMACIntVectorGet(hdkif->emac_base) & EMAC_MACINVECTOR_HOSTPEND) errFound = TRUE;
1099 if (!errFound) return FALSE; /* this is not the cause of the interrupt */
1100 rpp_sci_printk("HOSTPEND err\n");
1101 reg = HWREG(hdkif->emac_base + EMAC_MACSTATUS);
1102 rpp_sci_printk("TXCHERR: %d at CH: %d\n", ((reg >> EMAC_MACSTATUS_TXERRCODE_SHIFT) & 0x7), ((reg >> EMAC_MACSTATUS_TXERRCH_SHIFT) & 0x7));
1103 rpp_sci_printk("RXCHERR: %d at CH: %d\n", ((reg >> EMAC_MACSTATUS_RXERRCODE_SHIFT) & 0x7), ((reg >> EMAC_MACSTATUS_RXERRCH_SHIFT) & 0x7));
1104 /* no acknowledge - emac module has to be restarted */
1105 return TRUE; /* this was the reason of interrupt */
1108 #if PHY_LINK_MONITOR_INT
1109 boolean_t LinkIntHandler(void)
1111 uint8_t index = MAX_EMAC_INSTANCE, phyFound = FALSE;
1112 struct hdkif *hdkif;
1113 uint16_t regContent;
1114 volatile unsigned int autonegFinishWait = 0xFFFFFFF;
1115 volatile unsigned int dhcpBindWait = 0x3FFFFFFF;
1117 /* check each instance, whether this interrupt was meant for this function, if not return FALSE so other function may be tried */
1119 hdkif = &hdkif_data[--index];
1120 if ( hdkif->phy_addr == (HWREG(hdkif->mdio_base + MDIO_USERPHYSEL0) & 0x1f) && EMACIntVectorGet(hdkif->emac_base) & EMAC_MACINVECTOR_LINKINT0 ) phyFound = TRUE;
1122 if (!phyFound) return FALSE;
1123 struct netif *netif = &hdkNetIF[hdkif->inst_num];
1125 /* we handles here connection of cable after startup, not changes of linkstatus */
1127 /* wait for autonegotiation to be done */
1129 while (hdkif->phy_autoneg_is_done(hdkif->mdio_base, hdkif->phy_addr) == FALSE) ;
1130 #else /* ONCE_LINK_SETUP */
1131 while (hdkif->phy_autoneg_is_done(hdkif->mdio_base, hdkif->phy_addr) == FALSE & autonegFinishWait--) ;
1132 #endif /* ONCE_LINK_SETUP */
1134 /* provide informations retrieved from autoneg to EMAC module */
1135 hdkif->phy_partnerability(hdkif->mdio_base, hdkif->phy_addr, ®Content);
1136 if (regContent & (PHY_100BASETXDUPL_m | PHY_10BASETDUPL_m))
1137 EMACDuplexSet(hdkif->emac_base, EMAC_DUPLEX_FULL);
1138 /* this is right place to implement transmit flow control if desired - set TXFLOWEN in MACCONTROL */
1139 else if (regContent & (PHY_100BASETX_m | PHY_10BASET_m))
1140 EMACDuplexSet(hdkif->emac_base, EMAC_DUPLEX_HALF);
1142 /* acknowledge MDIO module */
1143 HWREG(hdkif->mdio_base + MDIO_LINKINTRAW) = MDIO_LINKINTMASKED_USERPHY0;
1144 HWREG(hdkif->mdio_base + MDIO_LINKINTMASKED) = MDIO_LINKINTMASKED_USERPHY0;
1146 /* acknowledge EMAC control module by writing appropriate key to MACEOIVECTOR */
1147 EMACCoreIntAck(hdkif->emac_base, EMAC_INT_CORE0_MISC);
1150 /* if link is up configure lwip struct netif */
1151 if (rpp_eth_phylinkstat(hdkif->inst_num)) {
1152 #if STATIC_IP_ADDRESS
1153 netif_set_up(netif);
1154 #elif LWIP_DHCP /* STATIC_IP_ADDRESS-LWIP_DHCP */
1155 if (dhcp_start(netif) != ERR_OK) /* XXX: can't be used from ISR (mem_malloc()) */
1156 return DHCP_MEM_ERR;
1159 while (netif->dhcp->state != DHCP_BOUND) ;
1161 while (netif->dhcp->state != DHCP_BOUND & dhcpBindWait--) ;
1162 if (!dhcpBindWait) {
1163 /* acknowledge MDIO module */
1164 HWREG(hdkif->mdio_base + MDIO_LINKINTRAW) = MDIO_LINKINTMASKED_USERPHY0;
1165 HWREG(hdkif->mdio_base + MDIO_LINKINTMASKED) = MDIO_LINKINTMASKED_USERPHY0;
1167 /* acknowledge EMAC control module by writing appropriate key to MACEOIVECTOR */
1168 EMACCoreIntAck(hdkif->emac_base, EMAC_INT_CORE0_MISC);
1172 #else /* LWIP_DHCP-LWIP_AUTOIP FIXME: there should be some kind of waiting till ip is assigned */
1173 autoip_start(netif);
1174 #endif /* STATIC_IP_ADDRESS-LWIP_DHCP-LWIP_AUTOIP */
1176 /* turn this interrupt off */
1177 HWREG(hdkif->emac_ctrl_base + EMAC_CTRL_CnMISCEN(0)) &= (~EMAC_CTRL_MISC_LINKINT0ENB & 0xf);
1178 #endif /* ONCE_LINK_SETUP */
1183 /* acknowledge MDIO module */
1184 HWREG(hdkif->mdio_base + MDIO_LINKINTRAW) = MDIO_LINKINTMASKED_USERPHY0;
1185 HWREG(hdkif->mdio_base + MDIO_LINKINTMASKED) = MDIO_LINKINTMASKED_USERPHY0;
1187 /* acknowledge EMAC control module by writing appropriate key to MACEOIVECTOR */
1188 EMACCoreIntAck(hdkif->emac_base, EMAC_INT_CORE0_MISC);
1191 #if STATIC_IP_ADDRESS
1192 netif_set_down(netif);
1193 #elif LWIP_DHCP /* STATIC_IP_ADDRESS-LWIP_DHCP */
1195 #endif /* STATIC_IP_ADDRESS-LWIP_DHCP-LWIP_AUTOIP */
1199 /* acknowledge MDIO module */
1200 HWREG(hdkif->mdio_base + MDIO_LINKINTRAW) = MDIO_LINKINTMASKED_USERPHY0;
1201 HWREG(hdkif->mdio_base + MDIO_LINKINTMASKED) = MDIO_LINKINTMASKED_USERPHY0;
1203 /* acknowledge EMAC control module by writing appropriate key to MACEOIVECTOR */
1204 EMACCoreIntAck(hdkif->emac_base, EMAC_INT_CORE0_MISC);
1208 #endif /* PHY_LINK_MONITOR_INT */
1209 #endif /* FREERTOS_POSIX */