]> rtime.felk.cvut.cz Git - pes-rpp/rpp-lib.git/blob - rpp/src/rpp/eth.c
Reformated by uncrustify
[pes-rpp/rpp-lib.git] / rpp / src / rpp / eth.c
1 /**
2  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without modification,
6  * are permitted provided that the following conditions are met:
7  *
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.
15  *
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
25  * OF SUCH DAMAGE.
26  *
27  * This file is part of the lwIP TCP/IP stack.
28  *
29  * Author: Adam Dunkels <adam@sics.se>
30  *
31  */
32
33 /**
34  * Copyright (c) 2010 Texas Instruments Incorporated
35  *
36  * This file is dervied from the "ethernetif.c" skeleton Ethernet network
37  * interface driver for lwIP.
38  *
39  */
40 /* Copyright (C) 2013-2014 Czech Technical University in Prague
41  *
42  * Authors:
43  *     - Carlos Jenkins <carlos@jenkins.co.cr>
44  *     - Rostislav Lisový
45  *     - Jan Doležal <pm.jenik@gmail.com>
46  *
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.
51  *
52  * File : eth.c
53  * Abstract:
54  *     Ethernet Communication RPP API implementation file. Using one PHY.
55  *
56  * References:
57  *     eth.h
58  *     RPP API documentation.
59  */
60
61 #include "rpp/rpp.h"
62
63 #ifndef FREERTOS_POSIX
64
65 /* lwIP headers */
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 */
72 #include "lwip/def.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 */
78
79 #include "hal/hal.h"
80 #include "sys/sys.h" /* includes - sys/phy_dp83848h.h */
81 #include "drv/emac.h"
82 #include "os/os.h"
83 #include "types.h"
84
85
86 /* options */
87
88 /* Number of EMAC Instances */
89 #define MAX_EMAC_INSTANCE         1
90
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 */
96
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
101
102 /* Define those to better describe the network interface. */
103 #define IFNAME0                   'e'
104 #define IFNAME1                   'n'
105
106
107 /**
108  * Time to wait for autonegotiation in ticks.
109  */
110 #define TICKS_PHY_AUTONEG         4000
111
112 /**
113  * NOT IMPLEMENTED
114  * When cable is connected (link status goes up) autonegotiation and/or dhcp is started.
115  */
116 #define PHY_LINK_MONITOR_INT      0 /* turn on handling interrupt - not implemented now */
117 /* end options */
118
119 /* Defining interface for all the emac instances */
120 static struct hdkif hdkif_data[MAX_EMAC_INSTANCE];
121
122 /*
123 ** The lwIP network interface structure for the HDK Ethernet MAC.
124 */
125 static struct netif hdkNetIF[MAX_EMAC_INSTANCE];
126
127 /* rpp startup init indicator */
128 static boolean_t initialized = FALSE, postInitialized = FALSE;
129
130 boolean_t sendDone = TRUE;
131
132 /* free pbuf notification */
133 #if !NO_SYS
134 xSemaphoreHandle pbufFreed;
135 #endif
136
137 /**********************************************testing functions**********************************************/
138
139 boolean_t isPostInitialized()
140 {
141         return postInitialized;
142 }
143
144 uint32_t rpp_eth_phylinkstat(uint32_t instNum)
145 {
146         struct hdkif *hdkif = &hdkif_data[instNum];
147
148         return PHY_link_status_get(hdkif->mdio_base, hdkif->phy_addr, 1);
149 }
150
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)
155 {
156         uint8_t index, outindex = 0;
157         char buff[BYTE_BUFF_SIZE];
158         struct hdkif *hdkif = &hdkif_data[instNum];
159
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);
166         }
167         macStr[outindex] = '\0';
168 }
169
170 /* @param ip will be filled accroding to content of ipstr */
171 err_t rpp_eth_stringToIP(ip_addr_t *ip, uint8_t *ipstr)
172 {
173         uint8_t charProccessed, index = 0, dotindex = 0xff, tmp = 0, dots = 0, fldEdit = 0;
174         uint32_t ipaddr = 0;
175
176         for (charProccessed = ipstr[index]; (charProccessed >= '0' && charProccessed <= '9') || charProccessed == '.'; charProccessed = ipstr[++index]) {
177                 if (charProccessed == '.') {
178                         if (++dotindex == index) {
179                                 dots = 0;
180                                 break;
181                         }
182                         dotindex = index;
183
184                         ipaddr = (ipaddr << 8) + tmp;
185
186                         dots++;
187                         if (dots > 3) break;
188
189                         tmp = 0;
190                         fldEdit = FALSE;
191                 }
192                 else
193                 {
194                         fldEdit = TRUE;
195                         tmp = tmp*10 + charProccessed - '0';
196                 }
197         }
198         if (dots != 3 || !fldEdit)
199                 /* if unsuccesful, don't modify previous content */
200                 return FAILURE;
201         ipaddr = (ipaddr << 8) + tmp;
202         ip->addr = ipaddr;
203         return SUCCESS;
204 }
205
206 /* returns number in range 0-65535 where 0 is error */
207 uint16_t rpp_eth_portStrToInt(uint8_t *string)
208 {
209         uint8_t index;
210         uint16_t portNO = 0;
211
212         for (index = 0; string[index] != '\0'; index++) {
213                 if (string[index] < '0' || string[index] > '9') {
214                         portNO = 0;
215                         break;
216                 }
217                 portNO = portNO * 10 + string[index] - '0';
218         }
219         return portNO;
220 }
221
222 struct netif*rpp_eth_get_netif(uint32_t instNum)
223 {
224         return &hdkNetIF[instNum];
225 }
226
227 /********************************************** forward declares **********************************************/
228
229 /*
230  * interface initializes
231  */
232 err_t rpp_eth_lwip_init(struct netif *netif);
233
234 /*
235  * Initializes hw such as PHY, MDIO, EMAC, EMAC control module
236  *
237  * @return SUCCESS if initialization successful.\n
238  *         FAILURE if initialization not successful.
239  */
240 err_t rpp_eth_hw_init(struct hdkif *hdkif);
241
242 /*
243  * Initializes hw, after lwIP was initialized and
244  * OS was initialized in case OS is used.
245  */
246 err_t rpp_eth_hw_init_postInit(struct netif *netif);
247
248 /********************************************** utility functions **********************************************/
249
250 /*
251  * Function to set the MAC address to the interface
252  * @param   inst_num the instance number
253  *
254  * @note    mac_addr[0] is considered MSB
255  */
256 void hdkif_macaddrset(u32_t inst_num, u8_t *mac_addr)
257 {
258         struct hdkif *hdkif;
259         u32_t temp;
260
261         hdkif = &hdkif_data[inst_num];
262
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];
266         }
267 #ifdef DEBUG
268         uint8_t macStr[18];
269         rpp_eth_get_macAddrStr(inst_num, macStr);
270         rpp_debug_printf("Setting MAC... %s\r\n", macStr);
271 #endif
272 }
273
274 /**
275  * Function to setup the instance parameters inside the interface
276  * @param   hdkif
277  * @return  none.
278  */
279 static void hdkif_inst_config(struct hdkif *hdkif)
280 {
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;
291         }
292 }
293
294 /********************************************** initializing functions **********************************************/
295
296 int8_t rpp_eth_init()
297 {
298         uint8_t instNum;
299         int8_t retVal = SUCCESS;
300
301         if (initialized)
302                 return FAILURE;
303
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])) {
309 #ifdef DEBUG
310                         rpp_sci_printk("rpp_eth_hw_init: %d", retVal);
311 #endif
312                         retVal = FAILURE;
313                 }
314         }
315
316         /* when one of instances was not initialized correctly return FAILURE without setting initialized variable to TRUE */
317         if (retVal) return FAILURE;
318
319 #if NO_SYS
320
321 #else /* NO_SYS */
322
323 #endif /* NO_SYS */
324
325         initialized = TRUE;
326
327         return retVal;
328 }
329
330 int8_t rpp_eth_init_postInit(uint32_t instNum, uint8_t *macArray)
331 {
332         if (postInitialized)
333                 return FAILURE;
334         int8_t retVal = SUCCESS;
335         struct netif *netif = &hdkNetIF[instNum];
336         u8_t mac_addr[MAC_ADDR_LEN] = RPP_MAC_ADDR;
337
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;
343
344         if (macArray == NULL)
345                 macArray = mac_addr;  /* use default MAC */
346         hdkif_macaddrset(instNum, macArray);
347
348         struct hdkif *hdkif;
349 #if NO_SYS
350         lwip_init();
351 #else /* NO_SYS */
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 */
354 #endif /* NO_SYS */
355
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 */
361         ip_addr.addr = 0;
362         net_mask.addr = 0;
363         gw_addr.addr = 0;
364 #endif /* STATIC_IP_ADDRESS */
365
366         /* init and add new netif */
367         /* add new network interface to lwIP list of ifaces and initialize netif with specific function */
368 #if NO_SYS
369         if ( netif_add(netif, &ip_addr, &net_mask, &gw_addr, (void*)instNum, rpp_eth_lwip_init, ethernet_input) == NULL )
370 #else /* NO_SYS */
371         if ( netif_add(netif, &ip_addr, &net_mask, &gw_addr, (void*)instNum, rpp_eth_lwip_init, tcpip_input) == NULL )
372 #endif /* NO_SYS */
373
374                 return NETIF_ADD_ERR;
375
376         netif_set_default(netif);
377
378         hdkif = (struct hdkif*)netif->state;
379 #if !NO_SYS
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 ----- */
389 #endif /* !NO_SYS */
390
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
396                 netif_set_up(netif);
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");
400                         return DHCP_MEM_ERR;
401                 }
402                 rpp_debug_printf("binding DHCP\r");
403                 while ((netif->dhcp->state != DHCP_BOUND) && (dhcpBindWait--)) /*sys_check_timeouts()*/;
404                 if (!dhcpBindWait)
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 */
407                 autoip_start(netif);
408 #endif /* STATIC_IP_ADDRESS-LWIP_DHCP-LWIP_AUTOIP */
409 #ifdef DEBUG
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);
417 #endif
418         }
419         else
420         {
421                 rpp_debug_printf((const char*)"cable not connected\r\n");
422                 retVal = PHY_LINK_DOWN;
423         }
424
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);
429
430         /* enable MISC interrupt - link monitoring in EMAC controle module */
431         HWREG(hdkif->emac_ctrl_base + EMAC_CTRL_CnMISCEN(0)) |= EMAC_CTRL_MISC_LINKINT0ENB;
432
433 #endif /* !PHY_LINK_MONITOR_INT */
434            /* ----- end - lwIP stuff ----- */
435
436         postInitialized = TRUE;
437         return retVal;
438 }
439
440 err_t rpp_eth_lwip_init(struct netif *netif)
441 {
442 #if LWIP_NETIF_HOSTNAME
443         /* Initialize interface hostname */
444         netif->hostname = "rpp";
445 #endif /* LWIP_NETIF_HOSTNAME */
446
447         uint32_t instNum = (uint32_t)netif->state;
448         /*netif->num = instNum; - auto-initiated when netif_add is called */
449
450         /* netif->state contained instNum, we replace it with corresponding hdkif */
451         struct hdkif *hdkif = &hdkif_data[instNum];
452         netif->state = hdkif;
453
454         netif->name[0] = IFNAME0;
455         netif->name[1] = IFNAME1;
456
457 #if !NO_SYS
458         hdkif->waitTicksForPHYAneg = TICKS_PHY_AUTONEG;
459 #endif
460
461         /*
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.
465          */
466         NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, 10000000);
467
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
471          * is available...)
472          */
473         netif->output = etharp_output;
474         netif->linkoutput = rpp_eth_send;
475         return rpp_eth_hw_init_postInit(netif);
476 }
477
478 #define INIT_ONLY_AFTER_RESET 1
479 err_t rpp_eth_hw_init(struct hdkif *hdkif)
480 {
481         uint8_t index;
482         uint16_t regContent;
483         uint32_t physAlive;
484
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
488 #if NO_SYS
489         uint8_t index = 80; /* Initially used to hw reset of PHY connected to GIO pin. This means 1us - for 80MHz clock. */
490 #else /* NO_SYS */
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. */
492 #endif /* NO_SYS */
493         hal_gpio_pin_set_value(*hal_gpio_pin_get_dsc(PIN_NAME_ETHRST,-1),0);
494         while (index--) ;
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);
498
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);
503
504         /* enable used receive channel if necessary */
505
506
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, &regContent);
511
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;
519                                 break;
520                         }
521                         else
522                         {
523                                 MDIOPhyRegRead(hdkif->mdio_base, index, PHY_BMCR, &regContent); /* 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;
527                                         break;
528                                 }
529                         }
530                 }
531                 if (!physAlive) {
532                         rpp_debug_printf("no phy found, phys: %d\r\n", physAlive);
533                         return NO_PHY_ALIVE;
534                 }
535 #else
536                 rpp_debug_printf("default phy not alive\r\n");
537                 return DFLT_PHY_NOT_ALIVE;
538 #endif
539         }
540
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);
543
544         /* TODO: you can implement init of receive flow control somewhere here if desired - set RXBUFFERFLOWEN in MACCONTROL */
545
546
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);
551
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);
558
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);
562
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);
565
566         return SUCCESS;
567 }
568
569 err_t rpp_eth_hw_init_postInit(struct netif *netif)
570 {
571         volatile unsigned int autonegFinishWait = 0x3FFFFFFF; /* 0x3FFFFFFF is for 80MHz aproximately 13s */
572         uint16_t regContent;
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;
576         struct pbuf *p, *q;
577         struct rxch *rxch;
578         struct txch *txch;
579
580         struct hdkif *hdkif = (struct hdkif*)netif->state;
581
582         rxch = &(hdkif->rxch);
583         txch = &(hdkif->txch);
584
585         rpp_debug_printf("autoneg started - check on cable if it's connected!\r\n");
586
587
588         /*
589          * Initialize the Descriptor Memory For TX and RX
590          * Only Channel 0 is supported for both TX and RX
591          */
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;
595
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 */
598
599         curr_txbd = txch->free_head;
600
601         /* Initialize all the TX buffer Descriptors */
602         while (num_bd--) {
603                 curr_txbd->next = curr_txbd + 1;
604                 curr_txbd->flags_pktlen = 0;
605                 last_txbd = curr_txbd;
606                 curr_txbd = curr_txbd->next;
607         }
608         last_txbd->next = txch->free_head;
609
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;
617
618         /*
619         ** Allocate the pbufs for the maximum count permitted or till the
620         ** number of buffer desceriptors expire, which ever is earlier.
621         */
622         while (pbuf_cnt < MAX_RX_PBUF_ALLOC) {
623                 p = pbuf_alloc(PBUF_RAW, PBUF_LEN_MAX, PBUF_POOL);
624
625                 if (p != NULL) {
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;
633
634                                         /* Save the pbuf */
635                                         curr_rxbd->pbuf = q;
636                                         last_rxbd = curr_rxbd;
637                                         curr_rxbd = curr_rxbd->next;
638                                         num_bd--;
639                                 }
640
641                         /* free the allocated pbuf if no free descriptors are left */
642                         else {
643                                 pbuf_free(p);
644                                 break;
645                         }
646                 }
647                 else
648                         break;
649                 pbuf_cnt++;
650         }
651
652         if (!pbuf_cnt) rpp_debug_printf("no pbufs attached to rx buffer descriptors during init\n");
653
654         last_rxbd->next = NULL;
655         rxch->active_tail = last_rxbd;
656
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 */
661
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);
664
665         /* lwIP stuff */
666
667         /* set length of MAC address */
668         netif->hwaddr_len = MAC_ADDR_LEN;
669
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];
673         }
674
675         /* maximum transfer unit */
676         netif->mtu = MAX_TRANSFER_UNIT;
677
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;
681
682         /* lwIP stuff - end */
683
684         /* for flow control frames */
685         EMACMACSrcAddrSet(hdkif->emac_base, hdkif->mac_addr);
686
687         /*  Be sure to program all eight MAC address registers -
688          *  whether the receive channel is to be enabled or not.
689          */
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);
692
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 */
695 #if !NO_SYS
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 */
698 #else
699         while (hdkif->phy_autoneg_is_done(hdkif->mdio_base, hdkif->phy_addr) == FALSE && autonegFinishWait--) ;  /* wait till aneg done */
700 #endif
701
702         if (hdkif->phy_autoneg_is_done(hdkif->mdio_base, hdkif->phy_addr) != FALSE)
703                 rpp_debug_printf("aneg finished \r\n");
704         else
705                 rpp_debug_printf("aneg timeout \r\n");
706
707         /* provide informations retrieved from autoneg to EMAC module */
708         hdkif->phy_partnerability(hdkif->mdio_base, hdkif->phy_addr, &regContent);
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);
714         else {
715                 rpp_debug_printf("Unknown duplex mode\r\n");
716                 return UNKN_DUPLEX_MODE;
717         }
718 #endif /* !PHY_LINK_MONITOR_INT */
719
720         /* enable hostpend interrupts in emac module */
721         HWREG(hdkif->emac_base + EMAC_MACINTMASKSET) |= EMAC_MACINTMASKSET_HOSTMASK;
722
723         /* enable hostpend interrupts in emac control module */
724         HWREG(hdkif->emac_ctrl_base + EMAC_CTRL_CnMISCEN(0)) |= EMAC_CTRL_MISC_HOSTPENDENB;
725
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);
732
733         return SUCCESS;
734 }
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749 /********************************************** send and receive functions / ISRs **********************************************/
750
751 err_t rpp_eth_send(struct netif *netif, struct pbuf *p)
752 {
753         err_t retVal = SUCCESS;
754
755         SYS_ARCH_DECL_PROTECT(lev);
756
757         /**
758          * This entire function must run within a "critical section" to preserve
759          * the integrity of the transmit pbuf queue.
760          *
761          */
762         SYS_ARCH_PROTECT(lev);
763
764         /* protect from access receive acces from interrupt */
765 #if !SYS_LIGHTWEIGHT_PROT
766         uint32_t prevProt = (uint32_t)_get_CPSR() & 0x80;
767         _disable_IRQ();
768 #endif
769
770
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;
775         }
776
777         /* call the actual transmit function */
778         retVal = rpp_eth_send_raw(netif, p);
779
780         /* Return to prior interrupt state and return. */
781         SYS_ARCH_UNPROTECT(lev);
782
783 #if !SYS_LIGHTWEIGHT_PROT
784         if (!prevProt) _enable_IRQ();
785 #endif
786
787         return retVal;
788 }
789
790 /**
791  * send packet, blocks till it is sent
792  * every send uses bds on the beginning of CPPI RAM
793  */
794 err_t rpp_eth_send_raw(struct netif *netif, struct pbuf *p)
795 {
796         struct pbuf *q;
797         volatile struct emac_tx_bd *curr_bd, *bd_end;
798         struct hdkif *hdkif;
799
800         hdkif = (struct hdkif*)netif->state;
801         curr_bd = (struct emac_tx_bd*)hdkif->emac_ctrl_ram;
802
803         /* destroy all flags previously set and update the total packet length */
804         curr_bd->flags_pktlen = p->tot_len;
805
806         /* Indicate the start of the packet */
807         curr_bd->flags_pktlen |= (EMAC_DSC_FLAG_SOP | EMAC_DSC_FLAG_OWNER);
808
809         /* Copy pbuf information into TX buffer descriptors */
810         for (q = p; q != NULL; q = q->next) {
811
812                 /* Intialize the buffer pointer and length */
813                 curr_bd->bufptr = (uint8_t*)(q->payload);
814                 curr_bd->bufoff_len = (q->len) & 0xFFFF;
815                 bd_end = curr_bd;
816                 curr_bd->pbuf = p;
817                 curr_bd = curr_bd->next;
818                 curr_bd->flags_pktlen = 0x0; /* destroy all previously set flags */
819         }
820
821         /* Indicate the end of the packet */
822         bd_end->next = NULL;
823         bd_end->flags_pktlen |= EMAC_DSC_FLAG_EOP;
824
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);
830
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("!");
835
836         EMACTxCPWrite(hdkif->emac_base, CHANNEL, (uint32_t)bd_end);
837
838         EMACCoreIntAck(hdkif->emac_base, EMAC_INT_CORE0_TX);
839
840         /* restore bds chain */
841         bd_end->next = curr_bd;
842
843         LINK_STATS_INC(link.xmit);
844         return SUCCESS;
845 }
846
847 void rpp_eth_recv_raw(void *arg)
848 {
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;
852         uint16_t tot_len;
853         struct netif *netif = (struct netif*)arg;
854         struct hdkif *hdkif = (struct hdkif*)netif->state;
855         struct rxch *rxch;
856
857         rxch = &(hdkif->rxch);
858
859
860 #if !NO_SYS && !ONE_DRIVER_TASK
861         SYS_ARCH_DECL_PROTECT(lev);
862         for (;; ) {
863                 vim_mask_set(RXinterruptVectorNumber);
864                 sys_arch_sem_wait(&(hdkif->goRX), 0);
865                 SYS_ARCH_PROTECT(lev);
866 #endif
867
868
869         /* Get the bd which contains the earliest filled data */
870         curr_bd = rxch->active_head;
871         last_bd = rxch->active_tail;
872
873         if (curr_bd->flags_pktlen & EMAC_DSC_FLAG_SOP != EMAC_DSC_FLAG_SOP) rpp_debug_printf("ERR: Active head is not SOP!\n");
874
875         /**
876          * Process the descriptors as long as data is available
877          * when the DMA is receiving data, SOP flag will be set
878          */
879         while (curr_bd->flags_pktlen & EMAC_DSC_FLAG_SOP) {
880                 ex_len = 0;
881                 len_to_alloc = 0;
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;
887
888                         /* Get the total length of the packet. curr_bd points to the start
889                          * of the packet.
890                          */
891                         tot_len = (curr_bd->flags_pktlen) & 0xFFFF;
892
893                         /* Get the start of the pbuf queue */
894                         q = curr_bd->pbuf;
895
896                         do {
897                                 /* Get the pbuf pointer which is associated with the current bd */
898                                 pbuf = curr_bd->pbuf;
899
900                                 /* If the earlier pbuf ended, update the chain */
901                                 if (pbuf->next == NULL)
902                                         pbuf->next = (struct pbuf*)(curr_bd->next)->pbuf;
903
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;
909                                 ex_len += pbuf->len;
910                                 curr_bd = curr_bd->next;
911 #ifdef DEBUG
912                                 if (curr_bd == NULL) rpp_debug_printf("rx curr_bd set to zero!\n");
913 #endif
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);
916
917                         /**
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'.
921                          */
922                         pbuf->next = NULL;
923
924                         /* Adjust the link statistics */
925                         LINK_STATS_INC(link.recv);
926
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);
932                         }
933
934                         /* Acknowledge that this packet is processed */
935                         EMACRxCPWrite(hdkif->emac_base, CHANNEL, (unsigned int)processed_bd);
936
937                         if (curr_bd != NULL)
938                                 rxch->active_head = curr_bd;
939                         else
940                                 rxch->active_head = processed_bd + 1;     //todo:reconsider
941
942                         /**
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.
947                          */
948                         /**
949                          * now len_to_alloc will contain the length of the pbuf which was freed
950                          * from the upper layer
951                          */
952                         rxch->freed_pbuf_len += len_to_alloc;
953 #if !NO_SYS
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 */
958                         do {
959 #endif
960                         new_pbuf = pbuf_alloc(PBUF_RAW, (rxch->freed_pbuf_len), PBUF_POOL);
961 #if !NO_SYS
962                         if (new_pbuf != NULL)
963                                 break;
964                         else
965                                 xSemaphoreTake(pbufFreed, 0);
966                         xSemaphoreTake(pbufFreed, portMAX_DELAY);
967                 }
968                 while (1) ;
969 #endif
970
971                         /* Write the descriptors with the pbuf info till either of them expires */
972                         if (new_pbuf != NULL) {
973                                 curr_bd = rxch->free_head;
974
975                                 for (q = new_pbuf; (q != NULL) && (curr_bd != rxch->active_head); q = q->next) {
976                                         curr_bd->bufptr = (uint8_t*)(q->payload);
977
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;
981
982                                         rxch->freed_pbuf_len -= q->len;
983
984                                         /* Save the pbuf */
985                                         curr_bd->pbuf = q;
986                                         last_bd = curr_bd;
987                                         curr_bd = curr_bd->next;
988                                 }
989
990                                 /**
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
994                                  */
995                                 if (q != NULL)
996                                         pbuf_free((struct pbuf*)q);
997
998                                 curr_tail = rxch->active_tail;
999                                 last_bd->next = NULL;
1000
1001                                 curr_tail->next = rxch->free_head;
1002
1003                                 /**
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.
1007                                  */
1008                                 if (curr_tail->flags_pktlen & EMAC_DSC_FLAG_EOQ)
1009                                         EMACRxHdrDescPtrWrite(hdkif->emac_base, (u32_t)(rxch->free_head), CHANNEL);
1010
1011                                 rxch->free_head  = curr_bd;
1012                                 rxch->active_tail = last_bd;
1013                         }
1014                 }
1015                 curr_bd = rxch->active_head;
1016         }
1017         EMACCoreIntAck(hdkif->emac_base, EMAC_INT_CORE0_RX);
1018
1019 #if !NO_SYS && !ONE_DRIVER_TASK
1020         SYS_ARCH_UNPROTECT(lev);
1021 }
1022 #endif
1023 }
1024
1025 void RxIntHandler(u32_t instNum)
1026 {
1027 #if !NO_SYS
1028         vim_mask_clr(RXinterruptVectorNumber);
1029         /*
1030            static portBASE_TYPE xHigherPriorityTaskWoken;
1031            xHigherPriorityTaskWoken = pdFALSE;
1032          */
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
1035         /*
1036            if( xHigherPriorityTaskWoken == pdTRUE )
1037            {
1038          */
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. */
1048         /*
1049            portSWITCH_CONTEXT();
1050            }
1051          */
1052 #else
1053         rpp_eth_recv_raw((void*)&hdkNetIF[instNum]);
1054 #endif
1055 }
1056
1057 void TxIntHandler(u32_t instNum)
1058 {
1059         //struct hdkif *hdkif = &hdkif_data[instNum];
1060 #if !NO_SYS
1061         vim_mask_clr(TXinterruptVectorNumber); /* see sys_startup.c */
1062         xSemaphoreGiveFromISR(hdkif_data[instNum].goTX, NULL);
1063 #else
1064         //sendDone = TRUE;
1065         //rpp_eth_send_bd_handler((void *) &hdkif_data[instNum]);
1066 #endif
1067 }
1068
1069 /**
1070  * TX err codes:
1071  *
1072  * 0 No error
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)
1079  *
1080  *
1081  * RX err codes:
1082  *
1083  * 0 No error
1084  * 1h Reserved
1085  * 2h Ownership bit not set in SOP buffer
1086  * 3h Reserved
1087  * 4h Zero buffer pointer
1088  */
1089 boolean_t HostPendErrHandler(void)
1090 {
1091         uint8_t index = MAX_EMAC_INSTANCE, errFound = FALSE;
1092         uint32_t reg;
1093         struct hdkif *hdkif;
1094
1095         while (index) {
1096                 hdkif = &hdkif_data[--index];
1097                 if (EMACIntVectorGet(hdkif->emac_base) & EMAC_MACINVECTOR_HOSTPEND) errFound = TRUE;
1098         }
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 */
1106 }
1107
1108 #if PHY_LINK_MONITOR_INT
1109 boolean_t LinkIntHandler(void)
1110 {
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;
1116
1117         /* check each instance, whether this interrupt was meant for this function, if not return FALSE so other function may be tried */
1118         while (index) {
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;
1121         }
1122         if (!phyFound) return FALSE;
1123         struct netif *netif = &hdkNetIF[hdkif->inst_num];
1124
1125         /* we handles here connection of cable after startup, not changes of linkstatus */
1126
1127         /* wait for autonegotiation to be done */
1128 #if ONCE_LINK_SETUP
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 */
1133
1134         /* provide informations retrieved from autoneg to EMAC module */
1135         hdkif->phy_partnerability(hdkif->mdio_base, hdkif->phy_addr, &regContent);
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);
1141         else {
1142                 /* acknowledge MDIO module */
1143                 HWREG(hdkif->mdio_base + MDIO_LINKINTRAW) = MDIO_LINKINTMASKED_USERPHY0;
1144                 HWREG(hdkif->mdio_base + MDIO_LINKINTMASKED) = MDIO_LINKINTMASKED_USERPHY0;
1145
1146                 /* acknowledge EMAC control module by writing appropriate key to MACEOIVECTOR */
1147                 EMACCoreIntAck(hdkif->emac_base, EMAC_INT_CORE0_MISC);
1148                 return FALSE;
1149         }
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;
1157
1158 #if ONCE_LINK_SETUP
1159                 while (netif->dhcp->state != DHCP_BOUND) ;
1160 #else
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;
1166
1167                         /* acknowledge EMAC control module by writing appropriate key to MACEOIVECTOR */
1168                         EMACCoreIntAck(hdkif->emac_base, EMAC_INT_CORE0_MISC);
1169                         return FALSE;
1170                 }
1171 #endif
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 */
1175 #if ONCE_LINK_SETUP
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 */
1179         }
1180         else
1181         {
1182 #if 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;
1186
1187                 /* acknowledge EMAC control module by writing appropriate key to MACEOIVECTOR */
1188                 EMACCoreIntAck(hdkif->emac_base, EMAC_INT_CORE0_MISC);
1189                 return FALSE;
1190 #else
1191 #if STATIC_IP_ADDRESS
1192                 netif_set_down(netif);
1193 #elif LWIP_DHCP /* STATIC_IP_ADDRESS-LWIP_DHCP */
1194                 dhcp_stop(netif);
1195 #endif /* STATIC_IP_ADDRESS-LWIP_DHCP-LWIP_AUTOIP */
1196 #endif
1197         }
1198
1199         /* acknowledge MDIO module */
1200         HWREG(hdkif->mdio_base + MDIO_LINKINTRAW) = MDIO_LINKINTMASKED_USERPHY0;
1201         HWREG(hdkif->mdio_base + MDIO_LINKINTMASKED) = MDIO_LINKINTMASKED_USERPHY0;
1202
1203         /* acknowledge EMAC control module by writing appropriate key to MACEOIVECTOR */
1204         EMACCoreIntAck(hdkif->emac_base, EMAC_INT_CORE0_MISC);
1205
1206         return TRUE;
1207 }
1208 #endif /* PHY_LINK_MONITOR_INT */
1209 #endif /* FREERTOS_POSIX */